This is the mail archive of the binutils@sourceware.org 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]

gold patch committed: Put .interp first


I got a report that on FreeBSD the .interp section must be in the
first page of the executable.  That is a good idea anyhow, since it
tends to reduce the reading required by the kernel.  This patch moves
.interp first, followed by allocated non-writable note sections,
followed by other sections used by the dynamic linker.  This is what
the GNU linker does.

While implementing this, I discovered that if the first sections in
the text segment are dynamic relocation sections, that objcopy and
strip fail.  The problem is in copy_elf_program_header: it ignores the
relocation sections when setting first_section, and thus gets the
wrong value for the program header size, and then later fails when it
finds that it can't put the relocation sections at the offset they
need.  I didn't debug it further than that, since this is kind of an
unusual case.

This patch looks large but is almost entirely the mechanical addition
of new parameters.

Committed to mainline and 2.20 branch.

Ian


2009-11-04  Ian Lance Taylor  <iant@google.com>

	* layout.cc (Layout::get_output_section): Add is_interp and
	is_dynamic_linker_section parameters.  Change all callers.
	(Layout::choose_output_section): Likewise.
	(Layout::make_output_section): Likewise.
	(Layout::add_output_section_data): Add is_dynamic_linker_section
	parameter.  Change all callers.
	* layout.h (class Layout): Update declarations.
	* output.h (class Output_section): Add is_interp, set_is_interp,
	is_dynamic_linker_section, set_is_dynamic_linker_section methods.
	Add is_interp_, is_dynamic_linker_section_ fields.  Change
	generate_code_fills_at_write_ to a bitfield.
	* output.cc (Output_section::Output_sections): Initialize new
	fields.
	(Output_segment::add_output_section): Add do_sort parameter.
	Change all callers.


Index: arm.cc
===================================================================
RCS file: /cvs/src/src/gold/arm.cc,v
retrieving revision 1.27
diff -p -u -r1.27 arm.cc
--- arm.cc	3 Nov 2009 21:18:13 -0000	1.27
+++ arm.cc	4 Nov 2009 15:51:58 -0000
@@ -2166,7 +2166,7 @@ Target_arm<big_endian>::got_section(Symb
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 					   (elfcpp::SHF_ALLOC
 					    | elfcpp::SHF_WRITE),
-					   this->got_);
+					   this->got_, false);
       os->set_is_relro();
 
       // The old GNU linker creates a .got.plt section.  We just
@@ -2177,7 +2177,7 @@ Target_arm<big_endian>::got_section(Symb
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 					   (elfcpp::SHF_ALLOC
 					    | elfcpp::SHF_WRITE),
-					   this->got_plt_);
+					   this->got_plt_, false);
       os->set_is_relro();
 
       // The first three entries are reserved.
@@ -2205,7 +2205,7 @@ Target_arm<big_endian>::rel_dyn_section(
       gold_assert(layout != NULL);
       this->rel_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
-				      elfcpp::SHF_ALLOC, this->rel_dyn_);
+				      elfcpp::SHF_ALLOC, this->rel_dyn_, true);
     }
   return this->rel_dyn_;
 }
@@ -3588,7 +3588,7 @@ Output_data_plt_arm<big_endian>::Output_
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
-				  elfcpp::SHF_ALLOC, this->rel_);
+				  elfcpp::SHF_ALLOC, this->rel_, true);
 }
 
 template<bool big_endian>
@@ -3750,7 +3750,7 @@ Target_arm<big_endian>::make_plt_entry(S
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_EXECINSTR),
-				      this->plt_);
+				      this->plt_, false);
     }
   this->plt_->add_entry(gsym);
 }
@@ -4300,7 +4300,8 @@ Target_arm<big_endian>::do_finalize_sect
 		      == NULL);
 	  Output_segment*  exidx_segment =
 	    layout->make_output_segment(elfcpp::PT_ARM_EXIDX, elfcpp::PF_R);
-	  exidx_segment->add_output_section(exidx_section, elfcpp::PF_R);
+	  exidx_segment->add_output_section(exidx_section, elfcpp::PF_R,
+					    false);
 	}
     }
 }
Index: common.cc
===================================================================
RCS file: /cvs/src/src/gold/common.cc,v
retrieving revision 1.18
diff -p -u -r1.18 common.cc
--- common.cc	22 Jun 2009 06:51:53 -0000	1.18
+++ common.cc	4 Nov 2009 15:51:58 -0000
@@ -239,7 +239,7 @@ Symbol_table::do_allocate_commons_list(
   Output_data_space *poc = new Output_data_space(addralign, ds_name);
   Output_section *os = layout->add_output_section_data(name,
 						       elfcpp::SHT_NOBITS,
-						       flags, poc);
+						       flags, poc, false);
   if (os != NULL)
     {
       if (commons_section_type == COMMONS_SMALL)
Index: copy-relocs.cc
===================================================================
RCS file: /cvs/src/src/gold/copy-relocs.cc,v
retrieving revision 1.5
diff -p -u -r1.5 copy-relocs.cc
--- copy-relocs.cc	1 Oct 2009 00:58:38 -0000	1.5
+++ copy-relocs.cc	4 Nov 2009 15:51:58 -0000
@@ -138,7 +138,7 @@ Copy_relocs<sh_type, size, big_endian>::
       layout->add_output_section_data(".bss",
 				      elfcpp::SHT_NOBITS,
 				      elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
-				      this->dynbss_);
+				      this->dynbss_, false);
     }
 
   Output_data_space* dynbss = this->dynbss_;
