* elf64-ppc.c (struct ppc64_elf_obj_tdata): Remove "has_dotsym"
authorAlan Modra <amodra@gmail.com>
Tue, 7 Nov 2006 03:24:13 +0000 (03:24 +0000)
committerAlan Modra <amodra@gmail.com>
Tue, 7 Nov 2006 03:24:13 +0000 (03:24 +0000)
and union.
(struct ppc_link_hash_entry): Add "next_dot_sym".
(struct ppc_link_hash_table): Add "dot_syms".
(link_hash_newfunc): Make list of syms starting with a dot.
(ppc_get_stub_entry, adjust_opd_syms): Adjust.
(ppc64_elf_add_symbol_hook): Don't set has_dotsym.
(struct add_symbol_adjust_data): Delete.
(add_symbol_adjust): Simplify params and return.
(ppc64_elf_check_directives): Just process the "dot_syms" lists,
not all syms.

bfd/ChangeLog
bfd/elf64-ppc.c

index 3b97d52c9af9bf6512c2da15c834e792fe8ed705..cd7e8f1497a62f66107c8f1c5d9cb5fcebf808a5 100644 (file)
@@ -1,3 +1,17 @@
+2006-11-07  Alan Modra  <amodra@bigpond.net.au>
+
+       * elf64-ppc.c (struct ppc64_elf_obj_tdata): Remove "has_dotsym"
+       and union.
+       (struct ppc_link_hash_entry): Add "next_dot_sym".
+       (struct ppc_link_hash_table): Add "dot_syms".
+       (link_hash_newfunc): Make list of syms starting with a dot.
+       (ppc_get_stub_entry, adjust_opd_syms): Adjust.
+       (ppc64_elf_add_symbol_hook): Don't set has_dotsym.
+       (struct add_symbol_adjust_data): Delete.
+       (add_symbol_adjust): Simplify params and return.
+       (ppc64_elf_check_directives): Just process the "dot_syms" lists,
+       not all syms.
+
 2006-11-02  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * libbfd-in.h (_bfd_clear_contents): New prototype.
index 52b3e623fa515520cd8edb3cd4359eb72401916d..84a7b5f56b56861e1c1de36a02f05e3a6dc8b9db 100644 (file)
@@ -2377,14 +2377,9 @@ struct ppc64_elf_obj_tdata
   asection *got;
   asection *relgot;
 
-  union {
-    /* Used during garbage collection.  We attach global symbols defined
-       on removed .opd entries to this section so that the sym is removed.  */
-    asection *deleted_section;
-
-    /* Used when adding symbols.  */
-    bfd_boolean has_dotsym;
-  } u;
+  /* Used during garbage collection.  We attach global symbols defined
+     on removed .opd entries to this section so that the sym is removed.  */
+  asection *deleted_section;
 
   /* TLS local dynamic got entry handling.  Suppose for multiple GOT
      sections means we potentially need one of these for each input bfd.  */
