diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -379,12 +379,15 @@ } // We expect sub-library names of the form "libfoo", which will match a dylib -// with a path of .*/libfoo.dylib. +// with a path of .*/libfoo.{dylib, tbd}. +// XXX ld64 seems to ignore the extension entirely when matching sub-libraries; +// I'm not sure what the use case for that is. static bool markSubLibrary(StringRef searchName) { for (InputFile *file : inputFiles) { if (auto *dylibFile = dyn_cast(file)) { StringRef filename = path::filename(dylibFile->getName()); - if (filename.consume_front(searchName) && filename == ".dylib") { + if (filename.consume_front(searchName) && + (filename == ".dylib" || filename == ".tbd")) { dylibFile->reexport = true; return true; } diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h --- a/lld/MachO/InputFiles.h +++ b/lld/MachO/InputFiles.h @@ -12,6 +12,7 @@ #include "MachOStructs.h" #include "lld/Common/LLVM.h" +#include "lld/Common/Memory.h" #include "llvm/ADT/DenseSet.h" #include "llvm/BinaryFormat/MachO.h" #include "llvm/Object/Archive.h" @@ -45,7 +46,7 @@ virtual ~InputFile() = default; Kind kind() const { return fileKind; } - StringRef getName() const { return mb.getBufferIdentifier(); } + StringRef getName() const { return name; } MemoryBufferRef mb; std::vector symbols; @@ -53,7 +54,11 @@ std::vector subsections; protected: - InputFile(Kind kind, MemoryBufferRef mb) : mb(mb), fileKind(kind) {} + InputFile(Kind kind, MemoryBufferRef mb) + : mb(mb), fileKind(kind), name(mb.getBufferIdentifier()) {} + + InputFile(Kind kind, const llvm::MachO::InterfaceFile &interface) + : fileKind(kind), name(saver.save(interface.getPath())) {} void parseSections(ArrayRef); @@ -64,6 +69,7 @@ private: const Kind fileKind; + const StringRef name; }; // .o file @@ -84,9 +90,6 @@ // .dylib file class DylibFile : public InputFile { public: - explicit DylibFile(const llvm::MachO::InterfaceFile &interface, - DylibFile *umbrella = nullptr); - // Mach-O dylibs can re-export other dylibs as sub-libraries, meaning that the // symbols in those sub-libraries will be available under the umbrella // library's namespace. Those sub-libraries can also have their own @@ -96,6 +99,9 @@ // (through an -lfoo flag), then `umbrella` should be a nullptr. explicit DylibFile(MemoryBufferRef mb, DylibFile *umbrella = nullptr); + explicit DylibFile(const llvm::MachO::InterfaceFile &interface, + DylibFile *umbrella = nullptr); + static bool classof(const InputFile *f) { return f->kind() == DylibKind; } StringRef dylibName; diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -397,7 +397,7 @@ } DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella) - : InputFile(DylibKind, MemoryBufferRef()) { + : InputFile(DylibKind, interface) { if (umbrella == nullptr) umbrella = this; diff --git a/lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libc++.tbd b/lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libc++.tbd new file mode 100644 --- /dev/null +++ b/lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libc++.tbd @@ -0,0 +1,10 @@ +--- !tapi-tbd-v3 +archs: [ i386, x86_64 ] +uuids: [ 'i386: 00000000-0000-0000-0000-000000000000', 'x86_64: 00000000-0000-0000-0000-0 +0000000001' ] +platform: macosx +install-name: '/usr/lib/libc++.dylib' +current-version: 1281 +exports: + - archs: [ i386, x86_64 ] +... diff --git a/lld/test/MachO/reexport-stub.s b/lld/test/MachO/reexport-stub.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/reexport-stub.s @@ -0,0 +1,12 @@ +# REQUIRES: x86 +# RUN: mkdir -p %t + +## This test verifies that a non-TBD dylib can re-export a TBD library. + +# RUN: echo "" | llvm-mc -filetype=obj -triple=x86_64-apple-darwin -o %t/reexporter.o +# RUN: lld -flavor darwinnew -dylib -syslibroot %S/Inputs/MacOSX.sdk -lc++ -sub_library libc++ \ +# RUN: %t/reexporter.o -o %t/libreexporter.dylib +# RUN: llvm-objdump --macho --all-headers %t/libreexporter.dylib | FileCheck %s --check-prefix=DYLIB-HEADERS +# DYLIB-HEADERS: cmd LC_REEXPORT_DYLIB +# DYLIB-HEADERS-NOT: Load command +# DYLIB-HEADERS: name /usr/lib/libc++.dylib