diff options
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; |