aboutsummaryrefslogtreecommitdiff
path: root/gold/powerpc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/powerpc.cc')
-rw-r--r--gold/powerpc.cc80
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;