PR ld/6430
[deliverable/binutils-gdb.git] / gold / layout.cc
index a3bcf2135698fa9f49c0f28354314ad9f819c42a..eae66794eb5b3d5c11ba0f503aa9f4577c211f9d 100644 (file)
@@ -90,6 +90,7 @@ Layout::Layout(const General_options& options, Script_options* script_options)
     special_output_list_(),
     section_headers_(NULL),
     tls_segment_(NULL),
+    relro_segment_(NULL),
     symtab_section_(NULL),
     symtab_xindex_(NULL),
     dynsym_section_(NULL),
@@ -192,11 +193,7 @@ Layout::include_section(Sized_relobj<size, big_endian>*, const char* name,
       if (parameters->options().strip_debug()
          && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
        {
-         // Debugging sections can only be recognized by name.
-         if (is_prefix_of(".debug", name)
-             || is_prefix_of(".gnu.linkonce.wi.", name)
-             || is_prefix_of(".line", name)
-             || is_prefix_of(".stab", name))
+         if (is_debug_info_section(name))
            return false;
        }
       if (parameters->options().strip_debug_gdb()
@@ -507,7 +504,8 @@ Layout::layout_group(Symbol_table* symtab,
                     const char* group_section_name,
                     const char* signature,
                     const elfcpp::Shdr<size, big_endian>& shdr,
-                    const elfcpp::Elf_Word* contents)
+                    elfcpp::Elf_Word flags,
+                    std::vector<unsigned int>* shndxes)
 {
   gold_assert(parameters->options().relocatable());
   gold_assert(shdr.get_sh_type() == elfcpp::SHT_GROUP);
@@ -535,7 +533,8 @@ Layout::layout_group(Symbol_table* symtab,
   section_size_type entry_count =
     convert_to_section_size_type(shdr.get_sh_size() / 4);
   Output_section_data* posd =
-    new Output_data_group<size, big_endian>(object, entry_count, contents);
+    new Output_data_group<size, big_endian>(object, entry_count, flags,
+                                           shndxes);
   os->add_output_section_data(posd);
 }
 
@@ -639,9 +638,10 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
   return os;
 }
 
-// Add POSD to an output section using NAME, TYPE, and FLAGS.
+// Add POSD to an output section using NAME, TYPE, and FLAGS.  Return
+// the output section.
 
-void
+Output_section*
 Layout::add_output_section_data(const char* name, elfcpp::Elf_Word type,
                                elfcpp::Elf_Xword flags,
                                Output_section_data* posd)
@@ -650,6 +650,7 @@ Layout::add_output_section_data(const char* name, elfcpp::Elf_Word type,
                                                   false);
   if (os != NULL)
     os->add_output_section_data(posd);
+  return os;
 }
 
 // Map section flags to segment flags.
@@ -708,6 +709,23 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
          || strcmp(name, ".fini_array") == 0))
     os->set_may_sort_attached_input_sections();
 
+  // With -z relro, we have to recognize the special sections by name.
+  // There is no other way.
+  if (!this->script_options_->saw_sections_clause()
+      && parameters->options().relro()
+      && type == elfcpp::SHT_PROGBITS
+      && (flags & elfcpp::SHF_ALLOC) != 0
+      && (flags & elfcpp::SHF_WRITE) != 0)
+    {
+      if (strcmp(name, ".data.rel.ro") == 0)
+       os->set_is_relro();
+      else if (strcmp(name, ".data.rel.ro.local") == 0)
+       {
+         os->set_is_relro();
+         os->set_is_relro_local();
+       }
+    }
+
   // 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.
@@ -833,6 +851,17 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
                                                        seg_flags);
       this->tls_segment_->add_output_section(os, seg_flags);
     }
+
+  // If -z relro is in effect, and we see a relro section, we create a
+  // PT_GNU_RELRO segment.  There can only be one such segment.
+  if (os->is_relro() && parameters->options().relro())
+    {
+      gold_assert(seg_flags == (elfcpp::PF_R | elfcpp::PF_W));
+      if (this->relro_segment_ == NULL)
+       this->relro_segment_ = this->make_output_segment(elfcpp::PT_GNU_RELRO,
+                                                        seg_flags);
+      this->relro_segment_->add_output_section(os, seg_flags);
+    }
 }
 
 // Make an output section for a script.
