diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2024-01-24 13:53:11 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2024-01-25 05:42:04 -0800 |
commit | 3eb33b8875a032678c375a76f689f928f57dfb15 (patch) | |
tree | fa521d89416ecbcd97e19ab28cf42ba0d351c180 | |
parent | 726f209eb1b05842d816eac8b0b8f9c7f6cd9fbc (diff) | |
download | gdb-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.
-rw-r--r-- | ld/emultempl/elf.em | 2 | ||||
-rw-r--r-- | ld/ldelf.c | 2 | ||||
-rw-r--r-- | ld/ldmain.c | 2 | ||||
-rw-r--r-- | ld/ldmisc.c | 75 | ||||
-rw-r--r-- | ld/ldmisc.h | 2 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/fatal-warnings-1a.d | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/fatal-warnings-1b.d | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/fatal-warnings-2a.d | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/fatal-warnings-2b.d | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/fatal-warnings-3a.d | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/fatal-warnings-3b.d | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/fatal-warnings-4a.d | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/fatal-warnings-4b.d | 6 |
13 files changed, 129 insertions, 2 deletions
diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em index f551225..55a870f 100644 --- a/ld/emultempl/elf.em +++ b/ld/emultempl/elf.em @@ -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 @@ -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; } diff --git a/ld/ldmain.c b/ld/ldmain.c index e90c202..3b4ad14 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -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) 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) { diff --git a/ld/ldmisc.h b/ld/ldmisc.h index e8b982f..2028912 100644 --- a/ld/ldmisc.h +++ b/ld/ldmisc.h @@ -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 index 0000000..d669392 --- /dev/null +++ b/ld/testsuite/ld-elf/fatal-warnings-1a.d @@ -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 index 0000000..644e96b --- /dev/null +++ b/ld/testsuite/ld-elf/fatal-warnings-1b.d @@ -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 index 0000000..5c46f43 --- /dev/null +++ b/ld/testsuite/ld-elf/fatal-warnings-2a.d @@ -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 index 0000000..5fa94e4 --- /dev/null +++ b/ld/testsuite/ld-elf/fatal-warnings-2b.d @@ -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 index 0000000..a377b73 --- /dev/null +++ b/ld/testsuite/ld-elf/fatal-warnings-3a.d @@ -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 index 0000000..87ea286 --- /dev/null +++ b/ld/testsuite/ld-elf/fatal-warnings-3b.d @@ -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 index 0000000..4685e38 --- /dev/null +++ b/ld/testsuite/ld-elf/fatal-warnings-4a.d @@ -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 index 0000000..6fc2185 --- /dev/null +++ b/ld/testsuite/ld-elf/fatal-warnings-4b.d @@ -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. |