* ld.h (ld_config_type): Add new field warn_once.
authorIan Lance Taylor <ian@airs.com>
Wed, 14 Sep 1994 22:27:16 +0000 (22:27 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 14 Sep 1994 22:27:16 +0000 (22:27 +0000)
* ldmain.c (undefined_symbol): Handle -warn-once.
* lexsup.c (parse_args): Recognize -warn-once.
* ld.texinfo (Options): Document -warn-once.
* ld.1: Likewise.
PR 4456.

ld/ChangeLog
ld/ld.1
ld/ld.h
ld/ldmain.c
ld/lexsup.c

index a77789b40b6deda81ca8f981de45fccaa7d43faa..d5def59642b185c3b564fdee1c93b133bfad66b5 100644 (file)
@@ -5,6 +5,12 @@ Wed Sep 14 12:49:12 1994  Steve Chamberlain  (sac@jonny.cygnus.com)
 
 Wed Sep 14 12:48:09 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
 
+       * ld.h (ld_config_type): Add new field warn_once.
+       * ldmain.c (undefined_symbol): Handle -warn-once.
+       * lexsup.c (parse_args): Recognize -warn-once.
+       * ld.texinfo (Options): Document -warn-once.
+       * ld.1: Likewise.
+
        * ldmisc.c (vfinfo): Handle %D as %C, but never print the function
        name.  For %C, print the function name on a separate line, to keep
        the length of error messages under control.
diff --git a/ld/ld.1 b/ld/ld.1
index 965e79116396c05660339e3d790d117cb23d3157..3b6393434c99cf307acb7d92df65502a32c68013 100644 (file)
--- a/ld/ld.1
+++ b/ld/ld.1
@@ -101,6 +101,7 @@ ld \- the GNU linker
 .RB "[\|" \-v "\|]"
 .RB "[\|" \-\-version "\|]"
 .RB "[\|" \-warn\-common "\|]" 
+.RB "[\|" \-warn\-once "\|]" 
 .RB "[\|" \-X "\|]" 
 .RB "[\|" \-x "\|]" 
 .ad b
@@ -777,6 +778,11 @@ a symbol definition.  Unix linkers allow this somewhat sloppy practice,
 but linkers on some other operating systems do not.  This option allows
 you to find potential problems from combining global symbols.
 
+.TP
+.B \-warn\-once
+Only warn once for each undefined symbol, rather than once per module
+which refers to it.
+
 .TP
 .B \-X 
 If \c
diff --git a/ld/ld.h b/ld/ld.h
index ff654a650a13df2af1fc412973d5bd28bacc35b3..d23633e168dee0322d30794069b01dac0af86a3c 100644 (file)
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -49,6 +49,15 @@ typedef struct
   /* 1 => assign space to common symbols even if `relocatable_output'.  */
   boolean force_common_definition;
   boolean relax;
+
+  /* Name of runtime interpreter to invoke.  */
+  char *interpreter;
+
+  /* Name to give runtime libary from the -soname argument.  */
+  char *soname;
+
+  /* Runtime library search path from the -rpath argument.  */
+  char *rpath;
 } args_type;
 
 extern args_type command_line;
@@ -72,6 +81,9 @@ typedef struct
   /* If true, warn about merging common symbols with others.  */
   boolean warn_common;
 
+  /* If true, only warn once about a particular undefined symbol.  */
+  boolean warn_once;
+
   boolean sort_common;
 
   boolean text_read_only;
index 754813b0ea496634506fffa1cb1f34eae175d1bf..392d302588ce10a2178756be7c9894e7cf861790 100644 (file)
@@ -782,6 +782,27 @@ undefined_symbol (info, name, abfd, section, address)
 
 #define MAX_ERRORS_IN_A_ROW 5
 
