diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp index a95dddff28a38..12c62554c2437 100644 --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -497,13 +497,17 @@ void StubHelperSection::writeTo(uint8_t *buf) const { } void StubHelperSection::setup() { - stubBinder = dyn_cast_or_null(symtab->find("dyld_stub_binder")); - if (stubBinder == nullptr) { - error("symbol dyld_stub_binder not found (normally in libSystem.dylib). " - "Needed to perform lazy binding."); + Symbol *binder = symtab->addUndefined("dyld_stub_binder", /*file=*/nullptr, + /*isWeakRef=*/false); + if (auto *undefined = dyn_cast(binder)) + treatUndefinedSymbol(*undefined, + "lazy binding (normally in libSystem.dylib)"); + + // treatUndefinedSymbol() can replace binder with a DylibSymbol; re-check. + stubBinder = dyn_cast_or_null(binder); + if (stubBinder == nullptr) return; - } - stubBinder->reference(RefState::Strong); + in.got->addEntry(stubBinder); inputSections.push_back(in.imageLoaderCache); diff --git a/lld/test/MachO/dyld-stub-binder.s b/lld/test/MachO/dyld-stub-binder.s new file mode 100644 index 0000000000000..36685580b5e1f --- /dev/null +++ b/lld/test/MachO/dyld-stub-binder.s @@ -0,0 +1,59 @@ +# REQUIRES: aarch64 +# RUN: rm -rf %t; split-file %s %t +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %t/foo.s -o %t/foo.o +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %t/bar.s -o %t/bar.o +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %t/test.s -o %t/test.o + +## Dylibs that don't do lazy dynamic calls don't need dyld_stub_binder. +# RUN: %lld -arch arm64 -dylib %t/foo.o -o %t/libfoo.dylib +# RUN: llvm-nm -m %t/libfoo.dylib | FileCheck --check-prefix=NOSTUB %s + +## Dylibs that do lazy dynamic calls do need dyld_stub_binder. +# RUN: not %lld -arch arm64 -dylib %t/bar.o %t/libfoo.dylib \ +# RUN: -o %t/libbar.dylib 2>&1 | FileCheck --check-prefix=MISSINGSTUB %s +# RUN: %lld -arch arm64 -lSystem -dylib %t/bar.o %t/libfoo.dylib \ +# RUN: -o %t/libbar.dylib +# RUN: llvm-nm -m %t/libbar.dylib | FileCheck --check-prefix=STUB %s + +## As do executables. +# RUN: not %lld -arch arm64 %t/libfoo.dylib %t/libbar.dylib %t/test.o \ +# RUN: -o %t/test 2>&1 | FileCheck --check-prefix=MISSINGSTUB %s +# RUN: %lld -arch arm64 -lSystem %t/libfoo.dylib %t/libbar.dylib %t/test.o \ +# RUN: -o %t/test +# RUN: llvm-nm -m %t/test | FileCheck --check-prefix=STUB %s + +## Test dynamic lookup of dyld_stub_binder. +# RUN: %lld -arch arm64 %t/libfoo.dylib %t/libbar.dylib %t/test.o \ +# RUN: -o %t/test -undefined dynamic_lookup +# RUN: llvm-nm -m %t/test | FileCheck --check-prefix=DYNSTUB %s +# RUN: %lld -arch arm64 %t/libfoo.dylib %t/libbar.dylib %t/test.o \ +# RUN: -o %t/test -U dyld_stub_binder +# RUN: llvm-nm -m %t/test | FileCheck --check-prefix=DYNSTUB %s + +# MISSINGSTUB: error: undefined symbol: dyld_stub_binder +# MISSINGSTUB-NEXT: >>> referenced by lazy binding (normally in libSystem.dylib) + +# NOSTUB-NOT: dyld_stub_binder +# STUB: (undefined) external dyld_stub_binder (from libSystem) +# DYNSTUB: (undefined) external dyld_stub_binder (dynamically looked up) + +#--- foo.s +.globl _foo +_foo: + +#--- bar.s +.text +.globl _bar +_bar: + bl _foo + ret + +#--- test.s +.text +.globl _main + +.p2align 2 +_main: + bl _foo + bl _bar + ret