Index: i386.cc
===================================================================
RCS file: /cvs/src/src/gold/i386.cc,v
retrieving revision 1.97
diff -p -u -r1.97 i386.cc
--- i386.cc	30 Oct 2009 18:49:59 -0000	1.97
+++ i386.cc	4 Nov 2009 15:51:59 -0000
@@ -459,7 +459,7 @@ Target_i386::got_section(Symbol_table* s
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 					   (elfcpp::SHF_ALLOC
 					    | elfcpp::SHF_WRITE),
-					   this->got_);
+					   this->got_, false);
       os->set_is_relro();
 
       // The old GNU linker creates a .got.plt section.  We just
@@ -470,7 +470,7 @@ Target_i386::got_section(Symbol_table* s
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 					   (elfcpp::SHF_ALLOC
 					    | elfcpp::SHF_WRITE),
-					   this->got_plt_);
+					   this->got_plt_, false);
       os->set_is_relro();
 
       // The first three entries are reserved.
@@ -498,7 +498,7 @@ Target_i386::rel_dyn_section(Layout* lay
       gold_assert(layout != NULL);
       this->rel_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
-				      elfcpp::SHF_ALLOC, this->rel_dyn_);
+				      elfcpp::SHF_ALLOC, this->rel_dyn_, true);
     }
   return this->rel_dyn_;
 }
@@ -573,7 +573,7 @@ Output_data_plt_i386::Output_data_plt_i3
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
-				  elfcpp::SHF_ALLOC, this->rel_);
+				  elfcpp::SHF_ALLOC, this->rel_, true);
 }
 
 void
@@ -758,7 +758,7 @@ Target_i386::make_plt_entry(Symbol_table
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_EXECINSTR),
-				      this->plt_);
+				      this->plt_, false);
     }
 
   this->plt_->add_entry(gsym);
Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.143
diff -p -u -r1.143 layout.cc
--- layout.cc	30 Oct 2009 18:49:59 -0000	1.143
+++ layout.cc	4 Nov 2009 15:52:01 -0000
@@ -388,11 +388,14 @@ Layout::find_output_segment(elfcpp::PT t
 
 // Return the output section to use for section NAME with type TYPE
 // and section flags FLAGS.  NAME must be canonicalized in the string
-// pool, and NAME_KEY is the key.
+// pool, and NAME_KEY is the key.  IS_INTERP is true if this is the
+// .interp section.  IS_DYNAMIC_LINKER_SECTION is true if this section
+// is used by the dynamic linker.
 
 Output_section*
 Layout::get_output_section(const char* name, Stringpool::Key name_key,
-			   elfcpp::Elf_Word type, elfcpp::Elf_Xword flags)
+			   elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
+			   bool is_interp, bool is_dynamic_linker_section)
 {
   elfcpp::Elf_Xword lookup_flags = flags;
 
@@ -441,7 +444,8 @@ Layout::get_output_section(const char* n
 	}
 
       if (os == NULL)
-	os = this->make_output_section(name, type, flags);
+	os = this->make_output_section(name, type, flags, is_interp,
+				       is_dynamic_linker_section);
       ins.first->second = os;
       return os;
     }
@@ -451,13 +455,16 @@ Layout::get_output_section(const char* n
 // RELOBJ, with type TYPE and flags FLAGS.  RELOBJ may be NULL for a
 // linker created section.  IS_INPUT_SECTION is true if we are
 // choosing an output section for an input section found in a input
-// file.  This will return NULL if the input section should be
-// discarded.
+// file.  IS_INTERP is true if this is the .interp section.
+// IS_DYNAMIC_LINKER_SECTION is true if this section is used by the
+// dynamic linker.  This will return NULL if the input section should
+// be discarded.
 
 Output_section*
 Layout::choose_output_section(const Relobj* relobj, const char* name,
 			      elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
-			      bool is_input_section)
+			      bool is_input_section, bool is_interp,
+			      bool is_dynamic_linker_section)
 {
   // We should not see any input sections after we have attached
   // sections to segments.
@@ -505,7 +512,9 @@ Layout::choose_output_section(const Relo
 
 	  name = this->namepool_.add(name, false, NULL);
 
-	  Output_section* os = this->make_output_section(name, type, flags);
+	  Output_section* os =
+	    this->make_output_section(name, type, flags, is_interp,
+				      is_dynamic_linker_section);
 	  os->set_found_in_sections_clause();
 	  *output_section_slot = os;
 	  return os;
@@ -528,7 +537,8 @@ Layout::choose_output_section(const Relo
 
   // Find or make the output section.  The output section is selected
   // based on the section name, type, and flags.
-  return this->get_output_section(name, name_key, type, flags);
+  return this->get_output_section(name, name_key, type, flags, is_interp,
+				  is_dynamic_linker_section);
 }
 
 // Return the output section to use for input section SHNDX, with name
@@ -561,12 +571,13 @@ Layout::layout(Sized_relobj<size, big_en
     {
       name = this->namepool_.add(name, true, NULL);
       os = this->make_output_section(name, shdr.get_sh_type(),
-				     shdr.get_sh_flags());
+				     shdr.get_sh_flags(), false, false);
     }
   else
     {
       os = this->choose_output_section(object, name, shdr.get_sh_type(),
-				       shdr.get_sh_flags(), true);
+				       shdr.get_sh_flags(), true, false,
+				       false);
       if (os == NULL)
 	return NULL;
     }
@@ -617,7 +628,7 @@ Layout::layout_reloc(Sized_relobj<size, 
   Output_section* os = this->choose_output_section(object, name.c_str(),
 						   sh_type,
 						   shdr.get_sh_flags(),
-						   false);
+						   false, false, false);
 
   os->set_should_link_to_symtab();
   os->set_info_section(data_section);
@@ -664,7 +675,8 @@ Layout::layout_group(Symbol_table* symta
   group_section_name = this->namepool_.add(group_section_name, true, NULL);
   Output_section* os = this->make_output_section(group_section_name,
 						 elfcpp::SHT_GROUP,
-						 shdr.get_sh_flags());
+						 shdr.get_sh_flags(),
+						 false, false);
 
   // We need to find a symbol with the signature in the symbol table.
   // If we don't find one now, we need to look again later.
@@ -718,7 +730,7 @@ Layout::layout_eh_frame(Sized_relobj<siz
 						   name,
 						   elfcpp::SHT_PROGBITS,
 						   elfcpp::SHF_ALLOC,
-						   false);
+						   false, false, false);
   if (os == NULL)
     return NULL;
 
