bfd/
authorAlan Modra <amodra@gmail.com>
Thu, 18 Mar 2004 12:50:20 +0000 (12:50 +0000)
committerAlan Modra <amodra@gmail.com>
Thu, 18 Mar 2004 12:50:20 +0000 (12:50 +0000)
* elf-bfd.h (struct elf_obj_tdata): Delete dt_soname field.  Add
dyn_lib_class field.  Rearrange for better packing.
(elf_dt_soname): Delete.
(elf_dyn_lib_class): Define.
* elf.c (bfd_elf_set_dt_needed_name): Update comment.
(bfd_elf_set_dt_needed_soname): Delete.
(bfd_elf_set_dyn_lib_class): New function.
* elflink.h (add_dt_needed_tag): New function.  Split out from..
(elf_link_add_object_symbols): ..here.  Rename "name" to "soname".
Use elf_dyn_lib_class to set dt_needed and add_needed.  Move fallback
initialization of soname.
(elf_link_check_versioned_symbol): Test elf_dyn_lib_class instead of
elf_dt_soname.
* bfd-in.h (enum dynamic_lib_link_class): New.
(bfd_elf_set_dt_needed_soname): Delete.
(bfd_elf_set_dyn_lib_class): Declare.
* bfd-in2.h: Regenerate.
ld/
* ld.texinfo: Add --as-needed doco.
* ldmain.c (as_needed): New global var.
* ldmain.h (as_needed): Declare.
* lexsup.c (option_values): Add OPTION_AS_NEEDED and
OPTION_NO_AS_NEEDED.
(ld_options): Likewise.
(parse_args): Handle them.
* ldlang.h (lang_input_statement_type): Add as_needed field.
* ldlang.c (new_afile): Set p->as_needed.
* emultempl/elf32.em (gld${EMULATION_NAME}_load_symbols): New function.
(gld${EMULATION_NAME}_try_needed): Use bfd_elf_set_dyn_lib_class.
(ld_${EMULATION_NAME}_emulation): Set LDEMUL_RECOGNIZED_FILE entry.

* ldlang.c (open_input_bfds): Remove useless cast.
(lang_do_assignments_1): Likewise.
(lang_for_each_input_section): Delete.

14 files changed:
bfd/ChangeLog
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/elf-bfd.h
bfd/elf.c
bfd/elflink.h
ld/ChangeLog
ld/emultempl/elf32.em
ld/ld.texinfo
ld/ldlang.c
ld/ldlang.h
ld/ldmain.c
ld/ldmain.h
ld/lexsup.c

index 2d41bb8..eb91f6e 100644 (file)
@@ -1,5 +1,23 @@
 2004-03-18  Alan Modra  <amodra@bigpond.net.au>
 
+       * elf-bfd.h (struct elf_obj_tdata): Delete dt_soname field.  Add
+       dyn_lib_class field.  Rearrange for better packing.
+       (elf_dt_soname): Delete.
+       (elf_dyn_lib_class): Define.
+       * elf.c (bfd_elf_set_dt_needed_name): Update comment.
+       (bfd_elf_set_dt_needed_soname): Delete.
+       (bfd_elf_set_dyn_lib_class): New function.
+       * elflink.h (add_dt_needed_tag): New function.  Split out from..
+       (elf_link_add_object_symbols): ..here.  Rename "name" to "soname".
+       Use elf_dyn_lib_class to set dt_needed and add_needed.  Move fallback
+       initialization of soname.
+       (elf_link_check_versioned_symbol): Test elf_dyn_lib_class instead of
+       elf_dt_soname.
+       * bfd-in.h (enum dynamic_lib_link_class): New.
+       (bfd_elf_set_dt_needed_soname): Delete.
+       (bfd_elf_set_dyn_lib_class): Declare.
+       * bfd-in2.h: Regenerate.
+
        * elflink.c (_bfd_elf_merge_symbol): Rewrite weak symbol handling.
        (_bfd_elf_add_default_symbol): Remove indirect BFD_ASSERTs.
        * elflink.h (elf_link_add_object_symbols): Don't clear dt_needed in
