Linker scripts and Section Reordering.

Sriraman Tallam tmsriram@google.com
Wed Jan 9 22:46:00 GMT 2013


On Wed, Jan 9, 2013 at 7:46 AM, Ian Lance Taylor <iant@google.com> wrote:
> On Tue, Jan 8, 2013 at 2:59 PM, Sriraman Tallam <tmsriram@google.com> wrote:
>>
>>   Using linker scripts along with section reordering, either through
>> --section-ordering-file or the plugin, can cause bugs during segment
>> address computation.
>>
>>   Linker scripts fire first, in file layout.cc,  function
>> "relaxation_loop_body" calls function
>> "set_section_addresses_from_script" and computes an output section
>> address for ".text". This can also sort text input sections if
>> specified via the linker script.
>>
>>    Section ordering sorting comes later and is called in a chain of
>> events starting from function "set_segment_offsets" which is called
>> again from function "relaxation_loop_body" in layout.cc. With section
>> ordering sorting, the output_section size can change, considering
>> alignment. If the resulting size happens to be smaller than what was
>> computed earlier, we get an error  of the form "address of section
>> <section-name> moves backward from XXX to YYY". This error will
>> correspond to the section that follows ".text" in the linker script as
>> its start address begins  where ".text" ends. This error code is
>> located in file output.cc in function "set_section_list_addresses".
>>
>>    The other problem is that of handling section sorting when it is
>> specified via linker scripts and section reordering. We encountered
>> this problem with the kernel where we cannot do without linker
>> scripts. We found that plugin based section reordering in the kernel
>> improves the performance of some applications but we also wanted the
>> ordering to be compatible with the linker script used.
>>
>>    To solve these problems, I propose the following simple patch. This
>> patch will invoke section sorting earlier, before the linker script
>> can compute the address of the output section. Then, the linker script
>> can re-sort the sections and the new computed address will be correct
>> as the order of sections will not change.
>>
>>   With the patch, the resulting order of input sections is definitely
>> agreeable with the linker script specification. All other input
>> sections which the linker script did not care about will be agreeable
>> with the section ordering spec. If we make the linker script sorting
>> glob generic, like specify just ".text.*"  within the sections clause,
>> then we can get the sorting from section ordering alone.
>>
>>
>> Patch attached.
>>
>>         * output.h (sort_attached_input_sections): Change to be public.
>>         * script-sections.cc (set_section_addresses): Call
>> sort_attached_input_sections
>>         before linker script assigns section addresses.
>
>>    // Sort the attached input sections.
>> -  void
>> -  sort_attached_input_sections();
>> +  // void
>> +  // sort_attached_input_sections();
>
> Remove this, don't just comment it out.

Sorry, this was just oversight.

>
>> +      if (os != NULL
>> +       && os->input_section_order_specified())
>> +     os->sort_attached_input_sections();
>
> It seems to me that this should be in
> Output_section_definition::set_section_addresses.  You may need it in
> Orphan_output_section::set_section_addresses but probably not.

I moved this to Output_section_definition::set_section_addresses. I
dont think this is necessary in
Orphan_output_section::set_section_addresses for the following reason.
Orphan_output_sections are for those not seen in the linker script.
Such an output section is created for every input section that is not
caught in the linker script. Such input sections are not grouped by
prefix as the output_section_name method in script-sections.cc is used
to group them. So, these input sections cannot be handled by section
ordering.

>
> Your patch implies that the ordering in the linker script overrides
> --section-ordering-file or a plugin.  This should be documented in a
> comment at least.

Done now.

I also updated the section_ordering_file testcase to use a simple linker script.
Thanks,

Sri

>
> Ian
-------------- next part --------------
	* output.h (sort_attached_input_sections): Change to be public.
	* script-sections.cc
	(Output_section_definition::set_section_addresses): Sort
	attached input sections according to section order before linker
	script assigns section addresses.

Index: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.144
diff -u -u -p -r1.144 output.h
--- output.h	12 Dec 2012 03:41:40 -0000	1.144
+++ output.h	9 Jan 2013 22:37:08 -0000
@@ -3300,6 +3300,10 @@ class Output_section : public Output_dat
     this->dynsym_index_ = index;
   }
 
+  // Sort the attached input sections.
+  void
+  sort_attached_input_sections();
+
   // Return whether the input sections sections attachd to this output
   // section may require sorting.  This is used to handle constructor
   // priorities compatibly with GNU ld.
@@ -4253,10 +4257,6 @@ class Output_section : public Output_dat
   add_output_merge_section(Output_section_data* posd, bool is_string,
 			   uint64_t entsize);
 
-  // Sort the attached input sections.
-  void
-  sort_attached_input_sections();
-
   // Find the merge section into which an input section with index SHNDX in
   // OBJECT has been added.  Return NULL if none found.
   Output_section_data*
