bfd/
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 19 Jul 2004 16:40:52 +0000 (16:40 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 19 Jul 2004 16:40:52 +0000 (16:40 +0000)
2004-07-19  H.J. Lu  <hongjiu.lu@intel.com>

* bfd-in.h (dynamic_lib_link_class): Add DYN_NO_ADD_NEEDED and
DYN_NO_NEEDED.
(bfd_elf_get_dyn_lib_class): New prototype.
* elf.c (bfd_elf_get_dyn_lib_class): New function.

* elflink.c (elf_link_add_object_symbols): Check DYN_AS_NEEDED,
DYN_DT_NEEDED and DYN_NO_NEEDED bits to see if a DT_NEEDED
entry is needed. Issue an error if a DT_NEEDED entry is needed
for a file marked DYN_NO_NEEDED.
(elf_link_check_versioned_symbol): Check the DYN_DT_NEEDED bit
for DT_NEEDED tags.

* bfd-in2.h: Regenerated.

ld/

2004-07-19  H.J. Lu  <hongjiu.lu@intel.com>

* emultempl/elf32.em (gld${EMULATION_NAME}_load_symbols): Also
check the add_needed field.
(dt_needed): New struct.
(gld${EMULATION_NAME}_try_needed): Change the first argument
to a pointer to struct dt_needed. Check the DYN_NO_ADD_NEEDED
bit in the file where the DT_NEEDED entry comes from.
(gld${EMULATION_NAME}_search_needed): Change the second
argument to a pointer to struct dt_needed.
(gld${EMULATION_NAME}_check_ld_so_conf): Updated.
(gld${EMULATION_NAME}_after_open): Likewise.

* ld.texinfo: Add --add-needed document.
* ldlang.c (new_afile): Set p->add_needed.
* ldlang.h (lang_input_statement_type): Add add_needed field.
* ldmain.h (add_needed): Declare.
* ldmain.c (add_needed): New global var.
* lexsup.c (option_values): Add OPTION_ADD_NEEDED and
OPTION_NO_ADD_NEEDED.
(ld_options): Likewise.
(parse_args): Handle them.

13 files changed:
bfd/ChangeLog
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/elf.c
bfd/elflink.c
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 db7ada4f1f9ae797298bc450423faab54e0731e2..aa3f6f805242257d0e260a5b5f2046eb1a8ad97e 100644 (file)
@@ -1,3 +1,19 @@
+2004-07-19  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * bfd-in.h (dynamic_lib_link_class): Add DYN_NO_ADD_NEEDED and
+       DYN_NO_NEEDED.
+       (bfd_elf_get_dyn_lib_class): New prototype.
+       * elf.c (bfd_elf_get_dyn_lib_class): New function.
+
+       * elflink.c (elf_link_add_object_symbols): Check DYN_AS_NEEDED,
+       DYN_DT_NEEDED and DYN_NO_NEEDED bits to see if a DT_NEEDED
+       entry is needed. Issue an error if a DT_NEEDED entry is needed
+       for a file marked DYN_NO_NEEDED.
+       (elf_link_check_versioned_symbol): Check the DYN_DT_NEEDED bit
+       for DT_NEEDED tags.
+
+       * bfd-in2.h: Regenerated.
+
 2004-07-14  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
        * elflink.c (elf_section_complain_discarded): Don't complain in
index 97296c88898f6648eef3c9ab5a086ec25b80290f..f48e9d71fce77e3d01c6b110322775245539727e 100644 (file)
@@ -625,7 +625,9 @@ struct bfd_link_needed_list
 enum dynamic_lib_link_class {
   DYN_NORMAL = 0,
   DYN_AS_NEEDED = 1,
-  DYN_DT_NEEDED = 2
+  DYN_DT_NEEDED = 2,
+  DYN_NO_ADD_NEEDED = 4,
+  DYN_NO_NEEDED = 8
 };
 
 extern bfd_boolean bfd_elf_record_link_assignment
@@ -643,6 +645,8 @@ extern const char *bfd_elf_get_dt_soname
   (bfd *);
 extern void bfd_elf_set_dyn_lib_class
   (bfd *, int);
+extern int bfd_elf_get_dyn_lib_class
+  (bfd *);
 extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
   (bfd *, struct bfd_link_info *);
 extern bfd_boolean bfd_elf_discard_info
index f3b1761726cce184b9227118ec63218ab130ac8f..502a01b5e4643c62ffd6263453c31111066dfd25 100644 (file)
@@ -632,7 +632,9 @@ struct bfd_link_needed_list
 enum dynamic_lib_link_class {
   DYN_NORMAL = 0,
   DYN_AS_NEEDED = 1,
-  DYN_DT_NEEDED = 2
+  DYN_DT_NEEDED = 2,
+  DYN_NO_ADD_NEEDED = 4,
+  DYN_NO_NEEDED = 8
 };
 
 extern bfd_boolean bfd_elf_record_link_assignment
@@ -650,6 +652,8 @@ extern const char *bfd_elf_get_dt_soname
   (bfd *);
 extern void bfd_elf_set_dyn_lib_class
   (bfd *, int);
+extern int bfd_elf_get_dyn_lib_class
+  (bfd *);
 extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
   (bfd *, struct bfd_link_info *);
 extern bfd_boolean bfd_elf_discard_info
@@ -1756,7 +1760,7 @@ enum bfd_architecture
 #define bfd_mach_avr5          5
   bfd_arch_cr16c,       /* National Semiconductor CompactRISC. */
 #define bfd_mach_cr16c         1
-  bfd_arch_crx,       /*  National Semiconductor CRX. */
+  bfd_arch_crx,       /*  National Semiconductor CRX.  */
 #define bfd_mach_crx           1
   bfd_arch_cris,      /* Axis CRIS */
   bfd_arch_s390,      /* IBM s390 */
index 1cf2dc0f245bc803dd4d28a9124866c34076e058..4371f15869da4bded996eac80788c72fe4d0eb7b 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1514,6 +1514,18 @@ bfd_elf_set_dt_needed_name (bfd *abfd, const char *name)
     elf_dt_name (abfd) = name;
 }
 