index 37df5f2..fedcb37 100644 (file)
@@ -599,6 +599,12 @@ struct bfd_link_needed_list
   const char *name;
 };
 
+enum dynamic_lib_link_class {
+  DYN_NORMAL = 0,
+  DYN_AS_NEEDED = 1,
+  DYN_DT_NEEDED = 2
+};
+
 extern bfd_boolean bfd_elf_record_link_assignment
   (bfd *, struct bfd_link_info *, const char *, bfd_boolean);
 extern struct bfd_link_needed_list *bfd_elf_get_needed_list
@@ -613,10 +619,10 @@ extern bfd_boolean bfd_elf64_size_dynamic_sections
    struct bfd_link_info *, struct bfd_section **, struct bfd_elf_version_tree *);
 extern void bfd_elf_set_dt_needed_name
   (bfd *, const char *);
-extern void bfd_elf_set_dt_needed_soname
-  (bfd *, const char *);
 extern const char *bfd_elf_get_dt_soname
   (bfd *);
+extern void bfd_elf_set_dyn_lib_class
+  (bfd *, int);
 extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
   (bfd *, struct bfd_link_info *);
 extern bfd_boolean bfd_elf32_discard_info
index c723731..5e53956 100644 (file)
@@ -606,6 +606,12 @@ struct bfd_link_needed_list
   const char *name;
 };
 
+enum dynamic_lib_link_class {
+  DYN_NORMAL = 0,
+  DYN_AS_NEEDED = 1,
+  DYN_DT_NEEDED = 2
+};
+
 extern bfd_boolean bfd_elf_record_link_assignment
   (bfd *, struct bfd_link_info *, const char *, bfd_boolean);
 extern struct bfd_link_needed_list *bfd_elf_get_needed_list
@@ -620,10 +626,10 @@ extern bfd_boolean bfd_elf64_size_dynamic_sections
    struct bfd_link_info *, struct bfd_section **, struct bfd_elf_version_tree *);
 extern void bfd_elf_set_dt_needed_name
   (bfd *, const char *);
-extern void bfd_elf_set_dt_needed_soname
-  (bfd *, const char *);
 extern const char *bfd_elf_get_dt_soname
   (bfd *);
+extern void bfd_elf_set_dyn_lib_class
+  (bfd *, int);
 extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
   (bfd *, struct bfd_link_info *);
 extern bfd_boolean bfd_elf32_discard_info
index 5f4bcd8..a90024f 100644 (file)
@@ -1,6 +1,6 @@
 /* BFD back-end data structures for ELF files.
    Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003 Free Software Foundation, Inc.
+   2002, 2003, 2004 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -1132,9 +1132,6 @@ struct elf_obj_tdata
   bfd_vma gp;                          /* The gp value */
   unsigned int gp_size;                        /* The gp size */
 
-  Elf_Internal_Shdr **group_sect_ptr;
-  int num_group;
-
   /* Information grabbed from an elf core file.  */
   int core_signal;
   int core_pid;
@@ -1142,10 +1139,6 @@ struct elf_obj_tdata
   char* core_program;
   char* core_command;
 
-  /* This is set to TRUE if the object was created by the backend
-     linker.  */
-  bfd_boolean linker;
-
   /* A mapping from external symbols to entries in the linker hash
      table, used when linking.  This is indexed by the symbol index
      minus the sh_info field of the symbol table header.  */
@@ -1171,21 +1164,6 @@ struct elf_obj_tdata
      one.  */
   const char *dt_name;
 
