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/powerpc.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/powerpc.cc')
-rw-r--r-- | gold/powerpc.cc | 80 |
1 files changed, 69 insertions, 11 deletions
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; |