+2015-12-09  Alan Modra  <amodra@gmail.com>
+
+       * object.h (struct Relocate_info): Add "rr".
+       * reloc.h (Relocatable_relocs::set_strategy): New accessor.
+       * reloc.cc (Sized_relobj_file::do_relocate_sections): Init
+       relinfo.rr for relocate_section and relocate_relocs.
+       * powerpc.cc (relocate): Add rel_type and preloc parameters.
+       Delete rela and r_type params, instead recalculate these from
+       preloc.
+       (relocate_relocs): Delete Relocatable_relocs* param, instead
+       use relinfo->rr.
+       * aarch64.cc: Likewise.
+       * arm.cc: Likewise.
+       * i386.cc: Likewise.
+       * mips.cc: Likewise.
+       * s390.cc: Likewise.
+       * sparc.cc: Likewise.
+       * target.h: Likewise.
+       * tilegx.cc: Likewise.
+       * x86_64.cc: Likewise.
+       * testsuite/testfile.cc: Likewise.
+       * target-reloc.h (relocate_section): Adjust to suit.
+       (apply_relocation, relocate_relocs): Likewise.
+
 2015-12-07  Alan Modra  <amodra@gmail.com>
 
        * powerpc.cc (add_2_2_12, ld_2_12, lis_2): Define.
 
       size_t reloc_count,
       Output_section* output_section,
       typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
-      const Relocatable_relocs*,
       unsigned char* view,
       typename elfcpp::Elf_types<size>::Elf_Addr view_address,
       section_size_type view_size,
     // Do a relocation.  Return false if the caller should not issue
     // any warnings about this relocation.
     inline bool
