[lld] ba5087f - ld64.lld: Add janky support for tbd files

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 1 21:07:15 PDT 2020


Author: Nico Weber
Date: 2020-07-02T00:05:52-04:00
New Revision: ba5087f13025a15662e164eb371fe0678258e03f

URL: https://github.com/llvm/llvm-project/commit/ba5087f13025a15662e164eb371fe0678258e03f
DIFF: https://github.com/llvm/llvm-project/commit/ba5087f13025a15662e164eb371fe0678258e03f.diff

LOG: ld64.lld: Add janky support for tbd files

With this, a simple hello world links against libSystem.tbd and the
old ld64.lld linker kind of works again with newer SDKs.

The motivation here is to have an arm64 cross linker that's good
enough to be able to run simple configure link checks on non-mac
systems for generating config.h files. Once -flavor darwinnew can
link arm64, we'll switch to that.

Added: 
    lld/test/mach-o/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd
    lld/test/mach-o/stub-link.s

Modified: 
    lld/lib/ReaderWriter/MachO/File.h
    lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
    lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
    lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
    lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp

Removed: 
    


################################################################################
diff  --git a/lld/lib/ReaderWriter/MachO/File.h b/lld/lib/ReaderWriter/MachO/File.h
index 072702973f81..a9a7faff89d2 100644
--- a/lld/lib/ReaderWriter/MachO/File.h
+++ b/lld/lib/ReaderWriter/MachO/File.h
@@ -17,6 +17,8 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/Format.h"
+#include "llvm/TextAPI/MachO/InterfaceFile.h"
+#include "llvm/TextAPI/MachO/TextAPIReader.h"
 #include <unordered_map>
 
 namespace lld {
@@ -322,7 +324,8 @@ class MachODylibFile : public SharedLibraryFile {
 
   void loadReExportedDylibs(FindDylib find) {
     for (ReExportedDylib &entry : _reExportedDylibs) {
-      entry.file = find(entry.path);
+      if (!entry.file)
+        entry.file = find(entry.path);
     }
   }
 
@@ -339,7 +342,7 @@ class MachODylibFile : public SharedLibraryFile {
     return std::error_code();
   }
 
-private:
+protected:
   OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
                                    StringRef installName) const {
     // First, check if requested symbol is directly implemented by this dylib.
@@ -373,6 +376,7 @@ class MachODylibFile : public SharedLibraryFile {
 
   struct ReExportedDylib {
     ReExportedDylib(StringRef p) : path(p), file(nullptr) { }
+    ReExportedDylib(StringRef p, MachODylibFile *file) : path(p), file(file) { }
     StringRef       path;
     MachODylibFile *file;
   };
@@ -393,6 +397,70 @@ class MachODylibFile : public SharedLibraryFile {
   mutable std::unordered_map<StringRef, AtomAndFlags> _nameToAtom;
 };
 
+class TAPIFile : public MachODylibFile {
+public:
+
+  TAPIFile(std::unique_ptr<MemoryBuffer> mb, MachOLinkingContext *ctx)
+      : MachODylibFile(std::move(mb), ctx) {}
+
+  std::error_code doParse() override {
+
+    llvm::Expected<std::unique_ptr<llvm::MachO::InterfaceFile>> result =
+        llvm::MachO::TextAPIReader::get(*_mb);
+    if (!result)
+      return std::make_error_code(std::errc::invalid_argument);
+
+    std::unique_ptr<llvm::MachO::InterfaceFile> interface{std::move(*result)};
+    return loadFromInterface(*interface);
+  }
+
+private:
+  std::error_code loadFromInterface(llvm::MachO::InterfaceFile &interface) {
+    llvm::MachO::Architecture arch;
+    switch(_ctx->arch()) {
+    case MachOLinkingContext::arch_x86:
+      arch = llvm::MachO::AK_i386;
+      break;
+    case MachOLinkingContext::arch_x86_64:
+      arch = llvm::MachO::AK_x86_64;
+      break;
+    case MachOLinkingContext::arch_arm64:
+      arch = llvm::MachO::AK_arm64;
+      break;
+    default:
+      return std::make_error_code(std::errc::invalid_argument);
+    }
+
+    setInstallName(interface.getInstallName().copy(allocator()));
+    // TODO(compnerd) filter out symbols based on the target platform
+    for (const auto symbol : interface.symbols())
+      if (symbol->getArchitectures().has(arch))
+        addExportedSymbol(symbol->getName(), symbol->isWeakDefined(), true);
+
+    for (const llvm::MachO::InterfaceFileRef &reexport :
+         interface.reexportedLibraries())
+      addReExportedDylib(reexport.getInstallName().copy(allocator()));
+
+    for (const auto& document : interface.documents()) {
+      for (auto& reexport : _reExportedDylibs) {
+        if (reexport.path != document->getInstallName())
+          continue;
+        assert(!reexport.file);
+        _ownedFiles.push_back(std::make_unique<TAPIFile>(
+            MemoryBuffer::getMemBuffer("", _mb->getBufferIdentifier()), _ctx));
+        reexport.file = _ownedFiles.back().get();
+        std::error_code err = _ownedFiles.back()->loadFromInterface(*document);
+        if (!err)
+          return err;
+      }
+    }
+
+    return std::error_code();
+  }
+
+  std::vector<std::unique_ptr<TAPIFile>> _ownedFiles;
+};
+
 } // end namespace mach_o
 } // end namespace lld
 

diff  --git a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
index 6fe9cde544d6..acd919e4d411 100644
--- a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
@@ -540,6 +540,12 @@ MachOLinkingContext::searchDirForLibrary(StringRef path,
     return llvm::None;
   }
 
+  // Search for stub library
+  fullPath.assign(path);
+  llvm::sys::path::append(fullPath, Twine("lib") + libName + ".tbd");
+  if (fileExists(fullPath))
+    return fullPath.str().copy(_allocator);
+
   // Search for dynamic library
   fullPath.assign(path);
   llvm::sys::path::append(fullPath, Twine("lib") + libName + ".dylib");

diff  --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
index 963f1227fa44..87601ca1be8b 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
@@ -576,6 +576,26 @@ class MachODylibReader : public Reader {
   MachOLinkingContext &_ctx;
 };
 
+class MachOTAPIReader : public Reader {
+public:
+  MachOTAPIReader(MachOLinkingContext &ctx) : _ctx(ctx) {}
+
+  bool canParse(file_magic magic, MemoryBufferRef mb) const override {
+    return magic == file_magic::tapi_file;
+  }
+
+  ErrorOr<std::unique_ptr<File>>
+  loadFile(std::unique_ptr<MemoryBuffer> mb,
+           const Registry &registry) const override {
+    std::unique_ptr<File> ret =
+        std::make_unique<TAPIFile>(std::move(mb), &_ctx);
+    return std::move(ret);
+  }
+
+private:
+  MachOLinkingContext &_ctx;
+};
+
 } // namespace normalized
 } // namespace mach_o
 