@@ -734,7 +746,7 @@ Layout::layout_eh_frame(Sized_relobj<siz
 					".eh_frame_hdr",
 					elfcpp::SHT_PROGBITS,
 					elfcpp::SHF_ALLOC,
-					false);
+					false, false, false);
 
 	  if (hdr_os != NULL)
 	    {
@@ -749,7 +761,7 @@ Layout::layout_eh_frame(Sized_relobj<siz
 		  Output_segment* hdr_oseg;
 		  hdr_oseg = this->make_output_segment(elfcpp::PT_GNU_EH_FRAME,
 						       elfcpp::PF_R);
-		  hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R);
+		  hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R, false);
 		}
 
 	      this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
@@ -800,10 +812,12 @@ Layout::layout_eh_frame(Sized_relobj<siz
 Output_section*
 Layout::add_output_section_data(const char* name, elfcpp::Elf_Word type,
 				elfcpp::Elf_Xword flags,
-				Output_section_data* posd)
+				Output_section_data* posd,
+				bool is_dynamic_linker_section)
 {
   Output_section* os = this->choose_output_section(NULL, name, type, flags,
-						   false);
+						   false, false,
+						   is_dynamic_linker_section);
   if (os != NULL)
     os->add_output_section_data(posd);
   return os;
@@ -838,11 +852,14 @@ is_compressible_debug_section(const char
 }
 
 // Make a new Output_section, and attach it to segments as
-// appropriate.
+// appropriate.  IS_INTERP is true if this is the .interp section.
+// IS_DYNAMIC_LINKER_SECTION is true if this section is used by the
+// dynamic linker.
 
 Output_section*
 Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
-			    elfcpp::Elf_Xword flags)
+			    elfcpp::Elf_Xword flags, bool is_interp,
+			    bool is_dynamic_linker_section)
 {
   Output_section* os;
   if ((flags & elfcpp::SHF_ALLOC) == 0
@@ -850,7 +867,6 @@ Layout::make_output_section(const char* 
       && is_compressible_debug_section(name))
     os = new Output_compressed_section(&parameters->options(), name, type,
 				       flags);
-
   else if ((flags & elfcpp::SHF_ALLOC) == 0
            && parameters->options().strip_debug_non_line()
            && strcmp(".debug_abbrev", name) == 0)
@@ -876,6 +892,11 @@ Layout::make_output_section(const char* 
       os = target->make_output_section(name, type, flags);
     }
 
+  if (is_interp)
+    os->set_is_interp();
+  if (is_dynamic_linker_section)
+    os->set_is_dynamic_linker_section();
+
   parameters->target().new_output_section(os);
 
   this->section_list_.push_back(os);
@@ -971,6 +992,8 @@ Layout::attach_allocated_section_to_segm
 
   elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
 
+  bool sort_sections = !this->script_options_->saw_sections_clause();
+
   // In general the only thing we really care about for PT_LOAD
   // segments is whether or not they are writable, so that is how we
   // search for them.  Large data sections also go into their own
@@ -998,7 +1021,7 @@ Layout::attach_allocated_section_to_segm
       if (os->is_large_data_section() && !(*p)->is_large_data_segment())
 	continue;
 
-      (*p)->add_output_section(os, seg_flags);
+      (*p)->add_output_section(os, seg_flags, sort_sections);
       break;
     }
 
@@ -1008,7 +1031,7 @@ Layout::attach_allocated_section_to_segm
                                                        seg_flags);
       if (os->is_large_data_section())
 	oseg->set_is_large_data_segment();
-      oseg->add_output_section(os, seg_flags);
+      oseg->add_output_section(os, seg_flags, sort_sections);
     }
 
   // If we see a loadable SHT_NOTE section, we create a PT_NOTE
@@ -1024,7 +1047,7 @@ Layout::attach_allocated_section_to_segm
               && (((*p)->flags() & elfcpp::PF_W)
                   == (seg_flags & elfcpp::PF_W)))
             {
-              (*p)->add_output_section(os, seg_flags);
+              (*p)->add_output_section(os, seg_flags, false);
               break;
             }
         }
@@ -1033,7 +1056,7 @@ Layout::attach_allocated_section_to_segm
         {
           Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
                                                            seg_flags);
-          oseg->add_output_section(os, seg_flags);
+          oseg->add_output_section(os, seg_flags, false);
         }
     }
 
@@ -1043,7 +1066,7 @@ Layout::attach_allocated_section_to_segm
     {
       if (this->tls_segment_ == NULL)
 	this->make_output_segment(elfcpp::PT_TLS, seg_flags);
-      this->tls_segment_->add_output_section(os, seg_flags);
+      this->tls_segment_->add_output_section(os, seg_flags, false);
     }
 
   // If -z relro is in effect, and we see a relro section, we create a
