From d215621ebe5a6b60dff2e60c788a0f761e3cb5bd Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 3 Jul 2014 16:32:45 +0930 Subject: [PATCH] Reload --as-needed libraries inside groups When a shared library appears within --start-group/--end-group ld may only discover a need for loading the library on the second or subsequent pass over archive libraries, as more objects are extracted. ld/ PR 17068 * ldlang.c (load_symbols): Always check flags.reload. (open_input_bfds): Always reload --as-needed shared libraries, not just when rescanning. * ldlang.h (struct lang_input_statement_flags): Update reload comment. * plugin.c (plugin_should_reload): Assume shared library arg. * plugin.h (plugin_should_reload): Update comment. ld/testsuite * ld-elf/pr17068.s: New. * ld-elf/pr17068a.s: New. * ld-elf/pr17068b.s: New. * ld-elf/pr17068c.s: New. * ld-elf/pr17068d.s: New. * ld-elf/pr17068e.s: New. * ld-elf/pr17068ez.s: New. * ld-elf/elf.exp: Run new test. --- ld/ChangeLog | 10 ++++++++++ ld/ldlang.c | 28 ++++++++++------------------ ld/ldlang.h | 2 +- ld/plugin.c | 6 ++---- ld/plugin.h | 2 +- ld/testsuite/ChangeLog | 11 +++++++++++ ld/testsuite/ld-elf/elf.exp | 26 ++++++++++++++++++++------ ld/testsuite/ld-elf/pr17068.s | 2 ++ ld/testsuite/ld-elf/pr17068a.s | 4 ++++ ld/testsuite/ld-elf/pr17068b.s | 4 ++++ ld/testsuite/ld-elf/pr17068c.s | 4 ++++ ld/testsuite/ld-elf/pr17068d.s | 6 ++++++ ld/testsuite/ld-elf/pr17068e.s | 3 +++ ld/testsuite/ld-elf/pr17068ez.s | 4 ++++ 14 files changed, 82 insertions(+), 30 deletions(-) create mode 100644 ld/testsuite/ld-elf/pr17068.s create mode 100644 ld/testsuite/ld-elf/pr17068a.s create mode 100644 ld/testsuite/ld-elf/pr17068b.s create mode 100644 ld/testsuite/ld-elf/pr17068c.s create mode 100644 ld/testsuite/ld-elf/pr17068d.s create mode 100644 ld/testsuite/ld-elf/pr17068e.s create mode 100644 ld/testsuite/ld-elf/pr17068ez.s diff --git a/ld/ChangeLog b/ld/ChangeLog index bfddd80..f7dd212 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,13 @@ +2014-07-03 Alan Modra + + PR 17068 + * ldlang.c (load_symbols): Always check flags.reload. + (open_input_bfds): Always reload --as-needed shared libraries, + not just when rescanning. + * ldlang.h (struct lang_input_statement_flags): Update reload comment. + * plugin.c (plugin_should_reload): Assume shared library arg. + * plugin.h (plugin_should_reload): Update comment. + 2014-07-01 Alan Modra * emultempl/ppc64elf.em (stub_added): Delete. diff --git a/ld/ldlang.c b/ld/ldlang.c index 60877b8..5e10c4a 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -2790,9 +2790,7 @@ load_symbols (lang_input_statement_type *entry, break; case bfd_object: -#ifdef ENABLE_PLUGINS if (!entry->flags.reload) -#endif ldlang_add_file (entry); if (trace_files || verbose) info_msg ("%I\n", entry); @@ -3268,38 +3266,32 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode) { lang_statement_union_type **os_tail; lang_statement_list_type add; + bfd *abfd; s->input_statement.target = current_target; /* If we are being called from within a group, and this is an archive which has already been searched, then force it to be researched unless the whole archive - has been loaded already. Do the same for a rescan. */ + has been loaded already. Do the same for a rescan. + Likewise reload --as-needed shared libs. */ if (mode != OPEN_BFD_NORMAL #ifdef ENABLE_PLUGINS && ((mode & OPEN_BFD_RESCAN) == 0 || plugin_insert == NULL) #endif - && !s->input_statement.flags.whole_archive && s->input_statement.flags.loaded - && s->input_statement.the_bfd != NULL - && bfd_check_format (s->input_statement.the_bfd, - bfd_archive)) - s->input_statement.flags.loaded = FALSE; -#ifdef ENABLE_PLUGINS - /* When rescanning, reload --as-needed shared libs. */ - else if ((mode & OPEN_BFD_RESCAN) != 0 - && plugin_insert == NULL - && s->input_statement.flags.loaded - && s->input_statement.flags.add_DT_NEEDED_for_regular - && s->input_statement.the_bfd != NULL - && ((s->input_statement.the_bfd->flags) & DYNAMIC) != 0 - && plugin_should_reload (s->input_statement.the_bfd)) + && (abfd = s->input_statement.the_bfd) != NULL + && ((bfd_get_format (abfd) == bfd_archive + && !s->input_statement.flags.whole_archive) + || (bfd_get_format (abfd) == bfd_object + && ((abfd->flags) & DYNAMIC) != 0 + && s->input_statement.flags.add_DT_NEEDED_for_regular + && plugin_should_reload (abfd)))) { s->input_statement.flags.loaded = FALSE; s->input_statement.flags.reload = TRUE; } -#endif os_tail = lang_output_section_statement.tail; lang_list_init (&add); diff --git a/ld/ldlang.h b/ld/ldlang.h index 7d69c56..0f7fdd4 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -279,7 +279,7 @@ struct lang_input_statement_flags /* Set if the file was claimed from an archive. */ unsigned int claim_archive : 1; - /* Set if reloading an --as-needed lib. */ + /* Set if reloading an archive or --as-needed lib. */ unsigned int reload : 1; #endif /* ENABLE_PLUGINS */ }; diff --git a/ld/plugin.c b/ld/plugin.c index 2a6d7c5..cd6ae60 100644 --- a/ld/plugin.c +++ b/ld/plugin.c @@ -1029,13 +1029,11 @@ plugin_notice (struct bfd_link_info *info, return TRUE; } -/* Return true if bfd is a dynamic library that should be reloaded. */ +/* Return true if ABFD, a dynamic library, should be reloaded. */ bfd_boolean plugin_should_reload (bfd *abfd) { - return ((abfd->flags & DYNAMIC) != 0 - && bfd_get_flavour (abfd) == bfd_target_elf_flavour - && bfd_get_format (abfd) == bfd_object + return (bfd_get_flavour (abfd) == bfd_target_elf_flavour && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0); } diff --git a/ld/plugin.h b/ld/plugin.h index beae7ab..1e239ca 100644 --- a/ld/plugin.h +++ b/ld/plugin.h @@ -66,7 +66,7 @@ extern void plugin_call_cleanup (void); add_symbols hook has been called so that it can be read when linking. */ extern bfd *plugin_get_ir_dummy_bfd (const char *name, bfd *template); -/* Return true if bfd is a dynamic library that should be reloaded. */ +/* Return true if ABFD, a dynamic library, should be reloaded. */ extern bfd_boolean plugin_should_reload (bfd *); #endif /* !def GLD_PLUGIN_H */ diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index b59f584..7d3a6e4 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2014-07-03 Alan Modra + + * ld-elf/pr17068.s: New. + * ld-elf/pr17068a.s: New. + * ld-elf/pr17068b.s: New. + * ld-elf/pr17068c.s: New. + * ld-elf/pr17068d.s: New. + * ld-elf/pr17068e.s: New. + * ld-elf/pr17068ez.s: New. + * ld-elf/elf.exp: Run new test. + 2014-07-02 Alan Modra * ld-powerpc/ambiguousv1.d: Match symbol table too. diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp index 4c8ca3a..839c931 100644 --- a/ld/testsuite/ld-elf/elf.exp +++ b/ld/testsuite/ld-elf/elf.exp @@ -77,13 +77,12 @@ if { ![istarget hppa64*-hpux*] } { } } -# Run a test to check linking a shared library with a broken linker -# script that accidentally marks dynamic sections as notes. The -# resulting executable is not expected to work, but the linker -# should not seg-fault whilst creating the binary. -# -# Only run the test on targets thats support creating shared libraries. +# Only run these tests on targets thats support creating shared libraries. if { [check_shared_lib_support] } then { + # Run a test to check linking a shared library with a broken linker + # script that accidentally marks dynamic sections as notes. The + # resulting executable is not expected to work, but the linker + # should not seg-fault whilst creating the binary. setup_xfail "tic6x-*-*" run_ld_link_tests { {"Build shared library for next test" @@ -93,6 +92,21 @@ if { [check_shared_lib_support] } then { { { ld "note-3.l" } } "a.out" } } + setup_xfail "tic6x-*-*" + run_ld_link_tests { + {"Build pr17068.so" + "-shared" "" "" + {pr17068d.s} {} "pr17068.so"} + {"Build pr17068a.a" + "" "" "" + {pr17068a.s pr17068c.s pr17068ez.s} {} "pr17068a.a"} + {"Build pr17068b.a" + "" "" "" + {pr17068b.s pr17068e.s} {} "pr17068b.a"} + {"pr17068 link --as-needed lib in group" + "--as-needed" "--start-group tmpdir/pr17068a.a tmpdir/pr17068.so tmpdir/pr17068b.a --end-group" "" + {start.s pr17068.s} {} "pr17068"} + } } set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]] diff --git a/ld/testsuite/ld-elf/pr17068.s b/ld/testsuite/ld-elf/pr17068.s new file mode 100644 index 0000000..9675ab4 --- /dev/null +++ b/ld/testsuite/ld-elf/pr17068.s @@ -0,0 +1,2 @@ + .data + .dc.a a diff --git a/ld/testsuite/ld-elf/pr17068a.s b/ld/testsuite/ld-elf/pr17068a.s new file mode 100644 index 0000000..552697c --- /dev/null +++ b/ld/testsuite/ld-elf/pr17068a.s @@ -0,0 +1,4 @@ + .data + .globl a +a: + .dc.a b diff --git a/ld/testsuite/ld-elf/pr17068b.s b/ld/testsuite/ld-elf/pr17068b.s new file mode 100644 index 0000000..aa536f2 --- /dev/null +++ b/ld/testsuite/ld-elf/pr17068b.s @@ -0,0 +1,4 @@ + .data + .globl b +b: + .dc.a c diff --git a/ld/testsuite/ld-elf/pr17068c.s b/ld/testsuite/ld-elf/pr17068c.s new file mode 100644 index 0000000..1d78f6d --- /dev/null +++ b/ld/testsuite/ld-elf/pr17068c.s @@ -0,0 +1,4 @@ + .data + .globl c +c: + .dc.a d diff --git a/ld/testsuite/ld-elf/pr17068d.s b/ld/testsuite/ld-elf/pr17068d.s new file mode 100644 index 0000000..6165128 --- /dev/null +++ b/ld/testsuite/ld-elf/pr17068d.s @@ -0,0 +1,6 @@ + .data + .globl d + .type d,%object +d: + .dc.a e + .size d,.-d diff --git a/ld/testsuite/ld-elf/pr17068e.s b/ld/testsuite/ld-elf/pr17068e.s new file mode 100644 index 0000000..095eb89 --- /dev/null +++ b/ld/testsuite/ld-elf/pr17068e.s @@ -0,0 +1,3 @@ + .data + .globl e +e: diff --git a/ld/testsuite/ld-elf/pr17068ez.s b/ld/testsuite/ld-elf/pr17068ez.s new file mode 100644 index 0000000..70e040d --- /dev/null +++ b/ld/testsuite/ld-elf/pr17068ez.s @@ -0,0 +1,4 @@ + .data + .globl e +e: + .dc.a z -- 2.7.4