mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
gold/
* symtab.h (Symbol::NON_PIC_REF): Remove. (Symbol::RELATIVE_REF, Symbol::TLS_REF): New Reference_flags. (Symbol::FUNCTION_CALL): Renumber. Reword comment. (Symbol::needs_dynamic_reloc): Don't check NON_PIC_REF. (Symbol::use_plt_offset): Take a flags argument and pass it directly to needs_dynamic_reloc. Restrict check for undefined weak symbols to function calls. * arm.cc (Target_arm::Scan::get_reference_flags): New function. (Target_arm::Scan::global): Use it. (Target_arm::Scan::scan_reloc_for_stub): Likewise. (Target_arm::Relocate::relocate): Likewise. (Target_arm::Relocate::should_apply_static_reloc): Replace flags parameter with an r_type parameter. Use get_reference_flags to get the flags. (Target_arm::Relocate::relocate): Update accordingly. * i386.cc (Target_i386::Scan::get_reference_flags): New function. (Target_i386::Scan::reloc_needs_plt_for_ifunc): Use it. (Target_i386::Scan::global): Likewise. (Target_i386::Relocate::relocate): Likewise. (Target_i386::Relocate::should_apply_static_reloc): Replace flags parameter with an r_type parameter. Use get_reference_flags to get the flags. (Target_i386::Relocate::relocate): Update accordingly. * powerpc.cc (Target_powerpc::Scan::get_reference_flags): New function. (Target_powerpc::Scan::global): Use it. (Target_powerpc::Scan::scan_reloc_for_stub): Likewise. (Target_powerpc::Relocate::relocate): Likewise. * sparc.cc (Target_sparc::Scan::get_reference_flags): New function. (Target_sparc::Scan::global): Use it. (Target_sparc::Scan::scan_reloc_for_stub): Likewise. (Target_sparc::Relocate::relocate): Likewise. * x86_64.cc (Target_x86_64::Scan::get_reference_flags): New function. (Target_x86_64::Scan::reloc_needs_plt_for_ifunc): Use it. (Target_x86_64::Scan::global): Likewise. (Target_x86_64::Relocate::relocate): Likewise.
This commit is contained in:
parent
fd50354116
commit
95a2c8d6f7
@ -1,3 +1,41 @@
|
||||
2010-11-11 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
|
||||
* symtab.h (Symbol::NON_PIC_REF): Remove.
|
||||
(Symbol::RELATIVE_REF, Symbol::TLS_REF): New Reference_flags.
|
||||
(Symbol::FUNCTION_CALL): Renumber. Reword comment.
|
||||
(Symbol::needs_dynamic_reloc): Don't check NON_PIC_REF.
|
||||
(Symbol::use_plt_offset): Take a flags argument and pass it
|
||||
directly to needs_dynamic_reloc. Restrict check for undefined
|
||||
weak symbols to function calls.
|
||||
* arm.cc (Target_arm::Scan::get_reference_flags): New function.
|
||||
(Target_arm::Scan::global): Use it.
|
||||
(Target_arm::Scan::scan_reloc_for_stub): Likewise.
|
||||
(Target_arm::Relocate::relocate): Likewise.
|
||||
(Target_arm::Relocate::should_apply_static_reloc): Replace flags
|
||||
parameter with an r_type parameter. Use get_reference_flags
|
||||
to get the flags.
|
||||
(Target_arm::Relocate::relocate): Update accordingly.
|
||||
* i386.cc (Target_i386::Scan::get_reference_flags): New function.
|
||||
(Target_i386::Scan::reloc_needs_plt_for_ifunc): Use it.
|
||||
(Target_i386::Scan::global): Likewise.
|
||||
(Target_i386::Relocate::relocate): Likewise.
|
||||
(Target_i386::Relocate::should_apply_static_reloc): Replace flags
|
||||
parameter with an r_type parameter. Use get_reference_flags
|
||||
to get the flags.
|
||||
(Target_i386::Relocate::relocate): Update accordingly.
|
||||
* powerpc.cc (Target_powerpc::Scan::get_reference_flags): New function.
|
||||
(Target_powerpc::Scan::global): Use it.
|
||||
(Target_powerpc::Scan::scan_reloc_for_stub): Likewise.
|
||||
(Target_powerpc::Relocate::relocate): Likewise.
|
||||
* sparc.cc (Target_sparc::Scan::get_reference_flags): New function.
|
||||
(Target_sparc::Scan::global): Use it.
|
||||
(Target_sparc::Scan::scan_reloc_for_stub): Likewise.
|
||||
(Target_sparc::Relocate::relocate): Likewise.
|
||||
* x86_64.cc (Target_x86_64::Scan::get_reference_flags): New function.
|
||||
(Target_x86_64::Scan::reloc_needs_plt_for_ifunc): Use it.
|
||||
(Target_x86_64::Scan::global): Likewise.
|
||||
(Target_x86_64::Relocate::relocate): Likewise.
|
||||
|
||||
2010-11-08 Doug Kwan <dougkwan@google.com>
|
||||
Cary Coutant <ccoutant@google.com>
|
||||
|
||||
|
174
gold/arm.cc
174
gold/arm.cc
@ -2556,6 +2556,9 @@ class Target_arm : public Sized_target<32, big_endian>
|
||||
: issued_non_pic_error_(false)
|
||||
{ }
|
||||
|
||||
static inline int
|
||||
get_reference_flags(unsigned int r_type);
|
||||
|
||||
inline void
|
||||
local(Symbol_table* symtab, Layout* layout, Target_arm* target,
|
||||
Sized_relobj<32, big_endian>* object,
|
||||
@ -2638,7 +2641,7 @@ class Target_arm : public Sized_target<32, big_endian>
|
||||
// Return whether the static relocation needs to be applied.
|
||||
inline bool
|
||||
should_apply_static_reloc(const Sized_symbol<32>* gsym,
|
||||
int ref_flags,
|
||||
unsigned int r_type,
|
||||
bool is_32bit,
|
||||
Output_section* output_section);
|
||||
|
||||
@ -7568,6 +7571,125 @@ Target_arm<big_endian>::optimize_tls_reloc(bool, int)
|
||||
return tls::TLSOPT_NONE;
|
||||
}
|
||||
|
||||
// Get the Reference_flags for a particular relocation.
|
||||
|
||||
template<bool big_endian>
|
||||
int
|
||||
Target_arm<big_endian>::Scan::get_reference_flags(unsigned int r_type)
|
||||
{
|
||||
switch (r_type)
|
||||
{
|
||||
case elfcpp::R_ARM_NONE:
|
||||
case elfcpp::R_ARM_V4BX:
|
||||
case elfcpp::R_ARM_GNU_VTENTRY:
|
||||
case elfcpp::R_ARM_GNU_VTINHERIT:
|
||||
// No symbol reference.
|
||||
return 0;
|
||||
|
||||
case elfcpp::R_ARM_ABS32:
|
||||
case elfcpp::R_ARM_ABS16:
|
||||
case elfcpp::R_ARM_ABS12:
|
||||
case elfcpp::R_ARM_THM_ABS5:
|
||||
case elfcpp::R_ARM_ABS8:
|
||||
case elfcpp::R_ARM_BASE_ABS:
|
||||
case elfcpp::R_ARM_MOVW_ABS_NC:
|
||||
case elfcpp::R_ARM_MOVT_ABS:
|
||||
case elfcpp::R_ARM_THM_MOVW_ABS_NC:
|
||||
case elfcpp::R_ARM_THM_MOVT_ABS:
|
||||
case elfcpp::R_ARM_ABS32_NOI:
|
||||
return Symbol::ABSOLUTE_REF;
|
||||
|
||||
case elfcpp::R_ARM_REL32:
|
||||
case elfcpp::R_ARM_LDR_PC_G0:
|
||||
case elfcpp::R_ARM_SBREL32:
|
||||
case elfcpp::R_ARM_THM_PC8:
|
||||
case elfcpp::R_ARM_BASE_PREL:
|
||||
case elfcpp::R_ARM_MOVW_PREL_NC:
|
||||
case elfcpp::R_ARM_MOVT_PREL:
|
||||
case elfcpp::R_ARM_THM_MOVW_PREL_NC:
|
||||
case elfcpp::R_ARM_THM_MOVT_PREL:
|
||||
case elfcpp::R_ARM_THM_ALU_PREL_11_0:
|
||||
case elfcpp::R_ARM_THM_PC12:
|
||||
case elfcpp::R_ARM_REL32_NOI:
|
||||
case elfcpp::R_ARM_ALU_PC_G0_NC:
|
||||
case elfcpp::R_ARM_ALU_PC_G0:
|
||||
case elfcpp::R_ARM_ALU_PC_G1_NC:
|
||||
case elfcpp::R_ARM_ALU_PC_G1:
|
||||
case elfcpp::R_ARM_ALU_PC_G2:
|
||||
case elfcpp::R_ARM_LDR_PC_G1:
|
||||
case elfcpp::R_ARM_LDR_PC_G2:
|
||||
case elfcpp::R_ARM_LDRS_PC_G0:
|
||||
case elfcpp::R_ARM_LDRS_PC_G1:
|
||||
case elfcpp::R_ARM_LDRS_PC_G2:
|
||||
case elfcpp::R_ARM_LDC_PC_G0:
|
||||
case elfcpp::R_ARM_LDC_PC_G1:
|
||||
case elfcpp::R_ARM_LDC_PC_G2:
|
||||
case elfcpp::R_ARM_ALU_SB_G0_NC:
|
||||
case elfcpp::R_ARM_ALU_SB_G0:
|
||||
case elfcpp::R_ARM_ALU_SB_G1_NC:
|
||||
case elfcpp::R_ARM_ALU_SB_G1:
|
||||
case elfcpp::R_ARM_ALU_SB_G2:
|
||||
case elfcpp::R_ARM_LDR_SB_G0:
|
||||
case elfcpp::R_ARM_LDR_SB_G1:
|
||||
case elfcpp::R_ARM_LDR_SB_G2:
|
||||
case elfcpp::R_ARM_LDRS_SB_G0:
|
||||
case elfcpp::R_ARM_LDRS_SB_G1:
|
||||
case elfcpp::R_ARM_LDRS_SB_G2:
|
||||
case elfcpp::R_ARM_LDC_SB_G0:
|
||||
case elfcpp::R_ARM_LDC_SB_G1:
|
||||
case elfcpp::R_ARM_LDC_SB_G2:
|
||||
case elfcpp::R_ARM_MOVW_BREL_NC:
|
||||
case elfcpp::R_ARM_MOVT_BREL:
|
||||
case elfcpp::R_ARM_MOVW_BREL:
|
||||
case elfcpp::R_ARM_THM_MOVW_BREL_NC:
|
||||
case elfcpp::R_ARM_THM_MOVT_BREL:
|
||||
case elfcpp::R_ARM_THM_MOVW_BREL:
|
||||
case elfcpp::R_ARM_GOTOFF32:
|
||||
case elfcpp::R_ARM_GOTOFF12:
|
||||
case elfcpp::R_ARM_PREL31:
|
||||
case elfcpp::R_ARM_SBREL31:
|
||||
return Symbol::RELATIVE_REF;
|
||||
|
||||
case elfcpp::R_ARM_PLT32:
|
||||
case elfcpp::R_ARM_CALL:
|
||||
case elfcpp::R_ARM_JUMP24:
|
||||
case elfcpp::R_ARM_THM_CALL:
|
||||
case elfcpp::R_ARM_THM_JUMP24:
|
||||
case elfcpp::R_ARM_THM_JUMP19:
|
||||
case elfcpp::R_ARM_THM_JUMP6:
|
||||
case elfcpp::R_ARM_THM_JUMP11:
|
||||
case elfcpp::R_ARM_THM_JUMP8:
|
||||
return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
|
||||
|
||||
case elfcpp::R_ARM_GOT_BREL:
|
||||
case elfcpp::R_ARM_GOT_ABS:
|
||||
case elfcpp::R_ARM_GOT_PREL:
|
||||
// Absolute in GOT.
|
||||
return Symbol::ABSOLUTE_REF;
|
||||
|
||||
case elfcpp::R_ARM_TLS_GD32: // Global-dynamic
|
||||
case elfcpp::R_ARM_TLS_LDM32: // Local-dynamic
|
||||
case elfcpp::R_ARM_TLS_LDO32: // Alternate local-dynamic
|
||||
case elfcpp::R_ARM_TLS_IE32: // Initial-exec
|
||||
case elfcpp::R_ARM_TLS_LE32: // Local-exec
|
||||
return Symbol::TLS_REF;
|
||||
|
||||
case elfcpp::R_ARM_TARGET1:
|
||||
case elfcpp::R_ARM_TARGET2:
|
||||
case elfcpp::R_ARM_COPY:
|
||||
case elfcpp::R_ARM_GLOB_DAT:
|
||||
case elfcpp::R_ARM_JUMP_SLOT:
|
||||
case elfcpp::R_ARM_RELATIVE:
|
||||
case elfcpp::R_ARM_PC24:
|
||||
case elfcpp::R_ARM_LDR_SBREL_11_0_NC:
|
||||
case elfcpp::R_ARM_ALU_SBREL_19_12_NC:
|
||||
case elfcpp::R_ARM_ALU_SBREL_27_20_CK:
|
||||
default:
|
||||
// Not expected. We will give an error later.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Report an unsupported relocation against a local symbol.
|
||||
|
||||
template<bool big_endian>
|
||||
@ -8074,7 +8196,7 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
|
||||
gsym->set_needs_dynsym_value();
|
||||
}
|
||||
// Make a dynamic relocation if necessary.
|
||||
if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF))
|
||||
if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
if (gsym->may_need_copy_reloc())
|
||||
{
|
||||
@ -8155,8 +8277,7 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
|
||||
// Relative addressing relocations.
|
||||
{
|
||||
// Make a dynamic relocation if necessary.
|
||||
int flags = Symbol::NON_PIC_REF;
|
||||
if (gsym->needs_dynamic_reloc(flags))
|
||||
if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
if (target->may_need_copy_reloc(gsym))
|
||||
{
|
||||
@ -8596,7 +8717,7 @@ template<bool big_endian>
|
||||
inline bool
|
||||
Target_arm<big_endian>::Relocate::should_apply_static_reloc(
|
||||
const Sized_symbol<32>* gsym,
|
||||
int ref_flags,
|
||||
unsigned int r_type,
|
||||
bool is_32bit,
|
||||
Output_section* output_section)
|
||||
{
|
||||
@ -8606,6 +8727,8 @@ Target_arm<big_endian>::Relocate::should_apply_static_reloc(
|
||||
if ((output_section->flags() & elfcpp::SHF_ALLOC) == 0)
|
||||
return true;
|
||||
|
||||
int ref_flags = Scan::get_reference_flags(r_type);
|
||||
|
||||
// For local symbols, we will have created a non-RELATIVE dynamic
|
||||
// relocation only if (a) the output is position independent,
|
||||
// (b) the relocation is absolute (not pc- or segment-relative), and
|
||||
@ -8711,7 +8834,7 @@ Target_arm<big_endian>::Relocate::relocate(
|
||||
{
|
||||
// This is a global symbol. Determine if we use PLT and if the
|
||||
// final target is THUMB.
|
||||
if (gsym->use_plt_offset(reloc_is_non_pic(r_type)))
|
||||
if (gsym->use_plt_offset(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
// This uses a PLT, change the symbol value.
|
||||
symval.set_output_value(target->plt_section()->address()
|
||||
@ -8835,62 +8958,53 @@ Target_arm<big_endian>::Relocate::relocate(
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_ABS8:
|
||||
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
|
||||
output_section))
|
||||
if (should_apply_static_reloc(gsym, r_type, false, output_section))
|
||||
reloc_status = Arm_relocate_functions::abs8(view, object, psymval);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_ABS12:
|
||||
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
|
||||
output_section))
|
||||
if (should_apply_static_reloc(gsym, r_type, false, output_section))
|
||||
reloc_status = Arm_relocate_functions::abs12(view, object, psymval);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_ABS16:
|
||||
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
|
||||
output_section))
|
||||
if (should_apply_static_reloc(gsym, r_type, false, output_section))
|
||||
reloc_status = Arm_relocate_functions::abs16(view, object, psymval);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_ABS32:
|
||||
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true,
|
||||
output_section))
|
||||
if (should_apply_static_reloc(gsym, r_type, true, output_section))
|
||||
reloc_status = Arm_relocate_functions::abs32(view, object, psymval,
|
||||
thumb_bit);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_ABS32_NOI:
|
||||
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true,
|
||||
output_section))
|
||||
if (should_apply_static_reloc(gsym, r_type, true, output_section))
|
||||
// No thumb bit for this relocation: (S + A)
|
||||
reloc_status = Arm_relocate_functions::abs32(view, object, psymval,
|
||||
0);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_MOVW_ABS_NC:
|
||||
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
|
||||
output_section))
|
||||
if (should_apply_static_reloc(gsym, r_type, false, output_section))
|
||||
reloc_status = Arm_relocate_functions::movw(view, object, psymval,
|
||||
0, thumb_bit,
|
||||
check_overflow);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_MOVT_ABS:
|
||||
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
|
||||
output_section))
|
||||
if (should_apply_static_reloc(gsym, r_type, false, output_section))
|
||||
reloc_status = Arm_relocate_functions::movt(view, object, psymval, 0);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_THM_MOVW_ABS_NC:
|
||||
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
|
||||
output_section))
|
||||
if (should_apply_static_reloc(gsym, r_type, false, output_section))
|
||||
reloc_status = Arm_relocate_functions::thm_movw(view, object, psymval,
|
||||
0, thumb_bit, false);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_THM_MOVT_ABS:
|
||||
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
|
||||
output_section))
|
||||
if (should_apply_static_reloc(gsym, r_type, false, output_section))
|
||||
reloc_status = Arm_relocate_functions::thm_movt(view, object,
|
||||
psymval, 0);
|
||||
break;
|
||||
@ -8933,8 +9047,7 @@ Target_arm<big_endian>::Relocate::relocate(
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_THM_ABS5:
|
||||
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
|
||||
output_section))
|
||||
if (should_apply_static_reloc(gsym, r_type, false, output_section))
|
||||
reloc_status = Arm_relocate_functions::thm_abs5(view, object, psymval);
|
||||
break;
|
||||
|
||||
@ -8964,13 +9077,8 @@ Target_arm<big_endian>::Relocate::relocate(
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_BASE_ABS:
|
||||
{
|
||||
if (!should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
|
||||
output_section))
|
||||
break;
|
||||
|
||||
if (should_apply_static_reloc(gsym, r_type, false, output_section))
|
||||
reloc_status = Arm_relocate_functions::base_abs(view, sym_origin);
|
||||
}
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_GOT_BREL:
|
||||
@ -10824,7 +10932,7 @@ Target_arm<big_endian>::scan_reloc_for_stub(
|
||||
{
|
||||
// This is a global symbol. Determine if we use PLT and if the
|
||||
// final target is THUMB.
|
||||
if (gsym->use_plt_offset(Relocate::reloc_is_non_pic(r_type)))
|
||||
if (gsym->use_plt_offset(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
// This uses a PLT, change the symbol value.
|
||||
symval.set_output_value(this->plt_section()->address()
|
||||
|
195
gold/i386.cc
195
gold/i386.cc
@ -335,6 +335,10 @@ class Target_i386 : public Target_freebsd<32, false>
|
||||
// The class which scans relocations.
|
||||
struct Scan
|
||||
{
|
||||
static inline int
|
||||
|
||||
get_reference_flags(unsigned int r_type);
|
||||
|
||||
inline void
|
||||
local(Symbol_table* symtab, Layout* layout, Target_i386* target,
|
||||
Sized_relobj<32, false>* object,
|
||||
@ -406,7 +410,7 @@ class Target_i386 : public Target_freebsd<32, false>
|
||||
// Return whether the static relocation needs to be applied.
|
||||
inline bool
|
||||
should_apply_static_reloc(const Sized_symbol<32>* gsym,
|
||||
int ref_flags,
|
||||
unsigned int r_type,
|
||||
bool is_32bit,
|
||||
Output_section* output_section);
|
||||
|
||||
@ -1191,6 +1195,76 @@ Target_i386::optimize_tls_reloc(bool is_final, int r_type)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the Reference_flags for a particular relocation.
|
||||
|
||||
int
|
||||
Target_i386::Scan::get_reference_flags(unsigned int r_type)
|
||||
{
|
||||
switch (r_type)
|
||||
{
|
||||
case elfcpp::R_386_NONE:
|
||||
case elfcpp::R_386_GNU_VTINHERIT:
|
||||
case elfcpp::R_386_GNU_VTENTRY:
|
||||
case elfcpp::R_386_GOTPC:
|
||||
// No symbol reference.
|
||||
return 0;
|
||||
|
||||
case elfcpp::R_386_32:
|
||||
case elfcpp::R_386_16:
|
||||
case elfcpp::R_386_8:
|
||||
return Symbol::ABSOLUTE_REF;
|
||||
|
||||
case elfcpp::R_386_PC32:
|
||||
case elfcpp::R_386_PC16:
|
||||
case elfcpp::R_386_PC8:
|
||||
case elfcpp::R_386_GOTOFF:
|
||||
return Symbol::RELATIVE_REF;
|
||||
|
||||
case elfcpp::R_386_PLT32:
|
||||
return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
|
||||
|
||||
case elfcpp::R_386_GOT32:
|
||||
// Absolute in GOT.
|
||||
return Symbol::ABSOLUTE_REF;
|
||||
|
||||
case elfcpp::R_386_TLS_GD: // Global-dynamic
|
||||
case elfcpp::R_386_TLS_GOTDESC: // Global-dynamic (from ~oliva url)
|
||||
case elfcpp::R_386_TLS_DESC_CALL:
|
||||
case elfcpp::R_386_TLS_LDM: // Local-dynamic
|
||||
case elfcpp::R_386_TLS_LDO_32: // Alternate local-dynamic
|
||||
case elfcpp::R_386_TLS_IE: // Initial-exec
|
||||
case elfcpp::R_386_TLS_IE_32:
|
||||
case elfcpp::R_386_TLS_GOTIE:
|
||||
case elfcpp::R_386_TLS_LE: // Local-exec
|
||||
case elfcpp::R_386_TLS_LE_32:
|
||||
return Symbol::TLS_REF;
|
||||
|
||||
case elfcpp::R_386_COPY:
|
||||
case elfcpp::R_386_GLOB_DAT:
|
||||
case elfcpp::R_386_JUMP_SLOT:
|
||||
case elfcpp::R_386_RELATIVE:
|
||||
case elfcpp::R_386_IRELATIVE:
|
||||
case elfcpp::R_386_TLS_TPOFF:
|
||||
case elfcpp::R_386_TLS_DTPMOD32:
|
||||
case elfcpp::R_386_TLS_DTPOFF32:
|
||||
case elfcpp::R_386_TLS_TPOFF32:
|
||||
case elfcpp::R_386_TLS_DESC:
|
||||
case elfcpp::R_386_32PLT:
|
||||
case elfcpp::R_386_TLS_GD_32:
|
||||
case elfcpp::R_386_TLS_GD_PUSH:
|
||||
case elfcpp::R_386_TLS_GD_CALL:
|
||||
case elfcpp::R_386_TLS_GD_POP:
|
||||
case elfcpp::R_386_TLS_LDM_32:
|
||||
case elfcpp::R_386_TLS_LDM_PUSH:
|
||||
case elfcpp::R_386_TLS_LDM_CALL:
|
||||
case elfcpp::R_386_TLS_LDM_POP:
|
||||
case elfcpp::R_386_USED_BY_INTEL_200:
|
||||
default:
|
||||
// Not expected. We will give an error later.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Report an unsupported relocation against a local symbol.
|
||||
|
||||
void
|
||||
@ -1208,66 +1282,11 @@ bool
|
||||
Target_i386::Scan::reloc_needs_plt_for_ifunc(Sized_relobj<32, false>* object,
|
||||
unsigned int r_type)
|
||||
{
|
||||
switch (r_type)
|
||||
{
|
||||
case elfcpp::R_386_NONE:
|
||||
case elfcpp::R_386_GNU_VTINHERIT:
|
||||
case elfcpp::R_386_GNU_VTENTRY:
|
||||
return false;
|
||||
|
||||
case elfcpp::R_386_32:
|
||||
case elfcpp::R_386_16:
|
||||
case elfcpp::R_386_8:
|
||||
case elfcpp::R_386_PC32:
|
||||
case elfcpp::R_386_PC16:
|
||||
case elfcpp::R_386_PC8:
|
||||
case elfcpp::R_386_PLT32:
|
||||
case elfcpp::R_386_GOTOFF:
|
||||
case elfcpp::R_386_GOTPC:
|
||||
case elfcpp::R_386_GOT32:
|
||||
return true;
|
||||
|
||||
case elfcpp::R_386_COPY:
|
||||
case elfcpp::R_386_GLOB_DAT:
|
||||
case elfcpp::R_386_JUMP_SLOT:
|
||||
case elfcpp::R_386_RELATIVE:
|
||||
case elfcpp::R_386_IRELATIVE:
|
||||
case elfcpp::R_386_TLS_TPOFF:
|
||||
case elfcpp::R_386_TLS_DTPMOD32:
|
||||
case elfcpp::R_386_TLS_DTPOFF32:
|
||||
case elfcpp::R_386_TLS_TPOFF32:
|
||||
case elfcpp::R_386_TLS_DESC:
|
||||
// We will give an error later.
|
||||
return false;
|
||||
|
||||
case elfcpp::R_386_TLS_GD:
|
||||
case elfcpp::R_386_TLS_GOTDESC:
|
||||
case elfcpp::R_386_TLS_DESC_CALL:
|
||||
case elfcpp::R_386_TLS_LDM:
|
||||
case elfcpp::R_386_TLS_LDO_32:
|
||||
case elfcpp::R_386_TLS_IE:
|
||||
case elfcpp::R_386_TLS_IE_32:
|
||||
case elfcpp::R_386_TLS_GOTIE:
|
||||
case elfcpp::R_386_TLS_LE:
|
||||
case elfcpp::R_386_TLS_LE_32:
|
||||
gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
|
||||
object->name().c_str(), r_type);
|
||||
return false;
|
||||
|
||||
case elfcpp::R_386_32PLT:
|
||||
case elfcpp::R_386_TLS_GD_32:
|
||||
case elfcpp::R_386_TLS_GD_PUSH:
|
||||
case elfcpp::R_386_TLS_GD_CALL:
|
||||
case elfcpp::R_386_TLS_GD_POP:
|
||||
case elfcpp::R_386_TLS_LDM_32:
|
||||
case elfcpp::R_386_TLS_LDM_PUSH:
|
||||
case elfcpp::R_386_TLS_LDM_CALL:
|
||||
case elfcpp::R_386_TLS_LDM_POP:
|
||||
case elfcpp::R_386_USED_BY_INTEL_200:
|
||||
default:
|
||||
// We will give an error later.
|
||||
return false;
|
||||
}
|
||||
int flags = Scan::get_reference_flags(r_type);
|
||||
if (flags & Symbol::TLS_REF)
|
||||
gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
|
||||
object->name().c_str(), r_type);
|
||||
return flags != 0;
|
||||
}
|
||||
|
||||
// Scan a relocation for a local symbol.
|
||||
@ -1676,7 +1695,7 @@ Target_i386::Scan::global(Symbol_table* symtab,
|
||||
gsym->set_needs_dynsym_value();
|
||||
}
|
||||
// Make a dynamic relocation if necessary.
|
||||
if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF))
|
||||
if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
if (gsym->may_need_copy_reloc())
|
||||
{
|
||||
@ -1737,10 +1756,7 @@ Target_i386::Scan::global(Symbol_table* symtab,
|
||||
target->make_plt_entry(symtab, layout, gsym);
|
||||
}
|
||||
// Make a dynamic relocation if necessary.
|
||||
int flags = Symbol::NON_PIC_REF;
|
||||
if (gsym->is_func())
|
||||
flags |= Symbol::FUNCTION_CALL;
|
||||
if (gsym->needs_dynamic_reloc(flags))
|
||||
if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
if (gsym->may_need_copy_reloc())
|
||||
{
|
||||
@ -2109,7 +2125,7 @@ Target_i386::do_finalize_sections(
|
||||
|
||||
inline bool
|
||||
Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym,
|
||||
int ref_flags,
|
||||
unsigned int r_type,
|
||||
bool is_32bit,
|
||||
Output_section* output_section)
|
||||
{
|
||||
@ -2119,6 +2135,8 @@ Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym,
|
||||
if ((output_section->flags() & elfcpp::SHF_ALLOC) == 0)
|
||||
return true;
|
||||
|
||||
int ref_flags = Scan::get_reference_flags(r_type);
|
||||
|
||||
// For local symbols, we will have created a non-RELATIVE dynamic
|
||||
// relocation only if (a) the output is position independent,
|
||||
// (b) the relocation is absolute (not pc- or segment-relative), and
|
||||
@ -2176,7 +2194,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
|
||||
if (gsym != NULL
|
||||
&& gsym->type() == elfcpp::STT_GNU_IFUNC
|
||||
&& r_type == elfcpp::R_386_32
|
||||
&& gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF)
|
||||
&& gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type))
|
||||
&& gsym->can_use_relative_reloc(false)
|
||||
&& !gsym->is_from_dynobj()
|
||||
&& !gsym->is_undefined()
|
||||
@ -2186,9 +2204,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
|
||||
// want to use the real value of the symbol, not the PLT offset.
|
||||
}
|
||||
else if (gsym != NULL
|
||||
&& gsym->use_plt_offset(r_type == elfcpp::R_386_PC8
|
||||
|| r_type == elfcpp::R_386_PC16
|
||||
|| r_type == elfcpp::R_386_PC32))
|
||||
&& gsym->use_plt_offset(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
symval.set_output_value(target->plt_section()->address()
|
||||
+ gsym->plt_offset());
|
||||
@ -2242,52 +2258,33 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
|
||||
break;
|
||||
|
||||
case elfcpp::R_386_32:
|
||||
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true,
|
||||
output_section))
|
||||
if (should_apply_static_reloc(gsym, r_type, true, output_section))
|
||||
Relocate_functions<32, false>::rel32(view, object, psymval);
|
||||
break;
|
||||
|
||||
case elfcpp::R_386_PC32:
|
||||
{
|
||||
int ref_flags = Symbol::NON_PIC_REF;
|
||||
if (gsym != NULL && gsym->is_func())
|
||||
ref_flags |= Symbol::FUNCTION_CALL;
|
||||
if (should_apply_static_reloc(gsym, ref_flags, true, output_section))
|
||||
Relocate_functions<32, false>::pcrel32(view, object, psymval, address);
|
||||
}
|
||||
if (should_apply_static_reloc(gsym, r_type, true, output_section))
|
||||
Relocate_functions<32, false>::pcrel32(view, object, psymval, address);
|
||||
break;
|
||||
|
||||
case elfcpp::R_386_16:
|
||||
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
|
||||
output_section))
|
||||
if (should_apply_static_reloc(gsym, r_type, false, output_section))
|
||||
Relocate_functions<32, false>::rel16(view, object, psymval);
|
||||
break;
|
||||
|
||||
case elfcpp::R_386_PC16:
|
||||
{
|
||||
int ref_flags = Symbol::NON_PIC_REF;
|
||||
if (gsym != NULL && gsym->is_func())
|
||||
ref_flags |= Symbol::FUNCTION_CALL;
|
||||
if (should_apply_static_reloc(gsym, ref_flags, false, output_section))
|
||||
Relocate_functions<32, false>::pcrel16(view, object, psymval, address);
|
||||
}
|
||||
if (should_apply_static_reloc(gsym, r_type, false, output_section))
|
||||
Relocate_functions<32, false>::pcrel16(view, object, psymval, address);
|
||||
break;
|
||||
|
||||
case elfcpp::R_386_8:
|
||||
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
|
||||
output_section))
|
||||
if (should_apply_static_reloc(gsym, r_type, false, output_section))
|
||||
Relocate_functions<32, false>::rel8(view, object, psymval);
|
||||
break;
|
||||
|
||||
case elfcpp::R_386_PC8:
|
||||
{
|
||||
int ref_flags = Symbol::NON_PIC_REF;
|
||||
if (gsym != NULL && gsym->is_func())
|
||||
ref_flags |= Symbol::FUNCTION_CALL;
|
||||
if (should_apply_static_reloc(gsym, ref_flags, false,
|
||||
output_section))
|
||||
Relocate_functions<32, false>::pcrel8(view, object, psymval, address);
|
||||
}
|
||||
if (should_apply_static_reloc(gsym, r_type, false, output_section))
|
||||
Relocate_functions<32, false>::pcrel8(view, object, psymval, address);
|
||||
break;
|
||||
|
||||
case elfcpp::R_386_PLT32:
|
||||
|
@ -188,6 +188,9 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
||||
: issued_non_pic_error_(false)
|
||||
{ }
|
||||
|
||||
static inline int
|
||||
get_reference_flags(unsigned int r_type);
|
||||
|
||||
inline void
|
||||
local(Symbol_table* symtab, Layout* layout, Target_powerpc* target,
|
||||
Sized_relobj<size, big_endian>* object,
|
||||
@ -1105,6 +1108,69 @@ optimize_tls_reloc(bool /* is_final */, int r_type)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the Reference_flags for a particular relocation.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
int
|
||||
Target_powerpc<size, big_endian>::Scan::get_reference_flags(
|
||||
unsigned int r_type)
|
||||
{
|
||||
switch (r_type)
|
||||
{
|
||||
case elfcpp::R_POWERPC_NONE:
|
||||
case elfcpp::R_POWERPC_GNU_VTINHERIT:
|
||||
case elfcpp::R_POWERPC_GNU_VTENTRY:
|
||||
case elfcpp::R_PPC64_TOC:
|
||||
// No symbol reference.
|
||||
return 0;
|
||||
|
||||
case elfcpp::R_POWERPC_ADDR16:
|
||||
case elfcpp::R_POWERPC_ADDR16_LO:
|
||||
case elfcpp::R_POWERPC_ADDR16_HI:
|
||||
case elfcpp::R_POWERPC_ADDR16_HA:
|
||||
case elfcpp::R_POWERPC_ADDR32:
|
||||
case elfcpp::R_PPC64_ADDR64:
|
||||
return Symbol::ABSOLUTE_REF;
|
||||
|
||||
case elfcpp::R_POWERPC_REL24:
|
||||
case elfcpp::R_PPC_LOCAL24PC:
|
||||
case elfcpp::R_PPC_REL16:
|
||||
case elfcpp::R_PPC_REL16_LO:
|
||||
case elfcpp::R_PPC_REL16_HI:
|
||||
case elfcpp::R_PPC_REL16_HA:
|
||||
return Symbol::RELATIVE_REF;
|
||||
|
||||
case elfcpp::R_PPC_PLTREL24:
|
||||
return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
|
||||
|
||||
case elfcpp::R_POWERPC_GOT16:
|
||||
case elfcpp::R_POWERPC_GOT16_LO:
|
||||
case elfcpp::R_POWERPC_GOT16_HI:
|
||||
case elfcpp::R_POWERPC_GOT16_HA:
|
||||
case elfcpp::R_PPC64_TOC16:
|
||||
case elfcpp::R_PPC64_TOC16_LO:
|
||||
case elfcpp::R_PPC64_TOC16_HI:
|
||||
case elfcpp::R_PPC64_TOC16_HA:
|
||||
case elfcpp::R_PPC64_TOC16_DS:
|
||||
case elfcpp::R_PPC64_TOC16_LO_DS:
|
||||
// Absolute in GOT.
|
||||
return Symbol::ABSOLUTE_REF;
|
||||
|
||||
case elfcpp::R_POWERPC_GOT_TPREL16:
|
||||
case elfcpp::R_POWERPC_TLS:
|
||||
return Symbol::TLS_REF;
|
||||
|
||||
case elfcpp::R_POWERPC_COPY:
|
||||
case elfcpp::R_POWERPC_GLOB_DAT:
|
||||
case elfcpp::R_POWERPC_JMP_SLOT:
|
||||
case elfcpp::R_POWERPC_RELATIVE:
|
||||
case elfcpp::R_POWERPC_DTPMOD:
|
||||
default:
|
||||
// Not expected. We will give an error later.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Report an unsupported relocation against a local symbol.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
@ -1400,7 +1466,7 @@ Target_powerpc<size, big_endian>::Scan::global(
|
||||
gsym->set_needs_dynsym_value();
|
||||
}
|
||||
// Make a dynamic relocation if necessary.
|
||||
if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF))
|
||||
if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
if (gsym->may_need_copy_reloc())
|
||||
{
|
||||
@ -1450,10 +1516,7 @@ Target_powerpc<size, big_endian>::Scan::global(
|
||||
if (gsym->needs_plt_entry())
|
||||
target->make_plt_entry(symtab, layout, gsym);
|
||||
// Make a dynamic relocation if necessary.
|
||||
int flags = Symbol::NON_PIC_REF;
|
||||
if (gsym->type() == elfcpp::STT_FUNC)
|
||||
flags |= Symbol::FUNCTION_CALL;
|
||||
if (gsym->needs_dynamic_reloc(flags))
|
||||
if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
if (gsym->may_need_copy_reloc())
|
||||
{
|
||||
@ -1682,12 +1745,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
||||
// Pick the value to use for symbols defined in shared objects.
|
||||
Symbol_value<size> symval;
|
||||
if (gsym != NULL
|
||||
&& gsym->use_plt_offset(r_type == elfcpp::R_POWERPC_REL24
|
||||
|| r_type == elfcpp::R_PPC_LOCAL24PC
|
||||
|| r_type == elfcpp::R_PPC_REL16
|
||||
|| r_type == elfcpp::R_PPC_REL16_LO
|
||||
|| r_type == elfcpp::R_PPC_REL16_HI
|
||||
|| r_type == elfcpp::R_PPC_REL16_HA))
|
||||
&& gsym->use_plt_offset(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
elfcpp::Elf_Xword value;
|
||||
|
||||
|
137
gold/sparc.cc
137
gold/sparc.cc
@ -198,6 +198,9 @@ class Target_sparc : public Sized_target<size, big_endian>
|
||||
: issued_non_pic_error_(false)
|
||||
{ }
|
||||
|
||||
static inline int
|
||||
get_reference_flags(unsigned int r_type);
|
||||
|
||||
inline void
|
||||
local(Symbol_table* symtab, Layout* layout, Target_sparc* target,
|
||||
Sized_relobj<size, big_endian>* object,
|
||||
@ -1576,6 +1579,119 @@ optimize_tls_reloc(bool is_final, int r_type)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the Reference_flags for a particular relocation.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
int
|
||||
Target_sparc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
|
||||
{
|
||||
r_type &= 0xff;
|
||||
switch (r_type)
|
||||
{
|
||||
case elfcpp::R_SPARC_NONE:
|
||||
case elfcpp::R_SPARC_REGISTER:
|
||||
case elfcpp::R_SPARC_GNU_VTINHERIT:
|
||||
case elfcpp::R_SPARC_GNU_VTENTRY:
|
||||
// No symbol reference.
|
||||
return 0;
|
||||
|
||||
case elfcpp::R_SPARC_UA64:
|
||||
case elfcpp::R_SPARC_64:
|
||||
case elfcpp::R_SPARC_HIX22:
|
||||
case elfcpp::R_SPARC_LOX10:
|
||||
case elfcpp::R_SPARC_H44:
|
||||
case elfcpp::R_SPARC_M44:
|
||||
case elfcpp::R_SPARC_L44:
|
||||
case elfcpp::R_SPARC_HH22:
|
||||
case elfcpp::R_SPARC_HM10:
|
||||
case elfcpp::R_SPARC_LM22:
|
||||
case elfcpp::R_SPARC_HI22:
|
||||
case elfcpp::R_SPARC_LO10:
|
||||
case elfcpp::R_SPARC_OLO10:
|
||||
case elfcpp::R_SPARC_UA32:
|
||||
case elfcpp::R_SPARC_32:
|
||||
case elfcpp::R_SPARC_UA16:
|
||||
case elfcpp::R_SPARC_16:
|
||||
case elfcpp::R_SPARC_11:
|
||||
case elfcpp::R_SPARC_10:
|
||||
case elfcpp::R_SPARC_8:
|
||||
case elfcpp::R_SPARC_7:
|
||||
case elfcpp::R_SPARC_6:
|
||||
case elfcpp::R_SPARC_5:
|
||||
return Symbol::ABSOLUTE_REF;
|
||||
|
||||
case elfcpp::R_SPARC_DISP8:
|
||||
case elfcpp::R_SPARC_DISP16:
|
||||
case elfcpp::R_SPARC_DISP32:
|
||||
case elfcpp::R_SPARC_DISP64:
|
||||
case elfcpp::R_SPARC_PC_HH22:
|
||||
case elfcpp::R_SPARC_PC_HM10:
|
||||
case elfcpp::R_SPARC_PC_LM22:
|
||||
case elfcpp::R_SPARC_PC10:
|
||||
case elfcpp::R_SPARC_PC22:
|
||||
case elfcpp::R_SPARC_WDISP30:
|
||||
case elfcpp::R_SPARC_WDISP22:
|
||||
case elfcpp::R_SPARC_WDISP19:
|
||||
case elfcpp::R_SPARC_WDISP16:
|
||||
return Symbol::RELATIVE_REF;
|
||||
|
||||
case elfcpp::R_SPARC_PLT64:
|
||||
case elfcpp::R_SPARC_PLT32:
|
||||
case elfcpp::R_SPARC_HIPLT22:
|
||||
case elfcpp::R_SPARC_LOPLT10:
|
||||
case elfcpp::R_SPARC_PCPLT10:
|
||||
return Symbol::FUNCTION_CALL | Symbol::ABSOLUTE_REF;
|
||||
|
||||
case elfcpp::R_SPARC_PCPLT32:
|
||||
case elfcpp::R_SPARC_PCPLT22:
|
||||
case elfcpp::R_SPARC_WPLT30:
|
||||
return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
|
||||
|
||||
case elfcpp::R_SPARC_GOTDATA_OP:
|
||||
case elfcpp::R_SPARC_GOTDATA_OP_HIX22:
|
||||
case elfcpp::R_SPARC_GOTDATA_OP_LOX10:
|
||||
case elfcpp::R_SPARC_GOT10:
|
||||
case elfcpp::R_SPARC_GOT13:
|
||||
case elfcpp::R_SPARC_GOT22:
|
||||
// Absolute in GOT.
|
||||
return Symbol::ABSOLUTE_REF;
|
||||
|
||||
case elfcpp::R_SPARC_TLS_GD_HI22: // Global-dynamic
|
||||
case elfcpp::R_SPARC_TLS_GD_LO10:
|
||||
case elfcpp::R_SPARC_TLS_GD_ADD:
|
||||
case elfcpp::R_SPARC_TLS_GD_CALL:
|
||||
case elfcpp::R_SPARC_TLS_LDM_HI22: // Local-dynamic
|
||||
case elfcpp::R_SPARC_TLS_LDM_LO10:
|
||||
case elfcpp::R_SPARC_TLS_LDM_ADD:
|
||||
case elfcpp::R_SPARC_TLS_LDM_CALL:
|
||||
case elfcpp::R_SPARC_TLS_LDO_HIX22: // Alternate local-dynamic
|
||||
case elfcpp::R_SPARC_TLS_LDO_LOX10:
|
||||
case elfcpp::R_SPARC_TLS_LDO_ADD:
|
||||
case elfcpp::R_SPARC_TLS_LE_HIX22:
|
||||
case elfcpp::R_SPARC_TLS_LE_LOX10:
|
||||
case elfcpp::R_SPARC_TLS_IE_HI22: // Initial-exec
|
||||
case elfcpp::R_SPARC_TLS_IE_LO10:
|
||||
case elfcpp::R_SPARC_TLS_IE_LD:
|
||||
case elfcpp::R_SPARC_TLS_IE_LDX:
|
||||
case elfcpp::R_SPARC_TLS_IE_ADD:
|
||||
return Symbol::TLS_REF;
|
||||
|
||||
case elfcpp::R_SPARC_COPY:
|
||||
case elfcpp::R_SPARC_GLOB_DAT:
|
||||
case elfcpp::R_SPARC_JMP_SLOT:
|
||||
case elfcpp::R_SPARC_RELATIVE:
|
||||
case elfcpp::R_SPARC_TLS_DTPMOD64:
|
||||
case elfcpp::R_SPARC_TLS_DTPMOD32:
|
||||
case elfcpp::R_SPARC_TLS_DTPOFF64:
|
||||
case elfcpp::R_SPARC_TLS_DTPOFF32:
|
||||
case elfcpp::R_SPARC_TLS_TPOFF64:
|
||||
case elfcpp::R_SPARC_TLS_TPOFF32:
|
||||
default:
|
||||
// Not expected. We will give an error later.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a PLT entry slot for a call to __tls_get_addr
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
@ -2068,10 +2184,7 @@ Target_sparc<size, big_endian>::Scan::global(
|
||||
if (gsym->needs_plt_entry())
|
||||
target->make_plt_entry(symtab, layout, gsym);
|
||||
// Make a dynamic relocation if necessary.
|
||||
int flags = Symbol::NON_PIC_REF;
|
||||
if (gsym->type() == elfcpp::STT_FUNC)
|
||||
flags |= Symbol::FUNCTION_CALL;
|
||||
if (gsym->needs_dynamic_reloc(flags))
|
||||
if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
if (gsym->may_need_copy_reloc())
|
||||
{
|
||||
@ -2127,7 +2240,7 @@ Target_sparc<size, big_endian>::Scan::global(
|
||||
gsym->set_needs_dynsym_value();
|
||||
}
|
||||
// Make a dynamic relocation if necessary.
|
||||
if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF))
|
||||
if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
unsigned int r_off = reloc.get_r_offset();
|
||||
|
||||
@ -2512,19 +2625,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
|
||||
// Pick the value to use for symbols defined in shared objects.
|
||||
Symbol_value<size> symval;
|
||||
if (gsym != NULL
|
||||
&& gsym->use_plt_offset(r_type == elfcpp::R_SPARC_DISP8
|
||||
|| r_type == elfcpp::R_SPARC_DISP16
|
||||
|| r_type == elfcpp::R_SPARC_DISP32
|
||||
|| r_type == elfcpp::R_SPARC_DISP64
|
||||
|| r_type == elfcpp::R_SPARC_PC_HH22
|
||||
|| r_type == elfcpp::R_SPARC_PC_HM10
|
||||
|| r_type == elfcpp::R_SPARC_PC_LM22
|
||||
|| r_type == elfcpp::R_SPARC_PC10
|
||||
|| r_type == elfcpp::R_SPARC_PC22
|
||||
|| r_type == elfcpp::R_SPARC_WDISP30
|
||||
|| r_type == elfcpp::R_SPARC_WDISP22
|
||||
|| r_type == elfcpp::R_SPARC_WDISP19
|
||||
|| r_type == elfcpp::R_SPARC_WDISP16))
|
||||
&& gsym->use_plt_offset(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
elfcpp::Elf_Xword value;
|
||||
|
||||
|
@ -614,15 +614,20 @@ class Symbol
|
||||
|
||||
// When determining whether a reference to a symbol needs a dynamic
|
||||
// relocation, we need to know several things about the reference.
|
||||
// These flags may be or'ed together.
|
||||
// These flags may be or'ed together. 0 means that the symbol
|
||||
// isn't referenced at all.
|
||||
enum Reference_flags
|
||||
{
|
||||
// Reference to the symbol's absolute address.
|
||||
// A reference to the symbol's absolute address. This includes
|
||||
// references that cause an absolute address to be stored in the GOT.
|
||||
ABSOLUTE_REF = 1,
|
||||
// A non-PIC reference.
|
||||
NON_PIC_REF = 2,
|
||||
// A function call.
|
||||
FUNCTION_CALL = 4
|
||||
// A reference that calculates the offset of the symbol from some
|
||||
// anchor point, such as the PC or GOT.
|
||||
RELATIVE_REF = 2,
|
||||
// A TLS-related reference.
|
||||
TLS_REF = 4,
|
||||
// A reference that can always be treated as a function call.
|
||||
FUNCTION_CALL = 8
|
||||
};
|
||||
|
||||
// Given a direct absolute or pc-relative static relocation against
|
||||
@ -653,12 +658,8 @@ class Symbol
|
||||
return true;
|
||||
|
||||
// A function call that can branch to a local PLT entry does not need
|
||||
// a dynamic relocation. A non-pic pc-relative function call in a
|
||||
// shared library cannot use a PLT entry.
|
||||
if ((flags & FUNCTION_CALL)
|
||||
&& this->has_plt_offset()
|
||||
&& !((flags & NON_PIC_REF)
|
||||
&& parameters->options().output_is_position_independent()))
|
||||
// a dynamic relocation.
|
||||
if ((flags & FUNCTION_CALL) && this->has_plt_offset())
|
||||
return false;
|
||||
|
||||
// A reference to any PLT entry in a non-position-independent executable
|
||||
@ -679,12 +680,10 @@ class Symbol
|
||||
}
|
||||
|
||||
// Whether we should use the PLT offset associated with a symbol for
|
||||
// a relocation. IS_NON_PIC_REFERENCE is true if this is a non-PIC
|
||||
// reloc--the same set of relocs for which we would pass NON_PIC_REF
|
||||
// to the needs_dynamic_reloc function.
|
||||
// a relocation. FLAGS is a set of Reference_flags.
|
||||
|
||||
bool
|
||||
use_plt_offset(bool is_non_pic_reference) const
|
||||
use_plt_offset(int flags) const
|
||||
{
|
||||
// If the symbol doesn't have a PLT offset, then naturally we
|
||||
// don't want to use it.
|
||||
@ -697,10 +696,7 @@ class Symbol
|
||||
|
||||
// If we are going to generate a dynamic relocation, then we will
|
||||
// wind up using that, so no need to use the PLT entry.
|
||||
if (this->needs_dynamic_reloc(FUNCTION_CALL
|
||||
| (is_non_pic_reference
|
||||
? NON_PIC_REF
|
||||
: 0)))
|
||||
if (this->needs_dynamic_reloc(flags))
|
||||
return false;
|
||||
|
||||
// If the symbol is from a dynamic object, we need to use the PLT
|
||||
@ -714,10 +710,10 @@ class Symbol
|
||||
&& (this->is_undefined() || this->is_preemptible()))
|
||||
return true;
|
||||
|
||||
// If this is a weak undefined symbol, we need to use the PLT
|
||||
// entry; the symbol may be defined by a library loaded at
|
||||
// runtime.
|
||||
if (this->is_weak_undefined())
|
||||
// If this is a call to a weak undefined symbol, we need to use
|
||||
// the PLT entry; the symbol may be defined by a library loaded
|
||||
// at runtime.
|
||||
if ((flags & FUNCTION_CALL) && this->is_weak_undefined())
|
||||
return true;
|
||||
|
||||
// Otherwise we can use the regular definition.
|
||||
|
144
gold/x86_64.cc
144
gold/x86_64.cc
@ -362,6 +362,9 @@ class Target_x86_64 : public Target_freebsd<64, false>
|
||||
: issued_non_pic_error_(false)
|
||||
{ }
|
||||
|
||||
static inline int
|
||||
get_reference_flags(unsigned int r_type);
|
||||
|
||||
inline void
|
||||
local(Symbol_table* symtab, Layout* layout, Target_x86_64* target,
|
||||
Sized_relobj<64, false>* object,
|
||||
@ -1236,6 +1239,73 @@ Target_x86_64::optimize_tls_reloc(bool is_final, int r_type)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the Reference_flags for a particular relocation.
|
||||
|
||||
int
|
||||
Target_x86_64::Scan::get_reference_flags(unsigned int r_type)
|
||||
{
|
||||
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_GOTPC32:
|
||||
case elfcpp::R_X86_64_GOTPC64:
|
||||
// No symbol reference.
|
||||
return 0;
|
||||
|
||||
case elfcpp::R_X86_64_64:
|
||||
case elfcpp::R_X86_64_32:
|
||||
case elfcpp::R_X86_64_32S:
|
||||
case elfcpp::R_X86_64_16:
|
||||
case elfcpp::R_X86_64_8:
|
||||
return Symbol::ABSOLUTE_REF;
|
||||
|
||||
case elfcpp::R_X86_64_PC64:
|
||||
case elfcpp::R_X86_64_PC32:
|
||||
case elfcpp::R_X86_64_PC16:
|
||||
case elfcpp::R_X86_64_PC8:
|
||||
case elfcpp::R_X86_64_GOTOFF64:
|
||||
return Symbol::RELATIVE_REF;
|
||||
|
||||
case elfcpp::R_X86_64_PLT32:
|
||||
case elfcpp::R_X86_64_PLTOFF64:
|
||||
return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
|
||||
|
||||
case elfcpp::R_X86_64_GOT64:
|
||||
case elfcpp::R_X86_64_GOT32:
|
||||
case elfcpp::R_X86_64_GOTPCREL64:
|
||||
case elfcpp::R_X86_64_GOTPCREL:
|
||||
case elfcpp::R_X86_64_GOTPLT64:
|
||||
// Absolute in GOT.
|
||||
return Symbol::ABSOLUTE_REF;
|
||||
|
||||
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 Symbol::TLS_REF;
|
||||
|
||||
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:
|
||||
case elfcpp::R_X86_64_TPOFF64:
|
||||
case elfcpp::R_X86_64_DTPMOD64:
|
||||
case elfcpp::R_X86_64_TLSDESC:
|
||||
case elfcpp::R_X86_64_SIZE32:
|
||||
case elfcpp::R_X86_64_SIZE64:
|
||||
default:
|
||||
// Not expected. We will give an error later.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Report an unsupported relocation against a local symbol.
|
||||
|
||||
void
|
||||
@ -1297,63 +1367,11 @@ bool
|
||||
Target_x86_64::Scan::reloc_needs_plt_for_ifunc(Sized_relobj<64, false>* object,
|
||||
unsigned int r_type)
|
||||
{
|
||||
switch (r_type)
|
||||
{
|
||||
case elfcpp::R_X86_64_NONE:
|
||||
case elfcpp::R_X86_64_GNU_VTINHERIT:
|
||||
case elfcpp::R_X86_64_GNU_VTENTRY:
|
||||
return false;
|
||||
|
||||
case elfcpp::R_X86_64_64:
|
||||
case elfcpp::R_X86_64_32:
|
||||
case elfcpp::R_X86_64_32S:
|
||||
case elfcpp::R_X86_64_16:
|
||||
case elfcpp::R_X86_64_8:
|
||||
case elfcpp::R_X86_64_PC64:
|
||||
case elfcpp::R_X86_64_PC32:
|
||||
case elfcpp::R_X86_64_PC16:
|
||||
case elfcpp::R_X86_64_PC8:
|
||||
case elfcpp::R_X86_64_PLT32:
|
||||
case elfcpp::R_X86_64_GOTPC32:
|
||||
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_GOT32:
|
||||
case elfcpp::R_X86_64_GOTPCREL64:
|
||||
case elfcpp::R_X86_64_GOTPCREL:
|
||||
case elfcpp::R_X86_64_GOTPLT64:
|
||||
return true;
|
||||
|
||||
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:
|
||||
case elfcpp::R_X86_64_TPOFF64:
|
||||
case elfcpp::R_X86_64_DTPMOD64:
|
||||
case elfcpp::R_X86_64_TLSDESC:
|
||||
// We will give an error later.
|
||||
return false;
|
||||
|
||||
case elfcpp::R_X86_64_TLSGD:
|
||||
case elfcpp::R_X86_64_GOTPC32_TLSDESC:
|
||||
case elfcpp::R_X86_64_TLSDESC_CALL:
|
||||
case elfcpp::R_X86_64_TLSLD:
|
||||
case elfcpp::R_X86_64_DTPOFF32:
|
||||
case elfcpp::R_X86_64_DTPOFF64:
|
||||
case elfcpp::R_X86_64_GOTTPOFF:
|
||||
case elfcpp::R_X86_64_TPOFF32:
|
||||
gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
|
||||
object->name().c_str(), r_type);
|
||||
return false;
|
||||
|
||||
case elfcpp::R_X86_64_SIZE32:
|
||||
case elfcpp::R_X86_64_SIZE64:
|
||||
default:
|
||||
// We will give an error later.
|
||||
return false;
|
||||
}
|
||||
int flags = Scan::get_reference_flags(r_type);
|
||||
if (flags & Symbol::TLS_REF)
|
||||
gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
|
||||
object->name().c_str(), r_type);
|
||||
return flags != 0;
|
||||
}
|
||||
|
||||
// Scan a relocation for a local symbol.
|
||||
@ -1779,7 +1797,7 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
|
||||
gsym->set_needs_dynsym_value();
|
||||
}
|
||||
// Make a dynamic relocation if necessary.
|
||||
if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF))
|
||||
if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
if (gsym->may_need_copy_reloc())
|
||||
{
|
||||
@ -1836,10 +1854,7 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
|
||||
if (gsym->needs_plt_entry())
|
||||
target->make_plt_entry(symtab, layout, gsym);
|
||||
// Make a dynamic relocation if necessary.
|
||||
int flags = Symbol::NON_PIC_REF;
|
||||
if (gsym->is_func())
|
||||
flags |= Symbol::FUNCTION_CALL;
|
||||
if (gsym->needs_dynamic_reloc(flags))
|
||||
if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
if (gsym->may_need_copy_reloc())
|
||||
{
|
||||
@ -2242,10 +2257,7 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
|
||||
// Pick the value to use for symbols defined in the PLT.
|
||||
Symbol_value<64> symval;
|
||||
if (gsym != NULL
|
||||
&& gsym->use_plt_offset(r_type == elfcpp::R_X86_64_PC64
|
||||
|| r_type == elfcpp::R_X86_64_PC32
|
||||
|| r_type == elfcpp::R_X86_64_PC16
|
||||
|| r_type == elfcpp::R_X86_64_PC8))
|
||||
&& gsym->use_plt_offset(Scan::get_reference_flags(r_type)))
|
||||
{
|
||||
symval.set_output_value(target->plt_section()->address()
|
||||
+ gsym->plt_offset());
|
||||
|
Loading…
Reference in New Issue
Block a user