bfd/
authorAlan Modra <amodra@gmail.com>
Thu, 8 Dec 2005 11:41:12 +0000 (11:41 +0000)
committerAlan Modra <amodra@gmail.com>
Thu, 8 Dec 2005 11:41:12 +0000 (11:41 +0000)
* elf32-ppc.c (struct ppc_elf_link_hash_table): Add emit_stub_syms.
(ppc_elf_select_plt_layout): Add emit_stub_syms param, save to htab.
(add_stub_sym): New function.
(allocate_dynrelocs): Call add_stub_sym.
(ppc_elf_size_dynamic_sections): Emit __glink and __glink_PLTresolve
when emit_stub_syms.
* elf32-ppc.h (ppc_elf_select_plt_layout): Update prototype.
ld/
* emultempl/ppc32elf.em (emit_stub_syms): New var.
(ppc_after_open): Pass it to ppc_elf_select_plt_layout.
(PARSE_AND_LIST_PROLOGUE <OPTION_STUBSYMS>): Define.
(PARSE_AND_LIST_LONGOPTS): Add emit-stub-syms.
(PARSE_AND_LIST_OPTIONS): Describe emit-stub-syms.
(PARSE_AND_LIST_OPTIONS): Handle it.

bfd/ChangeLog
bfd/elf32-ppc.c
bfd/elf32-ppc.h
ld/ChangeLog
ld/emultempl/ppc32elf.em

index 1db91701ca95f97d0210f48c790aaddb4cc5c798..8d89bc16bee6cc24eb9718bd3f47b1944b14a570 100644 (file)
@@ -1,3 +1,13 @@
+2005-12-08  Alan Modra  <amodra@bigpond.net.au>
+
+       * elf32-ppc.c (struct ppc_elf_link_hash_table): Add emit_stub_syms.
+       (ppc_elf_select_plt_layout): Add emit_stub_syms param, save to htab.
+       (add_stub_sym): New function.
+       (allocate_dynrelocs): Call add_stub_sym.
+       (ppc_elf_size_dynamic_sections): Emit __glink and __glink_PLTresolve
+       when emit_stub_syms.
+       * elf32-ppc.h (ppc_elf_select_plt_layout): Update prototype.
+
 2005-12-08  Alan Modra  <amodra@bigpond.net.au>
 
        * reloc.c (enum complain_overflow): Correct comments.
index 70d03a3f9966ce38b7bc9720bdf1a14252935afa..5b8c955a6787425503684eb38b98004b01fb44e0 100644 (file)
@@ -2353,6 +2353,9 @@ struct ppc_elf_link_hash_table
   unsigned int new_plt:1;
   unsigned int old_plt:1;
 
+  /* Set if we should emit symbols for stubs.  */
+  unsigned int emit_stub_syms:1;
+
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
 
@@ -3593,7 +3596,8 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 int
 ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
                           struct bfd_link_info *info,
-                          int force_old_plt)
+                          int force_old_plt,
+                          int emit_stub_syms)
 {
   struct ppc_elf_link_hash_table *htab;
   flagword flags;
@@ -3602,6 +3606,8 @@ ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
   if (force_old_plt || !htab->new_plt)
     htab->old_plt = 1;
 
+  htab->emit_stub_syms = emit_stub_syms;
+
   if (htab->is_vxworks)
     {
       /* The VxWorks PLT is a loaded section with contents.  */
@@ -4207,6 +4213,51 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   return TRUE;
 }
 \f
+/* Generate a symbol to mark plt call stubs, of the form
+   xxxxxxxx_plt_call_<callee> where xxxxxxxx is a hex number, usually 0,
+   specifying the addend on the plt relocation, or for -fPIC,
+   xxxxxxxx.got2_plt_call_<callee>.  */
+
+static bfd_boolean
+add_stub_sym (struct plt_entry *ent,
+             struct elf_link_hash_entry *h,
+             struct ppc_elf_link_hash_table *htab)
+{
+  struct elf_link_hash_entry *sh;
+  size_t len1, len2, len3;
+  char *name;
+
+  len1 = strlen (h->root.root.string);
+  len2 = sizeof ("plt_call_") - 1;
+  len3 = 0;
+  if (ent->sec)
+    len3 = strlen (ent->sec->name);
+  name = bfd_malloc (len1 + len2 + len3 + 10);
+  if (name == NULL)
+    return FALSE;
+  sprintf (name, "%08x", (unsigned) ent->addend & 0xffffffff);
+  if (ent->sec)
+    memcpy (name + 8, ent->sec->name, len3);
+  name[len3 + 8] = '_';
+  memcpy (name + len3 + 9, "plt_call_", len2);
+  memcpy (name + len3 + 9 + len2, h->root.root.string, len1 + 1);
+  sh = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE);
+  if (sh == NULL)
+    return FALSE;
+  if (sh->root.type == bfd_link_hash_new)
+    {
+      sh->root.type = bfd_link_hash_defined;
+      sh->root.u.def.section = htab->glink;
+      sh->root.u.def.value = ent->glink_offset;
+      sh->ref_regular = 1;
+      sh->def_regular = 1;
+      sh->ref_regular_nonweak = 1;
+      sh->forced_local = 1;
+      sh->non_elf = 0;
+    }
+  return TRUE;
+}
+
 /* Allocate NEED contiguous space in .got, and return the offset.
    Handles allocation of the got header when crossing 32k.  */
 
@@ -4308,6 +4359,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
                        h->root.u.def.value = glink_offset;
                      }
                    ent->glink_offset = glink_offset;
