Fix internal error with -z relro when .tbss is last relro section.
[deliverable/binutils-gdb.git] / gold / object.cc
index 34343031f8f11606c01b7a5474a43c1efa5bd3d2..f983b6603ee70d7e6bac3891b4fe429e0b25de6e 100644 (file)
@@ -1,7 +1,6 @@
 // object.cc -- support for an object file for linking in gold
 
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
-// Free Software Foundation, Inc.
+// Copyright (C) 2006-2015 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -42,6 +41,7 @@
 #include "plugin.h"
 #include "compressed_output.h"
 #include "incremental.h"
+#include "merge.h"
 
 namespace gold
 {
@@ -269,6 +269,50 @@ Object::handle_split_stack_section(const char* name)
 
 // Class Relobj
 
+template<int size>
+void
+Relobj::initialize_input_to_output_map(unsigned int shndx,
+         typename elfcpp::Elf_types<size>::Elf_Addr starting_address,
+         Unordered_map<section_offset_type,
+         typename elfcpp::Elf_types<size>::Elf_Addr>* output_addresses) const {
+  Object_merge_map *map = this->object_merge_map_;
+  map->initialize_input_to_output_map<size>(shndx, starting_address,
+                                           output_addresses);
+}
+
+void
+Relobj::add_merge_mapping(Output_section_data *output_data,
+                          unsigned int shndx, section_offset_type offset,
+                          section_size_type length,
+                          section_offset_type output_offset) {
+  if (this->object_merge_map_ == NULL)
+    {
+      this->object_merge_map_ =  new Object_merge_map();
+    }
+
+  this->object_merge_map_->add_mapping(output_data, shndx, offset, length,
+                                      output_offset);
+}
+
+bool
+Relobj::merge_output_offset(unsigned int shndx, section_offset_type offset,
+                            section_offset_type *poutput) const {
+  Object_merge_map* object_merge_map = this->object_merge_map_;
+  if (object_merge_map == NULL)
+    return false;
+  return object_merge_map->get_output_offset(shndx, offset, poutput);
+}
+
+bool
+Relobj::is_merge_section_for(const Output_section_data* output_data,
+                             unsigned int shndx) const {
+  Object_merge_map* object_merge_map = this->object_merge_map_;
+  if (object_merge_map == NULL)
+    return false;
+  return object_merge_map->is_merge_section_for(output_data, shndx);
+
+}
+
 // To copy the symbols data read from the file to a local data structure.
 // This function is called from do_layout only while doing garbage
 // collection.
@@ -335,7 +379,9 @@ Relobj::is_section_name_included(const char* name)
       || (is_prefix_of(".sdata", name)
          && strstr(name, "personality"))
       || (is_prefix_of(".gnu.linkonce.d", name)
-         && strstr(name, "personality")))
+         && strstr(name, "personality"))
+      || (is_prefix_of(".rodata", name)
+         && strstr(name, "nptl_version")))
     {
       return true;
     }
@@ -389,6 +435,23 @@ Sized_relobj<size, big_endian>::do_for_all_local_got_entries(
     }
 }
 
+// Get the address of an output section.
+
+template<int size, bool big_endian>
+uint64_t
+Sized_relobj<size, big_endian>::do_output_section_address(
+    unsigned int shndx)
+{
+  // If the input file is linked as --just-symbols, the output
+  // section address is the input section address.
+  if (this->just_symbols())
+    return this->section_address(shndx);
+
+  const Output_section* os = this->do_output_section(shndx);
+  gold_assert(os != NULL);
+  return os->address();
+}
+
 // Class Sized_relobj_file.
 
 template<int size, bool big_endian>