-    relocate(const Relocate_info<size, big_endian>*, Target_aarch64*,
-            Output_section*,
-            size_t relnum, const elfcpp::Rela<size, big_endian>&,
-            unsigned int r_type, const Sized_symbol<size>*,
-            const Symbol_value<size>*,
+    relocate(const Relocate_info<size, big_endian>*, unsigned int,
+            Target_aarch64*, Output_section*, size_t, const unsigned char*,
+            const Sized_symbol<size>*, const Symbol_value<size>*,
             unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
             section_size_type);
 
 inline bool
 Target_aarch64<size, big_endian>::Relocate::relocate(
     const Relocate_info<size, big_endian>* relinfo,
+    unsigned int,
     Target_aarch64<size, big_endian>* target,
     Output_section* ,
     size_t relnum,
-    const elfcpp::Rela<size, big_endian>& rela,
-    unsigned int r_type,
+    const unsigned char* preloc,
     const Sized_symbol<size>* gsym,
     const Symbol_value<size>* psymval,
     unsigned char* view,
 
   typedef AArch64_relocate_functions<size, big_endian> Reloc;
 
+  const elfcpp::Rela<size, big_endian> rela(preloc);
+  unsigned int r_type = elfcpp::elf_r_type<size>(rela.get_r_info());
   const AArch64_reloc_property* reloc_property =
       aarch64_reloc_property_table->get_reloc_property(r_type);
 
     size_t reloc_count,
     Output_section* output_section,
     typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
-    const Relocatable_relocs* rr,
     unsigned char* view,
     typename elfcpp::Elf_types<size>::Elf_Addr view_address,
     section_size_type view_size,
     reloc_count,
     output_section,
     offset_in_output_section,
-    rr,
     view,
     view_address,
     view_size,
 
                  Output_section* output_section,
                  typename elfcpp::Elf_types<32>::Elf_Off
                     offset_in_output_section,
-                 const Relocatable_relocs*,
                  unsigned char* view,
                  Arm_address view_address,
                  section_size_type view_size,
     // Do a relocation.  Return false if the caller should not issue
     // any warnings about this relocation.
     inline bool
-    relocate(const Relocate_info<32, big_endian>*, Target_arm*,
-            Output_section*,  size_t relnum,
-            const elfcpp::Rel<32, big_endian>&,
-            unsigned int r_type, const Sized_symbol<32>*,
-            const Symbol_value<32>*,
-            unsigned char*, Arm_address,
-            section_size_type);
+    relocate(const Relocate_info<32, big_endian>*, unsigned int,
+            Target_arm*, Output_section*, size_t, const unsigned char*,
+            const Sized_symbol<32>*, const Symbol_value<32>*,
+            unsigned char*, Arm_address, section_size_type);
 
     // Return whether we want to pass flag NON_PIC_REF for this
     // reloc.  This means the relocation type accesses a symbol not via
 inline bool
 Target_arm<big_endian>::Relocate::relocate(
     const Relocate_info<32, big_endian>* relinfo,
+    unsigned int,
     Target_arm* target,
     Output_section* output_section,
     size_t relnum,
-    const elfcpp::Rel<32, big_endian>& rel,
-    unsigned int r_type,
+    const unsigned char* preloc,
     const Sized_symbol<32>* gsym,
     const Symbol_value<32>* psymval,
     unsigned char* view,
 
   typedef Arm_relocate_functions<big_endian> Arm_relocate_functions;
 
+  const elfcpp::Rel<32, big_endian> rel(preloc);
+  unsigned int r_type = elfcpp::elf_r_type<32>(rel.get_r_info());
   r_type = get_real_reloc_type(r_type);
   const Arm_reloc_property* reloc_property =
     arm_reloc_property_table->get_implemented_static_reloc_property(r_type);
     size_t reloc_count,
     Output_section* output_section,
     typename elfcpp::Elf_types<32>::Elf_Off offset_in_output_section,
-    const Relocatable_relocs* rr,
     unsigned char* view,
     Arm_address view_address,
     section_size_type view_size,
     reloc_count,
     output_section,
     offset_in_output_section,
-    rr,
     view,
     view_address,
     view_size,
       elfcpp::Rel_write<32, big_endian> reloc_write(reloc_buffer);
       reloc_write.put_r_offset(reloc_offset);
       reloc_write.put_r_info(elfcpp::elf_r_info<32>(0, r_type));
-      elfcpp::Rel<32, big_endian> rel(reloc_buffer);
 
-      relocate.relocate(relinfo, this, output_section,
-                       this->fake_relnum_for_stubs, rel, r_type,
+      relocate.relocate(relinfo, elfcpp::SHT_REL, this, output_section,
+                       this->fake_relnum_for_stubs, reloc_buffer,
                        NULL, &symval, view + reloc_offset,
                        address + reloc_offset, reloc_size);
     }
 
                  size_t reloc_count,
                  Output_section* output_section,
                  elfcpp::Elf_types<32>::Elf_Off offset_in_output_section,
-                 const Relocatable_relocs*,
                  unsigned char* view,
                  elfcpp::Elf_types<32>::Elf_Addr view_address,
                  section_size_type view_size,
     // Do a relocation.  Return false if the caller should not issue
     // any warnings about this relocation.
     inline bool
-    relocate(const Relocate_info<32, false>*, Target_i386*, Output_section*,
-            size_t relnum, const elfcpp::Rel<32, false>&,
-            unsigned int r_type, const Sized_symbol<32>*,
-            const Symbol_value<32>*,
+    relocate(const Relocate_info<32, false>*, unsigned int,
+            Target_i386*, Output_section*, size_t, const unsigned char*,
+            const Sized_symbol<32>*, const Symbol_value<32>*,
             unsigned char*, elfcpp::Elf_types<32>::Elf_Addr,
             section_size_type);
 
 
 inline bool
 Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
-                                      Target_i386* target,
-                                      Output_section* output_section,
-                                      size_t relnum,
-                                      const elfcpp::Rel<32, false>& rel,
-                                      unsigned int r_type,
-                                      const Sized_symbol<32>* gsym,
-                                      const Symbol_value<32>* psymval,
-                                      unsigned char* view,
-                                      elfcpp::Elf_types<32>::Elf_Addr address,
-                                      section_size_type view_size)
+                               unsigned int,
+                               Target_i386* target,
+                               Output_section* output_section,
+                               size_t relnum,
+                               const unsigned char* preloc,
+                               const Sized_symbol<32>* gsym,
+                               const Symbol_value<32>* psymval,
+                               unsigned char* view,
+                               elfcpp::Elf_types<32>::Elf_Addr address,
+                               section_size_type view_size)
 {
+  const elfcpp::Rel<32, false> rel(preloc);
+  unsigned int r_type = elfcpp::elf_r_type<32>(rel.get_r_info());
+
   if (this->skip_call_tls_get_addr_)
     {
       if ((r_type != elfcpp::R_386_PLT32
     size_t reloc_count,
     Output_section* output_section,
     elfcpp::Elf_types<32>::Elf_Off offset_in_output_section,
-    const Relocatable_relocs* rr,
     unsigned char* view,
     elfcpp::Elf_types<32>::Elf_Addr view_address,
     section_size_type view_size,
     reloc_count,
     output_section,
     offset_in_output_section,
-    rr,
     view,
     view_address,
     view_size,
 
                   Output_section* output_section,
                   typename elfcpp::Elf_types<size>::Elf_Off
                     offset_in_output_section,
-                  const Relocatable_relocs*,
                   unsigned char* view,
                   Mips_address view_address,
                   section_size_type view_size,
     // Do a relocation.  Return false if the caller should not issue
     // any warnings about this relocation.
     inline bool
-    relocate(const Relocate_info<size, big_endian>*, Target_mips*,
-             Output_section*, size_t relnum,
-             const elfcpp::Rela<size, big_endian>*,
-             const elfcpp::Rel<size, big_endian>*,
-             unsigned int,
-             unsigned int,  const Sized_symbol<size>*,
-             const Symbol_value<size>*,
-             unsigned char*,
-             Mips_address,
-             section_size_type);
-
-    inline bool
-    relocate(const Relocate_info<size, big_endian>*, Target_mips*,
-             Output_section*, size_t relnum,
-             const elfcpp::Rel<size, big_endian>&,
-             unsigned int, const Sized_symbol<size>*,
-             const Symbol_value<size>*,
-             unsigned char*,
-             Mips_address,
-             section_size_type);
-
-    inline bool
-    relocate(const Relocate_info<size, big_endian>*, Target_mips*,
-             Output_section*, size_t relnum,
-             const elfcpp::Rela<size, big_endian>&,
-             unsigned int, const Sized_symbol<size>*,
-             const Symbol_value<size>*,
-             unsigned char*,
-             Mips_address,
-             section_size_type);
+    relocate(const Relocate_info<size, big_endian>*, unsigned int,
+            Target_mips*, Output_section*, size_t, const unsigned char*,
+            const Sized_symbol<size>*, const Symbol_value<size>*,
+            unsigned char*, Mips_address, section_size_type);
   };
 
   // A class which returns the size required for a relocation type,
       view,
       address,
       view_size,
-     reloc_symbol_changes);
+      reloc_symbol_changes);
 }
 
 // Return the size of a relocation while scanning during a relocatable
                         Output_section* output_section,
                         typename elfcpp::Elf_types<size>::Elf_Off
                           offset_in_output_section,
-                        const Relocatable_relocs* rr,
                         unsigned char* view,
                         Mips_address view_address,
                         section_size_type view_size,
     reloc_count,
     output_section,
     offset_in_output_section,
-    rr,
     view,
     view_address,
     view_size,
 inline bool
 Target_mips<size, big_endian>::Relocate::relocate(
                         const Relocate_info<size, big_endian>* relinfo,
+                        unsigned int rel_type,
                         Target_mips* target,
                         Output_section* output_section,
                         size_t relnum,
-                        const elfcpp::Rela<size, big_endian>* rela,
-                        const elfcpp::Rel<size, big_endian>* rel,
-                        unsigned int rel_type,
-                        unsigned int r_type,
+                        const unsigned char* preloc,
                         const Sized_symbol<size>* gsym,
                         const Symbol_value<size>* psymval,
                         unsigned char* view,
 
   if (rel_type == elfcpp::SHT_RELA)
     {
-      r_offset = rela->get_r_offset();
-      r_info = rela->get_r_info();
-      r_addend = rela->get_r_addend();
+      const elfcpp::Rela<size, big_endian> rela(preloc);
+      r_offset = rela.get_r_offset();
+      r_info = rela.get_r_info();
+      r_addend = rela.get_r_addend();
     }
   else
     {
-      r_offset = rel->get_r_offset();
-      r_info = rel->get_r_info();
+      const elfcpp::Rel<size, big_endian> rel(preloc);
+      r_offset = rel.get_r_offset();
+      r_info = rel.get_r_info();
       r_addend = 0;
     }
+  unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
 
   typedef Mips_relocate_functions<size, big_endian> Reloc_funcs;
   typename Reloc_funcs::Status reloc_status = Reloc_funcs::STATUS_OKAY;
   return true;
 }
 
-template<int size, bool big_endian>
-inline bool
-Target_mips<size, big_endian>::Relocate::relocate(
-                        const Relocate_info<size, big_endian>* relinfo,
-                        Target_mips* target,
-                        Output_section* output_section,
-                        size_t relnum,
-                        const elfcpp::Rela<size, big_endian>& reloc,
-                        unsigned int r_type,
-                        const Sized_symbol<size>* gsym,
-                        const Symbol_value<size>* psymval,
-                        unsigned char* view,
-                        Mips_address address,
-                        section_size_type view_size)
-{
-  return relocate(
-    relinfo,
-    target,
-    output_section,
-    relnum,
-    &reloc,
-    (const elfcpp::Rel<size, big_endian>*) NULL,
-    elfcpp::SHT_RELA,
-    r_type,
-    gsym,
-    psymval,
-    view,
-    address,
-    view_size);
-}
-
-template<int size, bool big_endian>
-inline bool
-Target_mips<size, big_endian>::Relocate::relocate(
-                        const Relocate_info<size, big_endian>* relinfo,
-                        Target_mips* target,
-                        Output_section* output_section,
-                        size_t relnum,
-                        const elfcpp::Rel<size, big_endian>& reloc,
-                        unsigned int r_type,
-                        const Sized_symbol<size>* gsym,
-                        const Symbol_value<size>* psymval,
-                        unsigned char* view,
-                        Mips_address address,
-                        section_size_type view_size)
-{
-  return relocate(
-    relinfo,
-    target,
-    output_section,
-    relnum,
-    (const elfcpp::Rela<size, big_endian>*) NULL,
-    &reloc,
-    elfcpp::SHT_REL,
-    r_type,
-    gsym,
-    psymval,
-    view,
-    address,
-    view_size);
-}
-
 // Get the Reference_flags for a particular relocation.
 
 template<int size, bool big_endian>
 
   unsigned int reloc_shndx;
   // Section header of relocation section.
   const unsigned char* reloc_shdr;
+  // Info about how relocs should be handled
+  Relocatable_relocs* rr;
   // Section index of section being relocated.
   unsigned int data_shndx;
   // Section header of data section.
 
                  Output_section* output_section,
                  typename elfcpp::Elf_types<size>::Elf_Off
                     offset_in_output_section,
-                 const Relocatable_relocs*,
                  unsigned char*,
                  Address view_address,
                  section_size_type,
     // Do a relocation.  Return false if the caller should not issue
     // any warnings about this relocation.
     inline bool
-    relocate(const Relocate_info<size, big_endian>*, Target_powerpc*,
-            Output_section*, size_t relnum,
-            const elfcpp::Rela<size, big_endian>&,
-            unsigned int r_type, const Sized_symbol<size>*,
-            const Symbol_value<size>*,
-            unsigned char*,
-            typename elfcpp::Elf_types<size>::Elf_Addr,
+    relocate(const Relocate_info<size, big_endian>*, unsigned int,
+            Target_powerpc*, Output_section*, size_t, const unsigned char*,
+            const Sized_symbol<size>*, const Symbol_value<size>*,
+            unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
             section_size_type);
   };
 
 inline bool
 Target_powerpc<size, big_endian>::Relocate::relocate(
     const Relocate_info<size, big_endian>* relinfo,
+    unsigned int,
     Target_powerpc* target,
     Output_section* os,
     size_t relnum,
-    const elfcpp::Rela<size, big_endian>& rela,
-    unsigned int r_type,
+    const unsigned char* preloc,
     const Sized_symbol<size>* gsym,
     const Symbol_value<size>* psymval,
     unsigned char* view,
   if (view == NULL)
     return true;
 
+  const elfcpp::Rela<size, big_endian> rela(preloc);
+  unsigned int r_type = elfcpp::elf_r_type<size>(rela.get_r_info());
   switch (this->maybe_skip_tls_get_addr_call(r_type, gsym))
     {
     case Track_tls::NOT_EXPECTED:
     size_t reloc_count,
     Output_section* output_section,
     typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
-    const Relocatable_relocs* rr,
     unsigned char*,
     Address view_address,
     section_size_type,
   bool zap_next = false;
   for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
     {
-      Relocatable_relocs::Reloc_strategy strategy = rr->strategy(i);
+      Relocatable_relocs::Reloc_strategy strategy = relinfo->rr->strategy(i);
       if (strategy == Relocatable_relocs::RELOC_DISCARD)
        continue;
 
 
                                     &reloc_map);
        }
 
+      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())
-           {
-             Relocatable_relocs* rr = this->relocatable_relocs(i);
-             target->relocate_relocs(&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);
          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_relocs(&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);
     }
 }
 
 
     return static_cast<Reloc_strategy>(this->reloc_strategies_[i]);
   }
 