@@ -1053,7 +1076,7 @@ Layout::attach_allocated_section_to_segm
       gold_assert(seg_flags == (elfcpp::PF_R | elfcpp::PF_W));
       if (this->relro_segment_ == NULL)
 	this->make_output_segment(elfcpp::PT_GNU_RELRO, seg_flags);
-      this->relro_segment_->add_output_section(os, seg_flags);
+      this->relro_segment_->add_output_section(os, seg_flags, false);
     }
 }
 
@@ -1064,7 +1087,8 @@ Layout::make_output_section_for_script(c
 {
   name = this->namepool_.add(name, false, NULL);
   Output_section* os = this->make_output_section(name, elfcpp::SHT_PROGBITS,
-						 elfcpp::SHF_ALLOC);
+						 elfcpp::SHF_ALLOC, false,
+						 false);
   os->set_found_in_sections_clause();
   return os;
 }
@@ -1134,7 +1158,7 @@ Layout::create_initial_dynamic_sections(
 						       elfcpp::SHT_DYNAMIC,
 						       (elfcpp::SHF_ALLOC
 							| elfcpp::SHF_WRITE),
-						       false);
+						       false, false, true);
   this->dynamic_section_->set_is_relro();
 
   symtab->define_in_output_data("_DYNAMIC", NULL, this->dynamic_section_, 0, 0,
@@ -1732,7 +1756,8 @@ Layout::create_note(const char* name, in
     flags = elfcpp::SHF_ALLOC;
   Output_section* os = this->choose_output_section(NULL, section_name,
 						   elfcpp::SHT_NOTE,
-						   flags, false);
+						   flags, false, false,
+						   false);
   if (os == NULL)
     return NULL;
 
@@ -1811,7 +1836,8 @@ Layout::create_executable_stack_info()
       elfcpp::Elf_Xword flags = 0;
       if (is_stack_executable)
 	flags |= elfcpp::SHF_EXECINSTR;
-      this->make_output_section(name, elfcpp::SHT_PROGBITS, flags);
+      this->make_output_section(name, elfcpp::SHT_PROGBITS, flags, false,
+				false);
     }
   else
     {
@@ -1971,7 +1997,8 @@ Layout::create_incremental_info_sections
     this->namepool_.add(".gnu_incremental_inputs", false, NULL);
   Output_section* inputs_os =
     this->make_output_section(incremental_inputs_name,
-			      elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0);
+			      elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0,
+			      false, false);
   Output_section_data* posd =
       this->incremental_inputs_->create_incremental_inputs_section_data();
   inputs_os->add_output_section_data(posd);
@@ -1981,7 +2008,7 @@ Layout::create_incremental_info_sections
     this->namepool_.add(".gnu_incremental_strtab", false, NULL);
   Output_section* strtab_os = this->make_output_section(incremental_strtab_name,
                                                         elfcpp::SHT_STRTAB,
-                                                        0);
+                                                        0, false, false);
   Output_data_strtab* strtab_data =
     new Output_data_strtab(this->incremental_inputs_->get_stringpool());
   strtab_os->add_output_section_data(strtab_data);
@@ -2593,7 +2620,7 @@ Layout::create_symtab_sections(const Inp
       const char* symtab_name = this->namepool_.add(".symtab", false, NULL);
       Output_section* osymtab = this->make_output_section(symtab_name,
 							  elfcpp::SHT_SYMTAB,
-							  0);
+							  0, false, false);
       this->symtab_section_ = osymtab;
 
       Output_section_data* pos = new Output_data_fixed_space(off - startoff,
@@ -2614,7 +2641,8 @@ Layout::create_symtab_sections(const Inp
 							       false, NULL);
 	  Output_section* osymtab_xindex =
 	    this->make_output_section(symtab_xindex_name,
-				      elfcpp::SHT_SYMTAB_SHNDX, 0);
+				      elfcpp::SHT_SYMTAB_SHNDX, 0, false,
+				      false);
 
 	  size_t symcount = (off - startoff) / symsize;
 	  this->symtab_xindex_ = new Output_symtab_xindex(symcount);
@@ -2636,7 +2664,7 @@ Layout::create_symtab_sections(const Inp
       const char* strtab_name = this->namepool_.add(".strtab", false, NULL);
       Output_section* ostrtab = this->make_output_section(strtab_name,
 							  elfcpp::SHT_STRTAB,
-							  0);
+							  0, false, false);
 
       Output_section_data* pstr = new Output_data_strtab(&this->sympool_);
       ostrtab->add_output_section_data(pstr);
@@ -2663,7 +2691,8 @@ Layout::create_shstrtab()
 
   const char* name = this->namepool_.add(".shstrtab", false, NULL);
 
-  Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0);
+  Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0,
+						 false, false);
 
   // We can't write out this section until we've set all the section
   // names, and we don't set the names of compressed output sections