+int
+bfd_elf_get_dyn_lib_class (bfd *abfd)
+{
+  int lib_class;
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+      && bfd_get_format (abfd) == bfd_object)
+    lib_class = elf_dyn_lib_class (abfd);
+  else
+    lib_class = 0;
+  return lib_class;
+}
+
 void
 bfd_elf_set_dyn_lib_class (bfd *abfd, int lib_class)
 {
index a6dafae2b11852dff30fda4cf1d8607ed10f854b..4920d9da8f033b722a9e2ff60f40f59218b5d4d9 100644 (file)
@@ -3064,8 +3064,13 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       /* 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.  Similary for libs brought
-        in by another lib's DT_NEEDED.  */
-      add_needed = elf_dyn_lib_class (abfd) == DYN_NORMAL;
+        in by another lib's DT_NEEDED.  When --no-add-needed is used
+        on a dynamic lib, we don't want to add a DT_NEEDED entry for
+        any dynamic library in DT_NEEDED tags in the dynamic lib at
+        all.  */
+      add_needed = (elf_dyn_lib_class (abfd)
+                   & (DYN_AS_NEEDED | DYN_DT_NEEDED
+                      | DYN_NO_NEEDED)) == 0;
 
       s = bfd_get_section_by_name (abfd, ".dynamic");
       if (s != NULL)
@@ -3846,7 +3851,17 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 
              /* 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 a DT_NEEDED entry for it.  Issue an error if
+                --no-add-needed is used.  */
+             if ((elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
+               {
+                 (*_bfd_error_handler)
+                   (_("%s: invalid DSO for symbol `%s' definition"),
+                    bfd_archive_filename (abfd), name);
+                 bfd_set_error (bfd_error_bad_value);
+                 goto error_free_vers;
+               }
+
              add_needed = TRUE;
              ret = elf_add_dt_needed_tag (info, soname, add_needed);
              if (ret < 0)
@@ -5818,7 +5833,7 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
     case bfd_link_hash_undefweak:
       abfd = h->root.u.undef.abfd;
       if ((abfd->flags & DYNAMIC) == 0
-         || elf_dyn_lib_class (abfd) != DYN_DT_NEEDED)
+         || (elf_dyn_lib_class (abfd) & DYN_DT_NEEDED) == 0)
        return FALSE;
       break;
 
index a1b679c1d58b8cf9e3a7e8a7a32c32ad31c7286b..e029451e86d1acf30a7d8e2849392dfa84ebc7c8 100644 (file)
@@ -1,3 +1,26 @@
+2004-07-19  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * emultempl/elf32.em (gld${EMULATION_NAME}_load_symbols): Also
+       check the add_needed field.
+       (dt_needed): New struct.
+       (gld${EMULATION_NAME}_try_needed): Change the first argument
+       to a pointer to struct dt_needed. Check the DYN_NO_ADD_NEEDED
+       bit in the file where the DT_NEEDED entry comes from.
+       (gld${EMULATION_NAME}_search_needed): Change the second
+       argument to a pointer to struct dt_needed.
+       (gld${EMULATION_NAME}_check_ld_so_conf): Updated.
+       (gld${EMULATION_NAME}_after_open): Likewise.
+
+       * ld.texinfo: Add --add-needed document.
+       * ldlang.c (new_afile): Set p->add_needed.
+       * ldlang.h (lang_input_statement_type): Add add_needed field.
+       * ldmain.h (add_needed): Declare.
+       * ldmain.c (add_needed): New global var.
+       * lexsup.c (option_values): Add OPTION_ADD_NEEDED and
+       OPTION_NO_ADD_NEEDED.
+       (ld_options): Likewise.
+       (parse_args): Handle them.
+
 2004-07-13  Christof Petig  <christof@petig-baender.de>
 
        * emultempl/pe.em (make_import_fixup): Use bfd_get_32 to correct
index 8dbd60a5735dc6433153276c6c88ccbca546a180..469f0540f4f7f4c71b11434309c7d2d9b9782c39 100644 (file)
@@ -96,14 +96,25 @@ cat >>e${EMULATION_NAME}.c <<EOF
 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;
+  int class = 0;
 
   /* 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);
+  if (entry->as_needed)
+    class = DYN_AS_NEEDED;
+
+  /* Tell the ELF linker that we don't want the output file to have a
+     DT_NEEDED entry for any dynamic library in DT_NEEDED tags from
+     this file at all.  */
+  if (!entry->add_needed)
+    class |= DYN_NO_ADD_NEEDED;
+
+  if (!class
+      || (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0)
+    return FALSE;
+
+  bfd_elf_set_dyn_lib_class (entry->the_bfd, class);
 
   /* Continue on with normal load_symbols processing.  */
   return FALSE;
@@ -242,16 +253,24 @@ gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s)
           global_needed->name, global_needed->by, soname);
 }
 
