[gdb] Fixup incomplete patch 0dbfed25e9
[deliverable/binutils-gdb.git] / gold / object.cc
index c1947bc63eb10351198c9ef1b803b221c3fa0ddd..2b58f04ce6646d10158c7e2fe10417b144dc6ce3 100644 (file)
@@ -1,6 +1,6 @@
 // object.cc -- support for an object file for linking in gold
 
-// Copyright (C) 2006-2015 Free Software Foundation, Inc.
+// Copyright (C) 2006-2018 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -476,7 +476,6 @@ Sized_relobj_file<size, big_endian>::Sized_relobj_file(
     local_plt_offsets_(),
     kept_comdat_sections_(),
     has_eh_frame_(false),
-    discarded_eh_frame_shndx_(-1U),
     is_deferred_layout_(false),
     deferred_layout_(),
     deferred_layout_relocs_(),
@@ -575,7 +574,7 @@ Sized_relobj_file<size, big_endian>::check_eh_frame_flags(
 {
   elfcpp::Elf_Word sh_type = shdr->get_sh_type();
   return ((sh_type == elfcpp::SHT_PROGBITS
-          || sh_type == elfcpp::SHT_X86_64_UNWIND)
+          || sh_type == parameters->target().unwind_section_type())
          && (shdr->get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
 }
 
@@ -816,9 +815,9 @@ Sized_relobj_file<size, big_endian>::do_find_special_sections(
   return (this->has_eh_frame_
          || (!parameters->options().relocatable()
              && parameters->options().gdb_index()
-             && (memmem(names, sd->section_names_size, "debug_info", 12) == 0
-                 || memmem(names, sd->section_names_size, "debug_types",
-                           13) == 0)));
+             && (memmem(names, sd->section_names_size, "debug_info", 11) != NULL
+                 || memmem(names, sd->section_names_size,
+                           "debug_types", 12) != NULL)));
 }
 
 // Read the sections and symbols from an object file.
@@ -1113,42 +1112,17 @@ Sized_relobj_file<size, big_endian>::include_section_group(
        {
          (*omit)[shndx] = true;
 
-         if (is_comdat)
-           {
-             Relobj* kept_object = kept_section->object();
-             if (kept_section->is_comdat())
-               {
-                 // Find the corresponding kept section, and store
-                 // that info in the discarded section table.
-                 unsigned int kept_shndx;
-                 uint64_t kept_size;
-                 if (kept_section->find_comdat_section(mname, &kept_shndx,
-                                                       &kept_size))
-                   {
-                     // We don't keep a mapping for this section if
-                     // it has a different size.  The mapping is only
-                     // used for relocation processing, and we don't
-                     // want to treat the sections as similar if the
-                     // sizes are different.  Checking the section
-                     // size is the approach used by the GNU linker.
-                     if (kept_size == member_shdr.get_sh_size())
-                       this->set_kept_comdat_section(shndx, kept_object,
-                                                     kept_shndx);
-                   }
-               }
-             else
-               {
-                 // The existing section is a linkonce section.  Add
-                 // a mapping if there is exactly one section in the
-                 // group (which is true when COUNT == 2) and if it
-                 // is the same size.
-                 if (count == 2
-                     && (kept_section->linkonce_size()
-                         == member_shdr.get_sh_size()))
-                   this->set_kept_comdat_section(shndx, kept_object,
-                                                 kept_section->shndx());
-               }
-           }
+         // Store a mapping from this section to the Kept_section
+         // information for the group.  This mapping is used for
+         // relocation processing and diagnostics.
+         // If the kept section is a linkonce section, we don't
+         // bother with it unless the comdat group contains just
+         // a single section, making it easy to match up.
+         if (is_comdat
+             && (kept_section->is_comdat() || count == 2))
+           this->set_kept_comdat_section(shndx, true, symndx,
+                                         member_shdr.get_sh_size(),
+                                         kept_section);
        }
     }
 
