aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog6
-rw-r--r--ld/ld.16
-rw-r--r--ld/ld.h12
-rw-r--r--ld/ldmain.c21
-rw-r--r--ld/lexsup.c59
5 files changed, 99 insertions, 5 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index a77789b..d5def59 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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 965e791..3b63934 100644
--- 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
@@ -778,6 +779,11 @@ 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
.B \-s\c
diff --git a/ld/ld.h b/ld/ld.h
index ff654a6..d23633e 100644
--- 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;
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 754813b..392d302 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -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
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 128f0b6..21e8f12 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -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;