[PATCH] elf: Don't load archive element after dynamic definition
H.J. Lu
hjl.tools@gmail.com
Tue Aug 25 17:28:42 GMT 2020
Don't load the archive element after seeing a definition in a shared
object.
bfd/
PR ld/26530
* elflink.c (elf_link_add_object_symbols): Also preserve the
dynamic_def bit for --as-needed.
(elf_link_add_archive_symbols): Don't load the archive element
after seeing a definition in a shared object.
ld/
PR ld/26530
* testsuite/ld-plugin/lto.exp: Run PR ld/26530 tests.
* testsuite/ld-plugin/pr26530a.c: New file.
* testsuite/ld-plugin/pr26530b.c: Likewise.
* testsuite/ld-plugin/pr26530c.c: Likewise.
---
bfd/elflink.c | 20 ++++++++++++++------
ld/testsuite/ld-plugin/lto.exp | 20 ++++++++++++++++++++
ld/testsuite/ld-plugin/pr26530a.c | 5 +++++
ld/testsuite/ld-plugin/pr26530b.c | 7 +++++++
ld/testsuite/ld-plugin/pr26530c.c | 12 ++++++++++++
5 files changed, 58 insertions(+), 6 deletions(-)
create mode 100644 ld/testsuite/ld-plugin/pr26530a.c
create mode 100644 ld/testsuite/ld-plugin/pr26530b.c
create mode 100644 ld/testsuite/ld-plugin/pr26530c.c
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 17a423270e..97e6ece97e 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -5340,7 +5340,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
struct elf_link_hash_entry *h;
bfd_size_type size;
unsigned int alignment_power;
- unsigned int non_ir_ref_dynamic;
+ struct elf_link_hash_entry preserved_h;
for (p = htab->root.table.table[i]; p != NULL; p = p->next)
{
@@ -5362,10 +5362,11 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
size = 0;
alignment_power = 0;
}
- /* Preserve non_ir_ref_dynamic so that this symbol
- will be exported when the dynamic lib becomes needed
- in the second pass. */
- non_ir_ref_dynamic = h->root.non_ir_ref_dynamic;
+ /* Preserve some bits so that this symbol will be exported
+ when the dynamic lib becomes needed in the second pass.
+ and to avoid linking in an archive after the dynamic
+ lib. */
+ preserved_h = *h;
memcpy (p, old_ent, htab->root.table.entsize);
old_ent = (char *) old_ent + htab->root.table.entsize;
h = (struct elf_link_hash_entry *) p;
@@ -5382,7 +5383,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if (alignment_power > h->root.u.c.p->alignment_power)
h->root.u.c.p->alignment_power = alignment_power;
}
- h->root.non_ir_ref_dynamic = non_ir_ref_dynamic;
+ h->root.non_ir_ref_dynamic
+ = preserved_h.root.non_ir_ref_dynamic;
+ h->dynamic_def = preserved_h.dynamic_def;
}
}
@@ -5819,6 +5822,11 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
if (h == NULL)
continue;
+ /* Don't load the archive element after seeing a definition
+ in a shared object. */
+ if (h->dynamic_def)
+ continue;
+
if (h->root.type == bfd_link_hash_undefined)
{
/* If the archive element has already been loaded then one
diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp
index 6a37025db5..8331500b33 100644
--- a/ld/testsuite/ld-plugin/lto.exp
+++ b/ld/testsuite/ld-plugin/lto.exp
@@ -419,6 +419,18 @@ set lto_link_elf_tests [list \
"-shared -Wl,--exclude-libs,ALL tmpdir/pr25618a.o tmpdir/pr25618.a" \
"-fpic" \
{dummy.c} {{readelf {--dyn-syms --wide} pr25618.d}} "pr25618.so" "c++"] \
+ [list "Build pr26530a.so" \
+ "-shared" "-O2 -fpic $no_lto" \
+ {pr26530a.c} {} "pr26530a.so" "c"] \
+ [list "Build pr26530b.so" \
+ "-shared" "-O2 -fpic $no_lto" \
+ {pr26530b.c} {} "pr26530b.so" "c"] \
+ [list "Build pr26530a.a" \
+ "" "-O2 $no_lto" \
+ {pr26530a.c} {} "pr26530a.a" "c"] \
+ [list "Build pr26530b.a" \
+ "" "-O2 $no_lto" \
+ {pr26530b.c} {} "pr26530b.a" "c"] \
]
# PR 14918 checks that libgcc is not spuriously included in a shared link of
@@ -582,6 +594,14 @@ set lto_run_elf_shared_tests [list \
[list {pr22220b} \
{-flto -fuse-linker-plugin -Wl,--no-as-needed tmpdir/pr22220lib.so tmpdir/pr22220main.o} {} \
{dummy.c} {pr22220b.exe} {pass.out} {} {c++}] \
+ [list "pr26530a" \
+ "-O2 -flto -fuse-linker-plugin" "" \
+ {pr26530c.c} "pr26530a.exe" "pass.out" "-O2 -flto" "c" {} \
+ "-Wl,--as-needed tmpdir/pr26530a.so tmpdir/pr26530b.a"] \
+ [list "pr26530b" \
+ "-O2 -flto -fuse-linker-plugin" "" \
+ {pr26530c.c} "pr26530b.exe" "pass.out" "-O2 -flto" "c" {} \
+ "-Wl,--as-needed tmpdir/pr26530a.a tmpdir/pr26530b.so"] \
]
# LTO run-time tests for ELF
diff --git a/ld/testsuite/ld-plugin/pr26530a.c b/ld/testsuite/ld-plugin/pr26530a.c
new file mode 100644
index 0000000000..08e746911e
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr26530a.c
@@ -0,0 +1,5 @@
+const char *
+lrealpath (const char *a)
+{
+ return a;
+}
diff --git a/ld/testsuite/ld-plugin/pr26530b.c b/ld/testsuite/ld-plugin/pr26530b.c
new file mode 100644
index 0000000000..0eb003f470
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr26530b.c
@@ -0,0 +1,7 @@
+#include <stdlib.h>
+
+void
+lrealpath (void)
+{
+ abort ();
+}
diff --git a/ld/testsuite/ld-plugin/pr26530c.c b/ld/testsuite/ld-plugin/pr26530c.c
new file mode 100644
index 0000000000..c8ef23675e
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr26530c.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+const char *lrealpath(const char *a);
+
+int
+main(int argc, char **argv)
+{
+ const char *path = lrealpath (argv[0]);
+ if (path[0] != '\0')
+ printf ("PASS\n");
+ return 0;
+}
--
2.26.2
More information about the Binutils
mailing list