+  if (config.warn_once)
+    {
+      static struct bfd_hash_table *hash;
+
+      /* Only warn once about a particular undefined symbol.  */
+
+      if (hash == NULL)
+       {
+         hash = ((struct bfd_hash_table *)
+                 xmalloc (sizeof (struct bfd_hash_table)));
+         if (! bfd_hash_table_init (hash, bfd_hash_newfunc))
+           einfo ("%F%P: bfd_hash_table_init failed: %E\n");
+       }
+
+      if (bfd_hash_lookup (hash, name, false, false) != NULL)
+       return true;
+
+      if (bfd_hash_lookup (hash, name, true, true) == NULL)
+       einfo ("%F%P: bfd_hash_lookup failed: %E\n");
+    }
+
   /* We never print more than a reasonable number of errors in a row
      for a single symbol.  */
   if (error_name != (char *) NULL
index 128f0b6d6ee1e305da4d7fe77c51b9c49ade265d..21e8f12d82d2800cf65bb782bfffeb0eece3b648 100644 (file)
@@ -34,6 +34,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "ldfile.h"
 #include "ldver.h"
 
+/* Somewhere above, sys/stat.h got included . . . . */
+#if !defined(S_ISDIR) && defined(S_IFDIR)
+#define        S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+
 /* Omit args to avoid the possibility of clashing with a system header
    that might disagree about consts.  */
 unsigned long strtoul ();
@@ -72,8 +77,10 @@ parse_args (argc, argv)
 #define OPTION_OFORMAT                 (OPTION_NON_SHARED + 1)
 #define OPTION_RELAX                   (OPTION_OFORMAT + 1)
 #define OPTION_RETAIN_SYMBOLS_FILE     (OPTION_RELAX + 1)
-#define OPTION_SHARED                  (OPTION_RETAIN_SYMBOLS_FILE + 1)
-#define OPTION_SORT_COMMON             (OPTION_SHARED + 1)
+#define OPTION_RPATH                   (OPTION_RETAIN_SYMBOLS_FILE + 1)
+#define OPTION_SHARED                  (OPTION_RPATH + 1)
+#define OPTION_SONAME                  (OPTION_SHARED + 1)
+#define OPTION_SORT_COMMON             (OPTION_SONAME + 1)
 #define OPTION_STATS                   (OPTION_SORT_COMMON + 1)
 #define OPTION_TBSS                    (OPTION_STATS + 1)
 #define OPTION_TDATA                   (OPTION_TBSS + 1)
@@ -82,6 +89,7 @@ parse_args (argc, argv)
 #define OPTION_UR                      (OPTION_TRADITIONAL_FORMAT + 1)
 #define OPTION_VERSION                 (OPTION_UR + 1)
 #define OPTION_WARN_COMMON             (OPTION_VERSION + 1)
+#define OPTION_WARN_ONCE               (OPTION_WARN_COMMON + 1)
 
   static struct option longopts[] = {
     {"Bdynamic", no_argument, NULL, OPTION_CALL_SHARED},
@@ -89,6 +97,7 @@ parse_args (argc, argv)
     {"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
     {"dc", no_argument, NULL, 'd'},
     {"defsym", required_argument, NULL, OPTION_DEFSYM},
+    {"dll-verbose", no_argument, NULL, OPTION_VERSION}, /* Linux.  */
     {"dn", no_argument, NULL, OPTION_NON_SHARED},
     {"dp", no_argument, NULL, 'd'},
     {"dy", no_argument, NULL, OPTION_CALL_SHARED},
@@ -108,7 +117,9 @@ parse_args (argc, argv)
     {"qmagic", no_argument, NULL, OPTION_IGNORE}, /* Linux compatibility.  */
     {"relax", no_argument, NULL, OPTION_RELAX},
     {"retain-symbols-file", required_argument, NULL, OPTION_RETAIN_SYMBOLS_FILE},
+    {"rpath", required_argument, NULL, OPTION_RPATH},
     {"shared", no_argument, NULL, OPTION_SHARED},
+    {"soname", required_argument, NULL, OPTION_SONAME},
     {"sort-common", no_argument, NULL, OPTION_SORT_COMMON},
     {"sort_common", no_argument, NULL, OPTION_SORT_COMMON},
     {"start-group", no_argument, NULL, '('},
@@ -121,6 +132,7 @@ parse_args (argc, argv)
     {"Ur", no_argument, NULL, OPTION_UR},
     {"version", no_argument, NULL, OPTION_VERSION},
     {"warn-common", no_argument, NULL, OPTION_WARN_COMMON},
+    {"warn-once", no_argument, NULL, OPTION_WARN_ONCE},
     {NULL, no_argument, NULL, 0}
   };
 
@@ -256,9 +268,40 @@ parse_args (argc, argv)
          config.dynamic_link = false;
          break;
        case 'R':
-         lang_add_input_file (optarg,
-                              lang_input_file_is_symbols_only_enum,
-                              (char *) NULL);
+         /* The GNU linker traditionally uses -R to mean to include
+            only the symbols from a file.  The Solaris linker uses -R
+            to set the path used by the runtime linker to find
+            libraries.  This is the GNU linker -rpath argument.  We
+            try to support both simultaneously by checking the file
+            named.  If it is a directory, rather than a regular file,
+            we assume -rpath was meant.  */
+         {
+           struct stat s;
+
+           if (stat (optarg, &s) >= 0
+               && ! S_ISDIR (s.st_mode))
+             {
+               lang_add_input_file (optarg,
+                                    lang_input_file_is_symbols_only_enum,
+                                    (char *) NULL);
+               break;
+             }
+         }
+         /* Fall through.  */
+       case OPTION_RPATH:
+         if (command_line.rpath == NULL)
+           command_line.rpath = buystring (optarg);
+         else
+           {
+             char *buf;
+
+             buf = xmalloc (strlen (command_line.rpath)
+                            + strlen (optarg)
+                            + 2);
+             sprintf (buf, "%s:%s", command_line.rpath, optarg);
+             free (command_line.rpath);
+             command_line.rpath = buf;
+           }
          break;
        case OPTION_RELAX:
          command_line.relax = true;
@@ -275,6 +318,9 @@ parse_args (argc, argv)
        case OPTION_SHARED:
          link_info.shared = true;
          break;
+       case OPTION_SONAME:
+         command_line.soname = optarg;
+         break;
        case OPTION_SORT_COMMON:
          config.sort_common = true;
          break;
@@ -327,6 +373,9 @@ parse_args (argc, argv)
        case OPTION_WARN_COMMON:
          config.warn_common = true;
          break;
+       case OPTION_WARN_ONCE:
+         config.warn_once = true;
+         break;
        case 'X':
          link_info.discard = discard_l;
          break;