If we a section with no flags followed by a section with the same name
authorIan Lance Taylor <iant@google.com>
Tue, 11 Mar 2008 16:50:08 +0000 (16:50 +0000)
committerIan Lance Taylor <iant@google.com>
Tue, 11 Mar 2008 16:50:08 +0000 (16:50 +0000)
with flags, put them in the same output section.

gold/layout.cc
gold/layout.h

index 124d3bcafefa41a50000b7f115d91977ce4add67..6a47064a7007eff3bfa46b2eb989da477741672a 100644 (file)
@@ -236,19 +236,38 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key,
   else
     {
       // This is the first time we've seen this name/type/flags
-      // combination.  If the section has contents but no flags, then
-      // see whether we have an existing section with the same name.
-      // This is a workaround for cases where assembler code forgets
-      // to set section flags, and the GNU linker would simply pick an
-      // existing section with the same name.  FIXME: Perhaps there
-      // should be an option to control this.
+      // combination.  For compatibility with the GNU linker, we
+      // combine sections with contents and zero flags with sections
+      // with non-zero flags.  This is a workaround for cases where
+      // assembler code forgets to set section flags.  FIXME: Perhaps
+      // there should be an option to control this.
       Output_section* os = NULL;
-      if (type == elfcpp::SHT_PROGBITS && flags == 0)
+
+      if (type == elfcpp::SHT_PROGBITS)
        {
-         os = this->find_output_section(name);
-         if (os != NULL && os->type() != elfcpp::SHT_PROGBITS)
-           os = NULL;
+          if (flags == 0)
+            {
+              Output_section* same_name = this->find_output_section(name);
+              if (same_name != NULL
+                  && same_name->type() == elfcpp::SHT_PROGBITS
+                  && (same_name->flags() & elfcpp::SHF_TLS) == 0)
+                os = same_name;
+            }
+          else if ((flags & elfcpp::SHF_TLS) == 0)
+            {
+              elfcpp::Elf_Xword zero_flags = 0;
+              const Key zero_key(name_key, std::make_pair(type, zero_flags));
+              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);
+                }
+            }
        }
+
       if (os == NULL)
        os = this->make_output_section(name, type, flags);
       ins.first->second = os;
@@ -297,7 +316,17 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
       if (output_section_slot != NULL)
        {
          if (*output_section_slot != NULL)
-           return *output_section_slot;
+            {
+              // 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;
+            }
 
          // We don't put sections found in the linker script into
          // SECTION_NAME_MAP_.  That keeps us from getting confused
@@ -623,93 +652,101 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
   if ((flags & elfcpp::SHF_ALLOC) == 0)
     this->unattached_section_list_.push_back(os);
   else
-    {
-      if (parameters->options().relocatable())
-       return os;
+    this->attach_to_segment(os, flags);
 
-      // If we have a SECTIONS clause, we can't handle the attachment
-      // to segments until after we've seen all the sections.
-      if (this->script_options_->saw_sections_clause())
-       return os;
+  return os;
+}
 
-      gold_assert(!this->script_options_->saw_phdrs_clause());
+// Attach an allocated output section to a segment.
 
-      // This output section goes into a PT_LOAD segment.
+void
+Layout::attach_to_segment(Output_section* os, elfcpp::Elf_Xword flags)
+{
+  gold_assert((flags & elfcpp::SHF_ALLOC) != 0);
 
-      elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
+  if (parameters->options().relocatable())
+    return;
 
-      // 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.  People who need segments sorted on some
-      // other basis will have to use a linker script.
+  // If we have a SECTIONS clause, we can't handle the attachment to
+  // segments until after we've seen all the sections.
+  if (this->script_options_->saw_sections_clause())
+    return;
 
-      Segment_list::const_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) == (seg_flags & elfcpp::PF_W))
-           {
-             // If -Tbss was specified, we need to separate the data
-             // and BSS segments.
-             if (this->options_.user_set_Tbss())
-               {
-                 if ((type == elfcpp::SHT_NOBITS)
-                     == (*p)->has_any_data_sections())
-                   continue;
-               }
+  gold_assert(!this->script_options_->saw_phdrs_clause());
 
-             (*p)->add_output_section(os, seg_flags);
-             break;
-           }
-       }
+  // This output section goes into a PT_LOAD segment.
 