-  /* When a reference in a regular object is resolved by a shared
-     object is loaded into via the DT_NEEDED entries by the linker
-     ELF emulation code, we need to add the shared object to the
-     DT_NEEDED list of the resulting binary to indicate the dependency
-     as if the -l option is passed to the linker. This field holds the
-     name of the loaded shared object.  */
-  const char *dt_soname;
-
-  /* Irix 5 often screws up the symbol table, sorting local symbols
-     after global symbols.  This flag is set if the symbol table in
-     this BFD appears to be screwed up.  If it is, we ignore the
-     sh_info field in the symbol table header, and always read all the
-     symbols.  */
-  bfd_boolean bad_symtab;
-
   /* Records the result of `get_program_header_size'.  */
   bfd_size_type program_header_size;
 
@@ -1213,8 +1191,8 @@ struct elf_obj_tdata
      created.  */
   asection *eh_frame_hdr;
 
-  /* Used to determine if the e_flags field has been initialized */
-  bfd_boolean flags_init;
+  Elf_Internal_Shdr **group_sect_ptr;
+  int num_group;
 
   /* Number of symbol version definitions we are about to emit.  */
   unsigned int cverdefs;
@@ -1237,6 +1215,25 @@ struct elf_obj_tdata
   asymbol *elf_text_symbol;
   asection *elf_data_section;
   asection *elf_text_section;
+
+  /* Whether a dyanmic object was specified normally on the linker
+     command line, or was specified when --as-needed was in effect,
+     or was found via a DT_NEEDED entry.  */
+  enum dynamic_lib_link_class dyn_lib_class;
+
+  /* This is set to TRUE if the object was created by the backend
+     linker.  */
+  bfd_boolean linker;
+
+  /* Irix 5 often screws up the symbol table, sorting local symbols
+     after global symbols.  This flag is set if the symbol table in
+     this BFD appears to be screwed up.  If it is, we ignore the
+     sh_info field in the symbol table header, and always read all the
+     symbols.  */
+  bfd_boolean bad_symtab;
+
+  /* Used to determine if the e_flags field has been initialized */
+  bfd_boolean flags_init;
 };
 
 #define elf_tdata(bfd)         ((bfd) -> tdata.elf_obj_data)
@@ -1263,7 +1260,7 @@ struct elf_obj_tdata
 #define elf_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got.offsets)
 #define elf_local_got_ents(bfd) (elf_tdata(bfd) -> local_got.ents)
 #define elf_dt_name(bfd)       (elf_tdata(bfd) -> dt_name)
-#define elf_dt_soname(bfd)     (elf_tdata(bfd) -> dt_soname)
+#define elf_dyn_lib_class(bfd) (elf_tdata(bfd) -> dyn_lib_class)
 #define elf_bad_symtab(bfd)    (elf_tdata(bfd) -> bad_symtab)
 #define elf_flags_init(bfd)    (elf_tdata(bfd) -> flags_init)
 \f
index 33b58f5..afde13e 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1479,8 +1479,7 @@ _bfd_elf_link_hash_table_create (bfd *abfd)
 
 /* This is a hook for the ELF emulation code in the generic linker to
    tell the backend linker what file name to use for the DT_NEEDED
-   entry for a dynamic object.  The generic linker passes name as an
-   empty string to indicate that no DT_NEEDED entry should be made.  */
+   entry for a dynamic object.  */
 
 void
 bfd_elf_set_dt_needed_name (bfd *abfd, const char *name)
@@ -1491,11 +1490,11 @@ bfd_elf_set_dt_needed_name (bfd *abfd, const char *name)
 }
 
 void
-bfd_elf_set_dt_needed_soname (bfd *abfd, const char *name)
+bfd_elf_set_dyn_lib_class (bfd *abfd, int lib_class)
 {
   if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
       && bfd_get_format (abfd) == bfd_object)