@@ -2776,7 +2805,7 @@ Layout::create_dynamic_symtab(const Inpu
   Output_section* dynsym = this->choose_output_section(NULL, ".dynsym",
 						       elfcpp::SHT_DYNSYM,
 						       elfcpp::SHF_ALLOC,
-						       false);
+						       false, false, true);
 
   Output_section_data* odata = new Output_data_fixed_space(index * symsize,
 							   align,
@@ -2806,7 +2835,7 @@ Layout::create_dynamic_symtab(const Inpu
 	this->choose_output_section(NULL, ".dynsym_shndx",
 				    elfcpp::SHT_SYMTAB_SHNDX,
 				    elfcpp::SHF_ALLOC,
-				    false);
+				    false, false, true);
 
       this->dynsym_xindex_ = new Output_symtab_xindex(index);
 
@@ -2829,7 +2858,7 @@ Layout::create_dynamic_symtab(const Inpu
   Output_section* dynstr = this->choose_output_section(NULL, ".dynstr",
 						       elfcpp::SHT_STRTAB,
 						       elfcpp::SHF_ALLOC,
-						       false);
+						       false, false, true);
 
   Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
   dynstr->add_output_section_data(strdata);
@@ -2855,7 +2884,7 @@ Layout::create_dynamic_symtab(const Inpu
       Output_section* hashsec = this->choose_output_section(NULL, ".hash",
 							    elfcpp::SHT_HASH,
 							    elfcpp::SHF_ALLOC,
-							    false);
+							    false, false, true);
 
       Output_section_data* hashdata = new Output_data_const_buffer(phash,
 								   hashlen,
@@ -2880,7 +2909,7 @@ Layout::create_dynamic_symtab(const Inpu
       Output_section* hashsec = this->choose_output_section(NULL, ".gnu.hash",
 							    elfcpp::SHT_GNU_HASH,
 							    elfcpp::SHF_ALLOC,
-							    false);
+							    false, false, true);
 
       Output_section_data* hashdata = new Output_data_const_buffer(phash,
 								   hashlen,
@@ -2978,7 +3007,7 @@ Layout::sized_create_version_sections(
   Output_section* vsec = this->choose_output_section(NULL, ".gnu.version",
 						     elfcpp::SHT_GNU_versym,
 						     elfcpp::SHF_ALLOC,
-						     false);
+						     false, false, true);
 
   unsigned char* vbuf;
   unsigned int vsize;
@@ -3003,7 +3032,7 @@ Layout::sized_create_version_sections(
       vdsec= this->choose_output_section(NULL, ".gnu.version_d",
 					 elfcpp::SHT_GNU_verdef,
 					 elfcpp::SHF_ALLOC,
-					 false);
+					 false, false, true);
 
       unsigned char* vdbuf;
       unsigned int vdsize;
@@ -3028,7 +3057,7 @@ Layout::sized_create_version_sections(
       vnsec = this->choose_output_section(NULL, ".gnu.version_r",
 					  elfcpp::SHT_GNU_verneed,
 					  elfcpp::SHF_ALLOC,
-					  false);
+					  false, false, true);
 
       unsigned char* vnbuf;
       unsigned int vnsize;
@@ -3068,14 +3097,14 @@ Layout::create_interp(const Target* targ
   Output_section* osec = this->choose_output_section(NULL, ".interp",
 						     elfcpp::SHT_PROGBITS,
 						     elfcpp::SHF_ALLOC,
-						     false);
+						     false, true, true);
   osec->add_output_section_data(odata);
 
   if (!this->script_options_->saw_phdrs_clause())
     {
       Output_segment* oseg = this->make_output_segment(elfcpp::PT_INTERP,
 						       elfcpp::PF_R);
-      oseg->add_output_section(osec, elfcpp::PF_R);
+      oseg->add_output_section(osec, elfcpp::PF_R, false);
     }
 }
 
@@ -3091,7 +3120,8 @@ Layout::finish_dynamic_section(const Inp
 						       (elfcpp::PF_R
 							| elfcpp::PF_W));
       oseg->add_output_section(this->dynamic_section_,
-			       elfcpp::PF_R | elfcpp::PF_W);
+			       elfcpp::PF_R | elfcpp::PF_W,
+			       false);
     }
 
   Output_data_dynamic* const odyn = this->dynamic_data_;
Index: layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.70
diff -p -u -r1.70 layout.h
--- layout.h	9 Oct 2009 23:18:19 -0000	1.70
+++ layout.h	4 Nov 2009 15:52:02 -0000
@@ -360,11 +360,13 @@ class Layout
   layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags);
 
   // Add an Output_section_data to the layout.  This is used for
-  // special sections like the GOT section.
+  // special sections like the GOT section.  IS_DYNAMIC_LINKER_SECTION
+  // is true for sections which are used by the dynamic linker, such
+  // as dynamic reloc sections.
   Output_section*
   add_output_section_data(const char* name, elfcpp::Elf_Word type,
 			  elfcpp::Elf_Xword flags,
-			  Output_section_data*);
+			  Output_section_data*, bool is_dynamic_linker_section);
 
   // Create dynamic sections if necessary.
   void
