PR10372, SH: ld test with sim/sh/run fails always
[binutils-gdb.git] / ld / ldfile.c
index aa84906992bbc75cdf338776e2ec092719269ea6..731ae5f7aedcf921bd36a1b32a3e0f5bfa189071 100644 (file)
@@ -1,5 +1,5 @@
 /* Linker file opening and searching.
-   Copyright (C) 1991-2020 Free Software Foundation, Inc.
+   Copyright (C) 1991-2022 Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
 
 #include "ldemul.h"
 #include "libiberty.h"
 #include "filenames.h"
-#ifdef ENABLE_PLUGINS
+#if BFD_SUPPORTS_PLUGINS
 #include "plugin-api.h"
 #include "plugin.h"
-#endif /* ENABLE_PLUGINS */
+#endif /* BFD_SUPPORTS_PLUGINS */
 
-bfd_boolean ldfile_assumed_script = FALSE;
+bool ldfile_assumed_script = false;
 const char *ldfile_output_machine_name = "";
 unsigned long ldfile_output_machine;
 enum bfd_architecture ldfile_output_architecture;
@@ -68,19 +68,19 @@ static search_arch_type **search_arch_tail_ptr = &search_arch_head;
 /* Test whether a pathname, after canonicalization, is the same or a
    sub-directory of the sysroot directory.  */
 
