ld: change --enable-new-dtags to only generate new dtags
[deliverable/binutils-gdb.git] / gold / layout.cc
index 1e31ccef9128642262fec474606ccd96df65f44c..250782a92bead199a193ca48ed9c6d4b7e41c70c 100644 (file)
@@ -408,12 +408,14 @@ Layout::Layout(int number_of_input_files, Script_options* script_options)
     resized_signatures_(false),
     have_stabstr_section_(false),
     section_ordering_specified_(false),
+    unique_segment_for_sections_specified_(false),
     incremental_inputs_(NULL),
     record_output_section_data_from_script_(false),
     script_output_section_data_list_(),
     segment_states_(NULL),
     relaxation_debug_check_(NULL),
     section_order_map_(),
+    section_segment_map_(),
     input_section_position_(),
     input_section_glob_(),
     incremental_base_(NULL),
@@ -580,7 +582,8 @@ bool
 Layout::include_section(Sized_relobj_file<size, big_endian>*, const char* name,
                        const elfcpp::Shdr<size, big_endian>& shdr)
 {
-  if (shdr.get_sh_flags() & elfcpp::SHF_EXCLUDE)
+  if (!parameters->options().relocatable()
+      && (shdr.get_sh_flags() & elfcpp::SHF_EXCLUDE))
     return false;
 
   switch (shdr.get_sh_type())
@@ -606,8 +609,7 @@ Layout::include_section(Sized_relobj_file<size, big_endian>*, const char* name,
     case elfcpp::SHT_GROUP:
       // If we are emitting relocations these should be handled
       // elsewhere.
-      gold_assert(!parameters->options().relocatable()
-                 && !parameters->options().emit_relocs());
+      gold_assert(!parameters->options().relocatable());
       return false;
 
     case elfcpp::SHT_PROGBITS:
@@ -825,6 +827,27 @@ Layout::keep_input_section(const Relobj* relobj, const char* name)
   return name != NULL && keep;
 }
 
+// Clear the input section flags that should not be copied to the
+// output section.
+
+elfcpp::Elf_Xword
+Layout::get_output_section_flags(elfcpp::Elf_Xword input_section_flags)
+{
+  // Some flags in the input section should not be automatically
+  // copied to the output section.
+  input_section_flags &= ~ (elfcpp::SHF_INFO_LINK
+                           | elfcpp::SHF_GROUP
+                           | elfcpp::SHF_MERGE
+                           | elfcpp::SHF_STRINGS);
+
+  // We only clear the SHF_LINK_ORDER flag in for
+  // a non-relocatable link.
+  if (!parameters->options().relocatable())
+    input_section_flags &= ~elfcpp::SHF_LINK_ORDER;
+
+  return input_section_flags;
+}
+
 // 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.  IS_INPUT_SECTION is true if we are
@@ -843,17 +866,7 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
   // 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_GROUP
-             | elfcpp::SHF_MERGE
-             | elfcpp::SHF_STRINGS);
-
-  // We only clear the SHF_LINK_ORDER flag in for
-  // a non-relocatable link.
-  if (!parameters->options().relocatable())
-    flags &= ~elfcpp::SHF_LINK_ORDER;
+  flags = this->get_output_section_flags(flags);
 
   if (this->script_options_->saw_sections_clause())
     {
@@ -1020,6 +1033,33 @@ Layout::init_fixed_output_section(const char* name,
   return os;
 }
 
+// Return the index by which an input section should be ordered.  This
+// is used to sort some .text sections, for compatibility with GNU ld.
+
+int
+Layout::special_ordering_of_input_section(const char* name)
+{
+  // The GNU linker has some special handling for some sections that
+  // wind up in the .text section.  Sections that start with these
+  // prefixes must appear first, and must appear in the order listed
+  // here.
+  static const char* const text_section_sort[] = 
+  {
+    ".text.unlikely",
+    ".text.exit",
+    ".text.startup",
+    ".text.hot"
+  };
+
+  for (size_t i = 0;
+       i < sizeof(text_section_sort) / sizeof(text_section_sort[0]);
+       i++)
+    if (is_prefix_of(text_section_sort[i], name))
+      return i;
+
+  return -1;
+}
+
 // Return the output section to use for input section SHNDX, with name
 // NAME, with header HEADER, from object OBJECT.  RELOC_SHNDX is the
 // index of a relocation section which applies to this section, or 0
@@ -1055,9 +1095,37 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
     }
   else
     {
-      os = this->choose_output_section(object, name, sh_type,
-                                      shdr.get_sh_flags(), true,
-                                      ORDER_INVALID, false);
+      // Plugins can choose to place one or more subsets of sections in
+      // unique segments and this is done by mapping these section subsets
+      // to unique output sections.  Check if this section needs to be
+      // remapped to a unique output section.
+      Section_segment_map::iterator it
+         = this->section_segment_map_.find(Const_section_id(object, shndx));
+      if (it == this->section_segment_map_.end())
+       {
+          os = this->choose_output_section(object, name, sh_type,
+                                          shdr.get_sh_flags(), true,
+                                          ORDER_INVALID, false);
+       }
+      else
+       {
+         // We know the name of the output section, directly call
+         // get_output_section here by-passing choose_output_section.
+         elfcpp::Elf_Xword flags
+           = this->get_output_section_flags(shdr.get_sh_flags());
+
+         const char* os_name = it->second->name;
+         Stringpool::Key name_key;
+         os_name = this->namepool_.add(os_name, true, &name_key);
+         os = this->get_output_section(os_name, name_key, sh_type, flags,
+                                       ORDER_INVALID, false);
+         if (!os->is_unique_segment())
+           {
+             os->set_is_unique_segment();
+             os->set_extra_segment_flags(it->second->flags);
+             os->set_segment_alignment(it->second->align);
+           }
+       }
       if (os == NULL)
        return NULL;
     }