-    elf_dt_soname (abfd) = name;
+    elf_dyn_lib_class (abfd) = lib_class;
 }
 
 /* Get the list of DT_NEEDED entries for a link.  This is a hook for
index ec20e75..82a2b3b 100644 (file)
@@ -68,6 +68,59 @@ sort_symbol (const void *arg1, const void *arg2)
     }
 }
 
+/* Add a DT_NEEDED entry for this dynamic object.  Returns -1 on error,
+   1 if a DT_NEEDED tag already exists, and 0 on success.  */
+
+static int
+add_dt_needed_tag (struct bfd_link_info *info, const char *soname,
+                  bfd_boolean do_it)
+{
+  struct elf_link_hash_table *hash_table;
+  bfd_size_type oldsize;
+  bfd_size_type strindex;
+
+  hash_table = elf_hash_table (info);
+  oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
+  strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE);
+  if (strindex == (bfd_size_type) -1)
+    return -1;
+
+  if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr))
+    {
+      asection *sdyn;
+      Elf_External_Dyn *dyncon, *dynconend;
+
+      sdyn = bfd_get_section_by_name (hash_table->dynobj, ".dynamic");
+      BFD_ASSERT (sdyn != NULL);
+
+      dyncon = (Elf_External_Dyn *) sdyn->contents;
+      dynconend = (Elf_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+      for (; dyncon < dynconend; dyncon++)
+       {
+         Elf_Internal_Dyn dyn;
+
+         elf_swap_dyn_in (hash_table->dynobj, dyncon, & dyn);
+         if (dyn.d_tag == DT_NEEDED
+             && dyn.d_un.d_val == strindex)
+           {
+             _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
+             return 1;
+           }
+       }
+    }
+
+  if (do_it)
+    {
+      if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
+       return -1;
+    }
+  else
+    /* We were just checking for existence of the tag.  */
+    _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
+
+  return 0;
+}
+
 /* Add symbols from an ELF object file to the linker hash table.  */
 
 static bfd_boolean
@@ -202,7 +255,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
     }
 
   dt_needed = FALSE;
