From da422fa49d508e33b8f1b2bd9b8f719b831b199b Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Mon, 25 Apr 2022 10:51:39 -0700 Subject: [PATCH] LTO: Handle __real_SYM reference in IR When an IR symbol SYM is referenced in IR via __real_SYM, its resolution should be LDPR_PREVAILING_DEF, not PREVAILING_DEF_IRONLY, since LTO doesn't know that __real_SYM should be resolved by SYM. bfd/ PR ld/29086 * linker.c (bfd_wrapped_link_hash_lookup): Mark SYM is referenced via __real_SYM. include/ PR ld/29086 * bfdlink.h (bfd_link_hash_entry): Add ref_real. ld/ PR ld/29086 * plugin.c (get_symbols): Resolve SYM definition to LDPR_PREVAILING_DEF for __real_SYM reference. * testsuite/ld-plugin/lto.exp: Run PR ld/29086 test. * testsuite/ld-plugin/pr29086.c: New file. --- bfd/linker.c | 1 + include/bfdlink.h | 3 +++ ld/plugin.c | 7 +++++-- ld/testsuite/ld-plugin/lto.exp | 8 ++++++++ ld/testsuite/ld-plugin/pr29086.c | 19 +++++++++++++++++++ 5 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 ld/testsuite/ld-plugin/pr29086.c diff --git a/bfd/linker.c b/bfd/linker.c index 088c1d06f3d..e9ebdbad040 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -599,6 +599,7 @@ bfd_wrapped_link_hash_lookup (bfd *abfd, n[1] = '\0'; strcat (n, l + sizeof REAL - 1); h = bfd_link_hash_lookup (info->hash, n, create, true, follow); + h->ref_real = 1; free (n); return h; } diff --git a/include/bfdlink.h b/include/bfdlink.h index 88cc8e26183..27a8e11cc22 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -114,6 +114,9 @@ struct bfd_link_hash_entry as distinct from a LTO IR object file. */ unsigned int non_ir_ref_dynamic : 1; + /* The symbol, SYM, is referenced by __real_SYM in an object file. */ + unsigned int ref_real : 1; + /* Symbol is a built-in define. These will be overridden by PROVIDE in a linker script. */ unsigned int linker_def : 1; diff --git a/ld/plugin.c b/ld/plugin.c index 6db52d16802..fe203104677 100644 --- a/ld/plugin.c +++ b/ld/plugin.c @@ -863,8 +863,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. Also check for wrapper symbol. */ - if (blhe->non_ir_ref_regular || wrap_status == wrapper) + symbol is externally visible. Also check for __real_SYM + reference and wrapper symbol. */ + if (blhe->non_ir_ref_regular + || blhe->ref_real + || wrap_status == wrapper) res = LDPR_PREVAILING_DEF; else if (wrap_status == wrapped) res = LDPR_RESOLVED_IR; diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp index f4ea1d48533..4e8e2dc7748 100644 --- a/ld/testsuite/ld-plugin/lto.exp +++ b/ld/testsuite/ld-plugin/lto.exp @@ -522,6 +522,14 @@ set lto_link_elf_tests [list \ {{"nm" {-D} "pr28849.d"}} \ "pr28849" \ ] \ + [list \ + "PR ld/pr29086" \ + "-Wl,--wrap=foo" \ + "-O0 -flto" \ + {pr29086.c} \ + {} \ + "pr29086" \ + ] \ ] # PR 14918 checks that libgcc is not spuriously included in a shared link of diff --git a/ld/testsuite/ld-plugin/pr29086.c b/ld/testsuite/ld-plugin/pr29086.c new file mode 100644 index 00000000000..d333d68e262 --- /dev/null +++ b/ld/testsuite/ld-plugin/pr29086.c @@ -0,0 +1,19 @@ +int +foo (void) +{ + return 0; +} + +int +main () +{ + return foo (); +} + +extern int __real_foo (void); + +int +__wrap_foo (void) +{ + return __real_foo (); +} -- 2.30.2