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:
Cary Coutant 2015-12-11 07:43:59 -08:00
parent b05b120205
commit 4d625b70fc
21 changed files with 1598 additions and 697 deletions

View file

@ -1,3 +1,9 @@
2016-01-11 Cary Coutant <ccoutant@gmail.com>
* elfcpp.h (Mips64_rel, Mips64_rel_write): New classes.
(Mips64_rela, Mips64_rela_write): New classes.
* elfcpp_internal.h (Mips64_rel_data, Mips64_rela_data): New structs.
2016-01-01 Alan Modra <amodra@gmail.com>
Update year range in copyright notice of all files.

View file

@ -1661,6 +1661,172 @@ class Rela_write
internal::Rela_data<size>* p_;
};
// MIPS-64 has a non-standard relocation layout.
template<bool big_endian>
class Mips64_rel
{
public:
Mips64_rel(const unsigned char* p)
: p_(reinterpret_cast<const internal::Mips64_rel_data*>(p))
{ }
template<typename File>
Mips64_rel(File* file, typename File::Location loc)
: p_(reinterpret_cast<const internal::Mips64_rel_data*>(
file->view(loc.file_offset, loc.data_size).data()))
{ }
typename Elf_types<64>::Elf_Addr
get_r_offset() const
{ return Convert<64, big_endian>::convert_host(this->p_->r_offset); }
Elf_Word
get_r_sym() const
{ return Convert<32, big_endian>::convert_host(this->p_->r_sym); }
unsigned char
get_r_ssym() const
{ return this->p_->r_ssym; }
unsigned char
get_r_type() const
{ return this->p_->r_type; }
unsigned char
get_r_type2() const
{ return this->p_->r_type2; }
unsigned char
get_r_type3() const
{ return this->p_->r_type3; }
private:
const internal::Mips64_rel_data* p_;
};
template<bool big_endian>
class Mips64_rel_write
{
public:
Mips64_rel_write(unsigned char* p)
: p_(reinterpret_cast<internal::Mips64_rel_data*>(p))
{ }
void
put_r_offset(typename Elf_types<64>::Elf_Addr v)
{ this->p_->r_offset = Convert<64, big_endian>::convert_host(v); }
void
put_r_sym(Elf_Word v)
{ this->p_->r_sym = Convert<32, big_endian>::convert_host(v); }
void
put_r_ssym(unsigned char v)
{ this->p_->r_ssym = v; }
void
put_r_type(unsigned char v)
{ this->p_->r_type = v; }
void
put_r_type2(unsigned char v)
{ this->p_->r_type2 = v; }
void
put_r_type3(unsigned char v)
{ this->p_->r_type3 = v; }
private:
internal::Mips64_rel_data* p_;
};
template<bool big_endian>
class Mips64_rela
{
public:
Mips64_rela(const unsigned char* p)
: p_(reinterpret_cast<const internal::Mips64_rela_data*>(p))
{ }
template<typename File>
Mips64_rela(File* file, typename File::Location loc)
: p_(reinterpret_cast<const internal::Mips64_rela_data*>(
file->view(loc.file_offset, loc.data_size).data()))
{ }
typename Elf_types<64>::Elf_Addr
get_r_offset() const
{ return Convert<64, big_endian>::convert_host(this->p_->r_offset); }
Elf_Word
get_r_sym() const
{ return Convert<32, big_endian>::convert_host(this->p_->r_sym); }
unsigned char
get_r_ssym() const
{ return this->p_->r_ssym; }
unsigned char
get_r_type() const
{ return this->p_->r_type; }
unsigned char
get_r_type2() const
{ return this->p_->r_type2; }
unsigned char
get_r_type3() const
{ return this->p_->r_type3; }
typename Elf_types<64>::Elf_Swxword
get_r_addend() const
{ return Convert<64, big_endian>::convert_host(this->p_->r_addend); }
private:
const internal::Mips64_rela_data* p_;
};
template<bool big_endian>
class Mips64_rela_write
{
public:
Mips64_rela_write(unsigned char* p)
: p_(reinterpret_cast<internal::Mips64_rela_data*>(p))
{ }
void
put_r_offset(typename Elf_types<64>::Elf_Addr v)
{ this->p_->r_offset = Convert<64, big_endian>::convert_host(v); }
void
put_r_sym(Elf_Word v)
{ this->p_->r_sym = Convert<32, big_endian>::convert_host(v); }
void
put_r_ssym(unsigned char v)
{ this->p_->r_ssym = v; }
void
put_r_type(unsigned char v)
{ this->p_->r_type = v; }
void
put_r_type2(unsigned char v)
{ this->p_->r_type2 = v; }
void
put_r_type3(unsigned char v)
{ this->p_->r_type3 = v; }
void
put_r_addend(typename Elf_types<64>::Elf_Swxword v)
{ this->p_->r_addend = Convert<64, big_endian>::convert_host(v); }
private:
internal::Mips64_rela_data* p_;
};
// Accessor classes for entries in the ELF SHT_DYNAMIC section aka
// PT_DYNAMIC segment.

View file

@ -180,6 +180,29 @@ struct Rela_data
typename Elf_types<size>::Elf_Swxword r_addend;
};
// MIPS-64 has a non-standard layout for relocations.
struct Mips64_rel_data
{
typename Elf_types<64>::Elf_Addr r_offset;
Elf_Word r_sym;
unsigned char r_ssym;
unsigned char r_type3;
unsigned char r_type2;
unsigned char r_type;
};
struct Mips64_rela_data
{
typename Elf_types<64>::Elf_Addr r_offset;
Elf_Word r_sym;
unsigned char r_ssym;
unsigned char r_type3;
unsigned char r_type2;
unsigned char r_type;
typename Elf_types<64>::Elf_Swxword r_addend;
};
// An entry in the ELF SHT_DYNAMIC section aka PT_DYNAMIC segment.
template<int size>

View file

