bfd/
authorAlan Modra <amodra@gmail.com>
Tue, 10 Aug 2004 11:23:03 +0000 (11:23 +0000)
committerAlan Modra <amodra@gmail.com>
Tue, 10 Aug 2004 11:23:03 +0000 (11:23 +0000)
* elf64-ppc.c (struct ppc_link_hash_entry): Add was_undefined.
(struct ppc_link_hash_table): Remove no_multi_toc, multi_toc_needed.
Make emit_stub_syms, stub_error and has_14bit_branch bit-fields.
Add twiddled_syms.
(link_hash_newfunc): Init was_undefined.
(add_symbol_adjust): Don't set undefined dot symbols to defweak;
Use undefweak instead.
(ppc64_elf_check_directives): Fix undefs chain.
(ppc64_elf_next_toc_section): Remove no_multi_toc and multi_toc_needed
references.
(ppc64_elf_size_stubs): Adjust for add_symbol_adjust change.
(undo_symbol_twiddle, ppc64_elf_restore_symbols): New functions.
* elf64-ppc.h (ppc64_elf_restore_symbols): Declare.
ld/
* emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Call
ppc64_elf_restore_symbols.

bfd/ChangeLog
bfd/elf64-ppc.c
bfd/elf64-ppc.h
ld/ChangeLog
ld/emultempl/ppc64elf.em

index 5a81642..e3afaa4 100644 (file)
@@ -1,3 +1,19 @@
+2004-08-10  Alan Modra  <amodra@bigpond.net.au>
+
+       * elf64-ppc.c (struct ppc_link_hash_entry): Add was_undefined.
+       (struct ppc_link_hash_table): Remove no_multi_toc, multi_toc_needed.
+       Make emit_stub_syms, stub_error and has_14bit_branch bit-fields.
+       Add twiddled_syms.
+       (link_hash_newfunc): Init was_undefined.
+       (add_symbol_adjust): Don't set undefined dot symbols to defweak;
+       Use undefweak instead.
+       (ppc64_elf_check_directives): Fix undefs chain.
+       (ppc64_elf_next_toc_section): Remove no_multi_toc and multi_toc_needed
+       references.
+       (ppc64_elf_size_stubs): Adjust for add_symbol_adjust change.
+       (undo_symbol_twiddle, ppc64_elf_restore_symbols): New functions.
+       * elf64-ppc.h (ppc64_elf_restore_symbols): Declare.
+
 2004-08-09  Jakub Jelinek  <jakub@redhat.com>
 
        * elf64-x86-64.c (elf64_x86_64_relocate_section): For -fno-pic
index c34bf15..b801887 100644 (file)
@@ -2788,6 +2788,9 @@ struct ppc_link_hash_entry
      globals defined in any opd section.  */
   unsigned int adjust_done:1;
 
+  /* Set if we twiddled this symbol to weak at some stage.  */
+  unsigned int was_undefined:1;
+
   /* Contexts in which symbol is used in the GOT (or TOC).
      TLS_GD .. TLS_EXPLICIT bits are or'd into the mask as the
      corresponding relocs are encountered during check_relocs.
@@ -2836,10 +2839,6 @@ struct ppc_link_hash_table
     bfd_vma toc_off;
   } *stub_group;
 
-  /* Support for multiple toc sections.  */
-  unsigned int no_multi_toc;
-  unsigned int multi_toc_needed;
-
   /* Temp used when calculating TOC pointers.  */
   bfd_vma toc_curr;
 
@@ -2871,14 +2870,17 @@ struct ppc_link_hash_table
   unsigned long stub_count[ppc_stub_plt_call];
 
   /* Set if we should emit symbols for stubs.  */
-  unsigned int emit_stub_syms;
+  unsigned int emit_stub_syms:1;
 
   /* Set on error.  */
-  unsigned int stub_error;
+  unsigned int stub_error:1;
 
   /* Flag set when small branches are detected.  Used to
      select suitable defaults for the stub group size.  */
-  unsigned int has_14bit_branch;
+  unsigned int has_14bit_branch:1;
+
+  /* Temp used by ppc64_elf_check_directives.  */
+  unsigned int twiddled_syms:1;
 
   /* Incremented every time we size stubs.  */
   unsigned int stub_iteration;
