]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
ld: Improve --fatal-warnings for unknown command-line options
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 24 Jan 2024 21:53:11 +0000 (13:53 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 25 Jan 2024 13:42:04 +0000 (05:42 -0800)
There are 2 problems with --fatal-warnings for unknown command-line
options:

1. --fatal-warnings doesn't trigger an error for an unknown command-line
option when --fatal-warnings is the last command-line option.
2. When --fatal-warnings triggers an error for an unknown command-line
option, the message says that the unknown command-line option is ignored.

This patch queues unknown command-line option warnings and outputs queued
command-line option warnings after all command-line options have been
processed so that --fatal-warnings can work for unknown command-line
options regardless of the order of --fatal-warnings.

When --fatal-warnings is used, the linker message is changed from

ld: warning: -z bad-option ignored

to

ld: error: unsupported option: -z bad-option

The above also applies to "-z dynamic-undefined-weak" when the known
"-z dynamic-undefined-weak" option is ignored.

PR ld/31289
* ldelf.c (ldelf_after_parse): Use queue_unknown_cmdline_warning
to warn the ignored -z dynamic-undefined-weak option.
* ldmain.c (main): Call output_unknown_cmdline_warnings after
calling ldemul_after_parse.
* ldmisc.c (CMDLINE_WARNING_SIZE): New.
(cmdline_warning_list): Likewise.
(cmdline_warning_head): Likewise.
(cmdline_warning_tail): Likewise.
(queue_unknown_cmdline_warning): Likewise.
(output_unknown_cmdline_warnings): Likewise.
* ldmisc.h (queue_unknown_cmdline_warning): Likewise.
(output_unknown_cmdline_warnings): Likewise.
* emultempl/elf.em (gld${EMULATION_NAME}_handle_option): Use
queue_unknown_cmdline_warning to warn unknown -z option.
* testsuite/ld-elf/fatal-warnings-1a.d: New file.
* testsuite/ld-elf/fatal-warnings-1b.d: Likewise.
* testsuite/ld-elf/fatal-warnings-2a.d: Likewise.
* testsuite/ld-elf/fatal-warnings-2b.d: Likewise.
* testsuite/ld-elf/fatal-warnings-3a.d: Likewise.
* testsuite/ld-elf/fatal-warnings-3b.d: Likewise.
* testsuite/ld-elf/fatal-warnings-4a.d: Likewise.
* testsuite/ld-elf/fatal-warnings-4b.d: Likewise.

13 files changed:
ld/emultempl/elf.em
ld/ldelf.c
ld/ldmain.c
ld/ldmisc.c
ld/ldmisc.h
ld/testsuite/ld-elf/fatal-warnings-1a.d [new file with mode: 0644]
ld/testsuite/ld-elf/fatal-warnings-1b.d [new file with mode: 0644]
ld/testsuite/ld-elf/fatal-warnings-2a.d [new file with mode: 0644]
ld/testsuite/ld-elf/fatal-warnings-2b.d [new file with mode: 0644]
ld/testsuite/ld-elf/fatal-warnings-3a.d [new file with mode: 0644]
ld/testsuite/ld-elf/fatal-warnings-3b.d [new file with mode: 0644]
ld/testsuite/ld-elf/fatal-warnings-4a.d [new file with mode: 0644]
ld/testsuite/ld-elf/fatal-warnings-4b.d [new file with mode: 0644]

index f551225cdaccdb9cd070f8c8391b4a3f42a6d6fe..55a870f7d2d3e73887f7826cd178da837c679dca 100644 (file)
@@ -873,7 +873,7 @@ fi
 
 fragment <<EOF
       else
-       einfo (_("%P: warning: -z %s ignored\n"), optarg);
+       queue_unknown_cmdline_warning ("-z %s", optarg);
       break;
 EOF
 
index 2852851dcd5a1f644dbb151ba05a2010c8a132ab..04045acbf3dc56947edb15effff5818dd5b69fd9 100644 (file)
@@ -74,7 +74,7 @@ ldelf_after_parse (void)
       && link_info.nointerp)
     {
       if (link_info.dynamic_undefined_weak > 0)
-       einfo (_("%P: warning: -z dynamic-undefined-weak ignored\n"));
+       queue_unknown_cmdline_warning ("-z dynamic-undefined-weak");
       link_info.dynamic_undefined_weak = 0;
     }
 
