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>
* emultempl/ppc64elf.em (stub_added): Delete.

View File

@ -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);

View File

@ -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 */
};

View File

@ -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);
}

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. */
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 */

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>
* 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
# 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]]

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