-  add_needed = FALSE;
+  add_needed = TRUE;
   if (! dynamic)
     {
       /* If we are creating a shared library, create all the dynamic
@@ -224,10 +277,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   else
     {
       asection *s;
-      const char *name;
-      bfd_size_type oldsize;
-      bfd_size_type strindex;
+      const char *soname = NULL;
       struct bfd_link_needed_list *rpath = NULL, *runpath = NULL;
+      int ret;
 
       /* ld --just-symbols and dynamic objects don't mix very well.
         Test for --just-symbols by looking at info set up by
@@ -236,26 +288,22 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
          && s->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
        goto error_return;
 
-      /* Find the name to use in a DT_NEEDED entry that refers to this
-        object.  If the object has a DT_SONAME entry, we use it.
-        Otherwise, if the generic linker stuck something in
-        elf_dt_name, we use that.  Otherwise, we just use the file
-        name.  If the generic linker put a null string into
-        elf_dt_name, we don't make a DT_NEEDED entry at all, even if
-        there is a DT_SONAME entry.  */
-      add_needed = TRUE;
-      name = bfd_get_filename (abfd);
-      if (elf_dt_name (abfd) != NULL)
+      /* If this dynamic lib was specified on the command line with
+        --as-needed in effect, then we don't want to add a DT_NEEDED
+        tag unless the lib is actually used.
+        For libs brought in by another lib's DT_NEEDED we do the same,
+        and also modify handling of weak syms.  */
+      switch elf_dyn_lib_class (abfd)
        {
-         name = elf_dt_name (abfd);
-         if (*name == '\0')
-           {
-             if (elf_dt_soname (abfd) != NULL)
-               dt_needed = TRUE;
-
-             add_needed = FALSE;
-           }
+       case DYN_NORMAL:
+         break;
+       case DYN_DT_NEEDED:
+         dt_needed = TRUE;
+         /* Fall thru */
+       case DYN_AS_NEEDED:
+         add_needed = FALSE;
        }
+
       s = bfd_get_section_by_name (abfd, ".dynamic");
       if (s != NULL)
        {
@@ -287,8 +335,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
              if (dyn.d_tag == DT_SONAME)
                {
                  unsigned int tagv = dyn.d_un.d_val;
-                 name = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
-                 if (name == NULL)
+                 soname = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
+                 if (soname == NULL)
                    goto error_free_dyn;
                }
              if (dyn.d_tag == DT_NEEDED)
@@ -405,53 +453,31 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       if (! _bfd_elf_link_create_dynamic_sections (abfd, info))
        goto error_return;
 
-      if (add_needed)
+      /* Find the name to use in a DT_NEEDED entry that refers to this
+        object.  If the object has a DT_SONAME entry, we use it.
+        Otherwise, if the generic linker stuck something in
+        elf_dt_name, we use that.  Otherwise, we just use the file
+        name.  */
+      if (soname == NULL || *soname == '\0')
        {
-         /* Add a DT_NEEDED entry for this dynamic object.  */
-         oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
-         strindex = _bfd_elf_strtab_add (hash_table->dynstr, name, FALSE);
-         if (strindex == (bfd_size_type) -1)
-           goto error_return;
-
-         if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr))
-           {
-             asection *sdyn;
-             Elf_External_Dyn *dyncon, *dynconend;
-
-             /* The hash table size did not change, which means that
-                the dynamic object name was already entered.  If we
-                have already included this dynamic object in the
-                link, just ignore it.  There is no reason to include
-                a particular dynamic object more than once.  */
-             sdyn = bfd_get_section_by_name (hash_table->dynobj, ".dynamic");
-             BFD_ASSERT (sdyn != NULL);
-
-             dyncon = (Elf_External_Dyn *) sdyn->contents;
-             dynconend = (Elf_External_Dyn *) (sdyn->contents +
-                                               sdyn->_raw_size);
-             for (; dyncon < dynconend; dyncon++)
-               {
-                 Elf_Internal_Dyn dyn;
+         soname = elf_dt_name (abfd);
+         if (soname == NULL || *soname == '\0')
+           soname = bfd_get_filename (abfd);
+       }
 
-                 elf_swap_dyn_in (hash_table->dynobj, dyncon, & dyn);
-                 if (dyn.d_tag == DT_NEEDED
-                     && dyn.d_un.d_val == strindex)
-                   {
-                     _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
-                     return TRUE;
-                   }
-               }
-           }
+      /* Save the SONAME because sometimes the linker emulation code
+        will need to know it.  */
+      elf_dt_name (abfd) = soname;
 
-         if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
-           goto error_return;
-       }
+      ret = add_dt_needed_tag (info, soname, add_needed);
+      if (ret < 0)
+       goto error_return;
 
-      /* Save the SONAME, if there is one, because sometimes the
-        linker emulation code will need to know it.  */
-      if (*name == '\0')
-       name = basename (bfd_get_filename (abfd));
-      elf_dt_name (abfd) = name;
+      /* If we have already included this dynamic object in the
+        link, just ignore it.  There is no reason to include a
+        particular dynamic object more than once.  */
+      if (ret > 0)
+       return TRUE;
     }
 
   /* If this is a dynamic object, we always link against the .dynsym
@@ -1051,49 +1077,21 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
                break;
              }
 
-         if (dt_needed && !add_needed && definition
+         if (!add_needed && definition
              && (h->elf_link_hash_flags
                  & ELF_LINK_HASH_REF_REGULAR) != 0)
            {
-             bfd_size_type oldsize;
-             bfd_size_type strindex;
-
-             /* The symbol from a DT_NEEDED object is referenced from
-                the regular object to create a dynamic executable. We
-                have to make sure there is a DT_NEEDED entry for it.  */
+             int ret;
 
+             /* A symbol from a library loaded via DT_NEEDED of some
+                other library is referenced by a regular object.
+                Add a DT_NEEDED entry for it.  */
              add_needed = TRUE;
-             oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
-             strindex = _bfd_elf_strtab_add (hash_table->dynstr,
-                                             elf_dt_soname (abfd), FALSE);
-             if (strindex == (bfd_size_type) -1)
+             ret = add_dt_needed_tag (info, elf_dt_name (abfd), add_needed);
+             if (ret < 0)
                goto error_free_vers;
 
