This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] adjust placement of sections into segments in cornercases


Looking further at what ld does when building Linux I discovered more
anomalies (all sections in the below descriptions are considered to be
page size aligned and a multiple of a page size large):

1) A non-writable section following a writable one would result in the
non-writable section to be merged into the writable segment, thus
losing
the write protection. The inverse case was dealt with properly.

2) A zero-sized bss section following a writable section and preceding
a non-writable one would result in the latter again losing its write
protection.

3) A zero-sized bss section between two writable sections would result
in a needlessly splitting the sections into two segments.

The patch attempts to address all these. Built and tested on
i686-pc-linux-gnu.

Jan

bfd/
2004-08-27 Jan Beulich <jbeulich@novell.com>

	* elf.c (map_sections_to_segments): Symmetrically handle
segment
	splits between non-writable and writable sections when a
writable
	section preceeds a non-writable one. Consider
loadable/non-loadable
	state of section only when it has non-zero size.
	(elf_sort_sections): Consider loadable state only after
comparing
	sizes (after comparing addresses there can, in a set of
sections
	with identical addresses, only be one with non-zero size, which
	should be ordered last here; among the zero-sized sections,
those
	that are loadable should preceed all non-loadable ones).

ld/testsuite/
2004-08-27 Jan Beulich <jbeulich@novell.com>

	* ld-elf/seg.*: New.

---
/home/jbeulich/src/binutils/mainline/2004-08-27.13.46/bfd/elf.c	2004-08-19
11:03:15.000000000 +0200
+++ 2004-08-27.13.46-elf-segments/bfd/elf.c	2004-08-27
14:01:06.010545560 +0200
@@ -3347,6 +3347,7 @@ map_sections_to_segments (bfd *abfd)
   asection **hdrpp;
   bfd_boolean phdr_in_segment = TRUE;
   bfd_boolean writable;
+  int loadable; /* 0: indifferent, < 0: no, > 0: yes */
   int tls_count = 0;
   asection *first_tls = NULL;
   asection *dynsec, *eh_frame_hdr;
@@ -3425,6 +3426,7 @@ map_sections_to_segments (bfd *abfd)
   phdr_index = 0;
   maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
   writable = FALSE;
+  loadable = 0;
   dynsec = bfd_get_section_by_name (abfd, ".dynamic");
   if (dynsec != NULL
       && (dynsec->flags & SEC_LOAD) == 0)
@@ -3477,11 +3479,12 @@ map_sections_to_segments (bfd *abfd)
              skip a page in the segment, then we need a new segment. 
*/
 	  new_segment = TRUE;
 	}
-      else if ((last_hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0
-	       && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0)
+      else if (loadable < 0
+	       && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0
+	       && hdr->size != 0)
 	{
-	  /* We don't want to put a loadable section after a
-             nonloadable section in the same segment.
+	  /* We don't want to put a non-empty loadable section after
+             a nonloadable section in the same segment.
              Consider .tbss sections as loadable for this purpose. 
*/
 	  new_segment = TRUE;
 	}
@@ -3492,8 +3495,7 @@ map_sections_to_segments (bfd *abfd)
              file, then there is no other reason for a new segment. 
*/
 	  new_segment = FALSE;
 	}
