+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.
-*- 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.
/* 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
enable_relro
enable_textrel_check
enable_separate_code
+enable_error_handling_script
enable_default_hash_style
enable_libctf
enable_werror
--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]
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
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
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.
_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
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],
$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.])
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
&& 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);
break;
}
}
+
entry->flags.missing_file = TRUE;
input_flags.missing_file = TRUE;
}
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,
free (relpp);
}
+#if SUPPORT_ERROR_HANDLING_SCRIPT
+char * error_handling_script = NULL;
+#endif
+
/* This is called when an undefined symbol is found. */
static void
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)
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)
{ {"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},
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;