@ -1,3 +1,149 @@
2016-01-11 Cary Coutant <ccoutant@gmail.com>
Refactor gold to enable support for MIPS-64 relocation format.
* gc.h (get_embedded_addend_size): Remove sh_type parameter.
(gc_process_relocs): Remove sh_type template parameter.
Use Classify_reloc to access r_sym, r_type, and r_addend fields.
* object.h (Sized_relobj_file::split_stack_adjust): Add target
parameter.
(Sized_relobj_file::split_stack_adjust_reltype): Likewise.
* reloc-types.h (Reloc_types::copy_reloc_addend): (SHT_REL and SHT_RELA
specializations) Remove.
* reloc.cc (Emit_relocs_strategy): Rename and move to target-reloc.h.
(Sized_relobj_file::emit_relocs_scan): Call Target::emit_relocs_scan().
(Sized_relobj_file::emit_relocs_scan_reltype): Remove.
(Sized_relobj_file::split_stack_adjust): Add target parameter.
Adjust all callers.
(Sized_relobj_file::split_stack_adjust_reltype): Likewise. Call
Target::get_r_sym() to get r_sym field from relocations.
(Track_relocs::next_symndx): Call Target::get_r_sym().
* target-reloc.h (scan_relocs): Remove sh_type template parameter;
add Classify_reloc template parameter. Use for accessing r_sym and
r_type.
(relocate_section): Likewise.
(Default_classify_reloc): New class (renamed and moved from reloc.cc).
(Default_scan_relocatable_relocs): Remove sh_type template parameter.
(Default_scan_relocatable_relocs::Reltype): New typedef.
(Default_scan_relocatable_relocs::reloc_size): New const.
(Default_scan_relocatable_relocs::sh_type): New const.
(Default_scan_relocatable_relocs::get_r_sym): New method.
(Default_scan_relocatable_relocs::get_r_type): New method.
(Default_emit_relocs_strategy): New class.
(scan_relocatable_relocs): Replace sh_type template parameter with
Scan_relocatable_relocs class. Use it to access r_sym and r_type
fields.
(relocate_relocs): Replace sh_type template parameter with
Classify_reloc class. Use it to access r_sym and r_type fields.
* target.h (Target::is_call_to_non_split): Replace r_type parameter
with pointer to relocation. Adjust all callers.
(Target::do_is_call_to_non_split): Likewise.
(Target::emit_relocs_scan): New virtual method.
(Sized_target::get_r_sym): New virtual method.
* target.cc (Target::do_is_call_to_non_split): Replace r_type parameter
with pointer to relocation.
* aarch64.cc (Target_aarch64::emit_relocs_scan): New method.
(Target_aarch64::Relocatable_size_for_reloc): Remove.
(Target_aarch64::gc_process_relocs): Use Default_classify_reloc.
(Target_aarch64::scan_relocs): Likewise.
(Target_aarch64::relocate_section): Likewise.
(Target_aarch64::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_aarch64::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_aarch64::relocate_relocs): Use Default_classify_reloc.
* arm.cc (Target_arm::Arm_scan_relocatable_relocs): Remove sh_type
template parameter.
(Target_arm::emit_relocs_scan): New method.
(Target_arm::Relocatable_size_for_reloc): Replace with...
(Target_arm::Classify_reloc): ...this.
(Target_arm::gc_process_relocs): Use Classify_reloc.
(Target_arm::scan_relocs): Likewise.
(Target_arm::relocate_section): Likewise.
(Target_arm::scan_relocatable_relocs): Likewise.
(Target_arm::relocate_relocs): Likewise.
* i386.cc (Target_i386::emit_relocs_scan): New method.
(Target_i386::Relocatable_size_for_reloc): Replace with...
(Target_i386::Classify_reloc): ...this.
(Target_i386::gc_process_relocs): Use Classify_reloc.
(Target_i386::scan_relocs): Likewise.
(Target_i386::relocate_section): Likewise.
(Target_i386::scan_relocatable_relocs): Likewise.
(Target_i386::relocate_relocs): Likewise.
* mips.cc (Mips_scan_relocatable_relocs): Remove sh_type template
parameter.
(Mips_reloc_types): New class template.
(Mips_classify_reloc): New class template.
(Target_mips::Reltype): New typedef.
(Target_mips::Relatype): New typedef.
(Target_mips::emit_relocs_scan): New method.
(Target_mips::get_r_sym): New method.
(Target_mips::Relocatable_size_for_reloc): Replace with
Mips_classify_reloc.
(Target_mips::copy_reloc): Use Mips_classify_reloc.
(Target_mips::gc_process_relocs): Likewise.
(Target_mips::scan_relocs): Likewise.
(Target_mips::relocate_section): Likewise.
(Target_mips::scan_relocatable_relocs): Likewise.
(Target_mips::relocate_relocs): Likewise.
(mips_get_size_for_reloc): New function, factored out from
Relocatable_size_for_reloc::get_size_for_reloc.
(Target_mips::Scan::local): Use Mips_classify_reloc.
(Target_mips::Scan::global): Likewise.
(Target_mips::Relocate::relocate): Likewise.
* powerpc.cc (Target_powerpc::emit_relocs_scan): New method.
(Target_powerpc::Relocatable_size_for_reloc): Remove.
(Target_powerpc::gc_process_relocs): Use Default_classify_reloc.
(Target_powerpc::scan_relocs): Likewise.
(Target_powerpc::relocate_section): Likewise.
(Powerpc_scan_relocatable_reloc): Convert to class template.
(Powerpc_scan_relocatable_reloc::Reltype): New typedef.
(Powerpc_scan_relocatable_reloc::reloc_size): New const.
(Powerpc_scan_relocatable_reloc::sh_type): New const.
(Powerpc_scan_relocatable_reloc::get_r_sym): New method.
(Powerpc_scan_relocatable_reloc::get_r_type): New method.
(Target_powerpc::scan_relocatable_relocs): Use
Powerpc_scan_relocatable_reloc.
(Target_powerpc::relocate_relocs): Use Default_classify_reloc.
* s390.cc (Target_s390::emit_relocs_scan): New method.
(Target_s390::Relocatable_size_for_reloc): Remove.
(Target_s390::gc_process_relocs): Use Default_classify_reloc.
(Target_s390::scan_relocs): Likewise.
(Target_s390::relocate_section): Likewise.
(Target_s390::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_s390::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_s390::relocate_relocs): Use Default_classify_reloc.
* sparc.cc (Target_sparc::emit_relocs_scan): New method.
(Target_sparc::Relocatable_size_for_reloc): Remove.
(Target_sparc::gc_process_relocs): Use Default_classify_reloc.
(Target_sparc::scan_relocs): Likewise.
(Target_sparc::relocate_section): Likewise.
(Target_sparc::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_sparc::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_sparc::relocate_relocs): Use Default_classify_reloc.
* tilegx.cc (Target_tilegx::emit_relocs_scan): New method.
(Target_tilegx::Relocatable_size_for_reloc): Remove.
(Target_tilegx::gc_process_relocs): Use Default_classify_reloc.
(Target_tilegx::scan_relocs): Likewise.
(Target_tilegx::relocate_section): Likewise.
(Target_tilegx::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_tilegx::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_tilegx::relocate_relocs): Use Default_classify_reloc.
* x86_64.cc (Target_x86_64::emit_relocs_scan): New method.
(Target_x86_64::Relocatable_size_for_reloc): Remove.
(Target_x86_64::gc_process_relocs): Use Default_classify_reloc.
(Target_x86_64::scan_relocs): Likewise.
(Target_x86_64::relocate_section): Likewise.
(Target_x86_64::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_x86_64::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_x86_64::relocate_relocs): Use Default_classify_reloc.
* testsuite/testfile.cc (Target_test::emit_relocs_scan): New method.
2016-01-01 Alan Modra <amodra@gmail.com>
Update year range in copyright notice of all files.

View file