@@ -3241,9 +3236,14 @@ struct ppc_link_hash_entry
 {
   struct elf_link_hash_entry elf;
 
-  /* A pointer to the most recently used stub hash entry against this
-     symbol.  */
-  struct ppc_stub_hash_entry *stub_cache;
+  union {
+    /* A pointer to the most recently used stub hash entry against this
+       symbol.  */
+    struct ppc_stub_hash_entry *stub_cache;
+
+    /* A pointer to the next symbol starting with a '.'  */
+    struct ppc_link_hash_entry *next_dot_sym;
+  } u;
 
   /* Track dynamic relocs copied for this symbol.  */
   struct ppc_dyn_relocs *dyn_relocs;
@@ -3321,6 +3321,9 @@ struct ppc_link_hash_table
   /* Highest output section index.  */
   int top_index;
 
+  /* Used when adding symbols.  */
+  struct ppc_link_hash_entry *dot_syms;
+
   /* List of input sections for each output section.  */
   asection **input_list;
 
@@ -3477,9 +3480,34 @@ link_hash_newfunc (struct bfd_hash_entry *entry,
     {
       struct ppc_link_hash_entry *eh = (struct ppc_link_hash_entry *) entry;
 
-      memset (&eh->stub_cache, 0,
+      memset (&eh->u.stub_cache, 0,
              (sizeof (struct ppc_link_hash_entry)
-              - offsetof (struct ppc_link_hash_entry, stub_cache)));
+              - offsetof (struct ppc_link_hash_entry, u.stub_cache)));
+
+      /* When making function calls, old ABI code references function entry
+        points (dot symbols), while new ABI code references the function
+        descriptor symbol.  We need to make any combination of reference and
+        definition work together, without breaking archive linking.
+
+        For a defined function "foo" and an undefined call to "bar":
+        An old object defines "foo" and ".foo", references ".bar" (possibly
+        "bar" too).
+        A new object defines "foo" and references "bar".
+
+        A new object thus has no problem with its undefined symbols being
+        satisfied by definitions in an old object.  On the other hand, the
+        old object won't have ".bar" satisfied by a new object.
+
+        Keep a list of newly added dot-symbols.  */
+
+      if (string[0] == '.')
+       {
+         struct ppc_link_hash_table *htab;
+
+         htab = (struct ppc_link_hash_table *) table;
+         eh->u.next_dot_sym = htab->dot_syms;
+         htab->dot_syms = eh;
+       }
     }
 
   return entry;
@@ -3625,11 +3653,11 @@ ppc_get_stub_entry (const asection *input_section,
      distinguish between them.  */
   id_sec = htab->stub_group[input_section->id].link_sec;
 
-  if (h != NULL && h->stub_cache != NULL
-      && h->stub_cache->h == h
-      && h->stub_cache->id_sec == id_sec)
+  if (h != NULL && h->u.stub_cache != NULL
+      && h->u.stub_cache->h == h
+      && h->u.stub_cache->id_sec == id_sec)
     {
-      stub_entry = h->stub_cache;
+      stub_entry = h->u.stub_cache;
     }
   else
     {
@@ -3642,7 +3670,7 @@ ppc_get_stub_entry (const asection *input_section,
       stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table,
                                         stub_name, FALSE, FALSE);
       if (h != NULL)
-       h->stub_cache = stub_entry;
+       h->u.stub_cache = stub_entry;
 
       free (stub_name);
     }
@@ -4051,29 +4079,14 @@ make_fdh (struct bfd_link_info *info,
   return fdh;
 }
 
-/* Hacks to support old ABI code.
-   When making function calls, old ABI code references function entry
-   points (dot symbols), while new ABI code references the function
-   descriptor symbol.  We need to make any combination of reference and
-   definition work together, without breaking archive linking.
-
-   For a defined function "foo" and an undefined call to "bar":
-   An old object defines "foo" and ".foo", references ".bar" (possibly
-   "bar" too).
-   A new object defines "foo" and references "bar".
-
-   A new object thus has no problem with its undefined symbols being
-   satisfied by definitions in an old object.  On the other hand, the
-   old object won't have ".bar" satisfied by a new object.  */
-
 /* Fix function descriptor symbols defined in .opd sections to be
    function type.  */
 
 static bfd_boolean
-ppc64_elf_add_symbol_hook (bfd *ibfd,
+ppc64_elf_add_symbol_hook (bfd *ibfd ATTRIBUTE_UNUSED,
                           struct bfd_link_info *info ATTRIBUTE_UNUSED,
                           Elf_Internal_Sym *isym,
-                          const char **name,
+                          const char **name ATTRIBUTE_UNUSED,
                           flagword *flags ATTRIBUTE_UNUSED,
                           asection **sec,
                           bfd_vma *value ATTRIBUTE_UNUSED)
@@ -4082,12 +4095,6 @@ ppc64_elf_add_symbol_hook (bfd *ibfd,
       && strcmp (bfd_get_section_name (ibfd, *sec), ".opd") == 0)
     isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC);
 
-  if ((*name)[0] == '.'
-      && ELF_ST_BIND (isym->st_info) == STB_GLOBAL
-      && ELF_ST_TYPE (isym->st_info) < STT_SECTION
-      && is_ppc64_elf_target (ibfd->xvec))
-    ppc64_elf_tdata (ibfd)->u.has_dotsym = 1;
-
   return TRUE;
 }
 
@@ -4136,35 +4143,25 @@ ppc64_elf_archive_symbol_lookup (bfd *abfd,
    most restrictive visibility of the function descriptor and the
    function entry symbol is used.  */
 
-struct add_symbol_adjust_data
-{
-  struct bfd_link_info *info;
-  bfd_boolean ok;
-};
-
 static bfd_boolean
-add_symbol_adjust (struct elf_link_hash_entry *h, void *inf)
+add_symbol_adjust (struct ppc_link_hash_entry *eh, struct bfd_link_info *info)
 {
-  struct add_symbol_adjust_data *data;
   struct ppc_link_hash_table *htab;
-  struct ppc_link_hash_entry *eh;
   struct ppc_link_hash_entry *fdh;
 
-  if (h->root.type == bfd_link_hash_indirect)
+  if (eh->elf.root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+  if (eh->elf.root.type == bfd_link_hash_warning)
+    eh = (struct ppc_link_hash_entry *) eh->elf.root.u.i.link;
 
-  if (h->root.root.string[0] != '.')
-    return TRUE;
+  if (eh->elf.root.root.string[0] != '.')
+    abort ();
 
-  data = inf;
-  htab = ppc_hash_table (data->info);
-  eh = (struct ppc_link_hash_entry *) h;
+  htab = ppc_hash_table (info);
   fdh = get_fdh (eh, htab);
   if (fdh == NULL
-      && !data->info->relocatable
+      && !info->relocatable
       && (eh->elf.root.type == bfd_link_hash_undefined
          || eh->elf.root.type == bfd_link_hash_undefweak)
       && eh->elf.ref_regular)
@@ -4172,9 +4169,9 @@ add_symbol_adjust (struct elf_link_hash_entry *h, void *inf)
       /* Make an undefweak function descriptor sym, which is enough to
         pull in an --as-needed shared lib, but won't cause link
         errors.  Archives are handled elsewhere.  */
-      fdh = make_fdh (data->info, eh);
+      fdh = make_fdh (info, eh);
       if (fdh == NULL)
-       data->ok = FALSE;
+       return FALSE;
       else
        fdh->elf.ref_regular = 1;
     }
@@ -4200,26 +4197,37 @@ add_symbol_adjust (struct elf_link_hash_entry *h, void *inf)
   return TRUE;
 }
 
+/* Process list of dot-symbols we made in link_hash_newfunc.  */
+
 static bfd_boolean
-ppc64_elf_check_directives (bfd *abfd, struct bfd_link_info *info)
+ppc64_elf_check_directives (bfd *ibfd, struct bfd_link_info *info)
 {
   struct ppc_link_hash_table *htab;
-  struct add_symbol_adjust_data data;
-
-  if (!is_ppc64_elf_target (abfd->xvec))
-    return TRUE;
-
-  if (!ppc64_elf_tdata (abfd)->u.has_dotsym)
-    return TRUE;
-  ppc64_elf_tdata (abfd)->u.deleted_section = NULL;
+  struct ppc_link_hash_entry **p, *eh;
 
   htab = ppc_hash_table (info);
   if (!is_ppc64_elf_target (htab->elf.root.creator))
     return TRUE;
 
-  data.info = info;
-  data.ok = TRUE;
-  elf_link_hash_traverse (&htab->elf, add_symbol_adjust, &data);
+  if (is_ppc64_elf_target (ibfd->xvec))
+    {
+      p = &htab->dot_syms;
+      while ((eh = *p) != NULL)
+       {
+         *p = NULL;
+         if (!add_symbol_adjust (eh, info))
+           return FALSE;
+         p = &eh->u.next_dot_sym;
+       }
+    }
+
+  /* Clear the list for non-ppc64 input files.  */
+  p = &htab->dot_syms;
+  while ((eh = *p) != NULL)
+    {
+      *p = NULL;
+      p = &eh->u.next_dot_sym;
+    }
 
   /* We need to fix the undefs list for any syms we have twiddled to
      undef_weak.  */
@@ -4228,7 +4236,7 @@ ppc64_elf_check_directives (bfd *abfd, struct bfd_link_info *info)
       bfd_link_repair_undef_list (&htab->elf.root);
       htab->twiddled_syms = 0;
     }
-  return data.ok;
+  return TRUE;
 }
 
 static bfd_boolean
@@ -6103,13 +6111,13 @@ adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
       if (adjust == -1)
        {
          /* This entry has been deleted.  */
-         asection *dsec = ppc64_elf_tdata (sym_sec->owner)->u.deleted_section;
+         asection *dsec = ppc64_elf_tdata (sym_sec->owner)->deleted_section;
          if (dsec == NULL)
            {
              for (dsec = sym_sec->owner->sections; dsec; dsec = dsec->next)
                if (elf_discarded_section (dsec))
                  {
-                   ppc64_elf_tdata (sym_sec->owner)->u.deleted_section = dsec;
+                   ppc64_elf_tdata (sym_sec->owner)->deleted_section = dsec;
                    break;
                  }
            }