diff options
-rw-r--r-- | bfd/elflink.c | 25 | ||||
-rw-r--r-- | bfd/plugin.c | 10 | ||||
-rw-r--r-- | bfd/plugin.h | 1 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/lto.exp | 15 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/pr20267a.c | 12 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/pr20267b.c | 1 |
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; |