aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/elf32-ppc.c110
-rw-r--r--bfd/elf64-ppc.c12
-rw-r--r--gold/ChangeLog16
-rw-r--r--gold/powerpc.cc191
5 files changed, 262 insertions, 75 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 99f5639..cb65c7d 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,13 @@
2018-04-09 Alan Modra <amodra@gmail.com>
+ * elf32-ppc.c (ppc_elf_check_relocs): Handle PLT16 relocs.
+ (ppc_elf_relocate_section): Likewise.
+ * elf64-ppc.c (ppc64_elf_check_relocs): Handle PLT16_LO_DS.
+ (ppc64_elf_relocate_section): Likewise. Correct PLT16
+ resolution to plt entry relative to toc pointer.
+
+2018-04-09 Alan Modra <amodra@gmail.com>
+
* elf64-ppc.c (TLS_TLS, TLS_GD, TLS_LD, TLS_TPREL, TLS_DTPREL,
TLS_TPRELGD, TLS_EXPLICIT): Renumber. Test TLS_TLS throughout
file when other TLS flags are tested in a mask.
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 5377461..9736301 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -4056,15 +4056,20 @@ ppc_elf_check_relocs (bfd *abfd,
In a non-pie executable even when there are
no plt calls. */
if (!bfd_link_pic (info)
- || is_branch_reloc (r_type))
+ || is_branch_reloc (r_type)
+ || r_type == R_PPC_PLT16_LO
+ || r_type == R_PPC_PLT16_HI
+ || r_type == R_PPC_PLT16_HA)
{
bfd_vma addend = 0;
if (r_type == R_PPC_PLTREL24)
- {
- ppc_elf_tdata (abfd)->makes_plt_call = 1;
- if (bfd_link_pic (info))
- addend = rel->r_addend;
- }
+ ppc_elf_tdata (abfd)->makes_plt_call = 1;
+ if (bfd_link_pic (info)
+ && (r_type == R_PPC_PLTREL24
+ || r_type == R_PPC_PLT16_LO
+ || r_type == R_PPC_PLT16_HI
+ || r_type == R_PPC_PLT16_HA))
+ addend = rel->r_addend;
if (!update_plt_info (abfd, ifunc, got2, addend))
return FALSE;
}
@@ -4277,7 +4282,9 @@ ppc_elf_check_relocs (bfd *abfd,
case R_PPC_PLTREL24:
if (h == NULL)
break;
+ ppc_elf_tdata (abfd)->makes_plt_call = 1;
/* Fall through */
+
case R_PPC_PLT32:
case R_PPC_PLTREL32:
case R_PPC_PLT16_LO:
@@ -4306,12 +4313,12 @@ ppc_elf_check_relocs (bfd *abfd,
{
bfd_vma addend = 0;
- if (r_type == R_PPC_PLTREL24)
- {
- ppc_elf_tdata (abfd)->makes_plt_call = 1;
- if (bfd_link_pic (info))
- addend = rel->r_addend;
- }
+ if (bfd_link_pic (info)
+ && (r_type == R_PPC_PLTREL24
+ || r_type == R_PPC_PLT16_LO
+ || r_type == R_PPC_PLT16_HI
+ || r_type == R_PPC_PLT16_HA))
+ addend = rel->r_addend;
h->needs_plt = 1;
if (!update_plt_info (abfd, &h->plt.plist, got2, addend))
return FALSE;
@@ -7747,7 +7754,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
bfd_boolean unresolved_reloc;
bfd_boolean warned;
unsigned int tls_type, tls_mask, tls_gd;
- struct plt_entry **ifunc;
+ struct plt_entry **ifunc, **plt_list;
struct reloc_howto_struct alt_howto;
again:
@@ -8099,8 +8106,33 @@ ppc_elf_relocate_section (bfd *output_bfd,
insn ^= BRANCH_PREDICT_BIT;
bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
- break;
}
+ break;
+
+ case R_PPC_PLT16_HA:
+ {
+ unsigned int insn;
+
+ insn = bfd_get_32 (input_bfd,
+ contents + rel->r_offset - d_offset);
+ if ((insn & (0x3f << 26)) == 15u << 26
+ && (insn & (0x1f << 16)) != 0)
+ {
+ if (!bfd_link_pic (info))
+ {
+ /* Convert addis to lis. */
+ insn &= ~(0x1f << 16);
+ bfd_put_32 (input_bfd, insn,
+ contents + rel->r_offset - d_offset);
+ }
+ }
+ else if (bfd_link_pic (info))
+ info->callbacks->einfo
+ (_("%P: %H: error: %s with unexpected instruction %x\n"),
+ input_bfd, input_section, rel->r_offset,
+ "R_PPC_PLT16_HA", insn);
+ }
+ break;
}
if (ELIMINATE_COPY_RELOCS
@@ -8239,10 +8271,17 @@ ppc_elf_relocate_section (bfd *output_bfd,
ent = NULL;
if (ifunc != NULL
&& (!bfd_link_pic (info)
- || is_branch_reloc (r_type)))
+ || is_branch_reloc (r_type)
+ || r_type == R_PPC_PLT16_LO
+ || r_type == R_PPC_PLT16_HI
+ || r_type == R_PPC_PLT16_HA))
{
addend = 0;
- if (r_type == R_PPC_PLTREL24 && bfd_link_pic (info))
+ if (bfd_link_pic (info)
+ && (r_type == R_PPC_PLTREL24
+ || r_type == R_PPC_PLT16_LO
+ || r_type == R_PPC_PLT16_HI
+ || r_type == R_PPC_PLT16_HA))
addend = rel->r_addend;
ent = find_plt_ent (ifunc, got2, addend);
}
@@ -9092,6 +9131,42 @@ ppc_elf_relocate_section (bfd *output_bfd,
addend = 0;
break;
+ case R_PPC_PLT16_LO:
+ case R_PPC_PLT16_HI:
+ case R_PPC_PLT16_HA:
+ plt_list = ifunc;
+ if (h != NULL)
+ plt_list = &h->plt.plist;
+ unresolved_reloc = TRUE;
+ if (plt_list != NULL)
+ {
+ struct plt_entry *ent;
+
+ ent = find_plt_ent (plt_list, got2,
+ bfd_link_pic (info) ? addend : 0);
+ if (ent != NULL)
+ {
+ unresolved_reloc = FALSE;
+ relocation = (htab->elf.splt->output_section->vma
+ + htab->elf.splt->output_offset
+ + ent->plt.offset);
+ if (bfd_link_pic (info))
+ {
+ bfd_vma got = 0;
+
+ if (ent->addend >= 32768)
+ got = (ent->addend
+ + ent->sec->output_section->vma
+ + ent->sec->output_offset);
+ else
+ got = SYM_VAL (htab->elf.hgot);
+ relocation -= got;
+ }
+ }
+ }
+ addend = 0;
+ break;
+
/* Relocate against _SDA_BASE_. */
case R_PPC_SDAREL16:
{
@@ -9420,9 +9495,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
case R_PPC_IRELATIVE:
case R_PPC_PLT32:
case R_PPC_PLTREL32:
- case R_PPC_PLT16_LO:
- case R_PPC_PLT16_HI:
- case R_PPC_PLT16_HA:
case R_PPC_ADDR30:
case R_PPC_EMB_RELSEC16:
case R_PPC_EMB_RELST_LO:
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 4226120..835baec 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -5623,6 +5623,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_PPC64_PLT16_HA:
case R_PPC64_PLT16_HI:
case R_PPC64_PLT16_LO:
+ case R_PPC64_PLT16_LO_DS:
case R_PPC64_PLT32:
case R_PPC64_PLT64:
/* This symbol requires a procedure linkage table entry. */
@@ -14664,6 +14665,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
case R_PPC64_PLT16_HA:
case R_PPC64_PLT16_HI:
case R_PPC64_PLT16_LO:
+ case R_PPC64_PLT16_LO_DS:
case R_PPC64_PLT32:
case R_PPC64_PLT64:
/* Relocation is to the entry for this symbol in the
@@ -14690,12 +14692,22 @@ ppc64_elf_relocate_section (bfd *output_bfd,
&& ent->addend == orig_rel.r_addend)
{
asection *plt;
+ bfd_vma got;
plt = htab->elf.splt;
if (!htab->elf.dynamic_sections_created
|| h == NULL
|| h->elf.dynindx == -1)
plt = htab->elf.iplt;
+ if (r_type == R_PPC64_PLT16_HA
+ || r_type ==R_PPC64_PLT16_HI
+ || r_type ==R_PPC64_PLT16_LO
+ || r_type ==R_PPC64_PLT16_LO_DS)
+ {
+ got = (elf_gp (output_bfd)
+ + htab->sec_info[input_section->id].toc_off);
+ relocation -= got;
+ }
relocation = (plt->output_section->vma
+ plt->output_offset
+ ent->plt.offset);
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 1c92cf1..48c87e4 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,19 @@
+2018-04-09 Alan Modra <amodra@gmail.com>
+
+ * powerpc.cc (Target_powerpc::plt_off): New functions.
+ (is_plt16_reloc): New function.
+ (Stub_table::plt_off): Use Target_powerpc::plt_off.
+ (Stub_table::plt_call_size): Use plt_off.
+ (Stub_table::do_write): Likewise.
+ (Target_powerpc::Scan::get_reference_flags): Return RELATIVE_REF
+ for PLT16 relocations.
+ (Target_powerpc::Scan::reloc_needs_plt_for_ifunc): Return true
+ for PLT16 relocations.
+ (Target_powerpc::Scan::global): Make a PLT entry for PLT16 relocations.
+ (Target_powerpc::Relocate::relocate): Support PLT16 relocations.
+ (Powerpc_scan_relocatable_reloc::global_strategy): Return RELOC_SPECIAL
+ for ppc32 plt16 relocs.
+
2018-04-06 Cary Coutant <ccoutant@gmail.com>
* object.cc (Sized_relobj_file::include_section_group): Store
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index a2c9698..0975fee 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -860,6 +860,29 @@ class Target_powerpc : public Sized_target<size, big_endian>
return this->iplt_;
}
+ // Return the plt offset and section for the given global sym.
+ Address
+ plt_off(const Symbol* gsym,
+ const Output_data_plt_powerpc<size, big_endian>** sec) const
+ {
+ if (gsym->type() == elfcpp::STT_GNU_IFUNC
+ && gsym->can_use_relative_reloc(false))
+ *sec = this->iplt_section();
+ else
+ *sec = this->plt_section();
+ return gsym->plt_offset();
+ }
+
+ // Return the plt offset and section for the given local sym.
+ Address
+ plt_off(const Sized_relobj_file<size, big_endian>* relobj,
+ unsigned int local_sym_index,
+ const Output_data_plt_powerpc<size, big_endian>** sec) const
+ {
+ *sec = this->iplt_section();
+ return relobj->local_plt_offset(local_sym_index);
+ }
+
// Get the .glink section.
const Output_data_glink<size, big_endian>*
glink_section() const
@@ -1730,6 +1753,17 @@ is_branch_reloc(unsigned int r_type)
|| r_type == elfcpp::R_POWERPC_ADDR14_BRNTAKEN);
}
+// Reloc resolves to plt entry.
+template<int size>
+inline bool
+is_plt16_reloc(unsigned int r_type)
+{
+ return (r_type == elfcpp::R_POWERPC_PLT16_LO
+ || r_type == elfcpp::R_POWERPC_PLT16_HI
+ || r_type == elfcpp::R_POWERPC_PLT16_HA
+ || (size == 64 && r_type == elfcpp::R_PPC64_PLT16_LO_DS));
+}
+
// If INSN is an opcode that may be used with an @tls operand, return
// the transformed insn for TLS optimisation, otherwise return 0. If
// REG is non-zero only match an insn with RB or RA equal to REG.
@@ -4408,21 +4442,17 @@ class Stub_table : public Output_relaxed_input_section
// Return the plt offset for the given call stub.
Address
- plt_off(typename Plt_stub_entries::const_iterator p, bool* is_iplt) const
+ plt_off(typename Plt_stub_entries::const_iterator p,
+ const Output_data_plt_powerpc<size, big_endian>** sec) const
{
const Symbol* gsym = p->first.sym_;
if (gsym != NULL)
- {
- *is_iplt = (gsym->type() == elfcpp::STT_GNU_IFUNC
- && gsym->can_use_relative_reloc(false));
- return gsym->plt_offset();
- }
+ return this->targ_->plt_off(gsym, sec);
else
{
- *is_iplt = true;
const Sized_relobj_file<size, big_endian>* relobj = p->first.object_;
unsigned int local_sym_index = p->first.locsym_;
- return relobj->local_plt_offset(local_sym_index);
+ return this->targ_->plt_off(relobj, local_sym_index, sec);
}
}
@@ -4437,12 +4467,9 @@ class Stub_table : public Output_relaxed_input_section
+ (this->targ_->is_tls_get_addr_opt(gsym) ? 8 * 4 : 0));
}
- bool is_iplt;
- Address plt_addr = this->plt_off(p, &is_iplt);
- if (is_iplt)
- plt_addr += this->targ_->iplt_section()->address();
- else
- plt_addr += this->targ_->plt_section()->address();
+ const Output_data_plt_powerpc<size, big_endian>* plt;
+ Address plt_addr = this->plt_off(p, &plt);
+ plt_addr += plt->address();
Address got_addr = this->targ_->got_section()->output_section()->address();
const Powerpc_relobj<size, big_endian>* ppcobj = static_cast
<const Powerpc_relobj<size, big_endian>*>(p->first.object_);
@@ -5158,27 +5185,15 @@ Stub_table<size, big_endian>::do_write(Output_file* of)
if (!this->plt_call_stubs_.empty())
{
- // The base address of the .plt section.
- Address plt_base = this->targ_->plt_section()->address();
- Address iplt_base = invalid_address;
-
// Write out plt call stubs.
typename Plt_stub_entries::const_iterator cs;
for (cs = this->plt_call_stubs_.begin();
cs != this->plt_call_stubs_.end();
++cs)
{
- bool is_iplt;
- Address pltoff = this->plt_off(cs, &is_iplt);
- Address plt_addr = pltoff;
- if (is_iplt)
- {
- if (iplt_base == invalid_address)
- iplt_base = this->targ_->iplt_section()->address();
- plt_addr += iplt_base;
- }
- else
- plt_addr += plt_base;
+ const Output_data_plt_powerpc<size, big_endian>* plt;
+ Address pltoff = this->plt_off(cs, &plt);
+ Address plt_addr = pltoff + plt->address();
const Powerpc_relobj<size, big_endian>* ppcobj = static_cast
<const Powerpc_relobj<size, big_endian>*>(cs->first.object_);
Address got_addr = got_os_addr + ppcobj->toc_base_offset();
@@ -5397,9 +5412,6 @@ Stub_table<size, big_endian>::do_write(Output_file* of)
{
if (!this->plt_call_stubs_.empty())
{
- // The base address of the .plt section.
- Address plt_base = this->targ_->plt_section()->address();
- Address iplt_base = invalid_address;
// The address of _GLOBAL_OFFSET_TABLE_.
Address g_o_t = invalid_address;
@@ -5409,16 +5421,9 @@ Stub_table<size, big_endian>::do_write(Output_file* of)
cs != this->plt_call_stubs_.end();
++cs)
{
- bool is_iplt;
- Address plt_addr = this->plt_off(cs, &is_iplt);
- if (is_iplt)
- {
- if (iplt_base == invalid_address)
- iplt_base = this->targ_->iplt_section()->address();
- plt_addr += iplt_base;
- }
- else
- plt_addr += plt_base;
+ const Output_data_plt_powerpc<size, big_endian>* plt;
+ Address plt_addr = this->plt_off(cs, &plt);
+ plt_addr += plt->address();
p = oview + cs->second.off_;
const Symbol* gsym = cs->first.sym_;
@@ -6244,6 +6249,10 @@ Target_powerpc<size, big_endian>::Scan::get_reference_flags(
case elfcpp::R_PPC64_TOC16_HA:
case elfcpp::R_PPC64_TOC16_DS:
case elfcpp::R_PPC64_TOC16_LO_DS:
+ case elfcpp::R_POWERPC_PLT16_LO:
+ case elfcpp::R_POWERPC_PLT16_HI:
+ case elfcpp::R_POWERPC_PLT16_HA:
+ case elfcpp::R_PPC64_PLT16_LO_DS:
ref = Symbol::RELATIVE_REF;
break;
@@ -6427,6 +6436,14 @@ Target_powerpc<size, big_endian>::Scan::reloc_needs_plt_for_ifunc(
case elfcpp::R_PPC64_GOT16_LO_DS:
return false;
+ // PLT relocs are OK and need a PLT entry.
+ case elfcpp::R_POWERPC_PLT16_LO:
+ case elfcpp::R_POWERPC_PLT16_HI:
+ case elfcpp::R_POWERPC_PLT16_HA:
+ case elfcpp::R_PPC64_PLT16_LO_DS:
+ return true;
+ break;
+
// Function calls are good, and these do need a PLT entry.
case elfcpp::R_POWERPC_ADDR24:
case elfcpp::R_POWERPC_ADDR14:
@@ -7245,6 +7262,14 @@ Target_powerpc<size, big_endian>::Scan::global(
}
break;
+ case elfcpp::R_POWERPC_PLT16_LO:
+ case elfcpp::R_POWERPC_PLT16_HI:
+ case elfcpp::R_POWERPC_PLT16_HA:
+ case elfcpp::R_PPC64_PLT16_LO_DS:
+ if (!pushed_ifunc)
+ target->make_plt_entry(symtab, layout, gsym);
+ break;
+
case elfcpp::R_PPC_PLTREL24:
case elfcpp::R_POWERPC_REL24:
if (!is_ifunc)
@@ -8366,9 +8391,12 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
bool has_stub_value = false;
bool localentry0 = false;
unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
- if ((gsym != NULL
+ bool has_plt_offset
+ = (gsym != NULL
? gsym->use_plt_offset(Scan::get_reference_flags(r_type, target))
- : object->local_has_plt_offset(r_sym))
+ : object->local_has_plt_offset(r_sym));
+ if (has_plt_offset
+ && !is_plt16_reloc<size>(r_type)
&& (!psymval->is_ifunc_symbol()
|| Scan::reloc_needs_plt_for_ifunc(target, object, r_type, false)))
{
@@ -8440,12 +8468,38 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
gold_assert(has_stub_value || !(os->flags() & elfcpp::SHF_ALLOC));
}
- if (r_type == elfcpp::R_POWERPC_GOT16
- || r_type == elfcpp::R_POWERPC_GOT16_LO
- || r_type == elfcpp::R_POWERPC_GOT16_HI
- || r_type == elfcpp::R_POWERPC_GOT16_HA
- || r_type == elfcpp::R_PPC64_GOT16_DS
- || r_type == elfcpp::R_PPC64_GOT16_LO_DS)
+ if (has_plt_offset && is_plt16_reloc<size>(r_type))
+ {
+ const Output_data_plt_powerpc<size, big_endian>* plt;
+ if (gsym)
+ value = target->plt_off(gsym, &plt);
+ else
+ value = target->plt_off(object, r_sym, &plt);
+ value += plt->address();
+
+ if (size == 64)
+ value -= (target->got_section()->output_section()->address()
+ + object->toc_base_offset());
+ else if (parameters->options().output_is_position_independent())
+ {
+ if (rela.get_r_addend() >= 32768)
+ {
+ unsigned int got2 = object->got2_shndx();
+ value -= (object->get_output_section_offset(got2)
+ + object->output_section(got2)->address()
+ + rela.get_r_addend());
+ }
+ else
+ value -= (target->got_section()->address()
+ + target->got_section()->g_o_t());
+ }
+ }
+ else if (r_type == elfcpp::R_POWERPC_GOT16
+ || r_type == elfcpp::R_POWERPC_GOT16_LO
+ || r_type == elfcpp::R_POWERPC_GOT16_HI
+ || r_type == elfcpp::R_POWERPC_GOT16_HA
+ || r_type == elfcpp::R_PPC64_GOT16_DS
+ || r_type == elfcpp::R_PPC64_GOT16_LO_DS)
{
if (gsym != NULL)
{
@@ -8777,7 +8831,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
else if (!has_stub_value)
{
Address addend = 0;
- if (!(size == 32 && r_type == elfcpp::R_PPC_PLTREL24))
+ if (!(size == 32
+ && (r_type == elfcpp::R_PPC_PLTREL24
+ || r_type == elfcpp::R_POWERPC_PLT16_LO
+ || r_type == elfcpp::R_POWERPC_PLT16_HI
+ || r_type == elfcpp::R_POWERPC_PLT16_HA)))
addend = rela.get_r_addend();
value = psymval->value(object, addend);
if (size == 64 && is_branch_reloc(r_type))
@@ -8944,6 +9002,23 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
}
break;
+ case elfcpp::R_POWERPC_PLT16_HA:
+ if (size == 32
+ && !parameters->options().output_is_position_independent())
+ {
+ Insn* iview = reinterpret_cast<Insn*>(view - d_offset);
+ Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
+
+ // Convert addis to lis.
+ if ((insn & (0x3f << 26)) == 15u << 26
+ && (insn & (0x1f << 16)) != 0)
+ {
+ insn &= ~(0x1f << 16);
+ elfcpp::Swap<32, big_endian>::writeval(iview, insn);
+ }
+ }
+ break;
+
default:
break;
}
@@ -9345,6 +9420,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
case elfcpp::R_POWERPC_REL16_LO:
case elfcpp::R_PPC64_TOC16_LO:
case elfcpp::R_POWERPC_GOT16_LO:
+ case elfcpp::R_POWERPC_PLT16_LO:
case elfcpp::R_POWERPC_SECTOFF_LO:
case elfcpp::R_POWERPC_TPREL16_LO:
case elfcpp::R_POWERPC_DTPREL16_LO:
@@ -9371,6 +9447,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
case elfcpp::R_POWERPC_REL16_HI:
case elfcpp::R_PPC64_TOC16_HI:
case elfcpp::R_POWERPC_GOT16_HI:
+ case elfcpp::R_POWERPC_PLT16_HI:
case elfcpp::R_POWERPC_SECTOFF_HI:
case elfcpp::R_POWERPC_TPREL16_HI:
case elfcpp::R_POWERPC_DTPREL16_HI:
@@ -9392,6 +9469,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
case elfcpp::R_POWERPC_REL16_HA:
case elfcpp::R_PPC64_TOC16_HA:
case elfcpp::R_POWERPC_GOT16_HA:
+ case elfcpp::R_POWERPC_PLT16_HA:
case elfcpp::R_POWERPC_SECTOFF_HA:
case elfcpp::R_POWERPC_TPREL16_HA:
case elfcpp::R_POWERPC_DTPREL16_HA:
@@ -9464,6 +9542,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
case elfcpp::R_PPC64_TOC16_LO_DS:
case elfcpp::R_PPC64_GOT16_DS:
case elfcpp::R_PPC64_GOT16_LO_DS:
+ case elfcpp::R_PPC64_PLT16_LO_DS:
case elfcpp::R_PPC64_SECTOFF_DS:
case elfcpp::R_PPC64_SECTOFF_LO_DS:
maybe_dq_reloc = true;
@@ -9522,9 +9601,6 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
case elfcpp::R_POWERPC_PLT32:
case elfcpp::R_POWERPC_PLTREL32:
- case elfcpp::R_POWERPC_PLT16_LO:
- case elfcpp::R_POWERPC_PLT16_HI:
- case elfcpp::R_POWERPC_PLT16_HA:
case elfcpp::R_PPC_SDAREL16:
case elfcpp::R_POWERPC_ADDR30:
case elfcpp::R_PPC64_PLT64:
@@ -9533,7 +9609,6 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
case elfcpp::R_PPC64_PLTGOT16_LO:
case elfcpp::R_PPC64_PLTGOT16_HI:
case elfcpp::R_PPC64_PLTGOT16_HA:
- case elfcpp::R_PPC64_PLT16_LO_DS:
case elfcpp::R_PPC64_PLTGOT16_DS:
case elfcpp::R_PPC64_PLTGOT16_LO_DS:
case elfcpp::R_PPC_EMB_RELSDA:
@@ -9660,7 +9735,11 @@ public:
inline Relocatable_relocs::Reloc_strategy
global_strategy(unsigned int r_type, Relobj*, unsigned int)
{
- if (r_type == elfcpp::R_PPC_PLTREL24)
+ if (size == 32
+ && (r_type == elfcpp::R_PPC_PLTREL24
+ || r_type == elfcpp::R_POWERPC_PLT16_LO
+ || r_type == elfcpp::R_POWERPC_PLT16_HI
+ || r_type == elfcpp::R_POWERPC_PLT16_HA))
return Relocatable_relocs::RELOC_SPECIAL;
return Relocatable_relocs::RELOC_COPY;
}