This is the mail archive of the 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]

Section sizing + orphan placement bugs

The patch at the end of this message is fairly obvious, but the testcase
deserves some explanation.  It shows at least one other serious bug that
this patch does not fix.

Here's a testcase that works on x86_64.  Should work just about anywhere
with a standard page size of 4K.  Assemble and then link with -shared.

	.section, "a", %note
	.space 16

	.section .data, "aw"
	.space 3800

	.section .rodata, "a"
	.space 4

./x86/ld/ld-new: section [00000000001011a0 -> 00000000001011af] overlaps section .data [00000000001010c8 -> 0000000000101f9f]
./x86/ld/ld-new: note: section lma 0x1011a0 overlaps previous sections

The -shared option is necessary to trigger the bug because it will cause
there to be no .interp section in the output.  We try to place notes with
.interp first.  Without that they get stuck into the orphan list for either
the next best flags match (usually .rodata), or *ABS*.

The .rodata section is necessary to trigger the bug because otherwise there
will be no output section for .rodata, so lang_output_section_find_by_flags
will place the orphaned section there.  If there is one, we'll see
that it has SHT_PROGBITS instead of SHT_NOTE, and refuse to use .rodata.  We
fall back to *ABS*, which places them at the front of the file.

I suspect we should try to place them with something else for shared
libraries; .rodata isn't a great choice.  But *ABS* works out OK most of the
time (if there aren't too many orphans, the note will end up in the first
page with the phdrs, anyway).

The .data section is necessary to trigger the bug because it causes the
DATA_SECTION_ALIGN mechanism to size sections a second time.  -z relro would
probably have a similar effect.

Now we've placed this output section at the very front of the list of
linker statements.  It ends up before the assignment to
. = . + SIZEOF_HEADERS, which is the other serious bug I mentioned up top.
We need to place orphans after an initial assignment to dot; otherwise, the
program headers will end up outside of the load segment!

Anyway, as a consequence of not having yet assigned to dot, the second call
to one_lang_size_sections_pass gets a stale value of os->region->current,
and places the section in an arbitrary location; then it resets dot
downwards and places everything else, and we end up overlapping .data.
The unreduced testcase somehow put it in the middle of .hash.

I think the attached fix is right for that part of the bug but I'm open to
suggestions on how to handle SIZEOF_HEADERS.

Daniel Jacobowitz
CodeSourcery, LLC

2005-11-23  Daniel Jacobowitz  <>

	* ldlang.c (lang_size_sections): Call lang_reset_memory_regions
	before redoing one_lang_size_sections_pass.

Index: ldlang.c
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.208
diff -u -p -r1.208 ldlang.c
--- ldlang.c	18 Nov 2005 04:12:27 -0000	1.208
+++ ldlang.c	23 Nov 2005 15:38:03 -0000
@@ -4499,6 +4499,7 @@ lang_size_sections (bfd_boolean *relax, 
 	  expld.dataseg.base -= maxpage;
 	  relro_end -= maxpage;
+      lang_reset_memory_regions ();
       one_lang_size_sections_pass (relax, check_regions);
       if (expld.dataseg.relro_end > relro_end)
@@ -4522,6 +4523,7 @@ lang_size_sections (bfd_boolean *relax, 
 		  < old_min_base)
 		expld.dataseg.base += expld.dataseg.pagesize;
 	      expld.dataseg.base -= (1 << max_alignment_power);
+	      lang_reset_memory_regions ();
 	      one_lang_size_sections_pass (relax, check_regions);
@@ -4542,6 +4544,7 @@ lang_size_sections (bfd_boolean *relax, 
 	  && first + last <= expld.dataseg.pagesize)
 	  expld.dataseg.phase = exp_dataseg_adjust;
+	  lang_reset_memory_regions ();
 	  one_lang_size_sections_pass (relax, check_regions);

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