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]

Re: gold input section handling


David Miller <davem@davemloft.net> writes:

> From: Ian Lance Taylor <iant@google.com>
> Date: Mon, 14 Apr 2008 09:45:05 -0700
>
>> Because the Linux kernel is not reliable about setting section flags
>> in assembler source, gold has exceptions such that it will combine
>> sections with zero flags with sections with non-zero flags if they
>> have the same name.
>> 
>> Because gcc uses an optimization for the .eh_frame section, making it
>> read-only possible and read-write when necessary, gold has an
>> exception for the .eh_frame section.
>
> I think the fact that gold needs two exceptions already, and we know
> of other cases that break, are good indications that it may not be
> tenable, in the end, to enforce this rule.
>
> There seems to be quite some precendence of using different section
> flags in different instances of a section.

I saw your later post, but this seems like a reasonable argument to
me.  I changed gold so that it ignores SHF_WRITE and SHF_EXECINSTR
when merging sections.  It still pays attention to SHF_ALLOC, except
for sections with zero flags.

I committed the attached patch.

Ian


2008-04-14  Ian Lance Taylor  <iant@google.com>

	* layout.cc (Layout::Layout): Initialize sections_are_attached_.
	(Layout::get_output_section): Ignore SHF_WRITE and SHF_EXECINSTR
	in the name/type/flags to section mapping.  Don't call
	allocate_output_section.
	(Layout::choose_output_section): Change parameter from adjust_name
	to is_input_section.  Don't permit input sections after sections
	are attached to segments.  Don't call allocate_output_section.
	(Layout::layout_eh_frame): Call update_flags_for_input_section,
	not write_enable_output_section.
	(Layout::make_output_section): Don't push to
	unattached_section_list_ nor call attach_to_segment.  Call
	attach_section_to_segment if sections are attached.
	(Layout::attach_sections_to_segments): New function.
	(Layout::attach_section_to_segment): New function.
	(Layout::attach_allocated_section_to_segment): Rename from
	attach_to_segment.  Remove flags parameter.
	(Layout::allocate_output_section): Remove function.
	(Layout::write_enable_output_section): Remove function.
	* layout.h (class Layout): Update for above changes.  Add new
	field sections_are_attached_.
	* output.h (Output_section::update_flags_for_input_section): New
	function.
	* output.cc (Output_section::add_input_section): Call
	update_flags_for_input_section.
	* gold.cc (queue_middle_tasks): Call attach_sections_to_segments.


