diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 8ab9a1f3fb..85d2cea2ee 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2016-06-20 H.J. Lu + + PR ld/18250 + PR ld/20267 + * elflink.c: Include plugin.h if BFD_SUPPORTS_PLUGINS is + defined. + (elf_link_is_defined_archive_symbol): Call + bfd_link_plugin_object_p on unknown plugin object and use the + IR symbol table if the input is an IR object. + * plugin.c (bfd_link_plugin_object_p): New function. + * plugin.h (bfd_link_plugin_object_p): New prototype. + 2016-06-20 H.J. Lu PR ld/20276 diff --git a/bfd/elflink.c b/bfd/elflink.c index d4e8db67ea..bb83854a27 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 a 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 2ab345216b..c66d95eaff 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 0ad92fcfb4..529f8c111f 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/ChangeLog b/ld/ChangeLog index cd161ab168..ca87628eb8 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,12 @@ +2016-06-20 H.J. Lu + + PR ld/20267 + * testsuite/ld-plugin/lto.exp (lto_link_tests): Add test for + PR ld/20267. + (lto_run_tests): Likewise. + * testsuite/ld-plugin/pr20267a.c: New file. + * testsuite/ld-plugin/pr20267b.c: Likewise. + 2016-06-20 H.J. Lu Alan Modra diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp index 7743719e3f..80bc469e59 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] } { @@ -341,6 +350,12 @@ set lto_run_tests [list \ [list "Run pr20276" \ "-O2 -flto tmpdir/pr20276a.o tmpdir/pr20276b.o" "" \ {dummy.c} "pr20276" "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 0000000000..0b37bc7d30 --- /dev/null +++ b/ld/testsuite/ld-plugin/pr20267a.c @@ -0,0 +1,12 @@ +#include + +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 0000000000..2ecbc2ca90 --- /dev/null +++ b/ld/testsuite/ld-plugin/pr20267b.c @@ -0,0 +1 @@ +int global_var = 20;