@@ -1079,6 +1147,14 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
                  || strcmp(name, ".dtors") == 0))))
     os->set_must_sort_attached_input_sections();
 
+  // By default the GNU linker sorts some special text sections ahead
+  // of others.  We are compatible.
+  if (!this->script_options_->saw_sections_clause()
+      && !this->is_section_ordering_specified()
+      && !parameters->options().relocatable()
+      && Layout::special_ordering_of_input_section(name) >= 0)
+    os->set_must_sort_attached_input_sections();
+
   // If this is a .ctors or .ctors.* section being mapped to a
   // .init_array section, or a .dtors or .dtors.* section being mapped
   // to a .fini_array section, we will need to reverse the words if
@@ -1117,6 +1193,15 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
   return os;
 }
 
+// Maps section SECN to SEGMENT s.
+void
+Layout::insert_section_segment_map(Const_section_id secn,
+                                  Unique_segment_info *s)
+{
+  gold_assert(this->unique_segment_for_sections_specified_); 
+  this->section_segment_map_[secn] = s;
+}
+
 // Handle a relocation section when doing a relocatable link.
 
 template<int size, bool big_endian>
@@ -1557,6 +1642,16 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
                  || strcmp(name, ".dtors") == 0))))
     os->set_may_sort_attached_input_sections();
 