-             if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr))
-               {
-                 asection *sdyn;
-                 Elf_External_Dyn *dyncon, *dynconend;
-
-                 sdyn = bfd_get_section_by_name (hash_table->dynobj,
-                                                 ".dynamic");
-                 BFD_ASSERT (sdyn != NULL);
-
-                 dyncon = (Elf_External_Dyn *) sdyn->contents;
-                 dynconend = (Elf_External_Dyn *) (sdyn->contents +
-                                                   sdyn->_raw_size);
-                 for (; dyncon < dynconend; dyncon++)
-                   {
-                     Elf_Internal_Dyn dyn;
-
-                     elf_swap_dyn_in (hash_table->dynobj,
-                                      dyncon, &dyn);
-                     BFD_ASSERT (dyn.d_tag != DT_NEEDED ||
-                                 dyn.d_un.d_val != strindex);
-                   }
-               }
-
-             if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
-               goto error_free_vers;
+             BFD_ASSERT (ret == 0);
            }
        }
     }
@@ -3950,7 +3948,8 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
     case bfd_link_hash_undefined:
     case bfd_link_hash_undefweak:
       abfd = h->root.u.undef.abfd;
-      if ((abfd->flags & DYNAMIC) == 0 || elf_dt_soname (abfd) == NULL)
+      if ((abfd->flags & DYNAMIC) == 0
+         || elf_dyn_lib_class (abfd) != DYN_DT_NEEDED)
        return FALSE;
       break;
 
index 0b3407f..3c4940c 100644 (file)
@@ -1,3 +1,22 @@
+2004-03-18  Alan Modra  <amodra@bigpond.net.au>
+
+       * ld.texinfo: Add --as-needed doco.
+       * ldmain.c (as_needed): New global var.
+       * ldmain.h (as_needed): Declare.
+       * lexsup.c (option_values): Add OPTION_AS_NEEDED and
+       OPTION_NO_AS_NEEDED.
+       (ld_options): Likewise.
+       (parse_args): Handle them.
+       * ldlang.h (lang_input_statement_type): Add as_needed field.
+       * ldlang.c (new_afile): Set p->as_needed.
+       * emultempl/elf32.em (gld${EMULATION_NAME}_load_symbols): New function.
+       (gld${EMULATION_NAME}_try_needed): Use bfd_elf_set_dyn_lib_class.
+       (ld_${EMULATION_NAME}_emulation): Set LDEMUL_RECOGNIZED_FILE entry.
+
+       * ldlang.c (open_input_bfds): Remove useless cast.
+       (lang_do_assignments_1): Likewise.
+       (lang_for_each_input_section): Delete.
+
 2004-03-17  Ralf Corsepius <corsepiu@faw.uni-ulm.de>
 
        * configure.tgt: Switch sh-*-rtems* to ELF.  Add sh-*-rtemscoff*.
index 45749e7..e95b3a9 100644 (file)
@@ -89,6 +89,28 @@ gld${EMULATION_NAME}_before_parse (void)
 EOF
 fi
 