@@ -745,18 +747,21 @@ class Layout
   // Return the output section for NAME, TYPE and FLAGS.
   Output_section*
   get_output_section(const char* name, Stringpool::Key name_key,
-		     elfcpp::Elf_Word type, elfcpp::Elf_Xword flags);
+		     elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
+		     bool is_interp, bool is_dynamic_linker_section);
 
   // Choose the output section for NAME in RELOBJ.
   Output_section*
   choose_output_section(const Relobj* relobj, const char* name,
 			elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
-			bool is_input_section);
+			bool is_input_section, bool is_interp,
+			bool is_dynamic_linker_section);
 
   // Create a new Output_section.
   Output_section*
   make_output_section(const char* name, elfcpp::Elf_Word type,
-		      elfcpp::Elf_Xword flags);
+		      elfcpp::Elf_Xword flags, bool is_interp,
+		      bool is_dynamic_linker_section);
 
   // Attach a section to a segment.
   void
Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.102
diff -p -u -r1.102 output.cc
--- output.cc	30 Oct 2009 18:49:59 -0000	1.102
+++ output.cc	4 Nov 2009 15:52:03 -0000
@@ -1797,13 +1797,15 @@ Output_section::Output_section(const cha
     is_relro_local_(false),
     is_small_section_(false),
     is_large_section_(false),
+    is_interp_(false),
+    is_dynamic_linker_section_(false),
+    generate_code_fills_at_write_(false),
     tls_offset_(0),
     checkpoint_(NULL),
     merge_section_map_(),
     merge_section_by_properties_map_(),
     relaxed_input_section_map_(),
-    is_relaxed_input_section_map_valid_(true),
-    generate_code_fills_at_write_(false)
+    is_relaxed_input_section_map_valid_(true)
 {
   // An unallocated section has no address.  Forcing this means that
   // we don't need special treatment for symbols defined in debug
@@ -3042,7 +3044,8 @@ Output_segment::Output_segment(elfcpp::E
 
 void
 Output_segment::add_output_section(Output_section* os,
-				   elfcpp::Elf_Word seg_flags)
+				   elfcpp::Elf_Word seg_flags,
+				   bool do_sort)
 {
   gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0);
   gold_assert(!this->is_max_align_known_);
@@ -3057,6 +3060,10 @@ Output_segment::add_output_section(Outpu
   else
     pdl = &this->output_data_;
 
+  // Note that while there may be many input sections in an output
+  // section, there are normally only a few output sections in an
+  // output segment.  The loops below are expected to be fast.
+
   // So that PT_NOTE segments will work correctly, we need to ensure
   // that all SHT_NOTE sections are adjacent.  This will normally
   // happen automatically, because all the SHT_NOTE input sections
@@ -3065,11 +3072,6 @@ Output_segment::add_output_section(Outpu
   // flags, and thus be in different output sections, but for the
   // different section flags to map into the same segment flags and
   // thus the same output segment.
-
-  // Note that while there may be many input sections in an output
-  // section, there are normally only a few output sections in an
-  // output segment.  This loop is expected to be fast.
-
   if (os->type() == elfcpp::SHT_NOTE && !pdl->empty())
     {
       Output_segment::Output_data_list::iterator p = pdl->end();
@@ -3091,8 +3093,8 @@ Output_segment::add_output_section(Outpu
   // case: we group the SHF_TLS/SHT_NOBITS sections right after the
   // SHF_TLS/SHT_PROGBITS sections.  This lets us set up PT_TLS
   // correctly.  SHF_TLS sections get added to both a PT_LOAD segment
-  // and the PT_TLS segment -- we do this grouping only for the
-  // PT_LOAD segment.
+  // and the PT_TLS segment; we do this grouping only for the PT_LOAD
+  // segment.
   if (this->type_ != elfcpp::PT_TLS
       && (os->flags() & elfcpp::SHF_TLS) != 0)
     {
@@ -3222,6 +3224,67 @@ Output_segment::add_output_section(Outpu
       gold_unreachable();
     }
 
+  // We do some further output section sorting in order to make the
+  // generated program run more efficiently.  We should only do this
+  // when not using a linker script, so it is controled by the DO_SORT
+  // parameter.
+  if (do_sort)
+    {
+      // FreeBSD requires the .interp section to be in the first page
+      // of the executable.  That is a more efficient location anyhow
+      // for any OS, since it means that the kernel will have the data
+      // handy after it reads the program headers.
+      if (os->is_interp() && !pdl->empty())
+	{
+	  pdl->insert(pdl->begin(), os);
+	  return;
+	}
+
+      // Put loadable non-writable notes immediately after the .interp
+      // sections, so that the PT_NOTE segment is on the first page of
+      // the executable.
+      if (os->type() == elfcpp::SHT_NOTE
+	  && (os->flags() & elfcpp::SHF_WRITE) == 0
+	  && !pdl->empty())
+	{
+	  Output_segment::Output_data_list::iterator p = pdl->begin();
+	  if ((*p)->is_section() && (*p)->output_section()->is_interp())
+	    ++p;
+	  pdl->insert(p, os);
+	}
+
+      // If this section is used by the dynamic linker, and it is not
+      // writable, then put it first, after the .interp section and
+      // any loadable notes.  This makes it more likely that the
+      // dynamic linker will have to read less data from the disk.
+      if (os->is_dynamic_linker_section()
+	  && !pdl->empty()
+	  && (os->flags() & elfcpp::SHF_WRITE) == 0)
+	{
+	  bool is_reloc = (os->type() == elfcpp::SHT_REL
+			   || os->type() == elfcpp::SHT_RELA);
+	  Output_segment::Output_data_list::iterator p = pdl->begin();
+	  while (p != pdl->end()
+		 && (*p)->is_section()
+		 && ((*p)->output_section()->is_dynamic_linker_section()
+		     || (*p)->output_section()->type() == elfcpp::SHT_NOTE))
+	    {
+	      // Put reloc sections after the other ones.  Putting the
+	      // dynamic reloc sections first confuses BFD, notably
+	      // objcopy and strip.
+	      if (!is_reloc
+		  && ((*p)->output_section()->type() == elfcpp::SHT_REL
+		      || (*p)->output_section()->type() == elfcpp::SHT_RELA))
+		break;
+	      ++p;
+	    }
+	  pdl->insert(p, os);
+	  return;
+	}
+    }
+
+  // If there were no constraints on the output section, just add it
+  // to the end of the list.
   pdl->push_back(os);
 }
 
Index: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.86
diff -p -u -r1.86 output.h
--- output.h	21 Oct 2009 08:08:41 -0000	1.86
+++ output.h	4 Nov 2009 15:52:04 -0000
@@ -2378,6 +2378,27 @@ class Output_section : public Output_dat
   is_large_data_section()
   { return this->is_large_section_ && this->type_ != elfcpp::SHT_NOBITS; }
 
+  // True if this is the .interp section which goes into the PT_INTERP
+  // segment.
+  bool
+  is_interp() const
+  { return this->is_interp_; }
+
+  // Record that this is the interp section.
+  void
+  set_is_interp()
+  { this->is_interp_ = true; }
+
+  // True if this is a section used by the dynamic linker.
+  bool
+  is_dynamic_linker_section() const
+  { return this->is_dynamic_linker_section_; }
+
+  // Record that this is a section used by the dynamic linker.
+  void
+  set_is_dynamic_linker_section()
+  { this->is_dynamic_linker_section_ = true; }
+
   // Return whether this section should be written after all the input
   // sections are complete.
   bool
@@ -3318,6 +3339,13 @@ class Output_section : public Output_dat
   bool is_small_section_ : 1;
   // True if this is a large section.
   bool is_large_section_ : 1;
+  // True if this is the .interp section going into the PT_INTERP
+  // segment.
+  bool is_interp_ : 1;
+  // True if this is section is read by the dynamic linker.
+  bool is_dynamic_linker_section_ : 1;
+  // Whether code-fills are generated at write.
+  bool generate_code_fills_at_write_ : 1;
   // For SHT_TLS sections, the offset of this section relative to the base
   // of the TLS segment.
   uint64_t tls_offset_;
@@ -3328,13 +3356,11 @@ class Output_section : public Output_dat
   // Map from merge section properties to merge_sections;
   Merge_section_by_properties_map merge_section_by_properties_map_;
   // Map from input sections to relaxed input sections.  This is mutable
-  // beacause it is udpated lazily.  We may need to update it in a
+  // because it is updated lazily.  We may need to update it in a
   // const qualified method.
   mutable Output_section_data_by_input_section_map relaxed_input_section_map_;
   // Whether relaxed_input_section_map_ is valid.
   mutable bool is_relaxed_input_section_map_valid_;
-  // Whether code-fills are generated at write.
-  bool generate_code_fills_at_write_;
 };
 
 // An output segment.  PT_LOAD segments are built from collections of
@@ -3403,9 +3429,12 @@ class Output_segment
   uint64_t
   maximum_alignment();
 
-  // Add an Output_section to this segment.
+  // Add the Output_section OS to this segment.  SEG_FLAGS is the
+  // segment flags to use.  DO_SORT is true if we should sort the
+  // placement of the input section for more efficient generated code.
   void
-  add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags);
+  add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags,
+		     bool do_sort);
 
   // Remove an Output_section from this segment.  It is an error if it
   // is not present.
Index: powerpc.cc
===================================================================
RCS file: /cvs/src/src/gold/powerpc.cc,v
retrieving revision 1.18
diff -p -u -r1.18 powerpc.cc
--- powerpc.cc	30 Oct 2009 18:49:59 -0000	1.18
+++ powerpc.cc	4 Nov 2009 15:52:04 -0000
@@ -708,7 +708,7 @@ Target_powerpc<size, big_endian>::got_se
 
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				      elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
-				      this->got_);
+				      this->got_, false);
 
       // Create the GOT2 or TOC in the .got section.
       if (size == 32)
@@ -717,7 +717,7 @@ Target_powerpc<size, big_endian>::got_se
 	  layout->add_output_section_data(".got2", elfcpp::SHT_PROGBITS,
 					  elfcpp::SHF_ALLOC
 					  | elfcpp::SHF_WRITE,
-					  this->got2_);
+					  this->got2_, false);
 	}
       else
 	{
@@ -725,7 +725,7 @@ Target_powerpc<size, big_endian>::got_se
 	  layout->add_output_section_data(".toc", elfcpp::SHT_PROGBITS,
 					  elfcpp::SHF_ALLOC
 					  | elfcpp::SHF_WRITE,
-					  this->toc_);
+					  this->toc_, false);
 	}
 
       // Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