@ -2869,6 +2869,21 @@ class Target_aarch64 : public Sized_target<size, big_endian>
const unsigned char* plocal_symbols,
Relocatable_relocs*);
// Scan the relocs for --emit-relocs.
void
emit_relocs_scan(Symbol_table* symtab,
Layout* layout,
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_syms,
Relocatable_relocs* rr);
// Relocate a section during a relocatable link.
void
relocate_relocs(
@ -3224,15 +3239,6 @@ class Target_aarch64 : public Sized_target<size, big_endian>
}; // End of class Relocate
// A class which returns the size required for a relocation type,
// used while scanning relocs during a relocatable link.
class Relocatable_size_for_reloc
{
public:
unsigned int
get_size_for_reloc(unsigned int, Relobj*);
};
// Adjust TLS relocation type based on the options and whether this
// is a local symbol.
static tls::Tls_optimization
@ -6630,17 +6636,16 @@ Target_aarch64<size, big_endian>::gc_process_relocs(
size_t local_symbol_count,
const unsigned char* plocal_symbols)
{
typedef Target_aarch64<size, big_endian> Aarch64;
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
if (sh_type == elfcpp::SHT_REL)
{
return;
}
gold::gc_process_relocs<
size, big_endian,
Target_aarch64<size, big_endian>,
elfcpp::SHT_RELA,
typename Target_aarch64<size, big_endian>::Scan,
typename Target_aarch64<size, big_endian>::Relocatable_size_for_reloc>(
gold::gc_process_relocs<size, big_endian, Aarch64, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -6671,13 +6676,18 @@ Target_aarch64<size, big_endian>::scan_relocs(
size_t local_symbol_count,
const unsigned char* plocal_symbols)
{
typedef Target_aarch64<size, big_endian> Aarch64;
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
if (sh_type == elfcpp::SHT_REL)
{
gold_error(_("%s: unsupported REL reloc section"),
object->name().c_str());
return;
}
gold::scan_relocs<size, big_endian, Target_aarch64, elfcpp::SHT_RELA, Scan>(
gold::scan_relocs<size, big_endian, Aarch64, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -7868,10 +7878,15 @@ Target_aarch64<size, big_endian>::relocate_section(
section_size_type view_size,
const Reloc_symbol_changes* reloc_symbol_changes)
{
gold_assert(sh_type == elfcpp::SHT_RELA);
typedef Target_aarch64<size, big_endian> Aarch64;
typedef typename Target_aarch64<size, big_endian>::Relocate AArch64_relocate;
gold::relocate_section<size, big_endian, Target_aarch64, elfcpp::SHT_RELA,
AArch64_relocate, gold::Default_comdat_behavior>(
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
gold_assert(sh_type == elfcpp::SHT_RELA);
gold::relocate_section<size, big_endian, Aarch64, AArch64_relocate,
gold::Default_comdat_behavior, Classify_reloc>(
relinfo,
this,
prelocs,
@ -7884,21 +7899,6 @@ Target_aarch64<size, big_endian>::relocate_section(
reloc_symbol_changes);
}
// Return the size of a relocation while scanning during a relocatable
// link.
template<int size, bool big_endian>
unsigned int
Target_aarch64<size, big_endian>::Relocatable_size_for_reloc::
get_size_for_reloc(
unsigned int ,
Relobj* )
{
// We will never support SHT_REL relocations.
gold_unreachable();
return 0;
}
// Scan the relocs during a relocatable link.
template<int size, bool big_endian>
@ -7917,13 +7917,14 @@ Target_aarch64<size, big_endian>::scan_relocatable_relocs(
const unsigned char* plocal_symbols,
Relocatable_relocs* rr)
{
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,

View file

@ -2040,9 +2040,9 @@ class Arm_output_data_got : public Output_data_got<32, big_endian>
// bits. The default handling of relocatable relocation cannot process these
// relocations. So we have to extend the default code.
template<bool big_endian, int sh_type, typename Classify_reloc>
template<bool big_endian, typename Classify_reloc>
class Arm_scan_relocatable_relocs :
public Default_scan_relocatable_relocs<sh_type, Classify_reloc>
public Default_scan_relocatable_relocs<Classify_reloc>
{
public:
// Return the strategy to use for a local symbol which is a section
@ -2050,7 +2050,7 @@ class Arm_scan_relocatable_relocs :
inline Relocatable_relocs::Reloc_strategy
local_section_strategy(unsigned int r_type, Relobj*)
{
if (sh_type == elfcpp::SHT_RELA)
if (Classify_reloc::sh_type == elfcpp::SHT_RELA)
return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA;
else
{
@ -2301,6 +2301,21 @@ class Target_arm : public Sized_target<32, big_endian>
const unsigned char* plocal_symbols,
Relocatable_relocs*);
// Scan the relocs for --emit-relocs.
void
emit_relocs_scan(Symbol_table* symtab,
Layout* layout,
Sized_relobj_file<32, big_endian>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_syms,
Relocatable_relocs* rr);
// Emit relocations for a section.
void
relocate_relocs(const Relocate_info<32, big_endian>*,
@ -2727,12 +2742,15 @@ class Target_arm : public Sized_target<32, big_endian>
};
// A class which returns the size required for a relocation type,
// used while scanning relocs during a relocatable link.
class Relocatable_size_for_reloc
// A class for inquiring about properties of a relocation,
// used while scanning relocs during a relocatable link and
// garbage collection.
class Classify_reloc :
public gold::Default_classify_reloc<elfcpp::SHT_REL, 32, big_endian>
{
public:
unsigned int
// Return the size of the addend of the relocation (only used for SHT_REL).
static unsigned int
get_size_for_reloc(unsigned int, Relobj*);
};
@ -9170,8 +9188,7 @@ Target_arm<big_endian>::gc_process_relocs(
typedef Target_arm<big_endian> Arm;
typedef typename Target_arm<big_endian>::Scan Scan;
gold::gc_process_relocs<32, big_endian, Arm, elfcpp::SHT_REL, Scan,
typename Target_arm::Relocatable_size_for_reloc>(
gold::gc_process_relocs<32, big_endian, Arm, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -9201,7 +9218,6 @@ Target_arm<big_endian>::scan_relocs(Symbol_table* symtab,
size_t local_symbol_count,
const unsigned char* plocal_symbols)
{
typedef typename Target_arm<big_endian>::Scan Scan;
if (sh_type == elfcpp::SHT_RELA)
{
gold_error(_("%s: unsupported RELA reloc section"),
@ -9209,7 +9225,7 @@ Target_arm<big_endian>::scan_relocs(Symbol_table* symtab,
return;
}
gold::scan_relocs<32, big_endian, Target_arm, elfcpp::SHT_REL, Scan>(
gold::scan_relocs<32, big_endian, Target_arm, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -10109,8 +10125,8 @@ Target_arm<big_endian>::relocate_section(
}
}
gold::relocate_section<32, big_endian, Target_arm, elfcpp::SHT_REL,
Arm_relocate, gold::Default_comdat_behavior>(
gold::relocate_section<32, big_endian, Target_arm, Arm_relocate,
gold::Default_comdat_behavior, Classify_reloc>(
relinfo,
this,
prelocs,
@ -10128,7 +10144,7 @@ Target_arm<big_endian>::relocate_section(
template<bool big_endian>
unsigned int
Target_arm<big_endian>::Relocatable_size_for_reloc::get_size_for_reloc(
Target_arm<big_endian>::Classify_reloc::get_size_for_reloc(
unsigned int r_type,
Relobj* object)
{
@ -10165,13 +10181,12 @@ Target_arm<big_endian>::scan_relocatable_relocs(
const unsigned char* plocal_symbols,
Relocatable_relocs* rr)
{
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,

View file

@ -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)

View file

@ -429,6 +429,21 @@ class Target_i386 : public Sized_target<32, false>
const unsigned char* plocal_symbols,
Relocatable_relocs*);
// Scan the relocs for --emit-relocs.
void
emit_relocs_scan(Symbol_table* symtab,
Layout* layout,
Sized_relobj_file<32, false>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_syms,
Relocatable_relocs* rr);
// Emit relocations for a section.
void
relocate_relocs(const Relocate_info<32, false>*,
@ -485,7 +500,7 @@ class Target_i386 : public Sized_target<32, false>
// Return whether SYM is call to a non-split function.
bool
do_is_call_to_non_split(const Symbol* sym, unsigned int) const;
do_is_call_to_non_split(const Symbol* sym, const unsigned char*) const;
// Adjust -fsplit-stack code which calls non-split-stack code.
void
@ -723,12 +738,15 @@ class Target_i386 : public Sized_target<32, false>
Local_dynamic_type local_dynamic_type_;
};
// A class which returns the size required for a relocation type,
// used while scanning relocs during a relocatable link.
class Relocatable_size_for_reloc
// A class for inquiring about properties of a relocation,
// used while scanning relocs during a relocatable link and
// garbage collection.
class Classify_reloc :
public gold::Default_classify_reloc<elfcpp::SHT_REL, 32, false>
{
public:
unsigned int
// Return the size of the addend of the relocation (only used for SHT_REL).
static unsigned int
get_size_for_reloc(unsigned int, Relobj*);
};
@ -2564,9 +2582,7 @@ Target_i386::gc_process_relocs(Symbol_table* symtab,
size_t local_symbol_count,
const unsigned char* plocal_symbols)
{
gold::gc_process_relocs<32, false, Target_i386, elfcpp::SHT_REL,
Target_i386::Scan,
Target_i386::Relocatable_size_for_reloc>(
gold::gc_process_relocs<32, false, Target_i386, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -2602,8 +2618,7 @@ Target_i386::scan_relocs(Symbol_table* symtab,
return;
}
gold::scan_relocs<32, false, Target_i386, elfcpp::SHT_REL,
Target_i386::Scan>(
gold::scan_relocs<32, false, Target_i386, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -3609,8 +3624,8 @@ Target_i386::relocate_section(const Relocate_info<32, false>* relinfo,
{
gold_assert(sh_type == elfcpp::SHT_REL);
gold::relocate_section<32, false, Target_i386, elfcpp::SHT_REL,
Target_i386::Relocate, gold::Default_comdat_behavior>(
gold::relocate_section<32, false, Target_i386, Relocate,
gold::Default_comdat_behavior, Classify_reloc>(
relinfo,
this,
prelocs,
@ -3627,7 +3642,7 @@ Target_i386::relocate_section(const Relocate_info<32, false>* relinfo,
// link.
unsigned int
Target_i386::Relocatable_size_for_reloc::get_size_for_reloc(
Target_i386::Classify_reloc::get_size_for_reloc(
unsigned int r_type,
Relobj* object)
{
@ -3712,13 +3727,12 @@ Target_i386::scan_relocatable_relocs(Symbol_table* symtab,
const unsigned char* plocal_symbols,
Relocatable_relocs* rr)
{
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()));

View file

@ -2642,9 +2642,9 @@ class Mips_output_section_reginfo : public Output_section
// The MIPS target has relocation types which default handling of relocatable
// relocation cannot process. So we have to extend the default code.
template<bool big_endian, int sh_type, typename Classify_reloc>
template<bool big_endian, typename Classify_reloc>
class Mips_scan_relocatable_relocs :
public Default_scan_relocatable_relocs<sh_type, Classify_reloc>
public Default_scan_relocatable_relocs<Classify_reloc>
{
public:
// Return the strategy to use for a local symbol which is a section
@ -2652,7 +2652,7 @@ class Mips_scan_relocatable_relocs :
inline Relocatable_relocs::Reloc_strategy
local_section_strategy(unsigned int r_type, Relobj* object)
{
if (sh_type == elfcpp::SHT_RELA)
if (Classify_reloc::sh_type == elfcpp::SHT_RELA)
return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA;
else
{
@ -2662,7 +2662,7 @@ class Mips_scan_relocatable_relocs :
return Relocatable_relocs::RELOC_SPECIAL;
default:
return Default_scan_relocatable_relocs<sh_type, Classify_reloc>::
return Default_scan_relocatable_relocs<Classify_reloc>::
local_section_strategy(r_type, object);
}
}
@ -2860,6 +2860,182 @@ class Symbol_visitor_check_symbols
Symbol_table* symtab_;
};
// Relocation types, parameterized by SHT_REL vs. SHT_RELA, size,
// and endianness. The relocation format for MIPS-64 is non-standard.
template<int sh_type, int size, bool big_endian>
struct Mips_reloc_types;
template<bool big_endian>
struct Mips_reloc_types<elfcpp::SHT_REL, 32, big_endian>
{
typedef typename elfcpp::Rel<32, big_endian> Reloc;
typedef typename elfcpp::Rel_write<32, big_endian> Reloc_write;
static unsigned typename elfcpp::Elf_types<32>::Elf_Swxword
get_r_addend(const Reloc*)
{ return 0; }
static inline void
set_reloc_addend(Reloc_write*,
typename elfcpp::Elf_types<32>::Elf_Swxword)
{ gold_unreachable(); }
};
template<bool big_endian>
struct Mips_reloc_types<elfcpp::SHT_RELA, 32, big_endian>
{
typedef typename elfcpp::Rela<32, big_endian> Reloc;
typedef typename elfcpp::Rela_write<32, big_endian> Reloc_write;
static unsigned typename elfcpp::Elf_types<32>::Elf_Swxword
get_r_addend(const Reloc* reloc)
{ return reloc->get_r_addend(); }
static inline void
set_reloc_addend(Reloc_write* p,
typename elfcpp::Elf_types<32>::Elf_Swxword val)
{ p->put_r_addend(val); }
};
template<bool big_endian>
struct Mips_reloc_types<elfcpp::SHT_REL, 64, big_endian>
{
typedef typename elfcpp::Mips64_rel<big_endian> Reloc;
typedef typename elfcpp::Mips64_rel_write<big_endian> Reloc_write;
static unsigned typename elfcpp::Elf_types<64>::Elf_Swxword
get_r_addend(const Reloc*)
{ return 0; }
static inline void
set_reloc_addend(Reloc_write*,
typename elfcpp::Elf_types<64>::Elf_Swxword)
{ gold_unreachable(); }
};
template<bool big_endian>
struct Mips_reloc_types<elfcpp::SHT_RELA, 64, big_endian>
{
typedef typename elfcpp::Mips64_rela<big_endian> Reloc;
typedef typename elfcpp::Mips64_rela_write<big_endian> Reloc_write;
static unsigned typename elfcpp::Elf_types<64>::Elf_Swxword
get_r_addend(const Reloc* reloc)
{ return reloc->get_r_addend(); }
static inline void
set_reloc_addend(Reloc_write* p,
typename elfcpp::Elf_types<64>::Elf_Swxword val)
{ p->put_r_addend(val); }
};
// Forward declaration.
static unsigned int
mips_get_size_for_reloc(unsigned int, Relobj*);
// A class for inquiring about properties of a relocation,
// used while scanning relocs during a relocatable link and
// garbage collection.
template<int sh_type_, int size, bool big_endian>
class Mips_classify_reloc;
template<int sh_type_, bool big_endian>
class Mips_classify_reloc<sh_type_, 32, big_endian> :
public gold::Default_classify_reloc<sh_type_, 32, big_endian>
{
public:
typedef typename Mips_reloc_types<sh_type_, 32, big_endian>::Reloc
Reltype;
typedef typename Mips_reloc_types<sh_type_, 32, big_endian>::Reloc_write
Reltype_write;
// Return the symbol referred to by the relocation.
static inline unsigned int
get_r_sym(const Reltype* reloc)
{ return elfcpp::elf_r_sym<32>(reloc->get_r_info()); }
// Return the type of the relocation.
static inline unsigned int
get_r_type(const Reltype* reloc)
{ return elfcpp::elf_r_type<32>(reloc->get_r_info()); }
// Return the explicit addend of the relocation (return 0 for SHT_REL).
static inline unsigned int
get_r_addend(const Reltype* reloc)
{ return Mips_reloc_types<sh_type_, 32, big_endian>::get_r_addend(reloc); }
// Write the r_info field to a new reloc, using the r_info field from
// the original reloc, replacing the r_sym field with R_SYM.
static inline void
put_r_info(Reltype_write* new_reloc, Reltype* reloc, unsigned int r_sym)
{
unsigned int r_type = elfcpp::elf_r_type<32>(reloc->get_r_info());
new_reloc->put_r_info(elfcpp::elf_r_info<64>(r_sym, r_type));
}
// Write the r_addend field to a new reloc.
static inline void
put_r_addend(Reltype_write* to,
typename elfcpp::Elf_types<32>::Elf_Swxword addend)
{ Mips_reloc_types<sh_type_, 32, big_endian>::set_reloc_addend(to, addend); }
// Return the size of the addend of the relocation (only used for SHT_REL).
static unsigned int
get_size_for_reloc(unsigned int r_type, Relobj* obj)
{ return mips_get_size_for_reloc(r_type, obj); }
};
template<int sh_type_, bool big_endian>
class Mips_classify_reloc<sh_type_, 64, big_endian> :
public gold::Default_classify_reloc<sh_type_, 64, big_endian>
{
public:
typedef typename Mips_reloc_types<sh_type_, 64, big_endian>::Reloc
Reltype;
typedef typename Mips_reloc_types<sh_type_, 64, big_endian>::Reloc_write
Reltype_write;
// Return the symbol referred to by the relocation.
static inline unsigned int
get_r_sym(const Reltype* reloc)
{ return reloc->get_r_sym(); }
// Return the type of the relocation.
static inline unsigned int
get_r_type(const Reltype* reloc)
{ return reloc->get_r_type(); }
// Return the explicit addend of the relocation (return 0 for SHT_REL).
static inline typename elfcpp::Elf_types<64>::Elf_Swxword
get_r_addend(const Reltype* reloc)
{ return Mips_reloc_types<sh_type_, 64, big_endian>::get_r_addend(reloc); }
// Write the r_info field to a new reloc, using the r_info field from
// the original reloc, replacing the r_sym field with R_SYM.
static inline void
put_r_info(Reltype_write* new_reloc, Reltype* reloc, unsigned int r_sym)
{
new_reloc->put_r_sym(r_sym);
new_reloc->put_r_ssym(reloc->get_r_ssym());
new_reloc->put_r_type3(reloc->get_r_type3());
new_reloc->put_r_type2(reloc->get_r_type2());
new_reloc->put_r_type(reloc->get_r_type());
}
// Write the r_addend field to a new reloc.
static inline void
put_r_addend(Reltype_write* to,
typename elfcpp::Elf_types<64>::Elf_Swxword addend)
{ Mips_reloc_types<sh_type_, 64, big_endian>::set_reloc_addend(to, addend); }
// Return the size of the addend of the relocation (only used for SHT_REL).
static unsigned int
get_size_for_reloc(unsigned int r_type, Relobj* obj)
{ return mips_get_size_for_reloc(r_type, obj); }
};
template<int size, bool big_endian>
class Target_mips : public Sized_target<size, big_endian>
{
@ -2870,6 +3046,10 @@ class Target_mips : public Sized_target<size, big_endian>
Reloca_section;
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype32;
typedef typename elfcpp::Swap<size, big_endian>::Valtype Valtype;
typedef typename Mips_reloc_types<elfcpp::SHT_REL, size, big_endian>::Reloc
Reltype;
typedef typename Mips_reloc_types<elfcpp::SHT_RELA, size, big_endian>::Reloc
Relatype;
public:
Target_mips(const Target::Target_info* info = &mips_info)
@ -2955,6 +3135,21 @@ class Target_mips : public Sized_target<size, big_endian>
const unsigned char* plocal_symbols,
Relocatable_relocs*);
// Scan the relocs for --emit-relocs.
void
emit_relocs_scan(Symbol_table* symtab,
Layout* layout,
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_syms,
Relocatable_relocs* rr);
// Emit relocations for a section.
void
relocate_relocs(const Relocate_info<size, big_endian>*,
@ -3164,6 +3359,17 @@ class Target_mips : public Sized_target<size, big_endian>
use_32bit_micromips_instructions() const
{ return this->insn32_; }
// Return the r_sym field from a relocation.
unsigned int
get_r_sym(const unsigned char* preloc) const
{
// Since REL and RELA relocs share the same structure through
// the r_info field, we can just use REL here.
Reltype rel(preloc);
return Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>::
get_r_sym(&rel);
}
protected:
// Return the value to use for a dynamic symbol which requires special
// treatment. This is how we support equality comparisons of function
@ -3268,7 +3474,7 @@ class Target_mips : public Sized_target<size, big_endian>
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
Output_section* output_section,
const elfcpp::Rel<size, big_endian>& reloc, unsigned int r_type,
const Reltype& reloc, unsigned int r_type,
const elfcpp::Sym<size, big_endian>& lsym,
bool is_discarded);
@ -3277,7 +3483,7 @@ class Target_mips : public Sized_target<size, big_endian>
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
Output_section* output_section,
const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
const Relatype& reloc, unsigned int r_type,
const elfcpp::Sym<size, big_endian>& lsym,
bool is_discarded);
@ -3286,8 +3492,8 @@ class Target_mips : public Sized_target<size, big_endian>
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
Output_section* output_section,
const elfcpp::Rela<size, big_endian>* rela,
const elfcpp::Rel<size, big_endian>* rel,
const Relatype* rela,
const Reltype* rel,
unsigned int rel_type,
unsigned int r_type,
const elfcpp::Sym<size, big_endian>& lsym,
@ -3298,7 +3504,7 @@ class Target_mips : public Sized_target<size, big_endian>
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
Output_section* output_section,
const elfcpp::Rel<size, big_endian>& reloc, unsigned int r_type,
const Reltype& reloc, unsigned int r_type,
Symbol* gsym);
inline void
@ -3306,7 +3512,7 @@ class Target_mips : public Sized_target<size, big_endian>
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
Output_section* output_section,
const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
const Relatype& reloc, unsigned int r_type,
Symbol* gsym);
inline void
@ -3314,8 +3520,8 @@ class Target_mips : public Sized_target<size, big_endian>
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
Output_section* output_section,
const elfcpp::Rela<size, big_endian>* rela,
const elfcpp::Rel<size, big_endian>* rel,
const Relatype* rela,
const Reltype* rel,
unsigned int rel_type,
unsigned int r_type,
Symbol* gsym);
@ -3326,7 +3532,7 @@ class Target_mips : public Sized_target<size, big_endian>
Sized_relobj_file<size, big_endian>*,
unsigned int,
Output_section*,
const elfcpp::Rel<size, big_endian>&,
const Reltype&,
unsigned int,
const elfcpp::Sym<size, big_endian>&)
{ return false; }
@ -3337,7 +3543,7 @@ class Target_mips : public Sized_target<size, big_endian>
Sized_relobj_file<size, big_endian>*,
unsigned int,
Output_section*,
const elfcpp::Rel<size, big_endian>&,
const Reltype&,
unsigned int, Symbol*)
{ return false; }
@ -3347,7 +3553,7 @@ class Target_mips : public Sized_target<size, big_endian>
Sized_relobj_file<size, big_endian>*,
unsigned int,
Output_section*,
const elfcpp::Rela<size, big_endian>&,
const Relatype&,
unsigned int,
const elfcpp::Sym<size, big_endian>&)
{ return false; }
@ -3358,7 +3564,7 @@ class Target_mips : public Sized_target<size, big_endian>
Sized_relobj_file<size, big_endian>*,
unsigned int,
Output_section*,
const elfcpp::Rela<size, big_endian>&,
const Relatype&,
unsigned int, Symbol*)
{ return false; }
private:
@ -3397,15 +3603,6 @@ class Target_mips : public Sized_target<size, big_endian>
unsigned char*, Mips_address, section_size_type);
};
// A class which returns the size required for a relocation type,
// used while scanning relocs during a relocatable link.
class Relocatable_size_for_reloc
{
public:
unsigned int
get_size_for_reloc(unsigned int, Relobj*);
};
// This POD class holds the dynamic relocations that should be emitted instead
// of R_MIPS_32, R_MIPS_REL32 and R_MIPS_64 relocations. We will emit these
// relocations if it turns out that the symbol does not have static
@ -3573,9 +3770,11 @@ class Target_mips : public Sized_target<size, big_endian>
copy_reloc(Symbol_table* symtab, Layout* layout,
Sized_relobj_file<size, big_endian>* object,
unsigned int shndx, Output_section* output_section,
Symbol* sym, const elfcpp::Rel<size, big_endian>& reloc)
Symbol* sym, const Reltype& reloc)
{
unsigned int r_type = elfcpp::elf_r_type<size>(reloc.get_r_info());
unsigned int r_type =
Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>::
get_r_type(&reloc);
this->copy_relocs_.copy_reloc(symtab, layout,
symtab->get_sized_symbol<size>(sym),
object, shndx, output_section,
@ -3725,7 +3924,6 @@ class Target_mips : public Sized_target<size, big_endian>
bool insn32_;
};
// Helper structure for R_MIPS*_HI16/LO16 and R_MIPS*_GOT16/LO16 relocations.
// It records high part of the relocation pair.
@ -7510,10 +7708,10 @@ Target_mips<size, big_endian>::gc_process_relocs(
const unsigned char* plocal_symbols)
{
typedef Target_mips<size, big_endian> Mips;
typedef typename Target_mips<size, big_endian>::Scan Scan;
typedef Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>
Classify_reloc;
gold::gc_process_relocs<size, big_endian, Mips, elfcpp::SHT_REL, Scan,
typename Target_mips::Relocatable_size_for_reloc>(
gold::gc_process_relocs<size, big_endian, Mips, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -7545,34 +7743,43 @@ Target_mips<size, big_endian>::scan_relocs(
const unsigned char* plocal_symbols)
{
typedef Target_mips<size, big_endian> Mips;
typedef typename Target_mips<size, big_endian>::Scan Scan;
if (sh_type == elfcpp::SHT_REL)
gold::scan_relocs<size, big_endian, Mips, elfcpp::SHT_REL, Scan>(
symtab,
layout,
this,
object,
data_shndx,
prelocs,
reloc_count,
output_section,
needs_special_offset_handling,
local_symbol_count,
plocal_symbols);
{
typedef Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>
Classify_reloc;
gold::scan_relocs<size, big_endian, Mips, Scan, Classify_reloc>(
symtab,
layout,
this,
object,
data_shndx,
prelocs,
reloc_count,
output_section,
needs_special_offset_handling,
local_symbol_count,
plocal_symbols);
}
else if (sh_type == elfcpp::SHT_RELA)
gold::scan_relocs<size, big_endian, Mips, elfcpp::SHT_RELA, Scan>(
symtab,
layout,
this,
object,
data_shndx,
prelocs,
reloc_count,
output_section,
needs_special_offset_handling,
local_symbol_count,
plocal_symbols);
{
typedef Mips_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
gold::scan_relocs<size, big_endian, Mips, Scan, Classify_reloc>(
symtab,
layout,
this,
object,
data_shndx,
prelocs,
reloc_count,
output_section,
needs_special_offset_handling,
local_symbol_count,
plocal_symbols);
}
}
template<int size, bool big_endian>
@ -8227,41 +8434,48 @@ Target_mips<size, big_endian>::relocate_section(
typedef typename Target_mips<size, big_endian>::Relocate Mips_relocate;
if (sh_type == elfcpp::SHT_REL)
gold::relocate_section<size, big_endian, Mips, elfcpp::SHT_REL,
Mips_relocate, gold::Default_comdat_behavior>(
relinfo,
this,
prelocs,
reloc_count,
output_section,
needs_special_offset_handling,
view,
address,
view_size,
reloc_symbol_changes);
{
typedef Mips_classify_reloc<elfcpp::SHT_REL, size, big_endian>
Classify_reloc;
gold::relocate_section<size, big_endian, Mips, Mips_relocate,
gold::Default_comdat_behavior, Classify_reloc>(
relinfo,
this,
prelocs,
reloc_count,
output_section,
needs_special_offset_handling,
view,
address,
view_size,
reloc_symbol_changes);
}
else if (sh_type == elfcpp::SHT_RELA)
gold::relocate_section<size, big_endian, Mips, elfcpp::SHT_RELA,
Mips_relocate, gold::Default_comdat_behavior>(
relinfo,
this,
prelocs,
reloc_count,
output_section,
needs_special_offset_handling,
view,
address,
view_size,
reloc_symbol_changes);
{
typedef Mips_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
gold::relocate_section<size, big_endian, Mips, Mips_relocate,
gold::Default_comdat_behavior, Classify_reloc>(
relinfo,
this,
prelocs,
reloc_count,
output_section,
needs_special_offset_handling,
view,
address,
view_size,
reloc_symbol_changes);
}
}
// Return the size of a relocation while scanning during a relocatable
// link.
template<int size, bool big_endian>
unsigned int
Target_mips<size, big_endian>::Relocatable_size_for_reloc::get_size_for_reloc(
unsigned int r_type,
Relobj* object)
mips_get_size_for_reloc(unsigned int r_type, Relobj* object)
{
switch (r_type)
{
@ -8344,13 +8558,14 @@ Target_mips<size, big_endian>::scan_relocatable_relocs(
const unsigned char* plocal_symbols,
Relocatable_relocs* rr)
{
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;

View file

@ -2710,7 +2710,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
unsigned int sh_type, unsigned int shndx,
const unsigned char* prelocs, size_t reloc_count,
unsigned char* view, section_size_type view_size,
Reloc_symbol_changes** reloc_map);
Reloc_symbol_changes** reloc_map,
const Sized_target<size, big_endian>* target);
template<int sh_type>
void
@ -2718,7 +2719,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
unsigned int shndx, const unsigned char* prelocs,
size_t reloc_count, unsigned char* view,
section_size_type view_size,
Reloc_symbol_changes** reloc_map);
Reloc_symbol_changes** reloc_map,
const Sized_target<size, big_endian>* target);
// Find all functions in a section.
void

View file

@ -663,6 +663,21 @@ class Target_powerpc : public Sized_target<size, big_endian>
const unsigned char* plocal_symbols,
Relocatable_relocs*);
// Scan the relocs for --emit-relocs.
void
emit_relocs_scan(Symbol_table* symtab,
Layout* layout,
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_syms,
Relocatable_relocs* rr);
// Emit relocations for a section.
void
relocate_relocs(const Relocate_info<size, big_endian>*,
@ -1105,19 +1120,6 @@ class Target_powerpc : public Sized_target<size, big_endian>
}
};
// A class which returns the size required for a relocation type,
// used while scanning relocs during a relocatable link.
class Relocatable_size_for_reloc
{
public:
unsigned int
get_size_for_reloc(unsigned int, Relobj*)
{
gold_unreachable();
return 0;
}
};
// Optimize the TLS relocation type based on what we know about the
// symbol. IS_FINAL is true if the final address of this symbol is
// known at link time.
@ -6430,7 +6432,9 @@ Target_powerpc<size, big_endian>::gc_process_relocs(
const unsigned char* plocal_symbols)
{
typedef Target_powerpc<size, big_endian> Powerpc;
typedef typename Target_powerpc<size, big_endian>::Scan Scan;
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
Powerpc_relobj<size, big_endian>* ppc_object
= static_cast<Powerpc_relobj<size, big_endian>*>(object);
if (size == 64)
@ -6460,8 +6464,7 @@ Target_powerpc<size, big_endian>::gc_process_relocs(
return;
}
gold::gc_process_relocs<size, big_endian, Powerpc, elfcpp::SHT_RELA, Scan,
typename Target_powerpc::Relocatable_size_for_reloc>(
gold::gc_process_relocs<size, big_endian, Powerpc, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -6707,7 +6710,8 @@ Target_powerpc<size, big_endian>::scan_relocs(
const unsigned char* plocal_symbols)
{
typedef Target_powerpc<size, big_endian> Powerpc;
typedef typename Target_powerpc<size, big_endian>::Scan Scan;
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
if (sh_type == elfcpp::SHT_REL)
{
@ -6716,7 +6720,7 @@ Target_powerpc<size, big_endian>::scan_relocs(
return;
}
gold::scan_relocs<size, big_endian, Powerpc, elfcpp::SHT_RELA, Scan>(
gold::scan_relocs<size, big_endian, Powerpc, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -8177,11 +8181,13 @@ Target_powerpc<size, big_endian>::relocate_section(
typedef typename Target_powerpc<size, big_endian>::Relocate Powerpc_relocate;
typedef typename Target_powerpc<size, big_endian>::Relocate_comdat_behavior
Powerpc_comdat_behavior;
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
gold_assert(sh_type == elfcpp::SHT_RELA);
gold::relocate_section<size, big_endian, Powerpc, elfcpp::SHT_RELA,
Powerpc_relocate, Powerpc_comdat_behavior>(
gold::relocate_section<size, big_endian, Powerpc, Powerpc_relocate,
Powerpc_comdat_behavior, Classify_reloc>(
relinfo,
this,
prelocs,
@ -8194,9 +8200,26 @@ Target_powerpc<size, big_endian>::relocate_section(
reloc_symbol_changes);
}
template<int size, bool big_endian>
class Powerpc_scan_relocatable_reloc
{
public:
typedef typename Reloc_types<elfcpp::SHT_RELA, size, big_endian>::Reloc
Reltype;
static const int reloc_size =
Reloc_types<elfcpp::SHT_RELA, size, big_endian>::reloc_size;
static const int sh_type = elfcpp::SHT_RELA;
// Return the symbol referred to by the relocation.
static inline unsigned int
get_r_sym(const Reltype* reloc)
{ return elfcpp::elf_r_sym<size>(reloc->get_r_info()); }
// Return the type of the relocation.
static inline unsigned int
get_r_type(const Reltype* reloc)
{ return elfcpp::elf_r_type<size>(reloc->get_r_info()); }
// Return the strategy to use for a local symbol which is not a
// section symbol, given the relocation type.
inline Relocatable_relocs::Reloc_strategy
@ -8244,10 +8267,11 @@ Target_powerpc<size, big_endian>::scan_relocatable_relocs(
const unsigned char* plocal_symbols,
Relocatable_relocs* rr)
{
typedef Powerpc_scan_relocatable_reloc<size, big_endian> Scan_strategy;
gold_assert(sh_type == elfcpp::SHT_RELA);
gold::scan_relocatable_relocs<size, big_endian, elfcpp::SHT_RELA,
Powerpc_scan_relocatable_reloc>(
gold::scan_relocatable_relocs<size, big_endian, Scan_strategy>(
symtab,
layout,
object,
@ -8261,6 +8285,45 @@ Target_powerpc<size, big_endian>::scan_relocatable_relocs(
rr);
}
// Scan the relocs for --emit-relocs.
template<int size, bool big_endian>
void
Target_powerpc<size, big_endian>::emit_relocs_scan(
Symbol_table* symtab,
Layout* layout,
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_syms,
Relocatable_relocs* rr)
{
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
typedef gold::Default_emit_relocs_strategy<Classify_reloc>
Emit_relocs_strategy;
gold_assert(sh_type == elfcpp::SHT_RELA);
gold::scan_relocatable_relocs<size, big_endian, Emit_relocs_strategy>(
symtab,
layout,
object,
data_shndx,
prelocs,
reloc_count,
output_section,
needs_special_offset_handling,
local_symbol_count,
plocal_syms,
rr);
}
// Emit relocations for a section.
// This is a modified version of the function by the same name in
// target-reloc.h. Using relocate_special_relocatable for

View file

@ -56,10 +56,6 @@ struct Reloc_types<elfcpp::SHT_REL, size, big_endian>
set_reloc_addend(Reloc_write*,
typename elfcpp::Elf_types<size>::Elf_Swxword)
{ gold_unreachable(); }
static inline void
copy_reloc_addend(Reloc_write*, const Reloc*)
{ gold_unreachable(); }
};
template<int size, bool big_endian>
@ -81,10 +77,6 @@ struct Reloc_types<elfcpp::SHT_RELA, size, big_endian>
set_reloc_addend(Reloc_write* p,
typename elfcpp::Elf_types<size>::Elf_Swxword val)
{ p->put_r_addend(val); }
static inline void
copy_reloc_addend(Reloc_write* to, const Reloc* from)
{ to->put_r_addend(from->get_r_addend()); }
};
}; // End namespace gold.

View file

@ -424,8 +424,8 @@ Sized_relobj_file<size, big_endian>::do_gc_process_relocs(Symbol_table* symtab,
template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_scan_relocs(Symbol_table* symtab,
Layout* layout,
Read_relocs_data* rd)
Layout* layout,
Read_relocs_data* rd)
{
Sized_target<size, big_endian>* target =
parameters->sized_target<size, big_endian>();
@ -501,41 +501,6 @@ Sized_relobj_file<size, big_endian>::do_scan_relocs(Symbol_table* symtab,
}
}
// This is a strategy class we use when scanning for --emit-relocs.
template<int sh_type>
class Emit_relocs_strategy
{
public:
// A local non-section symbol.
inline Relocatable_relocs::Reloc_strategy
local_non_section_strategy(unsigned int, Relobj*, unsigned int)
{ return Relocatable_relocs::RELOC_COPY; }
// A local section symbol.
inline Relocatable_relocs::Reloc_strategy
local_section_strategy(unsigned int, Relobj*)
{
if (sh_type == elfcpp::SHT_RELA)
return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA;
else
{
// The addend is stored in the section contents. Since this
// is not a relocatable link, we are going to apply the
// relocation contents to the section as usual. This means
// that we have no way to record the original addend. If the
// original addend is not zero, there is basically no way for
// the user to handle this correctly. Caveat emptor.
return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0;
}
}
// A global symbol.
inline Relocatable_relocs::Reloc_strategy
global_strategy(unsigned int, Relobj*, unsigned int)
{ return Relocatable_relocs::RELOC_COPY; }
};
// Scan the input relocations for --emit-relocs.
template<int size, bool big_endian>
@ -546,40 +511,18 @@ Sized_relobj_file<size, big_endian>::emit_relocs_scan(
const unsigned char* plocal_syms,
const Read_relocs_data::Relocs_list::iterator& p)
{
Sized_target<size, big_endian>* target =
parameters->sized_target<size, big_endian>();
Relocatable_relocs* rr = this->relocatable_relocs(p->reloc_shndx);
gold_assert(rr != NULL);
rr->set_reloc_count(p->reloc_count);
if (p->sh_type == elfcpp::SHT_REL)
this->emit_relocs_scan_reltype<elfcpp::SHT_REL>(symtab, layout,
plocal_syms, p, rr);
else
{
gold_assert(p->sh_type == elfcpp::SHT_RELA);
this->emit_relocs_scan_reltype<elfcpp::SHT_RELA>(symtab, layout,
plocal_syms, p, rr);
}
}
// Scan the input relocation for --emit-relocs, templatized on the
// type of the relocation section.
template<int size, bool big_endian>
template<int sh_type>
void
Sized_relobj_file<size, big_endian>::emit_relocs_scan_reltype(
Symbol_table* symtab,
Layout* layout,
const unsigned char* plocal_syms,
const Read_relocs_data::Relocs_list::iterator& p,
Relocatable_relocs* rr)
{
scan_relocatable_relocs<size, big_endian, sh_type,
Emit_relocs_strategy<sh_type> >(
target->emit_relocs_scan(
symtab,
layout,
this,
p->data_shndx,
p->sh_type,
p->contents->data(),
p->reloc_count,
p->output_section,
@ -628,8 +571,8 @@ Sized_relobj_file<size, big_endian>::incremental_relocs_scan_reltype(
reloc.get_r_offset()))
continue;
typename elfcpp::Elf_types<size>::Elf_WXword r_info =
reloc.get_r_info();
// FIXME: Some targets have a non-standard r_info field.
typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
if (r_sym >= this->local_symbol_count_)
@ -1025,7 +968,7 @@ Sized_relobj_file<size, big_endian>::do_relocate_sections(
if ((data_shdr.get_sh_flags() & elfcpp::SHF_EXECINSTR) != 0)
this->split_stack_adjust(symtab, pshdrs, sh_type, index,
prelocs, reloc_count, view, view_size,
&reloc_map);
&reloc_map, target);
}
Relocatable_relocs* rr = NULL;
@ -1142,6 +1085,7 @@ Sized_relobj_file<size, big_endian>::incremental_relocs_write_reltype(
{
Reloc reloc(prelocs);
// FIXME: Some targets have a non-standard r_info field.
typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
const unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
@ -1240,20 +1184,21 @@ Sized_relobj_file<size, big_endian>::split_stack_adjust(
size_t reloc_count,
unsigned char* view,
section_size_type view_size,
Reloc_symbol_changes** reloc_map)
Reloc_symbol_changes** reloc_map,
const Sized_target<size, big_endian>* target)
{
if (sh_type == elfcpp::SHT_REL)
this->split_stack_adjust_reltype<elfcpp::SHT_REL>(symtab, pshdrs, shndx,
prelocs, reloc_count,
view, view_size,
reloc_map);
reloc_map, target);
else
{
gold_assert(sh_type == elfcpp::SHT_RELA);
this->split_stack_adjust_reltype<elfcpp::SHT_RELA>(symtab, pshdrs, shndx,
prelocs, reloc_count,
view, view_size,
reloc_map);
reloc_map, target);
}
}
@ -1271,7 +1216,8 @@ Sized_relobj_file<size, big_endian>::split_stack_adjust_reltype(
size_t reloc_count,
unsigned char* view,
section_size_type view_size,
Reloc_symbol_changes** reloc_map)
Reloc_symbol_changes** reloc_map,
const Sized_target<size, big_endian>* target)
{
typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
@ -1283,10 +1229,10 @@ Sized_relobj_file<size, big_endian>::split_stack_adjust_reltype(
const unsigned char* pr = prelocs;
for (size_t i = 0; i < reloc_count; ++i, pr += reloc_size)
{
Reltype reloc(pr);
typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
// Some supported targets have a non-standard r_info field.
// If this call is too slow, we can move this routine to
// target-reloc.h and templatize it on Classify_reloc.
unsigned int r_sym = target->get_r_sym(pr);
if (r_sym < local_count)
continue;
@ -1305,9 +1251,9 @@ Sized_relobj_file<size, big_endian>::split_stack_adjust_reltype(
&& gsym->source() == Symbol::FROM_OBJECT
&& !gsym->object()->uses_split_stack())
{
unsigned int r_type = elfcpp::elf_r_type<size>(reloc.get_r_info());
if (parameters->target().is_call_to_non_split(gsym, r_type))
if (parameters->target().is_call_to_non_split(gsym, pr))
{
Reltype reloc(pr);
section_offset_type offset =
convert_to_section_size_type(reloc.get_r_offset());
non_split_refs.push_back(offset);
@ -1378,9 +1324,7 @@ Sized_relobj_file<size, big_endian>::split_stack_adjust_reltype(
{
Reltype reloc(pr);
typename elfcpp::Elf_types<size>::Elf_WXword r_info =
reloc.get_r_info();
unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
unsigned int r_sym = target->get_r_sym(pr);
if (r_sym < local_count)
continue;
@ -1600,11 +1544,9 @@ Track_relocs<size, big_endian>::next_symndx() const
{
if (this->pos_ >= this->len_)
return -1U;
// Rel and Rela start out the same, so we can use Rel to find the
// symbol index.
elfcpp::Rel<size, big_endian> rel(this->prelocs_ + this->pos_);
return elfcpp::elf_r_sym<size>(rel.get_r_info());
Sized_target<size, big_endian>* target
= parameters->sized_target<size, big_endian>();
return target->get_r_sym(this->prelocs_ + this->pos_);
}
// Return the addend of the next reloc, or 0 if there isn't one.

View file

@ -348,6 +348,21 @@ class Target_s390 : public Sized_target<size, true>
const unsigned char* plocal_symbols,
Relocatable_relocs*);
// Scan the relocs for --emit-relocs.
void
emit_relocs_scan(Symbol_table* symtab,
Layout* layout,
Sized_relobj_file<size, true>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_syms,
Relocatable_relocs* rr);
// Return a string used to fill a code section with nops.
std::string
do_code_fill(section_size_type length) const;
@ -596,15 +611,6 @@ class Target_s390 : public Sized_target<size, true>
section_size_type view_size);
};
// A class which returns the size required for a relocation type,
// used while scanning relocs during a relocatable link.
class Relocatable_size_for_reloc
{
public:
unsigned int
get_size_for_reloc(unsigned int, Relobj*);
};
// Adjust TLS relocation type based on the options and whether this
// is a local symbol.
static tls::Tls_optimization
@ -3086,13 +3092,13 @@ Target_s390<size>::gc_process_relocs(Symbol_table* symtab,
size_t local_symbol_count,
const unsigned char* plocal_symbols)
{
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, true>
Classify_reloc;
if (sh_type == elfcpp::SHT_REL)
return;
gold::gc_process_relocs<size, true, Target_s390<size>, elfcpp::SHT_RELA,
typename Target_s390<size>::Scan,
typename Target_s390<size>::Relocatable_size_for_reloc>(
gold::gc_process_relocs<size, true, Target_s390<size>, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -3924,6 +3930,9 @@ Target_s390<size>::scan_relocs(Symbol_table* symtab,
size_t local_symbol_count,
const unsigned char* plocal_symbols)
{
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, true>
Classify_reloc;
if (sh_type == elfcpp::SHT_REL)
{
gold_error(_("%s: unsupported REL reloc section"),
@ -3931,8 +3940,7 @@ Target_s390<size>::scan_relocs(Symbol_table* symtab,
return;
}
gold::scan_relocs<size, true, Target_s390<size>, elfcpp::SHT_RELA,
typename Target_s390<size>::Scan>(
gold::scan_relocs<size, true, Target_s390<size>, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -4019,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,

View file

@ -131,6 +131,21 @@ class Target_sparc : public Sized_target<size, big_endian>
const unsigned char* plocal_symbols,
Relocatable_relocs*);
// Scan the relocs for --emit-relocs.
void
emit_relocs_scan(Symbol_table* symtab,
Layout* layout,
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_syms,
Relocatable_relocs* rr);
// Emit relocations for a section.
void
relocate_relocs(const Relocate_info<size, big_endian>*,
@ -345,15 +360,6 @@ class Target_sparc : public Sized_target<size, big_endian>
unsigned char *reloc_adjust_addr_;
};
// A class which returns the size required for a relocation type,
// used while scanning relocs during a relocatable link.
class Relocatable_size_for_reloc
{
public:
unsigned int
get_size_for_reloc(unsigned int, Relobj*);
};
// Get the GOT section, creating it if necessary.
Output_data_got<size, big_endian>*
got_section(Symbol_table*, Layout*);
@ -3036,9 +3042,10 @@ Target_sparc<size, big_endian>::gc_process_relocs(
{
typedef Target_sparc<size, big_endian> Sparc;
typedef typename Target_sparc<size, big_endian>::Scan Scan;
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
gold::gc_process_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan,
typename Target_sparc::Relocatable_size_for_reloc>(
gold::gc_process_relocs<size, big_endian, Sparc, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -3070,7 +3077,8 @@ Target_sparc<size, big_endian>::scan_relocs(
const unsigned char* plocal_symbols)
{
typedef Target_sparc<size, big_endian> Sparc;
typedef typename Target_sparc<size, big_endian>::Scan Scan;
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
if (sh_type == elfcpp::SHT_REL)
{
@ -3079,7 +3087,7 @@ Target_sparc<size, big_endian>::scan_relocs(
return;
}
gold::scan_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan>(
gold::scan_relocs<size, big_endian, Sparc, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -4142,11 +4150,13 @@ Target_sparc<size, big_endian>::relocate_section(
{
typedef Target_sparc<size, big_endian> Sparc;
typedef typename Target_sparc<size, big_endian>::Relocate Sparc_relocate;
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
gold_assert(sh_type == elfcpp::SHT_RELA);
gold::relocate_section<size, big_endian, Sparc, elfcpp::SHT_RELA,
Sparc_relocate, gold::Default_comdat_behavior>(
gold::relocate_section<size, big_endian, Sparc, Sparc_relocate,
gold::Default_comdat_behavior, Classify_reloc>(
relinfo,
this,
prelocs,
@ -4159,20 +4169,6 @@ Target_sparc<size, big_endian>::relocate_section(
reloc_symbol_changes);
}
// Return the size of a relocation while scanning during a relocatable
// link.
template<int size, bool big_endian>
unsigned int
Target_sparc<size, big_endian>::Relocatable_size_for_reloc::get_size_for_reloc(
unsigned int,
Relobj*)
{
// We are always SHT_RELA, so we should never get here.
gold_unreachable();
return 0;
}
// Scan the relocs during a relocatable link.
template<int size, bool big_endian>
@ -4191,13 +4187,14 @@ Target_sparc<size, big_endian>::scan_relocatable_relocs(
const unsigned char* plocal_symbols,
Relocatable_relocs* rr)
{
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,

View file

@ -39,8 +39,8 @@ namespace gold
// avoid making a function call for each relocation, and to avoid
// repeating the generic code for each target.
template<int size, bool big_endian, typename Target_type, int sh_type,
typename Scan>
template<int size, bool big_endian, typename Target_type,
typename Scan, typename Classify_reloc>
inline void
scan_relocs(
Symbol_table* symtab,
@ -55,8 +55,8 @@ scan_relocs(
size_t local_count,
const unsigned char* plocal_syms)
{
typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
typedef typename Classify_reloc::Reltype Reltype;
const int reloc_size = Classify_reloc::reloc_size;
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
Scan scan;
@ -69,9 +69,8 @@ scan_relocs(
reloc.get_r_offset()))
continue;
typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
unsigned int r_sym = Classify_reloc::get_r_sym(&reloc);
unsigned int r_type = Classify_reloc::get_r_type(&reloc);
if (r_sym < local_count)
{
@ -253,9 +252,10 @@ issue_undefined_symbol_error(const Symbol* sym)
// symbol for the relocation, ignoring the symbol index in the
// relocation.
template<int size, bool big_endian, typename Target_type, int sh_type,
template<int size, bool big_endian, typename Target_type,
typename Relocate,
typename Relocate_comdat_behavior>
typename Relocate_comdat_behavior,
typename Classify_reloc>
inline void
relocate_section(
const Relocate_info<size, big_endian>* relinfo,
@ -269,8 +269,8 @@ relocate_section(
section_size_type view_size,
const Reloc_symbol_changes* reloc_symbol_changes)
{
typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
typedef typename Classify_reloc::Reltype Reltype;
const int reloc_size = Classify_reloc::reloc_size;
Relocate relocate;
Relocate_comdat_behavior relocate_comdat_behavior;
@ -295,8 +295,7 @@ relocate_section(
continue;
}
typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
unsigned int r_sym = Classify_reloc::get_r_sym(&reloc);
const Sized_symbol<size>* sym;
@ -399,8 +398,8 @@ relocate_section(
if (offset < 0 || static_cast<section_size_type>(offset) >= view_size)
v = NULL;
if (!relocate.relocate(relinfo, sh_type, target, output_section,
i, prelocs, sym, psymval,
if (!relocate.relocate(relinfo, Classify_reloc::sh_type, target,
output_section, i, prelocs, sym, psymval,
v, view_address + offset, view_size))
continue;
@ -464,18 +463,90 @@ apply_relocation(const Relocate_info<size, big_endian>* relinfo,
view + r_offset, address + r_offset, view_size);
}
// 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;

View file

@ -152,7 +152,7 @@ Target::do_make_output_section(const char* name, elfcpp::Elf_Word type,
// whether the symbol is a function.
bool
Target::do_is_call_to_non_split(const Symbol* sym, unsigned int) const
Target::do_is_call_to_non_split(const Symbol* sym, const unsigned char*) const
{
return sym->type() == elfcpp::STT_FUNC;
}

View file

@ -321,13 +321,13 @@ class Target
ehframe_datarel_base() const
{ return this->do_ehframe_datarel_base(); }
// Return true if a reference to SYM from a reloc of type R_TYPE
// Return true if a reference to SYM from a reloc at *PRELOC
// means that the current function may call an object compiled
// without -fsplit-stack. SYM is known to be defined in an object
// compiled without -fsplit-stack.
bool
is_call_to_non_split(const Symbol* sym, unsigned int r_type) const
{ return this->do_is_call_to_non_split(sym, r_type); }
is_call_to_non_split(const Symbol* sym, const unsigned char* preloc) const
{ return this->do_is_call_to_non_split(sym, preloc); }
// A function starts at OFFSET in section SHNDX in OBJECT. That
// function was compiled with -fsplit-stack, but it refers to a
@ -661,7 +661,7 @@ class Target
// default implementation is that any function not defined by the
// ABI is a call to a non-split function.
virtual bool
do_is_call_to_non_split(const Symbol* sym, unsigned int) const;
do_is_call_to_non_split(const Symbol* sym, const unsigned char*) const;
// Virtual function which may be overridden by the child class.
virtual void
@ -926,6 +926,22 @@ class Sized_target : public Target
const unsigned char* plocal_symbols,
Relocatable_relocs*) = 0;
// Scan the relocs for --emit-relocs. The parameters are
// like scan_relocatable_relocs.
virtual void
emit_relocs_scan(Symbol_table* symtab,
Layout* layout,
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_syms,
Relocatable_relocs* rr) = 0;
// Emit relocations for a section during a relocatable link, and for
// --emit-relocs. The parameters are like relocate_section, with
// additional parameters for the view of the output reloc section.
@ -1084,6 +1100,19 @@ class Sized_target : public Target
dst_obj, dst_shndx, dst_off);
}
// Return the r_sym field from a relocation.
// Most targets can use the default version of this routine,
// but some targets have a non-standard r_info field, and will
// need to provide a target-specific version.
virtual unsigned int
get_r_sym(const unsigned char* preloc) const
{
// Since REL and RELA relocs share the same structure through
// the r_info field, we can just use REL here.
elfcpp::Rel<size, big_endian> rel(preloc);
return elfcpp::elf_r_sym<size>(rel.get_r_info());
}
protected:
Sized_target(const Target::Target_info* pti)
: Target(pti)

View file

@ -71,6 +71,14 @@ class Target_test : public Sized_target<size, big_endian>
const unsigned char*, Relocatable_relocs*)
{ ERROR("call to Target_test::scan_relocatable_relocs"); }
void
emit_relocs_scan(Symbol_table*, Layout*,
Sized_relobj_file<size, big_endian>*, unsigned int,
unsigned int, const unsigned char*,
size_t, Output_section*, bool, size_t,
const unsigned char*, Relocatable_relocs*)
{ ERROR("call to Target_test::emit_relocs_scan"); }
void
relocate_relocs(const Relocate_info<size, big_endian>*,
unsigned int, const unsigned char*, size_t,

View file

@ -308,6 +308,21 @@ class Target_tilegx : public Sized_target<size, big_endian>
const unsigned char* plocal_symbols,
Relocatable_relocs*);
// Scan the relocs for --emit-relocs.
void
emit_relocs_scan(Symbol_table* symtab,
Layout* layout,
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_syms,
Relocatable_relocs* rr);
// Relocate a section during a relocatable link.
void
relocate_relocs(
@ -523,15 +538,6 @@ class Target_tilegx : public Sized_target<size, big_endian>
section_size_type);
};
// A class which returns the size required for a relocation type,
// used while scanning relocs during a relocatable link.
class Relocatable_size_for_reloc
{
public:
unsigned int
get_size_for_reloc(unsigned int, Relobj*);
};
// Adjust TLS relocation type based on the options and whether this
// is a local symbol.
static tls::Tls_optimization
@ -4154,26 +4160,26 @@ Target_tilegx<size, big_endian>::gc_process_relocs(Symbol_table* symtab,
{
typedef Target_tilegx<size, big_endian> Tilegx;
typedef typename Target_tilegx<size, big_endian>::Scan Scan;
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
if (sh_type == elfcpp::SHT_REL)
{
return;
}
gold::gc_process_relocs<size, big_endian,
Tilegx, elfcpp::SHT_RELA, Scan,
typename Target_tilegx<size, big_endian>::Relocatable_size_for_reloc>(
symtab,
layout,
this,
object,
data_shndx,
prelocs,
reloc_count,
output_section,
needs_special_offset_handling,
local_symbol_count,
plocal_symbols);
gold::gc_process_relocs<size, big_endian, Tilegx, Scan, Classify_reloc>(
symtab,
layout,
this,
object,
data_shndx,
prelocs,
reloc_count,
output_section,
needs_special_offset_handling,
local_symbol_count,
plocal_symbols);
}
// Scan relocations for a section.
@ -4193,6 +4199,8 @@ Target_tilegx<size, big_endian>::scan_relocs(Symbol_table* symtab,
{
typedef Target_tilegx<size, big_endian> Tilegx;
typedef typename Target_tilegx<size, big_endian>::Scan Scan;
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
if (sh_type == elfcpp::SHT_REL)
{
@ -4201,7 +4209,7 @@ Target_tilegx<size, big_endian>::scan_relocs(Symbol_table* symtab,
return;
}
gold::scan_relocs<size, big_endian, Tilegx, elfcpp::SHT_RELA, Scan>(
gold::scan_relocs<size, big_endian, Tilegx, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -4743,11 +4751,13 @@ Target_tilegx<size, big_endian>::relocate_section(
{
typedef Target_tilegx<size, big_endian> Tilegx;
typedef typename Target_tilegx<size, big_endian>::Relocate Tilegx_relocate;
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
Classify_reloc;
gold_assert(sh_type == elfcpp::SHT_RELA);
gold::relocate_section<size, big_endian, Tilegx, elfcpp::SHT_RELA,
Tilegx_relocate, gold::Default_comdat_behavior>(
gold::relocate_section<size, big_endian, Tilegx, Tilegx_relocate,
gold::Default_comdat_behavior, Classify_reloc>(
relinfo,
this,
prelocs,
@ -4788,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,

View file

@ -496,6 +496,21 @@ class Target_x86_64 : public Sized_target<size, false>
const unsigned char* plocal_symbols,
Relocatable_relocs*);
// Scan the relocs for --emit-relocs.
void
emit_relocs_scan(Symbol_table* symtab,
Layout* layout,
Sized_relobj_file<size, false>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_syms,
Relocatable_relocs* rr);
// Emit relocations for a section.
void
relocate_relocs(
@ -859,15 +874,6 @@ class Target_x86_64 : public Sized_target<size, false>
bool skip_call_tls_get_addr_;
};
// A class which returns the size required for a relocation type,
// used while scanning relocs during a relocatable link.
class Relocatable_size_for_reloc
{
public:
unsigned int
get_size_for_reloc(unsigned int, Relobj*);
};
// Check if relocation against this symbol is a candidate for
// conversion from
// mov foo@GOTPCREL(%rip), %reg
@ -3191,15 +3197,16 @@ Target_x86_64<size>::gc_process_relocs(Symbol_table* symtab,
size_t local_symbol_count,
const unsigned char* plocal_symbols)
{
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, false>
Classify_reloc;
if (sh_type == elfcpp::SHT_REL)
{
return;
}
gold::gc_process_relocs<size, false, Target_x86_64<size>, elfcpp::SHT_RELA,
typename Target_x86_64<size>::Scan,
typename Target_x86_64<size>::Relocatable_size_for_reloc>(
gold::gc_process_relocs<size, false, Target_x86_64<size>, Scan,
Classify_reloc>(
symtab,
layout,
this,
@ -3229,6 +3236,9 @@ Target_x86_64<size>::scan_relocs(Symbol_table* symtab,
size_t local_symbol_count,
const unsigned char* plocal_symbols)
{
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, false>
Classify_reloc;
if (sh_type == elfcpp::SHT_REL)
{
gold_error(_("%s: unsupported REL reloc section"),
@ -3236,8 +3246,7 @@ Target_x86_64<size>::scan_relocs(Symbol_table* symtab,
return;
}
gold::scan_relocs<size, false, Target_x86_64<size>, elfcpp::SHT_RELA,
typename Target_x86_64<size>::Scan>(
gold::scan_relocs<size, false, Target_x86_64<size>, Scan, Classify_reloc>(
symtab,
layout,
this,
@ -4268,11 +4277,13 @@ Target_x86_64<size>::relocate_section(
section_size_type view_size,
const Reloc_symbol_changes* reloc_symbol_changes)
{
typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, false>
Classify_reloc;
gold_assert(sh_type == elfcpp::SHT_RELA);
gold::relocate_section<size, false, Target_x86_64<size>, elfcpp::SHT_RELA,
typename Target_x86_64<size>::Relocate,
gold::Default_comdat_behavior>(
gold::relocate_section<size, false, Target_x86_64<size>, Relocate,
gold::Default_comdat_behavior, Classify_reloc>(
relinfo,
this,
prelocs,
@ -4313,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,