@@ -412,9 +475,9 @@ Sized_relobj_file<size, big_endian>::Sized_relobj_file(
     kept_comdat_sections_(),
     has_eh_frame_(false),
     discarded_eh_frame_shndx_(-1U),
+    is_deferred_layout_(false),
     deferred_layout_(),
-    deferred_layout_relocs_(),
-    compressed_sections_()
+    deferred_layout_relocs_()
 {
   this->e_type_ = ehdr.get_e_type();
 }
@@ -656,7 +719,8 @@ build_compressed_section_map(
     unsigned int shnum,
     const char* names,
     section_size_type names_size,
-    Sized_relobj_file<size, big_endian>* obj)
+    Object* obj,
+    bool decompress_if_needed)
 {
   Compressed_section_map* uncompressed_map = new Compressed_section_map();
   const unsigned int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
@@ -688,7 +752,7 @@ build_compressed_section_map(
              if (uncompressed_size != -1ULL)
                {
                  unsigned char* uncompressed_data = NULL;
-                 if (need_decompressed_section(name))
+                 if (decompress_if_needed && need_decompressed_section(name))
                    {
                      uncompressed_data = new unsigned char[uncompressed_size];
                      if (decompress_input_section(contents, len,
@@ -722,9 +786,14 @@ Sized_relobj_file<size, big_endian>::do_find_special_sections(
     this->has_eh_frame_ = true;
 
   if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
-    this->compressed_sections_
-      = build_compressed_section_map(pshdrs, this->shnum(), names,
-                                    sd->section_names_size, this);
+    {
+      Compressed_section_map* compressed_sections =
+         build_compressed_section_map<size, big_endian>(
+             pshdrs, this->shnum(), names, sd->section_names_size, this, true);
+      if (compressed_sections != NULL)
+        this->set_compressed_sections(compressed_sections);
+    }
+
   return (this->has_eh_frame_
          || (!parameters->options().relocatable()
              && parameters->options().gdb_index()
@@ -738,6 +807,16 @@ Sized_relobj_file<size, big_endian>::do_find_special_sections(
 template<int size, bool big_endian>
 void
 Sized_relobj_file<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
+{
+  this->base_read_symbols(sd);
+}
+
+// Read the sections and symbols from an object file.  This is common
+// code for all target-specific overrides of do_read_symbols().
+
+template<int size, bool big_endian>
+void
+Sized_relobj_file<size, big_endian>::base_read_symbols(Read_symbols_data* sd)
 {
   this->read_section_data(&this->elf_file_, sd);
 
@@ -1402,6 +1481,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
     {
       parameters->options().plugins()->add_deferred_layout_object(this);
       this->deferred_layout_.reserve(num_sections_to_defer);
+      this->is_deferred_layout_ = true;
     }
 
   // Whether we've seen a .note.GNU-stack section.
@@ -1562,10 +1642,13 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
        {
          if (is_pass_one)
            {
-             out_sections[i] = reinterpret_cast<Output_section*>(1);
+             if (this->is_deferred_layout())
+               out_sections[i] = reinterpret_cast<Output_section*>(2);
+             else
+               out_sections[i] = reinterpret_cast<Output_section*>(1);
              out_section_offsets[i] = invalid_address;
            }
-         else if (should_defer_layout)
+         else if (this->is_deferred_layout())
            this->deferred_layout_.push_back(Deferred_layout(i, name,
                                                             pshdrs,
                                                             reloc_shndx[i],
@@ -1616,7 +1699,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
                                symtab->icf()->get_folded_section(this, i);
                    Relobj* folded_obj =
                                reinterpret_cast<Relobj*>(folded.first);
-                   gold_info(_("%s: ICF folding section '%s' in file '%s'"
+                   gold_info(_("%s: ICF folding section '%s' in file '%s' "
                                "into '%s' in file '%s'"),
                              program_name, this->section_name(i).c_str(),
                              this->name().c_str(),
@@ -1630,11 +1713,12 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
        }
 
       // Defer layout here if input files are claimed by plugins.  When gc
-      // is turned on this function is called twice.  For the second call
-      // should_defer_layout should be false.
-      if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
+      // is turned on this function is called twice; we only want to do this
+      // on the first pass.
+      if (!is_pass_two
+          && this->is_deferred_layout()
+          && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
        {
-         gold_assert(!is_pass_two);
          this->deferred_layout_.push_back(Deferred_layout(i, name,
                                                           pshdrs,
                                                           reloc_shndx[i],
@@ -1687,6 +1771,28 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
   if (!is_pass_two)
     layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags, this);
 
+  // Handle the .eh_frame sections after the other sections.
+  gold_assert(!is_pass_one || eh_frame_sections.empty());
+  for (std::vector<unsigned int>::const_iterator p = eh_frame_sections.begin();
+       p != eh_frame_sections.end();
+       ++p)
+    {
+      unsigned int i = *p;
+      const unsigned char* pshdr;
+      pshdr = section_headers_data + i * This::shdr_size;
+      typename This::Shdr shdr(pshdr);
+
+      this->layout_eh_frame_section(layout,
+                                   symbols_data,
+                                   symbols_size,
+                                   symbol_names_data,
+                                   symbol_names_size,
+                                   i,
+                                   shdr,
+                                   reloc_shndx[i],
+                                   reloc_type[i]);
+    }
+
   // When doing a relocatable link handle the reloc sections at the
   // end.  Garbage collection  and Identical Code Folding is not
   // turned on for relocatable code.
@@ -1714,6 +1820,8 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       Output_section* data_section = out_sections[data_shndx];
       if (data_section == reinterpret_cast<Output_section*>(2))
        {
+         if (is_pass_two)
+           continue;
          // The layout for the data section was deferred, so we need
          // to defer the relocation section, too.
          const char* name = pnames + shdr.get_sh_name();
@@ -1739,28 +1847,6 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       out_section_offsets[i] = invalid_address;
     }
 
-  // Handle the .eh_frame sections at the end.
-  gold_assert(!is_pass_one || eh_frame_sections.empty());
-  for (std::vector<unsigned int>::const_iterator p = eh_frame_sections.begin();
-       p != eh_frame_sections.end();
-       ++p)
-    {
-      unsigned int i = *p;
-      const unsigned char* pshdr;
-      pshdr = section_headers_data + i * This::shdr_size;
-      typename This::Shdr shdr(pshdr);
-
-      this->layout_eh_frame_section(layout,
-                                   symbols_data,
-                                   symbols_size,
-                                   symbol_names_data,
-                                   symbol_names_size,
-                                   i,
-                                   shdr,
-                                   reloc_shndx[i],
-                                   reloc_type[i]);
-    }
-
   // When building a .gdb_index section, scan the .debug_info and
   // .debug_types sections.
   gold_assert(!is_pass_one
@@ -1815,22 +1901,24 @@ Sized_relobj_file<size, big_endian>::do_layout_deferred_sections(Layout* layout)
        ++deferred)
     {
       typename This::Shdr shdr(deferred->shdr_data_);
-      // If the section is not included, it is because the garbage collector
-      // decided it is not needed.  Avoid reverting that decision.
-      if (!this->is_section_included(deferred->shndx_))
-       continue;
 
-      if (parameters->options().relocatable()
-         || deferred->name_ != ".eh_frame"
-         || !this->check_eh_frame_flags(&shdr))
-       this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(),
-                            shdr, deferred->reloc_shndx_,
-                            deferred->reloc_type_);
-      else
+      if (!parameters->options().relocatable()
+         && deferred->name_ == ".eh_frame"
+         && this->check_eh_frame_flags(&shdr))
        {
+         // Checking is_section_included is not reliable for
+         // .eh_frame sections, because they do not have an output
+         // section.  This is not a problem normally because we call
+         // layout_eh_frame_section unconditionally, but when
+         // deferring sections that is not true.  We don't want to
+         // keep all .eh_frame sections because that will cause us to
+         // keep all sections that they refer to, which is the wrong
+         // way around.  Instead, the eh_frame code will discard
+         // .eh_frame sections that refer to discarded sections.
+
          // Reading the symbols again here may be slow.
          Read_symbols_data sd;
-         this->read_symbols(&sd);
+         this->base_read_symbols(&sd);
          this->layout_eh_frame_section(layout,
                                        sd.symbols->data(),
                                        sd.symbols_size,
@@ -1840,7 +1928,17 @@ Sized_relobj_file<size, big_endian>::do_layout_deferred_sections(Layout* layout)
                                        shdr,
                                        deferred->reloc_shndx_,
                                        deferred->reloc_type_);
+         continue;
        }
+
+      // If the section is not included, it is because the garbage collector
+      // decided it is not needed.  Avoid reverting that decision.
+      if (!this->is_section_included(deferred->shndx_))
+       continue;
+
+      this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(),
+                          shdr, deferred->reloc_shndx_,
+                          deferred->reloc_type_);
     }
 
   this->deferred_layout_.clear();
@@ -2319,7 +2417,9 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
              lv_out->set_merged_symbol_value(msv);
            }
        }
-      else if (lv_in->is_tls_symbol())
+      else if (lv_in->is_tls_symbol()
+               || (lv_in->is_section_symbol()
+                   && (os->flags() & elfcpp::SHF_TLS)))
        lv_out->set_output_value(os->tls_offset()
                                 + secoffset
                                 + lv_in->input_value());
@@ -2539,7 +2639,7 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
     dyn_oview = of->get_output_view(this->local_dynsym_offset_,
                                    dyn_output_size);
 
-  const Output_sections out_sections(this->output_sections());
+  const Output_sections& out_sections(this->output_sections());
 
   gold_assert(this->local_values_.size() == loccount);
 
@@ -2675,6 +2775,7 @@ Sized_relobj_file<size, big_endian>::get_symbol_location_info(
          && (static_cast<off_t>(sym.get_st_value() + sym.get_st_size())
              > offset))
        {
+         info->enclosing_symbol_type = sym.get_st_type();
          if (sym.get_st_name() > names_size)
            info->enclosing_symbol_name = "(invalid)";
          else
@@ -2753,9 +2854,8 @@ Sized_relobj_file<size, big_endian>::do_get_global_symbol_counts(
 // to the size.  Set *IS_NEW to true if the contents need to be freed
 // by the caller.
 
-template<int size, bool big_endian>
 const unsigned char*
-Sized_relobj_file<size, big_endian>::do_decompressed_section_contents(
+Object::decompressed_section_contents(
     unsigned int shndx,
     section_size_type* plen,
     bool* is_new)
@@ -2809,9 +2909,8 @@ Sized_relobj_file<size, big_endian>::do_decompressed_section_contents(
 // Discard any buffers of uncompressed sections.  This is done
 // at the end of the Add_symbols task.
 
-template<int size, bool big_endian>
 void
-Sized_relobj_file<size, big_endian>::do_discard_decompressed_sections()
+Object::discard_decompressed_sections()
 {
   if (this->compressed_sections_ == NULL)
     return;
@@ -2984,12 +3083,10 @@ Relocate_info<size, big_endian>::location(size_t, off_t offset) const
          ret += ":";
          ret += info.source_file;
        }
-      size_t len = info.enclosing_symbol_name.length() + 100;
-      char* buf = new char[len];
-      snprintf(buf, len, _(":function %s"),
-              info.enclosing_symbol_name.c_str());
-      ret += buf;
-      delete[] buf;
+      ret += ":";
+      if (info.enclosing_symbol_type == elfcpp::STT_FUNC)
+       ret += _("function ");
+      ret += info.enclosing_symbol_name;
       return ret;
     }
 
@@ -3160,6 +3257,24 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
 
 // Instantiate the templates we need.
 
+#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
+template
+void
+Relobj::initialize_input_to_output_map<64>(unsigned int shndx,
+      elfcpp::Elf_types<64>::Elf_Addr starting_address,
+      Unordered_map<section_offset_type,
+      elfcpp::Elf_types<64>::Elf_Addr>* output_addresses) const;
+#endif
+
+#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
+template
+void
+Relobj::initialize_input_to_output_map<32>(unsigned int shndx,
+      elfcpp::Elf_types<32>::Elf_Addr starting_address,
+      Unordered_map<section_offset_type,
+      elfcpp::Elf_types<32>::Elf_Addr>* output_addresses) const;
+#endif
+
 #ifdef HAVE_TARGET_32_LITTLE
 template
 void
@@ -3205,21 +3320,33 @@ Object::find_shdr<64,true>(const unsigned char*, const char*, const char*,
 #endif
 
 #ifdef HAVE_TARGET_32_LITTLE
+template
+class Sized_relobj<32, false>;
+
 template
 class Sized_relobj_file<32, false>;
 #endif
 
 #ifdef HAVE_TARGET_32_BIG
+template
+class Sized_relobj<32, true>;
+
 template
 class Sized_relobj_file<32, true>;
 #endif
 
 #ifdef HAVE_TARGET_64_LITTLE
+template
+class Sized_relobj<64, false>;
+
 template
 class Sized_relobj_file<64, false>;
 #endif
 
 #ifdef HAVE_TARGET_64_BIG
+template
+class Sized_relobj<64, true>;
+
 template
 class Sized_relobj_file<64, true>;
 #endif
This page took 0.029583 seconds and 4 git commands to generate.