Add symbols for global entry stub, and report stats
authorAlan Modra <amodra@gmail.com>
Tue, 1 Jul 2014 10:02:25 +0000 (19:32 +0930)
committerAlan Modra <amodra@gmail.com>
Tue, 1 Jul 2014 10:58:20 +0000 (20:28 +0930)
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
bfd/elf64-ppc.c
ld/ChangeLog
ld/emultempl/ppc64elf.em

index 0e74b4a973a1a291352e26fc53bba0b7a8df0816..d41d9e4f29ff3435a4c42a0284ada994f1ce3264 100644 (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.
index 3e7993e44b6b14dbcfd3b8bd57f4950a0948b5ab..267a9253163df760d540197522809990b690050b 100644 (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;
 }
index fd14305b1f501d4a7e1a33fee5a6ac670c226f8f..bfddd800e92c40cc822590c72cd0e99ae04b2db9 100644 (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
index 78faf6894e2e2502d6eb341d3f49ef2222b4dc1e..d45fdacf2da55628e82b5bf197dab64302809978 100644 (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 (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 ();