mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
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.
This commit is contained in:
parent
b05b120205
commit
4d625b70fc
@ -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.
|
||||
|
166
elfcpp/elfcpp.h
166
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.
|
||||
|
||||
|
@ -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>
|
||||
|
146
gold/ChangeLog
146
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.
|
||||
|
123
gold/aarch64.cc
123
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)
|
||||
{
|
||||
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);
|
||||
|
||||
typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
|
||||
Relocatable_size_for_reloc> Scan_relocatable_relocs;
|
||||
|
||||
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,
|
||||
|
93
gold/arm.cc
93
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)
|
||||
{
|
||||
typedef Arm_scan_relocatable_relocs<big_endian, Classify_reloc>
|
||||
Scan_relocatable_relocs;
|
||||
|
||||
gold_assert(sh_type == elfcpp::SHT_REL);
|
||||
|
||||
typedef Arm_scan_relocatable_relocs<big_endian, elfcpp::SHT_REL,
|
||||
Relocatable_size_for_reloc> Scan_relocatable_relocs;
|
||||
|
||||
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,
|
||||
|
31
gold/gc.h
31
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)
|
||||
|
92
gold/i386.cc
92
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)
|
||||
{
|
||||
typedef gold::Default_scan_relocatable_relocs<Classify_reloc>
|
||||
Scan_relocatable_relocs;
|
||||
|
||||
gold_assert(sh_type == elfcpp::SHT_REL);
|
||||
|
||||
typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_REL,
|
||||
Relocatable_size_for_reloc> Scan_relocatable_relocs;
|
||||
|
||||
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()));
|
||||
|
504
gold/mips.cc
504
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)
|
||||
{
|
||||
typedef Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>
|
||||
Classify_reloc;
|
||||
typedef Mips_scan_relocatable_relocs<big_endian, Classify_reloc>
|
||||
Scan_relocatable_relocs;
|
||||
|
||||
gold_assert(sh_type == elfcpp::SHT_REL);
|
||||
|
||||
typedef Mips_scan_relocatable_relocs<big_endian, elfcpp::SHT_REL,
|
||||
Relocatable_size_for_reloc> Scan_relocatable_relocs;
|
||||
|
||||
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;
|
||||
|
@ -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
|
||||
|
107
gold/powerpc.cc
107
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
|
||||
|
@ -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.
|
||||
|
112
gold/reloc.cc
112
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.
|
||||
|
201
gold/s390.cc
201
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,108 +4027,6 @@ Target_s390<size>::do_finalize_sections(
|
||||
}
|
||||
}
|
||||
|
||||
// Return the size of a relocation while scanning 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)
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
default:
|
||||
object->error(_("unsupported reloc %u in object file"), r_type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Scan the relocs during a relocatable link.
|
||||
|
||||
template<int size>
|
||||
@ -4139,13 +4045,14 @@ Target_s390<size>::scan_relocatable_relocs(
|
||||
const unsigned char* plocal_symbols,
|
||||
Relocatable_relocs* rr)
|
||||
{
|
||||
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, true>
|
||||
Classify_reloc;
|
||||
typedef gold::Default_scan_relocatable_relocs<Classify_reloc>
|
||||
Scan_relocatable_relocs;
|
||||
|
||||
gold_assert(sh_type == elfcpp::SHT_RELA);
|
||||
|
||||
typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
|
||||
Relocatable_size_for_reloc> Scan_relocatable_relocs;
|
||||
|
||||
gold::scan_relocatable_relocs<size, true, elfcpp::SHT_RELA,
|
||||
Scan_relocatable_relocs>(
|
||||
gold::scan_relocatable_relocs<size, true, Scan_relocatable_relocs>(
|
||||
symtab,
|
||||
layout,
|
||||
object,
|
||||
@ -4159,6 +4066,45 @@ Target_s390<size>::scan_relocatable_relocs(
|
||||
rr);
|
||||
}
|
||||
|
||||
// Scan the relocs for --emit-relocs.
|
||||
|
||||
template<int size>
|
||||
void
|
||||
Target_s390<size>::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)
|
||||
{
|
||||
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, true>
|
||||
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, true, 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>
|
||||
@ -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,
|
||||
|
109
gold/sparc.cc
109
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)
|
||||
{
|
||||
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);
|
||||
|
||||
typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
|
||||
Relocatable_size_for_reloc> Scan_relocatable_relocs;
|
||||
|
||||
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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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, typename Classify_reloc>
|
||||
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.
|
||||
// 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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -71,6 +71,14 @@ class Target_test : public Sized_target<size, big_endian>
|
||||
const unsigned char*, Relocatable_relocs*)
|
||||
{ ERROR("call to Target_test::scan_relocatable_relocs"); }
|
||||
|
||||
void
|
||||
emit_relocs_scan(Symbol_table*, Layout*,
|
||||
Sized_relobj_file<size, big_endian>*, unsigned int,
|
||||
unsigned int, const unsigned char*,
|
||||
size_t, Output_section*, bool, size_t,
|
||||
const unsigned char*, Relocatable_relocs*)
|
||||
{ ERROR("call to Target_test::emit_relocs_scan"); }
|
||||
|
||||
void
|
||||
relocate_relocs(const Relocate_info<size, big_endian>*,
|
||||
unsigned int, const unsigned char*, size_t,
|
||||
|
130
gold/tilegx.cc
130
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,19 +4798,6 @@ Target_tilegx<size, big_endian>::apply_relocation(
|
||||
view_size);
|
||||
}
|
||||
|
||||
// Return the size of a relocation while scanning 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*)
|
||||
{
|
||||
// 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>
|
||||
@ -4819,13 +4816,14 @@ Target_tilegx<size, big_endian>::scan_relocatable_relocs(
|
||||
const unsigned char* plocal_symbols,
|
||||
Relocatable_relocs* rr)
|
||||
{
|
||||
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);
|
||||
|
||||
typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
|
||||
Relocatable_size_for_reloc> Scan_relocatable_relocs;
|
||||
|
||||
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,
|
||||
@ -4839,6 +4837,45 @@ Target_tilegx<size, big_endian>::scan_relocatable_relocs(
|
||||
rr);
|
||||
}
|
||||
|
||||
// Scan the relocs for --emit-relocs.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Target_tilegx<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>
|
||||
@ -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,
|
||||
|
175
gold/x86_64.cc
175
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,81 +4324,6 @@ Target_x86_64<size>::apply_relocation(
|
||||
view_size);
|
||||
}
|
||||
|
||||
// Return the size of a relocation while scanning 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)
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Scan the relocs during a relocatable link.
|
||||
|
||||
template<int size>
|
||||
@ -4406,13 +4342,14 @@ Target_x86_64<size>::scan_relocatable_relocs(
|
||||
const unsigned char* plocal_symbols,
|
||||
Relocatable_relocs* rr)
|
||||
{
|
||||
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, false>
|
||||
Classify_reloc;
|
||||
typedef gold::Default_scan_relocatable_relocs<Classify_reloc>
|
||||
Scan_relocatable_relocs;
|
||||
|
||||
gold_assert(sh_type == elfcpp::SHT_RELA);
|
||||
|
||||
typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
|
||||
Relocatable_size_for_reloc> Scan_relocatable_relocs;
|
||||
|
||||
gold::scan_relocatable_relocs<size, false, elfcpp::SHT_RELA,
|
||||
Scan_relocatable_relocs>(
|
||||
gold::scan_relocatable_relocs<size, false, Scan_relocatable_relocs>(
|
||||
symtab,
|
||||
layout,
|
||||
object,
|
||||
@ -4426,6 +4363,45 @@ Target_x86_64<size>::scan_relocatable_relocs(
|
||||
rr);
|
||||
}
|
||||
|
||||
// Scan the relocs for --emit-relocs.
|
||||
|
||||
template<int size>
|
||||
void
|
||||
Target_x86_64<size>::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)
|
||||
{
|
||||
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, false>
|
||||
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, false, 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>
|
||||
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user