+if test x"$LDEMUL_RECOGNIZED_FILE" != xgld"${EMULATION_NAME}"_load_symbols; then
+cat >>e${EMULATION_NAME}.c <<EOF
+/* Handle as_needed DT_NEEDED.  */
+
+static bfd_boolean
+gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *entry)
+{
+  if (!entry->as_needed
+      || (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0)
+    return FALSE;
+
+  /* Tell the ELF linker that we don't want the output file to have a
+     DT_NEEDED entry for this file, unless it is used to resolve
+     references in a regular object.  */
+  bfd_elf_set_dyn_lib_class (entry->the_bfd, DYN_AS_NEEDED);
+
+  /* Continue on with normal load_symbols processing.  */
+  return FALSE;
+}
+EOF
+fi
+
 cat >>e${EMULATION_NAME}.c <<EOF
 
 /* These variables are required to pass information back and forth
@@ -336,14 +358,13 @@ cat >>e${EMULATION_NAME}.c <<EOF
       return TRUE;
     }
 
-  /* Tell the ELF backend that we don't want the output file to have a
-     DT_NEEDED entry for this file.  */
-  bfd_elf_set_dt_needed_name (abfd, "");
+  /* Specify the soname to use.  */
+  bfd_elf_set_dt_needed_name (abfd, soname);
 
-  /* Tell the ELF backend that the output file needs a DT_NEEDED
-     entry for this file if it is used to resolve the reference in
-     a regular object.  */
-  bfd_elf_set_dt_needed_soname (abfd, soname);
+  /* Tell the ELF linker that we don't want the output file to have a
+     DT_NEEDED entry for this file, unless it is used to resolve
+     references in a regular object.  */
+  bfd_elf_set_dyn_lib_class (abfd, DYN_DT_NEEDED);
 
   /* Add this file into the symbol table.  */
   if (! bfd_link_add_symbols (abfd, &link_info))
@@ -1752,7 +1773,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   gld${EMULATION_NAME}_handle_option,
   ${LDEMUL_UNRECOGNIZED_FILE-NULL},
   ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
-  ${LDEMUL_RECOGNIZED_FILE-NULL},
+  ${LDEMUL_RECOGNIZED_FILE-gld${EMULATION_NAME}_load_symbols},
   ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
   ${LDEMUL_NEW_VERS_PATTERN-NULL}
 };
index 9710f4f..4310c12 100644 (file)
@@ -972,6 +972,18 @@ behaviour from release 2.14 onwards is to reject such input files, and
 so the @samp{--accept-unknown-input-arch} option has been added to
 restore the old behaviour.
 
+@kindex --as-needed
+@kindex --no-as-needed
+@item --as-needed
+@itemx --no-as-needed
+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.
+@option{--no-as-needed} restores the default behaviour.
+
 @kindex -assert @var{keyword}
 @item -assert @var{keyword}
 This option is ignored for SunOS compatibility.