+struct dt_needed
+{
+  bfd *by;
+  const char *name;
+};
 
 /* This function is called for each possible name for a dynamic object
    named by a DT_NEEDED entry.  The FORCE parameter indicates whether
    to skip the check for a conflicting version.  */
 
 static bfd_boolean
-gld${EMULATION_NAME}_try_needed (const char *name, int force)
+gld${EMULATION_NAME}_try_needed (struct dt_needed *needed,
+                                int force)
 {
   bfd *abfd;
+  const char *name = needed->name;
   const char *soname;
+  int class;
 
   abfd = bfd_openr (name, bfd_get_target (output_bfd));
   if (abfd == NULL)
@@ -364,7 +383,17 @@ cat >>e${EMULATION_NAME}.c <<EOF
   /* 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);
+  class = DYN_DT_NEEDED;
+
+  /* Tell the ELF linker that we don't want the output file to have a
+     DT_NEEDED entry for this file at all if the entry is from a file
+     with DYN_NO_ADD_NEEDED.  */
+  if (needed->by
+      && (bfd_elf_get_dyn_lib_class (needed->by)
+         & DYN_NO_ADD_NEEDED) != 0)
+    class |= DYN_NO_NEEDED | DYN_NO_ADD_NEEDED;
+
+  bfd_elf_set_dyn_lib_class (abfd, class);
 
   /* Add this file into the symbol table.  */
   if (! bfd_link_add_symbols (abfd, &link_info))
@@ -377,16 +406,23 @@ cat >>e${EMULATION_NAME}.c <<EOF
 /* Search for a needed file in a path.  */
 
 static bfd_boolean
-gld${EMULATION_NAME}_search_needed (const char *path, const char *name, int force)
+gld${EMULATION_NAME}_search_needed (const char *path,
+                                   struct dt_needed *n, int force)
 {
   const char *s;
+  const char *name = n->name;
   size_t len;
+  struct dt_needed needed;
 
   if (name[0] == '/')
-    return gld${EMULATION_NAME}_try_needed (name, force);
+    return gld${EMULATION_NAME}_try_needed (n, force);
 
   if (path == NULL || *path == '\0')
     return FALSE;
+
+  needed.by = n->by;
+  needed.name = n->name;
+
   len = strlen (name);
   while (1)
     {
@@ -407,7 +443,8 @@ gld${EMULATION_NAME}_search_needed (const char *path, const char *name, int forc
        }
       strcpy (sset, name);
 
-      if (gld${EMULATION_NAME}_try_needed (filename, force))
+      needed.name = filename;
+      if (gld${EMULATION_NAME}_try_needed (&needed, force))
        return TRUE;
 
       free (filename);
@@ -474,6 +511,7 @@ gld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force)
 {
   static bfd_boolean initialized;
   static char *ld_so_conf;
+  struct dt_needed needed;
 
   if (! initialized)
     {
@@ -548,7 +586,10 @@ gld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force)
   if (ld_so_conf == NULL)
     return FALSE;
 
-  return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force);
+
+  needed.by = NULL;
+  needed.name = name;
+  return gld${EMULATION_NAME}_search_needed (ld_so_conf, &needed, force);
 }
 
 EOF
@@ -631,6 +672,7 @@ gld${EMULATION_NAME}_after_open (void)
   for (l = needed; l != NULL; l = l->next)
     {
       struct bfd_link_needed_list *ll;
+      struct dt_needed n, nn;
       int force;
 
       /* If we've already seen this file, skip it.  */
@@ -647,6 +689,9 @@ gld${EMULATION_NAME}_after_open (void)
       if (global_found)
        continue;
 
+      n.by = l->by;
+      n.name = l->name;
+      nn.by = l->by;
       if (trace_file_tries)
        info_msg (_("%s needed by %B\n"), l->name, l->by);
 
@@ -676,13 +721,13 @@ fi
 cat >>e${EMULATION_NAME}.c <<EOF
 
          if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
-                                                 l->name, force))
+                                                 &n, force))
            break;
 EOF
 if [ "x${USE_LIBPATH}" = xyes ] ; then
 cat >>e${EMULATION_NAME}.c <<EOF
          if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