-      if (p == this->segment_list_.end())
-       {
-         Output_segment* oseg = this->make_output_segment(elfcpp::PT_LOAD,
-                                                          seg_flags);
-         oseg->add_output_section(os, seg_flags);
-       }
+  elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
 
-      // If we see a loadable SHT_NOTE section, we create a PT_NOTE
-      // segment.
-      if (type == elfcpp::SHT_NOTE)
-       {
-         // See if we already have an equivalent PT_NOTE segment.
-         for (p = this->segment_list_.begin();
-              p != segment_list_.end();
-              ++p)
-           {
-             if ((*p)->type() == elfcpp::PT_NOTE
-                 && (((*p)->flags() & elfcpp::PF_W)
-                     == (seg_flags & elfcpp::PF_W)))
-               {
-                 (*p)->add_output_section(os, seg_flags);
-                 break;
-               }
-           }
+  // 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.  People who need segments sorted on some other
+  // basis will have to use a linker script.
 
-         if (p == this->segment_list_.end())
-           {
-             Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
-                                                              seg_flags);
-             oseg->add_output_section(os, seg_flags);
-           }
-       }
+  Segment_list::const_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) == (seg_flags & elfcpp::PF_W))
+        {
+          // If -Tbss was specified, we need to separate the data
+          // and BSS segments.
+          if (this->options_.user_set_Tbss())
+            {
+              if ((os->type() == elfcpp::SHT_NOBITS)
+                  == (*p)->has_any_data_sections())
+                continue;
+            }
 
-      // If we see a loadable SHF_TLS section, we create a PT_TLS
-      // segment.  There can only be one such segment.
-      if ((flags & elfcpp::SHF_TLS) != 0)
-       {
-         if (this->tls_segment_ == NULL)
-           this->tls_segment_ = this->make_output_segment(elfcpp::PT_TLS,
-                                                          seg_flags);
-         this->tls_segment_->add_output_section(os, seg_flags);
-       }
+          (*p)->add_output_section(os, seg_flags);
+          break;
+        }
     }
 
-  return os;
+  if (p == this->segment_list_.end())
+    {
+      Output_segment* oseg = this->make_output_segment(elfcpp::PT_LOAD,
+                                                       seg_flags);
+      oseg->add_output_section(os, seg_flags);
+    }
+
+  // If we see a loadable SHT_NOTE section, we create a PT_NOTE
+  // segment.
+  if (os->type() == elfcpp::SHT_NOTE)
+    {
+      // See if we already have an equivalent PT_NOTE segment.
+      for (p = this->segment_list_.begin();
+           p != segment_list_.end();
+           ++p)
+        {
+          if ((*p)->type() == elfcpp::PT_NOTE
+              && (((*p)->flags() & elfcpp::PF_W)
+                  == (seg_flags & elfcpp::PF_W)))
+            {
+              (*p)->add_output_section(os, seg_flags);
+              break;
+            }
+        }
+
+      if (p == this->segment_list_.end())
+        {
+          Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
+                                                           seg_flags);
+          oseg->add_output_section(os, seg_flags);
+        }
+    }
+
+  // If we see a loadable SHF_TLS section, we create a PT_TLS
+  // segment.  There can only be one such segment.
+  if ((flags & elfcpp::SHF_TLS) != 0)
+    {
+      if (this->tls_segment_ == NULL)
+        this->tls_segment_ = this->make_output_segment(elfcpp::PT_TLS,
+                                                       seg_flags);
+      this->tls_segment_->add_output_section(os, seg_flags);
+    }
 }
 
 // Make an output section for a script.
@@ -724,6 +761,23 @@ Layout::make_output_section_for_script(const char* name)
   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);
+}
+
 // Return the number of segments we expect to see.
 
 size_t
index 100518305e1683d9723508c54f2412a791e4a333..1712db95ea4646c4f0fdb754c65b8a9f6fbda220 100644 (file)
@@ -469,6 +469,14 @@ class Layout
   make_output_section(const char* name, elfcpp::Elf_Word type,
                      elfcpp::Elf_Xword flags);
 
+  // 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);
+
   // Set the final file offsets of all the segments.
   off_t
   set_segment_offsets(const Target*, Output_segment*, unsigned int* pshndx);