Add a new option to the linker: --error-handling-script=<NAME>. Run the script <NAME> if an undefined symbol or unfound library error is encountered.

PR 26626
	* ldmain.c (undefined_symbol): If an error handlign script is
	available, call it.
	* ldfile.c  (error_handling_script): Declare.
	(ldfile_open_file): If a library cannot be found and an error
	handling script is available, call it.
	* ldmain.h  (error_handling_script): Prototype.
	* ldlex.h (OPTION_ERROR_HANDLING_SCRIPT): Define.
	* lexsup.c (ld_options): Add --error-handling-script.
	(parse_args): Add support for --errror-handling-script.
	* ld.texi: Document the new feature.
	* configure.ac: Add --error-handling-script option to disable
	support for the new feature.
	* NEWS: Mention the new feature.
	* config.in: Regenerate.
	* configure: Regenerate.
This commit is contained in:
Nick Clifton 2020-10-16 11:37:26 +01:00
parent 472d09c18a
commit 23ae20f5e3
11 changed files with 178 additions and 2 deletions

View File

@ -1,3 +1,22 @@
2020-10-16 Nick Clifton <nickc@redhat.com>
PR 26626
* ldmain.c (undefined_symbol): If an error handlign script is
available, call it.
* ldfile.c (error_handling_script): Declare.
(ldfile_open_file): If a library cannot be found and an error
handling script is available, call it.
* ldmain.h (error_handling_script): Prototype.
* ldlex.h (OPTION_ERROR_HANDLING_SCRIPT): Define.
* lexsup.c (ld_options): Add --error-handling-script.
(parse_args): Add support for --errror-handling-script.
* ld.texi: Document the new feature.
* configure.ac: Add --error-handling-script option to disable
support for the new feature.
* NEWS: Mention the new feature.
* config.in: Regenerate.
* configure: Regenerate.
2020-10-16 Nelson Chu <nelson.chu@sifive.com>
* testsuite/ld-riscv-elf/ifunc-plt-got-overwrite.s: New testcase.

View File

@ -1,5 +1,10 @@
-*- text -*-
* Add --error-handling-script=<NAME> command line option to allow a helper
script to be invoked when an undefined symbol or a missing library is
encountered. This option can be suppressed via the configure time
switch: --enable-error-handling-script=no.
* Add -z x86-64-v[234] to the x86 ELF linker to mark x86-64-v[234] ISA
level as needed.

View File

@ -215,6 +215,10 @@
/* Define if you can safely include both <string.h> and <strings.h>. */
#undef STRING_WITH_STRINGS
/* Define to 1 if you want to support the --error-handling-script command line
option. */
#undef SUPPORT_ERROR_HANDLING_SCRIPT
/* Use b modifier when opening binary files? */
#undef USE_BINARY_FOPEN

28
ld/configure vendored
View File

@ -835,6 +835,7 @@ enable_new_dtags
enable_relro
enable_textrel_check
enable_separate_code
enable_error_handling_script
enable_default_hash_style
enable_libctf
enable_werror
@ -1505,6 +1506,9 @@ Optional Features:
--enable-textrel-check=[yes|no|warning|error]
enable DT_TEXTREL check in ELF linker
--enable-separate-code enable -z separate-code in ELF linker by default
--enable-error-handling-script
enable/disable support for the
--error-handling-script option
--enable-default-hash-style={sysv,gnu,both}
use this default hash style
--enable-libctf Handle .ctf type-info sections [default=yes]
@ -12039,7 +12043,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 12042 "configure"
#line 12046 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -12145,7 +12149,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 12148 "configure"
#line 12152 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -15945,6 +15949,17 @@ esac
fi
# Decide if --error-handling-script should be supported.
ac_support_error_handling_script=unset
# Check whether --enable-error-handling-script was given.
if test "${enable_error_handling_script+set}" = set; then :
enableval=$enable_error_handling_script; case "${enableval}" in
yes) ac_support_error_handling_script=1 ;;
no) ac_support_error_handling_script=0 ;;
esac
fi
# Decide which "--hash-style" to use by default
# Provide a configure time option to override our default.
# Check whether --enable-default-hash-style was given.
@ -17739,6 +17754,15 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
if test "${ac_support_error_handling_script}" = unset; then
ac_support_error_handling_script=1
fi
cat >>confdefs.h <<_ACEOF
#define SUPPORT_ERROR_HANDLING_SCRIPT $ac_support_error_handling_script
_ACEOF
cat >>confdefs.h <<_ACEOF
#define DEFAULT_EMIT_SYSV_HASH $ac_default_emit_sysv_hash

