[binutils-gdb] Add a new option to the linker: --error-handling-script=<NAME>. Run the script <NAME> if an undefin

Nick Clifton nickc@sourceware.org
Fri Oct 16 10:38:29 GMT 2020


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=23ae20f5e3afeeab9aa616c63ab3b357668476d5

commit 23ae20f5e3afeeab9aa616c63ab3b357668476d5
Author: Nick Clifton <nickc@redhat.com>
Date:   Fri Oct 16 11:37:26 2020 +0100

    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.

Diff:
---
 ld/ChangeLog    | 19 +++++++++++++++++++
 ld/NEWS         |  5 +++++
 ld/config.in    |  4 ++++
 ld/configure    | 28 ++++++++++++++++++++++++++--
 ld/configure.ac | 17 +++++++++++++++++
 ld/ld.texi      | 15 +++++++++++++++
 ld/ldfile.c     | 34 ++++++++++++++++++++++++++++++++++
 ld/ldlex.h      |  3 +++
 ld/ldmain.c     | 38 ++++++++++++++++++++++++++++++++++++++
 ld/ldmain.h     |  3 +++
 ld/lexsup.c     | 14 ++++++++++++++
 11 files changed, 178 insertions(+), 2 deletions(-)

diff --git a/ld/ChangeLog b/ld/ChangeLog
index 780bb4b5958..18dc37bdd86 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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.
diff --git a/ld/NEWS b/ld/NEWS
index 2f20a5fbcd0..81c44191d2b 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -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.
 
diff --git a/ld/config.in b/ld/config.in
index 2f4e5ea33e3..7b60d778587 100644
--- a/ld/config.in
+++ b/ld/config.in
@@ -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
 
diff --git a/ld/configure b/ld/configure
index b0b92a3cbfb..afe52ef5efa 100755
--- a/ld/configure
+++ b/ld/configure
@@ -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
diff --git a/ld/configure.ac b/ld/configure.ac
index 74bcdfec36d..7676009d910 100644
--- a/ld/configure.ac
+++ b/ld/configure.ac
@@ -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.])
diff --git a/ld/ld.texi b/ld/ld.texi
index 66bede283e8..95f31ea530b 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -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
diff --git a/ld/ldfile.c b/ld/ldfile.c
index e39170b5d94..51f878de958 100644
--- a/ld/ldfile.c
+++ b/ld/ldfile.c
@@ -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;
 	}
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 6eac75cef53..bb38cca4d6e 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -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,
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 08be9030cb5..cdb4fe58d91 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -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)
diff --git a/ld/ldmain.h b/ld/ldmain.h
index ac7db5720d5..6863727473a 100644
--- a/ld/ldmain.h
+++ b/ld/ldmain.h
@@ -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)
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 68943994846..eae64932dfc 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -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;


More information about the Binutils-cvs mailing list