diff options
author | Cary Coutant <ccoutant@gmail.com> | 2015-12-11 07:43:59 -0800 |
---|---|---|
committer | Cary Coutant <ccoutant@gmail.com> | 2016-01-11 18:51:18 -0800 |
commit | 4d625b70fc3fb7facc7159feb8d49b78ac6641f9 (patch) | |
tree | 437cb92850b8366f4a7ef33c773052e987b8e35b /gold/mips.cc | |
parent | b05b120205e697db6291abb95a8cd2be054f99e9 (diff) | |
download | gdb-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.
Diffstat (limited to 'gold/mips.cc')
-rw-r--r-- | gold/mips.cc | 504 |
1 files changed, 383 insertions, 121 deletions
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; |