index 3855998..0c08601 100644 (file)
@@ -445,6 +445,7 @@ new_afile (const char *name,
   p->next = NULL;
   p->symbol_count = 0;
   p->dynamic = config.dynamic_link;
+  p->as_needed = as_needed;
   p->whole_archive = whole_archive;
   p->loaded = FALSE;
   lang_statement_append (&input_file_chain,
@@ -1842,7 +1843,7 @@ open_input_bfds (lang_statement_union_type *s, bfd_boolean force)
          /* Maybe we should load the file's symbols.  */
          if (s->wild_statement.filename
              && ! wildcardp (s->wild_statement.filename))
-           (void) lookup_name (s->wild_statement.filename);
+           lookup_name (s->wild_statement.filename);
          open_input_bfds (s->wild_statement.children.head, force);
          break;
        case lang_group_statement_enum:
@@ -3348,8 +3349,7 @@ lang_do_assignments_1
            if (os->bfd_section != NULL)
              {
                dot = os->bfd_section->vma;
-               (void) lang_do_assignments_1 (os->children.head, os,
-                                             os->fill, dot);
+               lang_do_assignments_1 (os->children.head, os, os->fill, dot);
                dot = (os->bfd_section->vma
                       + TO_ADDR (os->bfd_section->_raw_size));
 
@@ -3938,24 +3938,6 @@ lang_for_each_file (void (*func) (lang_input_statement_type *))
     }
 }
 
-#if 0
-
-/* Not used.  */
-
-void
-lang_for_each_input_section (void (*func) (bfd *ab, asection *as))
-{
-  LANG_FOR_EACH_INPUT_STATEMENT (f)
-    {
-      asection *s;
-
-      for (s = f->the_bfd->sections; s != NULL; s = s->next)
-       func (f->the_bfd, s);
-    }
-}
-
-#endif
-
 void
 ldlang_add_file (lang_input_statement_type *entry)
 {
index d518398..649fea1 100644 (file)
@@ -264,6 +264,10 @@ typedef struct lang_input_statement_struct
   /* Whether to search for this entry as a dynamic archive.  */
   bfd_boolean dynamic;
 
+  /* Whether this entry should cause a DT_NEEDED tag only when
+     satisfying references from regular files, or always.  */
+  bfd_boolean as_needed;
+
   /* Whether to include the entire contents of an archive.  */
   bfd_boolean whole_archive;
 
index 88b5c75..d0e0b12 100644 (file)
@@ -1,6 +1,6 @@
 /* Main program of GNU linker.
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003
+   2002, 2003, 2004
    Free Software Foundation, Inc.
    Written by Steve Chamberlain steve@cygnus.com
 
@@ -93,6 +93,10 @@ bfd_boolean version_printed;
 /* Nonzero means link in every member of an archive.  */
 bfd_boolean whole_archive;
 
+/* Nonzero means create DT_NEEDED entries only if a dynamic library
+   actually satisfies some reference in a regular object.  */
+bfd_boolean as_needed;
+
 /* TRUE if we should demangle symbol names.  */
 bfd_boolean demangling;
 
index 10169dd..8cab5fe 100644 (file)
@@ -1,5 +1,5 @@
 /* ldmain.h -
-   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2002, 2003
+   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2002, 2003, 2004
    Free Software Foundation, Inc.
 
    This file is part of GLD, the Gnu Linker.
@@ -32,6 +32,7 @@ extern bfd_boolean trace_files;
 extern bfd_boolean trace_file_tries;
 extern bfd_boolean version_printed;
 extern bfd_boolean whole_archive;
+extern bfd_boolean as_needed;
 extern bfd_boolean demangling;
 extern int g_switch_value;
 extern const char *output_filename;
index e43e15e..d3b3d8d 100644 (file)
@@ -1,6 +1,6 @@
 /* Parse options for the GNU linker.
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003
+   2001, 2002, 2003, 2004
    Free Software Foundation, Inc.
 
    This file is part of GLD, the Gnu Linker.
@@ -112,6 +112,8 @@ enum option_values
   OPTION_SPLIT_BY_RELOC,
   OPTION_SPLIT_BY_FILE ,
   OPTION_WHOLE_ARCHIVE,
+  OPTION_AS_NEEDED,
+  OPTION_NO_AS_NEEDED,
   OPTION_WRAP,
   OPTION_FORCE_EXE_SUFFIX,
   OPTION_GC_SECTIONS,
@@ -438,6 +440,10 @@ static const struct ld_option ld_options[] =
      TWO_DASHES },
   { {"whole-archive", no_argument, NULL, OPTION_WHOLE_ARCHIVE},
       '\0', NULL, N_("Include all objects from following archives"), TWO_DASHES },
+  { {"as-needed", no_argument, NULL, OPTION_AS_NEEDED},
+      '\0', NULL, N_("Only set DT_NEEDED for following dynamic libs if used"), TWO_DASHES },
+  { {"no-as-needed", no_argument, NULL, OPTION_NO_AS_NEEDED},
+      '\0', NULL, N_("Always set DT_NEEDED for following dynamic libs"), TWO_DASHES },
   { {"wrap", required_argument, NULL, OPTION_WRAP},
       '\0', N_("SYMBOL"), N_("Use wrapper functions for SYMBOL"), TWO_DASHES }
 };
@@ -1156,6 +1162,12 @@ parse_args (unsigned argc, char **argv)
        case OPTION_WHOLE_ARCHIVE:
          whole_archive = TRUE;
          break;
+       case OPTION_AS_NEEDED:
+         as_needed = TRUE;
+         break;
+       case OPTION_NO_AS_NEEDED:
+         as_needed = FALSE;
+         break;
        case OPTION_WRAP:
          add_wrap (optarg);
          break;