Index: script-sections.cc
===================================================================
RCS file: /cvs/src/src/gold/script-sections.cc,v
retrieving revision 1.56
diff -u -u -p -r1.56 script-sections.cc
--- script-sections.cc	14 Aug 2012 08:31:56 -0000	1.56
+++ script-sections.cc	9 Jan 2013 22:37:09 -0000
@@ -2294,6 +2294,15 @@ Output_section_definition::set_section_a
   uint64_t old_dot_value = *dot_value;
   uint64_t old_load_address = *load_address;
 
+  // If input section sorting is requested via --section-ordering-file or
+  // linker plugins, then do it here.  This is important because we want 
+  // any sorting specified in the linker scripts, which will be done after
+  // this, to take precedence.  The final order of input sections is then 
+  // guaranteed to be according to the linker script specification.
+  if (this->output_section_ != NULL
+      && this->output_section_->input_section_order_specified())
+    this->output_section_->sort_attached_input_sections();
+
   // Decide the start address for the section.  The algorithm is:
   // 1) If an address has been specified in a linker script, use that.
   // 2) Otherwise if a memory region has been specified for the section,
Index: testsuite/Makefile.am
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.am,v
retrieving revision 1.203
diff -u -u -p -r1.203 Makefile.am
--- testsuite/Makefile.am	4 Jan 2013 23:50:27 -0000	1.203
+++ testsuite/Makefile.am	9 Jan 2013 22:37:09 -0000
@@ -251,8 +251,10 @@ final_layout.o: final_layout.cc
 	$(CXXCOMPILE) -O0 -c -ffunction-sections  -fdata-sections -g -o $@ $<
 final_layout_sequence.txt:
 	(echo "*_Z3barv*" && echo ".text._Z3bazv" && echo "*_Z3foov*" && echo "*global_varb*" && echo "*global_vara*" && echo "*global_varc*") > final_layout_sequence.txt
-final_layout: final_layout.o final_layout_sequence.txt gcctestdir/ld
-	$(CXXLINK) -Bgcctestdir/ -Wl,--section-ordering-file,final_layout_sequence.txt final_layout.o
+final_layout_script.lds:
+	(echo ""SECTIONS { .text : { *(.text*) } .bss : { *(.bss*) } }") > final_layout_script.lds
+final_layout: final_layout.o final_layout_sequence.txt final_layout_script.lds gcctestdir/ld
+	$(CXXLINK) -Bgcctestdir/ -Wl,--section-ordering-file,final_layout_sequence.txt -Wl,-T,final_layout_script.lds final_layout.o
 final_layout.stdout: final_layout
 	$(TEST_NM) -n --synthetic final_layout > final_layout.stdout
 
Index: testsuite/Makefile.in
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.in,v
retrieving revision 1.214
diff -u -u -p -r1.214 Makefile.in
--- testsuite/Makefile.in	4 Jan 2013 23:50:27 -0000	1.214
+++ testsuite/Makefile.in	9 Jan 2013 22:37:09 -0000
@@ -125,6 +125,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__E
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	icf_safe_test icf_safe_so_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	final_layout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	final_layout_sequence.txt \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	final_layout_script.lds \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	text_section_grouping \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	icf_virtual_function_folding_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	icf_preemptible_functions_test \
@@ -4355,8 +4356,10 @@ uninstall-am:
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	$(CXXCOMPILE) -O0 -c -ffunction-sections  -fdata-sections -g -o $@ $<
 @GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout_sequence.txt:
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	(echo "*_Z3barv*" && echo ".text._Z3bazv" && echo "*_Z3foov*" && echo "*global_varb*" && echo "*global_vara*" && echo "*global_varc*") > final_layout_sequence.txt
-@GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout: final_layout.o final_layout_sequence.txt gcctestdir/ld
-@GCC_TRUE@@NATIVE_LINKER_TRUE@	$(CXXLINK) -Bgcctestdir/ -Wl,--section-ordering-file,final_layout_sequence.txt final_layout.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout_script.lds:
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	(echo "SECTIONS { .text : { *(.text*) } .bss : { *(.bss*) } }") > final_layout_script.lds
+@GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout: final_layout.o final_layout_sequence.txt final_layout_script.lds gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	$(CXXLINK) -Bgcctestdir/ -Wl,--section-ordering-file,final_layout_sequence.txt -Wl,-T,final_layout_script.lds final_layout.o
 @GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout.stdout: final_layout
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	$(TEST_NM) -n --synthetic final_layout > final_layout.stdout
 @GCC_TRUE@@NATIVE_LINKER_TRUE@text_section_grouping.o: text_section_grouping.cc


More information about the Binutils mailing list