+
+                   if (htab->emit_stub_syms
+                       && !add_stub_sym (ent, h, htab))
+                     return FALSE;
                  }
                else
                  {
@@ -4747,6 +4802,41 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       /* Pad out to align the start of PLTresolve.  */
       htab->glink->size += -htab->glink->size & 15;
       htab->glink->size += GLINK_PLTRESOLVE;
+
+      if (htab->emit_stub_syms)
+       {
+         struct elf_link_hash_entry *sh;
+         sh = elf_link_hash_lookup (&htab->elf, "__glink",
+                                    TRUE, FALSE, FALSE);
+         if (sh == NULL)
+           return FALSE;
+         if (sh->root.type == bfd_link_hash_new)
+           {
+             sh->root.type = bfd_link_hash_defined;
+             sh->root.u.def.section = htab->glink;
+             sh->root.u.def.value = htab->glink_pltresolve;
+             sh->ref_regular = 1;
+             sh->def_regular = 1;
+             sh->ref_regular_nonweak = 1;
+             sh->forced_local = 1;
+             sh->non_elf = 0;
+           }
+         sh = elf_link_hash_lookup (&htab->elf, "__glink_PLTresolve",
+                                    TRUE, FALSE, FALSE);
+         if (sh == NULL)
+           return FALSE;
+         if (sh->root.type == bfd_link_hash_new)
+           {
+             sh->root.type = bfd_link_hash_defined;
+             sh->root.u.def.section = htab->glink;
+             sh->root.u.def.value = htab->glink->size - GLINK_PLTRESOLVE;
+             sh->ref_regular = 1;
+             sh->def_regular = 1;
+             sh->ref_regular_nonweak = 1;
+             sh->forced_local = 1;
+             sh->non_elf = 0;
+           }
+       }
     }
 
   /* We've now determined the sizes of the various dynamic sections.
index 2bec595392c96cd10937999a924bbefa1ffefed6..5f8f63a38a59605b29c53110add822b7d210023e 100644 (file)
@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
-int ppc_elf_select_plt_layout (bfd *, struct bfd_link_info *, int);
+int ppc_elf_select_plt_layout (bfd *, struct bfd_link_info *, int, int);
 asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *);
 bfd_boolean ppc_elf_tls_optimize (bfd *, struct bfd_link_info *);
 void ppc_elf_set_sdata_syms (bfd *, struct bfd_link_info *);
index d517ddb9fdab8dc0782f67e5e56d71bb980cc96d..ab6b84854a601a77c3bfb50b67eef65d928e564c 100644 (file)
@@ -1,3 +1,12 @@
+2005-12-08  Alan Modra  <amodra@bigpond.net.au>
+
+       * emultempl/ppc32elf.em (emit_stub_syms): New var.
+       (ppc_after_open): Pass it to ppc_elf_select_plt_layout.
+       (PARSE_AND_LIST_PROLOGUE <OPTION_STUBSYMS>): Define.
+       (PARSE_AND_LIST_LONGOPTS): Add emit-stub-syms.
+       (PARSE_AND_LIST_OPTIONS): Describe emit-stub-syms.
+       (PARSE_AND_LIST_OPTIONS): Handle it.
+
 2005-12-08  Alan Modra  <amodra@bigpond.net.au>
 
        * pe-dll.c (build_filler_bfd): Conform error message to standard.
index e4d56de418df1cb69b56f479fbab9a3f8dfb868a..10f91074dfecbc4e192d2c89b41d8de5a0184c5e 100644 (file)
@@ -41,6 +41,9 @@ is_ppc_elf32_vec(const bfd_target * vec)
 /* Whether to run tls optimization.  */
 static int notlsopt = 0;
 
+/* Whether to emit symbols for stubs.  */
+static int emit_stub_syms = 0;
+
 /* Chooses the correct place for .plt and .got.  */
 static int old_plt = 0;
 static int old_got = 0;
@@ -58,7 +61,9 @@ ppc_after_open (void)
       lang_output_section_statement_type *plt_os[2];
       lang_output_section_statement_type *got_os[2];
 
-      new_plt = ppc_elf_select_plt_layout (output_bfd, &link_info, old_plt);
+      emit_stub_syms |= link_info.emitrelocations;
+      new_plt = ppc_elf_select_plt_layout (output_bfd, &link_info, old_plt,
+                                          emit_stub_syms);
       if (new_plt < 0)
        einfo ("%X%P: select_plt_layout problem %E\n");
 
@@ -126,9 +131,11 @@ PARSE_AND_LIST_PROLOGUE='
 #define OPTION_NO_TLS_OPT              301
 #define OPTION_OLD_PLT                 302
 #define OPTION_OLD_GOT                 303
+#define OPTION_STUBSYMS                        304
 '
 
 PARSE_AND_LIST_LONGOPTS='
+  { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS },
   { "no-tls-optimize", no_argument, NULL, OPTION_NO_TLS_OPT },
   { "bss-plt", no_argument, NULL, OPTION_OLD_PLT },
   { "sdata-got", no_argument, NULL, OPTION_OLD_GOT },
@@ -136,6 +143,7 @@ PARSE_AND_LIST_LONGOPTS='
 
 PARSE_AND_LIST_OPTIONS='
   fprintf (file, _("\
+  --emit-stub-syms      Label linker stubs with a symbol.\n\
   --no-tls-optimize     Don'\''t try to optimize TLS accesses.\n\
   --bss-plt             Force old-style BSS PLT.\n\
   --sdata-got           Force GOT location just before .sdata.\n"
@@ -143,6 +151,10 @@ PARSE_AND_LIST_OPTIONS='
 '
 
 PARSE_AND_LIST_ARGS_CASES='
+    case OPTION_STUBSYMS:
+      emit_stub_syms = 1;
+      break;
+
     case OPTION_NO_TLS_OPT:
       notlsopt = 1;
       break;