+  // The GNU linker by default sorts .text.{unlikely,exit,startup,hot}
+  // sections before other .text sections.  We are compatible.  We
+  // need to know that this might happen before we attach any input
+  // sections.
+  if (!this->script_options_->saw_sections_clause()
+      && !this->is_section_ordering_specified()
+      && !parameters->options().relocatable()
+      && strcmp(name, ".text") == 0)
+    os->set_may_sort_attached_input_sections();
+
   // Check for .stab*str sections, as .stab* sections need to link to
   // them.
   if (type == elfcpp::SHT_STRTAB
@@ -1719,6 +1814,10 @@ Layout::attach_allocated_section_to_segment(const Target* target,
 
   elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
 
+  // If this output section's segment has extra flags that need to be set,
+  // coming from a linker plugin, do that.
+  seg_flags |= os->extra_segment_flags();
+
   // Check for --section-start.
   uint64_t addr;
   bool is_address_set = parameters->options().section_start(os->name(), &addr);
@@ -1731,45 +1830,51 @@ Layout::attach_allocated_section_to_segment(const Target* target,
   // have to use a linker script.
 
   Segment_list::const_iterator p;
-  for (p = this->segment_list_.begin();
-       p != this->segment_list_.end();
-       ++p)
+  if (!os->is_unique_segment())
     {
-      if ((*p)->type() != elfcpp::PT_LOAD)
-       continue;
-      if (!parameters->options().omagic()
-         && ((*p)->flags() & elfcpp::PF_W) != (seg_flags & elfcpp::PF_W))
-       continue;
-      if ((target->isolate_execinstr() || parameters->options().rosegment())
-         && ((*p)->flags() & elfcpp::PF_X) != (seg_flags & elfcpp::PF_X))
-       continue;
-      // If -Tbss was specified, we need to separate the data and BSS
-      // segments.
-      if (parameters->options().user_set_Tbss())
-       {
-         if ((os->type() == elfcpp::SHT_NOBITS)
-             == (*p)->has_any_data_sections())
-           continue;
-       }
-      if (os->is_large_data_section() && !(*p)->is_large_data_segment())
-       continue;
-
-      if (is_address_set)
+      for (p = this->segment_list_.begin();
+          p != this->segment_list_.end();
+          ++p)
        {
-         if ((*p)->are_addresses_set())
-           continue;
-
-         (*p)->add_initial_output_data(os);
-         (*p)->update_flags_for_output_section(seg_flags);
-         (*p)->set_addresses(addr, addr);
-         break;
-       }
-
-      (*p)->add_output_section_to_load(this, os, seg_flags);
-      break;
-    }
-
-  if (p == this->segment_list_.end())
+         if ((*p)->type() != elfcpp::PT_LOAD)                        
+           continue;                        
+         if ((*p)->is_unique_segment())                        
+           continue;                        
+         if (!parameters->options().omagic()                        
+             && ((*p)->flags() & elfcpp::PF_W) != (seg_flags & elfcpp::PF_W))                        
+           continue;                        
+         if ((target->isolate_execinstr() || parameters->options().rosegment())                        
+             && ((*p)->flags() & elfcpp::PF_X) != (seg_flags & elfcpp::PF_X))                        
+           continue;                        
+         // If -Tbss was specified, we need to separate the data and BSS                        
+         // segments.                        
+         if (parameters->options().user_set_Tbss())                        
+           {                        
+             if ((os->type() == elfcpp::SHT_NOBITS)                        
+                 == (*p)->has_any_data_sections())                        
+               continue;                        
+           }                        
+         if (os->is_large_data_section() && !(*p)->is_large_data_segment())                        
+           continue;                        
+                           
+         if (is_address_set)                        
+           {                        
+             if ((*p)->are_addresses_set())                        
+               continue;                        
+                           
+             (*p)->add_initial_output_data(os);                        
+             (*p)->update_flags_for_output_section(seg_flags);                        
+             (*p)->set_addresses(addr, addr);                        
+             break;                        
+           }                        
+                           
+         (*p)->add_output_section_to_load(this, os, seg_flags);                        
+         break;                        
+       }                        
+    }
+
+  if (p == this->segment_list_.end()
+      || os->is_unique_segment())
     {
       Output_segment* oseg = this->make_output_segment(elfcpp::PT_LOAD,
                                                       seg_flags);
@@ -1778,6 +1883,14 @@ Layout::attach_allocated_section_to_segment(const Target* target,
       oseg->add_output_section_to_load(this, os, seg_flags);
       if (is_address_set)
        oseg->set_addresses(addr, addr);
+      // Check if segment should be marked unique.  For segments marked
+      // unique by linker plugins, set the new alignment if specified.
+      if (os->is_unique_segment())
+       {
+         oseg->set_is_unique_segment();
+         if (os->segment_alignment() != 0)
+           oseg->set_minimum_p_align(os->segment_alignment());
+       }
     }
 
   // If we see a loadable SHT_NOTE section, we create a PT_NOTE
@@ -2251,7 +2364,7 @@ Layout::relaxation_loop_body(
   // compatible with putting the segment headers and file headers into
   // that segment.
   if (parameters->options().user_set_Ttext()
-      && parameters->options().Ttext() % target->common_pagesize() != 0)
+      && parameters->options().Ttext() % target->abi_pagesize() != 0)
     {
       load_seg = NULL;
       phdr_seg = NULL;
@@ -3122,9 +3235,11 @@ Layout::segment_precedes(const Output_segment* seg1,
 
   // We shouldn't get here--we shouldn't create segments which we
   // can't distinguish.  Unless of course we are using a weird linker
-  // script or overlapping --section-start options.
+  // script or overlapping --section-start options.  We could also get
+  // here if plugins want unique segments for subsets of sections.
   gold_assert(this->script_options_->saw_phdrs_clause()
-             || parameters->options().any_section_start());
+             || parameters->options().any_section_start()
+             || this->is_unique_segment_for_sections_specified());
   return false;
 }
 
@@ -3261,7 +3376,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
 
          if (!parameters->options().nmagic()
              && !parameters->options().omagic())
-           (*p)->set_minimum_p_align(common_pagesize);
+           (*p)->set_minimum_p_align(abi_pagesize);
 
          if (!are_addresses_set)
            {
@@ -3351,6 +3466,8 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
                  *pshndx = shndx_hold;
                  addr = align_address(aligned_addr, common_pagesize);
                  addr = align_address(addr, (*p)->maximum_alignment());
+                 if ((addr & (abi_pagesize - 1)) != 0)
+                   addr = addr + abi_pagesize;
                  off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
                  off = align_file_offset(off, addr, abi_pagesize);
 
@@ -4530,8 +4647,9 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
            }
        }
 
-      odyn->add_string(elfcpp::DT_RPATH, rpath_val);
-      if (parameters->options().enable_new_dtags())
+      if (!parameters->options().enable_new_dtags())
+       odyn->add_string(elfcpp::DT_RPATH, rpath_val);
+      else
        odyn->add_string(elfcpp::DT_RUNPATH, rpath_val);
     }
 
@@ -4932,6 +5050,19 @@ Layout::get_allocated_sections(Section_list* section_list) const
       section_list->push_back(*p);
 }
 
+// Store the executable sections into the section list.
+
+void
+Layout::get_executable_sections(Section_list* section_list) const
+{
+  for (Section_list::const_iterator p = this->section_list_.begin();
+       p != this->section_list_.end();
+       ++p)
+    if (((*p)->flags() & (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR))
+       == (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR))
+      section_list->push_back(*p);
+}
+
 // Create an output segment.
 
 Output_segment*
This page took 0.026837 seconds and 4 git commands to generate.