Index: lld/ELF/Driver.cpp =================================================================== --- lld/ELF/Driver.cpp +++ lld/ELF/Driver.cpp @@ -2246,6 +2246,14 @@ Symbol *real = addUnusedUndefined(saver().save("__real_" + name)); Symbol *wrap = addUnusedUndefined(saver().save("__wrap_" + name), sym->binding); + + // If sym is lazy change the binding to weak. This allows a + // wrap function to be supplied which references sym via real + // and a --wrap sym option, and for these to only have an effect + // if sym has been included in the link. + if (sym->isLazy()) + sym->binding = STB_WEAK; + v.push_back({sym, real, wrap}); // We want to tell LTO not to inline symbols to be overwritten Index: lld/test/ELF/wrap-extract-real.ll =================================================================== --- /dev/null +++ lld/test/ELF/wrap-extract-real.ll @@ -0,0 +1,26 @@ +# REQUIRES: x86 +## Show that the link succeeds if wrapped symbol foo is not included in the link. + +# RUN: rm -rf %t && split-file %s %t +# RUN: llvm-as %t/a.ll -o %t/a.o +# RUN: llvm-as %t/b.ll -o %t/b.o +# RUN: ld.lld %t/a.o --start-lib %t/b.o --end-lib --wrap foo -o /dev/null --trace 2>&1 | FileCheck %s + +CHECK-NOT: b.o + +#--- a.ll +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-elf" +define void @_start() { + call void @__real_foo() + ret void +} + +declare void @__real_foo() + +#--- b.ll +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-elf" +define void @foo() { + ret void +} Index: lld/test/ELF/wrap-extract-real.s =================================================================== --- /dev/null +++ lld/test/ELF/wrap-extract-real.s @@ -0,0 +1,15 @@ +# REQUIRES: x86 +## Show that the link succeeds if wrapped symbol foo is not included in the link. + +# RUN: rm -rf %t && split-file %s %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/a.s -o %t/a.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/b.s -o %t/b.o +# RUN: ld.lld %t/a.o --start-lib %t/b.o --end-lib -o %t/a --wrap foo -o /dev/null --trace 2>&1 | FileCheck %s + +CHECK-NOT: b.o + +#--- a.s +.globl _start; _start:; call __real_foo + +#--- b.s +.global foo; foo:; ret Index: lld/test/ELF/wrap-extract-unreferenced-orig.ll =================================================================== --- /dev/null +++ lld/test/ELF/wrap-extract-unreferenced-orig.ll @@ -0,0 +1,35 @@ +# REQUIRES: x86 +## Show that lld pulls in a definition of foo from an archive +## even if there are no references to foo after wrapping. + +# RUN: rm -rf %t && split-file %s %t +# RUN: llvm-as %t/a.ll -o %t/a.o +# RUN: llvm-as %t/b.ll -o %t/b.o +# RUN: llvm-as %t/c.ll -o %t/c.o +# RUN: ld.lld %t/a.o %t/b.o --start-lib %t/c.o --end-lib -o %t/a --wrap foo -o /dev/null --trace 2>&1 | FileCheck %s + +CHECK: c.o + +#--- a.ll +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-elf" +define void @_start() { + call void @foo() + ret void +} + +declare void @foo() + +#--- b.ll +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-elf" +define void @__wrap_foo() { + ret void +} + +#--- c.ll +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-elf" +define void @foo() { + ret void +} Index: lld/test/ELF/wrap-extract-unreferenced-orig.s =================================================================== --- /dev/null +++ lld/test/ELF/wrap-extract-unreferenced-orig.s @@ -0,0 +1,20 @@ +# REQUIRES: x86 +## Show that lld pulls in a definition of foo from an archive +## even if there are no references to foo after wrapping. + +# RUN: rm -rf %t && split-file %s %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/a.s -o %t/a.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/b.s -o %t/b.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/c.s -o %t/c.o +# RUN: ld.lld %t/a.o %t/b.o --start-lib %t/c.o --end-lib -o %t/a --wrap foo -o /dev/null --trace 2>&1 | FileCheck %s + +CHECK: c.o + +#--- a.s +.globl _start; _start:; call foo + +#--- b.s +.globl __wrap_foo; __wrap_foo:; ret + +#--- c.s +.global foo; foo:; ret