@@ -2995,6 +2997,7 @@ link_hash_newfunc (struct bfd_hash_entry *entry,
       eh->is_func = 0;
       eh->is_func_descriptor = 0;
       eh->adjust_done = 0;
+      eh->was_undefined = 0;
       eh->tls_mask = 0;
     }
 
@@ -3560,16 +3563,17 @@ ppc64_elf_archive_symbol_lookup (bfd *abfd,
 }
 
 /* This function satisfies all old ABI object references to ".bar" if a
-   new ABI object defines "bar".  This stops later archive searches from
-   including an object if we already have a function descriptor
-   definition.  It also prevents the linker complaining about undefined
-   symbols.  */
+   new ABI object defines "bar".  Well, at least, undefined dot symbols
+   are made weak.  This stops later archive searches from including an
+   object if we already have a function descriptor definition.  It also
+   prevents the linker complaining about undefined symbols.  */
 
 static bfd_boolean
 add_symbol_adjust (struct elf_link_hash_entry *h, void *inf)
 {
   struct bfd_link_info *info;
   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)
@@ -3584,13 +3588,15 @@ add_symbol_adjust (struct elf_link_hash_entry *h, void *inf)
 
   info = inf;
   htab = ppc_hash_table (info);
-  fdh = get_fdh ((struct ppc_link_hash_entry *) h, htab);
+  eh = (struct ppc_link_hash_entry *) h;
+  fdh = get_fdh (eh, htab);
   if (fdh != NULL)
     {
-      h->root.type = bfd_link_hash_defweak;
-      h->root.u.def.section = &bfd_und_section;
-      h->root.u.def.value = 0;
+      eh->elf.root.type = bfd_link_hash_undefweak;
+      eh->was_undefined = 1;
+      htab->twiddled_syms = 1;
     }
+
   return TRUE;
 }
 
@@ -3598,8 +3604,45 @@ static bfd_boolean
 ppc64_elf_check_directives (bfd *abfd ATTRIBUTE_UNUSED,
                            struct bfd_link_info *info)
 {
-  struct ppc_link_hash_table *htab = ppc_hash_table (info);
+  struct ppc_link_hash_table *htab;
+
+  htab = ppc_hash_table (info);
   elf_link_hash_traverse (&htab->elf, add_symbol_adjust, info);
+
+  /* We need to fix the undefs list for any syms we have twiddled to
+     undef_weak.  */
+  if (htab->twiddled_syms)
+    {
+      struct bfd_link_hash_entry **pun;
+
+      pun = &htab->elf.root.undefs;
+      while (*pun != NULL)
+       {
+         struct bfd_link_hash_entry *h = *pun;
+
+         if (h->type != bfd_link_hash_undefined
+             && h->type != bfd_link_hash_common)
+           {
+             *pun = h->und_next;
+             h->und_next = NULL;
+             if (h == htab->elf.root.undefs_tail)
+               {
+                 if (pun == &htab->elf.root.undefs)
+                   htab->elf.root.undefs_tail = NULL;
+                 else
+                   /* pun points at an und_next field.  Go back to
+                      the start of the link_hash_entry.  */
+                   htab->elf.root.undefs_tail = (struct bfd_link_hash_entry *)
+                     ((char *) pun - ((char *) &h->und_next - (char *) h));
+                 break;
+               }
+           }
+         else
+           pun = &h->und_next;
+       }
+
+      htab->twiddled_syms = 0;
+    }
   return TRUE;
 }
 
@@ -6862,20 +6905,15 @@ void
 ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec)
 {
   struct ppc_link_hash_table *htab = ppc_hash_table (info);
+  bfd_vma addr = isec->output_offset + isec->output_section->vma;
+  bfd_vma off = addr - htab->toc_curr;
 
-  if (!htab->no_multi_toc)
-    {
-      bfd_vma addr = isec->output_offset + isec->output_section->vma;
-      bfd_vma off = addr - htab->toc_curr;
-      if (off + isec->size > 0x10000)
-       {
-         htab->toc_curr = addr;
-         htab->multi_toc_needed = 1;
-       }
-      elf_gp (isec->owner) = (htab->toc_curr
-                             - elf_gp (isec->output_section->owner)
-                             + TOC_BASE_OFF);
-    }
+  if (off + isec->size > 0x10000)
+    htab->toc_curr = addr;
+
+  elf_gp (isec->owner) = (htab->toc_curr
+                         - elf_gp (isec->output_section->owner)
+                         + TOC_BASE_OFF);
 }
 
 /* Called after the last call to the above function.  */