-static bfd_boolean
+static bool
 is_sysrooted_pathname (const char *name)
 {
   char *realname;
   int len;
-  bfd_boolean result;
+  bool result;
 
   if (ld_canon_sysroot == NULL)
-    return FALSE;
+    return false;
 
   realname = lrealpath (name);
   len = strlen (realname);
-  result = FALSE;
+  result = false;
   if (len > ld_canon_sysroot_len
       && IS_DIR_SEPARATOR (realname[ld_canon_sysroot_len]))
     {
@@ -96,7 +96,7 @@ is_sysrooted_pathname (const char *name)
    Makes a copy of NAME using xmalloc().  */
 
 void
-ldfile_add_library_path (const char *name, bfd_boolean cmdline)
+ldfile_add_library_path (const char *name, bool cmdline)
 {
   search_dirs_type *new_dirs;
 
@@ -113,7 +113,7 @@ ldfile_add_library_path (const char *name, bfd_boolean cmdline)
      now.  */
   if (name[0] == '=')
     new_dirs->name = concat (ld_sysroot, name + 1, (const char *) NULL);
-  else if (CONST_STRNEQ (name, "$SYSROOT"))
+  else if (startswith (name, "$SYSROOT"))
     new_dirs->name = concat (ld_sysroot, name + strlen ("$SYSROOT"), (const char *) NULL);
   else
     new_dirs->name = xstrdup (name);
@@ -121,7 +121,7 @@ ldfile_add_library_path (const char *name, bfd_boolean cmdline)
 
 /* Try to open a BFD for a lang_input_statement.  */
 
-bfd_boolean
+bool
 ldfile_try_open_bfd (const char *attempt,
                     lang_input_statement_type *entry)
 {
@@ -139,16 +139,18 @@ ldfile_try_open_bfd (const char *attempt,
     {
       if (bfd_get_error () == bfd_error_invalid_target)
        einfo (_("%F%P: invalid BFD target `%s'\n"), entry->target);
-      return FALSE;
+      return false;
     }
 
+  track_dependency_files (attempt);
+
   /* Linker needs to decompress sections.  */
   entry->the_bfd->flags |= BFD_DECOMPRESS;
 
   /* This is a linker input BFD.  */
   entry->the_bfd->is_linker_input = 1;
 
-#ifdef ENABLE_PLUGINS
+#if BFD_SUPPORTS_PLUGINS
   if (entry->flags.lto_output)
     entry->the_bfd->lto_output = 1;
 #endif
@@ -160,8 +162,8 @@ ldfile_try_open_bfd (const char *attempt,
      a dynamic object.
 
      In the code below, it's OK to exit early if the check fails,
-     closing the checked BFD and returning FALSE, but if the BFD
-     checks out compatible, do not exit early returning TRUE, or
+     closing the checked BFD and returning false, but if the BFD
+     checks out compatible, do not exit early returning true, or
      the plugins will not get a chance to claim the file.  */
 
   if (entry->flags.search_dirs || !entry->flags.dynamic)
@@ -189,9 +191,9 @@ ldfile_try_open_bfd (const char *attempt,
                  /* Try to interpret the file as a linker script.  */
                  ldfile_open_command_file (attempt);
 
-                 ldfile_assumed_script = TRUE;
+                 ldfile_assumed_script = true;
                  parser_input = input_selected;
-                 ldlex_both ();
+                 ldlex_script ();
                  token = INPUT_SCRIPT;
                  while (token != 0)
                    {
@@ -240,8 +242,8 @@ ldfile_try_open_bfd (const char *attempt,
                                skip = 1;
                            }
                          free (arg1);
-                         if (arg2) free (arg2);
-                         if (arg3) free (arg3);
+                         free (arg2);
+                         free (arg3);
                          break;
                        case NAME:
                        case LNAME:
@@ -250,14 +252,13 @@ ldfile_try_open_bfd (const char *attempt,
                          free (yylval.name);
                          break;
                        case INT:
-                         if (yylval.bigint.str)
-                           free (yylval.bigint.str);
+                         free (yylval.bigint.str);
                          break;
                        }
                      token = yylex ();
                    }
                  ldlex_popstate ();
-                 ldfile_assumed_script = FALSE;
+                 ldfile_assumed_script = false;
                  fclose (yyin);
                  yyin = NULL;
                  if (skip)
@@ -268,7 +269,7 @@ ldfile_try_open_bfd (const char *attempt,
                               attempt, entry->local_sym_name);
                      bfd_close (entry->the_bfd);
                      entry->the_bfd = NULL;
-                     return FALSE;
+                     return false;
                    }
                }
              goto success;
@@ -280,7 +281,7 @@ ldfile_try_open_bfd (const char *attempt,
                     attempt);
              bfd_close (entry->the_bfd);
              entry->the_bfd = NULL;
-             return FALSE;
+             return false;
            }
 
          if (entry->flags.search_dirs
@@ -298,12 +299,12 @@ ldfile_try_open_bfd (const char *attempt,
                       attempt, entry->local_sym_name);
              bfd_close (entry->the_bfd);
              entry->the_bfd = NULL;
-             return FALSE;
+             return false;
            }
        }
     }
  success:
-#ifdef ENABLE_PLUGINS
+#if BFD_SUPPORTS_PLUGINS
   /* If plugins are active, they get first chance to claim
      any successfully-opened input file.  We skip archives
      here; the plugin wants us to offer it the individual
@@ -317,17 +318,17 @@ ldfile_try_open_bfd (const char *attempt,
       && !no_more_claiming
       && bfd_check_format (entry->the_bfd, bfd_object))
     plugin_maybe_claim (entry);
-#endif /* ENABLE_PLUGINS */
+#endif /* BFD_SUPPORTS_PLUGINS */
 
   /* It opened OK, the format checked out, and the plugins have had
      their chance to claim it, so this is success.  */
-  return TRUE;
+  return true;
 }
 
 /* Search for and open the file specified by ENTRY.  If it is an
    archive, use ARCH, LIB and SUFFIX to modify the file name.  */
 
-bfd_boolean
+bool
 ldfile_open_file_search (const char *arch,
                         lang_input_statement_type *entry,
                         const char *lib,
@@ -346,15 +347,15 @@ ldfile_open_file_search (const char *arch,
          if (ldfile_try_open_bfd (name, entry))
            {
              entry->filename = name;
-             return TRUE;
+             return true;
            }
          free (name);
        }
       else if (ldfile_try_open_bfd (entry->filename, entry))
-       return TRUE;
+       return true;
 
       if (IS_ABSOLUTE_PATH (entry->filename))
-       return FALSE;
+       return false;
     }
 
   for (search = search_head; search != NULL; search = search->next)
@@ -364,7 +365,7 @@ ldfile_open_file_search (const char *arch,
       if (entry->flags.dynamic && !bfd_link_relocatable (&link_info))
        {
          if (ldemul_open_dynamic_archive (arch, search, entry))
-           return TRUE;
+           return true;
        }
 
       if (entry->flags.maybe_archive && !entry->flags.full_name_provided)
@@ -377,13 +378,13 @@ ldfile_open_file_search (const char *arch,
       if (ldfile_try_open_bfd (string, entry))
        {
          entry->filename = string;
-         return TRUE;
+         return true;
        }
 
       free (string);
     }
 
-  return FALSE;
+  return false;
 }
 
 /* Open the input file specified by ENTRY.
@@ -408,15 +409,32 @@ ldfile_open_file (lang_input_statement_type *entry)
       else
        einfo (_("%P: cannot find %s: %E\n"), entry->local_sym_name);
 
-      entry->flags.missing_file = TRUE;
-      input_flags.missing_file = TRUE;
+      entry->flags.missing_file = true;
+      input_flags.missing_file = true;
     }
   else
     {
       search_arch_type *arch;
-      bfd_boolean found = FALSE;
+      bool found = false;
+
+      /* If extra_search_path is set, entry->filename is a relative path.
+        Search the directory of the current linker script before searching
+        other paths. */
+      if (entry->extra_search_path)
+       {
+         char *path = concat (entry->extra_search_path, slash, entry->filename,
+                              (const char *)0);
+         if (ldfile_try_open_bfd (path, entry))
+           {
+             entry->filename = path;
+             entry->flags.search_dirs = false;
+             return;
+           }
 
-      /* Try to open <filename><suffix> or lib<filename><suffix>.a */
+         free (path);
+       }
+
+      /* Try to open <filename><suffix> or lib<filename><suffix>.a.  */
       for (arch = search_arch_head; arch != NULL; arch = arch->next)
        {
          found = ldfile_open_file_search (arch->name, entry, "lib", ".a");
@@ -435,7 +453,7 @@ ldfile_open_file (lang_input_statement_type *entry)
       /* If we have found the file, we don't need to search directories
         again.  */
       if (found)
-       entry->flags.search_dirs = FALSE;
+       entry->flags.search_dirs = false;
       else
        {
          if (entry->flags.sysrooted
@@ -443,10 +461,60 @@ 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: %E\n"), entry->local_sym_name);
+           }
+#endif
          else
-           einfo (_("%P: cannot find %s\n"), entry->local_sym_name);
-         entry->flags.missing_file = TRUE;
-         input_flags.missing_file = TRUE;
+           einfo (_("%P: cannot find %s: %E\n"), entry->local_sym_name);
+
+         /* PR 25747: Be kind to users who forgot to add the
+            "lib" prefix to their library when it was created.  */
+         for (arch = search_arch_head; arch != NULL; arch = arch->next)
+           {
+             if (ldfile_open_file_search (arch->name, entry, "", ".a"))
+               {
+                 const char * base = lbasename (entry->filename);
+
+                 einfo (_("%P: note to link with %s use -l:%s or rename it to lib%s\n"),
+                        entry->filename, base, base);
+                 bfd_close (entry->the_bfd);
+                 entry->the_bfd = NULL;
+                 break;
+               }
+           }
+
+         entry->flags.missing_file = true;
+         input_flags.missing_file = true;
        }
     }
 }
