summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/elflink.c25
-rw-r--r--bfd/plugin.c10
-rw-r--r--bfd/plugin.h1
-rw-r--r--ld/testsuite/ld-plugin/lto.exp15
-rw-r--r--ld/testsuite/ld-plugin/pr20267a.c12
-rw-r--r--ld/testsuite/ld-plugin/pr20267b.c1
6 files changed, 58 insertions, 6 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c
index d4e8db67ea5..3aa7ddfe7b9 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -28,6 +28,9 @@
#include "safe-ctype.h"
#include "libiberty.h"
#include "objalloc.h"
+#ifdef BFD_SUPPORTS_PLUGINS
+#include "plugin.h"
+#endif
/* This struct is used to pass information to routines called via
elf_link_hash_traverse which must return failure. */
@@ -3124,15 +3127,25 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
if (abfd == NULL)
return FALSE;
- /* Return FALSE if the object has been claimed by plugin. */
- if (abfd->plugin_format == bfd_plugin_yes)
- return FALSE;
-
if (! bfd_check_format (abfd, bfd_object))
return FALSE;
- /* Select the appropriate symbol table. */
- if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
+ /* Select the appropriate symbol table. If we don't know if the
+ object file is an IR object, give linker LTO plugin an chance to
+ get the correct symbol table. */
+ if (abfd->plugin_format == bfd_plugin_yes
+#ifdef BFD_SUPPORTS_PLUGINS
+ || (abfd->plugin_format == bfd_plugin_unknown
+ && bfd_link_plugin_object_p (abfd))
+#endif
+ )
+ {
+ /* Use the IR symbol table if the object has been claimed by
+ plugin. */
+ abfd = abfd->plugin_dummy_bfd;
+ hdr = &elf_tdata (abfd)->symtab_hdr;
+ }
+ else if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
hdr = &elf_tdata (abfd)->symtab_hdr;
else
hdr = &elf_tdata (abfd)->dynsymtab_hdr;
diff --git a/bfd/plugin.c b/bfd/plugin.c
index 2ab345216b4..c66d95eaffc 100644
--- a/bfd/plugin.c
+++ b/bfd/plugin.c
@@ -287,6 +287,16 @@ bfd_plugin_specified_p (void)
return has_plugin > 0;
}
+/* Return TRUE if ABFD can be claimed by linker LTO plugin. */
+
+bfd_boolean
+bfd_link_plugin_object_p (bfd *abfd)
+{
+ if (ld_plugin_object_p)
+ return ld_plugin_object_p (abfd) != NULL;
+ return FALSE;
+}
+
extern const bfd_target plugin_vec;
/* Return TRUE if TARGET is a pointer to plugin_vec. */
diff --git a/bfd/plugin.h b/bfd/plugin.h
index 0ad92fcfb48..529f8c111fd 100644
--- a/bfd/plugin.h
+++ b/bfd/plugin.h
@@ -27,6 +27,7 @@ void bfd_plugin_set_program_name (const char *);
void bfd_plugin_set_plugin (const char *);
bfd_boolean bfd_plugin_target_p (const bfd_target *);
bfd_boolean bfd_plugin_specified_p (void);
+bfd_boolean bfd_link_plugin_object_p (bfd *);
void register_ld_plugin_object_p (const bfd_target *(*object_p) (bfd *));
typedef struct plugin_data_struct
diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp
index 9fa73e19cad..893eb7f2396 100644
--- a/ld/testsuite/ld-plugin/lto.exp
+++ b/ld/testsuite/ld-plugin/lto.exp
@@ -189,6 +189,15 @@ set lto_link_tests [list \
[list "Build pr20276b.o" \
"$plug_opt" "-flto $lto_no_fat" \
{pr20276b.c}] \
+ [list "Build pr20267a.o" \
+ "" "" \
+ {pr20267a.c}] \
+ [list "Build libpr20267a.a" \
+ "$plug_opt" "-flto $lto_fat" \
+ {pr20267b.c} {} "libpr20267a.a"] \
+ [list "Build libpr20267b.a" \
+ "$plug_opt" "-flto $lto_no_fat" \
+ {pr20267b.c} {} "libpr20267b.a"] \
]
if { [at_least_gcc_version 4 7] } {
@@ -344,6 +353,12 @@ set lto_run_tests [list \
[list "Run pr20276" \
"-O2 -flto tmpdir/pr20276a.o tmpdir/pr20267b.o" "" \
{dummy.c} "pr20267" "pass.out" "-flto -O2" "c"] \
+ [list "Run pr20267a" \
+ "-O2 -flto tmpdir/pr20267a.o tmpdir/libpr20267a.a" "" \
+ {dummy.c} "pr20267a" "pass.out" "-flto -O2" "c"] \
+ [list "Run pr20267b" \
+ "-O2 -flto tmpdir/pr20267a.o tmpdir/libpr20267b.a" "" \
+ {dummy.c} "pr20267b" "pass.out" "-flto -O2" "c"] \
]
if { [at_least_gcc_version 4 7] } {
diff --git a/ld/testsuite/ld-plugin/pr20267a.c b/ld/testsuite/ld-plugin/pr20267a.c
new file mode 100644
index 00000000000..0b37bc7d309
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr20267a.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+int global_var;
+extern void abort ();
+
+int main(void)
+{
+ if (global_var != 20)
+ abort ();
+ printf ("PASS\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/pr20267b.c b/ld/testsuite/ld-plugin/pr20267b.c
new file mode 100644
index 00000000000..2ecbc2ca908
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr20267b.c
@@ -0,0 +1 @@
+int global_var = 20;