gas: remove use of PTR
[binutils-gdb.git] / ld / ldfile.c
index 0943bb2dfa0fcc40565133773e86f72cf04d19f8..731ae5f7aedcf921bd36a1b32a3e0f5bfa189071 100644 (file)
@@ -1,5 +1,5 @@
 /* Linker file opening and searching.
-   Copyright (C) 1991-2017 Free Software Foundation, Inc.
+   Copyright (C) 1991-2022 Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
 
@@ -21,6 +21,7 @@
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "safe-ctype.h"
 #include "ld.h"
 #include "ldmisc.h"
 #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;
@@ -67,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]))
     {
@@ -95,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;
 
@@ -112,13 +113,15 @@ 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 (startswith (name, "$SYSROOT"))
+    new_dirs->name = concat (ld_sysroot, name + strlen ("$SYSROOT"), (const char *) NULL);
   else
     new_dirs->name = xstrdup (name);
 }
 
 /* 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)
 {
@@ -136,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
@@ -157,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)
@@ -186,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)
                    {
@@ -237,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:
@@ -247,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)
@@ -265,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;
@@ -277,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
@@ -295,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
+ success:
+#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
@@ -314,17 +318,17 @@ success:
       && !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,
@@ -343,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)
@@ -361,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)
@@ -374,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.
@@ -405,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;
+           }
+
+         free (path);
+       }
 
-      /* Try to open <filename><suffix> or lib<filename><suffix>.a */
+      /* 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");
@@ -432,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
@@ -440,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;
        }
     }
 }
@@ -451,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;
 
@@ -473,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);
@@ -533,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;
@@ -556,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;
        }
     }
@@ -583,23 +654,65 @@ ldfile_find_command_file (const char *name,
   return result;
 }
 
+enum script_open_style {
+  script_nonT,
+  script_T,
+  script_defaultT
+};
+
+struct script_name_list
+{
+  struct script_name_list *next;
+  enum script_open_style open_how;
+  char name[1];
+};
+
 /* Open command file NAME.  */
 
 static void
-ldfile_open_command_file_1 (const char *name, bfd_boolean default_only)
+ldfile_open_command_file_1 (const char *name, enum script_open_style open_how)
 {
   FILE *ldlex_input_stack;
-  bfd_boolean sysrooted;
-
-  ldlex_input_stack = ldfile_find_command_file (name, default_only, &sysrooted);
+  bool sysrooted;
+  static struct script_name_list *processed_scripts = NULL;
+  struct script_name_list *script;
+  size_t len;
+
+  /* PR 24576: Catch the case where the user has accidentally included
+     the same linker script twice.  */
+  for (script = processed_scripts; script != NULL; script = script->next)
+    {
+      if ((open_how != script_nonT || script->open_how != script_nonT)
+         && strcmp (name, script->name) == 0)
+       {
+         einfo (_("%F%P: error: linker script file '%s'"
+                  " appears multiple times\n"), name);
+         return;
+       }
+    }
 
+  /* FIXME: This memory is never freed, but that should not really matter.
+     It will be released when the linker exits, and it is unlikely to ever
+     be more than a few tens of bytes.  */
+  len = strlen (name);
+  script = xmalloc (sizeof (*script) + len);
+  script->next = processed_scripts;
+  script->open_how = open_how;
+  memcpy (script->name, name, len + 1);
+  processed_scripts = script;
+
+  ldlex_input_stack = ldfile_find_command_file (name,
+                                               open_how == script_defaultT,
+                                               &sysrooted);
   if (ldlex_input_stack == NULL)
     {
       bfd_set_error (bfd_error_system_call);
-      einfo (_("%P%F: cannot open linker script file %s: %E\n"), name);
+      einfo (_("%F%P: cannot open linker script file %s: %E\n"), name);
       return;
     }
 
+  track_dependency_files (name);
+
   lex_push_file (ldlex_input_stack, name, sysrooted);
 
   lineno = 1;
@@ -613,7 +726,13 @@ ldfile_open_command_file_1 (const char *name, bfd_boolean default_only)
 void
 ldfile_open_command_file (const char *name)
 {
-  ldfile_open_command_file_1 (name, FALSE);
+  ldfile_open_command_file_1 (name, script_nonT);
+}
+
+void
+ldfile_open_script_file (const char *name)
+{
+  ldfile_open_command_file_1 (name, script_T);
 }
 
 /* Open command file NAME at the default script location.  */
@@ -621,7 +740,7 @@ ldfile_open_command_file (const char *name)
 void
 ldfile_open_default_command_file (const char *name)
 {
-  ldfile_open_command_file_1 (name, TRUE);
+  ldfile_open_command_file_1 (name, script_defaultT);
 }
 
 void
@@ -661,5 +780,5 @@ ldfile_set_output_arch (const char *string, enum bfd_architecture defarch)
   else if (defarch != bfd_arch_unknown)
     ldfile_output_architecture = defarch;
   else
-    einfo (_("%P%F: cannot represent machine `%s'\n"), string);
+    einfo (_("%F%P: cannot represent machine `%s'\n"), string);
 }