@@ -751,7 +751,7 @@ Target_powerpc<size, big_endian>::rela_d
       gold_assert(layout != NULL);
       this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
-				      elfcpp::SHF_ALLOC, this->rela_dyn_);
+				      elfcpp::SHF_ALLOC, this->rela_dyn_, true);
     }
   return this->rela_dyn_;
 }
@@ -811,7 +811,7 @@ Output_data_plt_powerpc<size, big_endian
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
-				  elfcpp::SHF_ALLOC, this->rel_);
+				  elfcpp::SHF_ALLOC, this->rel_, true);
 }
 
 template<int size, bool big_endian>
@@ -940,7 +940,7 @@ Target_powerpc<size, big_endian>::make_p
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_EXECINSTR
 				       | elfcpp::SHF_WRITE),
-				      this->plt_);
+				      this->plt_, false);
 
       // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
       symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
@@ -1502,7 +1502,7 @@ Target_powerpc<size, big_endian>::scan_r
     Output_section* os = layout->add_output_section_data(".sdata", 0,
 							 elfcpp::SHF_ALLOC
 							 | elfcpp::SHF_WRITE,
-							 sdata);
+							 sdata, false);
     symtab->define_in_output_data("_SDA_BASE_", NULL,
 				  os,
 				  32768, 0,
Index: script-sections.cc
===================================================================
RCS file: /cvs/src/src/gold/script-sections.cc,v
retrieving revision 1.25
diff -p -u -r1.25 script-sections.cc
--- script-sections.cc	16 Oct 2009 18:56:07 -0000	1.25
+++ script-sections.cc	4 Nov 2009 15:52:05 -0000
@@ -3094,7 +3094,7 @@ Script_sections::create_segments(Layout*
 	  is_current_seg_readonly = true;
 	}
 
-      current_seg->add_output_section(*p, seg_flags);
+      current_seg->add_output_section(*p, seg_flags, false);
 
       if (((*p)->flags() & elfcpp::SHF_WRITE) != 0)
 	is_current_seg_readonly = false;
@@ -3173,7 +3173,7 @@ Script_sections::create_note_and_tls_seg
 	    Layout::section_flags_to_segment((*p)->flags());
 	  Output_segment* oseg = layout->make_output_segment(elfcpp::PT_NOTE,
 							     seg_flags);
-	  oseg->add_output_section(*p, seg_flags);
+	  oseg->add_output_section(*p, seg_flags, false);
 
 	  // Incorporate any subsequent SHT_NOTE sections, in the
 	  // hopes that the script is sensible.
@@ -3182,7 +3182,7 @@ Script_sections::create_note_and_tls_seg
 		 && (*pnext)->type() == elfcpp::SHT_NOTE)
 	    {
 	      seg_flags = Layout::section_flags_to_segment((*pnext)->flags());
-	      oseg->add_output_section(*pnext, seg_flags);
+	      oseg->add_output_section(*pnext, seg_flags, false);
 	      p = pnext;
 	      ++pnext;
 	    }