-                                                 l->name, force))
+                                                 &n, force))
            break;
 EOF
 fi
@@ -692,12 +737,12 @@ cat >>e${EMULATION_NAME}.c <<EOF
              && command_line.rpath == NULL)
            {
              lib_path = (const char *) getenv ("LD_RUN_PATH");
-             if (gld${EMULATION_NAME}_search_needed (lib_path, l->name,
+             if (gld${EMULATION_NAME}_search_needed (lib_path, &n,
                                                      force))
                break;
            }
          lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
-         if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force))
+         if (gld${EMULATION_NAME}_search_needed (lib_path, &n, force))
            break;
 EOF
 fi
@@ -710,7 +755,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
              char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name);
              found = (rp->by == l->by
                       && gld${EMULATION_NAME}_search_needed (tmpname,
-                                                             l->name,
+                                                             &n,
                                                              force));
              free (tmpname);
            }
@@ -729,7 +774,8 @@ cat >>e${EMULATION_NAME}.c <<EOF
                continue;
              filename = (char *) xmalloc (strlen (search->name) + len + 2);
              sprintf (filename, "%s/%s", search->name, l->name);
-             if (gld${EMULATION_NAME}_try_needed (filename, force))
+             nn.name = filename;
+             if (gld${EMULATION_NAME}_try_needed (&nn, force))
                break;
              free (filename);
            }
index 2b77260b60bbcc31abaadb51b1e6b3427266da07..8af022387449447386f1d06d98779da50a82ae7c 100644 (file)
@@ -984,6 +984,18 @@ 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 --add-needed
+@kindex --no-add-needed
+@item --add-needed
+@itemx --no-add-needed
+This option affects the treatment of dynamic libraries from ELF
+DT_NEEDED tags in dynamic libraries mentioned on the command line after
+the @option{--no-add-needed} option.  Normally, the linker will add
+a DT_NEEDED tag for each dynamic library from DT_NEEDED tags.
+@option{--no-add-needed} causes DT_NEEDED tags will never be emitted
+for those libraries from DT_NEEDED tags. @option{--add-needed} restores
+the default behaviour.
+
 @kindex -assert @var{keyword}
 @item -assert @var{keyword}
 This option is ignored for SunOS compatibility.
