[lld] 6fe27b5 - lld: initial pass at supporting TBD

Saleem Abdulrasool via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 8 18:16:20 PDT 2020


Author: Saleem Abdulrasool
Date: 2020-06-08T18:15:40-07:00
New Revision: 6fe27b5fed92aca21386a1ec3d1e4aa70e82e9fa

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

LOG: 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.

Added: 
    lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd
    lld/test/MachO/Inputs/iPhoneSimulator.sdk/usr/lib/libSystem.tbd
    lld/test/MachO/invalid/stub-link.s
    lld/test/MachO/stub-link.s

Modified: 
    lld/MachO/Driver.cpp
    lld/MachO/InputFiles.cpp
    lld/MachO/InputFiles.h
    lld/MachO/Writer.cpp

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 0b021c41a98f..d57e0fe937e9 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -75,19 +75,20 @@ opt::InputArgList MachOOptTable::parse(ArrayRef<const char *> argv) {
 }
 
 static Optional<std::string> 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<DylibFile>(mbref));
     break;
+  case file_magic::tapi_file: {
+    llvm::Expected<std::unique_ptr<llvm::MachO::InterfaceFile>> result =
+        TextAPIReader::get(mbref);
+    if (!result)
+      return;
+
+    std::unique_ptr<llvm::MachO::InterfaceFile> interface{std::move(*result)};
+    inputFiles.push_back(make<DylibFile>(std::move(interface)));
+    break;
+  }
   default:
     error(path + ": unhandled file type");
   }

diff  --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index 321e1caacc9b..1b299e9250d9 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<llvm::MachO::InterfaceFile> 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<DylibFile>(document, umbrella));
+}
+
 DylibFile::DylibFile() : InputFile(DylibKind, MemoryBufferRef()) {}
 
 DylibFile *DylibFile::createLibSystemMock() {

diff  --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h
index ffe0c2ec77f2..992e7b774b0f 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 <map>
 #include <vector>
@@ -73,6 +75,9 @@ class ObjFile : public InputFile {
 // .dylib file
 class DylibFile : public InputFile {
 public:
+  explicit DylibFile(std::shared_ptr<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
@@ -81,6 +86,7 @@ class DylibFile : public InputFile {
   // 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 768966103531..96ede13a2b64 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -251,7 +251,7 @@ class LCLoadDylinker : public LoadCommand {
 void Writer::scanRelocations() {
   for (InputSection *isec : inputSections) {
     for (Reloc &r : isec->relocs) {
-      if (auto *s = r.target.dyn_cast<Symbol *>()) {
+      if (auto *s = r.target.dyn_cast<lld::macho::Symbol *>()) {
         if (isa<Undefined>(s))
           error("undefined symbol " + s->getName() + ", referenced from " +
                 sys::path::filename(isec->file->getName()));
@@ -329,7 +329,7 @@ static DenseMap<const InputSection *, size_t> buildInputSectionPriorities() {
   // TODO: Make sure this handles weak symbols correctly.
   for (InputFile *file : inputFiles)
     if (isa<ObjFile>(file) || isa<ArchiveFile>(file))
-      for (Symbol *sym : file->symbols)
+      for (lld::macho::Symbol *sym : file->symbols)
         if (auto *d = dyn_cast<Defined>(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 000000000000..1a90cff2978b
--- /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 000000000000..3e62c2ee711b
--- /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 000000000000..f1c159037024
--- /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 at 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 000000000000..1bf65c46a787
--- /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 at GOTPCREL(%rip), %rax
+  ret


        


More information about the llvm-commits mailing list