Refactor gold to enable support for MIPS-64 relocation format.
authorCary Coutant <ccoutant@gmail.com>
Fri, 11 Dec 2015 15:43:59 +0000 (07:43 -0800)
committerCary Coutant <ccoutant@gmail.com>
Tue, 12 Jan 2016 02:51:18 +0000 (18:51 -0800)
For MIPS-64, the r_info field in the relocation format is
replaced by several individual fields, including r_sym and
r_type. To enable support for this format, I've refactored
target-independent code to remove almost all uses of the r_info
field. (I've left alone a couple of routines used only for
incremental linking, which I can update if/when the MIPS target
adds support for incremental linking.)

For routines that are already templated on a Classify_reloc class
(namely, gc_process_relocs, relocate_section, and
relocate_relocs), I've extended the Classify_reloc interface to
include sh_type (which no longer needs to be a separate template
parameter) as well as get_r_sym() and get_r_type() methods for
extracting the r_sym and r_type fields. For
scan_relocatable_relocs, I've extended the
Default_scan_relocatable_relocs class by converting it to a class
template with Classify_reloc as a template parameter. For the
remaining routines that need to access r_sym, I've added a
virtual Target::get_r_sym() method with an override for the MIPS
target.

In elfcpp, I've added Mips64_rel, etc., accessor classes and
corresponding internal data structures. The MIPS target uses
these new classes within its own Mips_classify_reloc class.
The Mips64_ accessor classes also expose the r_ssym, r_type2,
and r_type3 fields from the relocation.

These changes should be functionally the same for all but the
MIPS target.

elfcpp/
* elfcpp.h (Mips64_rel, Mips64_rel_write): New classes.
(Mips64_rela, Mips64_rela_write): New classes.
* elfcpp_internal.h (Mips64_rel_data, Mips64_rela_data): New structs.

gold/
* gc.h (get_embedded_addend_size): Remove sh_type parameter.
(gc_process_relocs): Remove sh_type template parameter.
Use Classify_reloc to access r_sym, r_type, and r_addend fields.
* object.h (Sized_relobj_file::split_stack_adjust): Add target
parameter.
(Sized_relobj_file::split_stack_adjust_reltype): Likewise.
* reloc-types.h (Reloc_types::copy_reloc_addend): (SHT_REL and SHT_RELA
specializations) Remove.
* reloc.cc (Emit_relocs_strategy): Rename and move to target-reloc.h.
(Sized_relobj_file::emit_relocs_scan): Call Target::emit_relocs_scan().
(Sized_relobj_file::emit_relocs_scan_reltype): Remove.
(Sized_relobj_file::split_stack_adjust): Add target parameter.
Adjust all callers.
(Sized_relobj_file::split_stack_adjust_reltype): Likewise. Call
Target::get_r_sym() to get r_sym field from relocations.
(Track_relocs::next_symndx): Call Target::get_r_sym().
* target-reloc.h (scan_relocs): Remove sh_type template parameter;
add Classify_reloc template parameter.  Use for accessing r_sym and
r_type.
(relocate_section): Likewise.
(Default_classify_reloc): New class (renamed and moved from reloc.cc).
(Default_scan_relocatable_relocs): Remove sh_type template parameter.
(Default_scan_relocatable_relocs::Reltype): New typedef.
(Default_scan_relocatable_relocs::reloc_size): New const.
(Default_scan_relocatable_relocs::sh_type): New const.
(Default_scan_relocatable_relocs::get_r_sym): New method.
(Default_scan_relocatable_relocs::get_r_type): New method.
(Default_emit_relocs_strategy): New class.
(scan_relocatable_relocs): Replace sh_type template parameter with
Scan_relocatable_relocs class.  Use it to access r_sym and r_type
fields.
(relocate_relocs): Replace sh_type template parameter with
Classify_reloc class.  Use it to access r_sym and r_type fields.
* target.h (Target::is_call_to_non_split): Replace r_type parameter
with pointer to relocation. Adjust all callers.
(Target::do_is_call_to_non_split): Likewise.
(Target::emit_relocs_scan): New virtual method.
(Sized_target::get_r_sym): New virtual method.
* target.cc (Target::do_is_call_to_non_split): Replace r_type parameter
with pointer to relocation.

* aarch64.cc (Target_aarch64::emit_relocs_scan): New method.
(Target_aarch64::Relocatable_size_for_reloc): Remove.
(Target_aarch64::gc_process_relocs): Use Default_classify_reloc.
(Target_aarch64::scan_relocs): Likewise.
(Target_aarch64::relocate_section): Likewise.
(Target_aarch64::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_aarch64::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_aarch64::relocate_relocs): Use Default_classify_reloc.
* arm.cc (Target_arm::Arm_scan_relocatable_relocs): Remove sh_type
template parameter.
(Target_arm::emit_relocs_scan): New method.
(Target_arm::Relocatable_size_for_reloc): Replace with...
(Target_arm::Classify_reloc): ...this.
(Target_arm::gc_process_relocs): Use Classify_reloc.
(Target_arm::scan_relocs): Likewise.
(Target_arm::relocate_section): Likewise.
(Target_arm::scan_relocatable_relocs): Likewise.
(Target_arm::relocate_relocs): Likewise.
* i386.cc (Target_i386::emit_relocs_scan): New method.
(Target_i386::Relocatable_size_for_reloc): Replace with...
(Target_i386::Classify_reloc): ...this.
(Target_i386::gc_process_relocs): Use Classify_reloc.
(Target_i386::scan_relocs): Likewise.
(Target_i386::relocate_section): Likewise.
(Target_i386::scan_relocatable_relocs): Likewise.
(Target_i386::relocate_relocs): Likewise.
* mips.cc (Mips_scan_relocatable_relocs): Remove sh_type template
parameter.
(Mips_reloc_types): New class template.
(Mips_classify_reloc): New class template.
(Target_mips::Reltype): New typedef.
(Target_mips::Relatype): New typedef.
(Target_mips::emit_relocs_scan): New method.
(Target_mips::get_r_sym): New method.
(Target_mips::Relocatable_size_for_reloc): Replace with
Mips_classify_reloc.
(Target_mips::copy_reloc): Use Mips_classify_reloc.
(Target_mips::gc_process_relocs): Likewise.
(Target_mips::scan_relocs): Likewise.
(Target_mips::relocate_section): Likewise.
(Target_mips::scan_relocatable_relocs): Likewise.
(Target_mips::relocate_relocs): Likewise.
(mips_get_size_for_reloc): New function, factored out from
Relocatable_size_for_reloc::get_size_for_reloc.
(Target_mips::Scan::local): Use Mips_classify_reloc.
(Target_mips::Scan::global): Likewise.
(Target_mips::Relocate::relocate): Likewise.
* powerpc.cc (Target_powerpc::emit_relocs_scan): New method.
(Target_powerpc::Relocatable_size_for_reloc): Remove.
(Target_powerpc::gc_process_relocs): Use Default_classify_reloc.
(Target_powerpc::scan_relocs): Likewise.
(Target_powerpc::relocate_section): Likewise.
(Powerpc_scan_relocatable_reloc): Convert to class template.
(Powerpc_scan_relocatable_reloc::Reltype): New typedef.
(Powerpc_scan_relocatable_reloc::reloc_size): New const.
(Powerpc_scan_relocatable_reloc::sh_type): New const.
(Powerpc_scan_relocatable_reloc::get_r_sym): New method.
(Powerpc_scan_relocatable_reloc::get_r_type): New method.
(Target_powerpc::scan_relocatable_relocs): Use
Powerpc_scan_relocatable_reloc.
(Target_powerpc::relocate_relocs): Use Default_classify_reloc.
* s390.cc (Target_s390::emit_relocs_scan): New method.
(Target_s390::Relocatable_size_for_reloc): Remove.
(Target_s390::gc_process_relocs): Use Default_classify_reloc.
(Target_s390::scan_relocs): Likewise.
(Target_s390::relocate_section): Likewise.
(Target_s390::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_s390::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_s390::relocate_relocs): Use Default_classify_reloc.
* sparc.cc (Target_sparc::emit_relocs_scan): New method.
(Target_sparc::Relocatable_size_for_reloc): Remove.
(Target_sparc::gc_process_relocs): Use Default_classify_reloc.
(Target_sparc::scan_relocs): Likewise.
(Target_sparc::relocate_section): Likewise.
(Target_sparc::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_sparc::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_sparc::relocate_relocs): Use Default_classify_reloc.
* tilegx.cc (Target_tilegx::emit_relocs_scan): New method.
(Target_tilegx::Relocatable_size_for_reloc): Remove.
(Target_tilegx::gc_process_relocs): Use Default_classify_reloc.
(Target_tilegx::scan_relocs): Likewise.
(Target_tilegx::relocate_section): Likewise.
(Target_tilegx::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_tilegx::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_tilegx::relocate_relocs): Use Default_classify_reloc.
* x86_64.cc (Target_x86_64::emit_relocs_scan): New method.
(Target_x86_64::Relocatable_size_for_reloc): Remove.
(Target_x86_64::gc_process_relocs): Use Default_classify_reloc.
(Target_x86_64::scan_relocs): Likewise.
(Target_x86_64::relocate_section): Likewise.
(Target_x86_64::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_x86_64::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_x86_64::relocate_relocs): Use Default_classify_reloc.

* testsuite/testfile.cc (Target_test::emit_relocs_scan): New method.

21 files changed:
elfcpp/ChangeLog
elfcpp/elfcpp.h
elfcpp/elfcpp_internal.h
gold/ChangeLog
gold/aarch64.cc
gold/arm.cc
gold/gc.h
gold/i386.cc
gold/mips.cc
gold/object.h
gold/powerpc.cc
gold/reloc-types.h
gold/reloc.cc
gold/s390.cc
gold/sparc.cc
gold/target-reloc.h
gold/target.cc
gold/target.h
gold/testsuite/testfile.cc
gold/tilegx.cc
gold/x86_64.cc

index e48be00308d5a73e340cc3be633351a7f4e0a2e1..198eb9232d3d6fbff97cd192dfe5585b1ebcbb37 100644 (file)
@@ -1,3 +1,9 @@
+2016-01-11  Cary Coutant  <ccoutant@gmail.com>
+
+       * elfcpp.h (Mips64_rel, Mips64_rel_write): New classes.
+       (Mips64_rela, Mips64_rela_write): New classes.
+       * elfcpp_internal.h (Mips64_rel_data, Mips64_rela_data): New structs.
+
 2016-01-01  Alan Modra  <amodra@gmail.com>
 
        Update year range in copyright notice of all files.
index e0eae42e77bf54248e4da50b13c7cc386dced2ec..3d7039a33bd674698c086169a2d8ac2268d646d7 100644 (file)
@@ -1661,6 +1661,172 @@ class Rela_write
   internal::Rela_data<size>* p_;
 };
 
+// MIPS-64 has a non-standard relocation layout.
+
+template<bool big_endian>
+class Mips64_rel
+{
+ public:
+  Mips64_rel(const unsigned char* p)
+    : p_(reinterpret_cast<const internal::Mips64_rel_data*>(p))
+  { }
+
+  template<typename File>
+  Mips64_rel(File* file, typename File::Location loc)
+    : p_(reinterpret_cast<const internal::Mips64_rel_data*>(
+          file->view(loc.file_offset, loc.data_size).data()))
+  { }
+
+  typename Elf_types<64>::Elf_Addr
+  get_r_offset() const
+  { return Convert<64, big_endian>::convert_host(this->p_->r_offset); }
+
+  Elf_Word
+  get_r_sym() const
+  { return Convert<32, big_endian>::convert_host(this->p_->r_sym); }
+
+  unsigned char
+  get_r_ssym() const
+  { return this->p_->r_ssym; }
+
+  unsigned char
+  get_r_type() const
+  { return this->p_->r_type; }
+
+  unsigned char
+  get_r_type2() const
+  { return this->p_->r_type2; }
+
+  unsigned char
+  get_r_type3() const
+  { return this->p_->r_type3; }
+
+ private:
+  const internal::Mips64_rel_data* p_;
+};
+
+template<bool big_endian>
+class Mips64_rel_write
+{
+ public:
+  Mips64_rel_write(unsigned char* p)
+    : p_(reinterpret_cast<internal::Mips64_rel_data*>(p))
+  { }
+
+  void
+  put_r_offset(typename Elf_types<64>::Elf_Addr v)
+  { this->p_->r_offset = Convert<64, big_endian>::convert_host(v); }
+
+  void
+  put_r_sym(Elf_Word v)
+  { this->p_->r_sym = Convert<32, big_endian>::convert_host(v); }
+
+  void
+  put_r_ssym(unsigned char v)
+  { this->p_->r_ssym = v; }
+
+  void
+  put_r_type(unsigned char v)
+  { this->p_->r_type = v; }
+
+  void
+  put_r_type2(unsigned char v)
+  { this->p_->r_type2 = v; }
+
+  void
+  put_r_type3(unsigned char v)
+  { this->p_->r_type3 = v; }
+
+ private:
+  internal::Mips64_rel_data* p_;
+};
+
+template<bool big_endian>
+class Mips64_rela
+{
+ public:
+  Mips64_rela(const unsigned char* p)
+    : p_(reinterpret_cast<const internal::Mips64_rela_data*>(p))
+  { }
+
+  template<typename File>
+  Mips64_rela(File* file, typename File::Location loc)
+    : p_(reinterpret_cast<const internal::Mips64_rela_data*>(
+          file->view(loc.file_offset, loc.data_size).data()))
+  { }
+
+  typename Elf_types<64>::Elf_Addr
+  get_r_offset() const
+  { return Convert<64, big_endian>::convert_host(this->p_->r_offset); }
+
+  Elf_Word
+  get_r_sym() const
+  { return Convert<32, big_endian>::convert_host(this->p_->r_sym); }
+
+  unsigned char
+  get_r_ssym() const
+  { return this->p_->r_ssym; }
+
+  unsigned char
+  get_r_type() const
+  { return this->p_->r_type; }
+
+  unsigned char
+  get_r_type2() const
+  { return this->p_->r_type2; }
+
+  unsigned char
+  get_r_type3() const
+  { return this->p_->r_type3; }
+
+  typename Elf_types<64>::Elf_Swxword
+  get_r_addend() const
+  { return Convert<64, big_endian>::convert_host(this->p_->r_addend); }
+
+ private:
+  const internal::Mips64_rela_data* p_;
+};
+
+template<bool big_endian>
+class Mips64_rela_write
+{
+ public:
+  Mips64_rela_write(unsigned char* p)
+    : p_(reinterpret_cast<internal::Mips64_rela_data*>(p))
+  { }
+
+  void
+  put_r_offset(typename Elf_types<64>::Elf_Addr v)
+  { this->p_->r_offset = Convert<64, big_endian>::convert_host(v); }
+
+  void
+  put_r_sym(Elf_Word v)
+  { this->p_->r_sym = Convert<32, big_endian>::convert_host(v); }
+
+  void
+  put_r_ssym(unsigned char v)
+  { this->p_->r_ssym = v; }
+
+  void
+  put_r_type(unsigned char v)
+  { this->p_->r_type = v; }
+
+  void
+  put_r_type2(unsigned char v)
+  { this->p_->r_type2 = v; }
+
+  void
+  put_r_type3(unsigned char v)
+  { this->p_->r_type3 = v; }
+
+  void
+  put_r_addend(typename Elf_types<64>::Elf_Swxword v)
+  { this->p_->r_addend = Convert<64, big_endian>::convert_host(v); }
+
+ private:
+  internal::Mips64_rela_data* p_;
+};
+
 // Accessor classes for entries in the ELF SHT_DYNAMIC section aka
 // PT_DYNAMIC segment.
 
index 7080a2d9ac774778e516b509997a54708f8e080b..edca55fabd19aa5a145c15e90fcb2bb3985e74cb 100644 (file)
@@ -180,6 +180,29 @@ struct Rela_data
   typename Elf_types<size>::Elf_Swxword r_addend;
 };
 
+// MIPS-64 has a non-standard layout for relocations.
+
+struct Mips64_rel_data
+{
+  typename Elf_types<64>::Elf_Addr r_offset;
+  Elf_Word r_sym;
+  unsigned char r_ssym;
+  unsigned char r_type3;
+  unsigned char r_type2;
+  unsigned char r_type;
+};
+
+struct Mips64_rela_data
+{
+  typename Elf_types<64>::Elf_Addr r_offset;
+  Elf_Word r_sym;
+  unsigned char r_ssym;
+  unsigned char r_type3;
+  unsigned char r_type2;
+  unsigned char r_type;
+  typename Elf_types<64>::Elf_Swxword r_addend;
+};
+
 // An entry in the ELF SHT_DYNAMIC section aka PT_DYNAMIC segment.
 
 template<int size>
index e48be00308d5a73e340cc3be633351a7f4e0a2e1..42c428bbb82fe82ab627506f738465a37d18058a 100644 (file)
@@ -1,3 +1,149 @@
+2016-01-11  Cary Coutant  <ccoutant@gmail.com>
+
+       Refactor gold to enable support for MIPS-64 relocation format.
+
+       * gc.h (get_embedded_addend_size): Remove sh_type parameter.
+       (gc_process_relocs): Remove sh_type template parameter.
+       Use Classify_reloc to access r_sym, r_type, and r_addend fields.
+       * object.h (Sized_relobj_file::split_stack_adjust): Add target
+       parameter.
+       (Sized_relobj_file::split_stack_adjust_reltype): Likewise.
+       * reloc-types.h (Reloc_types::copy_reloc_addend): (SHT_REL and SHT_RELA
+       specializations) Remove.
+       * reloc.cc (Emit_relocs_strategy): Rename and move to target-reloc.h.
+       (Sized_relobj_file::emit_relocs_scan): Call Target::emit_relocs_scan().
+       (Sized_relobj_file::emit_relocs_scan_reltype): Remove.
+       (Sized_relobj_file::split_stack_adjust): Add target parameter.
+       Adjust all callers.
+       (Sized_relobj_file::split_stack_adjust_reltype): Likewise. Call
+       Target::get_r_sym() to get r_sym field from relocations.
+       (Track_relocs::next_symndx): Call Target::get_r_sym().
+       * target-reloc.h (scan_relocs): Remove sh_type template parameter;
+       add Classify_reloc template parameter.  Use for accessing r_sym and
+       r_type.
+       (relocate_section): Likewise.
+       (Default_classify_reloc): New class (renamed and moved from reloc.cc).
+       (Default_scan_relocatable_relocs): Remove sh_type template parameter.
+       (Default_scan_relocatable_relocs::Reltype): New typedef.
+       (Default_scan_relocatable_relocs::reloc_size): New const.
+       (Default_scan_relocatable_relocs::sh_type): New const.
+       (Default_scan_relocatable_relocs::get_r_sym): New method.
+       (Default_scan_relocatable_relocs::get_r_type): New method.
+       (Default_emit_relocs_strategy): New class.
+       (scan_relocatable_relocs): Replace sh_type template parameter with
+       Scan_relocatable_relocs class.  Use it to access r_sym and r_type
+       fields.
+       (relocate_relocs): Replace sh_type template parameter with
+       Classify_reloc class.  Use it to access r_sym and r_type fields.
+       * target.h (Target::is_call_to_non_split): Replace r_type parameter
+       with pointer to relocation. Adjust all callers.
+       (Target::do_is_call_to_non_split): Likewise.
+       (Target::emit_relocs_scan): New virtual method.
+       (Sized_target::get_r_sym): New virtual method.
+       * target.cc (Target::do_is_call_to_non_split): Replace r_type parameter
+       with pointer to relocation.
+
+       * aarch64.cc (Target_aarch64::emit_relocs_scan): New method.
+       (Target_aarch64::Relocatable_size_for_reloc): Remove.
+       (Target_aarch64::gc_process_relocs): Use Default_classify_reloc.
+       (Target_aarch64::scan_relocs): Likewise.
+       (Target_aarch64::relocate_section): Likewise.
+       (Target_aarch64::Relocatable_size_for_reloc::get_size_for_reloc):
+       Remove.
+       (Target_aarch64::scan_relocatable_relocs): Use Default_classify_reloc.
+       (Target_aarch64::relocate_relocs): Use Default_classify_reloc.
+       * arm.cc (Target_arm::Arm_scan_relocatable_relocs): Remove sh_type
+       template parameter.
+       (Target_arm::emit_relocs_scan): New method.
+       (Target_arm::Relocatable_size_for_reloc): Replace with...
+       (Target_arm::Classify_reloc): ...this.
+       (Target_arm::gc_process_relocs): Use Classify_reloc.
+       (Target_arm::scan_relocs): Likewise.
+       (Target_arm::relocate_section): Likewise.
+       (Target_arm::scan_relocatable_relocs): Likewise.
+       (Target_arm::relocate_relocs): Likewise.
+       * i386.cc (Target_i386::emit_relocs_scan): New method.
+       (Target_i386::Relocatable_size_for_reloc): Replace with...
+       (Target_i386::Classify_reloc): ...this.
+       (Target_i386::gc_process_relocs): Use Classify_reloc.
+       (Target_i386::scan_relocs): Likewise.
+       (Target_i386::relocate_section): Likewise.
+       (Target_i386::scan_relocatable_relocs): Likewise.
+       (Target_i386::relocate_relocs): Likewise.
+       * mips.cc (Mips_scan_relocatable_relocs): Remove sh_type template
+       parameter.
+       (Mips_reloc_types): New class template.
+       (Mips_classify_reloc): New class template.
+       (Target_mips::Reltype): New typedef.
+       (Target_mips::Relatype): New typedef.
+       (Target_mips::emit_relocs_scan): New method.
+       (Target_mips::get_r_sym): New method.
+       (Target_mips::Relocatable_size_for_reloc): Replace with
+       Mips_classify_reloc.
+       (Target_mips::copy_reloc): Use Mips_classify_reloc.
+       (Target_mips::gc_process_relocs): Likewise.
+       (Target_mips::scan_relocs): Likewise.
+       (Target_mips::relocate_section): Likewise.
+       (Target_mips::scan_relocatable_relocs): Likewise.
+       (Target_mips::relocate_relocs): Likewise.
+       (mips_get_size_for_reloc): New function, factored out from
+       Relocatable_size_for_reloc::get_size_for_reloc.
+       (Target_mips::Scan::local): Use Mips_classify_reloc.
+       (Target_mips::Scan::global): Likewise.
+       (Target_mips::Relocate::relocate): Likewise.
+       * powerpc.cc (Target_powerpc::emit_relocs_scan): New method.
+       (Target_powerpc::Relocatable_size_for_reloc): Remove.
+       (Target_powerpc::gc_process_relocs): Use Default_classify_reloc.
+       (Target_powerpc::scan_relocs): Likewise.
+       (Target_powerpc::relocate_section): Likewise.
+       (Powerpc_scan_relocatable_reloc): Convert to class template.
+       (Powerpc_scan_relocatable_reloc::Reltype): New typedef.
+       (Powerpc_scan_relocatable_reloc::reloc_size): New const.
+       (Powerpc_scan_relocatable_reloc::sh_type): New const.
+       (Powerpc_scan_relocatable_reloc::get_r_sym): New method.
+       (Powerpc_scan_relocatable_reloc::get_r_type): New method.
+       (Target_powerpc::scan_relocatable_relocs): Use
+       Powerpc_scan_relocatable_reloc.
+       (Target_powerpc::relocate_relocs): Use Default_classify_reloc.
+       * s390.cc (Target_s390::emit_relocs_scan): New method.
+       (Target_s390::Relocatable_size_for_reloc): Remove.
+       (Target_s390::gc_process_relocs): Use Default_classify_reloc.
+       (Target_s390::scan_relocs): Likewise.
+       (Target_s390::relocate_section): Likewise.
+       (Target_s390::Relocatable_size_for_reloc::get_size_for_reloc):
+       Remove.
+       (Target_s390::scan_relocatable_relocs): Use Default_classify_reloc.
+       (Target_s390::relocate_relocs): Use Default_classify_reloc.
+       * sparc.cc (Target_sparc::emit_relocs_scan): New method.
+       (Target_sparc::Relocatable_size_for_reloc): Remove.
+       (Target_sparc::gc_process_relocs): Use Default_classify_reloc.
+       (Target_sparc::scan_relocs): Likewise.
+       (Target_sparc::relocate_section): Likewise.
+       (Target_sparc::Relocatable_size_for_reloc::get_size_for_reloc):
+       Remove.
+       (Target_sparc::scan_relocatable_relocs): Use Default_classify_reloc.
+       (Target_sparc::relocate_relocs): Use Default_classify_reloc.
+       * tilegx.cc (Target_tilegx::emit_relocs_scan): New method.
+       (Target_tilegx::Relocatable_size_for_reloc): Remove.
+       (Target_tilegx::gc_process_relocs): Use Default_classify_reloc.
+       (Target_tilegx::scan_relocs): Likewise.
+       (Target_tilegx::relocate_section): Likewise.
+       (Target_tilegx::Relocatable_size_for_reloc::get_size_for_reloc):
+       Remove.
+       (Target_tilegx::scan_relocatable_relocs): Use Default_classify_reloc.
+       (Target_tilegx::relocate_relocs): Use Default_classify_reloc.
+       * x86_64.cc (Target_x86_64::emit_relocs_scan): New method.
+       (Target_x86_64::Relocatable_size_for_reloc): Remove.
+       (Target_x86_64::gc_process_relocs): Use Default_classify_reloc.
+       (Target_x86_64::scan_relocs): Likewise.
+       (Target_x86_64::relocate_section): Likewise.
+       (Target_x86_64::Relocatable_size_for_reloc::get_size_for_reloc):
+       Remove.
+       (Target_x86_64::scan_relocatable_relocs): Use Default_classify_reloc.
+       (Target_x86_64::relocate_relocs): Use Default_classify_reloc.
+
+       * testsuite/testfile.cc (Target_test::emit_relocs_scan): New method.
+
 2016-01-01  Alan Modra  <amodra@gmail.com>
 
        Update year range in copyright notice of all files.
index 715936b544a0e3843abaa6d4dab049bf2e9150b5..20f2f4f0099d5a25ee927ca10dfd19d285825b7c 100644 (file)
@@ -2869,6 +2869,21 @@ class Target_aarch64 : public Sized_target<size, big_endian>
                          const unsigned char* plocal_symbols,
                          Relocatable_relocs*);
 
+  // Scan the relocs for --emit-relocs.
+  void
+  emit_relocs_scan(Symbol_table* symtab,
+                  Layout* layout,
+                  Sized_relobj_file<size, big_endian>* object,
+                  unsigned int data_shndx,
+                  unsigned int sh_type,
+                  const unsigned char* prelocs,
+                  size_t reloc_count,
+                  Output_section* output_section,
+                  bool needs_special_offset_handling,
+                  size_t local_symbol_count,
+                  const unsigned char* plocal_syms,
+                  Relocatable_relocs* rr);
+
   // Relocate a section during a relocatable link.
   void
   relocate_relocs(
@@ -3224,15 +3239,6 @@ class Target_aarch64 : public Sized_target<size, big_endian>
 
   };  // End of class Relocate
 
-  // A class which returns the size required for a relocation type,
-  // used while scanning relocs during a relocatable link.
-  class Relocatable_size_for_reloc
-  {
-   public:
-    unsigned int
-    get_size_for_reloc(unsigned int, Relobj*);
-  };
-
   // Adjust TLS relocation type based on the options and whether this
   // is a local symbol.
   static tls::Tls_optimization
@@ -6630,17 +6636,16 @@ Target_aarch64<size, big_endian>::gc_process_relocs(
     size_t local_symbol_count,
     const unsigned char* plocal_symbols)
 {
+  typedef Target_aarch64<size, big_endian> Aarch64;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+
   if (sh_type == elfcpp::SHT_REL)
     {
       return;
     }
 
-  gold::gc_process_relocs<
-    size, big_endian,
-    Target_aarch64<size, big_endian>,
-    elfcpp::SHT_RELA,
-    typename Target_aarch64<size, big_endian>::Scan,
-    typename Target_aarch64<size, big_endian>::Relocatable_size_for_reloc>(
+  gold::gc_process_relocs<size, big_endian, Aarch64, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -6671,13 +6676,18 @@ Target_aarch64<size, big_endian>::scan_relocs(
     size_t local_symbol_count,
     const unsigned char* plocal_symbols)
 {
+  typedef Target_aarch64<size, big_endian> Aarch64;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+
   if (sh_type == elfcpp::SHT_REL)
     {
       gold_error(_("%s: unsupported REL reloc section"),
                 object->name().c_str());
       return;
     }
-  gold::scan_relocs<size, big_endian, Target_aarch64, elfcpp::SHT_RELA, Scan>(
+
+  gold::scan_relocs<size, big_endian, Aarch64, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -7868,10 +7878,15 @@ Target_aarch64<size, big_endian>::relocate_section(
     section_size_type view_size,
     const Reloc_symbol_changes* reloc_symbol_changes)
 {
-  gold_assert(sh_type == elfcpp::SHT_RELA);
+  typedef Target_aarch64<size, big_endian> Aarch64;
   typedef typename Target_aarch64<size, big_endian>::Relocate AArch64_relocate;
-  gold::relocate_section<size, big_endian, Target_aarch64, elfcpp::SHT_RELA,
-                        AArch64_relocate, gold::Default_comdat_behavior>(
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+
+  gold_assert(sh_type == elfcpp::SHT_RELA);
+
+  gold::relocate_section<size, big_endian, Aarch64, AArch64_relocate,
+                        gold::Default_comdat_behavior, Classify_reloc>(
     relinfo,
     this,
     prelocs,
@@ -7884,21 +7899,6 @@ Target_aarch64<size, big_endian>::relocate_section(
     reloc_symbol_changes);
 }
 
-// Return the size of a relocation while scanning during a relocatable
-// link.
-
-template<int size, bool big_endian>
-unsigned int
-Target_aarch64<size, big_endian>::Relocatable_size_for_reloc::
-get_size_for_reloc(
-    unsigned int ,
-    Relobj* )
-{
-  // We will never support SHT_REL relocations.
-  gold_unreachable();
-  return 0;
-}
-
 // Scan the relocs during a relocatable link.
 
 template<int size, bool big_endian>
@@ -7917,13 +7917,14 @@ Target_aarch64<size, big_endian>::scan_relocatable_relocs(
     const unsigned char* plocal_symbols,
     Relocatable_relocs* rr)
 {
-  gold_assert(sh_type == elfcpp::SHT_RELA);
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+  typedef gold::Default_scan_relocatable_relocs<Classify_reloc>
+      Scan_relocatable_relocs;
 
-  typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
-    Relocatable_size_for_reloc> Scan_relocatable_relocs;
+  gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::scan_relocatable_relocs<size, big_endian, elfcpp::SHT_RELA,
-      Scan_relocatable_relocs>(
+  gold::scan_relocatable_relocs<size, big_endian, Scan_relocatable_relocs>(
     symtab,
     layout,
     object,
@@ -7937,6 +7938,45 @@ Target_aarch64<size, big_endian>::scan_relocatable_relocs(
     rr);
 }
 
+// Scan the relocs for --emit-relocs.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::emit_relocs_scan(
+    Symbol_table* symtab,
+    Layout* layout,
+    Sized_relobj_file<size, big_endian>* object,
+    unsigned int data_shndx,
+    unsigned int sh_type,
+    const unsigned char* prelocs,
+    size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
+    size_t local_symbol_count,
+    const unsigned char* plocal_syms,
+    Relocatable_relocs* rr)
+{
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+  typedef gold::Default_emit_relocs_strategy<Classify_reloc>
+      Emit_relocs_strategy;
+
+  gold_assert(sh_type == elfcpp::SHT_RELA);
+
+  gold::scan_relocatable_relocs<size, big_endian, Emit_relocs_strategy>(
+    symtab,
+    layout,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_syms,
+    rr);
+}
+
 // Relocate a section during a relocatable link.
 
 template<int size, bool big_endian>
@@ -7954,9 +7994,12 @@ Target_aarch64<size, big_endian>::relocate_relocs(
     unsigned char* reloc_view,
     section_size_type reloc_view_size)
 {
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_relocs<size, big_endian, elfcpp::SHT_RELA>(
+  gold::relocate_relocs<size, big_endian, Classify_reloc>(
     relinfo,
     prelocs,
     reloc_count,
index c20eb6d364ff55cac44d8675c26a6cc1c1d0342a..4cd0b91320ac05b2640e334d39148103216ea3d4 100644 (file)
@@ -2040,9 +2040,9 @@ class Arm_output_data_got : public Output_data_got<32, big_endian>
 // bits.  The default handling of relocatable relocation cannot process these
 // relocations.  So we have to extend the default code.
 
-template<bool big_endian, int sh_type, typename Classify_reloc>
+template<bool big_endian, typename Classify_reloc>
 class Arm_scan_relocatable_relocs :
-  public Default_scan_relocatable_relocs<sh_type, Classify_reloc>
+  public Default_scan_relocatable_relocs<Classify_reloc>
 {
  public:
   // Return the strategy to use for a local symbol which is a section
@@ -2050,7 +2050,7 @@ class Arm_scan_relocatable_relocs :
   inline Relocatable_relocs::Reloc_strategy
   local_section_strategy(unsigned int r_type, Relobj*)
   {
-    if (sh_type == elfcpp::SHT_RELA)
+    if (Classify_reloc::sh_type == elfcpp::SHT_RELA)
       return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA;
     else
       {
@@ -2301,6 +2301,21 @@ class Target_arm : public Sized_target<32, big_endian>
                          const unsigned char* plocal_symbols,
                          Relocatable_relocs*);
 
+  // Scan the relocs for --emit-relocs.
+  void
+  emit_relocs_scan(Symbol_table* symtab,
+                  Layout* layout,
+                  Sized_relobj_file<32, big_endian>* object,
+                  unsigned int data_shndx,
+                  unsigned int sh_type,
+                  const unsigned char* prelocs,
+                  size_t reloc_count,
+                  Output_section* output_section,
+                  bool needs_special_offset_handling,
+                  size_t local_symbol_count,
+                  const unsigned char* plocal_syms,
+                  Relocatable_relocs* rr);
+
   // Emit relocations for a section.
   void
   relocate_relocs(const Relocate_info<32, big_endian>*,
@@ -2727,12 +2742,15 @@ class Target_arm : public Sized_target<32, big_endian>
 
   };
 
-  // A class which returns the size required for a relocation type,
-  // used while scanning relocs during a relocatable link.
-  class Relocatable_size_for_reloc
+  // A class for inquiring about properties of a relocation,
+  // used while scanning relocs during a relocatable link and
+  // garbage collection.
+  class Classify_reloc :
+      public gold::Default_classify_reloc<elfcpp::SHT_REL, 32, big_endian>
   {
    public:
-    unsigned int
+    // Return the size of the addend of the relocation (only used for SHT_REL).
+    static unsigned int
     get_size_for_reloc(unsigned int, Relobj*);
   };
 
@@ -9170,8 +9188,7 @@ Target_arm<big_endian>::gc_process_relocs(
   typedef Target_arm<big_endian> Arm;
   typedef typename Target_arm<big_endian>::Scan Scan;
 
-  gold::gc_process_relocs<32, big_endian, Arm, elfcpp::SHT_REL, Scan,
-                         typename Target_arm::Relocatable_size_for_reloc>(
+  gold::gc_process_relocs<32, big_endian, Arm, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -9201,7 +9218,6 @@ Target_arm<big_endian>::scan_relocs(Symbol_table* symtab,
                                    size_t local_symbol_count,
                                    const unsigned char* plocal_symbols)
 {
-  typedef typename Target_arm<big_endian>::Scan Scan;
   if (sh_type == elfcpp::SHT_RELA)
     {
       gold_error(_("%s: unsupported RELA reloc section"),
@@ -9209,7 +9225,7 @@ Target_arm<big_endian>::scan_relocs(Symbol_table* symtab,
       return;
     }
 
-  gold::scan_relocs<32, big_endian, Target_arm, elfcpp::SHT_REL, Scan>(
+  gold::scan_relocs<32, big_endian, Target_arm, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -10109,8 +10125,8 @@ Target_arm<big_endian>::relocate_section(
        }
     }
 
-  gold::relocate_section<32, big_endian, Target_arm, elfcpp::SHT_REL,
-                        Arm_relocate, gold::Default_comdat_behavior>(
+  gold::relocate_section<32, big_endian, Target_arm, Arm_relocate,
+                        gold::Default_comdat_behavior, Classify_reloc>(
     relinfo,
     this,
     prelocs,
@@ -10128,7 +10144,7 @@ Target_arm<big_endian>::relocate_section(
 
 template<bool big_endian>
 unsigned int
-Target_arm<big_endian>::Relocatable_size_for_reloc::get_size_for_reloc(
+Target_arm<big_endian>::Classify_reloc::get_size_for_reloc(
     unsigned int r_type,
     Relobj* object)
 {
@@ -10165,13 +10181,12 @@ Target_arm<big_endian>::scan_relocatable_relocs(
     const unsigned char* plocal_symbols,
     Relocatable_relocs* rr)
 {
-  gold_assert(sh_type == elfcpp::SHT_REL);
+  typedef Arm_scan_relocatable_relocs<big_endian, Classify_reloc>
+      Scan_relocatable_relocs;
 
-  typedef Arm_scan_relocatable_relocs<big_endian, elfcpp::SHT_REL,
-    Relocatable_size_for_reloc> Scan_relocatable_relocs;
+  gold_assert(sh_type == elfcpp::SHT_REL);
 
-  gold::scan_relocatable_relocs<32, big_endian, elfcpp::SHT_REL,
-      Scan_relocatable_relocs>(
+  gold::scan_relocatable_relocs<32, big_endian, Scan_relocatable_relocs>(
     symtab,
     layout,
     object,
@@ -10185,6 +10200,44 @@ Target_arm<big_endian>::scan_relocatable_relocs(
     rr);
 }
 
+// Scan the relocs for --emit-relocs.
+
+template<bool big_endian>
+void
+Target_arm<big_endian>::emit_relocs_scan(Symbol_table* symtab,
+    Layout* layout,
+    Sized_relobj_file<32, big_endian>* object,
+    unsigned int data_shndx,
+    unsigned int sh_type,
+    const unsigned char* prelocs,
+    size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
+    size_t local_symbol_count,
+    const unsigned char* plocal_syms,
+    Relocatable_relocs* rr)
+{
+  typedef gold::Default_classify_reloc<elfcpp::SHT_REL, 32, big_endian>
+      Classify_reloc;
+  typedef gold::Default_emit_relocs_strategy<Classify_reloc>
+      Emit_relocs_strategy;
+
+  gold_assert(sh_type == elfcpp::SHT_REL);
+
+  gold::scan_relocatable_relocs<32, big_endian, Emit_relocs_strategy>(
+    symtab,
+    layout,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_syms,
+    rr);
+}
+
 // Emit relocations for a section.
 
 template<bool big_endian>
@@ -10204,7 +10257,7 @@ Target_arm<big_endian>::relocate_relocs(
 {
   gold_assert(sh_type == elfcpp::SHT_REL);
 
-  gold::relocate_relocs<32, big_endian, elfcpp::SHT_REL>(
+  gold::relocate_relocs<32, big_endian, Classify_reloc>(
     relinfo,
     prelocs,
     reloc_count,
index 2dcf61a6f3782cd224a395ccc67822a6814d321a..d0b16b22cdd261dc7ec792296ee15dd151f2a592 100644 (file)
--- a/gold/gc.h
+++ b/gold/gc.h
@@ -38,9 +38,6 @@ class Object;
 template<int size, bool big_endian>
 class Sized_relobj_file;
 
-template<int sh_type, int size, bool big_endian>
-struct Reloc_types;
-
 class Output_section;
 class General_options;
 class Layout;
@@ -153,12 +150,11 @@ struct Symbols_data
 
 template<typename Classify_reloc>
 inline unsigned int
-get_embedded_addend_size(int sh_type, int r_type, Relobj* obj)
+get_embedded_addend_size(int r_type, Relobj* obj)
 {
-  if (sh_type != elfcpp::SHT_REL)
-    return 0;
-  Classify_reloc classify_reloc;
-  return classify_reloc.get_size_for_reloc(r_type, obj);
+  if (Classify_reloc::sh_type == elfcpp::SHT_REL)
+    return Classify_reloc::get_size_for_reloc(r_type, obj);
+  return 0;
 }
 
 // This function implements the generic part of reloc
@@ -167,7 +163,7 @@ get_embedded_addend_size(int sh_type, int r_type, Relobj* obj)
 // garbage collection (--gc-sections) and identical code
 // folding (--icf).
 
-template<int size, bool big_endian, typename Target_type, int sh_type,
+template<int size, bool big_endian, typename Target_type,
         typename Scan, typename Classify_reloc>
 inline void
 gc_process_relocs(
@@ -185,8 +181,8 @@ gc_process_relocs(
 {
   Scan scan;
 
-  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
-  const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
+  typedef typename Classify_reloc::Reltype Reltype;
+  const int reloc_size = Classify_reloc::reloc_size;
   const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
 
   Icf::Sections_reachable_info* secvec = NULL;
@@ -224,11 +220,10 @@ gc_process_relocs(
   for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
     {
       Reltype reloc(prelocs);
-      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);
+      unsigned int r_sym = Classify_reloc::get_r_sym(&reloc);
+      unsigned int r_type = Classify_reloc::get_r_type(&reloc);
       typename elfcpp::Elf_types<size>::Elf_Swxword addend =
-      Reloc_types<sh_type, size, big_endian>::get_reloc_addend_noerror(&reloc);
+         Classify_reloc::get_r_addend(&reloc);
       Relobj* dst_obj;
       unsigned int dst_indx;
       typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
@@ -260,8 +255,7 @@ gc_process_relocs(
                 convert_to_section_size_type(reloc.get_r_offset());
              (*offsetvec).push_back(reloc_offset);
               (*reloc_addend_size_vec).push_back(
-                get_embedded_addend_size<Classify_reloc>(sh_type, r_type,
-                                                         src_obj));
+                get_embedded_addend_size<Classify_reloc>(r_type, src_obj));
             }
 
          // When doing safe folding, check to see if this relocation is that
@@ -337,8 +331,7 @@ gc_process_relocs(
                 convert_to_section_size_type(reloc.get_r_offset());
              (*offsetvec).push_back(reloc_offset);
               (*reloc_addend_size_vec).push_back(
-                get_embedded_addend_size<Classify_reloc>(sh_type, r_type,
-                                                         src_obj));
+                get_embedded_addend_size<Classify_reloc>(r_type, src_obj));
            }
 
           if (dst_obj == NULL)
index 57e5542f0bd870d080db10ed278fa7902ad29b9b..82886d4b8a9e8e9ff33955b7ae458722fc5f38af 100644 (file)
@@ -429,6 +429,21 @@ class Target_i386 : public Sized_target<32, false>
                          const unsigned char* plocal_symbols,
                          Relocatable_relocs*);
 
+  // Scan the relocs for --emit-relocs.
+  void
+  emit_relocs_scan(Symbol_table* symtab,
+                  Layout* layout,
+                  Sized_relobj_file<32, false>* object,
+                  unsigned int data_shndx,
+                  unsigned int sh_type,
+                  const unsigned char* prelocs,
+                  size_t reloc_count,
+                  Output_section* output_section,
+                  bool needs_special_offset_handling,
+                  size_t local_symbol_count,
+                  const unsigned char* plocal_syms,
+                  Relocatable_relocs* rr);
+
   // Emit relocations for a section.
   void
   relocate_relocs(const Relocate_info<32, false>*,
@@ -485,7 +500,7 @@ class Target_i386 : public Sized_target<32, false>
 
   // Return whether SYM is call to a non-split function.
   bool
-  do_is_call_to_non_split(const Symbol* sym, unsigned int) const;
+  do_is_call_to_non_split(const Symbol* sym, const unsigned char*) const;
 
   // Adjust -fsplit-stack code which calls non-split-stack code.
   void
@@ -723,12 +738,15 @@ class Target_i386 : public Sized_target<32, false>
     Local_dynamic_type local_dynamic_type_;
   };
 
-  // A class which returns the size required for a relocation type,
-  // used while scanning relocs during a relocatable link.
-  class Relocatable_size_for_reloc
+  // A class for inquiring about properties of a relocation,
+  // used while scanning relocs during a relocatable link and
+  // garbage collection.
+  class Classify_reloc :
+      public gold::Default_classify_reloc<elfcpp::SHT_REL, 32, false>
   {
    public:
-    unsigned int
+    // Return the size of the addend of the relocation (only used for SHT_REL).
+    static unsigned int
     get_size_for_reloc(unsigned int, Relobj*);
   };
 
@@ -2564,9 +2582,7 @@ Target_i386::gc_process_relocs(Symbol_table* symtab,
                                      size_t local_symbol_count,
                                      const unsigned char* plocal_symbols)
 {
-  gold::gc_process_relocs<32, false, Target_i386, elfcpp::SHT_REL,
-                         Target_i386::Scan,
-                         Target_i386::Relocatable_size_for_reloc>(
+  gold::gc_process_relocs<32, false, Target_i386, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -2602,8 +2618,7 @@ Target_i386::scan_relocs(Symbol_table* symtab,
       return;
     }
 
-  gold::scan_relocs<32, false, Target_i386, elfcpp::SHT_REL,
-                   Target_i386::Scan>(
+  gold::scan_relocs<32, false, Target_i386, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -3609,8 +3624,8 @@ Target_i386::relocate_section(const Relocate_info<32, false>* relinfo,
 {
   gold_assert(sh_type == elfcpp::SHT_REL);
 
-  gold::relocate_section<32, false, Target_i386, elfcpp::SHT_REL,
-                        Target_i386::Relocate, gold::Default_comdat_behavior>(
+  gold::relocate_section<32, false, Target_i386, Relocate,
+                        gold::Default_comdat_behavior, Classify_reloc>(
     relinfo,
     this,
     prelocs,
@@ -3627,7 +3642,7 @@ Target_i386::relocate_section(const Relocate_info<32, false>* relinfo,
 // link.
 
 unsigned int
-Target_i386::Relocatable_size_for_reloc::get_size_for_reloc(
+Target_i386::Classify_reloc::get_size_for_reloc(
     unsigned int r_type,
     Relobj* object)
 {
@@ -3712,13 +3727,12 @@ Target_i386::scan_relocatable_relocs(Symbol_table* symtab,
                                     const unsigned char* plocal_symbols,
                                     Relocatable_relocs* rr)
 {
-  gold_assert(sh_type == elfcpp::SHT_REL);
+  typedef gold::Default_scan_relocatable_relocs<Classify_reloc>
+      Scan_relocatable_relocs;
 
-  typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_REL,
-    Relocatable_size_for_reloc> Scan_relocatable_relocs;
+  gold_assert(sh_type == elfcpp::SHT_REL);
 
-  gold::scan_relocatable_relocs<32, false, elfcpp::SHT_REL,
-      Scan_relocatable_relocs>(
+  gold::scan_relocatable_relocs<32, false, Scan_relocatable_relocs>(
     symtab,
     layout,
     object,
@@ -3732,6 +3746,43 @@ Target_i386::scan_relocatable_relocs(Symbol_table* symtab,
     rr);
 }
 
+// Scan the relocs for --emit-relocs.
+
+void
+Target_i386::emit_relocs_scan(Symbol_table* symtab,
+                             Layout* layout,
+                             Sized_relobj_file<32, false>* object,
+                             unsigned int data_shndx,
+                             unsigned int sh_type,
+                             const unsigned char* prelocs,
+                             size_t reloc_count,
+                             Output_section* output_section,
+                             bool needs_special_offset_handling,
+                             size_t local_symbol_count,
+                             const unsigned char* plocal_syms,
+                             Relocatable_relocs* rr)
+{
+  typedef gold::Default_classify_reloc<elfcpp::SHT_REL, 32, false>
+      Classify_reloc;
+  typedef gold::Default_emit_relocs_strategy<Classify_reloc>
+      Emit_relocs_strategy;
+
+  gold_assert(sh_type == elfcpp::SHT_REL);
+
+  gold::scan_relocatable_relocs<32, false, Emit_relocs_strategy>(
+    symtab,
+    layout,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_syms,
+    rr);
+}
+
 // Emit relocations for a section.
 
 void
@@ -3750,7 +3801,7 @@ Target_i386::relocate_relocs(
 {
   gold_assert(sh_type == elfcpp::SHT_REL);
 
-  gold::relocate_relocs<32, false, elfcpp::SHT_REL>(
+  gold::relocate_relocs<32, false, Classify_reloc>(
     relinfo,
     prelocs,
     reloc_count,
@@ -3867,7 +3918,8 @@ Target_i386::do_ehframe_datarel_base() const
 // get_pc_thunk function.
 
 bool
-Target_i386::do_is_call_to_non_split(const Symbol* sym, unsigned int) const
+Target_i386::do_is_call_to_non_split(const Symbol* sym,
+                                    const unsigned char*) const
 {
   return (sym->type() == elfcpp::STT_FUNC
          && !is_prefix_of("__i686.get_pc_thunk.", sym->name()));
index 3d513fff17204632c0d14effc00a93348cb39257..c57ef4f807f4a51ade8a46ed822ef1267acc80a1 100644 (file)
@@ -2642,9 +2642,9 @@ class Mips_output_section_reginfo : public Output_section
 // The MIPS target has relocation types which default handling of relocatable
 // relocation cannot process.  So we have to extend the default code.
 
-template<bool big_endian, int sh_type, typename Classify_reloc>
+template<bool big_endian, typename Classify_reloc>
 class Mips_scan_relocatable_relocs :
-  public Default_scan_relocatable_relocs<sh_type, Classify_reloc>
+  public Default_scan_relocatable_relocs<Classify_reloc>
 {
  public:
   // Return the strategy to use for a local symbol which is a section
@@ -2652,7 +2652,7 @@ class Mips_scan_relocatable_relocs :
   inline Relocatable_relocs::Reloc_strategy
   local_section_strategy(unsigned int r_type, Relobj* object)
   {
-    if (sh_type == elfcpp::SHT_RELA)
+    if (Classify_reloc::sh_type == elfcpp::SHT_RELA)
       return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA;
     else
       {
@@ -2662,7 +2662,7 @@ class Mips_scan_relocatable_relocs :
             return Relocatable_relocs::RELOC_SPECIAL;
 
           default:
-            return Default_scan_relocatable_relocs<sh_type, Classify_reloc>::
+            return Default_scan_relocatable_relocs<Classify_reloc>::
                 local_section_strategy(r_type, object);
           }
       }
@@ -2860,6 +2860,182 @@ class Symbol_visitor_check_symbols
   Symbol_table* symtab_;
 };
 
+// Relocation types, parameterized by SHT_REL vs. SHT_RELA, size,
+// and endianness. The relocation format for MIPS-64 is non-standard.
+
+template<int sh_type, int size, bool big_endian>
+struct Mips_reloc_types;
+
+template<bool big_endian>
+struct Mips_reloc_types<elfcpp::SHT_REL, 32, big_endian>
+{
+  typedef typename elfcpp::Rel<32, big_endian> Reloc;
+  typedef typename elfcpp::Rel_write<32, big_endian> Reloc_write;
+
+  static unsigned typename elfcpp::Elf_types<32>::Elf_Swxword
+  get_r_addend(const Reloc*)
+  { return 0; }
+
+  static inline void
+  set_reloc_addend(Reloc_write*,
+                  typename elfcpp::Elf_types<32>::Elf_Swxword)
+  { gold_unreachable(); }
+};
+
+template<bool big_endian>
+struct Mips_reloc_types<elfcpp::SHT_RELA, 32, big_endian>
+{
+  typedef typename elfcpp::Rela<32, big_endian> Reloc;
+  typedef typename elfcpp::Rela_write<32, big_endian> Reloc_write;
+
+  static unsigned typename elfcpp::Elf_types<32>::Elf_Swxword
+  get_r_addend(const Reloc* reloc)
+  { return reloc->get_r_addend(); }
+
+  static inline void
+  set_reloc_addend(Reloc_write* p,
+                  typename elfcpp::Elf_types<32>::Elf_Swxword val)
+  { p->put_r_addend(val); }
+};
+
+template<bool big_endian>
+struct Mips_reloc_types<elfcpp::SHT_REL, 64, big_endian>
+{
+  typedef typename elfcpp::Mips64_rel<big_endian> Reloc;
+  typedef typename elfcpp::Mips64_rel_write<big_endian> Reloc_write;
+
+  static unsigned typename elfcpp::Elf_types<64>::Elf_Swxword
+  get_r_addend(const Reloc*)
+  { return 0; }
+
+  static inline void
+  set_reloc_addend(Reloc_write*,
+                  typename elfcpp::Elf_types<64>::Elf_Swxword)
+  { gold_unreachable(); }
+};
+
+template<bool big_endian>
+struct Mips_reloc_types<elfcpp::SHT_RELA, 64, big_endian>
+{
+  typedef typename elfcpp::Mips64_rela<big_endian> Reloc;
+  typedef typename elfcpp::Mips64_rela_write<big_endian> Reloc_write;
+
+  static unsigned typename elfcpp::Elf_types<64>::Elf_Swxword
+  get_r_addend(const Reloc* reloc)
+  { return reloc->get_r_addend(); }
+
+  static inline void
+  set_reloc_addend(Reloc_write* p,
+                  typename elfcpp::Elf_types<64>::Elf_Swxword val)
+  { p->put_r_addend(val); }
+};
+
+// Forward declaration.
+static unsigned int
+mips_get_size_for_reloc(unsigned int, Relobj*);
+
+// A class for inquiring about properties of a relocation,
+// used while scanning relocs during a relocatable link and
+// garbage collection.
+
+template<int sh_type_, int size, bool big_endian>
+class Mips_classify_reloc;
+
+template<int sh_type_, bool big_endian>
+class Mips_classify_reloc<sh_type_, 32, big_endian> :
+    public gold::Default_classify_reloc<sh_type_, 32, big_endian>
+{
+ public:
+  typedef typename Mips_reloc_types<sh_type_, 32, big_endian>::Reloc
+      Reltype;
+  typedef typename Mips_reloc_types<sh_type_, 32, big_endian>::Reloc_write
+      Reltype_write;
+
+  // Return the symbol referred to by the relocation.
+  static inline unsigned int
+  get_r_sym(const Reltype* reloc)
+  { return elfcpp::elf_r_sym<32>(reloc->get_r_info()); }
+
+  // Return the type of the relocation.
+  static inline unsigned int
+  get_r_type(const Reltype* reloc)
+  { return elfcpp::elf_r_type<32>(reloc->get_r_info()); }
+
+  // Return the explicit addend of the relocation (return 0 for SHT_REL).
+  static inline unsigned int
+  get_r_addend(const Reltype* reloc)
+  { return Mips_reloc_types<sh_type_, 32, big_endian>::get_r_addend(reloc); }
+
+  // Write the r_info field to a new reloc, using the r_info field from
+  // the original reloc, replacing the r_sym field with R_SYM.
+  static inline void
+  put_r_info(Reltype_write* new_reloc, Reltype* reloc, unsigned int r_sym)
+  {
+    unsigned int r_type = elfcpp::elf_r_type<32>(reloc->get_r_info());
+    new_reloc->put_r_info(elfcpp::elf_r_info<64>(r_sym, r_type));
+  }
+
+  // Write the r_addend field to a new reloc.
+  static inline void
+  put_r_addend(Reltype_write* to,
+              typename elfcpp::Elf_types<32>::Elf_Swxword addend)
+  { Mips_reloc_types<sh_type_, 32, big_endian>::set_reloc_addend(to, addend); }
+
+  // Return the size of the addend of the relocation (only used for SHT_REL).
+  static unsigned int
+  get_size_for_reloc(unsigned int r_type, Relobj* obj)
+  { return mips_get_size_for_reloc(r_type, obj); }
+};
+
+template<int sh_type_, bool big_endian>
+class Mips_classify_reloc<sh_type_, 64, big_endian> :
+    public gold::Default_classify_reloc<sh_type_, 64, big_endian>
+{
+ public:
+  typedef typename Mips_reloc_types<sh_type_, 64, big_endian>::Reloc
+      Reltype;
+  typedef typename Mips_reloc_types<sh_type_, 64, big_endian>::Reloc_write
+      Reltype_write;
+
+  // Return the symbol referred to by the relocation.
+  static inline unsigned int
+  get_r_sym(const Reltype* reloc)
+  { return reloc->get_r_sym(); }
+
+  // Return the type of the relocation.
+  static inline unsigned int
+  get_r_type(const Reltype* reloc)
+  { return reloc->get_r_type(); }
+
+  // Return the explicit addend of the relocation (return 0 for SHT_REL).
+  static inline typename elfcpp::Elf_types<64>::Elf_Swxword
+  get_r_addend(const Reltype* reloc)
+  { return Mips_reloc_types<sh_type_, 64, big_endian>::get_r_addend(reloc); }
+
+  // Write the r_info field to a new reloc, using the r_info field from
+  // the original reloc, replacing the r_sym field with R_SYM.
+  static inline void
+  put_r_info(Reltype_write* new_reloc, Reltype* reloc, unsigned int r_sym)
+  {
+    new_reloc->put_r_sym(r_sym);
+    new_reloc->put_r_ssym(reloc->get_r_ssym());
+    new_reloc->put_r_type3(reloc->get_r_type3());
+    new_reloc->put_r_type2(reloc->get_r_type2());
+    new_reloc->put_r_type(reloc->get_r_type());
+  }
+
+  // Write the r_addend field to a new reloc.
+  static inline void
+  put_r_addend(Reltype_write* to,
+              typename elfcpp::Elf_types<64>::Elf_Swxword addend)
+  { Mips_reloc_types<sh_type_, 64, big_endian>::set_reloc_addend(to, addend); }
+
+  // Return the size of the addend of the relocation (only used for SHT_REL).
+  static unsigned int
+  get_size_for_reloc(unsigned int r_type, Relobj* obj)
+  { return mips_get_size_for_reloc(r_type, obj); }
+};
+
 template<int size, bool big_endian>
 class Target_mips : public Sized_target<size, big_endian>
 {
@@ -2870,6 +3046,10 @@ class Target_mips : public Sized_target<size, big_endian>
     Reloca_section;
   typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype32;
   typedef typename elfcpp::Swap<size, big_endian>::Valtype Valtype;
+  typedef typename Mips_reloc_types<elfcpp::SHT_REL, size, big_endian>::Reloc
+      Reltype;
+  typedef typename Mips_reloc_types<elfcpp::SHT_RELA, size, big_endian>::Reloc
+      Relatype;
 
  public:
   Target_mips(const Target::Target_info* info = &mips_info)
@@ -2955,6 +3135,21 @@ class Target_mips : public Sized_target<size, big_endian>
                           const unsigned char* plocal_symbols,
                           Relocatable_relocs*);
 
+  // Scan the relocs for --emit-relocs.
+  void
+  emit_relocs_scan(Symbol_table* symtab,
+                  Layout* layout,
+                  Sized_relobj_file<size, big_endian>* object,
+                  unsigned int data_shndx,
+                  unsigned int sh_type,
+                  const unsigned char* prelocs,
+                  size_t reloc_count,
+                  Output_section* output_section,
+                  bool needs_special_offset_handling,
+                  size_t local_symbol_count,
+                  const unsigned char* plocal_syms,
+                  Relocatable_relocs* rr);
+
   // Emit relocations for a section.
   void
   relocate_relocs(const Relocate_info<size, big_endian>*,
@@ -3164,6 +3359,17 @@ class Target_mips : public Sized_target<size, big_endian>
   use_32bit_micromips_instructions() const
   { return this->insn32_; }
 
+  // Return the r_sym field from a relocation.
+  unsigned int
+  get_r_sym(const unsigned char* preloc) const
+  {
+    // Since REL and RELA relocs share the same structure through
+    // the r_info field, we can just use REL here.
+    Reltype rel(preloc);
+    return Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>::
+       get_r_sym(&rel);
+  }
+
  protected:
   // Return the value to use for a dynamic symbol which requires special
   // treatment.  This is how we support equality comparisons of function
@@ -3268,7 +3474,7 @@ class Target_mips : public Sized_target<size, big_endian>
           Sized_relobj_file<size, big_endian>* object,
           unsigned int data_shndx,
           Output_section* output_section,
-          const elfcpp::Rel<size, big_endian>& reloc, unsigned int r_type,
+          const Reltype& reloc, unsigned int r_type,
           const elfcpp::Sym<size, big_endian>& lsym,
           bool is_discarded);
 
@@ -3277,7 +3483,7 @@ class Target_mips : public Sized_target<size, big_endian>
           Sized_relobj_file<size, big_endian>* object,
           unsigned int data_shndx,
           Output_section* output_section,
-          const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
+          const Relatype& reloc, unsigned int r_type,
           const elfcpp::Sym<size, big_endian>& lsym,
           bool is_discarded);
 
@@ -3286,8 +3492,8 @@ class Target_mips : public Sized_target<size, big_endian>
           Sized_relobj_file<size, big_endian>* object,
           unsigned int data_shndx,
           Output_section* output_section,
-          const elfcpp::Rela<size, big_endian>* rela,
-          const elfcpp::Rel<size, big_endian>* rel,
+          const Relatype* rela,
+          const Reltype* rel,
           unsigned int rel_type,
           unsigned int r_type,
           const elfcpp::Sym<size, big_endian>& lsym,
@@ -3298,7 +3504,7 @@ class Target_mips : public Sized_target<size, big_endian>
            Sized_relobj_file<size, big_endian>* object,
            unsigned int data_shndx,
            Output_section* output_section,
-           const elfcpp::Rel<size, big_endian>& reloc, unsigned int r_type,
+           const Reltype& reloc, unsigned int r_type,
            Symbol* gsym);
 
     inline void
@@ -3306,7 +3512,7 @@ class Target_mips : public Sized_target<size, big_endian>
            Sized_relobj_file<size, big_endian>* object,
            unsigned int data_shndx,
            Output_section* output_section,
-           const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
+           const Relatype& reloc, unsigned int r_type,
            Symbol* gsym);
 
     inline void
@@ -3314,8 +3520,8 @@ class Target_mips : public Sized_target<size, big_endian>
            Sized_relobj_file<size, big_endian>* object,
            unsigned int data_shndx,
            Output_section* output_section,
-           const elfcpp::Rela<size, big_endian>* rela,
-           const elfcpp::Rel<size, big_endian>* rel,
+           const Relatype* rela,
+           const Reltype* rel,
            unsigned int rel_type,
            unsigned int r_type,
            Symbol* gsym);
@@ -3326,7 +3532,7 @@ class Target_mips : public Sized_target<size, big_endian>
                                         Sized_relobj_file<size, big_endian>*,
                                         unsigned int,
                                         Output_section*,
-                                        const elfcpp::Rel<size, big_endian>&,
+                                        const Reltype&,
                                         unsigned int,
                                         const elfcpp::Sym<size, big_endian>&)
     { return false; }
@@ -3337,7 +3543,7 @@ class Target_mips : public Sized_target<size, big_endian>
                                          Sized_relobj_file<size, big_endian>*,
                                          unsigned int,
                                          Output_section*,
-                                         const elfcpp::Rel<size, big_endian>&,
+                                         const Reltype&,
                                          unsigned int, Symbol*)
     { return false; }
 
@@ -3347,7 +3553,7 @@ class Target_mips : public Sized_target<size, big_endian>
                                         Sized_relobj_file<size, big_endian>*,
                                         unsigned int,
                                         Output_section*,
-                                        const elfcpp::Rela<size, big_endian>&,
+                                        const Relatype&,
                                         unsigned int,
                                         const elfcpp::Sym<size, big_endian>&)
     { return false; }
@@ -3358,7 +3564,7 @@ class Target_mips : public Sized_target<size, big_endian>
                                          Sized_relobj_file<size, big_endian>*,
                                          unsigned int,
                                          Output_section*,
-                                         const elfcpp::Rela<size, big_endian>&,
+                                         const Relatype&,
                                          unsigned int, Symbol*)
     { return false; }
    private:
@@ -3397,15 +3603,6 @@ class Target_mips : public Sized_target<size, big_endian>
             unsigned char*, Mips_address, section_size_type);
   };
 
-  // A class which returns the size required for a relocation type,
-  // used while scanning relocs during a relocatable link.
-  class Relocatable_size_for_reloc
-  {
-   public:
-    unsigned int
-    get_size_for_reloc(unsigned int, Relobj*);
-  };
-
   // This POD class holds the dynamic relocations that should be emitted instead
   // of R_MIPS_32, R_MIPS_REL32 and R_MIPS_64 relocations.  We will emit these
   // relocations if it turns out that the symbol does not have static
@@ -3573,9 +3770,11 @@ class Target_mips : public Sized_target<size, big_endian>
   copy_reloc(Symbol_table* symtab, Layout* layout,
              Sized_relobj_file<size, big_endian>* object,
              unsigned int shndx, Output_section* output_section,
-             Symbol* sym, const elfcpp::Rel<size, big_endian>& reloc)
+             Symbol* sym, const Reltype& reloc)
   {
-    unsigned int r_type = elfcpp::elf_r_type<size>(reloc.get_r_info());
+    unsigned int r_type =
+       Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>::
+         get_r_type(&reloc);
     this->copy_relocs_.copy_reloc(symtab, layout,
                                   symtab->get_sized_symbol<size>(sym),
                                   object, shndx, output_section,
@@ -3725,7 +3924,6 @@ class Target_mips : public Sized_target<size, big_endian>
   bool insn32_;
 };
 
-
 // Helper structure for R_MIPS*_HI16/LO16 and R_MIPS*_GOT16/LO16 relocations.
 // It records high part of the relocation pair.
 
@@ -7510,10 +7708,10 @@ Target_mips<size, big_endian>::gc_process_relocs(
                         const unsigned char* plocal_symbols)
 {
   typedef Target_mips<size, big_endian> Mips;
-  typedef typename Target_mips<size, big_endian>::Scan Scan;
+  typedef Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>
+      Classify_reloc;
 
-  gold::gc_process_relocs<size, big_endian, Mips, elfcpp::SHT_REL, Scan,
-                          typename Target_mips::Relocatable_size_for_reloc>(
+  gold::gc_process_relocs<size, big_endian, Mips, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -7545,34 +7743,43 @@ Target_mips<size, big_endian>::scan_relocs(
                         const unsigned char* plocal_symbols)
 {
   typedef Target_mips<size, big_endian> Mips;
-  typedef typename Target_mips<size, big_endian>::Scan Scan;
 
   if (sh_type == elfcpp::SHT_REL)
-    gold::scan_relocs<size, big_endian, Mips, elfcpp::SHT_REL, Scan>(
-      symtab,
-      layout,
-      this,
-      object,
-      data_shndx,
-      prelocs,
-      reloc_count,
-      output_section,
-      needs_special_offset_handling,
-      local_symbol_count,
-      plocal_symbols);
+    {
+      typedef Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>
+         Classify_reloc;
+
+      gold::scan_relocs<size, big_endian, Mips, Scan, Classify_reloc>(
+       symtab,
+       layout,
+       this,
+       object,
+       data_shndx,
+       prelocs,
+       reloc_count,
+       output_section,
+       needs_special_offset_handling,
+       local_symbol_count,
+       plocal_symbols);
+    }
   else if (sh_type == elfcpp::SHT_RELA)
-    gold::scan_relocs<size, big_endian, Mips, elfcpp::SHT_RELA, Scan>(
-      symtab,
-      layout,
-      this,
-      object,
-      data_shndx,
-      prelocs,
-      reloc_count,
-      output_section,
-      needs_special_offset_handling,
-      local_symbol_count,
-      plocal_symbols);
+    {
+      typedef Mips_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+         Classify_reloc;
+
+      gold::scan_relocs<size, big_endian, Mips, Scan, Classify_reloc>(
+       symtab,
+       layout,
+       this,
+       object,
+       data_shndx,
+       prelocs,
+       reloc_count,
+       output_section,
+       needs_special_offset_handling,
+       local_symbol_count,
+       plocal_symbols);
+    }
 }
 
 template<int size, bool big_endian>
@@ -8227,41 +8434,48 @@ Target_mips<size, big_endian>::relocate_section(
   typedef typename Target_mips<size, big_endian>::Relocate Mips_relocate;
 
   if (sh_type == elfcpp::SHT_REL)
-    gold::relocate_section<size, big_endian, Mips, elfcpp::SHT_REL,
-      Mips_relocate, gold::Default_comdat_behavior>(
-      relinfo,
-      this,
-      prelocs,
-      reloc_count,
-      output_section,
-      needs_special_offset_handling,
-      view,
-      address,
-      view_size,
-      reloc_symbol_changes);
+    {
+      typedef Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>
+         Classify_reloc;
+
+      gold::relocate_section<size, big_endian, Mips, Mips_relocate,
+                            gold::Default_comdat_behavior, Classify_reloc>(
+       relinfo,
+       this,
+       prelocs,
+       reloc_count,
+       output_section,
+       needs_special_offset_handling,
+       view,
+       address,
+       view_size,
+       reloc_symbol_changes);
+    }
   else if (sh_type == elfcpp::SHT_RELA)
-    gold::relocate_section<size, big_endian, Mips, elfcpp::SHT_RELA,
-      Mips_relocate, gold::Default_comdat_behavior>(
-      relinfo,
-      this,
-      prelocs,
-      reloc_count,
-      output_section,
-      needs_special_offset_handling,
-      view,
-      address,
-      view_size,
-      reloc_symbol_changes);
+    {
+      typedef Mips_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+         Classify_reloc;
+
+      gold::relocate_section<size, big_endian, Mips, Mips_relocate,
+                            gold::Default_comdat_behavior, Classify_reloc>(
+       relinfo,
+       this,
+       prelocs,
+       reloc_count,
+       output_section,
+       needs_special_offset_handling,
+       view,
+       address,
+       view_size,
+       reloc_symbol_changes);
+    }
 }
 
 // Return the size of a relocation while scanning during a relocatable
 // link.
 
-template<int size, bool big_endian>
 unsigned int
-Target_mips<size, big_endian>::Relocatable_size_for_reloc::get_size_for_reloc(
-    unsigned int r_type,
-    Relobj* object)
+mips_get_size_for_reloc(unsigned int r_type, Relobj* object)
 {
   switch (r_type)
     {
@@ -8344,13 +8558,14 @@ Target_mips<size, big_endian>::scan_relocatable_relocs(
                         const unsigned char* plocal_symbols,
                         Relocatable_relocs* rr)
 {
-  gold_assert(sh_type == elfcpp::SHT_REL);
+  typedef Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>
+      Classify_reloc;
+  typedef Mips_scan_relocatable_relocs<big_endian, Classify_reloc>
+      Scan_relocatable_relocs;
 
-  typedef Mips_scan_relocatable_relocs<big_endian, elfcpp::SHT_REL,
-    Relocatable_size_for_reloc> Scan_relocatable_relocs;
+  gold_assert(sh_type == elfcpp::SHT_REL);
 
-  gold::scan_relocatable_relocs<size, big_endian, elfcpp::SHT_REL,
-    Scan_relocatable_relocs>(
+  gold::scan_relocatable_relocs<size, big_endian, Scan_relocatable_relocs>(
     symtab,
     layout,
     object,
@@ -8364,6 +8579,45 @@ Target_mips<size, big_endian>::scan_relocatable_relocs(
     rr);
 }
 
+// Scan the relocs for --emit-relocs.
+
+template<int size, bool big_endian>
+void
+Target_mips<size, big_endian>::emit_relocs_scan(
+    Symbol_table* symtab,
+    Layout* layout,
+    Sized_relobj_file<size, big_endian>* object,
+    unsigned int data_shndx,
+    unsigned int sh_type,
+    const unsigned char* prelocs,
+    size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
+    size_t local_symbol_count,
+    const unsigned char* plocal_syms,
+    Relocatable_relocs* rr)
+{
+  typedef Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>
+      Classify_reloc;
+  typedef gold::Default_emit_relocs_strategy<Classify_reloc>
+      Emit_relocs_strategy;
+
+  gold_assert(sh_type == elfcpp::SHT_REL);
+
+  gold::scan_relocatable_relocs<size, big_endian, Emit_relocs_strategy>(
+    symtab,
+    layout,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_syms,
+    rr);
+}
+
 // Emit relocations for a section.
 
 template<int size, bool big_endian>
@@ -8382,9 +8636,12 @@ Target_mips<size, big_endian>::relocate_relocs(
                         unsigned char* reloc_view,
                         section_size_type reloc_view_size)
 {
+  typedef Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>
+      Classify_reloc;
+
   gold_assert(sh_type == elfcpp::SHT_REL);
 
-  gold::relocate_relocs<size, big_endian, elfcpp::SHT_REL>(
+  gold::relocate_relocs<size, big_endian, Classify_reloc>(
     relinfo,
     prelocs,
     reloc_count,
@@ -8550,8 +8807,8 @@ Target_mips<size, big_endian>::Scan::local(
                         Sized_relobj_file<size, big_endian>* object,
                         unsigned int data_shndx,
                         Output_section* output_section,
-                        const elfcpp::Rela<size, big_endian>* rela,
-                        const elfcpp::Rel<size, big_endian>* rel,
+                        const Relatype* rela,
+                        const Reltype* rel,
                         unsigned int rel_type,
                         unsigned int r_type,
                         const elfcpp::Sym<size, big_endian>& lsym,
@@ -8561,23 +8818,24 @@ Target_mips<size, big_endian>::Scan::local(
     return;
 
   Mips_address r_offset;
-  typename elfcpp::Elf_types<size>::Elf_WXword r_info;
+  unsigned int r_sym;
   typename elfcpp::Elf_types<size>::Elf_Swxword r_addend;
 
   if (rel_type == elfcpp::SHT_RELA)
     {
       r_offset = rela->get_r_offset();
-      r_info = rela->get_r_info();
+      r_sym = Mips_classify_reloc<elfcpp::SHT_RELA, size, big_endian>::
+         get_r_sym(rela);
       r_addend = rela->get_r_addend();
     }
   else
     {
       r_offset = rel->get_r_offset();
-      r_info = rel->get_r_info();
+      r_sym = Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>::
+         get_r_sym(rel);
       r_addend = 0;
     }
 
-  unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
   Mips_relobj<size, big_endian>* mips_obj =
     Mips_relobj<size, big_endian>::as_mips_relobj(object);
 
@@ -8655,7 +8913,6 @@ Target_mips<size, big_endian>::Scan::local(
       // R_MIPS_GOT_LO16 or R_MIPS_CALL_LO16.
       Mips_output_data_got<size, big_endian>* got =
         target->got_section(symtab, layout);
-      unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
       got->record_local_got_symbol(mips_obj, r_sym, r_addend, r_type, -1U);
     }
 
@@ -8790,7 +9047,6 @@ Target_mips<size, big_endian>::Scan::local(
             // executable), we need to create a dynamic relocation for
             // this location.
             Reloc_section* rel_dyn = target->rel_dyn_section(layout);
-            unsigned int r_sym = elfcpp::elf_r_sym<32>(r_info);
             rel_dyn->add_symbolless_local_addend(object, r_sym,
                                                  elfcpp::R_MIPS_REL32,
                                                  output_section, data_shndx,
@@ -8809,7 +9065,6 @@ Target_mips<size, big_endian>::Scan::local(
     case elfcpp::R_MIPS16_TLS_GD:
     case elfcpp::R_MICROMIPS_TLS_GD:
       {
-        unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
         bool output_is_shared = parameters->options().shared();
         const tls::Tls_optimization optimized_type
             = Target_mips<size, big_endian>::optimize_tls_reloc(
@@ -8929,7 +9184,7 @@ Target_mips<size, big_endian>::Scan::local(
                         Sized_relobj_file<size, big_endian>* object,
                         unsigned int data_shndx,
                         Output_section* output_section,
-                        const elfcpp::Rel<size, big_endian>& reloc,
+                        const Reltype& reloc,
                         unsigned int r_type,
                         const elfcpp::Sym<size, big_endian>& lsym,
                         bool is_discarded)
@@ -8944,7 +9199,7 @@ Target_mips<size, big_endian>::Scan::local(
     object,
     data_shndx,
     output_section,
-    (const elfcpp::Rela<size, big_endian>*) NULL,
+    (const Relatype*) NULL,
     &reloc,
     elfcpp::SHT_REL,
     r_type,
@@ -8961,7 +9216,7 @@ Target_mips<size, big_endian>::Scan::local(
                         Sized_relobj_file<size, big_endian>* object,
                         unsigned int data_shndx,
                         Output_section* output_section,
-                        const elfcpp::Rela<size, big_endian>& reloc,
+                        const Relatype& reloc,
                         unsigned int r_type,
                         const elfcpp::Sym<size, big_endian>& lsym,
                         bool is_discarded)
@@ -8977,7 +9232,7 @@ Target_mips<size, big_endian>::Scan::local(
     data_shndx,
     output_section,
     &reloc,
-    (const elfcpp::Rel<size, big_endian>*) NULL,
+    (const Reltype*) NULL,
     elfcpp::SHT_RELA,
     r_type,
     lsym, is_discarded);
@@ -8994,30 +9249,31 @@ Target_mips<size, big_endian>::Scan::global(
                                 Sized_relobj_file<size, big_endian>* object,
                                 unsigned int data_shndx,
                                 Output_section* output_section,
-                                const elfcpp::Rela<size, big_endian>* rela,
-                                const elfcpp::Rel<size, big_endian>* rel,
+                                const Relatype* rela,
+                                const Reltype* rel,
                                 unsigned int rel_type,
                                 unsigned int r_type,
                                 Symbol* gsym)
 {
   Mips_address r_offset;
-  typename elfcpp::Elf_types<size>::Elf_WXword r_info;
+  unsigned int r_sym;
   typename elfcpp::Elf_types<size>::Elf_Swxword r_addend;
 
   if (rel_type == elfcpp::SHT_RELA)
     {
       r_offset = rela->get_r_offset();
-      r_info = rela->get_r_info();
+      r_sym = Mips_classify_reloc<elfcpp::SHT_RELA, size, big_endian>::
+         get_r_sym(rela);
       r_addend = rela->get_r_addend();
     }
   else
     {
       r_offset = rel->get_r_offset();
-      r_info = rel->get_r_info();
+      r_sym = Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>::
+         get_r_sym(rel);
       r_addend = 0;
     }
 
-  unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
   Mips_relobj<size, big_endian>* mips_obj =
     Mips_relobj<size, big_endian>::as_mips_relobj(object);
   Mips_symbol<size>* mips_sym = Mips_symbol<size>::as_mips_sym(gsym);
@@ -9434,7 +9690,7 @@ Target_mips<size, big_endian>::Scan::global(
                                 Sized_relobj_file<size, big_endian>* object,
                                 unsigned int data_shndx,
                                 Output_section* output_section,
-                                const elfcpp::Rela<size, big_endian>& reloc,
+                                const Relatype& reloc,
                                 unsigned int r_type,
                                 Symbol* gsym)
 {
@@ -9446,7 +9702,7 @@ Target_mips<size, big_endian>::Scan::global(
     data_shndx,
     output_section,
     &reloc,
-    (const elfcpp::Rel<size, big_endian>*) NULL,
+    (const Reltype*) NULL,
     elfcpp::SHT_RELA,
     r_type,
     gsym);
@@ -9461,7 +9717,7 @@ Target_mips<size, big_endian>::Scan::global(
                                 Sized_relobj_file<size, big_endian>* object,
                                 unsigned int data_shndx,
                                 Output_section* output_section,
-                                const elfcpp::Rel<size, big_endian>& reloc,
+                                const Reltype& reloc,
                                 unsigned int r_type,
                                 Symbol* gsym)
 {
@@ -9472,7 +9728,7 @@ Target_mips<size, big_endian>::Scan::global(
     object,
     data_shndx,
     output_section,
-    (const elfcpp::Rela<size, big_endian>*) NULL,
+    (const Relatype*) NULL,
     &reloc,
     elfcpp::SHT_REL,
     r_type,
@@ -9546,32 +9802,38 @@ Target_mips<size, big_endian>::Relocate::relocate(
                         section_size_type)
 {
   Mips_address r_offset;
-  typename elfcpp::Elf_types<size>::Elf_WXword r_info;
+  unsigned int r_sym;
+  unsigned int r_type;
   typename elfcpp::Elf_types<size>::Elf_Swxword r_addend;
 
   if (rel_type == elfcpp::SHT_RELA)
     {
-      const elfcpp::Rela<size, big_endian> rela(preloc);
+      const Relatype rela(preloc);
       r_offset = rela.get_r_offset();
-      r_info = rela.get_r_info();
+      r_sym = Mips_classify_reloc<elfcpp::SHT_RELA, size, big_endian>::
+         get_r_sym(&rela);
+      r_type = Mips_classify_reloc<elfcpp::SHT_RELA, size, big_endian>::
+         get_r_type(&rela);
       r_addend = rela.get_r_addend();
     }
   else
     {
-      const elfcpp::Rel<size, big_endian> rel(preloc);
+
+      const Reltype rel(preloc);
       r_offset = rel.get_r_offset();
-      r_info = rel.get_r_info();
+      r_sym = Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>::
+         get_r_sym(&rel);
+      r_type = Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>::
+         get_r_type(&rel);
       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;
 
   Mips_relobj<size, big_endian>* object =
-    Mips_relobj<size, big_endian>::as_mips_relobj(relinfo->object);
+      Mips_relobj<size, big_endian>::as_mips_relobj(relinfo->object);
 
-  unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
   bool target_is_16_bit_code = false;
   bool target_is_micromips_code = false;
   bool cross_mode_jump;
index 25af3417e8b4b239f7d710a24b60d3a8f358008e..95f6d56e0861b4b1a49c3a8844adb9b87c3e3c09 100644 (file)
@@ -2710,7 +2710,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
                     unsigned int sh_type, unsigned int shndx,
                     const unsigned char* prelocs, 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);
 
   template<int sh_type>
   void
@@ -2718,7 +2719,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
                             unsigned int shndx, const unsigned char* prelocs,
                             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);
 
   // Find all functions in a section.
   void
index b1c5aeaa5f53f48b522cc544b8e9821ebd4c3d7a..e26a198671128cd54d66eee446aa0bc4d239805f 100644 (file)
@@ -663,6 +663,21 @@ class Target_powerpc : public Sized_target<size, big_endian>
                          const unsigned char* plocal_symbols,
                          Relocatable_relocs*);
 
+  // Scan the relocs for --emit-relocs.
+  void
+  emit_relocs_scan(Symbol_table* symtab,
+                  Layout* layout,
+                  Sized_relobj_file<size, big_endian>* object,
+                  unsigned int data_shndx,
+                  unsigned int sh_type,
+                  const unsigned char* prelocs,
+                  size_t reloc_count,
+                  Output_section* output_section,
+                  bool needs_special_offset_handling,
+                  size_t local_symbol_count,
+                  const unsigned char* plocal_syms,
+                  Relocatable_relocs* rr);
+
   // Emit relocations for a section.
   void
   relocate_relocs(const Relocate_info<size, big_endian>*,
@@ -1105,19 +1120,6 @@ class Target_powerpc : public Sized_target<size, big_endian>
     }
   };
 
-  // A class which returns the size required for a relocation type,
-  // used while scanning relocs during a relocatable link.
-  class Relocatable_size_for_reloc
-  {
-   public:
-    unsigned int
-    get_size_for_reloc(unsigned int, Relobj*)
-    {
-      gold_unreachable();
-      return 0;
-    }
-  };
-
   // Optimize the TLS relocation type based on what we know about the
   // symbol.  IS_FINAL is true if the final address of this symbol is
   // known at link time.
@@ -6430,7 +6432,9 @@ Target_powerpc<size, big_endian>::gc_process_relocs(
     const unsigned char* plocal_symbols)
 {
   typedef Target_powerpc<size, big_endian> Powerpc;
-  typedef typename Target_powerpc<size, big_endian>::Scan Scan;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+
   Powerpc_relobj<size, big_endian>* ppc_object
     = static_cast<Powerpc_relobj<size, big_endian>*>(object);
   if (size == 64)
@@ -6460,8 +6464,7 @@ Target_powerpc<size, big_endian>::gc_process_relocs(
       return;
     }
 
-  gold::gc_process_relocs<size, big_endian, Powerpc, elfcpp::SHT_RELA, Scan,
-                         typename Target_powerpc::Relocatable_size_for_reloc>(
+  gold::gc_process_relocs<size, big_endian, Powerpc, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -6707,7 +6710,8 @@ Target_powerpc<size, big_endian>::scan_relocs(
     const unsigned char* plocal_symbols)
 {
   typedef Target_powerpc<size, big_endian> Powerpc;
-  typedef typename Target_powerpc<size, big_endian>::Scan Scan;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
 
   if (sh_type == elfcpp::SHT_REL)
     {
@@ -6716,7 +6720,7 @@ Target_powerpc<size, big_endian>::scan_relocs(
       return;
     }
 
-  gold::scan_relocs<size, big_endian, Powerpc, elfcpp::SHT_RELA, Scan>(
+  gold::scan_relocs<size, big_endian, Powerpc, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -8177,11 +8181,13 @@ Target_powerpc<size, big_endian>::relocate_section(
   typedef typename Target_powerpc<size, big_endian>::Relocate Powerpc_relocate;
   typedef typename Target_powerpc<size, big_endian>::Relocate_comdat_behavior
     Powerpc_comdat_behavior;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
 
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_section<size, big_endian, Powerpc, elfcpp::SHT_RELA,
-                        Powerpc_relocate, Powerpc_comdat_behavior>(
+  gold::relocate_section<size, big_endian, Powerpc, Powerpc_relocate,
+                        Powerpc_comdat_behavior, Classify_reloc>(
     relinfo,
     this,
     prelocs,
@@ -8194,9 +8200,26 @@ Target_powerpc<size, big_endian>::relocate_section(
     reloc_symbol_changes);
 }
 
+template<int size, bool big_endian>
 class Powerpc_scan_relocatable_reloc
 {
 public:
+  typedef typename Reloc_types<elfcpp::SHT_RELA, size, big_endian>::Reloc
+      Reltype;
+  static const int reloc_size =
+      Reloc_types<elfcpp::SHT_RELA, size, big_endian>::reloc_size;
+  static const int sh_type = elfcpp::SHT_RELA;
+
+  // Return the symbol referred to by the relocation.
+  static inline unsigned int
+  get_r_sym(const Reltype* reloc)
+  { return elfcpp::elf_r_sym<size>(reloc->get_r_info()); }
+
+  // Return the type of the relocation.
+  static inline unsigned int
+  get_r_type(const Reltype* reloc)
+  { return elfcpp::elf_r_type<size>(reloc->get_r_info()); }
+
   // Return the strategy to use for a local symbol which is not a
   // section symbol, given the relocation type.
   inline Relocatable_relocs::Reloc_strategy
@@ -8244,10 +8267,11 @@ Target_powerpc<size, big_endian>::scan_relocatable_relocs(
     const unsigned char* plocal_symbols,
     Relocatable_relocs* rr)
 {
+  typedef Powerpc_scan_relocatable_reloc<size, big_endian> Scan_strategy;
+
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::scan_relocatable_relocs<size, big_endian, elfcpp::SHT_RELA,
-                               Powerpc_scan_relocatable_reloc>(
+  gold::scan_relocatable_relocs<size, big_endian, Scan_strategy>(
     symtab,
     layout,
     object,
@@ -8261,6 +8285,45 @@ Target_powerpc<size, big_endian>::scan_relocatable_relocs(
     rr);
 }
 
+// Scan the relocs for --emit-relocs.
+
+template<int size, bool big_endian>
+void
+Target_powerpc<size, big_endian>::emit_relocs_scan(
+    Symbol_table* symtab,
+    Layout* layout,
+    Sized_relobj_file<size, big_endian>* object,
+    unsigned int data_shndx,
+    unsigned int sh_type,
+    const unsigned char* prelocs,
+    size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
+    size_t local_symbol_count,
+    const unsigned char* plocal_syms,
+    Relocatable_relocs* rr)
+{
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+  typedef gold::Default_emit_relocs_strategy<Classify_reloc>
+      Emit_relocs_strategy;
+
+  gold_assert(sh_type == elfcpp::SHT_RELA);
+
+  gold::scan_relocatable_relocs<size, big_endian, Emit_relocs_strategy>(
+    symtab,
+    layout,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_syms,
+    rr);
+}
+
 // Emit relocations for a section.
 // This is a modified version of the function by the same name in
 // target-reloc.h.  Using relocate_special_relocatable for
index b42be59e0d8acc46e2942aff6eafec84e616f432..7334b9f6ee799c0441e036ba1bf6749152c49ea2 100644 (file)
@@ -56,10 +56,6 @@ struct Reloc_types<elfcpp::SHT_REL, size, big_endian>
   set_reloc_addend(Reloc_write*,
                   typename elfcpp::Elf_types<size>::Elf_Swxword)
   { gold_unreachable(); }
-
-  static inline void
-  copy_reloc_addend(Reloc_write*, const Reloc*)
-  { gold_unreachable(); }
 };
 
 template<int size, bool big_endian>
@@ -81,10 +77,6 @@ struct Reloc_types<elfcpp::SHT_RELA, size, big_endian>
   set_reloc_addend(Reloc_write* p,
                   typename elfcpp::Elf_types<size>::Elf_Swxword val)
   { p->put_r_addend(val); }
-
-  static inline void
-  copy_reloc_addend(Reloc_write* to, const Reloc* from)
-  { to->put_r_addend(from->get_r_addend()); }
 };
 
 }; // End namespace gold.
index 3354019e713168b49effff5bf11778232746282f..b1a50e6807f1b50b9579fbeddcdb7ba1b7730248 100644 (file)
@@ -424,8 +424,8 @@ Sized_relobj_file<size, big_endian>::do_gc_process_relocs(Symbol_table* symtab,
 template<int size, bool big_endian>
 void
 Sized_relobj_file<size, big_endian>::do_scan_relocs(Symbol_table* symtab,
-                                              Layout* layout,
-                                              Read_relocs_data* rd)
+                                                   Layout* layout,
+                                                   Read_relocs_data* rd)
 {
   Sized_target<size, big_endian>* target =
     parameters->sized_target<size, big_endian>();
@@ -501,41 +501,6 @@ Sized_relobj_file<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>
@@ -546,40 +511,18 @@ Sized_relobj_file<size, big_endian>::emit_relocs_scan(
     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_file<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,
@@ -628,8 +571,8 @@ Sized_relobj_file<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_)
@@ -1025,7 +968,7 @@ Sized_relobj_file<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;
@@ -1142,6 +1085,7 @@ Sized_relobj_file<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);
@@ -1240,20 +1184,21 @@ Sized_relobj_file<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);
     }
 }
 
@@ -1271,7 +1216,8 @@ Sized_relobj_file<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;
@@ -1283,10 +1229,10 @@ Sized_relobj_file<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;
 
@@ -1305,9 +1251,9 @@ Sized_relobj_file<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))
            {
+             Reltype reloc(pr);
              section_offset_type offset =
                convert_to_section_size_type(reloc.get_r_offset());
              non_split_refs.push_back(offset);
@@ -1378,9 +1324,7 @@ Sized_relobj_file<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;
 
@@ -1600,11 +1544,9 @@ Track_relocs<size, big_endian>::next_symndx() const
 {
   if (this->pos_ >= this->len_)
     return -1U;
-
-  // 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());
+  Sized_target<size, big_endian>* target
+      = parameters->sized_target<size, big_endian>();
+  return target->get_r_sym(this->prelocs_ + this->pos_);
 }
 
 // Return the addend of the next reloc, or 0 if there isn't one.
index eb92fb7c1e768d465ba3ded403225e6f69014e06..2671441a2ac7bb2ff06a4909b52edb25cc309774 100644 (file)
@@ -348,6 +348,21 @@ class Target_s390 : public Sized_target<size, true>
                          const unsigned char* plocal_symbols,
                          Relocatable_relocs*);
 
+  // Scan the relocs for --emit-relocs.
+  void
+  emit_relocs_scan(Symbol_table* symtab,
+                  Layout* layout,
+                  Sized_relobj_file<size, true>* object,
+                  unsigned int data_shndx,
+                  unsigned int sh_type,
+                  const unsigned char* prelocs,
+                  size_t reloc_count,
+                  Output_section* output_section,
+                  bool needs_special_offset_handling,
+                  size_t local_symbol_count,
+                  const unsigned char* plocal_syms,
+                  Relocatable_relocs* rr);
+
   // Return a string used to fill a code section with nops.
   std::string
   do_code_fill(section_size_type length) const;
@@ -596,15 +611,6 @@ class Target_s390 : public Sized_target<size, true>
                 section_size_type view_size);
   };
 
-  // A class which returns the size required for a relocation type,
-  // used while scanning relocs during a relocatable link.
-  class Relocatable_size_for_reloc
-  {
-   public:
-    unsigned int
-    get_size_for_reloc(unsigned int, Relobj*);
-  };
-
   // Adjust TLS relocation type based on the options and whether this
   // is a local symbol.
   static tls::Tls_optimization
@@ -3086,13 +3092,13 @@ Target_s390<size>::gc_process_relocs(Symbol_table* symtab,
                                       size_t local_symbol_count,
                                       const unsigned char* plocal_symbols)
 {
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, true>
+      Classify_reloc;
 
   if (sh_type == elfcpp::SHT_REL)
     return;
 
-  gold::gc_process_relocs<size, true, Target_s390<size>, elfcpp::SHT_RELA,
-                         typename Target_s390<size>::Scan,
-                         typename Target_s390<size>::Relocatable_size_for_reloc>(
+  gold::gc_process_relocs<size, true, Target_s390<size>, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -3924,6 +3930,9 @@ Target_s390<size>::scan_relocs(Symbol_table* symtab,
                                 size_t local_symbol_count,
                                 const unsigned char* plocal_symbols)
 {
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, true>
+      Classify_reloc;
+
   if (sh_type == elfcpp::SHT_REL)
     {
       gold_error(_("%s: unsupported REL reloc section"),
@@ -3931,8 +3940,7 @@ Target_s390<size>::scan_relocs(Symbol_table* symtab,
       return;
     }
 
-  gold::scan_relocs<size, true, Target_s390<size>, elfcpp::SHT_RELA,
-      typename Target_s390<size>::Scan>(
+  gold::scan_relocs<size, true, Target_s390<size>, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -4019,113 +4027,50 @@ Target_s390<size>::do_finalize_sections(
     }
 }
 
-// Return the size of a relocation while scanning during a relocatable
-// link.
+// Scan the relocs during a relocatable link.
 
 template<int size>
-unsigned int
-Target_s390<size>::Relocatable_size_for_reloc::get_size_for_reloc(
-    unsigned int r_type,
-    Relobj* object)
+void
+Target_s390<size>::scan_relocatable_relocs(
+    Symbol_table* symtab,
+    Layout* layout,
+    Sized_relobj_file<size, true>* object,
+    unsigned int data_shndx,
+    unsigned int sh_type,
+    const unsigned char* prelocs,
+    size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
+    size_t local_symbol_count,
+    const unsigned char* plocal_symbols,
+    Relocatable_relocs* rr)
 {
-  switch (r_type)
-    {
-    case elfcpp::R_390_NONE:
-    case elfcpp::R_390_GNU_VTINHERIT:
-    case elfcpp::R_390_GNU_VTENTRY:
-    case elfcpp::R_390_TLS_GD32:          // Global-dynamic
-    case elfcpp::R_390_TLS_GD64:
-    case elfcpp::R_390_TLS_GDCALL:
-    case elfcpp::R_390_TLS_LDM32:         // Local-dynamic
-    case elfcpp::R_390_TLS_LDM64:
-    case elfcpp::R_390_TLS_LDO32:
-    case elfcpp::R_390_TLS_LDO64:
-    case elfcpp::R_390_TLS_LDCALL:
-    case elfcpp::R_390_TLS_IE32:          // Initial-exec
-    case elfcpp::R_390_TLS_IE64:
-    case elfcpp::R_390_TLS_IEENT:
-    case elfcpp::R_390_TLS_GOTIE12:
-    case elfcpp::R_390_TLS_GOTIE20:
-    case elfcpp::R_390_TLS_GOTIE32:
-    case elfcpp::R_390_TLS_GOTIE64:
-    case elfcpp::R_390_TLS_LOAD:
-    case elfcpp::R_390_TLS_LE32:          // Local-exec
-    case elfcpp::R_390_TLS_LE64:
-      return 0;
-
-    case elfcpp::R_390_64:
-    case elfcpp::R_390_PC64:
-    case elfcpp::R_390_GOT64:
-    case elfcpp::R_390_PLT64:
-    case elfcpp::R_390_GOTOFF64:
-    case elfcpp::R_390_GOTPLT64:
-    case elfcpp::R_390_PLTOFF64:
-      return 8;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, true>
+      Classify_reloc;
+  typedef gold::Default_scan_relocatable_relocs<Classify_reloc>
+      Scan_relocatable_relocs;
 
-    case elfcpp::R_390_32:
-    case elfcpp::R_390_PC32:
-    case elfcpp::R_390_GOT32:
-    case elfcpp::R_390_PLT32:
-    case elfcpp::R_390_GOTOFF32:
-    case elfcpp::R_390_GOTPC:
-    case elfcpp::R_390_PC32DBL:
-    case elfcpp::R_390_PLT32DBL:
-    case elfcpp::R_390_GOTPCDBL:
-    case elfcpp::R_390_GOTENT:
-    case elfcpp::R_390_GOTPLT32:
-    case elfcpp::R_390_GOTPLTENT:
-    case elfcpp::R_390_PLTOFF32:
-    case elfcpp::R_390_20:
-    case elfcpp::R_390_GOT20:
-    case elfcpp::R_390_GOTPLT20:
-      return 4;
-
-    case elfcpp::R_390_PC24DBL:
-    case elfcpp::R_390_PLT24DBL:
-      return 3;
-
-    case elfcpp::R_390_12:
-    case elfcpp::R_390_GOT12:
-    case elfcpp::R_390_GOTPLT12:
-    case elfcpp::R_390_PC12DBL:
-    case elfcpp::R_390_PLT12DBL:
-    case elfcpp::R_390_16:
-    case elfcpp::R_390_GOT16:
-    case elfcpp::R_390_PC16:
-    case elfcpp::R_390_PC16DBL:
-    case elfcpp::R_390_PLT16DBL:
-    case elfcpp::R_390_GOTOFF16:
-    case elfcpp::R_390_GOTPLT16:
-    case elfcpp::R_390_PLTOFF16:
-      return 2;
-
-    case elfcpp::R_390_8:
-      return 1;
-
-      // These are relocations which should only be seen by the
-      // dynamic linker, and should never be seen here.
-    case elfcpp::R_390_COPY:
-    case elfcpp::R_390_GLOB_DAT:
-    case elfcpp::R_390_JMP_SLOT:
-    case elfcpp::R_390_RELATIVE:
-    case elfcpp::R_390_IRELATIVE:
-    case elfcpp::R_390_TLS_DTPMOD:
-    case elfcpp::R_390_TLS_DTPOFF:
-    case elfcpp::R_390_TLS_TPOFF:
-      object->error(_("unexpected reloc %u in object file"), r_type);
-      return 0;
+  gold_assert(sh_type == elfcpp::SHT_RELA);
 
-    default:
-      object->error(_("unsupported reloc %u in object file"), r_type);
-      return 0;
-    }
+  gold::scan_relocatable_relocs<size, true, Scan_relocatable_relocs>(
+    symtab,
+    layout,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_symbols,
+    rr);
 }
 
-// Scan the relocs during a relocatable link.
+// Scan the relocs for --emit-relocs.
 
 template<int size>
 void
-Target_s390<size>::scan_relocatable_relocs(
+Target_s390<size>::emit_relocs_scan(
     Symbol_table* symtab,
     Layout* layout,
     Sized_relobj_file<size, true>* object,
@@ -4136,16 +4081,17 @@ Target_s390<size>::scan_relocatable_relocs(
     Output_section* output_section,
     bool needs_special_offset_handling,
     size_t local_symbol_count,
-    const unsigned char* plocal_symbols,
+    const unsigned char* plocal_syms,
     Relocatable_relocs* rr)
 {
-  gold_assert(sh_type == elfcpp::SHT_RELA);
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, true>
+      Classify_reloc;
+  typedef gold::Default_emit_relocs_strategy<Classify_reloc>
+      Emit_relocs_strategy;
 
-  typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
-    Relocatable_size_for_reloc> Scan_relocatable_relocs;
+  gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::scan_relocatable_relocs<size, true, elfcpp::SHT_RELA,
-      Scan_relocatable_relocs>(
+  gold::scan_relocatable_relocs<size, true, Emit_relocs_strategy>(
     symtab,
     layout,
     object,
@@ -4155,7 +4101,7 @@ Target_s390<size>::scan_relocatable_relocs(
     output_section,
     needs_special_offset_handling,
     local_symbol_count,
-    plocal_symbols,
+    plocal_syms,
     rr);
 }
 
@@ -4176,9 +4122,12 @@ Target_s390<size>::relocate_relocs(
     unsigned char* reloc_view,
     section_size_type reloc_view_size)
 {
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, true>
+      Classify_reloc;
+
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_relocs<size, true, elfcpp::SHT_RELA>(
+  gold::relocate_relocs<size, true, Classify_reloc>(
     relinfo,
     prelocs,
     reloc_count,
@@ -4259,11 +4208,13 @@ Target_s390<size>::relocate_section(
     section_size_type view_size,
     const Reloc_symbol_changes* reloc_symbol_changes)
 {
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, true>
+      Classify_reloc;
+
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_section<size, true, Target_s390<size>, elfcpp::SHT_RELA,
-                        typename Target_s390<size>::Relocate,
-                        gold::Default_comdat_behavior>(
+  gold::relocate_section<size, true, Target_s390<size>, Relocate,
+                        gold::Default_comdat_behavior, Classify_reloc>(
     relinfo,
     this,
     prelocs,
index 049e0ab8986fc7e66da58424e65312b21e194ba8..c97c32ceb70dae85f640e84295297cf0d8ba2d6d 100644 (file)
@@ -131,6 +131,21 @@ class Target_sparc : public Sized_target<size, big_endian>
                          const unsigned char* plocal_symbols,
                          Relocatable_relocs*);
 
+  // Scan the relocs for --emit-relocs.
+  void
+  emit_relocs_scan(Symbol_table* symtab,
+                  Layout* layout,
+                  Sized_relobj_file<size, big_endian>* object,
+                  unsigned int data_shndx,
+                  unsigned int sh_type,
+                  const unsigned char* prelocs,
+                  size_t reloc_count,
+                  Output_section* output_section,
+                  bool needs_special_offset_handling,
+                  size_t local_symbol_count,
+                  const unsigned char* plocal_syms,
+                  Relocatable_relocs* rr);
+
   // Emit relocations for a section.
   void
   relocate_relocs(const Relocate_info<size, big_endian>*,
@@ -345,15 +360,6 @@ class Target_sparc : public Sized_target<size, big_endian>
     unsigned char *reloc_adjust_addr_;
   };
 
-  // A class which returns the size required for a relocation type,
-  // used while scanning relocs during a relocatable link.
-  class Relocatable_size_for_reloc
-  {
-   public:
-    unsigned int
-    get_size_for_reloc(unsigned int, Relobj*);
-  };
-
   // Get the GOT section, creating it if necessary.
   Output_data_got<size, big_endian>*
   got_section(Symbol_table*, Layout*);
@@ -3036,9 +3042,10 @@ Target_sparc<size, big_endian>::gc_process_relocs(
 {
   typedef Target_sparc<size, big_endian> Sparc;
   typedef typename Target_sparc<size, big_endian>::Scan Scan;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
 
-  gold::gc_process_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan,
-                         typename Target_sparc::Relocatable_size_for_reloc>(
+  gold::gc_process_relocs<size, big_endian, Sparc, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -3070,7 +3077,8 @@ Target_sparc<size, big_endian>::scan_relocs(
                        const unsigned char* plocal_symbols)
 {
   typedef Target_sparc<size, big_endian> Sparc;
-  typedef typename Target_sparc<size, big_endian>::Scan Scan;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
 
   if (sh_type == elfcpp::SHT_REL)
     {
@@ -3079,7 +3087,7 @@ Target_sparc<size, big_endian>::scan_relocs(
       return;
     }
 
-  gold::scan_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan>(
+  gold::scan_relocs<size, big_endian, Sparc, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -4142,11 +4150,13 @@ Target_sparc<size, big_endian>::relocate_section(
 {
   typedef Target_sparc<size, big_endian> Sparc;
   typedef typename Target_sparc<size, big_endian>::Relocate Sparc_relocate;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
 
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_section<size, big_endian, Sparc, elfcpp::SHT_RELA,
-                        Sparc_relocate, gold::Default_comdat_behavior>(
+  gold::relocate_section<size, big_endian, Sparc, Sparc_relocate,
+                        gold::Default_comdat_behavior, Classify_reloc>(
     relinfo,
     this,
     prelocs,
@@ -4159,20 +4169,6 @@ Target_sparc<size, big_endian>::relocate_section(
     reloc_symbol_changes);
 }
 
-// Return the size of a relocation while scanning during a relocatable
-// link.
-
-template<int size, bool big_endian>
-unsigned int
-Target_sparc<size, big_endian>::Relocatable_size_for_reloc::get_size_for_reloc(
-    unsigned int,
-    Relobj*)
-{
-  // We are always SHT_RELA, so we should never get here.
-  gold_unreachable();
-  return 0;
-}
-
 // Scan the relocs during a relocatable link.
 
 template<int size, bool big_endian>
@@ -4191,13 +4187,14 @@ Target_sparc<size, big_endian>::scan_relocatable_relocs(
                        const unsigned char* plocal_symbols,
                        Relocatable_relocs* rr)
 {
-  gold_assert(sh_type == elfcpp::SHT_RELA);
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+  typedef gold::Default_scan_relocatable_relocs<Classify_reloc>
+      Scan_relocatable_relocs;
 
-  typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
-    Relocatable_size_for_reloc> Scan_relocatable_relocs;
+  gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::scan_relocatable_relocs<size, big_endian, elfcpp::SHT_RELA,
-      Scan_relocatable_relocs>(
+  gold::scan_relocatable_relocs<size, big_endian, Scan_relocatable_relocs>(
     symtab,
     layout,
     object,
@@ -4211,6 +4208,45 @@ Target_sparc<size, big_endian>::scan_relocatable_relocs(
     rr);
 }
 
+// Scan the relocs for --emit-relocs.
+
+template<int size, bool big_endian>
+void
+Target_sparc<size, big_endian>::emit_relocs_scan(
+    Symbol_table* symtab,
+    Layout* layout,
+    Sized_relobj_file<size, big_endian>* object,
+    unsigned int data_shndx,
+    unsigned int sh_type,
+    const unsigned char* prelocs,
+    size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
+    size_t local_symbol_count,
+    const unsigned char* plocal_syms,
+    Relocatable_relocs* rr)
+{
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+  typedef gold::Default_emit_relocs_strategy<Classify_reloc>
+      Emit_relocs_strategy;
+
+  gold_assert(sh_type == elfcpp::SHT_RELA);
+
+  gold::scan_relocatable_relocs<size, big_endian, Emit_relocs_strategy>(
+    symtab,
+    layout,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_syms,
+    rr);
+}
+
 // Emit relocations for a section.
 
 template<int size, bool big_endian>
@@ -4228,9 +4264,12 @@ Target_sparc<size, big_endian>::relocate_relocs(
     unsigned char* reloc_view,
     section_size_type reloc_view_size)
 {
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_relocs<size, big_endian, elfcpp::SHT_RELA>(
+  gold::relocate_relocs<size, big_endian, Classify_reloc>(
     relinfo,
     prelocs,
     reloc_count,
index cec5ee173deb6e805df7a2cecae06459118d0156..bdf673d741e20fc395bfd9b7fd3cc8050a46e46e 100644 (file)
@@ -39,8 +39,8 @@ namespace gold
 // avoid making a function call for each relocation, and to avoid
 // repeating the generic code for each target.
 
-template<int size, bool big_endian, typename Target_type, int sh_type,
-        typename Scan>
+template<int size, bool big_endian, typename Target_type,
+        typename Scan, typename Classify_reloc>
 inline void
 scan_relocs(
     Symbol_table* symtab,
@@ -55,8 +55,8 @@ scan_relocs(
     size_t local_count,
     const unsigned char* plocal_syms)
 {
-  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
-  const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
+  typedef typename Classify_reloc::Reltype Reltype;
+  const int reloc_size = Classify_reloc::reloc_size;
   const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
   Scan scan;
 
@@ -69,9 +69,8 @@ scan_relocs(
                                                      reloc.get_r_offset()))
        continue;
 
-      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);
+      unsigned int r_sym = Classify_reloc::get_r_sym(&reloc);
+      unsigned int r_type = Classify_reloc::get_r_type(&reloc);
 
       if (r_sym < local_count)
        {
@@ -253,9 +252,10 @@ issue_undefined_symbol_error(const Symbol* sym)
 // symbol for the relocation, ignoring the symbol index in the
 // relocation.
 
-template<int size, bool big_endian, typename Target_type, int sh_type,
+template<int size, bool big_endian, typename Target_type,
         typename Relocate,
-        typename Relocate_comdat_behavior>
+        typename Relocate_comdat_behavior,
+        typename Classify_reloc>
 inline void
 relocate_section(
     const Relocate_info<size, big_endian>* relinfo,
@@ -269,8 +269,8 @@ relocate_section(
     section_size_type view_size,
     const Reloc_symbol_changes* reloc_symbol_changes)
 {
-  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
-  const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
+  typedef typename Classify_reloc::Reltype Reltype;
+  const int reloc_size = Classify_reloc::reloc_size;
   Relocate relocate;
   Relocate_comdat_behavior relocate_comdat_behavior;
 
@@ -295,8 +295,7 @@ relocate_section(
            continue;
        }
 
-      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 = Classify_reloc::get_r_sym(&reloc);
 
       const Sized_symbol<size>* sym;
 
@@ -399,8 +398,8 @@ relocate_section(
       if (offset < 0 || static_cast<section_size_type>(offset) >= view_size)
        v = NULL;
 
-      if (!relocate.relocate(relinfo, sh_type, target, output_section,
-                            i, prelocs, sym, psymval,
+      if (!relocate.relocate(relinfo, Classify_reloc::sh_type, target,
+                            output_section, i, prelocs, sym, psymval,
                             v, view_address + offset, view_size))
        continue;
 
@@ -464,18 +463,90 @@ apply_relocation(const Relocate_info<size, big_endian>* relinfo,
                    view + r_offset, address + r_offset, view_size);
 }
 
+// A class for inquiring about properties of a relocation,
+// used while scanning relocs during a relocatable link and
+// garbage collection. This class may be used as the default
+// for SHT_RELA targets, but SHT_REL targets must implement
+// a derived class that overrides get_size_for_reloc.
+// The MIPS-64 target also needs to override the methods
+// for accessing the r_sym and r_type fields of a relocation,
+// due to its non-standard use of the r_info field.
+
+template<int sh_type_, int size, bool big_endian>
+class Default_classify_reloc
+{
+ public:
+  typedef typename Reloc_types<sh_type_, size, big_endian>::Reloc
+      Reltype;
+  typedef typename Reloc_types<sh_type_, size, big_endian>::Reloc_write
+      Reltype_write;
+  static const int reloc_size =
+      Reloc_types<sh_type_, size, big_endian>::reloc_size;
+  static const int sh_type = sh_type_;
+
+  // Return the symbol referred to by the relocation.
+  static inline unsigned int
+  get_r_sym(const Reltype* reloc)
+  { return elfcpp::elf_r_sym<size>(reloc->get_r_info()); }
+
+  // Return the type of the relocation.
+  static inline unsigned int
+  get_r_type(const Reltype* reloc)
+  { return elfcpp::elf_r_type<size>(reloc->get_r_info()); }
+
+  // Return the explicit addend of the relocation (return 0 for SHT_REL).
+  static inline typename elfcpp::Elf_types<size>::Elf_Swxword
+  get_r_addend(const Reltype* reloc)
+  { return Reloc_types<sh_type_, size, big_endian>::get_reloc_addend(reloc); }
+
+  // Write the r_info field to a new reloc, using the r_info field from
+  // the original reloc, replacing the r_sym field with R_SYM.
+  static inline void
+  put_r_info(Reltype_write* new_reloc, Reltype* reloc, unsigned int r_sym)
+  {
+    unsigned int r_type = elfcpp::elf_r_type<size>(reloc->get_r_info());
+    new_reloc->put_r_info(elfcpp::elf_r_info<size>(r_sym, r_type));
+  }
+
+  // Write the r_addend field to a new reloc.
+  static inline void
+  put_r_addend(Reltype_write* to,
+              typename elfcpp::Elf_types<size>::Elf_Swxword addend)
+  { Reloc_types<sh_type_, size, big_endian>::set_reloc_addend(to, addend); }
+
+  // Return the size of the addend of the relocation (only used for SHT_REL).
+  static unsigned int
+  get_size_for_reloc(unsigned int, Relobj*)
+  {
+    gold_unreachable();
+    return 0;
+  }
+};
+
 // This class may be used as a typical class for the
-// Scan_relocatable_reloc parameter to scan_relocatable_relocs.  The
-// template parameter Classify_reloc must be a class type which
-// provides a function get_size_for_reloc which returns the number of
-// bytes to which a reloc applies.  This class is intended to capture
-// the most typical target behaviour, while still permitting targets
-// to define their own independent class for Scan_relocatable_reloc.
-
-template<int sh_type, typename Classify_reloc>
+// Scan_relocatable_reloc parameter to scan_relocatable_relocs.
+// This class is intended to capture the most typical target behaviour,
+// while still permitting targets to define their own independent class
+// for Scan_relocatable_reloc.
+
+template<typename Classify_reloc>
 class Default_scan_relocatable_relocs
 {
  public:
+  typedef typename Classify_reloc::Reltype Reltype;
+  static const int reloc_size = Classify_reloc::reloc_size;
+  static const int sh_type = Classify_reloc::sh_type;
+
+  // Return the symbol referred to by the relocation.
+  static inline unsigned int
+  get_r_sym(const Reltype* reloc)
+  { return Classify_reloc::get_r_sym(reloc); }
+
+  // Return the type of the relocation.
+  static inline unsigned int
+  get_r_type(const Reltype* reloc)
+  { return Classify_reloc::get_r_type(reloc); }
+
   // Return the strategy to use for a local symbol which is not a
   // section symbol, given the relocation type.
   inline Relocatable_relocs::Reloc_strategy
@@ -497,8 +568,7 @@ class Default_scan_relocatable_relocs
       return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA;
     else
       {
-       Classify_reloc classify;
-       switch (classify.get_size_for_reloc(r_type, object))
+       switch (Classify_reloc::get_size_for_reloc(r_type, object))
          {
          case 0:
            return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0;
@@ -523,6 +593,56 @@ class Default_scan_relocatable_relocs
   { return Relocatable_relocs::RELOC_COPY; }
 };
 
+// This is a strategy class used with scan_relocatable_relocs
+// and --emit-relocs.
+
+template<typename Classify_reloc>
+class Default_emit_relocs_strategy
+{
+ public:
+  typedef typename Classify_reloc::Reltype Reltype;
+  static const int reloc_size = Classify_reloc::reloc_size;
+  static const int sh_type = Classify_reloc::sh_type;
+
+  // Return the symbol referred to by the relocation.
+  static inline unsigned int
+  get_r_sym(const Reltype* reloc)
+  { return Classify_reloc::get_r_sym(reloc); }
+
+  // Return the type of the relocation.
+  static inline unsigned int
+  get_r_type(const Reltype* reloc)
+  { return Classify_reloc::get_r_type(reloc); }
+
+  // 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 relocs during a relocatable link.  This is a default
 // definition which should work for most targets.
 // Scan_relocatable_reloc must name a class type which provides three
@@ -531,8 +651,7 @@ class Default_scan_relocatable_relocs
 // local_section_strategy.  Most targets should be able to use
 // Default_scan_relocatable_relocs as this class.
 
-template<int size, bool big_endian, int sh_type,
-        typename Scan_relocatable_reloc>
+template<int size, bool big_endian, typename Scan_relocatable_reloc>
 void
 scan_relocatable_relocs(
     Symbol_table*,
@@ -547,8 +666,8 @@ scan_relocatable_relocs(
     const unsigned char* plocal_syms,
     Relocatable_relocs* rr)
 {
-  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
-  const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
+  typedef typename Scan_relocatable_reloc::Reltype Reltype;
+  const int reloc_size = Scan_relocatable_reloc::reloc_size;
   const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
   Scan_relocatable_reloc scan;
 
@@ -564,10 +683,9 @@ scan_relocatable_relocs(
        strategy = Relocatable_relocs::RELOC_DISCARD;
       else
        {
-         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);
+         const unsigned int r_sym = Scan_relocatable_reloc::get_r_sym(&reloc);
+         const unsigned int r_type =
+             Scan_relocatable_reloc::get_r_type(&reloc);
 
          if (r_sym >= local_symbol_count)
            strategy = scan.global_strategy(r_type, object, r_sym);
@@ -610,7 +728,7 @@ scan_relocatable_relocs(
 // Relocate relocs.  Called for a relocatable link, and for --emit-relocs.
 // This is a default definition which should work for most targets.
 
-template<int size, bool big_endian, int sh_type>
+template<int size, bool big_endian, typename Classify_reloc>
 void
 relocate_relocs(
     const Relocate_info<size, big_endian>* relinfo,
@@ -625,10 +743,9 @@ relocate_relocs(
     section_size_type reloc_view_size)
 {
   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
-  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
-  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc_write
-    Reltype_write;
-  const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
+  typedef typename Classify_reloc::Reltype Reltype;
+  typedef typename Classify_reloc::Reltype_write Reltype_write;
+  const int reloc_size = Classify_reloc::reloc_size;
   const Address invalid_address = static_cast<Address>(0) - 1;
 
   Sized_relobj_file<size, big_endian>* const object = relinfo->object;
@@ -647,8 +764,8 @@ relocate_relocs(
          // Target wants to handle this relocation.
          Sized_target<size, big_endian>* target =
            parameters->sized_target<size, big_endian>();
-         target->relocate_special_relocatable(relinfo, sh_type, prelocs,
-                                              i, output_section,
+         target->relocate_special_relocatable(relinfo, Classify_reloc::sh_type,
+                                              prelocs, i, output_section,
                                               offset_in_output_section,
                                               view, view_address,
                                               view_size, pwrite);
@@ -658,9 +775,7 @@ relocate_relocs(
       Reltype reloc(prelocs);
       Reltype_write reloc_write(pwrite);
 
-      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);
+      const unsigned int r_sym = Classify_reloc::get_r_sym(&reloc);
 
       // Get the new symbol index.
 
@@ -748,16 +863,15 @@ relocate_relocs(
        }
 
       reloc_write.put_r_offset(new_offset);
-      reloc_write.put_r_info(elfcpp::elf_r_info<size>(new_symndx, r_type));
+      Classify_reloc::put_r_info(&reloc_write, &reloc, new_symndx);
 
       // Handle the reloc addend based on the strategy.
 
       if (strategy == Relocatable_relocs::RELOC_COPY)
        {
-         if (sh_type == elfcpp::SHT_RELA)
-           Reloc_types<sh_type, size, big_endian>::
-             copy_reloc_addend(&reloc_write,
-                               &reloc);
+         if (Classify_reloc::sh_type == elfcpp::SHT_RELA)
+           Classify_reloc::put_r_addend(&reloc_write,
+                                        Classify_reloc::get_r_addend(&reloc));
        }
       else
        {
@@ -777,12 +891,10 @@ relocate_relocs(
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA:
              {
                typename elfcpp::Elf_types<size>::Elf_Swxword addend;
-               addend = Reloc_types<sh_type, size, big_endian>::
-                          get_reloc_addend(&reloc);
+               addend = Classify_reloc::get_r_addend(&reloc);
                gold_assert(os != NULL);
                addend = psymval->value(object, addend) - os->address();
-               Reloc_types<sh_type, size, big_endian>::
-                 set_reloc_addend(&reloc_write, addend);
+               Classify_reloc::put_r_addend(&reloc_write, addend);
              }
              break;
 
index 658fadfe7b70e3d718c1991981e2fcdf3143597a..cc3765a8c0fdb7be315262605a6d36705347b886 100644 (file)
@@ -152,7 +152,7 @@ Target::do_make_output_section(const char* name, elfcpp::Elf_Word type,
 // whether the symbol is a function.
 
 bool
-Target::do_is_call_to_non_split(const Symbol* sym, unsigned int) const
+Target::do_is_call_to_non_split(const Symbol* sym, const unsigned char*) const
 {
   return sym->type() == elfcpp::STT_FUNC;
 }
index 27e8a2ecdf400f8d0722be1a4e5af333cdb77879..c0f24eea795e8a658d2074fc8129d82bca9bea05 100644 (file)
@@ -321,13 +321,13 @@ class Target
   ehframe_datarel_base() const
   { return this->do_ehframe_datarel_base(); }
 
-  // Return true if a reference to SYM from a reloc of type R_TYPE
+  // Return true if a reference to SYM from a reloc at *PRELOC
   // means that the current function may call an object compiled
   // without -fsplit-stack.  SYM is known to be defined in an object
   // compiled without -fsplit-stack.
   bool
-  is_call_to_non_split(const Symbol* sym, unsigned int r_type) const
-  { return this->do_is_call_to_non_split(sym, r_type); }
+  is_call_to_non_split(const Symbol* sym, const unsigned char* preloc) const
+  { return this->do_is_call_to_non_split(sym, preloc); }
 
   // A function starts at OFFSET in section SHNDX in OBJECT.  That
   // function was compiled with -fsplit-stack, but it refers to a
@@ -661,7 +661,7 @@ class Target
   // default implementation is that any function not defined by the
   // ABI is a call to a non-split function.
   virtual bool
-  do_is_call_to_non_split(const Symbol* sym, unsigned int) const;
+  do_is_call_to_non_split(const Symbol* sym, const unsigned char*) const;
 
   // Virtual function which may be overridden by the child class.
   virtual void
@@ -926,6 +926,22 @@ class Sized_target : public Target
                          const unsigned char* plocal_symbols,
                          Relocatable_relocs*) = 0;
 
+  // Scan the relocs for --emit-relocs.  The parameters are
+  // like scan_relocatable_relocs.
+  virtual void
+  emit_relocs_scan(Symbol_table* symtab,
+                  Layout* layout,
+                  Sized_relobj_file<size, big_endian>* object,
+                  unsigned int data_shndx,
+                  unsigned int sh_type,
+                  const unsigned char* prelocs,
+                  size_t reloc_count,
+                  Output_section* output_section,
+                  bool needs_special_offset_handling,
+                  size_t local_symbol_count,
+                  const unsigned char* plocal_syms,
+                  Relocatable_relocs* rr) = 0;
+
   // Emit relocations for a section during a relocatable link, and for
   // --emit-relocs.  The parameters are like relocate_section, with
   // additional parameters for the view of the output reloc section.
@@ -1084,6 +1100,19 @@ class Sized_target : public Target
                              dst_obj, dst_shndx, dst_off);
   }
 
+  // Return the r_sym field from a relocation.
+  // Most targets can use the default version of this routine,
+  // but some targets have a non-standard r_info field, and will
+  // need to provide a target-specific version.
+  virtual unsigned int
+  get_r_sym(const unsigned char* preloc) const
+  {
+    // Since REL and RELA relocs share the same structure through
+    // the r_info field, we can just use REL here.
+    elfcpp::Rel<size, big_endian> rel(preloc);
+    return elfcpp::elf_r_sym<size>(rel.get_r_info());
+  }
+
  protected:
   Sized_target(const Target::Target_info* pti)
     : Target(pti)
index bb5ff708c2b396d56fdc1879cedcd3559f2a8a52..4049e4ae831944812c9996c904f86f9b253b6d20 100644 (file)
@@ -71,6 +71,14 @@ class Target_test : public Sized_target<size, big_endian>
                          const unsigned char*, Relocatable_relocs*)
   { ERROR("call to Target_test::scan_relocatable_relocs"); }
 
+  void
+  emit_relocs_scan(Symbol_table*, Layout*,
+                  Sized_relobj_file<size, big_endian>*, unsigned int,
+                  unsigned int, const unsigned char*,
+                  size_t, Output_section*, bool, size_t,
+                  const unsigned char*, Relocatable_relocs*)
+  { ERROR("call to Target_test::emit_relocs_scan"); }
+
   void
   relocate_relocs(const Relocate_info<size, big_endian>*,
                  unsigned int, const unsigned char*, size_t,
index 07960ef445248d722cf91b59ac91ab5276f223e5..bb1733025fbc16924cb1e81c856fc01cb5403980 100644 (file)
@@ -308,6 +308,21 @@ class Target_tilegx : public Sized_target<size, big_endian>
                           const unsigned char* plocal_symbols,
                           Relocatable_relocs*);
 
+  // Scan the relocs for --emit-relocs.
+  void
+  emit_relocs_scan(Symbol_table* symtab,
+                  Layout* layout,
+                  Sized_relobj_file<size, big_endian>* object,
+                  unsigned int data_shndx,
+                  unsigned int sh_type,
+                  const unsigned char* prelocs,
+                  size_t reloc_count,
+                  Output_section* output_section,
+                  bool needs_special_offset_handling,
+                  size_t local_symbol_count,
+                  const unsigned char* plocal_syms,
+                  Relocatable_relocs* rr);
+
   // Relocate a section during a relocatable link.
   void
   relocate_relocs(
@@ -523,15 +538,6 @@ class Target_tilegx : public Sized_target<size, big_endian>
             section_size_type);
   };
 
-  // A class which returns the size required for a relocation type,
-  // used while scanning relocs during a relocatable link.
-  class Relocatable_size_for_reloc
-  {
-   public:
-    unsigned int
-    get_size_for_reloc(unsigned int, Relobj*);
-  };
-
   // Adjust TLS relocation type based on the options and whether this
   // is a local symbol.
   static tls::Tls_optimization
@@ -4154,26 +4160,26 @@ Target_tilegx<size, big_endian>::gc_process_relocs(Symbol_table* symtab,
 {
   typedef Target_tilegx<size, big_endian> Tilegx;
   typedef typename Target_tilegx<size, big_endian>::Scan Scan;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
 
   if (sh_type == elfcpp::SHT_REL)
     {
       return;
     }
 
-   gold::gc_process_relocs<size, big_endian,
-                           Tilegx, elfcpp::SHT_RELA, Scan,
-      typename Target_tilegx<size, big_endian>::Relocatable_size_for_reloc>(
-          symtab,
-          layout,
-          this,
-          object,
-          data_shndx,
-          prelocs,
-          reloc_count,
-          output_section,
-          needs_special_offset_handling,
-          local_symbol_count,
-          plocal_symbols);
+   gold::gc_process_relocs<size, big_endian, Tilegx, Scan, Classify_reloc>(
+     symtab,
+     layout,
+     this,
+     object,
+     data_shndx,
+     prelocs,
+     reloc_count,
+     output_section,
+     needs_special_offset_handling,
+     local_symbol_count,
+     plocal_symbols);
 }
 // Scan relocations for a section.
 
@@ -4193,6 +4199,8 @@ Target_tilegx<size, big_endian>::scan_relocs(Symbol_table* symtab,
 {
   typedef Target_tilegx<size, big_endian> Tilegx;
   typedef typename Target_tilegx<size, big_endian>::Scan Scan;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
 
   if (sh_type == elfcpp::SHT_REL)
     {
@@ -4201,7 +4209,7 @@ Target_tilegx<size, big_endian>::scan_relocs(Symbol_table* symtab,
       return;
     }
 
-  gold::scan_relocs<size, big_endian, Tilegx, elfcpp::SHT_RELA, Scan>(
+  gold::scan_relocs<size, big_endian, Tilegx, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -4743,11 +4751,13 @@ Target_tilegx<size, big_endian>::relocate_section(
 {
   typedef Target_tilegx<size, big_endian> Tilegx;
   typedef typename Target_tilegx<size, big_endian>::Relocate Tilegx_relocate;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
 
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_section<size, big_endian, Tilegx, elfcpp::SHT_RELA,
-                        Tilegx_relocate, gold::Default_comdat_behavior>(
+  gold::relocate_section<size, big_endian, Tilegx, Tilegx_relocate,
+                        gold::Default_comdat_behavior, Classify_reloc>(
     relinfo,
     this,
     prelocs,
@@ -4788,24 +4798,50 @@ Target_tilegx<size, big_endian>::apply_relocation(
     view_size);
 }
 
-// Return the size of a relocation while scanning during a relocatable
-// link.
+// Scan the relocs during a relocatable link.
 
 template<int size, bool big_endian>
-unsigned int
-Target_tilegx<size,big_endian>::Relocatable_size_for_reloc::get_size_for_reloc(
-  unsigned int, Relobj*)
+void
+Target_tilegx<size, big_endian>::scan_relocatable_relocs(
+    Symbol_table* symtab,
+    Layout* layout,
+    Sized_relobj_file<size, big_endian>* object,
+    unsigned int data_shndx,
+    unsigned int sh_type,
+    const unsigned char* prelocs,
+    size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
+    size_t local_symbol_count,
+    const unsigned char* plocal_symbols,
+    Relocatable_relocs* rr)
 {
-  // We are always SHT_RELA, so we should never get here.
-  gold_unreachable();
-  return 0;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+  typedef gold::Default_scan_relocatable_relocs<Classify_reloc>
+      Scan_relocatable_relocs;
+
+  gold_assert(sh_type == elfcpp::SHT_RELA);
+
+  gold::scan_relocatable_relocs<size, big_endian, Scan_relocatable_relocs>(
+    symtab,
+    layout,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_symbols,
+    rr);
 }
 
-// Scan the relocs during a relocatable link.
+// Scan the relocs for --emit-relocs.
 
 template<int size, bool big_endian>
 void
-Target_tilegx<size, big_endian>::scan_relocatable_relocs(
+Target_tilegx<size, big_endian>::emit_relocs_scan(
     Symbol_table* symtab,
     Layout* layout,
     Sized_relobj_file<size, big_endian>* object,
@@ -4816,16 +4852,17 @@ Target_tilegx<size, big_endian>::scan_relocatable_relocs(
     Output_section* output_section,
     bool needs_special_offset_handling,
     size_t local_symbol_count,
-    const unsigned char* plocal_symbols,
+    const unsigned char* plocal_syms,
     Relocatable_relocs* rr)
 {
-  gold_assert(sh_type == elfcpp::SHT_RELA);
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+  typedef gold::Default_emit_relocs_strategy<Classify_reloc>
+      Emit_relocs_strategy;
 
-  typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
-    Relocatable_size_for_reloc> Scan_relocatable_relocs;
+  gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::scan_relocatable_relocs<size, big_endian, elfcpp::SHT_RELA,
-      Scan_relocatable_relocs>(
+  gold::scan_relocatable_relocs<size, big_endian, Emit_relocs_strategy>(
     symtab,
     layout,
     object,
@@ -4835,7 +4872,7 @@ Target_tilegx<size, big_endian>::scan_relocatable_relocs(
     output_section,
     needs_special_offset_handling,
     local_symbol_count,
-    plocal_symbols,
+    plocal_syms,
     rr);
 }
 
@@ -4856,9 +4893,12 @@ Target_tilegx<size, big_endian>::relocate_relocs(
     unsigned char* reloc_view,
     section_size_type reloc_view_size)
 {
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_relocs<size, big_endian, elfcpp::SHT_RELA>(
+  gold::relocate_relocs<size, big_endian, Classify_reloc>(
     relinfo,
     prelocs,
     reloc_count,
index c48a513e2f4acb776a257128e055c4752201de15..3cfc064d4b467de85c2c30dd1ac6dfbb4cfe9959 100644 (file)
@@ -496,6 +496,21 @@ class Target_x86_64 : public Sized_target<size, false>
                          const unsigned char* plocal_symbols,
                          Relocatable_relocs*);
 
+  // Scan the relocs for --emit-relocs.
+  void
+  emit_relocs_scan(Symbol_table* symtab,
+                  Layout* layout,
+                  Sized_relobj_file<size, false>* object,
+                  unsigned int data_shndx,
+                  unsigned int sh_type,
+                  const unsigned char* prelocs,
+                  size_t reloc_count,
+                  Output_section* output_section,
+                  bool needs_special_offset_handling,
+                  size_t local_symbol_count,
+                  const unsigned char* plocal_syms,
+                  Relocatable_relocs* rr);
+
   // Emit relocations for a section.
   void
   relocate_relocs(
@@ -859,15 +874,6 @@ class Target_x86_64 : public Sized_target<size, false>
     bool skip_call_tls_get_addr_;
   };
 
-  // A class which returns the size required for a relocation type,
-  // used while scanning relocs during a relocatable link.
-  class Relocatable_size_for_reloc
-  {
-   public:
-    unsigned int
-    get_size_for_reloc(unsigned int, Relobj*);
-  };
-
   // Check if relocation against this symbol is a candidate for
   // conversion from
   // mov foo@GOTPCREL(%rip), %reg
@@ -3191,15 +3197,16 @@ Target_x86_64<size>::gc_process_relocs(Symbol_table* symtab,
                                       size_t local_symbol_count,
                                       const unsigned char* plocal_symbols)
 {
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, false>
+      Classify_reloc;
 
   if (sh_type == elfcpp::SHT_REL)
     {
       return;
     }
 
-   gold::gc_process_relocs<size, false, Target_x86_64<size>, elfcpp::SHT_RELA,
-                          typename Target_x86_64<size>::Scan,
-                          typename Target_x86_64<size>::Relocatable_size_for_reloc>(
+   gold::gc_process_relocs<size, false, Target_x86_64<size>, Scan,
+                          Classify_reloc>(
     symtab,
     layout,
     this,
@@ -3229,6 +3236,9 @@ Target_x86_64<size>::scan_relocs(Symbol_table* symtab,
                                 size_t local_symbol_count,
                                 const unsigned char* plocal_symbols)
 {
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, false>
+      Classify_reloc;
+
   if (sh_type == elfcpp::SHT_REL)
     {
       gold_error(_("%s: unsupported REL reloc section"),
@@ -3236,8 +3246,7 @@ Target_x86_64<size>::scan_relocs(Symbol_table* symtab,
       return;
     }
 
-  gold::scan_relocs<size, false, Target_x86_64<size>, elfcpp::SHT_RELA,
-      typename Target_x86_64<size>::Scan>(
+  gold::scan_relocs<size, false, Target_x86_64<size>, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -4268,11 +4277,13 @@ Target_x86_64<size>::relocate_section(
     section_size_type view_size,
     const Reloc_symbol_changes* reloc_symbol_changes)
 {
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, false>
+      Classify_reloc;
+
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_section<size, false, Target_x86_64<size>, elfcpp::SHT_RELA,
-                        typename Target_x86_64<size>::Relocate,
-                        gold::Default_comdat_behavior>(
+  gold::relocate_section<size, false, Target_x86_64<size>, Relocate,
+                        gold::Default_comdat_behavior, Classify_reloc>(
     relinfo,
     this,
     prelocs,
@@ -4313,86 +4324,50 @@ Target_x86_64<size>::apply_relocation(
     view_size);
 }
 
-// Return the size of a relocation while scanning during a relocatable
-// link.
+// Scan the relocs during a relocatable link.
 
 template<int size>
-unsigned int
-Target_x86_64<size>::Relocatable_size_for_reloc::get_size_for_reloc(
-    unsigned int r_type,
-    Relobj* object)
+void
+Target_x86_64<size>::scan_relocatable_relocs(
+    Symbol_table* symtab,
+    Layout* layout,
+    Sized_relobj_file<size, false>* object,
+    unsigned int data_shndx,
+    unsigned int sh_type,
+    const unsigned char* prelocs,
+    size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
+    size_t local_symbol_count,
+    const unsigned char* plocal_symbols,
+    Relocatable_relocs* rr)
 {
-  switch (r_type)
-    {
-    case elfcpp::R_X86_64_NONE:
-    case elfcpp::R_X86_64_GNU_VTINHERIT:
-    case elfcpp::R_X86_64_GNU_VTENTRY:
-    case elfcpp::R_X86_64_TLSGD:            // Global-dynamic
-    case elfcpp::R_X86_64_GOTPC32_TLSDESC:  // Global-dynamic (from ~oliva url)
-    case elfcpp::R_X86_64_TLSDESC_CALL:
-    case elfcpp::R_X86_64_TLSLD:            // Local-dynamic
-    case elfcpp::R_X86_64_DTPOFF32:
-    case elfcpp::R_X86_64_DTPOFF64:
-    case elfcpp::R_X86_64_GOTTPOFF:         // Initial-exec
-    case elfcpp::R_X86_64_TPOFF32:          // Local-exec
-      return 0;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, false>
+      Classify_reloc;
+  typedef gold::Default_scan_relocatable_relocs<Classify_reloc>
+      Scan_relocatable_relocs;
 
-    case elfcpp::R_X86_64_64:
-    case elfcpp::R_X86_64_PC64:
-    case elfcpp::R_X86_64_GOTOFF64:
-    case elfcpp::R_X86_64_GOTPC64:
-    case elfcpp::R_X86_64_PLTOFF64:
-    case elfcpp::R_X86_64_GOT64:
-    case elfcpp::R_X86_64_GOTPCREL64:
-    case elfcpp::R_X86_64_GOTPCREL:
-    case elfcpp::R_X86_64_GOTPCRELX:
-    case elfcpp::R_X86_64_REX_GOTPCRELX:
-    case elfcpp::R_X86_64_GOTPLT64:
-      return 8;
-
-    case elfcpp::R_X86_64_32:
-    case elfcpp::R_X86_64_32S:
-    case elfcpp::R_X86_64_PC32:
-    case elfcpp::R_X86_64_PC32_BND:
-    case elfcpp::R_X86_64_PLT32:
-    case elfcpp::R_X86_64_PLT32_BND:
-    case elfcpp::R_X86_64_GOTPC32:
-    case elfcpp::R_X86_64_GOT32:
-      return 4;
-
-    case elfcpp::R_X86_64_16:
-    case elfcpp::R_X86_64_PC16:
-      return 2;
-
-    case elfcpp::R_X86_64_8:
-    case elfcpp::R_X86_64_PC8:
-      return 1;
-
-    case elfcpp::R_X86_64_COPY:
-    case elfcpp::R_X86_64_GLOB_DAT:
-    case elfcpp::R_X86_64_JUMP_SLOT:
-    case elfcpp::R_X86_64_RELATIVE:
-    case elfcpp::R_X86_64_IRELATIVE:
-      // These are outstanding tls relocs, which are unexpected when linking
-    case elfcpp::R_X86_64_TPOFF64:
-    case elfcpp::R_X86_64_DTPMOD64:
-    case elfcpp::R_X86_64_TLSDESC:
-      object->error(_("unexpected reloc %u in object file"), r_type);
-      return 0;
+  gold_assert(sh_type == elfcpp::SHT_RELA);
 
-    case elfcpp::R_X86_64_SIZE32:
-    case elfcpp::R_X86_64_SIZE64:
-    default:
-      object->error(_("unsupported reloc %u against local symbol"), r_type);
-      return 0;
-    }
+  gold::scan_relocatable_relocs<size, false, Scan_relocatable_relocs>(
+    symtab,
+    layout,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_symbols,
+    rr);
 }
 
-// Scan the relocs during a relocatable link.
+// Scan the relocs for --emit-relocs.
 
 template<int size>
 void
-Target_x86_64<size>::scan_relocatable_relocs(
+Target_x86_64<size>::emit_relocs_scan(
     Symbol_table* symtab,
     Layout* layout,
     Sized_relobj_file<size, false>* object,
@@ -4403,16 +4378,17 @@ Target_x86_64<size>::scan_relocatable_relocs(
     Output_section* output_section,
     bool needs_special_offset_handling,
     size_t local_symbol_count,
-    const unsigned char* plocal_symbols,
+    const unsigned char* plocal_syms,
     Relocatable_relocs* rr)
 {
-  gold_assert(sh_type == elfcpp::SHT_RELA);
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, false>
+      Classify_reloc;
+  typedef gold::Default_emit_relocs_strategy<Classify_reloc>
+      Emit_relocs_strategy;
 
-  typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
-    Relocatable_size_for_reloc> Scan_relocatable_relocs;
+  gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::scan_relocatable_relocs<size, false, elfcpp::SHT_RELA,
-      Scan_relocatable_relocs>(
+  gold::scan_relocatable_relocs<size, false, Emit_relocs_strategy>(
     symtab,
     layout,
     object,
@@ -4422,7 +4398,7 @@ Target_x86_64<size>::scan_relocatable_relocs(
     output_section,
     needs_special_offset_handling,
     local_symbol_count,
-    plocal_symbols,
+    plocal_syms,
     rr);
 }
 
@@ -4443,9 +4419,12 @@ Target_x86_64<size>::relocate_relocs(
     unsigned char* reloc_view,
     section_size_type reloc_view_size)
 {
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, false>
+      Classify_reloc;
+
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_relocs<size, false, elfcpp::SHT_RELA>(
+  gold::relocate_relocs<size, false, Classify_reloc>(
     relinfo,
     prelocs,
     reloc_count,
This page took 0.109648 seconds and 4 git commands to generate.