From 64b5d6d785eb4c337b7c071ab9607186541a8b14 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 20 Sep 2017 09:17:56 +0930 Subject: [PATCH] [GOLD] PowerPC function address in non-PIC ppc32, like many targets, defines the address of a function as the PLT call stub code for functions referenced but not defined in a non-PIC executable. ppc32 gold, unlike other targets, inherits the ppc64 multiple stub capability for dealing with very large binaries where one set of stubs can't be reached from all code locations. This means there can be multiple choices of address for a function, which might cause function pointer comparison failures. So for ppc32, make non-branch references always use the first stub group. (PowerPC64 ELFv1 is always PIC so doesn't need to define the address of an external function as the PLT stub. PowerPC64 ELFv2 needs a special set of global entry stubs to serve as the address of external functions, so it too is not affected by this bug.) * powerpc.cc (Target_powerpc::Branch_info::make_stub): Put stubs for ppc32 non-branch relocs in first stub table. (Target_powerpc::Relocate::relocate): Resolve similarly. --- gold/ChangeLog | 6 ++++++ gold/powerpc.cc | 25 ++++++++++++++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index 867cbef2ed3..4faf195c23e 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,9 @@ +2017-09-20 Alan Modra + + * powerpc.cc (Target_powerpc::Branch_info::make_stub): Put + stubs for ppc32 non-branch relocs in first stub table. + (Target_powerpc::Relocate::relocate): Resolve similarly. + 2017-09-19 Alan Modra * options.h (stub-group-multi): Default to true. Add diff --git a/gold/powerpc.cc b/gold/powerpc.cc index ff116e3b9fc..ba302f27357 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -3151,11 +3151,17 @@ Target_powerpc::Branch_info::make_stub( target->glink_section()->add_global_entry(gsym); else { - if (stub_table == NULL) + if (stub_table == NULL + && !(size == 32 + && gsym != NULL + && !parameters->options().output_is_position_independent() + && !is_branch_reloc(this->r_type_))) stub_table = this->object_->stub_table(this->shndx_); if (stub_table == NULL) { - // This is a ref from a data section to an ifunc symbol. + // This is a ref from a data section to an ifunc symbol, + // or a non-branch reloc for which we always want to use + // one set of stubs for resolving function addresses. stub_table = ifunc_stub_table; } gold_assert(stub_table != NULL); @@ -8334,11 +8340,20 @@ Target_powerpc::Relocate::relocate( } else { - Stub_table* stub_table - = object->stub_table(relinfo->data_shndx); + Stub_table* stub_table = NULL; + if (target->stub_tables().size() == 1) + stub_table = target->stub_tables()[0]; + if (stub_table == NULL + && !(size == 32 + && gsym != NULL + && !parameters->options().output_is_position_independent() + && !is_branch_reloc(r_type))) + stub_table = object->stub_table(relinfo->data_shndx); if (stub_table == NULL) { - // This is a ref from a data section to an ifunc symbol. + // This is a ref from a data section to an ifunc symbol, + // or a non-branch reloc for which we always want to use + // one set of stubs for resolving function addresses. if (target->stub_tables().size() != 0) stub_table = target->stub_tables()[0]; } -- 2.30.2