diff options
-rw-r--r-- | bfd/ChangeLog | 8 | ||||
-rw-r--r-- | bfd/elf32-ppc.c | 110 | ||||
-rw-r--r-- | bfd/elf64-ppc.c | 12 | ||||
-rw-r--r-- | gold/ChangeLog | 16 | ||||
-rw-r--r-- | gold/powerpc.cc | 191 |
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; } |