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 /gold/mips.cc
parentReapply: List inferiors/threads/pspaces in ascending order (diff)
downloadbinutils-gdb-4d625b70fc3fb7facc7159feb8d49b78ac6641f9.tar.gz
binutils-gdb-4d625b70fc3fb7facc7159feb8d49b78ac6641f9.tar.bz2
binutils-gdb-4d625b70fc3fb7facc7159feb8d49b78ac6641f9.zip
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.cc504
1 files changed, 383 insertions, 121 deletions
diff --git a/gold/mips.cc b/gold/mips.cc
index 3d513fff172..c57ef4f807f 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;