diff --git a/gold/ChangeLog b/gold/ChangeLog index d1d5298343..f7448b97e4 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,41 @@ +2010-11-11 Richard Sandiford + + * 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 Cary Coutant diff --git a/gold/arm.cc b/gold/arm.cc index 69a21c01d5..183bc30248 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::optimize_tls_reloc(bool, int) return tls::TLSOPT_NONE; } +// Get the Reference_flags for a particular relocation. + +template +int +Target_arm::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 @@ -8074,7 +8196,7 @@ Target_arm::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::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 inline bool Target_arm::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::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::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::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::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::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::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 693ae4c9b0..0a3931ad64 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,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: diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 49af65f8fe..661477a899 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -188,6 +188,9 @@ class Target_powerpc : public Sized_target : 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* object, @@ -1105,6 +1108,69 @@ optimize_tls_reloc(bool /* is_final */, int r_type) } } +// Get the Reference_flags for a particular relocation. + +template +int +Target_powerpc::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 @@ -1400,7 +1466,7 @@ Target_powerpc::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::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::Relocate::relocate( // Pick the value to use for symbols defined in shared objects. Symbol_value 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 2f8ef7a43e..22bdd2c64a 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -198,6 +198,9 @@ class Target_sparc : public Sized_target : 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* object, @@ -1576,6 +1579,119 @@ optimize_tls_reloc(bool is_final, int r_type) } } +// Get the Reference_flags for a particular relocation. + +template +int +Target_sparc::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 void @@ -2068,10 +2184,7 @@ Target_sparc::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::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::Relocate::relocate( // Pick the value to use for symbols defined in shared objects. Symbol_value 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 6542edbe5e..f5650509b7 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 4853603fdb..a7edba54d1 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());