aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2010-11-11 10:43:30 +0000
committerRichard Sandiford <rdsandiford@googlemail.com>2010-11-11 10:43:30 +0000
commit95a2c8d6f73bc3c7ac6641b2cbe9a7d7deefada8 (patch)
tree90fb3bbadbb8dd9d0d87efb6ba8bca25557054ed /gold
parentfd50354116e30413803893c41178623d156f28de (diff)
downloadgdb-95a2c8d6f73bc3c7ac6641b2cbe9a7d7deefada8.zip
gdb-95a2c8d6f73bc3c7ac6641b2cbe9a7d7deefada8.tar.gz
gdb-95a2c8d6f73bc3c7ac6641b2cbe9a7d7deefada8.tar.bz2
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.
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog38
-rw-r--r--gold/arm.cc174
-rw-r--r--gold/i386.cc151
-rw-r--r--gold/powerpc.cc80
-rw-r--r--gold/sparc.cc137
-rw-r--r--gold/symtab.h44
-rw-r--r--gold/x86_64.cc144
7 files changed, 539 insertions, 229 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index d1d5298..f7448b9 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -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>
diff --git a/gold/arm.cc b/gold/arm.cc
index 69a21c0..183bc30 100644
--- a/gold/arm.cc
+++ b/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()
diff --git a/gold/i386.cc b/gold/i386.cc
index 693ae4c..0a3931a 100644
--- a/gold/i386.cc
+++ b/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,41 +1195,49 @@ Target_i386::optimize_tls_reloc(bool is_final, int r_type)
}
}
-// Report an unsupported relocation against a local symbol.
+// Get the Reference_flags for a particular relocation.
-void
-Target_i386::Scan::unsupported_reloc_local(Sized_relobj<32, false>* object,
- unsigned int r_type)
-{
- gold_error(_("%s: unsupported reloc %u against local symbol"),
- object->name().c_str(), r_type);
-}
-
-// Return whether we need to make a PLT entry for a relocation of a
-// given type against a STT_GNU_IFUNC symbol.
-
-bool
-Target_i386::Scan::reloc_needs_plt_for_ifunc(Sized_relobj<32, false>* object,
- unsigned int r_type)
+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:
- return false;
+ 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_PLT32:
case elfcpp::R_386_GOTOFF:
- case elfcpp::R_386_GOTPC:
+ return Symbol::RELATIVE_REF;
+
+ case elfcpp::R_386_PLT32:
+ return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
+
case elfcpp::R_386_GOT32:
- return true;
+ // 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:
@@ -1237,23 +1249,6 @@ Target_i386::Scan::reloc_needs_plt_for_ifunc(Sized_relobj<32, false>* object,
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:
@@ -1265,11 +1260,35 @@ Target_i386::Scan::reloc_needs_plt_for_ifunc(Sized_relobj<32, false>* object,
case elfcpp::R_386_TLS_LDM_POP:
case elfcpp::R_386_USED_BY_INTEL_200:
default:
- // We will give an error later.
- return false;
+ // Not expected. We will give an error later.
+ return 0;
}
}
+// Report an unsupported relocation against a local symbol.
+
+void
+Target_i386::Scan::unsupported_reloc_local(Sized_relobj<32, false>* object,
+ unsigned int r_type)
+{
+ gold_error(_("%s: unsupported reloc %u against local symbol"),
+ object->name().c_str(), r_type);
+}
+
+// Return whether we need to make a PLT entry for a relocation of a
+// given type against a STT_GNU_IFUNC symbol.
+
+bool
+Target_i386::Scan::reloc_needs_plt_for_ifunc(Sized_relobj<32, false>* object,
+ unsigned int r_type)
+{
+ 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.
inline void
@@ -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:
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 49af65f..661477a 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -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;
diff --git a/gold/sparc.cc b/gold/sparc.cc
index 2f8ef7a..22bdd2c 100644
--- a/gold/sparc.cc
+++ b/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;
diff --git a/gold/symtab.h b/gold/symtab.h
index 6542edb..f565050 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -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.
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 4853603..a7edba5 100644
--- a/gold/x86_64.cc
+++ b/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());