@@ -7222,15 +7260,12 @@ ppc64_elf_size_stubs (bfd *output_bfd,
                  else
                    {
                      sym_value = 0;
-                     /* Recognise an old ABI func code entry sym by
-                        the weird section for a defined sym, and use
-                        the func descriptor sym instead.  */
-                     if (hash->elf.root.type == bfd_link_hash_defweak
-                         && hash->elf.root.u.def.section == &bfd_und_section
+                     /* Recognise an old ABI func code entry sym, and
+                        use the func descriptor sym instead.  */
+                     if (hash->elf.root.type == bfd_link_hash_undefweak
                          && hash->elf.root.root.string[0] == '.'
                          && (fdh = get_fdh (hash, htab)) != NULL)
                        {
-                         sym_sec = NULL;
                          if (fdh->elf.root.type == bfd_link_hash_defined
                              || fdh->elf.root.type == bfd_link_hash_defweak)
                            {
@@ -7239,6 +7274,8 @@ ppc64_elf_size_stubs (bfd *output_bfd,
                              if (sym_sec->output_section != NULL)
                                ok_dest = TRUE;
                            }
+                         else
+                           fdh = NULL;
                        }
                      else if (hash->elf.root.type == bfd_link_hash_defined
                               || hash->elf.root.type == bfd_link_hash_defweak)
@@ -7289,6 +7326,7 @@ ppc64_elf_size_stubs (bfd *output_bfd,
                            {
                              /* Fixup old ABI sym to point at code
                                 entry.  */
+                             hash->elf.root.type = bfd_link_hash_defweak;
                              hash->elf.root.u.def.section = code_sec;
                              hash->elf.root.u.def.value = sym_value;
                            }
@@ -7662,6 +7700,34 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
   return TRUE;
 }
 
+/* This function undoes the changes made by add_symbol_adjust.  */
+
+static bfd_boolean
+undo_symbol_twiddle (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
+{
+  struct ppc_link_hash_entry *eh;
+
+  if (h->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;
+
+  eh = (struct ppc_link_hash_entry *) h;
+  if (eh->elf.root.type != bfd_link_hash_undefweak || !eh->was_undefined)
+    return TRUE;
+
+  eh->elf.root.type = bfd_link_hash_undefined;
+  return TRUE;
+}
+
+void
+ppc64_elf_restore_symbols (struct bfd_link_info *info)
+{
+  struct ppc_link_hash_table *htab = ppc_hash_table (info);
+  elf_link_hash_traverse (&htab->elf, undo_symbol_twiddle, info);
+}
+
 /* The RELOCATE_SECTION function is called by the ELF backend linker
    to handle the relocations for a section.
 
index 171e552..b1f4343 100644 (file)
@@ -40,3 +40,5 @@ bfd_boolean ppc64_elf_size_stubs
    asection *(*) (const char *, asection *), void (*) (void));
 bfd_boolean ppc64_elf_build_stubs
   (bfd_boolean, struct bfd_link_info *, char **);
+void ppc64_elf_restore_symbols
+  (struct bfd_link_info *info);
index 658ea4a..374d8ce 100644 (file)
@@ -1,3 +1,8 @@
+2004-08-10  Alan Modra  <amodra@bigpond.net.au>
+
+       * emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Call
+       ppc64_elf_restore_symbols.
+
 2004-08-09  Alan Modra  <amodra@bigpond.net.au>
 
        * emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Error if
index ffd6a2b..f2d5e6e 100644 (file)
@@ -379,6 +379,8 @@ gld${EMULATION_NAME}_finish (void)
       if (msg != NULL)
        free (msg);
     }
+
+  ppc64_elf_restore_symbols (&link_info);
 }