+  // Set the strategy for reloc I.
+  void
+  set_strategy(unsigned int i, Reloc_strategy strategy)
+  {
+    gold_assert(i < this->reloc_strategies_.size());
+    this->reloc_strategies_[i] = strategy;
+  }
+
   // Return the number of relocations to create in the output file.
   size_t
   output_reloc_count() const
 
       size_t reloc_count,
       Output_section* output_section,
       typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
-      const Relocatable_relocs*,
       unsigned char* view,
       typename elfcpp::Elf_types<size>::Elf_Addr view_address,
       section_size_type view_size,
     // Do a relocation.  Return false if the caller should not issue
     // any warnings about this relocation.
     inline bool
-    relocate(const Relocate_info<size, true>*, Target_s390*,
-            Output_section*,
-            size_t relnum, const elfcpp::Rela<size, true>&,
-            unsigned int r_type, const Sized_symbol<size>*,
-            const Symbol_value<size>*,
+    relocate(const Relocate_info<size, true>*, unsigned int,
+            Target_s390*, Output_section*, size_t, const unsigned char*,
+            const Sized_symbol<size>*, const Symbol_value<size>*,
             unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
             section_size_type);
 
 inline bool
 Target_s390<size>::Relocate::relocate(
     const Relocate_info<size, true>* relinfo,
+    unsigned int,
     Target_s390<size>* target,
     Output_section*,
     size_t relnum,
-    const elfcpp::Rela<size, true>& rela,
-    unsigned int r_type,
+    const unsigned char* preloc,
     const Sized_symbol<size>* gsym,
     const Symbol_value<size>* psymval,
     unsigned char* view,
   if (view == NULL)
     return true;
 
+  const elfcpp::Rela<size, true> rela(preloc);
+  unsigned int r_type = elfcpp::elf_r_type<size>(rela.get_r_info());
   const Sized_relobj_file<size, true>* object = relinfo->object;
 
   // Pick the value to use for symbols defined in the PLT.
     size_t reloc_count,
     Output_section* output_section,
     typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
-    const Relocatable_relocs* rr,
     unsigned char* view,
     typename elfcpp::Elf_types<size>::Elf_Addr view_address,
     section_size_type view_size,
     reloc_count,
     output_section,
     offset_in_output_section,
-    rr,
     view,
     view_address,
     view_size,
 
                  Output_section* output_section,
                  typename elfcpp::Elf_types<size>::Elf_Off
                     offset_in_output_section,
-                 const Relocatable_relocs*,
                  unsigned char* view,
                  typename elfcpp::Elf_types<size>::Elf_Addr view_address,
                  section_size_type view_size,
     // Do a relocation.  Return false if the caller should not issue
     // any warnings about this relocation.
     inline bool
-    relocate(const Relocate_info<size, big_endian>*, Target_sparc*,
-            Output_section*, size_t relnum,
-            const elfcpp::Rela<size, big_endian>&,
-            unsigned int r_type, const Sized_symbol<size>*,
-            const Symbol_value<size>*,
-            unsigned char*,
-            typename elfcpp::Elf_types<size>::Elf_Addr,
+    relocate(const Relocate_info<size, big_endian>*, unsigned int,
+            Target_sparc*, Output_section*, size_t, const unsigned char*,
+            const Sized_symbol<size>*, const Symbol_value<size>*,
+            unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
             section_size_type);
 
    private:
 inline bool
 Target_sparc<size, big_endian>::Relocate::relocate(
                        const Relocate_info<size, big_endian>* relinfo,
+                       unsigned int,
                        Target_sparc* target,
                        Output_section*,
                        size_t relnum,
-                       const elfcpp::Rela<size, big_endian>& rela,
-                       unsigned int r_type,
+                       const unsigned char* preloc,
                        const Sized_symbol<size>* gsym,
                        const Symbol_value<size>* psymval,
                        unsigned char* view,
                        typename elfcpp::Elf_types<size>::Elf_Addr address,
                        section_size_type view_size)
 {
+  const elfcpp::Rela<size, big_endian> rela(preloc);
+  unsigned int r_type = elfcpp::elf_r_type<size>(rela.get_r_info());
   bool orig_is_ifunc = psymval->is_ifunc_symbol();
   r_type &= 0xff;
 
     size_t reloc_count,
     Output_section* output_section,
     typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
-    const Relocatable_relocs* rr,
     unsigned char* view,
     typename elfcpp::Elf_types<size>::Elf_Addr view_address,
     section_size_type view_size,
     reloc_count,
     output_section,
     offset_in_output_section,
-    rr,
     view,
     view_address,
     view_size,
 
 
       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_type = elfcpp::elf_r_type<size>(r_info);
 
       const Sized_symbol<size>* sym;
 
       if (offset < 0 || static_cast<section_size_type>(offset) >= view_size)
        v = NULL;
 
-      if (!relocate.relocate(relinfo, target, output_section, i, reloc,
-                            r_type, sym, psymval, v, view_address + offset,
-                            view_size))
+      if (!relocate.relocate(relinfo, sh_type, target, output_section,
+                            i, prelocs, sym, psymval,
+                            v, view_address + offset, view_size))
        continue;
 
       if (v == NULL)
   // Construct the ELF relocation in a temporary buffer.
   const int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
   unsigned char relbuf[reloc_size];
-  elfcpp::Rela<size, big_endian> rel(relbuf);
   elfcpp::Rela_write<size, big_endian> orel(relbuf);
   orel.put_r_offset(r_offset);
   orel.put_r_info(elfcpp::elf_r_info<size>(0, r_type));
     symval.set_is_ifunc_symbol();
 
   Relocate relocate;
-  relocate.relocate(relinfo, target, NULL, -1U, rel, r_type, sym, &symval,
+  relocate.relocate(relinfo, elfcpp::SHT_RELA, target, NULL,
+                   -1U, relbuf, sym, &symval,
                    view + r_offset, address + r_offset, view_size);
 }
 
     size_t reloc_count,
     Output_section* output_section,
     typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
-    const Relocatable_relocs* rr,
     unsigned char* view,
     typename elfcpp::Elf_types<size>::Elf_Addr view_address,
     section_size_type view_size,
 
   for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
     {
-      Relocatable_relocs::Reloc_strategy strategy = rr->strategy(i);
+      Relocatable_relocs::Reloc_strategy strategy = relinfo->rr->strategy(i);
       if (strategy == Relocatable_relocs::RELOC_DISCARD)
        continue;
 
 
                  Output_section* output_section,
                  typename elfcpp::Elf_types<size>::Elf_Off
                     offset_in_output_section,
-                 const Relocatable_relocs*,
                  unsigned char* view,
                  typename elfcpp::Elf_types<size>::Elf_Addr view_address,
                  section_size_type view_size,
 
   relocate_relocs(const Relocate_info<size, big_endian>*,
                  unsigned int, const unsigned char*, size_t,
                  Output_section*, typename elfcpp::Elf_types<size>::Elf_Off,
-                  const Relocatable_relocs*, unsigned char*,
+                 unsigned char*,
                  typename elfcpp::Elf_types<size>::Elf_Addr,
                  section_size_type, unsigned char*,
                  section_size_type)
 
       size_t reloc_count,
       Output_section* output_section,
       typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
-      const Relocatable_relocs*,
       unsigned char* view,
       typename elfcpp::Elf_types<size>::Elf_Addr view_address,
       section_size_type view_size,
     // Do a relocation.  Return false if the caller should not issue
     // any warnings about this relocation.
     inline bool
-    relocate(const Relocate_info<size, big_endian>*, Target_tilegx*,
-             Output_section*,
-             size_t relnum, const elfcpp::Rela<size, big_endian>&,
-             unsigned int r_type, const Sized_symbol<size>*,
-             const Symbol_value<size>*,
-             unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
-             section_size_type);
+    relocate(const Relocate_info<size, big_endian>*, unsigned int,
+            Target_tilegx*, Output_section*, size_t, const unsigned char*,
+            const Sized_symbol<size>*, const Symbol_value<size>*,
+            unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
+            section_size_type);
   };
 
   // A class which returns the size required for a relocation type,
 inline bool
 Target_tilegx<size, big_endian>::Relocate::relocate(
     const Relocate_info<size, big_endian>* relinfo,
+    unsigned int,
     Target_tilegx<size, big_endian>* target,
     Output_section*,
     size_t relnum,
-    const elfcpp::Rela<size, big_endian>& rela,
-    unsigned int r_type,
+    const unsigned char* preloc,
     const Sized_symbol<size>* gsym,
     const Symbol_value<size>* psymval,
     unsigned char* view,
   typedef Tilegx_relocate_functions<size, big_endian> TilegxReloc;
   typename TilegxReloc::Tilegx_howto r_howto;
 
+  const elfcpp::Rela<size, big_endian> rela(preloc);
+  unsigned int r_type = elfcpp::elf_r_type<size>(rela.get_r_info());
   const Sized_relobj_file<size, big_endian>* object = relinfo->object;
 
   // Pick the value to use for symbols defined in the PLT.
     size_t reloc_count,
     Output_section* output_section,
     typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
-    const Relocatable_relocs* rr,
     unsigned char* view,
     typename elfcpp::Elf_types<size>::Elf_Addr view_address,
     section_size_type view_size,
     reloc_count,
     output_section,
     offset_in_output_section,
-    rr,
     view,
     view_address,
     view_size,
 
       size_t reloc_count,
       Output_section* output_section,
       typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
-      const Relocatable_relocs*,
       unsigned char* view,
       typename elfcpp::Elf_types<size>::Elf_Addr view_address,
       section_size_type view_size,
     // Do a relocation.  Return false if the caller should not issue
     // any warnings about this relocation.
     inline bool
-    relocate(const Relocate_info<size, false>*, Target_x86_64*,
-            Output_section*,
-            size_t relnum, const elfcpp::Rela<size, false>&,
-            unsigned int r_type, const Sized_symbol<size>*,
-            const Symbol_value<size>*,
+    relocate(const Relocate_info<size, false>*, unsigned int,
+            Target_x86_64*, Output_section*, size_t, const unsigned char*,
+            const Sized_symbol<size>*, const Symbol_value<size>*,
             unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
             section_size_type);
 
 inline bool
 Target_x86_64<size>::Relocate::relocate(
     const Relocate_info<size, false>* relinfo,
+    unsigned int,
     Target_x86_64<size>* target,
     Output_section*,
     size_t relnum,
-    const elfcpp::Rela<size, false>& rela,
-    unsigned int r_type,
+    const unsigned char* preloc,
     const Sized_symbol<size>* gsym,
     const Symbol_value<size>* psymval,
     unsigned char* view,
     typename elfcpp::Elf_types<size>::Elf_Addr address,
     section_size_type view_size)
 {
+  const elfcpp::Rela<size, false> rela(preloc);
+  unsigned int r_type = elfcpp::elf_r_type<size>(rela.get_r_info());
+
   if (this->skip_call_tls_get_addr_)
     {
       if ((r_type != elfcpp::R_X86_64_PLT32
     size_t reloc_count,
     Output_section* output_section,
     typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
-    const Relocatable_relocs* rr,
     unsigned char* view,
     typename elfcpp::Elf_types<size>::Elf_Addr view_address,
     section_size_type view_size,
     reloc_count,
     output_section,
     offset_in_output_section,
-    rr,
     view,
     view_address,
     view_size,