Re: Have the linker report an error if the same script is used twice
authorAlan Modra <amodra@gmail.com>
Thu, 23 May 2019 00:52:56 +0000 (10:22 +0930)
committerAlan Modra <amodra@gmail.com>
Thu, 23 May 2019 01:08:45 +0000 (10:38 +0930)
git commit 6ec6968b1b2 results in
... error: linker script file '/usr/local/lib64/libgcc_s.so' appears multiple times
collect2: error: ld returned 1 exit status
FAIL: bootstrap

This patch changes things so that an error is given only when a -T
script or the default script is invoked more than once.  I'm still a
little nervous that we match script file names, not the entire path.

PR 24576
* ldfile.c (enum script_open_style): New.
(struct script_name_list): New.
(ldfile_open_command_file_1): Take a script_open_style param
rather than booleans.  Adjust callers.  Only fail when -T or
default -T script is invoked twice.
(ldfile_try_open_bfd): Revert last change.

ld/ChangeLog
ld/ldfile.c

index 7f7fef6..d46fd95 100644 (file)
@@ -1,3 +1,13 @@
+2019-05-23  Alan Modra  <amodra@gmail.com>
+
+       PR 24576
+       * ldfile.c (enum script_open_style): New.
+       (struct script_name_list): New.
+       (ldfile_open_command_file_1): Take a script_open_style param
+       rather than booleans.  Adjust callers.  Only fail when -T or
+       default -T script is invoked twice.
+       (ldfile_try_open_bfd): Revert last change.
+
 2019-05-22  Julius Werner  <jwerner@chromium.org>
            Nick Clifton  <nickc@redhat.com>
 
index 5bb08f7..7f60319 100644 (file)
@@ -186,7 +186,7 @@ ldfile_try_open_bfd (const char *attempt,
                  extern FILE *yyin;
 
                  /* Try to interpret the file as a linker script.  */
-                 ldfile_open_script_file (attempt);
+                 ldfile_open_command_file (attempt);
 
                  ldfile_assumed_script = TRUE;
                  parser_input = input_selected;
@@ -585,44 +585,56 @@ 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,
-                           bfd_boolean is_script)
+ldfile_open_command_file_1 (const char *name, enum script_open_style open_how)
 {
   FILE *ldlex_input_stack;
   bfd_boolean sysrooted;
+  static struct script_name_list *processed_scripts = NULL;
+  struct script_name_list *script;
+  size_t len;
 
-  if (is_script)
+  /* 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)
     {
-      static struct name_list *processed_scripts = NULL;
-      struct name_list *script;
-
-      /* 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)
        {
-         if (strcmp (name, script->name) == 0)
-           {
-             einfo (_("%F%P: error: linker script file '%s' appears multiple times\n"),
-                    name);
-             return;
-           }
+         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.  */
-      script = xmalloc (sizeof (name_list));
-      script->name = strdup (name);
-      script->next = processed_scripts;
-      processed_scripts = script;
     }
 
-  ldlex_input_stack = ldfile_find_command_file (name, default_only, &sysrooted);
-
+  /* 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);
@@ -643,13 +655,13 @@ ldfile_open_command_file_1 (const char *name,
 void
 ldfile_open_command_file (const char *name)
 {
-  ldfile_open_command_file_1 (name, FALSE, FALSE);
+  ldfile_open_command_file_1 (name, script_nonT);
 }
 
 void
 ldfile_open_script_file (const char *name)
 {
-  ldfile_open_command_file_1 (name, FALSE, TRUE);
+  ldfile_open_command_file_1 (name, script_T);
 }
 
 /* Open command file NAME at the default script location.  */
@@ -657,7 +669,7 @@ ldfile_open_script_file (const char *name)
 void
 ldfile_open_default_command_file (const char *name)
 {
-  ldfile_open_command_file_1 (name, TRUE, TRUE);
+  ldfile_open_command_file_1 (name, script_defaultT);
 }
 
 void