-      else if (! writable
-	       && (hdr->flags & SEC_READONLY) == 0
+      else if (! writable == ! (hdr->flags & SEC_READONLY)
 	       && (((last_hdr->lma + last_size - 1)
 		    & ~(maxpagesize - 1))
 		   != (hdr->lma & ~(maxpagesize - 1))))
@@ -3517,6 +3519,13 @@ map_sections_to_segments (bfd *abfd)
 	{
 	  if ((hdr->flags & SEC_READONLY) == 0)
 	    writable = TRUE;
+	  if (hdr->size != 0)
+	    {
+	      if ((hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0)
+		loadable = 1;
+	      else
+		loadable = -1;
+	    }
 	  last_hdr = hdr;
 	  /* .tbss sections effectively have zero size.  */
 	  if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) !=
SEC_THREAD_LOCAL)
@@ -3540,6 +3549,12 @@ map_sections_to_segments (bfd *abfd)
 	writable = TRUE;
       else
 	writable = FALSE;
+      if (hdr->size == 0)
+	loadable = 0;
+      else if ((hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0)
+	loadable = 1;
+      else
+	loadable = -1;
 
       last_hdr = hdr;
       /* .tbss sections effectively have zero size.  */
@@ -3719,27 +3734,6 @@ elf_sort_sections (const void *arg1, con
   else if (sec1->vma > sec2->vma)
     return 1;
 
-  /* Put !SEC_LOAD sections after SEC_LOAD ones.  */
-
-#define TOEND(x) (((x)->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0)
-
-  if (TOEND (sec1))
-    {
-      if (TOEND (sec2))
-	{
-	  /* If the indicies are the same, do not return 0
-	     here, but continue to try the next comparison.  */
-	  if (sec1->target_index - sec2->target_index != 0)
-	    return sec1->target_index - sec2->target_index;
-	}
-      else
-	return 1;
-    }
-  else if (TOEND (sec2))
-    return -1;
-
-#undef TOEND
-
   /* Sort by size, to put zero sized sections
      before others at the same address.  */
 
@@ -3751,6 +3745,15 @@ elf_sort_sections (const void *arg1, con
   if (size1 > size2)
     return 1;
 
+  /* Put !SEC_LOAD sections after SEC_LOAD ones.  */
+
+#define TOEND(x) (((x)->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0)
+
+  if (TOEND (sec1) != TOEND (sec2))
+    return TOEND (sec1) - TOEND (sec2);
+
+#undef TOEND
+
   return sec1->target_index - sec2->target_index;
 }
 
---
/home/jbeulich/src/binutils/mainline/2004-08-27.13.46/ld/testsuite/ld-elf/seg.d	1970-01-01
01:00:00.000000000 +0100
+++
2004-08-27.13.46-elf-segments/ld/testsuite/ld-elf/seg.d	2004-08-27
13:42:42.000000000 +0200
@@ -0,0 +1,18 @@
+#source: seg.s
+#ld: -T seg.ld
+#objdump: -p
+
+.*:.*elf.*
+
+.*:
+[ 	]*LOAD[ 	].*
+[ 	]*filesz (0x0*1000+) memsz \1 flags r-x
+[ 	]*LOAD[ 	].*
+[ 	]*filesz (0x0*3000+) memsz \1 flags rw-
+[ 	]*LOAD[ 	].*
+[ 	]*filesz (0x0*1000+) memsz \1 flags r-x
+[ 	]*LOAD[ 	].*
+[ 	]*filesz (0x0*1000+) memsz \1 flags rw-
+[ 	]*LOAD[ 	].*
+[ 	]*filesz (0x0*1000+) memsz \1 flags r-x
+#pass
---
/home/jbeulich/src/binutils/mainline/2004-08-27.13.46/ld/testsuite/ld-elf/seg.ld	1970-01-01
01:00:00.000000000 +0100
+++
2004-08-27.13.46-elf-segments/ld/testsuite/ld-elf/seg.ld	2004-08-27
13:22:05.000000000 +0200
@@ -0,0 +1,13 @@
+SECTIONS {
+	. = 0xABC00000;
+	.text : { *(.text) }
+	.rodata : { *(.rodata) }
+	.data : { *(.data) }
+	.bss : { *(.bss) }
+	.write1 : { *(.write1) }
+	.write2 : { *(.write2) }
+	.exec1 : { *(.exec1) }
+	.write3 : { *(.write3) }
+	.bss3 : { *(.bss3) }
+	.exec2 : { *(.exec2) }
+}
---
/home/jbeulich/src/binutils/mainline/2004-08-27.13.46/ld/testsuite/ld-elf/seg.s	1970-01-01
01:00:00.000000000 +0100
+++
2004-08-27.13.46-elf-segments/ld/testsuite/ld-elf/seg.s	2004-08-27
13:40:38.000000000 +0200
@@ -0,0 +1,54 @@
+.equ	PAGESIZE, 0x10000
+
+.global	_start
+
+.text
+_start:
+.byte	0xCC
+
+.section	.rodata, "a", @progbits
+.align	4
+code:
+.rept	PAGESIZE - 4
+ .byte	0xCC
+.endr
+
+.data
+data:
+.rept	PAGESIZE
+ .byte	0xDD
+.endr
+
+.section	.write1, "aw", @progbits
+write1:
+.rept	PAGESIZE
+ .byte	0x11
+.endr
+
+.section	.write2, "aw", @progbits
+write2:
+.rept	PAGESIZE
+ .byte	0x22
+.endr
+
+.section	.exec1, "ax", @progbits
+exec1:
+.rept	PAGESIZE
+ .byte	0xE1
+.endr
+
+.section	.write3, "aw", @progbits
+.align	4
+write3:
+.rept	PAGESIZE
+ .byte	0x33
+.endr
+
+.section	.bss3, "aw", @nobits
+bss3:
+
+.section	.exec2, "ax", @progbits
+exec2:
+.rept	PAGESIZE
+ .byte	0xE2
+.endr

Attachment: binutils-mainline-elf-segments.patch
Description: Binary data


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]