* 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:
Richard Sandiford 2010-11-11 10:43:30 +00:00
parent fd50354116
commit 95a2c8d6f7
7 changed files with 561 additions and 251 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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