@@ -903,6 +932,7 @@ Layout::create_initial_dynamic_sections(Symbol_table* symtab)
                                                       (elfcpp::SHF_ALLOC
                                                        | elfcpp::SHF_WRITE),
                                                       false);
+  this->dynamic_section_->set_is_relro();
 
   symtab->define_in_output_data("_DYNAMIC", NULL, this->dynamic_section_, 0, 0,
                                elfcpp::STT_OBJECT, elfcpp::STB_LOCAL,
@@ -1510,12 +1540,25 @@ Layout::segment_precedes(const Output_segment* seg1,
   if (type2 == elfcpp::PT_LOAD && type1 != elfcpp::PT_LOAD)
     return false;
 
-  // We put the PT_TLS segment last, because that is where the dynamic
-  // linker expects to find it (this is just for efficiency; other
-  // positions would also work correctly).
-  if (type1 == elfcpp::PT_TLS && type2 != elfcpp::PT_TLS)
+  // We put the PT_TLS segment last except for the PT_GNU_RELRO
+  // segment, because that is where the dynamic linker expects to find
+  // it (this is just for efficiency; other positions would also work
+  // correctly).
+  if (type1 == elfcpp::PT_TLS
+      && type2 != elfcpp::PT_TLS
+      && type2 != elfcpp::PT_GNU_RELRO)
+    return false;
+  if (type2 == elfcpp::PT_TLS
+      && type1 != elfcpp::PT_TLS
+      && type1 != elfcpp::PT_GNU_RELRO)
+    return true;
+
+  // We put the PT_GNU_RELRO segment last, because that is where the
+  // dynamic linker expects to find it (as with PT_TLS, this is just
+  // for efficiency).
+  if (type1 == elfcpp::PT_GNU_RELRO && type2 != elfcpp::PT_GNU_RELRO)
     return false;
-  if (type2 == elfcpp::PT_TLS && type1 != elfcpp::PT_TLS)
+  if (type2 == elfcpp::PT_GNU_RELRO && type1 != elfcpp::PT_GNU_RELRO)
     return true;
 
   const elfcpp::Elf_Word flags1 = seg1->flags();
@@ -2481,7 +2524,7 @@ Layout::create_interp(const Target* target)
     {
       Output_segment* oseg = this->make_output_segment(elfcpp::PT_INTERP,
                                                       elfcpp::PF_R);
-      oseg->add_initial_output_section(osec, elfcpp::PF_R);
+      oseg->add_output_section(osec, elfcpp::PF_R);
     }
 }
 
@@ -2496,8 +2539,8 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
       Output_segment* oseg = this->make_output_segment(elfcpp::PT_DYNAMIC,
                                                       (elfcpp::PF_R
                                                        | elfcpp::PF_W));
-      oseg->add_initial_output_section(this->dynamic_section_,
-                                      elfcpp::PF_R | elfcpp::PF_W);
+      oseg->add_output_section(this->dynamic_section_,
+                              elfcpp::PF_R | elfcpp::PF_W);
     }
 
   Output_data_dynamic* const odyn = this->dynamic_data_;
