From 6fe27b5fed92aca21386a1ec3d1e4aa70e82e9fa Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 5 Jun 2020 11:18:33 -0700 Subject: [PATCH] lld: initial pass at supporting TBD Add support to lld to use Text Based API stubs for linking. This is support is incomplete not filtering out platforms. It also does not account for architecture specific API handling and potentially does not correctly handle trees of re-exports with inlined libraries being treated as direct children of the top level library. --- lld/MachO/Driver.cpp | 15 ++++++-- lld/MachO/InputFiles.cpp | 19 ++++++++++ lld/MachO/InputFiles.h | 6 ++++ lld/MachO/Writer.cpp | 4 +-- .../MachO/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd | 42 ++++++++++++++++++++++ .../iPhoneSimulator.sdk/usr/lib/libSystem.tbd | 23 ++++++++++++ lld/test/MachO/invalid/stub-link.s | 15 ++++++++ lld/test/MachO/stub-link.s | 21 +++++++++++ 8 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd create mode 100644 lld/test/MachO/Inputs/iPhoneSimulator.sdk/usr/lib/libSystem.tbd create mode 100644 lld/test/MachO/invalid/stub-link.s create mode 100644 lld/test/MachO/stub-link.s diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp index 0b021c4..d57e0fe 100644 --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -75,19 +75,20 @@ opt::InputArgList MachOOptTable::parse(ArrayRef argv) { } static Optional findLibrary(StringRef name) { + std::string stub = (llvm::Twine("lib") + name + ".tbd").str(); std::string shared = (llvm::Twine("lib") + name + ".dylib").str(); std::string archive = (llvm::Twine("lib") + name + ".a").str(); llvm::SmallString<260> location; for (StringRef dir : config->searchPaths) { - for (StringRef library : {shared, archive}) { + for (StringRef library : {stub, shared, archive}) { location = dir; llvm::sys::path::append(location, library); if (fs::exists(location)) return location.str().str(); } } - return None; + return {}; } static TargetInfo *createTargetInfo(opt::InputArgList &args) { @@ -135,6 +136,16 @@ static void addFile(StringRef path) { case file_magic::macho_dynamically_linked_shared_lib: inputFiles.push_back(make(mbref)); break; + case file_magic::tapi_file: { + llvm::Expected> result = + TextAPIReader::get(mbref); + if (!result) + return; + + std::unique_ptr interface{std::move(*result)}; + inputFiles.push_back(make(std::move(interface))); + break; + } default: error(path + ": unhandled file type"); } diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp index 321e1ca..1b299e9 100644 --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -378,6 +378,25 @@ DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella) } } +DylibFile::DylibFile(std::shared_ptr interface, + DylibFile *umbrella) + : InputFile(DylibKind, MemoryBufferRef()) { + if (umbrella == nullptr) + umbrella = this; + + dylibName = saver.save(interface->getInstallName()); + // TODO(compnerd) filter out symbols based on the target platform + for (const auto symbol : interface->symbols()) + if (symbol->getArchitectures().has(config->arch)) + symbols.push_back( + symtab->addDylib(saver.save(symbol->getName()), umbrella)); + // TODO(compnerd) properly represent the hierarchy of the documents as it is + // in theory possible to have re-exported dylibs from re-exported dylibs which + // should be parent'ed to the child. + for (auto document : interface->documents()) + reexported.push_back(make(document, umbrella)); +} + DylibFile::DylibFile() : InputFile(DylibKind, MemoryBufferRef()) {} DylibFile *DylibFile::createLibSystemMock() { diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h index ffe0c2e..992e7b7 100644 --- a/lld/MachO/InputFiles.h +++ b/lld/MachO/InputFiles.h @@ -16,6 +16,8 @@ #include "llvm/BinaryFormat/MachO.h" #include "llvm/Object/Archive.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/TextAPI/MachO/InterfaceFile.h" +#include "llvm/TextAPI/MachO/TextAPIReader.h" #include #include @@ -73,6 +75,9 @@ public: // .dylib file class DylibFile : public InputFile { public: + explicit DylibFile(std::shared_ptr 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 @@ -81,6 +86,7 @@ public: // to the root. On the other hand, if a dylib is being directly loaded // (through an -lfoo flag), then `umbrella` should be a nullptr. explicit DylibFile(MemoryBufferRef mb, DylibFile *umbrella = nullptr); + static bool classof(const InputFile *f) { return f->kind() == DylibKind; } // Do not use this constructor!! This is meant only for createLibSystemMock(), diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp index 7689661..96ede13 100644 --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -251,7 +251,7 @@ private: void Writer::scanRelocations() { for (InputSection *isec : inputSections) { for (Reloc &r : isec->relocs) { - if (auto *s = r.target.dyn_cast()) { + if (auto *s = r.target.dyn_cast()) { if (isa(s)) error("undefined symbol " + s->getName() + ", referenced from " + sys::path::filename(isec->file->getName())); @@ -329,7 +329,7 @@ static DenseMap buildInputSectionPriorities() { // TODO: Make sure this handles weak symbols correctly. for (InputFile *file : inputFiles) if (isa(file) || isa(file)) - for (Symbol *sym : file->symbols) + for (lld::macho::Symbol *sym : file->symbols) if (auto *d = dyn_cast(sym)) addSym(*d); diff --git a/lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd b/lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd new file mode 100644 index 0000000..1a90cff --- /dev/null +++ b/lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd @@ -0,0 +1,42 @@ +--- !tapi-tbd-v3 +archs: [ x86_64 ] +uuids: [ 'x86_64: 00000000-0000-0000-0000-000000000000' ] +platform: macosx +install-name: '/usr/lib/libSystem.B.dylib' +current-version: 0001.001.1 +exports: + - archs: [ 'x86_64' ] + re-exports: [ '/usr/lib/system/libdyld.dylib', + '/usr/lib/system/libsystem_c.dylib', + '/usr/lib/system/libsystem_m.dylib' ] +--- !tapi-tbd-v3 +archs: [ x86_64 ] +uuids: [ 'x86_64: 00000000-0000-0000-0000-000000000001' ] +platform: macosx +install-name: '/usr/lib/libdyld.dylib' +current-version: 0001.001.1 +parent-umbrella: System +exports: + - archs: [ 'x86_64' ] + symbols: [ dyld_stub_binder ] +--- !tapi-tbd-v3 +archs: [ x86_64 ] +uuids: [ 'x86_64: 00000000-0000-0000-0000-000000000002' ] +platform: macosx +install-name: '/usr/lib/libsystem_c.dylib' +current-version: 0001.001.1 +parent-umbrella: System +exports: + - archs: [ 'x86_64' ] + symbols: [ ] +--- !tapi-tbd-v3 +archs: [ x86_64 ] +uuids: [ 'x86_64: 00000000-0000-0000-0000-000000000003' ] +platform: macosx +install-name: '/usr/lib/libsystem_m.dylib' +current-version: 0001.001.1 +parent-umbrella: System +exports: + - archs: [ 'x86_64' ] + symbols: [ ___nan ] +... diff --git a/lld/test/MachO/Inputs/iPhoneSimulator.sdk/usr/lib/libSystem.tbd b/lld/test/MachO/Inputs/iPhoneSimulator.sdk/usr/lib/libSystem.tbd new file mode 100644 index 0000000..3e62c2e --- /dev/null +++ b/lld/test/MachO/Inputs/iPhoneSimulator.sdk/usr/lib/libSystem.tbd @@ -0,0 +1,23 @@ +--- !tapi-tbd-v3 +archs: [ i386, x86_64 ] +uuids: [ 'i386: 00000000-0000-0000-0000-000000000000', 'x86_64: 00000000-0000-0000-0000-000000000001' ] +platform: ios +install-name: '/usr/lib/libSystem.B.dylib' +current-version: 1281 +exports: + - archs: [ i386, x86_64 ] + re-exports: [ '/usr/lib/system/libcache.dylib' ] + symbols: [ __crashreporter_info__ ] +--- !tapi-tbd-v3 +archs: [ i386, x86_64 ] +uuids: [ 'i386: 00000000-0000-0000-0000-000000000002', 'x86_64: 00000000-0000-0000-0000-000000000003' ] +platform: ios +install-name: '/usr/lib/libcache.dylib' +current-version: 83 +parent-umbrella: System +exports: + - archs: [ i386 ] + symbols: [ __cache_handle_memory_pressure_event ] + - archs: [ i386, x86_64 ] + symbols: [ _cache_create, _cache_destroy, _cache_get ] +... diff --git a/lld/test/MachO/invalid/stub-link.s b/lld/test/MachO/invalid/stub-link.s new file mode 100644 index 0000000..f1c1590 --- /dev/null +++ b/lld/test/MachO/invalid/stub-link.s @@ -0,0 +1,15 @@ +# REQUIRES: x86 + +# RUN: mkdir -p %t +# +# RUN: llvm-mc -filetype obj -triple x86_64-apple-ios %s -o %t/test.o +# RUN: not lld -flavor darwinnew -o %t/test -Z -L%S/../Inputs/iPhoneSimulator.sdk/usr/lib -lSystem %t/test.o 2>&1 | FileCheck %s + +# CHECK: error: undefined symbol __cache_handle_memory_pressure_event + +.section __TEXT,__text +.global _main + +_main: + movq __cache_handle_memory_pressure_event@GOTPCREL(%rip), %rax + ret diff --git a/lld/test/MachO/stub-link.s b/lld/test/MachO/stub-link.s new file mode 100644 index 0000000..1bf65c4 --- /dev/null +++ b/lld/test/MachO/stub-link.s @@ -0,0 +1,21 @@ +# REQUIRES: x86 + +# RUN: mkdir -p %t +# +# RUN: llvm-mc -filetype obj -triple x86_64-apple-darwin %s -o %t/test.o +# RUN: lld -flavor darwinnew -o %t/test -Z -L%S/Inputs/MacOSX.sdk/usr/lib -lSystem %t/test.o +# +# RUN: llvm-objdump --bind --no-show-raw-insn -d -r %t/test | FileCheck %s + +# CHECK: Disassembly of section __TEXT,__text: +# CHECK: movq {{.*}} # [[ADDR:[0-9a-f]+]] + +# CHECK: Bind table: +# CHECK: __DATA_CONST __got 0x[[ADDR]] pointer 0 libSystem ___nan + +.section __TEXT,__text +.global _main + +_main: + movq ___nan@GOTPCREL(%rip), %rax + ret -- 2.7.4