View File

@ -195,6 +195,16 @@ AC_ARG_ENABLE(separate-code,
no) ac_default_ld_z_separate_code=0 ;;
esac])
# Decide if --error-handling-script should be supported.
ac_support_error_handling_script=unset
AC_ARG_ENABLE(error-handling-script,
AS_HELP_STRING([--enable-error-handling-script],
[enable/disable support for the --error-handling-script option]),
[case "${enableval}" in
yes) ac_support_error_handling_script=1 ;;
no) ac_support_error_handling_script=0 ;;
esac])
# Decide which "--hash-style" to use by default
# Provide a configure time option to override our default.
AC_ARG_ENABLE([default-hash-style],
@ -489,6 +499,13 @@ AC_DEFINE_UNQUOTED(DEFAULT_LD_Z_SEPARATE_CODE,
$ac_default_ld_z_separate_code,
[Define to 1 if you want to enable -z separate-code in ELF linker by default.])
if test "${ac_support_error_handling_script}" = unset; then
ac_support_error_handling_script=1
fi
AC_DEFINE_UNQUOTED(SUPPORT_ERROR_HANDLING_SCRIPT,
$ac_support_error_handling_script,
[Define to 1 if you want to support the --error-handling-script command line option.])
AC_DEFINE_UNQUOTED([DEFAULT_EMIT_SYSV_HASH],
[$ac_default_emit_sysv_hash],
[Define to 1 if you want to emit sysv hash in the ELF linker by default.])

View File

@ -1923,6 +1923,21 @@ architecture. This is used, for example, to dynamically select an
appropriate memset function.
@end itemize
@kindex --error-handling-script=@var{scriptname}
@item --error-handling-script=@var{scriptname}
If this option is provided then the linker will invoke
@var{scriptname} whenever an error is encountered. Currently however
only two kinds of error are supported: missing symbols and missing
libraries. Two arguments will be passed to script: the keyword
``missing-symbol'' or `missing-lib'' and the @var{name} of the
missing symbol or library. The intention is that the script will
provide suggestions to the user as to where the symbol or library
might be found. After the script has finished then the normal linker
error message will be displayed.
The availability of this option is controlled by a configure time
switch, so it may not be present in specific implementations.
@kindex --no-undefined-version
@item --no-undefined-version
Normally when a symbol has an undefined version, the linker will ignore

View File

@ -461,6 +461,39 @@ ldfile_open_file (lang_input_statement_type *entry)
&& IS_ABSOLUTE_PATH (entry->local_sym_name))
einfo (_("%P: cannot find %s inside %s\n"),
entry->local_sym_name, ld_sysroot);
#if SUPPORT_ERROR_HANDLING_SCRIPT
else if (error_handling_script != NULL)
{
char * argv[4];
const char * res;
int status, err;
argv[0] = error_handling_script;
argv[1] = "missing-lib";
argv[2] = (char *) entry->local_sym_name;
argv[3] = NULL;
if (verbose)
einfo (_("%P: About to run error handling script '%s' with arguments: '%s' '%s'\n"),
argv[0], argv[1], argv[2]);
res = pex_one (PEX_SEARCH, error_handling_script, argv,
N_("error handling script"),
NULL /* Send stdout to random, temp file. */,
NULL /* Write to stderr. */,
&status, &err);
if (res != NULL)
{
einfo (_("%P: Failed to run error handling script '%s', reason: "),
error_handling_script);
/* FIXME: We assume here that errrno == err. */
perror (res);
}
else /* We ignore the return status of the script
and always print the error message. */
einfo (_("%P: cannot find %s\n"), entry->local_sym_name);
}
#endif
else
einfo (_("%P: cannot find %s\n"), entry->local_sym_name);
@ -479,6 +512,7 @@ ldfile_open_file (lang_input_statement_type *entry)
break;
}
}
entry->flags.missing_file = TRUE;
input_flags.missing_file = TRUE;
}

View File

@ -116,6 +116,9 @@ enum option_values
OPTION_ALLOW_SHLIB_UNDEFINED,
OPTION_NO_ALLOW_SHLIB_UNDEFINED,
OPTION_ALLOW_MULTIPLE_DEFINITION,
#if SUPPORT_ERROR_HANDLING_SCRIPT
OPTION_ERROR_HANDLING_SCRIPT,
#endif
OPTION_NO_UNDEFINED_VERSION,
OPTION_DEFAULT_SYMVER,
OPTION_DEFAULT_IMPORTED_SYMVER,

View File

@ -1382,6 +1382,10 @@ warning_find_reloc (bfd *abfd, asection *sec, void *iarg)
free (relpp);
}
#if SUPPORT_ERROR_HANDLING_SCRIPT
char * error_handling_script = NULL;
#endif
/* This is called when an undefined symbol is found. */
static void
@ -1419,6 +1423,40 @@ undefined_symbol (struct bfd_link_info *info,
error_name = xstrdup (name);
}
#if SUPPORT_ERROR_HANDLING_SCRIPT
if (error_handling_script != NULL
&& error_count < MAX_ERRORS_IN_A_ROW)
{
char * argv[4];
const char * res;
int status, err;
argv[0] = error_handling_script;
argv[1] = "missing-symbol";
argv[2] = (char *) name;
argv[3] = NULL;
if (verbose)
einfo (_("%P: About to run error handling script '%s' with arguments: '%s' '%s'\n"),
argv[0], argv[1], argv[2]);
res = pex_one (PEX_SEARCH, error_handling_script, argv,
N_("error handling script"),
NULL /* Send stdout to random, temp file. */,
NULL /* Write to stderr. */,
&status, &err);
if (res != NULL)
{
einfo (_("%P: Failed to run error handling script '%s', reason: "),
error_handling_script);
/* FIXME: We assume here that errrno == err. */
perror (res);
}
/* We ignore the return status of the script and
carry on to issue the normal error message. */
}
#endif /* SUPPORT_ERROR_HANDLING_SCRIPT */
if (section != NULL)
{
if (error_count < MAX_ERRORS_IN_A_ROW)

View File

@ -37,6 +37,9 @@ extern int g_switch_value;
extern const char *output_filename;
extern struct bfd_link_info link_info;
extern int overflow_cutoff_limit;
#if SUPPORT_ERROR_HANDLING_SCRIPT
extern char *error_handling_script;
#endif
#define RELAXATION_DISABLED_BY_DEFAULT \
(link_info.disable_target_specific_optimizations < 0)

View File

@ -386,6 +386,11 @@ static const struct ld_option ld_options[] =
{ {"allow-multiple-definition", no_argument, NULL,
OPTION_ALLOW_MULTIPLE_DEFINITION},
'\0', NULL, N_("Allow multiple definitions"), TWO_DASHES },
#if SUPPORT_ERROR_HANDLING_SCRIPT
{ {"error-handling-script", required_argument, NULL,
OPTION_ERROR_HANDLING_SCRIPT},
'\0', N_("SCRIPT"), N_("Provide a script to help with undefined symbol errors"), TWO_DASHES},
#endif
{ {"no-undefined-version", no_argument, NULL, OPTION_NO_UNDEFINED_VERSION},
'\0', NULL, N_("Disallow undefined version"), TWO_DASHES },
{ {"default-symver", no_argument, NULL, OPTION_DEFAULT_SYMVER},
@ -1043,6 +1048,15 @@ parse_args (unsigned argc, char **argv)
case OPTION_ALLOW_MULTIPLE_DEFINITION:
link_info.allow_multiple_definition = TRUE;
break;
#if SUPPORT_ERROR_HANDLING_SCRIPT
case OPTION_ERROR_HANDLING_SCRIPT:
/* FIXME: Should we warn if the script is being overridden by another ?
Or maybe they should be chained together ? */
error_handling_script = optarg;
break;
#endif
case OPTION_NO_UNDEFINED_VERSION:
link_info.allow_undefined_version = FALSE;
break;