* nto-procfs.c (get_regset): Pass correct pointer.
[deliverable/binutils-gdb.git] / gold / layout.cc
index 8c7cd9968bb0f471eb991c669333978da70ba70a..a651d0650d9cc96a066bad2ee80f3fb6bdfa7fd1 100644 (file)
@@ -1,6 +1,6 @@
 // layout.cc -- lay out output file sections for gold
 
-// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -45,6 +45,9 @@
 #include "compressed_output.h"
 #include "reduced_debug_output.h"
 #include "reloc.h"
+#include "descriptors.h"
+#include "plugin.h"
+#include "incremental.h"
 #include "layout.h"
 
 namespace gold
@@ -84,8 +87,8 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task)
 
 // Layout methods.
 
-Layout::Layout(const General_options& options, Script_options* script_options)
-  : options_(options),
+Layout::Layout(int number_of_input_files, Script_options* script_options)
+  : number_of_input_files_(number_of_input_files),
     script_options_(script_options),
     namepool_(),
     sympool_(),
@@ -95,7 +98,6 @@ Layout::Layout(const General_options& options, Script_options* script_options)
     segment_list_(),
     section_list_(),
     unattached_section_list_(),
-    sections_are_attached_(false),
     special_output_list_(),
     section_headers_(NULL),
     tls_segment_(NULL),
@@ -115,11 +117,14 @@ Layout::Layout(const General_options& options, Script_options* script_options)
     debug_info_(NULL),
     group_signatures_(),
     output_file_size_(-1),
+    sections_are_attached_(false),
     input_requires_executable_stack_(false),
     input_with_gnu_stack_note_(false),
     input_without_gnu_stack_note_(false),
     has_static_tls_(false),
-    any_postprocessing_sections_(false)
+    any_postprocessing_sections_(false),
+    resized_signatures_(false),
+    incremental_inputs_(NULL)
 {
   // Make space for more than enough segments for a typical file.
   // This is just for efficiency--it's OK if we wind up needing more.
@@ -128,6 +133,10 @@ Layout::Layout(const General_options& options, Script_options* script_options)
   // We expect two unattached Output_data objects: the file header and
   // the segment headers.
   this->special_output_list_.reserve(2);
+
+  // Initialize structure needed for an incremental build.
+  if (parameters->options().incremental())
+    this->incremental_inputs_ = new Incremental_inputs;
 }
 
 // Hash a key we use to look up an output section mapping.
@@ -138,14 +147,6 @@ Layout::Hash_key::operator()(const Layout::Key& k) const
  return k.first + k.second.first + k.second.second;
 }
 
-// Return whether PREFIX is a prefix of STR.
-
-static inline bool
-is_prefix_of(const char* prefix, const char* str)
-{
-  return strncmp(prefix, str, strlen(prefix)) == 0;
-}
-
 // Returns whether the given section is in the list of
 // debug-sections-used-by-some-version-of-gdb.  Currently,
 // we've checked versions of gdb up to and including 6.7.1.