index e90c2021b331ef91e027b7421feb0ec46148bc88..3b4ad144a2f4d326c9c15278065b5bfa7a98bbcd 100644 (file)
@@ -479,6 +479,8 @@ main (int argc, char **argv)
 
   ldemul_after_parse ();
 
+  output_unknown_cmdline_warnings ();
+
   if (config.map_filename)
     {
       if (strcmp (config.map_filename, "-") == 0)
index 3c862ea437ab166d86e96ee51534f4c9728b7d92..180b24b3448779051d4d2b6e863b11af0043db88 100644 (file)
@@ -620,6 +620,81 @@ einfo (const char *fmt, ...)
   fflush (stderr);
 }
 
+/* The buffer size for each command-line option warning.  */
+#define CMDLINE_WARNING_SIZE   256
+
+/* A linked list of command-line option warnings.  */
+
+struct cmdline_warning_list
+{
+  struct cmdline_warning_list *next;
+  char *warning;
+};
+
+/* The head of the linked list of command-line option warnings.  */
+static struct cmdline_warning_list *cmdline_warning_head = NULL;
+
+/* The tail of the linked list of command-line option warnings.  */
+static struct cmdline_warning_list **cmdline_warning_tail
+  = &cmdline_warning_head;
+
+/* Queue an unknown command-line option warning.  */
+
+void
+queue_unknown_cmdline_warning (const char *fmt, ...)
+{
+  va_list arg;
+  struct cmdline_warning_list *warning_ptr
+    = xmalloc (sizeof (*warning_ptr));
+  warning_ptr->warning = xmalloc (CMDLINE_WARNING_SIZE);
+  warning_ptr->next = NULL;
+  int written;
+
+  va_start (arg, fmt);
+  written = vsnprintf (warning_ptr->warning, CMDLINE_WARNING_SIZE, fmt,
+                      arg);
+  if (written < 0 || written >= CMDLINE_WARNING_SIZE)
+    {
+      /* If vsnprintf fails or truncates, output the warning directly.  */
+      fflush (stdout);
+      va_start (arg, fmt);
+      vfinfo (stderr, fmt, arg, true);
+      fflush (stderr);
+    }
+  else
+    {
+      *cmdline_warning_tail = warning_ptr;
+      cmdline_warning_tail = &warning_ptr->next;
+    }
+  va_end (arg);
+}
+
+/* Output queued unknown command-line option warnings.  */
+
+void
+output_unknown_cmdline_warnings (void)
+{
+  struct cmdline_warning_list *list = cmdline_warning_head;
+  struct cmdline_warning_list *next;
+  if (list == NULL)
+    return;
+
+  fflush (stdout);
+
+  for (; list != NULL; list = next)
+    {
+      next = list->next;
+      if (config.fatal_warnings)
+       einfo (_("%P: error: unsupported option: %s\n"), list->warning);
+      else
+       einfo (_("%P: warning: %s ignored\n"), list->warning);
+      free (list->warning);
+      free (list);
+    }
+
+  fflush (stderr);
+}
+
 void
 info_assert (const char *file, unsigned int line)
 {
index e8b982fe324e639349e7ff9b6c6d3ea87e1695af..20289127c0a0ccc691e9936662093e7958a0f63a 100644 (file)
@@ -27,6 +27,8 @@ extern void minfo (const char *, ...);
 extern void info_msg (const char *, ...);
 extern void lfinfo (FILE *, const char *, ...);
 extern void info_assert (const char *, unsigned int);
+extern void queue_unknown_cmdline_warning (const char *, ...);
+extern void output_unknown_cmdline_warnings (void);
 
 #define ASSERT(x) \
 do { if (!(x)) info_assert(__FILE__,__LINE__); } while (0)
diff --git a/ld/testsuite/ld-elf/fatal-warnings-1a.d b/ld/testsuite/ld-elf/fatal-warnings-1a.d
new file mode 100644 (file)
index 0000000..d669392
--- /dev/null
@@ -0,0 +1,6 @@
+#PR ld/31289
+#source: pr22269.s
+#ld: -pie --no-dynamic-linker --fatal-warnings -z dynamic-undefined-weak
+#readelf: -r -x .data.rel.ro
+#error: unsupported option: -z dynamic-undefined-weak
+#target: *-*-linux* *-*-gnu* *-*-nacl* arm*-*-uclinuxfdpiceabi
diff --git a/ld/testsuite/ld-elf/fatal-warnings-1b.d b/ld/testsuite/ld-elf/fatal-warnings-1b.d
new file mode 100644 (file)
index 0000000..644e96b
--- /dev/null
@@ -0,0 +1,6 @@
+#PR ld/31289
+#source: pr22269.s
+#ld: -pie --no-dynamic-linker -z dynamic-undefined-weak --fatal-warnings
+#readelf: -r -x .data.rel.ro
+#error: unsupported option: -z dynamic-undefined-weak
+#target: *-*-linux* *-*-gnu* *-*-nacl* arm*-*-uclinuxfdpiceabi
diff --git a/ld/testsuite/ld-elf/fatal-warnings-2a.d b/ld/testsuite/ld-elf/fatal-warnings-2a.d
new file mode 100644 (file)
index 0000000..5c46f43
--- /dev/null
@@ -0,0 +1,6 @@
+#PR ld/31289
+#source: start.s
+#ld: -z bad-option1 -z bad-option2
+#warning: -z bad-option1 ignored
+#xfail: [is_generic]
+# generic linker targets don't support -z options.
diff --git a/ld/testsuite/ld-elf/fatal-warnings-2b.d b/ld/testsuite/ld-elf/fatal-warnings-2b.d
new file mode 100644 (file)
index 0000000..5fa94e4
--- /dev/null
@@ -0,0 +1,6 @@
+#PR ld/31289
+#source: start.s
+#ld: -z bad-option1 -z bad-option2
+#warning: -z bad-option2 ignored
+#xfail: [is_generic]
+# generic linker targets don't support -z options.
diff --git a/ld/testsuite/ld-elf/fatal-warnings-3a.d b/ld/testsuite/ld-elf/fatal-warnings-3a.d
new file mode 100644 (file)
index 0000000..a377b73
--- /dev/null
@@ -0,0 +1,6 @@
+#PR ld/31289
+#source: start.s
+#ld: --fatal-warnings -z bad-option1 -z bad-option2
+#error: unsupported option: -z bad-option1
+#xfail: [is_generic]
+# generic linker targets don't support -z options.
diff --git a/ld/testsuite/ld-elf/fatal-warnings-3b.d b/ld/testsuite/ld-elf/fatal-warnings-3b.d
new file mode 100644 (file)
index 0000000..87ea286
--- /dev/null
@@ -0,0 +1,6 @@
+#PR ld/31289
+#source: start.s
+#ld: --fatal-warnings -z bad-option1 -z bad-option2
+#error: unsupported option: -z bad-option2
+#xfail: [is_generic]
+# generic linker targets don't support -z options.
diff --git a/ld/testsuite/ld-elf/fatal-warnings-4a.d b/ld/testsuite/ld-elf/fatal-warnings-4a.d
new file mode 100644 (file)
index 0000000..4685e38
--- /dev/null
@@ -0,0 +1,6 @@
+#PR ld/31289
+#source: start.s
+#ld: -z bad-option1 -z bad-option2 --fatal-warnings
+#error: unsupported option: -z bad-option1
+#xfail: [is_generic]
+# generic linker targets don't support -z options.
diff --git a/ld/testsuite/ld-elf/fatal-warnings-4b.d b/ld/testsuite/ld-elf/fatal-warnings-4b.d
new file mode 100644 (file)
index 0000000..6fc2185
--- /dev/null
@@ -0,0 +1,6 @@
+#PR ld/31289
+#source: start.s
+#ld: -z bad-option1 -z bad-option2 --fatal-warnings
+#error: unsupported option: -z bad-option2
+#xfail: [is_generic]
+# generic linker targets don't support -z options.