aboutsummaryrefslogtreecommitdiff
path: root/ld/ldmisc.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2024-01-24 13:53:11 -0800
committerH.J. Lu <hjl.tools@gmail.com>2024-01-25 05:42:04 -0800
commit3eb33b8875a032678c375a76f689f928f57dfb15 (patch)
treefa521d89416ecbcd97e19ab28cf42ba0d351c180 /ld/ldmisc.c
parent726f209eb1b05842d816eac8b0b8f9c7f6cd9fbc (diff)
downloadgdb-3eb33b8875a032678c375a76f689f928f57dfb15.zip
gdb-3eb33b8875a032678c375a76f689f928f57dfb15.tar.gz
gdb-3eb33b8875a032678c375a76f689f928f57dfb15.tar.bz2
ld: Improve --fatal-warnings for unknown command-line options
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.
Diffstat (limited to 'ld/ldmisc.c')
-rw-r--r--ld/ldmisc.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/ld/ldmisc.c b/ld/ldmisc.c
index 3c862ea..180b24b 100644
--- a/ld/ldmisc.c
+++ b/ld/ldmisc.c
@@ -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)
{