@@ -583,6 +603,7 @@ void Registry::addSupportMachOObjects(MachOLinkingContext &ctx) {
   MachOLinkingContext::Arch arch = ctx.arch();
   add(std::unique_ptr<Reader>(new mach_o::normalized::MachOObjectReader(ctx)));
   add(std::unique_ptr<Reader>(new mach_o::normalized::MachODylibReader(ctx)));
+  add(std::unique_ptr<Reader>(new mach_o::normalized::MachOTAPIReader(ctx)));
   addKindTable(Reference::KindNamespace::mach_o, ctx.archHandler().kindArch(),
                ctx.archHandler().kindStrings());
   add(std::unique_ptr<YamlIOTaggedDocumentHandler>(

diff  --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
index 55dcad955e85..42ac711bc9dc 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
@@ -1037,7 +1037,7 @@ llvm::Error Util::addSymbols(const lld::File &atomFile,
 
   // Add all stabs.
   for (auto &stab : _stabs) {
-    Symbol sym;
+    lld::mach_o::normalized::Symbol sym;
     sym.type = static_cast<NListType>(stab.type);
     sym.scope = 0;
     sym.sect = stab.other;
@@ -1066,7 +1066,7 @@ llvm::Error Util::addSymbols(const lld::File &atomFile,
           AtomAndIndex ai = { atom, sect->finalSectionIndex, symbolScope };
           globals.push_back(ai);
         } else {
-          Symbol sym;
+          lld::mach_o::normalized::Symbol sym;
           sym.name  = atom->name();
           sym.type  = N_SECT;
           sym.scope = symbolScope;
@@ -1082,7 +1082,7 @@ llvm::Error Util::addSymbols(const lld::File &atomFile,
         char tmpName[16];
         sprintf(tmpName, "L%04u", tempNum++);
         StringRef tempRef(tmpName);
-        Symbol sym;
+        lld::mach_o::normalized::Symbol sym;
         sym.name  = tempRef.copy(file.ownedAllocations);
         sym.type  = N_SECT;
         sym.scope = 0;
@@ -1099,7 +1099,7 @@ llvm::Error Util::addSymbols(const lld::File &atomFile,
   std::sort(globals.begin(), globals.end(), AtomSorter());
   const uint32_t globalStartIndex = file.localSymbols.size();
   for (AtomAndIndex &ai : globals) {
-    Symbol sym;
+    lld::mach_o::normalized::Symbol sym;
     sym.name  = ai.atom->name();
     sym.type  = N_SECT;
     sym.scope = ai.scope;
@@ -1124,7 +1124,7 @@ llvm::Error Util::addSymbols(const lld::File &atomFile,
   std::sort(undefs.begin(), undefs.end(), AtomSorter());
   const uint32_t start = file.globalSymbols.size() + file.localSymbols.size();
   for (AtomAndIndex &ai : undefs) {
-    Symbol sym;
+    lld::mach_o::normalized::Symbol sym;
     uint16_t desc = 0;
     if (!rMode) {
       uint8_t ordinal = 0;

diff  --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
index 80a1bf00a70d..0a59e24c47a8 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
@@ -223,10 +223,11 @@ Atom::Scope atomScope(uint8_t scope) {
   llvm_unreachable("unknown scope value!");
 }
 
-void appendSymbolsInSection(const std::vector<Symbol> &inSymbols,
-                            uint32_t sectionIndex,
-                            SmallVector<const Symbol *, 64> &outSyms) {
-  for (const Symbol &sym : inSymbols) {
+void appendSymbolsInSection(
+    const std::vector<lld::mach_o::normalized::Symbol> &inSymbols,
+    uint32_t sectionIndex,
+    SmallVector<const lld::mach_o::normalized::Symbol *, 64> &outSyms) {
+  for (const lld::mach_o::normalized::Symbol &sym : inSymbols) {
     // Only look at definition symbols.
     if ((sym.type & N_TYPE) != N_SECT)
       continue;
@@ -286,13 +287,14 @@ llvm::Error processSymboledSection(DefinedAtom::ContentType atomType,
   }
 
   // Find all symbols in this section.
-  SmallVector<const Symbol *, 64> symbols;
+  SmallVector<const lld::mach_o::normalized::Symbol *, 64> symbols;
   appendSymbolsInSection(normalizedFile.globalSymbols, sectIndex, symbols);
   appendSymbolsInSection(normalizedFile.localSymbols,  sectIndex, symbols);
 
   // Sort symbols.
   std::sort(symbols.begin(), symbols.end(),
-            [](const Symbol *lhs, const Symbol *rhs) -> bool {
+            [](const lld::mach_o::normalized::Symbol *lhs,
+               const lld::mach_o::normalized::Symbol *rhs) -> bool {
               if (lhs == rhs)
                 return false;
               // First by address.
@@ -300,7 +302,7 @@ llvm::Error processSymboledSection(DefinedAtom::ContentType atomType,
               uint64_t rhsAddr = rhs->value;
               if (lhsAddr != rhsAddr)
                 return lhsAddr < rhsAddr;
-               // If same address, one is an alias so sort by scope.
+              // If same address, one is an alias so sort by scope.
               Atom::Scope lScope = atomScope(lhs->scope);
               Atom::Scope rScope = atomScope(rhs->scope);
               if (lScope != rScope)
@@ -339,8 +341,8 @@ llvm::Error processSymboledSection(DefinedAtom::ContentType atomType,
                    scatterable, copyRefs);
   }
 
-  const Symbol *lastSym = nullptr;
-  for (const Symbol *sym : symbols) {
+  const lld::mach_o::normalized::Symbol *lastSym = nullptr;
+  for (const lld::mach_o::normalized::Symbol *sym : symbols) {
     if (lastSym != nullptr) {
       // Ignore any assembler added "ltmpNNN" symbol at start of section
       // if there is another symbol at the start.
@@ -550,7 +552,7 @@ llvm::Error convertRelocs(const Section &section,
   auto atomBySymbol = [&] (uint32_t symbolIndex, const lld::Atom **result)
                            -> llvm::Error {
     // Find symbol from index.
-    const Symbol *sym = nullptr;
+    const lld::mach_o::normalized::Symbol *sym = nullptr;
     uint32_t numStabs  = normalizedFile.stabsSymbols.size();
     uint32_t numLocal  = normalizedFile.localSymbols.size();
     uint32_t numGlobal = normalizedFile.globalSymbols.size();

diff  --git a/lld/test/mach-o/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd b/lld/test/mach-o/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd
new file mode 100644
index 000000000000..1a90cff2978b
--- /dev/null
+++ b/lld/test/mach-o/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/mach-o/stub-link.s b/lld/test/mach-o/stub-link.s
new file mode 100644
index 000000000000..fb12b76f44d9
--- /dev/null
+++ b/lld/test/mach-o/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: ld64.lld -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 __got 0x[[ADDR]] pointer 0 libSystem ___nan
+
+.section __TEXT,__text
+.global _main
+
+_main:
+  movq ___nan at GOTPCREL(%rip), %rax
+  ret


        


More information about the llvm-commits mailing list