]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
PR26150, Assertion when asm() defines global symbols, -flto and --start-group
authorAlan Modra <amodra@gmail.com>
Tue, 23 Jun 2020 14:20:56 +0000 (23:50 +0930)
committerAlan Modra <amodra@gmail.com>
Tue, 23 Jun 2020 15:20:48 +0000 (00:50 +0930)
If an archive map contains symbols that aren't actually defined by the
indexed element for any reason, then loading that element will leave
the symbol undefined (or common).  This leads to the possibility of
the element being loaded again should the archive be searched again
due to the action of --start-group/--end-group.  The testcase
triggering this problem was an archive containing fat lto objects,
with the archive map incorrectly created by ar rather than gcc-ar.

PR 26150
* ldlang.c (ldlang_add_file): Assert that we aren't adding the
current end of link.next list again too.
* ldmain.c (add_archive_element): Don't load archive elements
again that have already been loaded.

ld/ChangeLog
ld/ldlang.c
ld/ldmain.c

index d59b00b75dae4122658602e13f5ac119be39d059..a2e3f62e9e76d59496636e58c83fee6035bc82ed 100644 (file)
@@ -1,3 +1,11 @@
+2020-06-23  Alan Modra  <amodra@gmail.com>
+
+       PR 26150
+       * ldlang.c (ldlang_add_file): Assert that we aren't adding the
+       current end of link.next list again too.
+       * ldmain.c (add_archive_element): Don't load archive elements
+       again that have already been loaded.
+
 2020-06-23  Alan Modra  <amodra@gmail.com>
 
        * testsuite/ld-elf/shared.exp (pr14170): Clear xfail for
index 8ab6a0b0c36f69660e544493d6ff4b454f0cfe43..38ed83a274b34138eff369f7d6282bda14c7c907 100644 (file)
@@ -7266,7 +7266,8 @@ ldlang_add_file (lang_input_statement_type *entry)
 
   /* The BFD linker needs to have a list of all input BFDs involved in
      a link.  */
-  ASSERT (entry->the_bfd->link.next == NULL);
+  ASSERT (link_info.input_bfds_tail != &entry->the_bfd->link.next
+         && entry->the_bfd->link.next == NULL);
   ASSERT (entry->the_bfd != link_info.output_bfd);
 
   *link_info.input_bfds_tail = entry->the_bfd;
index d34d30ae3371a88e94abb5d9774a8325149daee9..94a745ec31592175d9b10ae924df53879c59bcef 100644 (file)
@@ -822,10 +822,6 @@ add_archive_element (struct bfd_link_info *info,
   input->local_sym_name = bfd_get_filename (abfd);
   input->the_bfd = abfd;
 
-  parent = bfd_usrdata (abfd->my_archive);
-  if (parent != NULL && !parent->flags.reload)
-    parent->next = input;
-
   /* Save the original data for trace files/tries below, as plugins
      (if enabled) may possibly alter it to point to a replacement
      BFD, but we still want to output the original BFD filename.  */
@@ -853,6 +849,23 @@ add_archive_element (struct bfd_link_info *info,
     }
 #endif /* BFD_SUPPORTS_PLUGINS */
 
+  if (link_info.input_bfds_tail == &input->the_bfd->link.next
+      || input->the_bfd->link.next != NULL)
+    {
+      /* We have already loaded this element, and are attempting to
+        load it again.  This can happen when the archive map doesn't
+        match actual symbols defined by the element.  */
+      free (input);
+      bfd_set_error (bfd_error_malformed_archive);
+      return FALSE;
+    }
+
+  /* Set the file_chain pointer of archives to the last element loaded
+     from the archive.  See ldlang.c:find_rescan_insertion.  */
+  parent = bfd_usrdata (abfd->my_archive);
+  if (parent != NULL && !parent->flags.reload)
+    parent->next = input;
+
   ldlang_add_file (input);
 
   if (config.map_file != NULL)