@@ -205,6 +206,9 @@ bool
 Layout::include_section(Sized_relobj<size, big_endian>*, const char* name,
                        const elfcpp::Shdr<size, big_endian>& shdr)
 {
+  if (shdr.get_sh_flags() & elfcpp::SHF_EXCLUDE)
+    return false;
+
   switch (shdr.get_sh_type())
     {
     case elfcpp::SHT_NULL:
@@ -255,6 +259,14 @@ Layout::include_section(Sized_relobj<size, big_endian>*, const char* name,
               && !is_gdb_debug_section(name))
            return false;
        }
+      if (parameters->options().strip_lto_sections()
+          && !parameters->options().relocatable()
+          && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
+        {
+          // Ignore LTO sections containing intermediate code.
+          if (is_prefix_of(".gnu.lto_", name))
+            return false;
+        }
       return true;
 
     default:
@@ -421,7 +433,9 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
   // output section.
 
   size_t len = strlen(name);
-  if (is_input_section && !parameters->options().relocatable())
+  if (is_input_section
+      && !this->script_options_->saw_sections_clause()
+      && !parameters->options().relocatable())
     name = Layout::output_section_name(name, &len);
 
   Stringpool::Key name_key;
@@ -574,6 +588,10 @@ Layout::layout_group(Symbol_table* symtab,
     os->set_info_symndx(sym);
   else
     {
+      // Reserve some space to minimize reallocations.
+      if (this->group_signatures_.empty())
+       this->group_signatures_.reserve(this->number_of_input_files_ * 16);
+
       // We will wind up using a symbol whose name is the signature.
       // So just put the signature in the symbol name pool to save it.
       signature = symtab->canonicalize_name(signature);
@@ -624,7 +642,7 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
       this->eh_frame_section_ = os;
       this->eh_frame_data_ = new Eh_frame();
 
-      if (this->options_.eh_frame_hdr())
+      if (parameters->options().eh_frame_hdr())
        {
          Output_section* hdr_os =
            this->choose_output_section(NULL,
@@ -744,12 +762,13 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
 {
   Output_section* os;
   if ((flags & elfcpp::SHF_ALLOC) == 0
-      && strcmp(this->options_.compress_debug_sections(), "none") != 0
+      && strcmp(parameters->options().compress_debug_sections(), "none") != 0
       && is_compressible_debug_section(name))
-    os = new Output_compressed_section(&this->options_, name, type, flags);
+    os = new Output_compressed_section(&parameters->options(), name, type,
+                                      flags);
 
   else if ((flags & elfcpp::SHF_ALLOC) == 0
-           && this->options_.strip_debug_non_line()
+           && parameters->options().strip_debug_non_line()
            && strcmp(".debug_abbrev", name) == 0)
     {
       os = this->debug_abbrev_ = new Output_reduced_debug_abbrev_section(
@@ -758,7 +777,7 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
         this->debug_info_->set_abbreviations(this->debug_abbrev_);
     }
   else if ((flags & elfcpp::SHF_ALLOC) == 0
-           && this->options_.strip_debug_non_line()
+           && parameters->options().strip_debug_non_line()
            && strcmp(".debug_info", name) == 0)
     {
       os = this->debug_info_ = new Output_reduced_debug_info_section(
@@ -870,7 +889,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
         {
           // If -Tbss was specified, we need to separate the data
           // and BSS segments.
-          if (this->options_.user_set_Tbss())
+          if (parameters->options().user_set_Tbss())
             {
               if ((os->type() == elfcpp::SHT_NOBITS)
                   == (*p)->has_any_data_sections())
@@ -920,8 +939,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
   if ((flags & elfcpp::SHF_TLS) != 0)
     {
       if (this->tls_segment_ == NULL)
-        this->tls_segment_ = this->make_output_segment(elfcpp::PT_TLS,
-                                                       seg_flags);
+       this->make_output_segment(elfcpp::PT_TLS, seg_flags);
       this->tls_segment_->add_output_section(os, seg_flags);
     }
 
@@ -931,8 +949,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
     {
       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->make_output_segment(elfcpp::PT_GNU_RELRO, seg_flags);
       this->relro_segment_->add_output_section(os, seg_flags);
     }
 }
@@ -1204,6 +1221,12 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
       this->create_version_sections(&versions, symtab, local_dynamic_count,
                                    dynamic_symbols, dynstr);
     }
+  
+  if (this->incremental_inputs_)
+    {
+      this->incremental_inputs_->finalize();
+      this->create_incremental_info_sections();
+    }
 
   // If there is a SECTIONS clause, put all the input sections into
   // the required order.
@@ -1215,7 +1238,8 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
   else
     load_seg = this->find_first_load_seg();
 
-  if (this->options_.oformat_enum() != General_options::OBJECT_FORMAT_ELF)
+  if (parameters->options().oformat_enum()
+      != General_options::OBJECT_FORMAT_ELF)
     load_seg = NULL;
 
   gold_assert(phdr_seg == NULL || load_seg != NULL);
@@ -1236,7 +1260,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
   // Lay out the file header.
   Output_file_header* file_header;
   file_header = new Output_file_header(target, symtab, segment_headers,
-                                      this->options_.entry());
+                                      parameters->options().entry());
   if (load_seg != NULL)
     load_seg->add_initial_output_data(file_header);
 
@@ -1322,7 +1346,8 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
 // *TRAILING_PADDING to the number of trailing zero bytes required.
 
 Output_section*
-Layout::create_note(const char* name, int note_type, size_t descsz,
+Layout::create_note(const char* name, int note_type,
+                   const char* section_name, size_t descsz,
                    bool allocate, size_t* trailing_padding)
 {
   // Authorities all agree that the values in a .note field should
@@ -1389,7 +1414,7 @@ Layout::create_note(const char* name, int note_type, size_t descsz,
 
   memcpy(buffer + 3 * (size / 8), name, namesz);
 
-  const char* note_name = this->namepool_.add(".note", false, NULL);
+  const char *note_name = this->namepool_.add(section_name, false, NULL);
   elfcpp::Elf_Xword flags = 0;
   if (allocate)
     flags = elfcpp::SHF_ALLOC;
@@ -1419,7 +1444,8 @@ Layout::create_gold_note()
 
   size_t trailing_padding;
   Output_section *os = this->create_note("GNU", elfcpp::NT_GNU_GOLD_VERSION,
-                                        desc.size(), false, &trailing_padding);
+                                        ".note.gnu.gold-version", desc.size(),
+                                        false, &trailing_padding);
 
   Output_section_data* posd = new Output_data_const(desc, 4);
   os->add_output_section_data(posd);
@@ -1447,8 +1473,8 @@ void
 Layout::create_executable_stack_info(const Target* target)
 {
   bool is_stack_executable;
-  if (this->options_.is_execstack_set())
-    is_stack_executable = this->options_.is_stack_executable();
+  if (parameters->options().is_execstack_set())
+    is_stack_executable = parameters->options().is_stack_executable();
   else if (!this->input_with_gnu_stack_note_)
     return;
   else
@@ -1507,14 +1533,14 @@ Layout::create_build_id()
       char buffer[uuidsz];
       memset(buffer, 0, uuidsz);
 
-      int descriptor = ::open("/dev/urandom", O_RDONLY);
+      int descriptor = open_descriptor(-1, "/dev/urandom", O_RDONLY);
       if (descriptor < 0)
        gold_error(_("--build-id=uuid failed: could not open /dev/urandom: %s"),
                   strerror(errno));
       else
        {
          ssize_t got = ::read(descriptor, buffer, uuidsz);
-         ::close(descriptor);
+         release_descriptor(descriptor, true);
          if (got < 0)
            gold_error(_("/dev/urandom: read failed: %s"), strerror(errno));
          else if (static_cast<size_t>(got) != uuidsz)
@@ -1551,7 +1577,8 @@ Layout::create_build_id()
   // Create the note.
   size_t trailing_padding;
   Output_section* os = this->create_note("GNU", elfcpp::NT_GNU_BUILD_ID,
-                                        descsz, true, &trailing_padding);
+                                        ".note.gnu.build-id", descsz, true,
+                                        &trailing_padding);
 
   if (!desc.empty())
     {
@@ -1578,6 +1605,37 @@ Layout::create_build_id()
     }
 }
 
+// Create .gnu_incremental_inputs and .gnu_incremental_strtab sections needed
+// for the next run of incremental linking to check what has changed.
+
+void
+Layout::create_incremental_info_sections()
+{
+  gold_assert(this->incremental_inputs_ != NULL);
+
+  // Add the .gnu_incremental_inputs section.
+  const char *incremental_inputs_name =
+    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);
+  Output_section_data* posd =
+      this->incremental_inputs_->create_incremental_inputs_section_data();
+  inputs_os->add_output_section_data(posd);
+  
+  // Add the .gnu_incremental_strtab section.
+  const char *incremental_strtab_name =
+    this->namepool_.add(".gnu_incremental_strtab", false, NULL);
+  Output_section* strtab_os = this->make_output_section(incremental_strtab_name,
+                                                        elfcpp::SHT_STRTAB,
+                                                        0);
+  Output_data_strtab* strtab_data =
+    new Output_data_strtab(this->incremental_inputs_->get_stringpool());
+  strtab_os->add_output_section_data(strtab_data);
+  
+  inputs_os->set_link_section(strtab_data);
+}
+
 // Return whether SEG1 should be before SEG2 in the output file.  This
 // is based entirely on the segment type and flags.  When this is
 // called the segment addresses has normally not yet been set.
@@ -1709,8 +1767,8 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
   // Find the PT_LOAD segments, and set their addresses and offsets
   // and their section's addresses and offsets.
   uint64_t addr;
-  if (this->options_.user_set_Ttext())
-    addr = this->options_.Ttext();
+  if (parameters->options().user_set_Ttext())
+    addr = parameters->options().Ttext();
   else if (parameters->options().shared())
     addr = 0;
   else
@@ -1732,6 +1790,9 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
        }
     }
 
+  const bool check_sections = parameters->options().check_sections();
+  Output_segment* last_load_segment = NULL;
+
   bool was_readonly = false;
   for (Segment_list::iterator p = this->segment_list_.begin();
        p != this->segment_list_.end();
@@ -1750,19 +1811,19 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
              // the physical address.
              addr = (*p)->paddr();
            }
-         else if (this->options_.user_set_Tdata()
+         else if (parameters->options().user_set_Tdata()
                   && ((*p)->flags() & elfcpp::PF_W) != 0
-                  && (!this->options_.user_set_Tbss()
+                  && (!parameters->options().user_set_Tbss()
                       || (*p)->has_any_data_sections()))
            {
-             addr = this->options_.Tdata();
+             addr = parameters->options().Tdata();
              are_addresses_set = true;
            }
-         else if (this->options_.user_set_Tbss()
+         else if (parameters->options().user_set_Tbss()
                   && ((*p)->flags() & elfcpp::PF_W) != 0
                   && !(*p)->has_any_data_sections())
            {
-             addr = this->options_.Tbss();
+             addr = parameters->options().Tbss();
              are_addresses_set = true;
            }
 
@@ -1848,6 +1909,25 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
 
          if (((*p)->flags() & elfcpp::PF_W) == 0)
            was_readonly = true;
+
+         // Implement --check-sections.  We know that the segments
+         // are sorted by LMA.
+         if (check_sections && last_load_segment != NULL)
+           {
+             gold_assert(last_load_segment->paddr() <= (*p)->paddr());
+             if (last_load_segment->paddr() + last_load_segment->memsz()
+                 > (*p)->paddr())
+               {
+                 unsigned long long lb1 = last_load_segment->paddr();
+                 unsigned long long le1 = lb1 + last_load_segment->memsz();
+                 unsigned long long lb2 = (*p)->paddr();
+                 unsigned long long le2 = lb2 + (*p)->memsz();
+                 gold_error(_("load segment overlap [0x%llx -> 0x%llx] and "
+                              "[0x%llx -> 0x%llx]"),
+                            lb1, le1, lb2, le2);
+               }
+           }
+         last_load_segment = *p;
        }
     }
 
@@ -2586,7 +2666,7 @@ Layout::sized_create_version_sections(
 void
 Layout::create_interp(const Target* target)
 {
-  const char* interp = this->options_.dynamic_linker();
+  const char* interp = parameters->options().dynamic_linker();
   if (interp == NULL)
     {
       interp = target->dynamic_linker();
@@ -2638,7 +2718,7 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
 
   if (parameters->options().shared())
     {
-      const char* soname = this->options_.soname();
+      const char* soname = parameters->options().soname();
       if (soname != NULL)
        odyn->add_string(elfcpp::DT_SONAME, soname);
     }
@@ -2655,7 +2735,7 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
   // FIXME: Support DT_INIT_ARRAY and DT_FINI_ARRAY.
 
   // Add a DT_RPATH entry if needed.
-  const General_options::Dir_list& rpath(this->options_.rpath());
+  const General_options::Dir_list& rpath(parameters->options().rpath());
   if (!rpath.empty())
     {
       std::string rpath_val;
@@ -2732,6 +2812,8 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
     }
   if (parameters->options().shared() && this->has_static_tls())
     flags |= elfcpp::DF_STATIC_TLS;
+  if (parameters->options().origin())
+    flags |= elfcpp::DF_ORIGIN;
   odyn->add_constant(elfcpp::DT_FLAGS, flags);
 
   flags = 0;
@@ -2753,6 +2835,8 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
     flags &= ~(elfcpp::DF_1_INITFIRST
               | elfcpp::DF_1_NODELETE
               | elfcpp::DF_1_NOOPEN);
+  if (parameters->options().origin())
+    flags |= elfcpp::DF_1_ORIGIN;
   if (flags)
     odyn->add_constant(elfcpp::DT_FLAGS_1, flags);
 }
@@ -2865,6 +2949,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 '.note', we keep it unchanged (e.g. to
+  // avoid truncating '.note.ABI-tag' to '.note').
+
   // If the name starts with ".data.rel.ro.local" we use
   // ".data.rel.ro.local".
 
@@ -2880,6 +2967,8 @@ Layout::output_section_name(const char* name, size_t* plen)
   const char* sdot = strchr(s, '.');
   if (sdot == NULL)
     return name;
+  if (strncmp(name, ".note.", 6) == 0)
+    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)
@@ -2899,38 +2988,61 @@ Layout::output_section_name(const char* name, size_t* plen)
   return name;
 }
 
-// Record the signature of a comdat section, and return whether to
-// include it in the link.  If GROUP is true, this is a regular
-// section group.  If GROUP is false, this is a group signature
-// derived from the name of a linkonce section.  We want linkonce
-// signatures and group signatures to block each other, but we don't
-// want a linkonce signature to block another linkonce signature.
+// Check if a comdat group or .gnu.linkonce section with the given
+// NAME is selected for the link.  If there is already a section,
+// *KEPT_SECTION is set to point to the signature and the function
+// returns false.  Otherwise, the CANDIDATE signature is recorded for
+// this NAME in the layout object, *KEPT_SECTION is set to the
+// internal copy and the function return false.  In some cases, with
+// CANDIDATE->GROUP_ being false, KEPT_SECTION can point back to
+// CANDIDATE.
 
 bool
-Layout::add_comdat(Relobj* object, unsigned int shndx,
-                   const std::string& signature, bool group)
+Layout::find_or_add_kept_section(const std::string& name,
+                                 Kept_section* candidate,
+                                 Kept_section** kept_section)
 {
-  Kept_section kept(object, shndx, group);
+  // It's normal to see a couple of entries here, for the x86 thunk
+  // sections.  If we see more than a few, we're linking a C++
+  // program, and we resize to get more space to minimize rehashing.
+  if (this->signatures_.size() > 4
+      && !this->resized_signatures_)
+    {
+      reserve_unordered_map(&this->signatures_,
+                           this->number_of_input_files_ * 64);
+      this->resized_signatures_ = true;
+    }
+
   std::pair<Signatures::iterator, bool> ins(
-    this->signatures_.insert(std::make_pair(signature, kept)));
+    this->signatures_.insert(std::make_pair(name, *candidate)));
 
+  if (kept_section)
+    *kept_section = &ins.first->second;
   if (ins.second)
     {
       // This is the first time we've seen this signature.
       return true;
     }
 
-  if (ins.first->second.group_)
+  if (ins.first->second.is_group)
     {
       // We've already seen a real section group with this signature.
+      // If the kept group is from a plugin object, and we're in
+      // the replacement phase, accept the new one as a replacement.
+      if (ins.first->second.object == NULL
+          && parameters->options().plugins()->in_replacement_phase())
+        {
+          ins.first->second = *candidate;
+          return true;
+        }
       return false;
     }
-  else if (group)
+  else if (candidate->is_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.group_ = true;
+      ins.first->second.is_group = true;
       return false;
     }
   else
@@ -2938,6 +3050,7 @@ Layout::add_comdat(Relobj* object, unsigned int shndx,
       // We've already seen a linkonce section and this is a linkonce
       // section.  These don't block each other--this may be the same
       // symbol name with different section types.
+      *kept_section = candidate;
       return true;
     }
 }
@@ -2952,8 +3065,8 @@ Layout::find_kept_object(const std::string& signature,
   if (p == this->signatures_.end())
     return NULL;
   if (pshndx != NULL)
-    *pshndx = p->second.shndx_;
-  return p->second.object_;
+    *pshndx = p->second.shndx;
+  return p->second.object;
 }
 
 // Store the allocated sections into the section list.
@@ -2976,6 +3089,12 @@ Layout::make_output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
   gold_assert(!parameters->options().relocatable());
   Output_segment* oseg = new Output_segment(type, flags);
   this->segment_list_.push_back(oseg);
+
+  if (type == elfcpp::PT_TLS)
+    this->tls_segment_ = oseg;
+  else if (type == elfcpp::PT_GNU_RELRO)
+    this->relro_segment_ = oseg;
+
   return oseg;
 }
 
@@ -3056,7 +3175,7 @@ Layout::write_sections_after_input_sections(Output_file* of)
     {
       off_t off = this->output_file_size_;
       off = this->set_section_offsets(off, POSTPROCESSING_SECTIONS_PASS);
-      
+
       // Now that we've finalized the names, we can finalize the shstrab.
       off =
        this->set_section_offsets(off,
@@ -3130,7 +3249,7 @@ Layout::write_build_id(Output_file* of) const
 void
 Layout::write_binary(Output_file* in) const
 {
-  gold_assert(this->options_.oformat_enum()
+  gold_assert(parameters->options().oformat_enum()
              == General_options::OBJECT_FORMAT_BINARY);
 
   // Get the size of the binary file.
@@ -3272,8 +3391,8 @@ Write_symbols_task::locks(Task_locker* tl)
 void
 Write_symbols_task::run(Workqueue*)
 {
-  this->symtab_->write_globals(this->input_objects_, this->sympool_,
-                              this->dynpool_, this->layout_->symtab_xindex(),
+  this->symtab_->write_globals(this->sympool_, this->dynpool_,
+                              this->layout_->symtab_xindex(),
                               this->layout_->dynsym_xindex(), this->of_);
 }
 
This page took 0.031065 seconds and 4 git commands to generate.