LTO: Properly handle wrapper symbols in IR

When a wrapper symbol, __wrap_FOO, is defined in IR, its resolution
should be LDPR_PREVAILING_DEF, not PREVAILING_DEF_IRONLY, since LTO
doesn't know that __wrap_FOO provides definition of FOO.  And resolution
of FOO should be LDPR_RESOLVED_IR since it is resolved by __wrap_FOO in
IR.

	PR ld/24406
	* ld.texi: Remove LTO warning from --wrap.
	* plugin.c (get_symbols): Update resolution for wrapper and
	wrapped symbols.
	* testsuite/ld-plugin/lto.exp: Run ld/24406 tests.
	* testsuite/ld-plugin/pr24406-1.c: New file.
	* testsuite/ld-plugin/pr24406-2a.c: Likewise.
	* testsuite/ld-plugin/pr24406-2b.c: Likewise.
This commit is contained in:
H.J. Lu 2019-04-25 07:53:46 -07:00
parent 723adb650a
commit 6fe014bcd3
7 changed files with 89 additions and 10 deletions

View File

@ -1,3 +1,14 @@
2019-04-25 H.J. Lu <hongjiu.lu@intel.com>
PR ld/24406
* ld.texi: Remove LTO warning from --wrap.
* plugin.c (get_symbols): Update resolution for wrapper and
wrapped symbols.
* testsuite/ld-plugin/lto.exp: Run ld/24406 tests.
* testsuite/ld-plugin/pr24406-1.c: New file.
* testsuite/ld-plugin/pr24406-2a.c: Likewise.
* testsuite/ld-plugin/pr24406-2b.c: Likewise.
2019-04-25 Sudakshina Das <sudi.das@arm.com>
* testsuite/ld-aarch64/bti-pac-plt-1.d: Update.

View File

@ -2438,9 +2438,6 @@ g (void)
@}
@end smallexample
Please keep in mind that with link-time optimization (LTO) enabled, your whole
program may be a translation unit.
@kindex --eh-frame-hdr
@kindex --no-eh-frame-hdr
@item --eh-frame-hdr

View File

@ -741,13 +741,32 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms,
struct bfd_link_hash_entry *blhe;
asection *owner_sec;
int res;
struct bfd_link_hash_entry *h
= bfd_link_hash_lookup (link_info.hash, syms[n].name,
FALSE, FALSE, TRUE);
enum { wrap_none, wrapper, wrapped } wrap_status = wrap_none;
if (syms[n].def != LDPK_UNDEF)
blhe = bfd_link_hash_lookup (link_info.hash, syms[n].name,
FALSE, FALSE, TRUE);
if (syms[n].def != LDPK_UNDEF && syms[n].def != LDPK_WEAKUNDEF)
{
blhe = h;
if (blhe)
{
/* Check if a symbol is a wrapper symbol. */
struct bfd_link_hash_entry *unwrap
= unwrap_hash_lookup (&link_info, (bfd *) abfd, blhe);
if (unwrap && unwrap != h)
wrap_status = wrapper;
}
}
else
blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd, &link_info,
syms[n].name, FALSE, FALSE, TRUE);
{
blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
&link_info, syms[n].name,
FALSE, FALSE, TRUE);
/* Check if a symbol is a wrapped symbol. */
if (blhe && blhe != h)
wrap_status = wrapped;
}
if (!blhe)
{
/* The plugin is called to claim symbols in an archive element
@ -833,9 +852,11 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms,
/* We need to know if the sym is referenced from non-IR files. Or
even potentially-referenced, perhaps in a future final link if
this is a partial one, perhaps dynamically at load-time if the
symbol is externally visible. */
if (blhe->non_ir_ref_regular)
symbol is externally visible. Also check for wrapper symbol. */
if (blhe->non_ir_ref_regular || wrap_status == wrapper)
res = LDPR_PREVAILING_DEF;
else if (wrap_status == wrapped)
res = LDPR_RESOLVED_IR;
else if (is_visible_from_outside (&syms[n], blhe))
res = def_ironly_exp;
}

View File

@ -231,6 +231,9 @@ set lto_link_tests [list \
{pr23958.c} \
"" \
"libpr23958.so"] \
[list "Build pr24406-2b.o" \
"" "-O2 -fno-lto" \
{pr24406-2b.c}] \
]
if { [at_least_gcc_version 4 7] } {
@ -434,6 +437,15 @@ set lto_run_tests [list \
"-O2 -flto" "" \
{dummy.c} "pr22751" "pass.out" "-flto -O2" "c" "" \
"-Wl,--whole-archive tmpdir/pr22751.a -Wl,--no-whole-archive"] \
[list "Run pr24406-1" \
"-O2 -flto" "" \
{pr24406-1.c} "pr24406-1" "pass.out" "-flto -O2" "c" "" \
"-Wl,--wrap=read"] \
[list "Run pr24406-2" \
"-O2 -flto" "" \
{pr24406-2a.c} "pr24406-2" "pass.out" \
"-flto -O2" "c" "" \
"tmpdir/pr24406-2b.o -Wl,--wrap=cook"] \
]
if { [at_least_gcc_version 4 7] } {

View File

@ -0,0 +1,17 @@
#include <stdio.h>
#include <unistd.h>
ssize_t
__wrap_read (int fd, void *buffer, size_t count)
{
puts ("PASS");
return fd + count + sizeof (buffer);
}
int
main ()
{
int i = read (1, "abc", 5);
return i == 0;
}

View File

@ -0,0 +1,17 @@
#include <stdio.h>
extern int cook(void);
int __wrap_cook(void)
{
puts ("PASS");
return 0;
}
int main()
{
if (cook () == -1)
__builtin_abort ();
return 0;
}

View File

@ -0,0 +1,4 @@
int cook(void)
{
return -1;
}