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.
This commit is contained in:
Alan Modra 2014-07-03 16:32:45 +09:30
parent fd48cee009
commit d215621ebe
14 changed files with 82 additions and 30 deletions

View File

@ -1,3 +1,13 @@
2014-07-03 Alan Modra <amodra@gmail.com>
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 <amodra@gmail.com> 2014-07-01 Alan Modra <amodra@gmail.com>
* emultempl/ppc64elf.em (stub_added): Delete. * emultempl/ppc64elf.em (stub_added): Delete.

View File

@ -2790,9 +2790,7 @@ load_symbols (lang_input_statement_type *entry,
break; break;
case bfd_object: case bfd_object:
#ifdef ENABLE_PLUGINS
if (!entry->flags.reload) if (!entry->flags.reload)
#endif
ldlang_add_file (entry); ldlang_add_file (entry);
if (trace_files || verbose) if (trace_files || verbose)
info_msg ("%I\n", entry); 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_union_type **os_tail;
lang_statement_list_type add; lang_statement_list_type add;
bfd *abfd;
s->input_statement.target = current_target; s->input_statement.target = current_target;
/* If we are being called from within a group, and this /* If we are being called from within a group, and this
is an archive which has already been searched, then is an archive which has already been searched, then
force it to be researched unless the whole archive 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 if (mode != OPEN_BFD_NORMAL
#ifdef ENABLE_PLUGINS #ifdef ENABLE_PLUGINS
&& ((mode & OPEN_BFD_RESCAN) == 0 && ((mode & OPEN_BFD_RESCAN) == 0
|| plugin_insert == NULL) || plugin_insert == NULL)
#endif #endif
&& !s->input_statement.flags.whole_archive
&& s->input_statement.flags.loaded && s->input_statement.flags.loaded
&& s->input_statement.the_bfd != NULL && (abfd = s->input_statement.the_bfd) != NULL
&& bfd_check_format (s->input_statement.the_bfd, && ((bfd_get_format (abfd) == bfd_archive
bfd_archive)) && !s->input_statement.flags.whole_archive)
s->input_statement.flags.loaded = FALSE; || (bfd_get_format (abfd) == bfd_object
#ifdef ENABLE_PLUGINS && ((abfd->flags) & DYNAMIC) != 0
/* When rescanning, reload --as-needed shared libs. */ && s->input_statement.flags.add_DT_NEEDED_for_regular
else if ((mode & OPEN_BFD_RESCAN) != 0 && plugin_should_reload (abfd))))
&& 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))
{ {
s->input_statement.flags.loaded = FALSE; s->input_statement.flags.loaded = FALSE;
s->input_statement.flags.reload = TRUE; s->input_statement.flags.reload = TRUE;
} }
#endif
os_tail = lang_output_section_statement.tail; os_tail = lang_output_section_statement.tail;
lang_list_init (&add); lang_list_init (&add);

View File

@ -279,7 +279,7 @@ struct lang_input_statement_flags
/* Set if the file was claimed from an archive. */ /* Set if the file was claimed from an archive. */
unsigned int claim_archive : 1; 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; unsigned int reload : 1;
#endif /* ENABLE_PLUGINS */ #endif /* ENABLE_PLUGINS */
}; };

View File

@ -1029,13 +1029,11 @@ plugin_notice (struct bfd_link_info *info,
return TRUE; 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 bfd_boolean
plugin_should_reload (bfd *abfd) plugin_should_reload (bfd *abfd)
{ {
return ((abfd->flags & DYNAMIC) != 0 return (bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& bfd_get_format (abfd) == bfd_object
&& (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0); && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0);
} }

View File

@ -66,7 +66,7 @@ extern void plugin_call_cleanup (void);
add_symbols hook has been called so that it can be read when linking. */ 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); 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 *); extern bfd_boolean plugin_should_reload (bfd *);
#endif /* !def GLD_PLUGIN_H */ #endif /* !def GLD_PLUGIN_H */

View File

@ -1,3 +1,14 @@
2014-07-03 Alan Modra <amodra@gmail.com>
* 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 <amodra@gmail.com> 2014-07-02 Alan Modra <amodra@gmail.com>
* ld-powerpc/ambiguousv1.d: Match symbol table too. * ld-powerpc/ambiguousv1.d: Match symbol table too.

View File

@ -77,13 +77,12 @@ if { ![istarget hppa64*-hpux*] } {
} }
} }
# Run a test to check linking a shared library with a broken linker # Only run these tests on targets thats support creating shared libraries.
# 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.
if { [check_shared_lib_support] } then { 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-*-*" setup_xfail "tic6x-*-*"
run_ld_link_tests { run_ld_link_tests {
{"Build shared library for next test" {"Build shared library for next test"
@ -93,6 +92,21 @@ if { [check_shared_lib_support] } then {
{ { ld "note-3.l" } } { { ld "note-3.l" } }
"a.out" } "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]] set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]

View File

@ -0,0 +1,2 @@
.data
.dc.a a

View File

@ -0,0 +1,4 @@
.data
.globl a
a:
.dc.a b

View File

@ -0,0 +1,4 @@
.data
.globl b
b:
.dc.a c

View File

@ -0,0 +1,4 @@
.data
.globl c
c:
.dc.a d

View File

@ -0,0 +1,6 @@
.data
.globl d
.type d,%object
d:
.dc.a e
.size d,.-d

View File

@ -0,0 +1,3 @@
.data
.globl e
e:

View File

@ -0,0 +1,4 @@
.data
.globl e
e:
.dc.a z