From 3988aed54acce3c682a877b51b0e09cce1079e81 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 31 Oct 2017 22:13:21 +1030 Subject: [PATCH] PR22374, PowerPC unnecessary PLT entries 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. --- bfd/ChangeLog | 9 ++++++++ bfd/elf32-ppc.c | 23 ++++++++++++++++---- bfd/elf64-ppc.c | 30 +++++++++++++++++++++++---- ld/ChangeLog | 4 ++++ ld/testsuite/ld-powerpc/ambiguousv2.d | 5 ----- 5 files changed, 58 insertions(+), 13 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a28769abf50..fca37c0da5d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2017-11-01 Alan Modra + + 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. + 2017-10-31 Nick Clifton PR 22373 diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index afd233f9c56..bd62c42518d 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 8c98fd5d0eb..5cf862b2dca 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/ChangeLog b/ld/ChangeLog index 84bebb3f1fd..bdc98d6ecd0 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,7 @@ +2017-11-01 Alan Modra + + * testsuite/ld-powerpc/ambiguousv2.d: Remove FIXME. + 2017-11-01 Alan Modra PR 22374 diff --git a/ld/testsuite/ld-powerpc/ambiguousv2.d b/ld/testsuite/ld-powerpc/ambiguousv2.d index fec3a2ca5f6..7afdfe104ac 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: .* -- 2.30.2