Author: Fangrui Song Date: 2021-01-22T09:20:29-08:00 New Revision: d24b94f070ff4e6621b66d5df4b3a15a693d52bf
URL: https://github.com/llvm/llvm-project/commit/d24b94f070ff4e6621b66d5df4b3a15a693d52bf DIFF: https://github.com/llvm/llvm-project/commit/d24b94f070ff4e6621b66d5df4b3a15a693d52bf.diff LOG: [ELF] --wrap: retain __wrap_foo if foo is defined in an object/bitcode file If foo is referenced in any object file, bitcode file or shared object, `__wrap_foo` should be retained as the redirection target of sym (f96ff3c0f8ebd941b3f6b345164c3d858b781484). If the object file defining foo has foo references, we cannot easily distinguish the case from cases where foo is not referenced (we haven't scanned relocations). Retain `__wrap_foo` because we choose to wrap sym references regardless of whether sym is defined to keep non-LTO/LTO/relocatable links' behaviors similar https://sourceware.org/bugzilla/show_bug.cgi?id=26358 . If foo is defined in a shared object, `__wrap_foo` can still be omitted (`wrap-dynamic-undef.s`). Reviewed By: andrewng Differential Revision: https://reviews.llvm.org/D95152 Added: lld/test/ELF/lto/wrap-defined.ll lld/test/ELF/wrap-defined.s Modified: lld/ELF/Driver.cpp lld/ELF/Options.td lld/docs/ld.lld.1 lld/test/ELF/wrap-shlib-undefined.s Removed: ################################################################################ diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index de613b5c9d19..72d245e5dc01 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1922,7 +1922,13 @@ static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) { // Tell LTO not to eliminate these symbols. sym->isUsedInRegularObj = true; - if (sym->referenced) + // If sym is referenced in any object file, bitcode file or shared object, + // retain wrap which is the redirection target of sym. If the object file + // defining sym has sym references, we cannot easily distinguish the case + // from cases where sym is not referenced. Retain wrap because we choose to + // wrap sym references regardless of whether sym is defined + // (https://sourceware.org/bugzilla/show_bug.cgi?id=26358). + if (sym->referenced || sym->isDefined()) wrap->isUsedInRegularObj = true; } return v; diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index f404fdd74385..c50aa84e30e7 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -473,8 +473,9 @@ defm whole_archive: B<"whole-archive", "Force load of all members in a static library", "Do not force load of all members in a static library (default)">; -defm wrap: Eq<"wrap", "Use wrapper functions for symbol">, - MetaVarName<"<symbol>">; +defm wrap : Eq<"wrap", "Redirect symbol references to __wrap_symbol and " + "__real_symbol references to symbol">, + MetaVarName<"<symbol>">; def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">, HelpText<"Linker option extensions">; diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 index 1449b02c4906..79a684def275 100644 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -635,7 +635,14 @@ Report unresolved symbols as warnings. .It Fl -whole-archive Force load of all members in a static library. .It Fl -wrap Ns = Ns Ar symbol -Use wrapper functions for symbol. +Redirect +.Ar symbol +references to +.Ar __wrap_symbol +and +.Ar __real_symbol +references to +.Ar symbol. .It Fl z Ar option Linker option extensions. .Bl -tag -width indent -compact diff --git a/lld/test/ELF/lto/wrap-defined.ll b/lld/test/ELF/lto/wrap-defined.ll new file mode 100644 index 000000000000..8a5abf8c1d85 --- /dev/null +++ b/lld/test/ELF/lto/wrap-defined.ll @@ -0,0 +1,21 @@ +; REQUIRES: x86 +;; Similar to ../wrap-defined.s but for LTO. + +; RUN: llvm-as %s -o %t.o +; RUN: ld.lld -shared %t.o -wrap=bar -o %t.so +; RUN: llvm-objdump -d %t.so | FileCheck %s + +; CHECK: <_start>: +; CHECK-NEXT: jmp {{.*}} <__wrap_bar@plt> + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @bar() { + ret void +} + +define void @_start() { + call void @bar() + ret void +} diff --git a/lld/test/ELF/wrap-defined.s b/lld/test/ELF/wrap-defined.s new file mode 100644 index 000000000000..026b52661726 --- /dev/null +++ b/lld/test/ELF/wrap-defined.s @@ -0,0 +1,33 @@ +# REQUIRES: x86 + +# RUN: rm -rf %t && split-file %s %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/main.s -o %t/main.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/wrap.s -o %t/wrap.o +# RUN: ld.lld -shared --soname=fixed %t/wrap.o -o %t/wrap.so + +## GNU ld does not wrap a defined symbol in an object file +## https://sourceware.org/bugzilla/show_bug.cgi?id=26358 +## We choose to wrap defined symbols so that LTO, non-LTO and relocatable links +## behave the same. The 'call bar' in main.o will reference __wrap_bar. We cannot +## easily distinguish the case from cases where bar is not referenced, so we +## export __wrap_bar whenever bar is defined, regardless of whether it is indeed +## referenced. + +# RUN: ld.lld -shared %t/main.o --wrap bar -o %t1.so +# RUN: llvm-objdump -d %t1.so | FileCheck %s +# RUN: ld.lld %t/main.o %t/wrap.so --wrap bar -o %t1 +# RUN: llvm-objdump -d %t1 | FileCheck %s + +# CHECK: <_start>: +# CHECK-NEXT: callq {{.*}} <__wrap_bar@plt> + +#--- main.s +.globl _start, bar +_start: + call bar +bar: + +#--- wrap.s +.globl __wrap_bar +__wrap_bar: + retq diff --git a/lld/test/ELF/wrap-shlib-undefined.s b/lld/test/ELF/wrap-shlib-undefined.s index 0c4a79171e27..2897b7e39ce2 100644 --- a/lld/test/ELF/wrap-shlib-undefined.s +++ b/lld/test/ELF/wrap-shlib-undefined.s @@ -23,11 +23,11 @@ # RUN: ld.lld %t/main.o %t/bar.so --wrap=foo -o %t2 # RUN: llvm-readelf --dyn-syms %t2 | FileCheck %s --check-prefix=CHECK2 -## The reference __real_foo from %t/bar.so causes foo to be exported. -## __wrap_foo is not used, thus not exported. -# CHECK2: Symbol table '.dynsym' contains 3 entries: +## See wrap-plt2.s why __wrap_foo is retained. +# CHECK2: Symbol table '.dynsym' contains 4 entries: # CHECK2: NOTYPE LOCAL DEFAULT UND # CHECK2-NEXT: NOTYPE GLOBAL DEFAULT UND bar +# CHECK2-NEXT: NOTYPE GLOBAL DEFAULT UND __wrap_foo # CHECK2-NEXT: NOTYPE GLOBAL DEFAULT 6 foo ## __wrap_bar is undefined. _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits