aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@gmail.com>2015-12-11 07:43:59 -0800
committerCary Coutant <ccoutant@gmail.com>2016-01-11 18:51:18 -0800
commit4d625b70fc3fb7facc7159feb8d49b78ac6641f9 (patch)
tree437cb92850b8366f4a7ef33c773052e987b8e35b
parentb05b120205e697db6291abb95a8cd2be054f99e9 (diff)
downloadgdb-4d625b70fc3fb7facc7159feb8d49b78ac6641f9.zip
gdb-4d625b70fc3fb7facc7159feb8d49b78ac6641f9.tar.gz
gdb-4d625b70fc3fb7facc7159feb8d49b78ac6641f9.tar.bz2
Refactor gold to enable support for MIPS-64 relocation format.
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.
-rw-r--r--elfcpp/ChangeLog6
-rw-r--r--elfcpp/elfcpp.h166
-rw-r--r--elfcpp/elfcpp_internal.h23
-rw-r--r--gold/ChangeLog146
-rw-r--r--gold/aarch64.cc123
-rw-r--r--gold/arm.cc93
-rw-r--r--gold/gc.h31
-rw-r--r--gold/i386.cc92
-rw-r--r--gold/mips.cc504
-rw-r--r--gold/object.h6
-rw-r--r--gold/powerpc.cc107
-rw-r--r--gold/reloc-types.h8
-rw-r--r--gold/reloc.cc112
-rw-r--r--gold/s390.cc195
-rw-r--r--gold/sparc.cc109
-rw-r--r--gold/target-reloc.h216
-rw-r--r--gold/target.cc2
-rw-r--r--gold/target.h37
-rw-r--r--gold/testsuite/testfile.cc8
-rw-r--r--gold/tilegx.cc128
-rw-r--r--gold/x86_64.cc169
21 files changed, 1591 insertions, 690 deletions
diff --git a/elfcpp/ChangeLog b/elfcpp/ChangeLog
index e48be00..198eb92 100644
--- a/elfcpp/ChangeLog
+++ b/elfcpp/ChangeLog
@@ -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.
diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h
index e0eae42..3d7039a 100644
--- a/elfcpp/elfcpp.h
+++ b/elfcpp/elfcpp.h
@@ -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.
diff --git a/elfcpp/elfcpp_internal.h b/elfcpp/elfcpp_internal.h
index 7080a2d..edca55f 100644
--- a/elfcpp/elfcpp_internal.h
+++ b/elfcpp/elfcpp_internal.h
@@ -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>
diff --git a/gold/ChangeLog b/gold/ChangeLog
index e48be00..42c428b 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -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.
diff --git a/gold/aarch64.cc b/gold/aarch64.cc
index 715936b..20f2f4f 100644
--- a/gold/aarch64.cc
+++ b/gold/aarch64.cc
@@ -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,
diff --git a/gold/arm.cc b/gold/arm.cc
index c20eb6d..4cd0b91 100644
--- a/gold/arm.cc
+++ b/gold/arm.cc
@@ -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,
diff --git a/gold/gc.h b/gold/gc.h
index 2dcf61a..d0b16b2 100644
--- 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)
diff --git a/gold/i386.cc b/gold/i386.cc
index 57e5542..82886d4 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -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()));
diff --git a/gold/mips.cc b/gold/mips.cc
index 3d513ff..c57ef4f 100644
--- a/gold/mips.cc
+++ b/gold/mips.cc
@@ -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;
diff --git a/gold/object.h b/gold/object.h
index 25af341..95f6d56 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -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
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index b1c5aea..e26a198 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -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
diff --git a/gold/reloc-types.h b/gold/reloc-types.h
index b42be59..7334b9f 100644
--- a/gold/reloc-types.h
+++ b/gold/reloc-types.h
@@ -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.
diff --git a/gold/reloc.cc b/gold/reloc.cc
index 3354019..b1a50e6 100644
--- a/gold/reloc.cc
+++ b/gold/reloc.cc
@@ -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.
diff --git a/gold/s390.cc b/gold/s390.cc
index eb92fb7..2671441 100644
--- a/gold/s390.cc
+++ b/gold/s390.cc
@@ -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,
diff --git a/gold/sparc.cc b/gold/sparc.cc
index 049e0ab..c97c32c 100644
--- a/gold/sparc.cc
+++ b/gold/sparc.cc
@@ -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,
diff --git a/gold/target-reloc.h b/gold/target-reloc.h
index cec5ee1..bdf673d 100644
--- a/gold/target-reloc.h
+++ b/gold/target-reloc.h
@@ -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;
diff --git a/gold/target.cc b/gold/target.cc
index 658fadf..cc3765a 100644
--- a/gold/target.cc
+++ b/gold/target.cc
@@ -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;
}
diff --git a/gold/target.h b/gold/target.h
index 27e8a2e..c0f24ee 100644
--- a/gold/target.h
+++ b/gold/target.h
@@ -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)
diff --git a/gold/testsuite/testfile.cc b/gold/testsuite/testfile.cc
index bb5ff70..4049e4a 100644
--- a/gold/testsuite/testfile.cc
+++ b/gold/testsuite/testfile.cc
@@ -72,6 +72,14 @@ class Target_test : public Sized_target<size, big_endian>
{ 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,
Output_section*, typename elfcpp::Elf_types<size>::Elf_Off,
diff --git a/gold/tilegx.cc b/gold/tilegx.cc
index 07960ef..bb17330 100644
--- a/gold/tilegx.cc
+++ b/gold/tilegx.cc
@@ -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,
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index c48a513..3cfc064 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -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,