gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gold / reloc.cc
index 6f2ede7024bb7e09aebbd947373f96d4b83a6ca3..7cd9f859e0d9973ac46b0fd383c61817cb44cd71 100644 (file)
@@ -1,6 +1,6 @@
 // reloc.cc -- relocate input files for gold.
 
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright (C) 2006-2020 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -56,7 +56,9 @@ Read_relocs::is_runnable()
 void
 Read_relocs::locks(Task_locker* tl)
 {
-  tl->add(this, this->object_->token());
+  Task_token* token = this->object_->token();
+  if (token != NULL)
+    tl->add(this, token);
 }
 
 // Read the relocations and then start a Scan_relocs_task.
@@ -172,7 +174,9 @@ Scan_relocs::is_runnable()
 void
 Scan_relocs::locks(Task_locker* tl)
 {
-  tl->add(this, this->object_->token());
+  Task_token* token = this->object_->token();
+  if (token != NULL)
+    tl->add(this, token);
   tl->add(this, this->next_blocker_);
 }
 
@@ -222,7 +226,9 @@ Relocate_task::locks(Task_locker* tl)
   if (this->input_sections_blocker_ != NULL)
     tl->add(this, this->input_sections_blocker_);
   tl->add(this, this->final_blocker_);
-  tl->add(this, this->object_->token());
+  Task_token* token = this->object_->token();
+  if (token != NULL)
+    tl->add(this, token);
 }
 
 // Run the task.
@@ -252,7 +258,7 @@ Relocate_task::get_name() const
 
 template<int size, bool big_endian>
 void
-Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
+Sized_relobj_file<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
 {
   rd->relocs.clear();
 
@@ -263,7 +269,7 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
   rd->relocs.reserve(shnum / 2);
 
   const Output_sections& out_sections(this->output_sections());
-  const std::vector<Address>& out_offsets(this->section_offsets_);
+  const std::vector<Address>& out_offsets(this->section_offsets());
 
   const unsigned char* pshdrs = this->get_view(this->elf_file_.shoff(),
                                               shnum * This::shdr_size,
@@ -303,7 +309,7 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
       if (!is_section_allocated
          && !parameters->options().relocatable()
          && !parameters->options().emit_relocs()
-         && !parameters->options().incremental())
+         && !parameters->incremental())
        continue;
 
       if (this->adjust_shndx(shdr.get_sh_link()) != this->symtab_shndx_)
@@ -316,6 +322,9 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
 
       off_t sh_size = shdr.get_sh_size();
 
+      if (sh_size == 0)
+       continue;
+
       unsigned int reloc_size;
       if (sh_type == elfcpp::SHT_REL)
        reloc_size = elfcpp::Elf_sizes<size>::rel_size;
@@ -369,14 +378,14 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
 }
 
 // Process the relocs to generate mappings from source sections to referenced
-// sections.  This is used during garbage colletion to determine garbage 
+// sections.  This is used during garbage collection to determine garbage
 // sections.
 
 template<int size, bool big_endian>
 void
