include/
authorAlan Modra <amodra@gmail.com>
Tue, 1 Feb 2005 01:11:27 +0000 (01:11 +0000)
committerAlan Modra <amodra@gmail.com>
Tue, 1 Feb 2005 01:11:27 +0000 (01:11 +0000)
* bfdlink.h (bfd_link_repair_undef_list): Declare.
bfd/
* elf64-ppc.c (ppc64_elf_check_directives): Move undefs list fixup..
* linker.c (bfd_link_repair_undef_list): ..to new function, but don't
remove anything but new and undefweak.
* elflink.c (_bfd_elf_link_create_dynamic_sections): Override any
existing _DYNAMIC.
(_bfd_elf_create_dynamic_sections): Formatting.
(bfd_elf_record_link_assignment): Call bfd_link_repair_undef_list.
(_bfd_elf_merge_symbol): Don't handle as-needed syms here.
(struct elf_smash_data): New.
(elf_smash_syms): New function.
(elf_link_add_object_symbols): Call elf_smash_syms.  Don't add
unneeded dynamic objects to loaded list.
(elf_link_output_extsym): Don't handle as-needed here.  Strip
bfd_link_hash_new symbols.
* elf32-cris.c (elf_cris_discard_excess_program_dynamics): Don't
delref when dynindx is already -1.
* elf64-alpha.c (elf64_alpha_output_extsym): Strip bfd_link_hash_new
symbols.
* elfxx-mips.c (mips_elf_output_extsym): Likewise.
ld/
* ld.texinfo: Clarify --as-needed operation.

bfd/ChangeLog
bfd/elf32-cris.c
bfd/elf64-alpha.c
bfd/elf64-ppc.c
bfd/elflink.c
bfd/elfxx-mips.c
bfd/linker.c
include/ChangeLog
include/bfdlink.h
ld/ChangeLog
ld/ld.texinfo

index bba5cde6ded456564ebe426d19599c8197e9c99b..fd043090e0e7d022f003d4cb499473df70401e68 100644 (file)
@@ -1,3 +1,25 @@
+2005-02-01  Alan Modra  <amodra@bigpond.net.au>
+
+       * elf64-ppc.c (ppc64_elf_check_directives): Move undefs list fixup..
+       * linker.c (bfd_link_repair_undef_list): ..to new function, but don't
+       remove anything but new and undefweak.
+       * elflink.c (_bfd_elf_link_create_dynamic_sections): Override any
+       existing _DYNAMIC.
+       (_bfd_elf_create_dynamic_sections): Formatting.
+       (bfd_elf_record_link_assignment): Call bfd_link_repair_undef_list.
+       (_bfd_elf_merge_symbol): Don't handle as-needed syms here.
+       (struct elf_smash_data): New.
+       (elf_smash_syms): New function.
+       (elf_link_add_object_symbols): Call elf_smash_syms.  Don't add
+       unneeded dynamic objects to loaded list.
+       (elf_link_output_extsym): Don't handle as-needed here.  Strip
+       bfd_link_hash_new symbols.
+       * elf32-cris.c (elf_cris_discard_excess_program_dynamics): Don't
+       delref when dynindx is already -1.
+       * elf64-alpha.c (elf64_alpha_output_extsym): Strip bfd_link_hash_new
+       symbols.
+       * elfxx-mips.c (mips_elf_output_extsym): Likewise.
+
 2005-02-01  Ben Elliston  <bje@au.ibm.com>
 
        * elfxx-target.h (bfd_elfNN_bfd_discard_group): Redefine.
