diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2010-11-11 10:43:30 +0000 |
---|---|---|
committer | Richard Sandiford <rdsandiford@googlemail.com> | 2010-11-11 10:43:30 +0000 |
commit | 95a2c8d6f73bc3c7ac6641b2cbe9a7d7deefada8 (patch) | |
tree | 90fb3bbadbb8dd9d0d87efb6ba8bca25557054ed /gold/i386.cc | |
parent | fd50354116e30413803893c41178623d156f28de (diff) | |
download | fsf-binutils-gdb-95a2c8d6f73bc3c7ac6641b2cbe9a7d7deefada8.zip fsf-binutils-gdb-95a2c8d6f73bc3c7ac6641b2cbe9a7d7deefada8.tar.gz fsf-binutils-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/i386.cc')
-rw-r--r-- | gold/i386.cc | 151 |
1 files changed, 74 insertions, 77 deletions
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: |