@@ -737,6 +737,10 @@ struct elf_link_hash_table
/* Small local sym cache. */
struct sym_cache sym_cache;
+ /* Hash table of symbols which are first defined in archives or shared
+ objects when there are any IR inputs. */
+ struct bfd_link_hash_table *first_hash;
+
/* Short-cuts to get to dynamic linker sections. */
asection *sgot;
asection *sgotplt;
@@ -4265,7 +4265,22 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
}
if ((abfd->flags & DYNAMIC) == 0)
- dynamic = false;
+ {
+ dynamic = false;
+ if ((abfd->flags & BFD_PLUGIN) != 0
+ && is_elf_hash_table (&htab->root)
+ && htab->first_hash == NULL)
+ {
+ /* Initialize first_hash for an IR input. */
+ htab->first_hash = (struct bfd_link_hash_table *)
+ xmalloc (sizeof (struct bfd_link_hash_table));
+ if (!bfd_hash_table_init (&htab->first_hash->table,
+ _bfd_link_hash_newfunc,
+ sizeof (struct bfd_link_hash_entry)))
+ info->callbacks->einfo
+ (_("%F%P: first_hash failed to initialize: %E\n"));
+ }
+ }
else
{
dynamic = true;
@@ -5118,16 +5133,31 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if (skip)
continue;
- /* Override a definition only if the new symbol matches the
- existing one. */
- if (override && matched)
- definition = false;
-
h = *sym_hash;
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ /* Override a definition only if the new symbol matches the
+ existing one. */
+ if (override && matched)
+ {
+ definition = false;
+ if (htab->first_hash != NULL
+ && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0
+ && h->root.non_ir_ref_regular)
+ {
+ /* When reloading --as-needed shared objects for new
+ symbols added from IR inputs, if this shared object
+ has the first definition, use it. */
+ struct bfd_link_hash_entry *e
+ = bfd_link_hash_lookup (htab->first_hash, name,
+ false, false, true);
+ if (e != NULL && e->u.undef.abfd == abfd)
+ definition = true;
+ }
+ }
+
if (h->versioned != unversioned
&& elf_tdata (abfd)->verdef != NULL
&& vernum > 1
@@ -5477,8 +5507,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if (!add_needed
&& matched
&& definition
- && h->root.type != bfd_link_hash_indirect
- && ((dynsym
+ && h->root.type != bfd_link_hash_indirect)
+ {
+ if ((dynsym
&& h->ref_regular_nonweak)
|| (old_bfd != NULL
&& (old_bfd->flags & BFD_PLUGIN) != 0
@@ -5487,37 +5518,60 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
|| (h->ref_dynamic_nonweak
&& (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0
&& !on_needed_list (elf_dt_name (abfd),
- htab->needed, NULL))))
- {
- const char *soname = elf_dt_name (abfd);
+ htab->needed, NULL)))
+ {
+ const char *soname = elf_dt_name (abfd);
+
+ info->callbacks->minfo ("%!", soname, old_bfd,
+ h->root.root.string);
+
+ /* A symbol from a library loaded via DT_NEEDED of some
+ other library is referenced by a regular object.
+ Add a DT_NEEDED entry for it. Issue an error if
+ --no-add-needed is used and the reference was not
+ a weak one. */
+ if (old_bfd != NULL
+ && (elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: undefined reference to symbol '%s'"),
+ old_bfd, name);
+ bfd_set_error (bfd_error_missing_dso);
+ goto error_free_vers;
+ }
- info->callbacks->minfo ("%!", soname, old_bfd,
- h->root.root.string);
+ elf_dyn_lib_class (abfd) = (enum dynamic_lib_link_class)
+ (elf_dyn_lib_class (abfd) & ~DYN_AS_NEEDED);
- /* A symbol from a library loaded via DT_NEEDED of some
- other library is referenced by a regular object.
- Add a DT_NEEDED entry for it. Issue an error if
- --no-add-needed is used and the reference was not
- a weak one. */
- if (old_bfd != NULL
- && (elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
- {
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%pB: undefined reference to symbol '%s'"),
- old_bfd, name);
- bfd_set_error (bfd_error_missing_dso);
- goto error_free_vers;
+ /* Create dynamic sections for backends that require
+ that be done before setup_gnu_properties. */
+ if (!_bfd_elf_link_create_dynamic_sections (abfd, info))
+ return false;
+ add_needed = true;
}
+ else if (dynamic
+ && htab->first_hash != NULL
+ && h->root.u.def.section->owner == abfd)
+ {
+ /* Add this symbol to first hash if this shared
+ object has the first definition. */
+ struct bfd_link_hash_entry *e
+ = bfd_link_hash_lookup (htab->first_hash, name, true,
+ false, true);
+ if (e == NULL)
+ info->callbacks->einfo
+ (_("%F%P: %pB: failed to add %s to first hash\n"),
+ abfd, name);
- elf_dyn_lib_class (abfd) = (enum dynamic_lib_link_class)
- (elf_dyn_lib_class (abfd) & ~DYN_AS_NEEDED);
-
- /* Create dynamic sections for backends that require
- that be done before setup_gnu_properties. */
- if (!_bfd_elf_link_create_dynamic_sections (abfd, info))
- return false;
- add_needed = true;
+ if (e->type == bfd_link_hash_new)
+ {
+ /* Change the type to bfd_link_hash_defined and
+ store ABFD in u.undef->abfd. */
+ e->type = bfd_link_hash_defined;
+ e->u.undef.abfd = abfd;
+ }
+ }
}
}
}
@@ -5963,7 +6017,30 @@ _bfd_elf_archive_symbol_lookup (bfd *abfd,
p = strchr (name, ELF_VER_CHR);
if (p == NULL || p[1] != ELF_VER_CHR)
- return h;
+ {
+ struct elf_link_hash_table *htab = elf_hash_table (info);
+ if (htab->first_hash != NULL)
+ {
+ /* Add this symbol to first hash if this archive has the
+ first definition. */
+ struct bfd_link_hash_entry *e
+ = bfd_link_hash_lookup (htab->first_hash, name, true,
+ false, true);
+ if (e == NULL)
+ info->callbacks->einfo
+ (_("%F%P: %pB: failed to add %s to first hash\n"),
+ abfd, name);
+
+ if (e->type == bfd_link_hash_new)
+ {
+ /* Change the type to bfd_link_hash_defined and store
+ ABFD in u.undef->abfd. */
+ e->type = bfd_link_hash_defined;
+ e->u.undef.abfd = abfd;
+ }
+ }
+ return h;
+ }
/* First check with only one `@'. */
len = strlen (name);
@@ -6102,7 +6179,23 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
if (h->type != bfd_link_hash_undefweak)
/* Symbol must be defined. Don't check it again. */
included[i] = true;
- continue;
+
+ /* Ignore the archive if the symbol isn't defined in a
+ shared object. */
+ if (!((struct elf_link_hash_entry *) h)->def_dynamic)
+ continue;
+ /* Ignore the dynamic definition if symbol is first
+ defined in this archive. */
+ struct elf_link_hash_table *htab = elf_hash_table (info);
+ if (htab->first_hash != NULL)
+ {
+ struct bfd_link_hash_entry *e
+ = bfd_link_hash_lookup (htab->first_hash,
+ symdef->name, false, false,
+ true);
+ if (e == NULL || e->u.undef.abfd != abfd)
+ continue;
+ }
}
/* We need to include this archive member. */
@@ -8185,6 +8278,11 @@ _bfd_elf_link_hash_table_free (bfd *obfd)
_bfd_elf_strtab_free (htab->dynstr);
_bfd_merge_sections_free (htab->merge_info);
_bfd_generic_link_hash_table_free (obfd);
+ if (htab->first_hash != NULL)
+ {
+ bfd_hash_table_free (&htab->first_hash->table);
+ free (htab->first_hash);
+ }
}
/* This is a hook for the ELF emulation code in the generic linker to
@@ -539,6 +539,22 @@ set lto_link_elf_tests [list \
"" \
"pr30281.so" \
] \
+ [list \
+ "Build pr31482b.a" \
+ "" \
+ "" \
+ {pr31482b.c} \
+ "" \
+ "pr31482b.a" \
+ ] \
+ [list \
+ "Build pr31482c.so" \
+ "-shared" \
+ "-fPIC" \
+ {pr31482c.c} \
+ "" \
+ "pr31482c.so" \
+ ] \
]
# PR 14918 checks that libgcc is not spuriously included in a shared link of
@@ -722,6 +738,22 @@ set lto_run_elf_shared_tests [list \
{-Wl,--as-needed,-R,tmpdir} {} \
{lto-19c.c} {lto-19.exe} {pass.out} {-flto -O2} {c} {} \
{tmpdir/liblto-19.so tmpdir/liblto-19.a}] \
+ [list {pr31482a} \
+ {-Wl,--no-as-needed,-R,tmpdir} {} \
+ {pr31482a.c} {pr31482a.exe} {pass.out} {-flto} {c} {} \
+ {tmpdir/pr31482b.a tmpdir/pr31482c.so}] \
+ [list {pr31482b} \
+ {-Wl,--no-as-needed,-R,tmpdir} {} \
+ {pr31482a.c} {pr31482b.exe} {pass1.out} {-flto} {c} {} \
+ {tmpdir/pr31482c.so tmpdir/pr31482b.a}] \
+ [list {pr31489a} \
+ {-Wl,--as-needed,-R,tmpdir} {} \
+ {pr31482a.c} {pr31489a.exe} {pass.out} {-flto} {c} {} \
+ {tmpdir/pr31482b.a tmpdir/pr31482c.so}] \
+ [list {pr31489b} \
+ {-Wl,--as-needed,-R,tmpdir} {} \
+ {pr31482a.c} {pr31489b.exe} {pass1.out} {-flto} {c} {} \
+ {tmpdir/pr31482c.so tmpdir/pr31482b.a}] \
]
# LTO run-time tests for ELF
new file mode 100644
@@ -0,0 +1 @@
+PASS1
new file mode 100644
@@ -0,0 +1,8 @@
+#include <stdlib.h>
+
+int
+main()
+{
+ abort ();
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,9 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+void
+abort (void)
+{
+ printf ("PASS\n");
+ exit (0);
+}
new file mode 100644
@@ -0,0 +1,9 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+void
+abort (void)
+{
+ printf ("PASS1\n");
+ exit (0);
+}