index 8daf9c5337a0644be91304beeed70f117a7e96bf..c5cfd5c45a26b40432a11db5f4ac9059424f93b6 100644 (file)
@@ -454,6 +454,7 @@ new_afile (const char *name,
   p->next = NULL;
   p->symbol_count = 0;
   p->dynamic = config.dynamic_link;
+  p->add_needed = add_needed;
   p->as_needed = as_needed;
   p->whole_archive = whole_archive;
   p->loaded = FALSE;
index 0b56c276c38180f048968936ed30179dd613fd13..f7e2fa619e767e808ff0c6c782a86876fa52b29b 100644 (file)
@@ -266,6 +266,10 @@ typedef struct lang_input_statement_struct
   /* Whether to search for this entry as a dynamic archive.  */
   bfd_boolean dynamic;
 
+  /* Whether DT_NEEDED tags should be added for dynamic libraries in
+     DT_NEEDED tags from this entry.  */
+  bfd_boolean add_needed;
+
   /* Whether this entry should cause a DT_NEEDED tag only when
      satisfying references from regular files, or always.  */
   bfd_boolean as_needed;
index f1804c438a0fe069ba4968eb49f3d94d418c7133..193fd69b09a2900bb45a28a728a32574fdfde807 100644 (file)
@@ -97,6 +97,10 @@ bfd_boolean whole_archive;
    actually satisfies some reference in a regular object.  */
 bfd_boolean as_needed;
 
+/* Nonzero means never create DT_NEEDED entries for dynamic libraries
+   in DT_NEEDED tags.  */
+bfd_boolean add_needed = TRUE;
+
 /* TRUE if we should demangle symbol names.  */
 bfd_boolean demangling;
 
index 8cab5fe1f22a56f3cd3a703eb78a62561febc9b8..976810ebd168ad6e674acf031f6a301b06fb7a47 100644 (file)
@@ -33,6 +33,7 @@ extern bfd_boolean trace_file_tries;
 extern bfd_boolean version_printed;
 extern bfd_boolean whole_archive;
 extern bfd_boolean as_needed;
+extern bfd_boolean add_needed;
 extern bfd_boolean demangling;
 extern int g_switch_value;
 extern const char *output_filename;
index 55ab5ee0da0249320c04352ce3c64b2555760772..9a599a3d5c4920d563589d5fa6aecf52552b3eec 100644 (file)
@@ -112,6 +112,8 @@ enum option_values
   OPTION_SPLIT_BY_RELOC,
   OPTION_SPLIT_BY_FILE ,
   OPTION_WHOLE_ARCHIVE,
+  OPTION_ADD_NEEDED,
+  OPTION_NO_ADD_NEEDED,
   OPTION_AS_NEEDED,
   OPTION_NO_AS_NEEDED,
   OPTION_WRAP,
@@ -482,6 +484,12 @@ static const struct ld_option ld_options[] =
   { {"whole-archive", no_argument, NULL, OPTION_WHOLE_ARCHIVE},
     '\0', NULL, N_("Include all objects from following archives"),
     TWO_DASHES },
+  { {"add-needed", no_argument, NULL, OPTION_ADD_NEEDED},
+    '\0', NULL, N_("Set DT_NEEDED tags for DT_NEEDED entries in\n"
+                  "\t\t\t\tfollowing dynamic libs"), TWO_DASHES },
+  { {"no-add-needed", no_argument, NULL, OPTION_NO_ADD_NEEDED},
+    '\0', NULL, N_("Do not set DT_NEEDED tags for DT_NEEDED entries\n"
+                  "\t\t\t\tin following dynamic libs"), 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 },
@@ -1196,6 +1204,12 @@ parse_args (unsigned argc, char **argv)
        case OPTION_WHOLE_ARCHIVE:
          whole_archive = TRUE;
          break;
+       case OPTION_ADD_NEEDED:
+         add_needed = TRUE;
+         break;
+       case OPTION_NO_ADD_NEEDED:
+         add_needed = FALSE;
+         break;
        case OPTION_AS_NEEDED:
          as_needed = TRUE;
          break;