@@ -3197,14 +3197,14 @@ Script_sections::create_note_and_tls_seg
 	    Layout::section_flags_to_segment((*p)->flags());
 	  Output_segment* oseg = layout->make_output_segment(elfcpp::PT_TLS,
 							     seg_flags);
-	  oseg->add_output_section(*p, seg_flags);
+	  oseg->add_output_section(*p, seg_flags, false);
 
 	  Layout::Section_list::const_iterator pnext = p + 1;
 	  while (pnext != sections->end()
 		 && ((*pnext)->flags() & elfcpp::SHF_TLS) != 0)
 	    {
 	      seg_flags = Layout::section_flags_to_segment((*pnext)->flags());
-	      oseg->add_output_section(*pnext, seg_flags);
+	      oseg->add_output_section(*pnext, seg_flags, false);
 	      p = pnext;
 	      ++pnext;
 	    }
@@ -3358,7 +3358,7 @@ Script_sections::attach_sections_using_p
 
 	      elfcpp::Elf_Word seg_flags =
 		Layout::section_flags_to_segment(os->flags());
-	      r->second->add_output_section(os, seg_flags);
+	      r->second->add_output_section(os, seg_flags, false);
 
 	      if (r->second->type() == elfcpp::PT_LOAD)
 		{
Index: sparc.cc
===================================================================
RCS file: /cvs/src/src/gold/sparc.cc,v
retrieving revision 1.22
diff -p -u -r1.22 sparc.cc
--- sparc.cc	30 Oct 2009 18:49:59 -0000	1.22
+++ sparc.cc	4 Nov 2009 15:52:06 -0000
@@ -1022,7 +1022,7 @@ Target_sparc<size, big_endian>::got_sect
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 					   (elfcpp::SHF_ALLOC
 					    | elfcpp::SHF_WRITE),
-					   this->got_);
+					   this->got_, false);
       os->set_is_relro();
 
       // Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
@@ -1048,7 +1048,7 @@ Target_sparc<size, big_endian>::rela_dyn
       gold_assert(layout != NULL);
       this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
-				      elfcpp::SHF_ALLOC, this->rela_dyn_);
+				      elfcpp::SHF_ALLOC, this->rela_dyn_, true);
     }
   return this->rela_dyn_;
 }
@@ -1150,7 +1150,7 @@ Output_data_plt_sparc<size, big_endian>:
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
-				  elfcpp::SHF_ALLOC, this->rel_);
+				  elfcpp::SHF_ALLOC, this->rel_, true);
 }
 
 template<int size, bool big_endian>
@@ -1367,7 +1367,7 @@ Target_sparc<size, big_endian>::make_plt
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_EXECINSTR
 				       | elfcpp::SHF_WRITE),
-				      this->plt_);
+				      this->plt_, false);
 
       // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
       symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
Index: x86_64.cc
===================================================================
RCS file: /cvs/src/src/gold/x86_64.cc,v
retrieving revision 1.90
diff -p -u -r1.90 x86_64.cc
--- x86_64.cc	30 Oct 2009 18:49:59 -0000	1.90
+++ x86_64.cc	4 Nov 2009 15:52:07 -0000
@@ -467,7 +467,7 @@ Target_x86_64::got_section(Symbol_table*
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 					   (elfcpp::SHF_ALLOC
 					    | elfcpp::SHF_WRITE),
-					   this->got_);
+					   this->got_, false);
       os->set_is_relro();
 
       // The old GNU linker creates a .got.plt section.  We just
@@ -478,7 +478,7 @@ Target_x86_64::got_section(Symbol_table*
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 					   (elfcpp::SHF_ALLOC
 					    | elfcpp::SHF_WRITE),
-					   this->got_plt_);
+					   this->got_plt_, false);
       os->set_is_relro();
 
       // The first three entries are reserved.
@@ -506,7 +506,7 @@ Target_x86_64::rela_dyn_section(Layout* 
       gold_assert(layout != NULL);
       this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
-				      elfcpp::SHF_ALLOC, this->rela_dyn_);
+				      elfcpp::SHF_ALLOC, this->rela_dyn_, true);
     }
   return this->rela_dyn_;
 }
@@ -606,7 +606,7 @@ Output_data_plt_x86_64::Output_data_plt_
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
-				  elfcpp::SHF_ALLOC, this->rel_);
+				  elfcpp::SHF_ALLOC, this->rel_, true);
 }
 
 void
@@ -802,7 +802,7 @@ Target_x86_64::make_plt_section(Symbol_t
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_EXECINSTR),
-				      this->plt_);
+				      this->plt_, false);
     }
 }
 

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