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.
This commit is contained in:
Alan Modra 2014-07-01 19:32:25 +09:30
parent 2dc0e7b400
commit 7341d5e22f
4 changed files with 71 additions and 28 deletions

View File

@ -1,3 +1,11 @@
2014-07-01 Alan Modra <amodra@gmail.com>
* 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 <amodra@gmail.com>
* elf64-ppc.c (abiversion, set_abiversion): Move earlier.

View File

@ -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;
}

View File

@ -1,3 +1,10 @@
2014-07-01 Alan Modra <amodra@gmail.com>
* 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 <amodra@gmail.com>
* sysdep.h: Don't include limits.h and sys/param.h. Don't

View File

@ -29,6 +29,7 @@ fragment <<EOF
#include "elf-bfd.h"
#include "elf64-ppc.h"
#include "ldlex.h"
#include "elf/ppc64.h"
static asection *ppc_add_stub_section (const char *, asection *);
static void ppc_layout_sections_again (void);
@ -42,7 +43,6 @@ static struct ppc64_elf_params params = { NULL,
/* Fake input file for stubs. */
static lang_input_statement_type *stub_file;
static int stub_added = 0;
/* Whether we need to call ppc_layout_sections_again. */
static int need_laying_out = 0;
@ -390,7 +390,6 @@ ppc_add_stub_section (const char *stub_sec_name, asection *input_section)
if (info.add.head == NULL)
goto err_ret;
stub_added = 1;
if (hook_in_stub (&info, &os->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 ((elf_elfheader (link_info.output_bfd)->e_flags & EF_PPC64_ABI) == 1)
entry_section = ".opd";
if (stub_added)
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 ();