-Sized_relobj<size, big_endian>::do_gc_process_relocs(Symbol_table* symtab,
-                                                    Layout* layout,
-                                                    Read_relocs_data* rd)
+Sized_relobj_file<size, big_endian>::do_gc_process_relocs(Symbol_table* symtab,
+                                                         Layout* layout,
+                                                         Read_relocs_data* rd)
 {  
   Sized_target<size, big_endian>* target =
     parameters->sized_target<size, big_endian>();
@@ -414,9 +423,9 @@ Sized_relobj<size, big_endian>::do_gc_process_relocs(Symbol_table* symtab,
 
 template<int size, bool big_endian>
 void
-Sized_relobj<size, big_endian>::do_scan_relocs(Symbol_table* symtab,
-                                              Layout* layout,
-                                              Read_relocs_data* rd)
+Sized_relobj_file<size, big_endian>::do_scan_relocs(Symbol_table* symtab,
+                                                   Layout* layout,
+                                                   Read_relocs_data* rd)
 {
   Sized_target<size, big_endian>* target =
     parameters->sized_target<size, big_endian>();
@@ -483,7 +492,7 @@ Sized_relobj<size, big_endian>::do_scan_relocs(Symbol_table* symtab,
 
   // For incremental links, finalize the allocation of relocations.
   if (layout->incremental_inputs() != NULL)
-    this->finalize_incremental_relocs(layout);
+    this->finalize_incremental_relocs(layout, true);
 
   if (rd->local_symbols != NULL)
     {
@@ -492,85 +501,28 @@ Sized_relobj<size, big_endian>::do_scan_relocs(Symbol_table* symtab,
     }
 }
 
-// This is a strategy class we use when scanning for --emit-relocs.
-
-template<int sh_type>
-class Emit_relocs_strategy
-{
- public:
-  // A local non-section symbol.
-  inline Relocatable_relocs::Reloc_strategy
-  local_non_section_strategy(unsigned int, Relobj*, unsigned int)
-  { return Relocatable_relocs::RELOC_COPY; }
-
-  // A local section symbol.
-  inline Relocatable_relocs::Reloc_strategy
-  local_section_strategy(unsigned int, Relobj*)
-  {
-    if (sh_type == elfcpp::SHT_RELA)
-      return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA;
-    else
-      {
-       // The addend is stored in the section contents.  Since this
-       // is not a relocatable link, we are going to apply the
-       // relocation contents to the section as usual.  This means
-       // that we have no way to record the original addend.  If the
-       // original addend is not zero, there is basically no way for
-       // the user to handle this correctly.  Caveat emptor.
-       return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0;
-      }
-  }
-
-  // A global symbol.
-  inline Relocatable_relocs::Reloc_strategy
-  global_strategy(unsigned int, Relobj*, unsigned int)
-  { return Relocatable_relocs::RELOC_COPY; }
-};
-
 // Scan the input relocations for --emit-relocs.
 
 template<int size, bool big_endian>
 void
-Sized_relobj<size, big_endian>::emit_relocs_scan(
+Sized_relobj_file<size, big_endian>::emit_relocs_scan(
     Symbol_table* symtab,
     Layout* layout,
     const unsigned char* plocal_syms,
     const Read_relocs_data::Relocs_list::iterator& p)
 {
+  Sized_target<size, big_endian>* target =
+      parameters->sized_target<size, big_endian>();
+
   Relocatable_relocs* rr = this->relocatable_relocs(p->reloc_shndx);
   gold_assert(rr != NULL);
   rr->set_reloc_count(p->reloc_count);
-
-  if (p->sh_type == elfcpp::SHT_REL)
-    this->emit_relocs_scan_reltype<elfcpp::SHT_REL>(symtab, layout,
-                                                   plocal_syms, p, rr);
-  else
-    {
-      gold_assert(p->sh_type == elfcpp::SHT_RELA);
-      this->emit_relocs_scan_reltype<elfcpp::SHT_RELA>(symtab, layout,
-                                                      plocal_syms, p, rr);
-    }
-}
-
-// Scan the input relocation for --emit-relocs, templatized on the
-// type of the relocation section.
-
-template<int size, bool big_endian>
-template<int sh_type>
-void
-Sized_relobj<size, big_endian>::emit_relocs_scan_reltype(
-    Symbol_table* symtab,
-    Layout* layout,
-    const unsigned char* plocal_syms,
-    const Read_relocs_data::Relocs_list::iterator& p,
-    Relocatable_relocs* rr)
-{
-  scan_relocatable_relocs<size, big_endian, sh_type,
-                         Emit_relocs_strategy<sh_type> >(
+  target->emit_relocs_scan(
     symtab,
     layout,
     this,
     p->data_shndx,
+    p->sh_type,
     p->contents->data(),
     p->reloc_count,
     p->output_section,
@@ -584,7 +536,7 @@ Sized_relobj<size, big_endian>::emit_relocs_scan_reltype(
 
 template<int size, bool big_endian>
 void
-Sized_relobj<size, big_endian>::incremental_relocs_scan(
+Sized_relobj_file<size, big_endian>::incremental_relocs_scan(
     const Read_relocs_data::Relocs_list::iterator& p)
 {
   if (p->sh_type == elfcpp::SHT_REL)
@@ -596,13 +548,13 @@ Sized_relobj<size, big_endian>::incremental_relocs_scan(
     }
 }
 
-// Scan the input relocation for --emit-relocs, templatized on the
+// Scan the input relocation for --incremental, templatized on the
 // type of the relocation section.
 
 template<int size, bool big_endian>
 template<int sh_type>
 void
-Sized_relobj<size, big_endian>::incremental_relocs_scan_reltype(
+Sized_relobj_file<size, big_endian>::incremental_relocs_scan_reltype(
     const Read_relocs_data::Relocs_list::iterator& p)
 {
   typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
@@ -619,8 +571,8 @@ Sized_relobj<size, big_endian>::incremental_relocs_scan_reltype(
                                                         reloc.get_r_offset()))
        continue;
 
-      typename elfcpp::Elf_types<size>::Elf_WXword r_info =
-         reloc.get_r_info();
+      // FIXME: Some targets have a non-standard r_info field.
+      typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
       const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
 
       if (r_sym >= this->local_symbol_count_)
@@ -632,9 +584,9 @@ Sized_relobj<size, big_endian>::incremental_relocs_scan_reltype(
 
 template<int size, bool big_endian>
 void
-Sized_relobj<size, big_endian>::do_relocate(const Symbol_table* symtab,
-                                           const Layout* layout,
-                                           Output_file* of)
+Sized_relobj_file<size, big_endian>::do_relocate(const Symbol_table* symtab,
+                                                const Layout* layout,
+                                                Output_file* of)
 {
   unsigned int shnum = this->shnum();
 
@@ -650,12 +602,30 @@ Sized_relobj<size, big_endian>::do_relocate(const Symbol_table* symtab,
   // section data to the output file.  The second one applies
   // relocations.
 
-  this->write_sections(pshdrs, of, &views);
+  this->write_sections(layout, pshdrs, of, &views);
 
   // To speed up relocations, we set up hash tables for fast lookup of
   // input offsets to output addresses.
   this->initialize_input_to_output_maps();
 
+  // Make the views available through get_output_view() for the duration
+  // of this routine.  This RAII class will reset output_views_ to NULL
+  // when the views go out of scope.
+  struct Set_output_views
+  {
+    Set_output_views(const Views** ppviews, const Views* pviews)
+    {
+      ppviews_ = ppviews;
+      *ppviews = pviews;
+    }
+
+    ~Set_output_views()
+    { *ppviews_ = NULL; }
+
+    const Views** ppviews_;
+  };
+  Set_output_views set_output_views(&this->output_views_, &views);
+
   // Apply relocations.
 
   this->relocate_sections(symtab, layout, pshdrs, of, &views);
@@ -669,6 +639,8 @@ Sized_relobj<size, big_endian>::do_relocate(const Symbol_table* symtab,
     {
       if (views[i].view != NULL)
        {
+         if (views[i].is_ctors_reverse_view)
+           this->reverse_words(views[i].view, views[i].view_size);
          if (!views[i].is_postprocessing_view)
            {
              if (views[i].is_input_output_view)
@@ -684,10 +656,8 @@ Sized_relobj<size, big_endian>::do_relocate(const Symbol_table* symtab,
 
   // Write out the local symbols.
   this->write_local_symbols(of, layout->sympool(), layout->dynpool(),
-                           layout->symtab_xindex(), layout->dynsym_xindex());
-
-  // We should no longer need the local symbol values.
-  this->clear_local_symbols();
+                           layout->symtab_xindex(), layout->dynsym_xindex(),
+                           layout->symtab_section_offset());
 }
 
 // Sort a Read_multiple vector by file offset.
@@ -705,13 +675,14 @@ struct Read_multiple_compare
 
 template<int size, bool big_endian>
 void
-Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs,
-                                              Output_file* of,
-                                              Views* pviews)
+Sized_relobj_file<size, big_endian>::write_sections(const Layout* layout,
+                                                   const unsigned char* pshdrs,
+                                                   Output_file* of,
+                                                   Views* pviews)
 {
   unsigned int shnum = this->shnum();
   const Output_sections& out_sections(this->output_sections());
-  const std::vector<Address>& out_offsets(this->section_offsets_);
+  const std::vector<Address>& out_offsets(this->section_offsets());
 
   File_read::Read_multiple rm;
   bool is_sorted = true;
@@ -754,6 +725,7 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs,
          pvs->address = posd->address();
          pvs->is_input_output_view = false;
          pvs->is_postprocessing_view = false;
+         pvs->is_ctors_reverse_view = false;
 
          continue;
        }
@@ -855,7 +827,9 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs,
          // Read and decompress the section.
           section_size_type len;
          const unsigned char* p = this->section_contents(i, &len, false);
-         if (!decompress_input_section(p, len, view, view_size))
+         if (!decompress_input_section(p, len, view, view_size,
+                                       size, big_endian,
+                                       shdr.get_sh_flags()))
            this->error(_("could not decompress section %s"),
                        this->section_name(i).c_str());
         }
@@ -868,6 +842,12 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs,
       pvs->view_size = view_size;
       pvs->is_input_output_view = output_offset == invalid_address;
       pvs->is_postprocessing_view = os->requires_postprocessing();
+      pvs->is_ctors_reverse_view =
+       (!parameters->options().relocatable()
+        && view_size > size / 8
+        && (strcmp(os->name(), ".init_array") == 0
+            || strcmp(os->name(), ".fini_array") == 0)
+        && layout->is_ctors_in_init_array(this, i));
     }
 
   // Actually read the data.
@@ -884,27 +864,50 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs,
 
 template<int size, bool big_endian>
 void
-Sized_relobj<size, big_endian>::do_relocate_sections(
+Sized_relobj_file<size, big_endian>::do_relocate_sections(
     const Symbol_table* symtab,
     const Layout* layout,
     const unsigned char* pshdrs,
     Output_file* of,
     Views* pviews)
 {
-  unsigned int shnum = this->shnum();
+  this->relocate_section_range(symtab, layout, pshdrs, of, pviews,
+                              1, this->shnum() - 1);
+}
+
+// Relocate section data for the range of sections START_SHNDX through
+// END_SHNDX.
+
+template<int size, bool big_endian>
+void
+Sized_relobj_file<size, big_endian>::relocate_section_range(
+    const Symbol_table* symtab,
+    const Layout* layout,
+    const unsigned char* pshdrs,
+    Output_file* of,
+    Views* pviews,
+    unsigned int start_shndx,
+    unsigned int end_shndx)
+{
+  gold_assert(start_shndx >= 1);
+  gold_assert(end_shndx < this->shnum());
+
+  if (end_shndx < start_shndx)
+    return;
+
   Sized_target<size, big_endian>* target =
     parameters->sized_target<size, big_endian>();
 
   const Output_sections& out_sections(this->output_sections());
-  const std::vector<Address>& out_offsets(this->section_offsets_);
+  const std::vector<Address>& out_offsets(this->section_offsets());
 
   Relocate_info<size, big_endian> relinfo;
   relinfo.symtab = symtab;
   relinfo.layout = layout;
   relinfo.object = this;
 
-  const unsigned char* p = pshdrs + This::shdr_size;
-  for (unsigned int i = 1; i < shnum; ++i, p += This::shdr_size)
+  const unsigned char* p = pshdrs + start_shndx * This::shdr_size;
+  for (unsigned int i = start_shndx; i <= end_shndx; ++i, p += This::shdr_size)
     {
       typename This::Shdr shdr(p);
 
@@ -988,108 +991,59 @@ Sized_relobj<size, big_endian>::do_relocate_sections(
          if ((data_shdr.get_sh_flags() & elfcpp::SHF_EXECINSTR) != 0)
            this->split_stack_adjust(symtab, pshdrs, sh_type, index,
                                     prelocs, reloc_count, view, view_size,
-                                    &reloc_map);
+                                    &reloc_map, target);
        }
 
+      Relocatable_relocs* rr = NULL;
+      if (parameters->options().emit_relocs()
+         || parameters->options().relocatable())
+       rr = this->relocatable_relocs(i);
+      relinfo.rr = rr;
+
       if (!parameters->options().relocatable())
        {
          target->relocate_section(&relinfo, sh_type, prelocs, reloc_count, os,
                                   output_offset == invalid_address,
                                   view, address, view_size, reloc_map);
          if (parameters->options().emit_relocs())
-           this->emit_relocs(&relinfo, i, sh_type, prelocs, reloc_count,
-                             os, output_offset, view, address, view_size,
-                             (*pviews)[i].view, (*pviews)[i].view_size);
-         if (parameters->options().incremental())
+           target->relocate_relocs(&relinfo, sh_type, prelocs, reloc_count,
+                                   os, output_offset,
+                                   view, address, view_size,
+                                   (*pviews)[i].view,
+                                   (*pviews)[i].view_size);
+         if (parameters->incremental())
            this->incremental_relocs_write(&relinfo, sh_type, prelocs,
                                           reloc_count, os, output_offset, of);
        }
       else
-       {
-         Relocatable_relocs* rr = this->relocatable_relocs(i);
-         target->relocate_for_relocatable(&relinfo, sh_type, prelocs,
-                                          reloc_count, os, output_offset, rr,
-                                          view, address, view_size,
-                                          (*pviews)[i].view,
-                                          (*pviews)[i].view_size);
-       }
+       target->relocate_relocs(&relinfo, sh_type, prelocs, reloc_count,
+                               os, output_offset,
+                               view, address, view_size,
+                               (*pviews)[i].view,
+                               (*pviews)[i].view_size);
     }
 }
 
-// Emit the relocs for --emit-relocs.
+// Return the output view for section SHNDX.
 
 template<int size, bool big_endian>
-void
-Sized_relobj<size, big_endian>::emit_relocs(
-    const Relocate_info<size, big_endian>* relinfo,
-    unsigned int i,
-    unsigned int sh_type,
-    const unsigned char* prelocs,
-    size_t reloc_count,
-    Output_section* output_section,
-    typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section,
-    unsigned char* view,
-    typename elfcpp::Elf_types<size>::Elf_Addr address,
-    section_size_type view_size,
-    unsigned char* reloc_view,
-    section_size_type reloc_view_size)
-{
-  if (sh_type == elfcpp::SHT_REL)
-    this->emit_relocs_reltype<elfcpp::SHT_REL>(relinfo, i, prelocs,
-                                              reloc_count, output_section,
-                                              offset_in_output_section,
-                                              view, address, view_size,
-                                              reloc_view, reloc_view_size);
-  else
-    {
-      gold_assert(sh_type == elfcpp::SHT_RELA);
-      this->emit_relocs_reltype<elfcpp::SHT_RELA>(relinfo, i, prelocs,
-                                                 reloc_count, output_section,
-                                                 offset_in_output_section,
-                                                 view, address, view_size,
-                                                 reloc_view, reloc_view_size);
-    }
-}
-
-// Emit the relocs for --emit-relocs, templatized on the type of the
-// relocation section.
-
-template<int size, bool big_endian>
-template<int sh_type>
-void
-Sized_relobj<size, big_endian>::emit_relocs_reltype(
-    const Relocate_info<size, big_endian>* relinfo,
-    unsigned int i,
-    const unsigned char* prelocs,
-    size_t reloc_count,
-    Output_section* output_section,
-    typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section,
-    unsigned char* view,
-    typename elfcpp::Elf_types<size>::Elf_Addr address,
-    section_size_type view_size,
-    unsigned char* reloc_view,
-    section_size_type reloc_view_size)
+unsigned char*
+Sized_relobj_file<size, big_endian>::do_get_output_view(
+    unsigned int shndx,
+    section_size_type* plen) const
 {
-  const Relocatable_relocs* rr = this->relocatable_relocs(i);
-  relocate_for_relocatable<size, big_endian, sh_type>(
-    relinfo,
-    prelocs,
-    reloc_count,
-    output_section,
-    offset_in_output_section,
-    rr,
-    view,
-    address,
-    view_size,
-    reloc_view,
-    reloc_view_size);
+  gold_assert(this->output_views_ != NULL);
+  gold_assert(shndx < this->output_views_->size());
+  const View_size& v = (*this->output_views_)[shndx];
+  *plen = v.view_size;
+  return v.view;
 }
 
 // Write the incremental relocs.
 
 template<int size, bool big_endian>
 void
-Sized_relobj<size, big_endian>::incremental_relocs_write(
+Sized_relobj_file<size, big_endian>::incremental_relocs_write(
     const Relocate_info<size, big_endian>* relinfo,
     unsigned int sh_type,
     const unsigned char* prelocs,
@@ -1125,7 +1079,7 @@ Sized_relobj<size, big_endian>::incremental_relocs_write(
 template<int size, bool big_endian>
 template<int sh_type>
 void
-Sized_relobj<size, big_endian>::incremental_relocs_write_reltype(
+Sized_relobj_file<size, big_endian>::incremental_relocs_write_reltype(
     const Relocate_info<size, big_endian>* relinfo,
     const unsigned char* prelocs,
     size_t reloc_count,
@@ -1137,7 +1091,8 @@ Sized_relobj<size, big_endian>::incremental_relocs_write_reltype(
   const unsigned int reloc_size =
       Reloc_types<sh_type, size, big_endian>::reloc_size;
   const unsigned int sizeof_addr = size / 8;
-  const unsigned int incr_reloc_size = 8 + 2 * sizeof_addr;
+  const unsigned int incr_reloc_size =
+      Incremental_relocs_reader<size, big_endian>::reloc_size;
 
   unsigned int out_shndx = output_section->out_shndx();
 
@@ -1153,6 +1108,7 @@ Sized_relobj<size, big_endian>::incremental_relocs_write_reltype(
     {
       Reloc reloc(prelocs);
 
+      // FIXME: Some targets have a non-standard r_info field.
       typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
       const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
       const unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
@@ -1210,7 +1166,7 @@ Sized_relobj<size, big_endian>::incremental_relocs_write_reltype(
 
 template<int size, bool big_endian>
 void
-Sized_relobj<size, big_endian>::initialize_input_to_output_maps()
+Sized_relobj_file<size, big_endian>::initialize_input_to_output_maps()
 {
   const unsigned int loccount = this->local_symbol_count_;
   for (unsigned int i = 1; i < loccount; ++i)
@@ -1224,7 +1180,7 @@ Sized_relobj<size, big_endian>::initialize_input_to_output_maps()
 
 template<int size, bool big_endian>
 void
-Sized_relobj<size, big_endian>::free_input_to_output_maps()
+Sized_relobj_file<size, big_endian>::free_input_to_output_maps()
 {
   const unsigned int loccount = this->local_symbol_count_;
   for (unsigned int i = 1; i < loccount; ++i)
@@ -1242,7 +1198,7 @@ Sized_relobj<size, big_endian>::free_input_to_output_maps()
 
 template<int size, bool big_endian>
 void
-Sized_relobj<size, big_endian>::split_stack_adjust(
+Sized_relobj_file<size, big_endian>::split_stack_adjust(
     const Symbol_table* symtab,
     const unsigned char* pshdrs,
     unsigned int sh_type,
@@ -1251,20 +1207,21 @@ Sized_relobj<size, big_endian>::split_stack_adjust(
     size_t reloc_count,
     unsigned char* view,
     section_size_type view_size,
-    Reloc_symbol_changes** reloc_map)
+    Reloc_symbol_changes** reloc_map,
+    const Sized_target<size, big_endian>* target)
 {
   if (sh_type == elfcpp::SHT_REL)
     this->split_stack_adjust_reltype<elfcpp::SHT_REL>(symtab, pshdrs, shndx,
                                                      prelocs, reloc_count,
                                                      view, view_size,
-                                                     reloc_map);
+                                                     reloc_map, target);
   else
     {
       gold_assert(sh_type == elfcpp::SHT_RELA);
       this->split_stack_adjust_reltype<elfcpp::SHT_RELA>(symtab, pshdrs, shndx,
                                                         prelocs, reloc_count,
                                                         view, view_size,
-                                                        reloc_map);
+                                                        reloc_map, target);
     }
 }
 
@@ -1274,7 +1231,7 @@ Sized_relobj<size, big_endian>::split_stack_adjust(
 template<int size, bool big_endian>
 template<int sh_type>
 void
-Sized_relobj<size, big_endian>::split_stack_adjust_reltype(
+Sized_relobj_file<size, big_endian>::split_stack_adjust_reltype(
     const Symbol_table* symtab,
     const unsigned char* pshdrs,
     unsigned int shndx,
@@ -1282,7 +1239,8 @@ Sized_relobj<size, big_endian>::split_stack_adjust_reltype(
     size_t reloc_count,
     unsigned char* view,
     section_size_type view_size,
-    Reloc_symbol_changes** reloc_map)
+    Reloc_symbol_changes** reloc_map,
+    const Sized_target<size, big_endian>* target)
 {
   typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
   const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
@@ -1294,10 +1252,10 @@ Sized_relobj<size, big_endian>::split_stack_adjust_reltype(
   const unsigned char* pr = prelocs;
   for (size_t i = 0; i < reloc_count; ++i, pr += reloc_size)
     {
-      Reltype reloc(pr);
-
-      typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
-      unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
+      // Some supported targets have a non-standard r_info field.
+      // If this call is too slow, we can move this routine to
+      // target-reloc.h and templatize it on Classify_reloc.
+      unsigned int r_sym = target->get_r_sym(pr);
       if (r_sym < local_count)
        continue;
 
@@ -1316,9 +1274,10 @@ Sized_relobj<size, big_endian>::split_stack_adjust_reltype(
          && gsym->source() == Symbol::FROM_OBJECT
          && !gsym->object()->uses_split_stack())
        {
-         unsigned int r_type = elfcpp::elf_r_type<size>(reloc.get_r_info());
-         if (parameters->target().is_call_to_non_split(gsym, r_type))
+         if (parameters->target().is_call_to_non_split(gsym, pr, view,
+                                                       view_size))
            {
+             Reltype reloc(pr);
              section_offset_type offset =
                convert_to_section_size_type(reloc.get_r_offset());
              non_split_refs.push_back(offset);
@@ -1375,6 +1334,7 @@ Sized_relobj<size, big_endian>::split_stack_adjust_reltype(
       std::string from;
       std::string to;
       parameters->target().calls_non_split(this, shndx, p->first, p->second,
+                                          prelocs, reloc_count,
                                           view, view_size, &from, &to);
       if (!from.empty())
        {
@@ -1388,9 +1348,7 @@ Sized_relobj<size, big_endian>::split_stack_adjust_reltype(
            {
              Reltype reloc(pr);
 
-             typename elfcpp::Elf_types<size>::Elf_WXword r_info =
-               reloc.get_r_info();
-             unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
+             unsigned int r_sym = target->get_r_sym(pr);
              if (r_sym < local_count)
                continue;
 
@@ -1431,10 +1389,10 @@ Sized_relobj<size, big_endian>::split_stack_adjust_reltype(
 
 template<int size, bool big_endian>
 void
-Sized_relobj<size, big_endian>::find_functions(
+Sized_relobj_file<size, big_endian>::find_functions(
     const unsigned char* pshdrs,
     unsigned int shndx,
-    Sized_relobj<size, big_endian>::Function_offsets* function_offsets)
+    Sized_relobj_file<size, big_endian>::Function_offsets* function_offsets)
 {
   // We need to read the symbols to find the functions.  If we wanted
   // to, we could cache reading the symbols across all sections in the
@@ -1461,13 +1419,21 @@ Sized_relobj<size, big_endian>::find_functions(
        continue;
 
       bool is_ordinary;
-      unsigned int sym_shndx = this->adjust_sym_shndx(i, isym.get_st_shndx(),
-                                                     &is_ordinary);
-      if (!is_ordinary || sym_shndx != shndx)
+      Symbol_location loc;
+      loc.shndx = this->adjust_sym_shndx(i, isym.get_st_shndx(),
+                                        &is_ordinary);
+      if (!is_ordinary)
+       continue;
+
+      loc.object = this;
+      loc.offset = isym.get_st_value();
+      parameters->target().function_location(&loc);
+
+      if (loc.shndx != shndx)
        continue;
 
       section_offset_type value =
-       convert_to_section_size_type(isym.get_st_value());
+       convert_to_section_size_type(loc.offset);
       section_size_type fnsize =
        convert_to_section_size_type(isym.get_st_size());
 
@@ -1475,6 +1441,26 @@ Sized_relobj<size, big_endian>::find_functions(
     }
 }
 
+// Reverse the words in a section.  Used for .ctors sections mapped to
+// .init_array sections.  See ctors_sections_in_init_array in
+// layout.cc.
+
+template<int size, bool big_endian>
+void
+Sized_relobj_file<size, big_endian>::reverse_words(unsigned char* view,
+                                                  section_size_type view_size)
+{
+  typedef typename elfcpp::Swap<size, big_endian>::Valtype Valtype;
+  Valtype* vview = reinterpret_cast<Valtype*>(view);
+  section_size_type vview_size = view_size / (size / 8);
+  for (section_size_type i = 0; i < vview_size / 2; ++i)
+    {
+      Valtype tmp = vview[i];
+      vview[i] = vview[vview_size - 1 - i];
+      vview[vview_size - 1 - i] = tmp;
+    }
+}
+
 // Class Merged_symbol_value.
 
 template<int size>
@@ -1483,10 +1469,9 @@ Merged_symbol_value<size>::initialize_input_to_output_map(
     const Relobj* object,
     unsigned int input_shndx)
 {
-  Object_merge_map* map = object->merge_map();
-  map->initialize_input_to_output_map<size>(input_shndx,
-                                           this->output_start_address_,
-                                           &this->output_addresses_);
+  object->initialize_input_to_output_map<size>(input_shndx,
+                                              this->output_start_address_,
+                                              &this->output_addresses_);
 }
 
 // Get the output value corresponding to an input offset if we
@@ -1500,9 +1485,8 @@ Merged_symbol_value<size>::value_from_output_section(
     typename elfcpp::Elf_types<size>::Elf_Addr input_offset) const
 {
   section_offset_type output_offset;
-  bool found = object->merge_map()->get_output_offset(NULL, input_shndx,
-                                                     input_offset,
-                                                     &output_offset);
+  bool found = object->merge_output_offset(input_shndx, input_offset,
+                                          &output_offset);
 
   // If this assertion fails, it means that some relocation was
   // against a portion of an input merge section which we didn't map
@@ -1584,11 +1568,23 @@ Track_relocs<size, big_endian>::next_symndx() const
 {
   if (this->pos_ >= this->len_)
     return -1U;
+  Sized_target<size, big_endian>* target
+      = parameters->sized_target<size, big_endian>();
+  return target->get_r_sym(this->prelocs_ + this->pos_);
+}
 
-  // Rel and Rela start out the same, so we can use Rel to find the
-  // symbol index.
-  elfcpp::Rel<size, big_endian> rel(this->prelocs_ + this->pos_);
-  return elfcpp::elf_r_sym<size>(rel.get_r_info());
+// Return the addend of the next reloc, or 0 if there isn't one.
+
+template<int size, bool big_endian>
+uint64_t
+Track_relocs<size, big_endian>::next_addend() const
+{
+  if (this->pos_ >= this->len_)
+    return 0;
+  if (this->reloc_size_ == elfcpp::Elf_sizes<size>::rel_size)
+    return 0;
+  elfcpp::Rela<size, big_endian> rela(this->prelocs_ + this->pos_);
+  return rela.get_r_addend();
 }
 
 // Advance to the next reloc whose r_offset is greater than or equal
@@ -1617,205 +1613,273 @@ Track_relocs<size, big_endian>::advance(off_t offset)
 #ifdef HAVE_TARGET_32_LITTLE
 template
 void
-Sized_relobj<32, false>::do_read_relocs(Read_relocs_data* rd);
+Sized_relobj_file<32, false>::do_read_relocs(Read_relocs_data* rd);
 #endif
 
 #ifdef HAVE_TARGET_32_BIG
 template
 void
-Sized_relobj<32, true>::do_read_relocs(Read_relocs_data* rd);
+Sized_relobj_file<32, true>::do_read_relocs(Read_relocs_data* rd);
 #endif
 
 #ifdef HAVE_TARGET_64_LITTLE
 template
 void
-Sized_relobj<64, false>::do_read_relocs(Read_relocs_data* rd);
+Sized_relobj_file<64, false>::do_read_relocs(Read_relocs_data* rd);
 #endif
 
 #ifdef HAVE_TARGET_64_BIG
 template
 void
-Sized_relobj<64, true>::do_read_relocs(Read_relocs_data* rd);
+Sized_relobj_file<64, true>::do_read_relocs(Read_relocs_data* rd);
 #endif
 
 #ifdef HAVE_TARGET_32_LITTLE
 template
 void
-Sized_relobj<32, false>::do_gc_process_relocs(Symbol_table* symtab,
-                                             Layout* layout,
-                                             Read_relocs_data* rd);
+Sized_relobj_file<32, false>::do_gc_process_relocs(Symbol_table* symtab,
+                                                  Layout* layout,
+                                                  Read_relocs_data* rd);
 #endif
 
 #ifdef HAVE_TARGET_32_BIG
 template
 void
-Sized_relobj<32, true>::do_gc_process_relocs(Symbol_table* symtab,
-                                            Layout* layout,
-                                            Read_relocs_data* rd);
+Sized_relobj_file<32, true>::do_gc_process_relocs(Symbol_table* symtab,
+                                                 Layout* layout,
+                                                 Read_relocs_data* rd);
 #endif
 
 #ifdef HAVE_TARGET_64_LITTLE
 template
 void
-Sized_relobj<64, false>::do_gc_process_relocs(Symbol_table* symtab,
-                                             Layout* layout,
-                                             Read_relocs_data* rd);
+Sized_relobj_file<64, false>::do_gc_process_relocs(Symbol_table* symtab,
+                                                  Layout* layout,
+                                                  Read_relocs_data* rd);
 #endif
 
 #ifdef HAVE_TARGET_64_BIG
 template
 void
-Sized_relobj<64, true>::do_gc_process_relocs(Symbol_table* symtab,
-                                            Layout* layout,
-                                            Read_relocs_data* rd);
+Sized_relobj_file<64, true>::do_gc_process_relocs(Symbol_table* symtab,
+                                                 Layout* layout,
+                                                 Read_relocs_data* rd);
 #endif
 
 #ifdef HAVE_TARGET_32_LITTLE
 template
 void
-Sized_relobj<32, false>::do_scan_relocs(Symbol_table* symtab,
-                                       Layout* layout,
-                                       Read_relocs_data* rd);
+Sized_relobj_file<32, false>::do_scan_relocs(Symbol_table* symtab,
+                                            Layout* layout,
+                                            Read_relocs_data* rd);
 #endif
 
 #ifdef HAVE_TARGET_32_BIG
 template
 void
-Sized_relobj<32, true>::do_scan_relocs(Symbol_table* symtab,
-                                      Layout* layout,
-                                      Read_relocs_data* rd);
+Sized_relobj_file<32, true>::do_scan_relocs(Symbol_table* symtab,
+                                           Layout* layout,
+                                           Read_relocs_data* rd);
 #endif
 
 #ifdef HAVE_TARGET_64_LITTLE
 template
 void
-Sized_relobj<64, false>::do_scan_relocs(Symbol_table* symtab,
-                                       Layout* layout,
-                                       Read_relocs_data* rd);
+Sized_relobj_file<64, false>::do_scan_relocs(Symbol_table* symtab,
+                                            Layout* layout,
+                                            Read_relocs_data* rd);
 #endif
 
 #ifdef HAVE_TARGET_64_BIG
 template
 void
-Sized_relobj<64, true>::do_scan_relocs(Symbol_table* symtab,
-                                      Layout* layout,
-                                      Read_relocs_data* rd);
+Sized_relobj_file<64, true>::do_scan_relocs(Symbol_table* symtab,
+                                           Layout* layout,
+                                           Read_relocs_data* rd);
 #endif
 
 #ifdef HAVE_TARGET_32_LITTLE
 template
 void
-Sized_relobj<32, false>::do_relocate(const Symbol_table* symtab,
-                                    const Layout* layout,
-                                    Output_file* of);
+Sized_relobj_file<32, false>::do_relocate(const Symbol_table* symtab,
+                                         const Layout* layout,
+                                         Output_file* of);
 #endif
 
 #ifdef HAVE_TARGET_32_BIG
 template
 void
-Sized_relobj<32, true>::do_relocate(const Symbol_table* symtab,
-                                   const Layout* layout,
-                                   Output_file* of);
+Sized_relobj_file<32, true>::do_relocate(const Symbol_table* symtab,
+                                        const Layout* layout,
+                                        Output_file* of);
 #endif
 
 #ifdef HAVE_TARGET_64_LITTLE
 template
 void
-Sized_relobj<64, false>::do_relocate(const Symbol_table* symtab,
-                                    const Layout* layout,
-                                    Output_file* of);
+Sized_relobj_file<64, false>::do_relocate(const Symbol_table* symtab,
+                                         const Layout* layout,
+                                         Output_file* of);
 #endif
 
 #ifdef HAVE_TARGET_64_BIG
 template
 void
-Sized_relobj<64, true>::do_relocate(const Symbol_table* symtab,
-                                   const Layout* layout,
-                                   Output_file* of);
+Sized_relobj_file<64, true>::do_relocate(const Symbol_table* symtab,
+                                        const Layout* layout,
+                                        Output_file* of);
 #endif
 
 #ifdef HAVE_TARGET_32_LITTLE
 template
 void
-Sized_relobj<32, false>::do_relocate_sections(
+Sized_relobj_file<32, false>::do_relocate_sections(
     const Symbol_table* symtab,
     const Layout* layout,
     const unsigned char* pshdrs,
     Output_file* of,
     Views* pviews);
+
+template
+void
+Sized_relobj_file<32, false>::relocate_section_range(
+    const Symbol_table* symtab,
+    const Layout* layout,
+    const unsigned char* pshdrs,
+    Output_file* of,
+    Views* pviews,
+    unsigned int start_shndx,
+    unsigned int end_shndx);
+
+template
+unsigned char*
+Sized_relobj_file<32, false>::do_get_output_view(
+    unsigned int shndx,
+    section_size_type* plen) const;
 #endif
 
 #ifdef HAVE_TARGET_32_BIG
 template
 void
-Sized_relobj<32, true>::do_relocate_sections(
+Sized_relobj_file<32, true>::do_relocate_sections(
     const Symbol_table* symtab,
     const Layout* layout,
     const unsigned char* pshdrs,
     Output_file* of,
     Views* pviews);
+
+template
+void
+Sized_relobj_file<32, true>::relocate_section_range(
+    const Symbol_table* symtab,
+    const Layout* layout,
+    const unsigned char* pshdrs,
+    Output_file* of,
+    Views* pviews,
+    unsigned int start_shndx,
+    unsigned int end_shndx);
+
+template
+unsigned char*
+Sized_relobj_file<32, true>::do_get_output_view(
+    unsigned int shndx,
+    section_size_type* plen) const;
 #endif
 
 #ifdef HAVE_TARGET_64_LITTLE
 template
 void
-Sized_relobj<64, false>::do_relocate_sections(
+Sized_relobj_file<64, false>::do_relocate_sections(
     const Symbol_table* symtab,
     const Layout* layout,
     const unsigned char* pshdrs,
     Output_file* of,
     Views* pviews);
+
+template
+void
+Sized_relobj_file<64, false>::relocate_section_range(
+    const Symbol_table* symtab,
+    const Layout* layout,
+    const unsigned char* pshdrs,
+    Output_file* of,
+    Views* pviews,
+    unsigned int start_shndx,
+    unsigned int end_shndx);
+
+template
+unsigned char*
+Sized_relobj_file<64, false>::do_get_output_view(
+    unsigned int shndx,
+    section_size_type* plen) const;
 #endif
 
 #ifdef HAVE_TARGET_64_BIG
 template
 void
-Sized_relobj<64, true>::do_relocate_sections(
+Sized_relobj_file<64, true>::do_relocate_sections(
     const Symbol_table* symtab,
     const Layout* layout,
     const unsigned char* pshdrs,
     Output_file* of,
     Views* pviews);
+
+template
+void
+Sized_relobj_file<64, true>::relocate_section_range(
+    const Symbol_table* symtab,
+    const Layout* layout,
+    const unsigned char* pshdrs,
+    Output_file* of,
+    Views* pviews,
+    unsigned int start_shndx,
+    unsigned int end_shndx);
+
+template
+unsigned char*
+Sized_relobj_file<64, true>::do_get_output_view(
+    unsigned int shndx,
+    section_size_type* plen) const;
 #endif
 
 #ifdef HAVE_TARGET_32_LITTLE
 template
 void
-Sized_relobj<32, false>::initialize_input_to_output_maps();
+Sized_relobj_file<32, false>::initialize_input_to_output_maps();
 
 template
 void
-Sized_relobj<32, false>::free_input_to_output_maps();
+Sized_relobj_file<32, false>::free_input_to_output_maps();
 #endif
 
 #ifdef HAVE_TARGET_32_BIG
 template
 void
-Sized_relobj<32, true>::initialize_input_to_output_maps();
+Sized_relobj_file<32, true>::initialize_input_to_output_maps();
 
 template
 void
-Sized_relobj<32, true>::free_input_to_output_maps();
+Sized_relobj_file<32, true>::free_input_to_output_maps();
 #endif
 
 #ifdef HAVE_TARGET_64_LITTLE
 template
 void
-Sized_relobj<64, false>::initialize_input_to_output_maps();
+Sized_relobj_file<64, false>::initialize_input_to_output_maps();
 
 template
 void
-Sized_relobj<64, false>::free_input_to_output_maps();
+Sized_relobj_file<64, false>::free_input_to_output_maps();
 #endif
 
 #ifdef HAVE_TARGET_64_BIG
 template
 void
-Sized_relobj<64, true>::initialize_input_to_output_maps();
+Sized_relobj_file<64, true>::initialize_input_to_output_maps();
 
 template
 void
-Sized_relobj<64, true>::free_input_to_output_maps();
+Sized_relobj_file<64, true>::free_input_to_output_maps();
 #endif
 
 #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
This page took 0.040223 seconds and 4 git commands to generate.