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.
This commit is contained in:
H.J. Lu 2024-01-24 13:53:11 -08:00
parent 726f209eb1
commit 3eb33b8875
13 changed files with 129 additions and 2 deletions

View 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

View 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;
}

View 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)

View 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)
{

View 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)

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.