This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PR22374, PowerPC unnecessary PLT entries
- From: Alan Modra <amodra at gmail dot com>
- To: binutils at sourceware dot org
- Date: Wed, 1 Nov 2017 18:47:55 +1030
- Subject: PR22374, PowerPC unnecessary PLT entries
- Authentication-results: sourceware.org; auth=none
We don't need a PLT entry when function pointer initialization in a
read/write section is the only reference to a given function symbol.
This patch prevents the unnecessary PLT entry, and ensures no dynamic
relocs are emitted when UNDEFWEAK_NO_DYNAMIC_RELOC says so.
bfd/
PR 22374
* elf32-ppc.c (ppc_elf_adjust_dynamic_symbol): Don't create a plt
entry when just a dynamic reloc can serve. Ensure no dynamic
relocations when UNDEFWEAK_NO_DYNAMIC_RELOC by setting non_got_ref.
Expand and move the non_got_ref comment.
* elf64-ppc.c (ppc64_elf_adjust_dynamic_symbol): Likewise.
ld/
* testsuite/ld-powerpc/ambiguousv2.d: Remove FIXME.
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index afd233f..bd62c42 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -5507,6 +5507,16 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
h->plt.plist = NULL;
h->needs_plt = 0;
h->pointer_equality_needed = 0;
+ /* After adjust_dynamic_symbol, non_got_ref set in the
+ non-pic case means that dyn_relocs for this symbol should
+ be discarded. We either want the symbol to remain
+ undefined, or we have a local definition of some sort.
+ The "local definition" for non-function symbols may be
+ due to creating a local definition in .dynbss, and for
+ function symbols, defining the symbol on the PLT call
+ stub code. Set non_got_ref here to ensure undef weaks
+ stay undefined. */
+ h->non_got_ref = 1;
}
else
{
@@ -5520,19 +5530,24 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
resolution of the symbol to be set at load time rather
than link time. */
if ((h->pointer_equality_needed
- || (!h->ref_regular_nonweak && h->non_got_ref))
+ || (h->non_got_ref
+ && !h->ref_regular_nonweak
+ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)))
&& !htab->is_vxworks
&& !ppc_elf_hash_entry (h)->has_sda_refs
&& !readonly_dynrelocs (h, NULL))
{
h->pointer_equality_needed = 0;
- /* After adjust_dynamic_symbol, non_got_ref set in the
- non-pic case means that dyn_relocs for this symbol
- should be discarded. */
+ /* Say that we do want dynamic relocs. */
h->non_got_ref = 0;
+ /* If we haven't seen a branch reloc then we don't need
+ a plt entry. */
+ if (!h->needs_plt)
+ h->plt.plist = NULL;
}
}
h->protected_def = 0;
+ /* Function symbols can't have copy relocs. */
return TRUE;
}
else
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 8c98fd5..5cf862b 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -7193,6 +7193,16 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
h->plt.plist = NULL;
h->needs_plt = 0;
h->pointer_equality_needed = 0;
+ /* After adjust_dynamic_symbol, non_got_ref set in the
+ non-pic case means that dyn_relocs for this symbol should
+ be discarded. We either want the symbol to remain
+ undefined, or we have a local definition of some sort.
+ The "local definition" for non-function symbols may be
+ due to creating a local definition in .dynbss, and for
+ ELFv2 function symbols, defining the symbol on the PLT
+ call stub code. Set non_got_ref here to ensure undef
+ weaks stay undefined. */
+ h->non_got_ref = 1;
}
else if (abiversion (info->output_bfd) >= 2)
{
@@ -7207,13 +7217,25 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
&& !alias_readonly_dynrelocs (h))
{
h->pointer_equality_needed = 0;
- /* After adjust_dynamic_symbol, non_got_ref set in
- the non-pic case means that dyn_relocs for this
- symbol should be discarded. */
+ /* Say that we do want dynamic relocs. */
h->non_got_ref = 0;
+ /* If we haven't seen a branch reloc then we don't need
+ a plt entry. */
+ if (!h->needs_plt)
+ h->plt.plist = NULL;
}
- /* If making a plt entry, then we don't need copy relocs. */
+ /* ELFv2 function symbols can't have copy relocs. */
+ return TRUE;
+ }
+ else if (!h->needs_plt
+ && !alias_readonly_dynrelocs (h))
+ {
+ /* If we haven't seen a branch reloc then we don't need a
+ plt entry. */
+ h->plt.plist = NULL;
+ h->pointer_equality_needed = 0;
+ h->non_got_ref = 0;
return TRUE;
}
}
diff --git a/ld/testsuite/ld-powerpc/ambiguousv2.d b/ld/testsuite/ld-powerpc/ambiguousv2.d
index fec3a2c..7afdfe1 100644
--- a/ld/testsuite/ld-powerpc/ambiguousv2.d
+++ b/ld/testsuite/ld-powerpc/ambiguousv2.d
@@ -8,16 +8,11 @@
# anything to mark it as ELFv1 or ELFv2. We should get a dynamic
# reloc on the function address, not have a global entry stub, and
# my_func should be undefined dynamic with value zero.
-# FIXME someday: No need for a plt entry.
Relocation section .* contains 1 entries:
.*
.* R_PPC64_ADDR64 .* my_func \+ 0
-Relocation section .* contains 1 entries:
-.*
-.* R_PPC64_JMP_SLOT .* my_func \+ 0
-
Symbol table '\.dynsym' contains 5 entries:
.*
0: .*
--
Alan Modra
Australia Development Lab, IBM