index 44cae03ede38f06c26ee9a80e498bec6082fe4b0..c80146b1b77c800f599940e296e9b3b2f53c06c8 100644 (file)
@@ -3130,6 +3130,7 @@ elf_cris_discard_excess_program_dynamics (h, inf)
         introduce new problems.  Of course we don't do this if we're
         exporting all dynamic symbols.  */
       if (! info->export_dynamic
+         && h->root.dynindx != -1
          && !h->root.def_dynamic
          && !h->root.ref_dynamic)
        {
index a55ebe6d156087d2f181bf7c22a64695e61aef40..f0c22d9656ce1473acff3495bbb1aa36e84f2657 100644 (file)
@@ -1,5 +1,5 @@
 /* Alpha specific support for 64-bit ELF
-   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@tamu.edu>.
 
@@ -2741,7 +2741,9 @@ elf64_alpha_output_extsym (h, data)
 
   if (h->root.indx == -2)
     strip = FALSE;
-  else if ((h->root.def_dynamic || h->root.ref_dynamic)
+  else if ((h->root.def_dynamic
+           || h->root.ref_dynamic
+           || h->root.root.type == bfd_link_hash_new)
           && !h->root.def_regular
           && !h->root.ref_regular)
     strip = TRUE;
index 2f30dd53d5fd56c654238946a3d6cf00d565617b..c75c34a71364780ade38ac00bba3315089a0294e 100644 (file)
@@ -4066,34 +4066,7 @@ ppc64_elf_check_directives (bfd *abfd ATTRIBUTE_UNUSED,
      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->u.undef.next;
-             h->u.undef.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 u.undef.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->u.undef.next - (char *) h));
-                 break;
-               }
-           }
-         else
-           pun = &h->u.undef.next;
-       }
-
+      bfd_link_repair_undef_list (&htab->elf.root);
       htab->twiddled_syms = 0;
     }
   return TRUE;
index c7dfbd123fc3ebcf0ea87a109bc1ad5d86140b23..9d07c4c1619ad6e349a4fde6ad02637757a8f482 100644 (file)
@@ -210,14 +210,22 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
     return FALSE;
 
   /* The special symbol _DYNAMIC is always set to the start of the
-     .dynamic section.  This call occurs before we have processed the
-     symbols for any dynamic object, so we don't have to worry about
-     overriding a dynamic definition.  We could set _DYNAMIC in a
-     linker script, but we only want to define it if we are, in fact,
-     creating a .dynamic section.  We don't want to define it if there
-     is no .dynamic section, since on some ELF platforms the start up
-     code examines it to decide how to initialize the process.  */
-  bh = NULL;
+     .dynamic section.  We could set _DYNAMIC in a linker script, but we
+     only want to define it if we are, in fact, creating a .dynamic
+     section.  We don't want to define it if there is no .dynamic
+     section, since on some ELF platforms the start up code examines it
+     to decide how to initialize the process.  */
+  h = elf_link_hash_lookup (elf_hash_table (info), "_DYNAMIC",
+                           FALSE, FALSE, FALSE);
+  if (h != NULL)
+    {
+      /* Zap symbol defined in an as-needed lib that wasn't linked.
+        This is a symptom of a larger problem:  Absolute symbols
+        defined in shared libraries can't be overridden, because we
+        lose the link to the bfd which is via the symbol section.  */
+      h->root.type = bfd_link_hash_new;
+    }
+  bh = &h->root;
   if (! (_bfd_generic_link_add_one_symbol
         (info, abfd, "_DYNAMIC", BSF_GLOBAL, s, 0, NULL, FALSE,
          get_elf_backend_data (abfd)->collect, &bh)))
@@ -322,16 +330,16 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
        return FALSE;
 
       /* The .rel[a].bss section holds copy relocs.  This section is not
-     normally needed.  We need to create it here, though, so that the
-     linker will map it to an output section.  We can't just create it
-     only if we need it, because we will not know whether we need it
-     until we have seen all the input files, and the first time the
-     main linker code calls BFD after examining all the input files
-     (size_dynamic_sections) the input sections have already been
-     mapped to the output sections.  If the section turns out not to
-     be needed, we can discard it later.  We will never need this
-     section when generating a shared object, since they do not use
-     copy relocs.  */
+        normally needed.  We need to create it here, though, so that the
+        linker will map it to an output section.  We can't just create it
+        only if we need it, because we will not know whether we need it
+        until we have seen all the input files, and the first time the
+        main linker code calls BFD after examining all the input files
+        (size_dynamic_sections) the input sections have already been
+        mapped to the output sections.  If the section turns out not to
+        be needed, we can discard it later.  We will never need this
+        section when generating a shared object, since they do not use
+        copy relocs.  */
       if (! info->shared)
        {
          s = bfd_make_section (abfd,
@@ -442,15 +450,16 @@ bfd_elf_record_link_assignment (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   /* Since we're defining the symbol, don't let it seem to have not
      been defined.  record_dynamic_symbol and size_dynamic_sections
-     may depend on this.
-     ??? Changing bfd_link_hash_undefined to bfd_link_hash_new (or
-     to bfd_link_hash_undefweak, see linker.c:link_action) runs the risk
-     of some later symbol manipulation setting the symbol back to
-     bfd_link_hash_undefined, and the linker trying to add the symbol to
-     the undefs list twice.  */
+     may depend on this.  */
   if (h->root.type == bfd_link_hash_undefweak
       || h->root.type == bfd_link_hash_undefined)
-    h->root.type = bfd_link_hash_new;
+    {
+      struct elf_link_hash_table *htab = elf_hash_table (info);
+
+      if (h->root.u.undef.next != NULL || htab->root.undefs_tail == &h->root)
+       bfd_link_repair_undef_list (&htab->root);
+      h->root.type = bfd_link_hash_new;
+    }
 
   if (h->root.type == bfd_link_hash_new)
     h->non_elf = 0;
@@ -728,7 +737,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
   int bind;
   bfd *oldbfd;
   bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
-  bfd_boolean newweak, oldweak, old_asneeded;
+  bfd_boolean newweak, oldweak;
 
   *skip = FALSE;
   *override = FALSE;
@@ -858,14 +867,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
   else
     olddef = TRUE;
 
-  /* If the old definition came from an as-needed dynamic library which
-     wasn't found to be needed, treat the sym as undefined.  */
-  old_asneeded = FALSE;
-  if (newdyn
-      && olddyn
-      && (elf_dyn_lib_class (oldbfd) & DYN_AS_NEEDED) != 0)
-    old_asneeded = TRUE;
-
   /* Check TLS symbol.  */
   if ((ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS)
       && ELF_ST_TYPE (sym->st_info) != h->type)
@@ -1068,7 +1069,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
 
   if (olddyn
       && olddef
-      && !old_asneeded
       && h->root.type == bfd_link_hash_defined
       && h->def_dynamic
       && (h->root.u.def.section->flags & SEC_ALLOC) != 0
@@ -1120,7 +1120,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
 
   if (newdyn
       && newdef
-      && ((olddef && !old_asneeded)
+      && (olddef
          || (h->root.type == bfd_link_hash_common
              && (newweak
                  || ELF_ST_TYPE (sym->st_info) == STT_FUNC))))
@@ -1170,7 +1170,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
      symbol is a function or is weak.  */
 
   flip = NULL;
-  if ((!newdyn || old_asneeded)
+  if (!newdyn
       && (newdef
          || (bfd_is_com_section (sec)
              && (oldweak
@@ -2813,6 +2813,69 @@ elf_add_dt_needed_tag (bfd *abfd,
   return 0;
 }
 
+/* Called via elf_link_hash_traverse, elf_smash_syms sets all symbols
+   belonging to NOT_NEEDED to bfd_link_hash_new.  We know there are no
+   references to these symbols.  */
+
+struct elf_smash_syms_data
+{
+  bfd *not_needed;
+  struct elf_link_hash_table *htab;
+  bfd_boolean twiddled;
+};
+
+static bfd_boolean
+elf_smash_syms (struct elf_link_hash_entry *h, void *data)
+{
+  struct elf_smash_syms_data *inf = (struct elf_smash_syms_data *) data;
+  struct bfd_link_hash_entry *bh;
+
+  switch (h->root.type)
+    {
+    default:
+    case bfd_link_hash_new:
+      return TRUE;
+
+    case bfd_link_hash_undefined:
+    case bfd_link_hash_undefweak:
+      if (h->root.u.undef.abfd != inf->not_needed)
+       return TRUE;
+      break;
+
+    case bfd_link_hash_defined:
+    case bfd_link_hash_defweak:
+      if (h->root.u.def.section->owner != inf->not_needed)
+       return TRUE;
+      break;
+
+    case bfd_link_hash_common:
+      if (h->root.u.c.p->section->owner != inf->not_needed)
+       return TRUE;
+      break;
+
+    case bfd_link_hash_warning:
+    case bfd_link_hash_indirect:
+      elf_smash_syms ((struct elf_link_hash_entry *) h->root.u.i.link, data);
+      if (h->root.u.i.link->type != bfd_link_hash_new)
+       return TRUE;
+      if (h->root.u.i.link->u.undef.abfd != inf->not_needed)
+       return TRUE;
+      break;
+    }
+
+  /* Set sym back to newly created state, but keep undefs list pointer.  */
+  bh = h->root.u.undef.next;
+  if (bh != NULL || inf->htab->root.undefs_tail == &h->root)
+    inf->twiddled = TRUE;
+  (*inf->htab->root.table.newfunc) (&h->root.root,
+                                   &inf->htab->root.table,
+                                   h->root.root.string);
+  h->root.u.undef.next = bh;
+  h->root.u.undef.abfd = inf->not_needed;
+  h->non_elf = 0;
+  return TRUE;
+}
+
 /* Sort symbol by value and section.  */
 static int
 elf_sort_symbol (const void *arg1, const void *arg2)
@@ -4031,6 +4094,18 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
     free (isymbuf);
   isymbuf = NULL;
 
+  if (!add_needed)
+    {
+      struct elf_smash_syms_data inf;
+      inf.not_needed = abfd;
+      inf.htab = hash_table;
+      inf.twiddled = FALSE;
+      elf_link_hash_traverse (hash_table, elf_smash_syms, &inf);
+      if (inf.twiddled)
+       bfd_link_repair_undef_list (&hash_table->root);
+      weaks = NULL;
+    }
+
   /* Now set the weakdefs field correctly for all the weak defined
      symbols we found.  The only way to do this is to search all the
      symbols.  Since we only need the information for non functions in
@@ -4263,7 +4338,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
-  if (is_elf_hash_table (hash_table))
+  if (is_elf_hash_table (hash_table) && add_needed)
     {
       /* Add this bfd to the loaded list.  */
       struct elf_link_loaded_list *n;
@@ -6170,7 +6245,6 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
   if (h->root.type == bfd_link_hash_undefined
       && h->ref_dynamic
       && !h->ref_regular
-      && (elf_dyn_lib_class (h->root.u.undef.abfd) & DYN_AS_NEEDED) == 0
       && ! elf_link_check_versioned_symbol (finfo->info, bed, h)
       && finfo->info->unresolved_syms_in_shared_libs != RM_IGNORE)
     {
@@ -6212,7 +6286,8 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
   if (h->indx == -2)
     strip = FALSE;
   else if ((h->def_dynamic
-           || h->ref_dynamic)
+           || h->ref_dynamic
+           || h->root.type == bfd_link_hash_new)
           && !h->def_regular
           && !h->ref_regular)
     strip = TRUE;
index 595c9dfafda2589cfd45a2c704081082b042a01b..be0e7dcb6a100f12d9cbebc75e4c3c37c8cbc2d4 100644 (file)
@@ -1,6 +1,6 @@
 /* MIPS-specific support for ELF
    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004 Free Software Foundation, Inc.
+   2003, 2004, 2005 Free Software Foundation, Inc.
 
    Most of the information added by Ian Lance Taylor, Cygnus Support,
    <ian@cygnus.com>.
@@ -1491,7 +1491,8 @@ mips_elf_output_extsym (struct mips_elf_link_hash_entry *h, void *data)
   if (h->root.indx == -2)
     strip = FALSE;
   else if ((h->root.def_dynamic
-           || h->root.ref_dynamic)
+           || h->root.ref_dynamic
+           || h->root.type == bfd_link_hash_new)
           && !h->root.def_regular
           && !h->root.ref_regular)
     strip = TRUE;
index 5f4e935f8a1d825d86a10d428b0c2c15fe209748..34f66d1e94a8835c01e7c738b98882b6a385c2da 100644 (file)
@@ -1,6 +1,6 @@
 /* linker.c -- BFD linker routines
    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004 Free Software Foundation, Inc.
+   2003, 2004, 2005 Free Software Foundation, Inc.
    Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -623,6 +623,45 @@ bfd_link_add_undef (struct bfd_link_hash_table *table,
     table->undefs = h;
   table->undefs_tail = h;
 }
+
+/* The undefs list was designed so that in normal use we don't need to
+   remove entries.  However, if symbols on the list are changed from
+   bfd_link_hash_undefined to either bfd_link_hash_undefweak or
+   bfd_link_hash_new for some reason, then they must be removed from the
+   list.  Failure to do so might result in the linker attempting to add
+   the symbol to the list again at a later stage.  */
+
+void
+bfd_link_repair_undef_list (struct bfd_link_hash_table *table)
+{
+  struct bfd_link_hash_entry **pun;
+
+  pun = &table->undefs;
+  while (*pun != NULL)
+    {
+      struct bfd_link_hash_entry *h = *pun;
+
+      if (h->type == bfd_link_hash_new
+         || h->type == bfd_link_hash_undefweak)
+       {
+         *pun = h->u.undef.next;
+         h->u.undef.next = NULL;
+         if (h == table->undefs_tail)
+           {
+             if (pun == &table->undefs)
+               table->undefs_tail = NULL;
+             else
+               /* pun points at an u.undef.next field.  Go back to
+                  the start of the link_hash_entry.  */
+               table->undefs_tail = (struct bfd_link_hash_entry *)
+                 ((char *) pun - ((char *) &h->u.undef.next - (char *) h));
+             break;
+           }
+       }
+      else
+       pun = &h->u.undef.next;
+    }
+}
 \f
 /* Routine to create an entry in a generic link hash table.  */
 
index c4fab4bbf49a14f0e3db40400142a72e0db0bc52..43d8ddf8142fd389c6e1dbf4d56275039eee1747 100644 (file)
@@ -1,3 +1,7 @@
+2005-02-01  Alan Modra  <amodra@bigpond.net.au>
+
+       * bfdlink.h (bfd_link_repair_undef_list): Declare.
+
 2005-01-10  Andreas Schwab  <schwab@suse.de>
 
        * dis-asm.h (struct disassemble_info): Add skip_zeroes and
index 9950920a3699b16b667ea52a74ee2de33ea5eeb6..789a38a07db3e8c070c9314803ca7a366b82b130 100644 (file)
@@ -1,6 +1,6 @@
 /* bfdlink.h -- header file for BFD link routines
    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003,
-   2004 Free Software Foundation, Inc.
+   2004, 2005 Free Software Foundation, Inc.
    Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -197,6 +197,10 @@ extern void bfd_link_hash_traverse
 extern void bfd_link_add_undef
   (struct bfd_link_hash_table *, struct bfd_link_hash_entry *);
 
+/* Remove symbols from the undefs list that don't belong there.  */
+extern void bfd_link_repair_undef_list
+  (struct bfd_link_hash_table *table);
+
 struct bfd_sym_chain
 {
   struct bfd_sym_chain *next;
index 324ccaacb0e8b823c184bb23ad330dc34c489a48..b7206d5d62e7a28274ec2e41a7950f49fdea61ac 100644 (file)
@@ -1,3 +1,7 @@
+2005-02-01  Alan Modra  <amodra@bigpond.net.au>
+
+       * ld.texinfo: Clarify --as-needed operation.
+
 2005-01-31  Andrew Cagney  <cagney@gnu.org>
 
        * configure: Regenerate to track ../gettext.m4.
index 4511868081ce4e66ff63d6a21810bae452c8746a..ba73f4231b627ab6e340d324f63513c3ac885e00 100644 (file)
@@ -994,8 +994,9 @@ This option affects ELF DT_NEEDED tags for dynamic libraries mentioned
 on the command line after the @option{--as-needed} option.  Normally,
 the linker will add a DT_NEEDED tag for each dynamic library mentioned
 on the command line, regardless of whether the library is actually
-needed. @option{--as-needed} causes DT_NEEDED tags to only be emitted
-for libraries that satisfy some reference from regular objects.
+needed.  @option{--as-needed} causes DT_NEEDED tags to only be emitted
+for libraries that satisfy some symbol reference from regular objects
+which is undefined at the point that the library was linked.
 @option{--no-as-needed} restores the default behaviour.
 
 @kindex --add-needed