aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-ppc.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2014-07-01 19:32:25 +0930
committerAlan Modra <amodra@gmail.com>2014-07-01 20:28:20 +0930
commit7341d5e22f1061016411734ba162d362ac5928db (patch)
tree36cec79187a6e05bf2e6fa095168347669fbb11e /bfd/elf64-ppc.c
parent2dc0e7b400e46f105960c0dfcd431013f0013c6a (diff)
downloadgdb-7341d5e22f1061016411734ba162d362ac5928db.zip
gdb-7341d5e22f1061016411734ba162d362ac5928db.tar.gz
gdb-7341d5e22f1061016411734ba162d362ac5928db.tar.bz2
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.
Diffstat (limited to 'bfd/elf64-ppc.c')
-rw-r--r--bfd/elf64-ppc.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 3e7993e..267a925 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;
}