diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9650b3d827c..3ff3b1e2395 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2020-10-09 Alan Modra + + * elf64-ppc.c (write_plt_relocs_for_local_syms): Don't do local + entry offset optimisation. + 2020-10-09 H.J. Lu PR gas/26703 diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index fa0c7f96e79..c30215b5507 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -14259,8 +14259,6 @@ write_plt_relocs_for_local_syms (struct bfd_link_info *info) } val = sym->st_value + ent->addend; - if (ELF_ST_TYPE (sym->st_info) != STT_GNU_IFUNC) - val += PPC64_LOCAL_ENTRY_OFFSET (sym->st_other); if (sym_sec != NULL && sym_sec->output_section != NULL) val += sym_sec->output_offset + sym_sec->output_section->vma; diff --git a/gold/ChangeLog b/gold/ChangeLog index 0c00d96f4eb..25248a6267a 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,17 @@ +2020-10-09 Alan Modra + + * powerpc.cc (Powerpc_relobj::do_relocate_sections): Don't do + local entry offset optimisation for lplt_section. + (Target_powerpc::Branch_info::make_stub): Don't add local + entry offset to long branch dest passed to + add_long_branch_entry. Do pass st_other bits. + (Stub_table::Branch_stub_ent): Add "other_" field. + (Stub_table::add_long_branch_entry): Add "other" param, and + save. + (Stub_table::branch_stub_size): Adjust long branch offset. + (Stub_table::do_write): Likewise. + (Target_powerpc::Relocate::relocate): Likewise. + 2020-10-09 Alan Modra * powerpc.cc (is_got_reloc): New function. diff --git a/gold/powerpc.cc b/gold/powerpc.cc index f9eb4f98bda..476fb4e588d 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -2767,8 +2767,6 @@ Powerpc_relobj::do_relocate_sections( if (this->local_has_plt_offset(i)) { Address value = this->local_symbol_value(i, 0); - if (size == 64) - value += ppc64_local_entry_offset(i); size_t off = this->local_plt_offset(i); elfcpp::Swap::writeval(oview + off, value); modified = true; @@ -3539,6 +3537,7 @@ Target_powerpc::Branch_info::make_stub( from += (this->object_->output_section(this->shndx_)->address() + this->offset_); Address to; + unsigned int other; if (gsym != NULL) { switch (gsym->source()) @@ -3566,8 +3565,7 @@ Target_powerpc::Branch_info::make_stub( to = symtab->compute_final_value(gsym, &status); if (status != Symbol_table::CFVS_OK) return true; - if (size == 64) - to += this->object_->ppc64_local_entry_offset(gsym); + other = gsym->nonvis() >> 3; } else { @@ -3584,8 +3582,7 @@ Target_powerpc::Branch_info::make_stub( || !symval.has_output_value()) return true; to = symval.value(this->object_, 0); - if (size == 64) - to += this->object_->ppc64_local_entry_offset(this->r_sym_); + other = this->object_->st_other(this->r_sym_) >> 5; } if (!(size == 32 && this->r_type_ == elfcpp::R_PPC_PLTREL24)) to += this->addend_; @@ -3598,7 +3595,11 @@ Target_powerpc::Branch_info::make_stub( &to, &dest_shndx)) return true; } - Address delta = to - from; + unsigned int local_ent = 0; + if (size == 64 + && this->r_type_ != elfcpp::R_PPC64_REL24_NOTOC) + local_ent = elfcpp::ppc64_decode_local_entry(other); + Address delta = to + local_ent - from; if (delta + max_branch_offset >= 2 * max_branch_offset || (size == 64 && this->r_type_ == elfcpp::R_PPC64_REL24_NOTOC @@ -3620,7 +3621,7 @@ Target_powerpc::Branch_info::make_stub( && gsym->output_data() == target->savres_section()); ok = stub_table->add_long_branch_entry(this->object_, this->r_type_, - from, to, save_res); + from, to, other, save_res); } } if (!ok) @@ -4688,7 +4689,7 @@ class Stub_table : public Output_relaxed_input_section { Branch_stub_ent(unsigned int off, bool notoc, bool save_res) : off_(off), iter_(0), notoc_(notoc), toc_(0), save_res_(save_res), - tocoff_(0) + other_(0), tocoff_(0) { } unsigned int off_; @@ -4696,6 +4697,7 @@ class Stub_table : public Output_relaxed_input_section unsigned int notoc_ : 1; unsigned int toc_ : 1; unsigned int save_res_ : 1; + unsigned int other_ : 3; unsigned int tocoff_ : 8; }; typedef typename elfcpp::Elf_types::Elf_Addr Address; @@ -4762,7 +4764,7 @@ class Stub_table : public Output_relaxed_input_section // Add a long branch stub. bool add_long_branch_entry(const Powerpc_relobj*, - unsigned int, Address, Address, bool); + unsigned int, Address, Address, unsigned int, bool); const Branch_stub_ent* find_long_branch_entry(const Powerpc_relobj*, @@ -5282,6 +5284,7 @@ Stub_table::add_long_branch_entry( unsigned int r_type, Address from, Address to, + unsigned int other, bool save_res) { Branch_stub_key key(object, to); @@ -5301,6 +5304,8 @@ Stub_table::add_long_branch_entry( this->need_resize_ = true; p.first->second.toc_ = true; } + if (p.first->second.other_ == 0) + p.first->second.other_ = other; gold_assert(save_res == p.first->second.save_res_); if (p.second || (this->resizing_ && !p.first->second.iter_)) { @@ -6198,6 +6203,7 @@ Stub_table::branch_stub_size( } } + off += elfcpp::ppc64_decode_local_entry(p->second.other_); if (off + (1 << 25) < 2 << 25) return bytes + 4; if (!this->targ_->power10_stubs() @@ -6377,6 +6383,7 @@ Stub_table::do_write(Output_file* of) } if (bs->second.toc_) { + delta += elfcpp::ppc64_decode_local_entry(bs->second.other_); if (delta + (1 << 25) >= 2 << 25) { Address brlt_addr @@ -6410,6 +6417,8 @@ Stub_table::do_write(Output_file* of) } else { + if (!bs->second.notoc_) + delta += elfcpp::ppc64_decode_local_entry(bs->second.other_); if (bs->second.notoc_ || delta + (1 << 25) >= 2 << 25) { unsigned char* startp = p; @@ -6640,6 +6649,8 @@ Stub_table::do_write(Output_file* of) p = oview + off; Address loc = this->stub_address() + off; Address delta = bs->first.dest_ - loc; + if (!bs->second.notoc_) + delta += elfcpp::ppc64_decode_local_entry(bs->second.other_); if (bs->second.notoc_) { unsigned char* startp = p; @@ -11039,14 +11050,15 @@ Target_powerpc::Relocate::relocate( || r_type == elfcpp::R_POWERPC_PLT16_HA))) addend = rela.get_r_addend(); value = psymval->value(object, addend); + unsigned int local_ent = 0; if (size == 64 && is_branch_reloc(r_type)) { if (target->abiversion() >= 2) { if (gsym != NULL) - value += object->ppc64_local_entry_offset(gsym); + local_ent = object->ppc64_local_entry_offset(gsym); else - value += object->ppc64_local_entry_offset(r_sym); + local_ent = object->ppc64_local_entry_offset(r_sym); } else { @@ -11055,9 +11067,9 @@ Target_powerpc::Relocate::relocate( &value, &dest_shndx); } } - Address max_branch_offset = max_branch_delta(r_type); - if (max_branch_offset != 0 - && (value - address + max_branch_offset >= 2 * max_branch_offset + Address max_branch = max_branch_delta(r_type); + if (max_branch != 0 + && (value + local_ent - address + max_branch >= 2 * max_branch || (size == 64 && r_type == elfcpp::R_PPC64_REL24_NOTOC && (gsym != NULL @@ -11082,12 +11094,15 @@ Target_powerpc::Relocate::relocate( + ent->off_); if (size == 64 && r_type != elfcpp::R_PPC64_REL24_NOTOC) - value += ent->tocoff_; + value += (elfcpp::ppc64_decode_local_entry(ent->other_) + + ent->tocoff_); } has_stub_value = true; } } } + if (!has_stub_value) + value += local_ent; } switch (r_type)