From 7341d5e22f1061016411734ba162d362ac5928db Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 1 Jul 2014 19:32:25 +0930 Subject: [PATCH] Add symbols for global entry stub, and report stats The undefined function symbols (with non-zero value) on global entry stubs are discarded by objdump when disassembling, so give objdump another symbol to mark the stubs. Also fixes a couple of bugs: - entry_section was set to .opd for ELFv2, which meant a hard error rather than a warning when _start wasn't defined. - global entry stubs were not built if they were the only type of stub in an executable. bfd/ * elf64-ppc.c (ppc_stub_type): Add ppc_stub_global_entry. (struct ppc_link_hash_table): Increase size of stub_count array. (build_global_entry_stubs): Emit symbol on global entry stub. (ppc64_elf_build_stubs): NULL check htab->brlt. Add global entry stub stats. ld/ * emultempl/ppc64elf.em (stub_added): Delete. (gld${EMULATION_NAME}_finish): Call ppc64_elf_build_stubs even when none of the usual stubs have been added. Only change entry_section for ELFv1. --- bfd/ChangeLog | 8 +++++++ bfd/elf64-ppc.c | 39 ++++++++++++++++++++++++++++----- ld/ChangeLog | 7 ++++++ ld/emultempl/ppc64elf.em | 47 ++++++++++++++++++++-------------------- 4 files changed, 72 insertions(+), 29 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0e74b4a973..d41d9e4f29 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2014-07-01 Alan Modra + + * elf64-ppc.c (ppc_stub_type): Add ppc_stub_global_entry. + (struct ppc_link_hash_table): Increase size of stub_count array. + (build_global_entry_stubs): Emit symbol on global entry stub. + (ppc64_elf_build_stubs): NULL check htab->brlt. Add global entry + stub stats. + 2014-07-01 Alan Modra * elf64-ppc.c (abiversion, set_abiversion): Move earlier. diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 3e7993e44b..267a925316 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -3785,7 +3785,8 @@ enum ppc_stub_type { ppc_stub_plt_branch, ppc_stub_plt_branch_r2off, ppc_stub_plt_call, - ppc_stub_plt_call_r2save + ppc_stub_plt_call_r2save, + ppc_stub_global_entry }; struct ppc_stub_hash_entry { @@ -3959,7 +3960,7 @@ struct ppc_link_hash_table bfd_size_type got_reli_size; /* Statistics. */ - unsigned long stub_count[ppc_stub_plt_call_r2save]; + unsigned long stub_count[ppc_stub_global_entry]; /* Number of stubs against global syms. */ unsigned long stub_globals; @@ -12491,6 +12492,32 @@ build_global_entry_stubs (struct elf_link_hash_entry *h, void *inf) htab->stub_error = TRUE; } + htab->stub_count[ppc_stub_global_entry - 1] += 1; + if (htab->params->emit_stub_syms) + { + size_t len = strlen (h->root.root.string); + char *name = bfd_malloc (sizeof "12345678.global_entry." + len); + + if (name == NULL) + return FALSE; + + sprintf (name, "%08x.global_entry.%s", s->id, h->root.root.string); + h = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE); + if (h == NULL) + return FALSE; + if (h->root.type == bfd_link_hash_new) + { + h->root.type = bfd_link_hash_defined; + h->root.u.def.section = s; + h->root.u.def.value = p - s->contents; + h->ref_regular = 1; + h->def_regular = 1; + h->ref_regular_nonweak = 1; + h->forced_local = 1; + h->non_elf = 0; + } + } + if (PPC_HA (off) != 0) { bfd_put_32 (s->owner, ADDIS_R12_R12 | PPC_HA (off), p); @@ -12669,7 +12696,7 @@ ppc64_elf_build_stubs (struct bfd_link_info *info, elf_link_hash_traverse (&htab->elf, build_global_entry_stubs, info); } - if (htab->brlt->size != 0) + if (htab->brlt != NULL && htab->brlt->size != 0) { htab->brlt->contents = bfd_zalloc (htab->brlt->owner, htab->brlt->size); @@ -12843,7 +12870,8 @@ ppc64_elf_build_stubs (struct bfd_link_info *info, " long branch %lu\n" " long toc adj %lu\n" " plt call %lu\n" - " plt call toc %lu"), + " plt call toc %lu\n" + " global entry %lu"), stub_sec_count, stub_sec_count == 1 ? "" : "s", htab->stub_count[ppc_stub_long_branch - 1], @@ -12851,7 +12879,8 @@ ppc64_elf_build_stubs (struct bfd_link_info *info, htab->stub_count[ppc_stub_plt_branch - 1], htab->stub_count[ppc_stub_plt_branch_r2off - 1], htab->stub_count[ppc_stub_plt_call - 1], - htab->stub_count[ppc_stub_plt_call_r2save - 1]); + htab->stub_count[ppc_stub_plt_call_r2save - 1], + htab->stub_count[ppc_stub_global_entry - 1]); } return TRUE; } diff --git a/ld/ChangeLog b/ld/ChangeLog index fd14305b1f..bfddd800e9 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,10 @@ +2014-07-01 Alan Modra + + * emultempl/ppc64elf.em (stub_added): Delete. + (gld${EMULATION_NAME}_finish): Call ppc64_elf_build_stubs even when + none of the usual stubs have been added. Only change entry_section + for ELFv1. + 2014-07-01 Alan Modra * sysdep.h: Don't include limits.h and sys/param.h. Don't diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index 78faf6894e..d45fdacf2d 100644 --- a/ld/emultempl/ppc64elf.em +++ b/ld/emultempl/ppc64elf.em @@ -29,6 +29,7 @@ fragment <children.head)) return stub_sec; @@ -518,33 +517,33 @@ gld${EMULATION_NAME}_after_allocation (void) static void gld${EMULATION_NAME}_finish (void) { + char *msg = NULL; + char *line, *endline; + /* e_entry on PowerPC64 points to the function descriptor for _start. If _start is missing, default to the first function descriptor in the .opd section. */ - entry_section = ".opd"; - - if (stub_added) + if ((elf_elfheader (link_info.output_bfd)->e_flags & EF_PPC64_ABI) == 1) + entry_section = ".opd"; + + if (params.emit_stub_syms < 0) + params.emit_stub_syms = 1; + if (stub_file != NULL + && !link_info.relocatable + && !ppc64_elf_build_stubs (&link_info, config.stats ? &msg : NULL)) + einfo ("%X%P: can not build stubs: %E\n"); + + fflush (stdout); + for (line = msg; line != NULL; line = endline) { - char *msg = NULL; - char *line, *endline; - - if (params.emit_stub_syms < 0) - params.emit_stub_syms = 1; - if (!ppc64_elf_build_stubs (&link_info, config.stats ? &msg : NULL)) - einfo ("%X%P: can not build stubs: %E\n"); - - fflush (stdout); - for (line = msg; line != NULL; line = endline) - { - endline = strchr (line, '\n'); - if (endline != NULL) - *endline++ = '\0'; - fprintf (stderr, "%s: %s\n", program_name, line); - } - fflush (stderr); - if (msg != NULL) - free (msg); + endline = strchr (line, '\n'); + if (endline != NULL) + *endline++ = '\0'; + fprintf (stderr, "%s: %s\n", program_name, line); } + fflush (stderr); + if (msg != NULL) + free (msg); ppc64_elf_restore_symbols (&link_info); finish_default (); -- 2.34.1