@@ -454,7 +522,7 @@ ldfile_open_file (lang_input_statement_type *entry)
 /* Try to open NAME.  */
 
 static FILE *
-try_open (const char *name, bfd_boolean *sysrooted)
+try_open (const char *name, bool *sysrooted)
 {
   FILE *result;
 
@@ -476,12 +544,12 @@ try_open (const char *name, bfd_boolean *sysrooted)
 
 /* Return TRUE iff directory DIR contains an "ldscripts" subdirectory.  */
 
-static bfd_boolean
+static bool
 check_for_scripts_dir (char *dir)
 {
   char *buf;
   struct stat s;
-  bfd_boolean res;
+  bool res;
 
   buf = concat (dir, "/ldscripts", (const char *) NULL);
   res = stat (buf, &s) == 0 && S_ISDIR (s.st_mode);
@@ -536,8 +604,8 @@ find_scripts_dir (void)
 
 static FILE *
 ldfile_find_command_file (const char *name,
-                         bfd_boolean default_only,
-                         bfd_boolean *sysrooted)
+                         bool default_only,
+                         bool *sysrooted)
 {
   search_dirs_type *search;
   FILE *result = NULL;
@@ -559,7 +627,7 @@ ldfile_find_command_file (const char *name,
        {
          search_dirs_type **save_tail_ptr = search_tail_ptr;
          search_tail_ptr = &script_search;
-         ldfile_add_library_path (script_dir, TRUE);
+         ldfile_add_library_path (script_dir, true);
          search_tail_ptr = save_tail_ptr;
        }
     }
@@ -605,7 +673,7 @@ static void
 ldfile_open_command_file_1 (const char *name, enum script_open_style open_how)
 {
   FILE *ldlex_input_stack;
-  bfd_boolean sysrooted;
+  bool sysrooted;
   static struct script_name_list *processed_scripts = NULL;
   struct script_name_list *script;
   size_t len;
@@ -643,6 +711,8 @@ ldfile_open_command_file_1 (const char *name, enum script_open_style open_how)
       return;
     }
 
+  track_dependency_files (name);
+
   lex_push_file (ldlex_input_stack, name, sysrooted);
 
   lineno = 1;