@@ -1213,10 +1187,8 @@ Sized_relobj_file<size, big_endian>::include_linkonce_section(
       // that the kept section is another linkonce section.  If it is
       // the same size, record it as the section which corresponds to
       // this one.
-      if (kept2->object() != NULL
-         && !kept2->is_comdat()
-         && kept2->linkonce_size() == sh_size)
-       this->set_kept_comdat_section(index, kept2->object(), kept2->shndx());
+      if (kept2->object() != NULL && !kept2->is_comdat())
+       this->set_kept_comdat_section(index, false, 0, sh_size, kept2);
     }
   else if (!include1)
     {
@@ -1227,13 +1199,8 @@ Sized_relobj_file<size, big_endian>::include_linkonce_section(
       // this linkonce section.  We'll handle the simple case where
       // the group has only one member section.  Otherwise, it's not
       // worth the effort.
-      unsigned int kept_shndx;
-      uint64_t kept_size;
-      if (kept1->object() != NULL
-         && kept1->is_comdat()
-         && kept1->find_single_comdat_section(&kept_shndx, &kept_size)
-         && kept_size == sh_size)
-       this->set_kept_comdat_section(index, kept1->object(), kept_shndx);
+      if (kept1->object() != NULL && kept1->is_comdat())
+       this->set_kept_comdat_section(index, false, 0, sh_size, kept1);
     }
   else
     {
@@ -1253,12 +1220,13 @@ Sized_relobj_file<size, big_endian>::layout_section(
     unsigned int shndx,
     const char* name,
     const typename This::Shdr& shdr,
+    unsigned int sh_type,
     unsigned int reloc_shndx,
     unsigned int reloc_type)
 {
   off_t offset;
-  Output_section* os = layout->layout(this, shndx, name, shdr,
-                                         reloc_shndx, reloc_type, &offset);
+  Output_section* os = layout->layout(this, shndx, name, shdr, sh_type,
+                                     reloc_shndx, reloc_type, &offset);
 
   this->output_sections()[shndx] = os;
   if (offset == -1)
@@ -1303,13 +1271,7 @@ Sized_relobj_file<size, big_endian>::layout_eh_frame_section(
                                               &offset);
   this->output_sections()[shndx] = os;
   if (os == NULL || offset == -1)
-    {
-      // An object can contain at most one section holding exception
-      // frame information.
-      gold_assert(this->discarded_eh_frame_shndx_ == -1U);
-      this->discarded_eh_frame_shndx_ = shndx;
-      this->section_offsets()[shndx] = invalid_address;
-    }
+    this->section_offsets()[shndx] = invalid_address;
   else
     this->section_offsets()[shndx] = convert_types<Address, off_t>(offset);
 
@@ -1344,6 +1306,8 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
                                               Layout* layout,
                                               Read_symbols_data* sd)
 {
+  const unsigned int unwind_section_type =
+      parameters->target().unwind_section_type();
   const unsigned int shnum = this->shnum();
 
   /* Should this function be called twice?  */
@@ -1529,15 +1493,17 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
   for (unsigned int i = 1; i < shnum; ++i, pshdrs += This::shdr_size)
     {
       typename This::Shdr shdr(pshdrs);
+      const unsigned int sh_name = shdr.get_sh_name();
+      unsigned int sh_type = shdr.get_sh_type();
 
-      if (shdr.get_sh_name() >= section_names_size)
+      if (sh_name >= section_names_size)
        {
          this->error(_("bad section name offset for section %u: %lu"),
-                     i, static_cast<unsigned long>(shdr.get_sh_name()));
+                     i, static_cast<unsigned long>(sh_name));
          return;
        }
 
-      const char* name = pnames + shdr.get_sh_name();
+      const char* name = pnames + sh_name;
 
       if (!is_pass_two)
        {
@@ -1575,7 +1541,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
          bool discard = omit[i];
          if (!discard)
            {
-             if (shdr.get_sh_type() == elfcpp::SHT_GROUP)
+             if (sh_type == elfcpp::SHT_GROUP)
                {
                  if (!this->include_section_group(symtab, layout, i, name,
                                                   shdrs, pnames,
@@ -1595,7 +1561,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
          Incremental_inputs* incremental_inputs = layout->incremental_inputs();
          if (incremental_inputs != NULL
              && !discard
-             && can_incremental_update(shdr.get_sh_type()))
+             && can_incremental_update(sh_type))
            {
              off_t sh_size = shdr.get_sh_size();
              section_size_type uncompressed_size;
@@ -1617,8 +1583,8 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
        {
          if (this->is_section_name_included(name)
              || layout->keep_input_section (this, name)
-             || shdr.get_sh_type() == elfcpp::SHT_INIT_ARRAY
-             || shdr.get_sh_type() == elfcpp::SHT_FINI_ARRAY)
+             || sh_type == elfcpp::SHT_INIT_ARRAY
+             || sh_type == elfcpp::SHT_FINI_ARRAY)
            {
              symtab->gc()->worklist().push_back(Section_id(this, i));
            }
@@ -1639,14 +1605,14 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       // reloc sections and process them later. Garbage collection is
       // not triggered when relocatable code is desired.
       if (emit_relocs
-         && (shdr.get_sh_type() == elfcpp::SHT_REL
-             || shdr.get_sh_type() == elfcpp::SHT_RELA))
+         && (sh_type == elfcpp::SHT_REL
+             || sh_type == elfcpp::SHT_RELA))
        {
          reloc_sections.push_back(i);
          continue;
        }
 
-      if (relocatable && shdr.get_sh_type() == elfcpp::SHT_GROUP)
+      if (relocatable && sh_type == elfcpp::SHT_GROUP)
        continue;
 
       // The .eh_frame section is special.  It holds exception frame
@@ -1655,26 +1621,30 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       // sections so that the exception frame reader can reliably
       // determine which sections are being discarded, and discard the
       // corresponding information.
-      if (!relocatable
-         && strcmp(name, ".eh_frame") == 0
-         && this->check_eh_frame_flags(&shdr))
+      if (this->check_eh_frame_flags(&shdr)
+         && strcmp(name, ".eh_frame") == 0)
        {
-         if (is_pass_one)
+         // If the target has a special unwind section type, let's
+         // canonicalize it here.
+         sh_type = unwind_section_type;
+         if (!relocatable)
            {
-             if (this->is_deferred_layout())
-               out_sections[i] = reinterpret_cast<Output_section*>(2);
+             if (is_pass_one)
+               {
+                 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 (this->is_deferred_layout())
+               this->deferred_layout_.push_back(
+                   Deferred_layout(i, name, sh_type, pshdrs,
+                                   reloc_shndx[i], reloc_type[i]));
              else
-               out_sections[i] = reinterpret_cast<Output_section*>(1);
-             out_section_offsets[i] = invalid_address;
+               eh_frame_sections.push_back(i);
+             continue;
            }
-         else if (this->is_deferred_layout())
-           this->deferred_layout_.push_back(Deferred_layout(i, name,
-                                                            pshdrs,
-                                                            reloc_shndx[i],
-                                                            reloc_type[i]));
-         else
-           eh_frame_sections.push_back(i);
-         continue;
        }
 
       if (is_pass_two && parameters->options().gc_sections())
@@ -1738,7 +1708,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
           && this->is_deferred_layout()
           && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
        {
-         this->deferred_layout_.push_back(Deferred_layout(i, name,
+         this->deferred_layout_.push_back(Deferred_layout(i, name, sh_type,
                                                           pshdrs,
                                                           reloc_shndx[i],
                                                           reloc_type[i]));
@@ -1767,7 +1737,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
        {
          // When garbage collection is switched on the actual layout
          // only happens in the second call.
-         this->layout_section(layout, i, name, shdr, reloc_shndx[i],
+         this->layout_section(layout, i, name, shdr, sh_type, reloc_shndx[i],
                               reloc_type[i]);
 
          // When generating a .gdb_index section, we do additional
@@ -1845,7 +1815,8 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
          // to defer the relocation section, too.
          const char* name = pnames + shdr.get_sh_name();
          this->deferred_layout_relocs_.push_back(
-             Deferred_layout(i, name, pshdr, 0, elfcpp::SHT_NULL));
+             Deferred_layout(i, name, shdr.get_sh_type(), pshdr, 0,
+                             elfcpp::SHT_NULL));
          out_sections[i] = reinterpret_cast<Output_section*>(2);
          out_section_offsets[i] = invalid_address;
          continue;
@@ -1956,7 +1927,7 @@ Sized_relobj_file<size, big_endian>::do_layout_deferred_sections(Layout* layout)
        continue;
 
       this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(),
-                          shdr, deferred->reloc_shndx_,
+                          shdr, shdr.get_sh_type(), deferred->reloc_shndx_,
                           deferred->reloc_type_);
     }
 
@@ -2225,9 +2196,14 @@ Sized_relobj_file<size, big_endian>::do_count_local_symbols(Stringpool* pool,
 
       // Decide whether this symbol should go into the output file.
 
-      if ((shndx < shnum && out_sections[shndx] == NULL)
-         || shndx == this->discarded_eh_frame_shndx_)
+      if (is_ordinary
+         && shndx < shnum
+         && (out_sections[shndx] == NULL
+             || (out_sections[shndx]->order() == ORDER_EHFRAME
+                 && out_section_offsets[shndx] == invalid_address)))
        {
+         // This is either a discarded section or an optimized .eh_frame
+         // section.
          lv.set_no_output_symtab_entry();
          gold_assert(!lv.needs_output_dynsym_entry());
          continue;
@@ -2392,10 +2368,10 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
 
          // This is a SHF_MERGE section or one which otherwise
          // requires special handling.
-         if (shndx == this->discarded_eh_frame_shndx_)
+         if (os->order() == ORDER_EHFRAME)
            {
-             // This local symbol belongs to a discarded .eh_frame
-             // section.  Just treat it like the case in which
+             // This local symbol belongs to a discarded or optimized
+             // .eh_frame section.  Just treat it like the case in which
              // os == NULL above.
              gold_assert(this->has_eh_frame_);
              return This::CFLV_DISCARDED;
@@ -2404,8 +2380,11 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
            {
              // This is not a section symbol.  We can determine
              // the final value now.
-             lv_out->set_output_value(
-                 os->output_address(this, shndx, lv_in->input_value()));
+             uint64_t value =
+               os->output_address(this, shndx, lv_in->input_value());
+             if (relocatable)
+               value -= os->address();
+             lv_out->set_output_value(value);
            }
          else if (!os->find_starting_output_address(this, shndx, &start))
            {
@@ -2419,10 +2398,10 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
                os->find_relaxed_input_section(this, shndx);
              if (posd != NULL)
                {
-                 Address relocatable_link_adjustment =
-                   relocatable ? os->address() : 0;
-                 lv_out->set_output_value(posd->address()
-                                          - relocatable_link_adjustment);
+                 uint64_t value = posd->address();
+                 if (relocatable)
+                   value -= os->address();
+                 lv_out->set_output_value(value);
                }
              else
                lv_out->set_output_value(os->address());
@@ -2676,7 +2655,6 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
       elfcpp::Sym<size, big_endian> isym(psyms);
 
       Symbol_value<size>& lv(this->local_values_[i]);
-      typename elfcpp::Elf_types<size>::Elf_Addr sym_value = lv.value(this, 0);
 
       bool is_ordinary;
       unsigned int st_shndx = this->adjust_sym_shndx(i, isym.get_st_shndx(),
@@ -2686,9 +2664,6 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
          gold_assert(st_shndx < out_sections.size());
          if (out_sections[st_shndx] == NULL)
            continue;
-         // In relocatable object files symbol values are section relative.
-         if (parameters->options().relocatable())
-           sym_value -= out_sections[st_shndx]->address();
          st_shndx = out_sections[st_shndx]->out_shndx();
          if (st_shndx >= elfcpp::SHN_LORESERVE)
            {
@@ -2708,7 +2683,7 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
          gold_assert(isym.get_st_name() < strtab_size);
          const char* name = pnames + isym.get_st_name();
          osym.put_st_name(sympool->get_offset(name));
-         osym.put_st_value(sym_value);
+         osym.put_st_value(lv.value(this, 0));
          osym.put_st_size(isym.get_st_size());
          osym.put_st_info(isym.get_st_info());
          osym.put_st_other(isym.get_st_other());
@@ -2726,7 +2701,7 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
          gold_assert(isym.get_st_name() < strtab_size);
          const char* name = pnames + isym.get_st_name();
          osym.put_st_name(dynpool->get_offset(name));
-         osym.put_st_value(sym_value);
+         osym.put_st_value(lv.value(this, 0));
          osym.put_st_size(isym.get_st_size());
          osym.put_st_info(isym.get_st_info());
          osym.put_st_other(isym.get_st_other());
@@ -2837,26 +2812,117 @@ template<int size, bool big_endian>
 typename Sized_relobj_file<size, big_endian>::Address
 Sized_relobj_file<size, big_endian>::map_to_kept_section(
     unsigned int shndx,
-    bool* found) const
+    std::string& section_name,
+    bool* pfound) const
 {
-  Relobj* kept_object;
-  unsigned int kept_shndx;
-  if (this->get_kept_comdat_section(shndx, &kept_object, &kept_shndx))
-    {
-      Sized_relobj_file<size, big_endian>* kept_relobj =
-       static_cast<Sized_relobj_file<size, big_endian>*>(kept_object);
-      Output_section* os = kept_relobj->output_section(kept_shndx);
-      Address offset = kept_relobj->get_output_section_offset(kept_shndx);
-      if (os != NULL && offset != invalid_address)
+  Kept_section* kept_section;
+  bool is_comdat;
+  uint64_t sh_size;
+  unsigned int symndx;
+  bool found = false;
+
+  if (this->get_kept_comdat_section(shndx, &is_comdat, &symndx, &sh_size,
+                                   &kept_section))
+    {
+      Relobj* kept_object = kept_section->object();
+      unsigned int kept_shndx = 0;
+      if (!kept_section->is_comdat())
+        {
+         // The kept section is a linkonce section.
+         if (sh_size == kept_section->linkonce_size())
+           found = true;
+        }
+      else
+       {
+         if (is_comdat)
+           {
+             // Find the corresponding kept section.
+             // Since we're using this mapping for relocation processing,
+             // we don't want to match sections unless they have the same
+             // size.
+             uint64_t kept_size;
+             if (kept_section->find_comdat_section(section_name, &kept_shndx,
+                                                   &kept_size))
+               {
+                 if (sh_size == kept_size)
+                   found = true;
+               }
+           }
+         else
+           {
+             uint64_t kept_size;
+             if (kept_section->find_single_comdat_section(&kept_shndx,
+                                                          &kept_size)
+                 && sh_size == kept_size)
+               found = true;
+           }
+       }
+
+      if (found)
        {
-         *found = true;
-         return os->address() + offset;
+         Sized_relobj_file<size, big_endian>* kept_relobj =
+           static_cast<Sized_relobj_file<size, big_endian>*>(kept_object);
+         Output_section* os = kept_relobj->output_section(kept_shndx);
+         Address offset = kept_relobj->get_output_section_offset(kept_shndx);
+         if (os != NULL && offset != invalid_address)
+           {
+             *pfound = true;
+             return os->address() + offset;
+           }
        }
     }
-  *found = false;
+  *pfound = false;
   return 0;
 }
 
+// Look for a kept section corresponding to the given discarded section,
+// and return its object file.
+
+template<int size, bool big_endian>
+Relobj*
+Sized_relobj_file<size, big_endian>::find_kept_section_object(
+    unsigned int shndx, unsigned int *symndx_p) const
+{
+  Kept_section* kept_section;
+  bool is_comdat;
+  uint64_t sh_size;
+  if (this->get_kept_comdat_section(shndx, &is_comdat, symndx_p, &sh_size,
+                                   &kept_section))
+    return kept_section->object();
+  return NULL;
+}
+
+// Return the name of symbol SYMNDX.
+
+template<int size, bool big_endian>
+const char*
+Sized_relobj_file<size, big_endian>::get_symbol_name(unsigned int symndx)
+{
+  if (this->symtab_shndx_ == 0)
+    return NULL;
+
+  section_size_type symbols_size;
+  const unsigned char* symbols = this->section_contents(this->symtab_shndx_,
+                                                       &symbols_size,
+                                                       false);
+
+  unsigned int symbol_names_shndx =
+    this->adjust_shndx(this->section_link(this->symtab_shndx_));
+  section_size_type names_size;
+  const unsigned char* symbol_names_u =
+    this->section_contents(symbol_names_shndx, &names_size, false);
+  const char* symbol_names = reinterpret_cast<const char*>(symbol_names_u);
+
+  const unsigned char* p = symbols + symndx * This::sym_size;
+
+  if (p >= symbols + symbols_size)
+    return NULL;
+
+  elfcpp::Sym<size, big_endian> sym(p);
+
+  return symbol_names + sym.get_st_name();
+}
+
 // Get symbol counts.
 
 template<int size, bool big_endian>
@@ -3456,4 +3522,36 @@ Xindex::read_symtab_xindex<64, true>(Object*, unsigned int,
                                     const unsigned char*);
 #endif
 
+#ifdef HAVE_TARGET_32_LITTLE
+template
+Compressed_section_map*
+build_compressed_section_map<32, false>(const unsigned char*, unsigned int,
+                                       const char*, section_size_type, 
+                                       Object*, bool);
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+Compressed_section_map*
+build_compressed_section_map<32, true>(const unsigned char*, unsigned int,
+                                       const char*, section_size_type, 
+                                       Object*, bool);
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+Compressed_section_map*
+build_compressed_section_map<64, false>(const unsigned char*, unsigned int,
+                                       const char*, section_size_type, 
+                                       Object*, bool);
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+Compressed_section_map*
+build_compressed_section_map<64, true>(const unsigned char*, unsigned int,
+                                       const char*, section_size_type, 
+                                       Object*, bool);
+#endif
+
 } // End namespace gold.
This page took 0.059737 seconds and 4 git commands to generate.