Skip to content

Commit 0961e63

Browse files
committed
PR30217, dynamic relocations using local dynamic symbols
glibc's ld.so ignores local dynamic symbols. It's been that way forever. We therefore can't use them on dynamic relocations. Fixing that problem uncovered another problem in sorting of dynamic relocs, caused no doubt by copying make_iplt_section (where we don't want reloc sorting by the generic gold function, we want iplt relocs last) to make_lplt_section (where we do want sorting). PR 30217 * powerpc.cc (branch_needs_plt_entry): New function. (Target_powerpc::plt_off): Use it here.. (Target_powerpc::Scan::global): ..and here to correct PLT16 reloc handling for forced-local global symbols. (Output_data_plt_powerpc::add_entry): Rename "stash" parameter "is_local". Emit relative relocs for globals that are forced local, and don't set_needs_dynsym_entry. (Target_powerpc::make_lplt_section): Don't create a separate reloc section, use rela_dyn. (Target_powerpc::make_brlt_section): Likewise.
1 parent d56e433 commit 0961e63

File tree

1 file changed

+39
-24
lines changed

1 file changed

+39
-24
lines changed

gold/powerpc.cc

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,24 @@ enum Got_type
636636
GOT_TYPE_SMALL_TPREL = 7
637637
};
638638

639+
// gsym->needs_plt_entry purpose is to decide whether a non-branch
640+
// reloc should reference a plt entry. It can't be used to decide
641+
// whether branches need a plt entry. In fact the call to
642+
// needs_plt_entry here is not needed; All cases where it might
643+
// return true ought to be covered already. However, since this
644+
// function is used to decide between plt_ and lplt_ sections in
645+
// plt_off, make certain that every case where make_plt_entry puts
646+
// entries in plt_ is covered here.
647+
static bool
648+
branch_needs_plt_entry(const Symbol* gsym)
649+
{
650+
return (((!gsym->is_defined()
651+
|| gsym->is_from_dynobj()
652+
|| gsym->is_preemptible())
653+
&& !gsym->final_value_is_known())
654+
|| gsym->needs_plt_entry());
655+
}
656+
639657
template<int size, bool big_endian>
640658
class Target_powerpc : public Sized_target<size, big_endian>
641659
{
@@ -927,7 +945,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
927945
if (gsym->type() == elfcpp::STT_GNU_IFUNC
928946
&& gsym->can_use_relative_reloc(false))
929947
*sec = this->iplt_section();
930-
else if (!parameters->doing_static_link())
948+
else if (branch_needs_plt_entry(gsym))
931949
*sec = this->plt_section();
932950
else
933951
*sec = this->lplt_section();
@@ -4133,7 +4151,7 @@ class Output_data_plt_powerpc : public Output_section_data_build
41334151
template<int size, bool big_endian>
41344152
void
41354153
Output_data_plt_powerpc<size, big_endian>::add_entry(Symbol* gsym,
4136-
bool stash)
4154+
bool is_local)
41374155
{
41384156
if (!gsym->has_plt_offset())
41394157
{
@@ -4143,13 +4161,24 @@ Output_data_plt_powerpc<size, big_endian>::add_entry(Symbol* gsym,
41434161
gsym->set_plt_offset(off);
41444162
if (this->rel_)
41454163
{
4146-
gsym->set_needs_dynsym_entry();
4147-
unsigned int dynrel = elfcpp::R_POWERPC_JMP_SLOT;
4148-
this->rel_->add_global(gsym, dynrel, this, off, 0);
4164+
if (is_local)
4165+
{
4166+
unsigned int dynrel = elfcpp::R_POWERPC_RELATIVE;
4167+
if (size == 64 && this->targ_->abiversion() < 2)
4168+
dynrel = elfcpp::R_POWERPC_JMP_SLOT;
4169+
this->rel_->add_symbolless_global_addend(gsym, dynrel,
4170+
this, off, 0);
4171+
}
4172+
else
4173+
{
4174+
gsym->set_needs_dynsym_entry();
4175+
unsigned int dynrel = elfcpp::R_POWERPC_JMP_SLOT;
4176+
this->rel_->add_global(gsym, dynrel, this, off, 0);
4177+
}
41494178
}
41504179
off += this->plt_entry_size();
41514180
this->set_current_data_size(off);
4152-
if (stash)
4181+
if (is_local)
41534182
{
41544183
Local_plt_ent sym(gsym);
41554184
this->sym_ents_.push_back(sym);
@@ -4493,13 +4522,7 @@ Target_powerpc<size, big_endian>::make_lplt_section(Symbol_table* symtab,
44934522
{
44944523
Reloc_section* lplt_rel = NULL;
44954524
if (parameters->options().output_is_position_independent())
4496-
{
4497-
lplt_rel = new Reloc_section(false);
4498-
this->rela_dyn_section(layout);
4499-
if (this->rela_dyn_->output_section())
4500-
this->rela_dyn_->output_section()
4501-
->add_output_section_data(lplt_rel);
4502-
}
4525+
lplt_rel = this->rela_dyn_section(layout);
45034526
this->lplt_
45044527
= new Output_data_plt_powerpc<size, big_endian>(this, symtab, lplt_rel,
45054528
"** LPLT");
@@ -4609,11 +4632,7 @@ Target_powerpc<size, big_endian>::make_brlt_section(Layout* layout)
46094632
{
46104633
// When PIC we can't fill in .branch_lt but must initialise at
46114634
// runtime via dynamic relocations.
4612-
this->rela_dyn_section(layout);
4613-
brlt_rel = new Reloc_section(false);
4614-
if (this->rela_dyn_->output_section())
4615-
this->rela_dyn_->output_section()
4616-
->add_output_section_data(brlt_rel);
4635+
brlt_rel = this->rela_dyn_section(layout);
46174636
}
46184637
this->brlt_section_
46194638
= new Output_data_brlt_powerpc<size, big_endian>(this, brlt_rel);
@@ -9009,7 +9028,7 @@ Target_powerpc<size, big_endian>::Scan::global(
90099028
case elfcpp::R_PPC64_PLT16_LO_DS:
90109029
if (!pushed_ifunc)
90119030
{
9012-
if (!parameters->doing_static_link())
9031+
if (branch_needs_plt_entry(gsym))
90139032
target->make_plt_entry(symtab, layout, gsym);
90149033
else
90159034
target->make_local_plt_entry(symtab, layout, gsym);
@@ -9028,11 +9047,7 @@ Target_powerpc<size, big_endian>::Scan::global(
90289047
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
90299048
target->push_branch(ppc_object, data_shndx, reloc.get_r_offset(),
90309049
r_type, r_sym, reloc.get_r_addend());
9031-
if (gsym->needs_plt_entry()
9032-
|| (!gsym->final_value_is_known()
9033-
&& (gsym->is_undefined()
9034-
|| gsym->is_from_dynobj()
9035-
|| gsym->is_preemptible())))
9050+
if (branch_needs_plt_entry(gsym))
90369051
target->make_plt_entry(symtab, layout, gsym);
90379052
}
90389053
// Fall through.

0 commit comments

Comments
 (0)