@@ -2636,7 +2679,8 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
 #define MAPPING_INIT(f, t) { f, sizeof(f) - 1, t, sizeof(t) - 1 }
 const Layout::Linkonce_mapping Layout::linkonce_mapping[] =
 {
-  MAPPING_INIT("d.rel.ro", ".data.rel.ro"),    // Must be before "d".
+  MAPPING_INIT("d.rel.ro.local", ".data.rel.ro.local"), // Before "d.rel.ro".
+  MAPPING_INIT("d.rel.ro", ".data.rel.ro"),            // Before "d".
   MAPPING_INIT("t", ".text"),
   MAPPING_INIT("r", ".rodata"),
   MAPPING_INIT("d", ".data"),
@@ -2738,6 +2782,9 @@ Layout::output_section_name(const char* name, size_t* plen)
   // initial '.', we use the name unchanged (i.e., "mysection" and
   // ".text" are unchanged).
 
+  // If the name starts with ".data.rel.ro.local" we use
+  // ".data.rel.ro.local".
+
   // If the name starts with ".data.rel.ro" we use ".data.rel.ro".
 
   // Otherwise, we drop the second '.' and everything that comes after
@@ -2751,6 +2798,13 @@ Layout::output_section_name(const char* name, size_t* plen)
   if (sdot == NULL)
     return name;
 
+  const char* const data_rel_ro_local = ".data.rel.ro.local";
+  if (strncmp(name, data_rel_ro_local, strlen(data_rel_ro_local)) == 0)
+    {
+      *plen = strlen(data_rel_ro_local);
+      return data_rel_ro_local;
+    }
+
   const char* const data_rel_ro = ".data.rel.ro";
   if (strncmp(name, data_rel_ro, strlen(data_rel_ro)) == 0)
     {
@@ -2770,11 +2824,12 @@ Layout::output_section_name(const char* name, size_t* plen)
 // want a linkonce signature to block another linkonce signature.
 
 bool
-Layout::add_comdat(const char* signature, bool group)
+Layout::add_comdat(Relobj* object, unsigned int shndx,
+                   const std::string& signature, bool group)
 {
-  std::string sig(signature);
+  Kept_section kept(object, shndx, group);
   std::pair<Signatures::iterator, bool> ins(
-    this->signatures_.insert(std::make_pair(sig, group)));
+    this->signatures_.insert(std::make_pair(signature, kept)));
 
   if (ins.second)
     {
@@ -2782,7 +2837,7 @@ Layout::add_comdat(const char* signature, bool group)
       return true;
     }
 
-  if (ins.first->second)
+  if (ins.first->second.group_)
     {
       // We've already seen a real section group with this signature.
       return false;
@@ -2792,7 +2847,7 @@ Layout::add_comdat(const char* signature, bool group)
       // This is a real section group, and we've already seen a
       // linkonce section with this signature.  Record that we've seen
       // a section group, and don't include this section group.
-      ins.first->second = true;
+      ins.first->second.group_ = true;
       return false;
     }
   else
@@ -2804,6 +2859,20 @@ Layout::add_comdat(const char* signature, bool group)
     }
 }
 
+// Find the given comdat signature, and return the object and section
+// index of the kept group.
+Relobj*
+Layout::find_kept_object(const std::string& signature,
+                         unsigned int* pshndx) const
+{
+  Signatures::const_iterator p = this->signatures_.find(signature);
+  if (p == this->signatures_.end())
+    return NULL;
+  if (pshndx != NULL)
+    *pshndx = p->second.shndx_;
+  return p->second.object_;
+}
+
 // Store the allocated sections into the section list.
 
 void
@@ -3247,7 +3316,8 @@ Layout::layout_group<32, false>(Symbol_table* symtab,
                                const char* group_section_name,
                                const char* signature,
                                const elfcpp::Shdr<32, false>& shdr,
-                               const elfcpp::Elf_Word* contents);
+                               elfcpp::Elf_Word flags,
+                               std::vector<unsigned int>* shndxes);
 #endif
 
 #ifdef HAVE_TARGET_32_BIG
@@ -3259,7 +3329,8 @@ Layout::layout_group<32, true>(Symbol_table* symtab,
                               const char* group_section_name,
                               const char* signature,
                               const elfcpp::Shdr<32, true>& shdr,
-                              const elfcpp::Elf_Word* contents);
+                              elfcpp::Elf_Word flags,
+                              std::vector<unsigned int>* shndxes);
 #endif
 
 #ifdef HAVE_TARGET_64_LITTLE
@@ -3271,7 +3342,8 @@ Layout::layout_group<64, false>(Symbol_table* symtab,
                                const char* group_section_name,
                                const char* signature,
                                const elfcpp::Shdr<64, false>& shdr,
-                               const elfcpp::Elf_Word* contents);
+                               elfcpp::Elf_Word flags,
+                               std::vector<unsigned int>* shndxes);
 #endif
 
 #ifdef HAVE_TARGET_64_BIG
@@ -3283,7 +3355,8 @@ Layout::layout_group<64, true>(Symbol_table* symtab,
                               const char* group_section_name,
                               const char* signature,
                               const elfcpp::Shdr<64, true>& shdr,
-                              const elfcpp::Elf_Word* contents);
+                              elfcpp::Elf_Word flags,
+                              std::vector<unsigned int>* shndxes);
 #endif
 
 #ifdef HAVE_TARGET_32_LITTLE
This page took 0.026807 seconds and 4 git commands to generate.