Index: gold.cc
===================================================================
RCS file: /cvs/src/src/gold/gold.cc,v
retrieving revision 1.51
diff -p -u -r1.51 gold.cc
--- gold.cc	4 Mar 2008 18:21:43 -0000	1.51
+++ gold.cc	15 Apr 2008 03:59:36 -0000
@@ -212,6 +212,9 @@ queue_middle_tasks(const General_options
   // Define symbols from any linker scripts.
   layout->define_script_symbols(symtab);
 
+  // Attach sections to segments.
+  layout->attach_sections_to_segments();
+
   if (!parameters->options().relocatable())
     {
       // Predefine standard symbols.
Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.97
diff -p -u -r1.97 layout.cc
--- layout.cc	9 Apr 2008 00:26:48 -0000	1.97
+++ layout.cc	15 Apr 2008 03:59:36 -0000
@@ -79,10 +79,10 @@ Layout::Layout(const General_options& op
   : options_(options), script_options_(script_options), namepool_(),
     sympool_(), dynpool_(), signatures_(),
     section_name_map_(), segment_list_(), section_list_(),
-    unattached_section_list_(), special_output_list_(),
-    section_headers_(NULL), tls_segment_(NULL), symtab_section_(NULL),
-    dynsym_section_(NULL), dynamic_section_(NULL), dynamic_data_(NULL),
-    eh_frame_section_(NULL), eh_frame_data_(NULL),
+    unattached_section_list_(), sections_are_attached_(false),
+    special_output_list_(), section_headers_(NULL), tls_segment_(NULL),
+    symtab_section_(NULL), dynsym_section_(NULL), dynamic_section_(NULL),
+    dynamic_data_(NULL), eh_frame_section_(NULL), eh_frame_data_(NULL),
     added_eh_frame_data_(false), eh_frame_hdr_section_(NULL),
     build_id_note_(NULL), group_signatures_(), output_file_size_(-1),
     input_requires_executable_stack_(false),
@@ -234,7 +234,15 @@ Output_section*
 Layout::get_output_section(const char* name, Stringpool::Key name_key,
 			   elfcpp::Elf_Word type, elfcpp::Elf_Xword flags)
 {
-  const Key key(name_key, std::make_pair(type, flags));
+  elfcpp::Elf_Xword lookup_flags = flags;
+
+  // Ignoring SHF_WRITE and SHF_EXECINSTR here means that we combine
+  // read-write with read-only sections.  Some other ELF linkers do
+  // not do this.  FIXME: Perhaps there should be an option
+  // controlling this.
+  lookup_flags &= ~(elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR);
+
+  const Key key(name_key, std::make_pair(type, lookup_flags));
   const std::pair<Key, Output_section*> v(key, NULL);
   std::pair<Section_name_map::iterator, bool> ins(
     this->section_name_map_.insert(v));
@@ -268,11 +276,7 @@ Layout::get_output_section(const char* n
               Section_name_map::iterator p =
                   this->section_name_map_.find(zero_key);
               if (p != this->section_name_map_.end())
-                {
-                  os = p->second;
-                  if ((flags & elfcpp::SHF_ALLOC) != 0)
-                    this->allocate_output_section(os, flags);
-                }
+		os = p->second;
             }
 	}
 
@@ -285,17 +289,22 @@ Layout::get_output_section(const char* n
 
 // Pick the output section to use for section NAME, in input file
 // RELOBJ, with type TYPE and flags FLAGS.  RELOBJ may be NULL for a
-// linker created section.  ADJUST_NAME is true if we should apply the
-// standard name mappings in Layout::output_section_name.  This will
-// return NULL if the input section should be discarded.
+// 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.
 
 Output_section*
 Layout::choose_output_section(const Relobj* relobj, const char* name,
 			      elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
-			      bool adjust_name)
+			      bool is_input_section)
 {
-  // We should ignore some flags.  FIXME: This will need some
-  // adjustment for ld -r.
+  // We should not see any input sections after we have attached
+  // sections to segments.
+  gold_assert(!is_input_section || !this->sections_are_attached_);
+
+  // Some flags in the input section should not be automatically
+  // copied to the output section.
   flags &= ~ (elfcpp::SHF_INFO_LINK
 	      | elfcpp::SHF_LINK_ORDER
 	      | elfcpp::SHF_GROUP
@@ -324,17 +333,7 @@ Layout::choose_output_section(const Relo
       if (output_section_slot != NULL)
 	{
 	  if (*output_section_slot != NULL)
-            {
-              // If the output section was created unallocated, and we
-              // are now allocating it, then we need to clear the
-              // address set in the constructor and remove it from the
-              // unattached section list.
-              if (((*output_section_slot)->flags() & elfcpp::SHF_ALLOC) == 0
-                  && (flags & elfcpp::SHF_ALLOC) != 0)
-                this->allocate_output_section(*output_section_slot, flags);
-
-              return *output_section_slot;
-            }
+	    return *output_section_slot;
 
 	  // We don't put sections found in the linker script into
 	  // SECTION_NAME_MAP_.  That keeps us from getting confused
@@ -356,7 +355,7 @@ Layout::choose_output_section(const Relo
   // output section.
 
   size_t len = strlen(name);
-  if (adjust_name && !parameters->options().relocatable())
+  if (is_input_section && !parameters->options().relocatable())
     name = Layout::output_section_name(name, &len);
 
   Stringpool::Key name_key;
@@ -550,16 +549,6 @@ Layout::layout_eh_frame(Sized_relobj<siz
   if (os == NULL)
     return NULL;
 
-  // On some targets gcc assumes that a read-only .eh_frame section
-  // will be merged with a read-write .eh_frame section.
-  if ((shdr.get_sh_flags() & elfcpp::SHF_WRITE) != 0
-      && (os->flags() & elfcpp::SHF_WRITE) == 0)
-    {
-      elfcpp::Elf_Xword new_flags = os->flags() | elfcpp::SHF_WRITE;
-      this->write_enable_output_section(os, new_flags);
-      os->set_flags(new_flags);
-    }
-
   if (this->eh_frame_section_ == NULL)
     {
       this->eh_frame_section_ = os;
@@ -606,6 +595,8 @@ Layout::layout_eh_frame(Sized_relobj<siz
 						      reloc_shndx,
 						      reloc_type))
     {
+      os->update_flags_for_input_section(shdr.get_sh_flags());
+
       // We found a .eh_frame section we are going to optimize, so now
       // we can add the set of optimized sections to the output
       // section.  We need to postpone adding this until we've found a
@@ -689,11 +680,6 @@ Layout::make_output_section(const char* 
 
   this->section_list_.push_back(os);
 
-  if ((flags & elfcpp::SHF_ALLOC) == 0)
-    this->unattached_section_list_.push_back(os);
-  else
-    this->attach_to_segment(os, flags);
-
   // The GNU linker by default sorts some sections by priority, so we
   // do the same.  We need to know that this might happen before we
   // attach any input sections.
@@ -704,14 +690,46 @@ Layout::make_output_section(const char* 
 	  || strcmp(name, ".fini_array") == 0))
     os->set_may_sort_attached_input_sections();
 
+  // If we have already attached the sections to segments, then we
+  // need to attach this one now.  This happens for sections created
+  // directly by the linker.
+  if (this->sections_are_attached_)
+    this->attach_section_to_segment(os);
+
   return os;
 }
 
+// Attach output sections to segments.  This is called after we have
+// seen all the input sections.
+
+void
+Layout::attach_sections_to_segments()
+{
+  for (Section_list::iterator p = this->section_list_.begin();
+       p != this->section_list_.end();
+       ++p)
+    this->attach_section_to_segment(*p);
+
+  this->sections_are_attached_ = true;
+}
+
+// Attach an output section to a segment.
+
+void
+Layout::attach_section_to_segment(Output_section* os)
+{
+  if ((os->flags() & elfcpp::SHF_ALLOC) == 0)
+    this->unattached_section_list_.push_back(os);
+  else
+    this->attach_allocated_section_to_segment(os);
+}
+
 // Attach an allocated output section to a segment.
 
 void
-Layout::attach_to_segment(Output_section* os, elfcpp::Elf_Xword flags)
+Layout::attach_allocated_section_to_segment(Output_section* os)
 {
+  elfcpp::Elf_Xword flags = os->flags();
   gold_assert((flags & elfcpp::SHF_ALLOC) != 0);
 
   if (parameters->options().relocatable())
@@ -811,58 +829,6 @@ Layout::make_output_section_for_script(c
   return os;
 }
 
-// We have to move an existing output section from the unallocated
-// list to the allocated list.
-
-void
-Layout::allocate_output_section(Output_section* os, elfcpp::Elf_Xword flags)
-{
-  os->reset_address_and_file_offset();
-
-  Section_list::iterator p = std::find(this->unattached_section_list_.begin(),
-                                       this->unattached_section_list_.end(),
-                                       os);
-  gold_assert(p != this->unattached_section_list_.end());
-  this->unattached_section_list_.erase(p);
-
-  this->attach_to_segment(os, flags);
-}
-
-// We have to move an existing output section from the read-only
-// segment to the writable segment.
-
-void
-Layout::write_enable_output_section(Output_section* os,
-                                    elfcpp::Elf_Xword flags)
-{
-  gold_assert((os->flags() & elfcpp::SHF_WRITE) == 0);
-  gold_assert(os->type() == elfcpp::SHT_PROGBITS);
-  gold_assert((flags & elfcpp::SHF_WRITE) != 0);
-  gold_assert((flags & elfcpp::SHF_ALLOC) != 0);
-
-  if (parameters->options().relocatable())
-    return;
-
-  if (this->script_options_->saw_sections_clause())
-    return;
-
-  Segment_list::iterator p;
-  for (p = this->segment_list_.begin();
-       p != this->segment_list_.end();
-       ++p)
-    {
-      if ((*p)->type() == elfcpp::PT_LOAD
-          && ((*p)->flags() & elfcpp::PF_W) == 0)
-        {
-          (*p)->remove_output_section(os);
-          break;
-        }
-    }
-  gold_assert(p != this->segment_list_.end());
-
-  this->attach_to_segment(os, flags);
-}
-
 // Return the number of segments we expect to see.
 
 size_t
Index: layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.53
diff -p -u -r1.53 layout.h
--- layout.h	9 Apr 2008 00:26:48 -0000	1.53
+++ layout.h	15 Apr 2008 03:59:36 -0000
@@ -340,6 +340,10 @@ class Layout
   static elfcpp::Elf_Word
   section_flags_to_segment(elfcpp::Elf_Xword flags);
 
+  // Attach sections to segments.
+  void
+  attach_sections_to_segments();
+
  private:
   Layout(const Layout&);
   Layout& operator=(const Layout&);
@@ -475,7 +479,7 @@ class Layout
   Output_section*
   choose_output_section(const Relobj* relobj, const char* name,
 			elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
-			bool adjust_name);
+			bool is_input_section);
 
   // Create a new Output_section.
   Output_section*
@@ -484,15 +488,11 @@ class Layout
 
   // Attach a section to a segment.
   void
-  attach_to_segment(Output_section*, elfcpp::Elf_Xword flags);
-
-  // Allocate a previously unallocated output section.
-  void
-  allocate_output_section(Output_section*, elfcpp::Elf_Xword flags);
+  attach_section_to_segment(Output_section*);
 
-  // Turn a read-only output section into a read-write output section.
+  // Attach an allocated section to a segment.
   void
-  write_enable_output_section(Output_section*, elfcpp::Elf_Xword flags);
+  attach_allocated_section_to_segment(Output_section*);
 
   // Set the final file offsets of all the segments.
   off_t
@@ -578,6 +578,8 @@ class Layout
   // The list of output sections which are not attached to any output
   // segment.
   Section_list unattached_section_list_;
+  // Whether we have attached the sections to the segments.
+  bool sections_are_attached_;
   // The list of unattached Output_data objects which require special
   // handling because they are not Output_sections.
   Data_list special_output_list_;
Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.71
diff -p -u -r1.71 output.cc
--- output.cc	11 Apr 2008 22:55:13 -0000	1.71
+++ output.cc	15 Apr 2008 03:59:37 -0000
@@ -1673,10 +1673,7 @@ Output_section::add_input_section(Sized_
     this->addralign_ = addralign;
 
   typename elfcpp::Elf_types<size>::Elf_WXword sh_flags = shdr.get_sh_flags();
-  this->flags_ |= (sh_flags
-		   & (elfcpp::SHF_WRITE
-		      | elfcpp::SHF_ALLOC
-		      | elfcpp::SHF_EXECINSTR));
+  this->update_flags_for_input_section(sh_flags);
 
   uint64_t entsize = shdr.get_sh_entsize();
 
Index: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.62
diff -p -u -r1.62 output.h
--- output.h	11 Apr 2008 22:55:13 -0000	1.62
+++ output.h	15 Apr 2008 03:59:37 -0000
@@ -1714,6 +1714,16 @@ class Output_section : public Output_dat
   set_flags(elfcpp::Elf_Xword flags)
   { this->flags_ = flags; }
 
+  // Update the output section flags based on input section flags.
+  void
+  update_flags_for_input_section(elfcpp::Elf_Xword flags)
+  {
+    this->flags_ |= (flags
+		     & (elfcpp::SHF_WRITE
+			| elfcpp::SHF_ALLOC
+			| elfcpp::SHF_EXECINSTR));
+  }
+
   // Return the entsize field.
   uint64_t
   entsize() const

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