[llvm] 5255ca9 - [llvm-jitlink] Update handling of library options.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 14 18:50:00 PST 2021


Author: Lang Hames
Date: 2021-12-15T13:49:30+11:00
New Revision: 5255ca9726e9734eae5115488517175f9c94c9de

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

LOG: [llvm-jitlink] Update handling of library options.

Adds -L<search-path> and -l<library> options that are analogous to ld's
versions.

Each instance of -L<search-path> or -l<library> will apply to the most recent
-jd option on the command line (-jd <name> creates a JITDylib with the given
name). Library names will match against JITDylibs first, then llvm-jitlink will
look through the search paths for files named <search-path>/lib<library>.dylib
or <search-path>/lib<library>.a.

The default "main" JITDylib will link against all JITDylibs created by -jd
options, and all JITDylibs will link against the process symbols (unless
-no-process-symbols is specified).

The -dlopen option is renamed -preload, and will load dylibs into the JITDylib
for the ORC runtime only.

The effect of these changes is to make it easier to describe a non-trivial
program layout to llvm-jitlink for testing purposes. E.g. the following
invocation describes a program consisting of three JITDylibs: "main" (created
implicitly) containing main.o, "Foo" containing foo1.o and foo2.o, and linking
against library "bar" (not a JITDylib, so it must be a .dylib or .a on disk)
and "Baz" (which is a JITDylib), and "Baz" containing baz.o.

llvm-jitlink \
  main.o \
  -jd Foo foo1.o foo2.o -L${HOME}/lib -lbar -lBaz
  -jd Baz baz.o

Added: 
    llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_extra_def_strong.s
    llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_extra_def_weak.s
    llvm/test/ExecutionEngine/JITLink/X86/MachO_archive_support.s

Modified: 
    compiler-rt/test/orc/TestCases/Darwin/arm64/trivial-objc-methods.S
    compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-objc-methods.S
    compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-swift-types-section.S
    llvm/test/ExecutionEngine/JITLink/X86/MachO_gdb_jit_nonzero_alignment_offsets.s
    llvm/test/ExecutionEngine/JITLink/X86/MachO_weak_definitions.s
    llvm/tools/llvm-jitlink/llvm-jitlink.cpp
    llvm/tools/llvm-jitlink/llvm-jitlink.h

Removed: 
    llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_strong_def_extra.s
    llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_weak_defs_extra.s


################################################################################
diff  --git a/compiler-rt/test/orc/TestCases/Darwin/arm64/trivial-objc-methods.S b/compiler-rt/test/orc/TestCases/Darwin/arm64/trivial-objc-methods.S
index 6c681efc6d803..1a0718c0b822c 100644
--- a/compiler-rt/test/orc/TestCases/Darwin/arm64/trivial-objc-methods.S
+++ b/compiler-rt/test/orc/TestCases/Darwin/arm64/trivial-objc-methods.S
@@ -1,5 +1,5 @@
 // RUN: %clang -c -o %t %s
-// RUN: %llvm_jitlink -dlopen libobjc.A.dylib %t
+// RUN: %llvm_jitlink -preload libobjc.A.dylib %t
 //
 // Test that Objective-C class and instance methods work.
 

diff  --git a/compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-objc-methods.S b/compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-objc-methods.S
index 5934630aeccf2..8e5f95cd27e56 100644
--- a/compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-objc-methods.S
+++ b/compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-objc-methods.S
@@ -1,5 +1,5 @@
 // RUN: %clang -c -o %t %s
-// RUN: %llvm_jitlink -dlopen libobjc.A.dylib %t
+// RUN: %llvm_jitlink -preload libobjc.A.dylib %t
 //
 // Test that Objective-C class and instance methods work.
 

diff  --git a/compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-swift-types-section.S b/compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-swift-types-section.S
index 106bb5e9b8ed2..f6bb257bb46bf 100644
--- a/compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-swift-types-section.S
+++ b/compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-swift-types-section.S
@@ -1,5 +1,5 @@
 # RUN: %clang -c -o %t %s
-# RUN: %llvm_jitlink -dlopen /usr/lib/swift/libswiftCore.dylib %t
+# RUN: %llvm_jitlink -preload /usr/lib/swift/libswiftCore.dylib %t
 
 # REQUIRES: osx-swift-runtime
 

diff  --git a/llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_strong_def_extra.s b/llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_extra_def_strong.s
similarity index 70%
rename from llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_strong_def_extra.s
rename to llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_extra_def_strong.s
index 15785ed0f69c7..260ffee4c5add 100644
--- a/llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_strong_def_extra.s
+++ b/llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_extra_def_strong.s
@@ -1,11 +1,11 @@
-# Supplies a strong definition of WeakDef.
+# Supplies a strong definition of ExtraDef.
 
 	.section	__TEXT,__text,regular,pure_instructions
 	.build_version macos, 10, 14	sdk_version 10, 14
 	.section	__DATA,__data
-	.globl	WeakDef
+	.globl	ExtraDef
 	.p2align	2
-WeakDef:
+ExtraDef:
 	.long	3
 
 .subsections_via_symbols

diff  --git a/llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_extra_def_weak.s b/llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_extra_def_weak.s
new file mode 100644
index 0000000000000..200faed3fec57
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_extra_def_weak.s
@@ -0,0 +1,19 @@
+# Supplies a weak def of ExtraDef, and a pointer holding its address,
+# ExtraDefInExtraFile.
+
+	.section	__TEXT,__text,regular,pure_instructions
+	.build_version macos, 10, 14	sdk_version 10, 14
+	.section	__DATA,__data
+	.globl	ExtraDef
+	.weak_definition	ExtraDef
+	.p2align	2
+ExtraDef:
+	.long	2
+
+	.globl	ExtraDefAddrInExtraFile
+	.p2align	3
+ExtraDefAddrInExtraFile:
+	.quad	ExtraDef
+
+
+.subsections_via_symbols

diff  --git a/llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_weak_defs_extra.s b/llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_weak_defs_extra.s
deleted file mode 100644
index b25bb8a3079ba..0000000000000
--- a/llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_weak_defs_extra.s
+++ /dev/null
@@ -1,19 +0,0 @@
-# Supplies a weak def, WeakDef, and a pointer holding its address,
-# WeakDefAddrInExtraFile.
-
-	.section	__TEXT,__text,regular,pure_instructions
-	.build_version macos, 10, 14	sdk_version 10, 14
-	.section	__DATA,__data
-	.globl	WeakDef
-	.weak_definition	WeakDef
-	.p2align	2
-WeakDef:
-	.long	2
-
-	.globl	WeakDefAddrInExtraFile
-	.p2align	3
-WeakDefAddrInExtraFile:
-	.quad	WeakDef
-
-
-.subsections_via_symbols

diff  --git a/llvm/test/ExecutionEngine/JITLink/X86/MachO_archive_support.s b/llvm/test/ExecutionEngine/JITLink/X86/MachO_archive_support.s
new file mode 100644
index 0000000000000..e3fea53e397b9
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/X86/MachO_archive_support.s
@@ -0,0 +1,22 @@
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: llvm-mc -triple x86_64-apple-macosx10.9 -filetype=obj \
+# RUN:   -o %t/MachO_extra_def_strong.o %S/Inputs/MachO_extra_def_strong.s
+# RUN: llvm-ar crs %t/libExtraDef.a %t/MachO_extra_def_strong.o
+# RUN: llvm-mc -triple x86_64-apple-macosx10.9 -filetype=obj \
+# RUN:   -o %t/MachO_archive_support.o %s
+# RUN: llvm-jitlink -noexec %t/MachO_archive_support.o -lFoo -jd Foo -L%t -lExtraDef
+#
+# Test that archives can be loaded and referenced from other JITDylibs.
+
+        .section  __TEXT,__text,regular,pure_instructions
+
+        .globl  _main
+        .p2align  4, 0x90
+_main:
+        retq
+
+	.section	__DATA,__data
+	.globl	ExtraDefRef
+	.p2align	3
+ExtraDefRef:
+	.quad	ExtraDef

diff  --git a/llvm/test/ExecutionEngine/JITLink/X86/MachO_gdb_jit_nonzero_alignment_offsets.s b/llvm/test/ExecutionEngine/JITLink/X86/MachO_gdb_jit_nonzero_alignment_offsets.s
index e8618e0868bb1..7f313b42f1bf3 100644
--- a/llvm/test/ExecutionEngine/JITLink/X86/MachO_gdb_jit_nonzero_alignment_offsets.s
+++ b/llvm/test/ExecutionEngine/JITLink/X86/MachO_gdb_jit_nonzero_alignment_offsets.s
@@ -1,18 +1,18 @@
 # REQUIRES: system-darwin && asserts
 # RUN: rm -rf %t && mkdir -p %t
 # RUN: llvm-mc -triple x86_64-apple-macosx10.9 -filetype=obj \
-# RUN:   -o %t/MachO_strong_def_extra.o %S/Inputs/MachO_strong_def_extra.s
+# RUN:   -o %t/MachO_extra_def_strong.o %S/Inputs/MachO_extra_def_strong.s
 # RUN: llvm-mc -triple x86_64-apple-macosx10.9 -filetype=obj \
 # RUN:   -o %t/MachO_gdb_jit_nonzero_alignment_offsets.o %s
 # RUN: llvm-jitlink -noexec -debugger-support \
 # RUN:   %t/MachO_gdb_jit_nonzero_alignment_offsets.o \
-# RUN:   %t/MachO_strong_def_extra.o
+# RUN:   %t/MachO_extra_def_strong.o
 #
 # Check that blocks with non-zero alignment offsets don't break debugging
 # support.
 #
-# In this test case the WeakDef symbol below will be overridden by a strong def
-# in MachO_strong_defs_extra.s. This will leave main (with alignment 16,
+# In this test case the ExtraDef symbol below will be overridden by a strong
+# def in MachO_strong_defs_extra.s. This will leave main (with alignment 16,
 # alignment offset 4) as the only block in __TEXT,__text. The testcase ensures
 # that the debugging support plugin doesn't crash or throw an error in this
 # case.
@@ -20,10 +20,10 @@
         .section	__TEXT,__text,regular,pure_instructions
 	.p2align	4, 0x90
 
-	.globl	WeakDef
-	.weak_definition	WeakDef
+	.globl	ExtraDef
+	.weak_definition	ExtraDef
 	.p2align	2
-WeakDef:
+ExtraDef:
 	.long	42
 
 	.globl	_main

diff  --git a/llvm/test/ExecutionEngine/JITLink/X86/MachO_weak_definitions.s b/llvm/test/ExecutionEngine/JITLink/X86/MachO_weak_definitions.s
index e6440130e1388..4a69ec06e57ae 100644
--- a/llvm/test/ExecutionEngine/JITLink/X86/MachO_weak_definitions.s
+++ b/llvm/test/ExecutionEngine/JITLink/X86/MachO_weak_definitions.s
@@ -1,14 +1,14 @@
 # RUN: rm -rf %t && mkdir -p %t
 # RUN: llvm-mc -triple x86_64-apple-macosx10.9 -filetype=obj \
-# RUN:   -o %t/MachO_weak_defs_extra.o %S/Inputs/MachO_weak_defs_extra.s
+# RUN:   -o %t/MachO_extra_def_weak.o %S/Inputs/MachO_extra_def_weak.s
 # RUN: llvm-mc -triple x86_64-apple-macosx10.9 -filetype=obj \
 # RUN:   -o %t/MachO_weak_definitions.o %s
 # RUN: llvm-jitlink -noexec -check=%s %t/MachO_weak_definitions.o \
-# RUN:   %t/MachO_weak_defs_extra.o
+# RUN:   %t/MachO_extra_def_weak.o
 #
 # Check that objects linked separately agree on the address of weak symbols.
 #
-# jitlink-check: *{8}WeakDefAddrInThisFile = *{8}WeakDefAddrInExtraFile
+# jitlink-check: *{8}ExtraDefAddrInThisFile = *{8}ExtraDefAddrInExtraFile
 
 	.section	__TEXT,__text,regular,pure_instructions
 	.build_version macos, 10, 14	sdk_version 10, 14
@@ -18,22 +18,22 @@ _main:
 	retq
 
 	.section	__DATA,__data
-	.globl	WeakDef
-	.weak_definition	WeakDef
+	.globl	ExtraDef
+	.weak_definition	ExtraDef
 	.p2align	2
-WeakDef:
+ExtraDef:
 	.long	1
 
-	.globl	WeakDefAddrInThisFile
+	.globl	ExtraDefAddrInThisFile
 	.p2align	3
-WeakDefAddrInThisFile:
-	.quad	WeakDef
+ExtraDefAddrInThisFile:
+	.quad	ExtraDef
 
-# Take the address of WeakDefAddrInExtraFile to force its materialization
+# Take the address of ExtraDefAddrInExtraFile to force its materialization
 	.globl	extra_file_anchor
 	.p2align	3
 extra_file_anchor:
-	.quad	WeakDefAddrInExtraFile
+	.quad	ExtraDefAddrInExtraFile
 
 
 .subsections_via_symbols

diff  --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index 306fac9f77e7e..366944b506756 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -72,6 +72,16 @@ static cl::list<std::string> InputFiles(cl::Positional, cl::OneOrMore,
                                         cl::desc("input files"),
                                         cl::cat(JITLinkCategory));
 
+static cl::list<std::string>
+    LibrarySearchPaths("L",
+                       cl::desc("Add dir to the list of library search paths"),
+                       cl::Prefix, cl::cat(JITLinkCategory));
+
+static cl::list<std::string>
+    Libraries("l",
+              cl::desc("Link against library X in the library search paths"),
+              cl::Prefix, cl::cat(JITLinkCategory));
+
 static cl::opt<bool> NoExec("noexec", cl::desc("Do not execute loaded code"),
                             cl::init(false), cl::cat(JITLinkCategory));
 
@@ -87,14 +97,16 @@ static cl::opt<std::string>
     EntryPointName("entry", cl::desc("Symbol to call as main entry point"),
                    cl::init(""), cl::cat(JITLinkCategory));
 
-static cl::list<std::string> JITLinkDylibs(
-    "jld",
+static cl::list<std::string> JITDylibs(
+    "jd",
     cl::desc("Specifies the JITDylib to be used for any subsequent "
-             "input file arguments"),
+             "input file, -L<seacrh-path>, and -l<library> arguments"),
     cl::cat(JITLinkCategory));
 
 static cl::list<std::string>
-    Dylibs("dlopen", cl::desc("Dynamic libraries to load before linking"),
+    Dylibs("preload",
+           cl::desc("Pre-load dynamic libraries (e.g. language runtimes "
+                    "required by the ORC runtime)"),
            cl::ZeroOrMore, cl::cat(JITLinkCategory));
 
 static cl::list<std::string> InputArgv("args", cl::Positional,
@@ -128,6 +140,11 @@ static cl::opt<bool> ShowInitialExecutionSessionState(
     cl::desc("Print ExecutionSession state before resolving entry point"),
     cl::init(false), cl::cat(JITLinkCategory));
 
+static cl::opt<bool> ShowEntryExecutionSessionState(
+    "show-entry-es",
+    cl::desc("Print ExecutionSession state after resolving entry point"),
+    cl::init(false), cl::cat(JITLinkCategory));
+
 static cl::opt<bool> ShowAddrs(
     "show-addrs",
     cl::desc("Print registered symbol, section, got and stub addresses"),
@@ -1278,95 +1295,48 @@ static void addPhonyExternalsGenerator(Session &S) {
   S.MainJD->addGenerator(std::make_unique<PhonyExternalsGenerator>());
 }
 
-static Error loadObjects(Session &S) {
-  std::map<unsigned, JITDylib *> IdxToJLD;
-
+static Error createJITDylibs(Session &S,
+                             std::map<unsigned, JITDylib *> &IdxToJD) {
   // First, set up JITDylibs.
   LLVM_DEBUG(dbgs() << "Creating JITDylibs...\n");
   {
     // Create a "main" JITLinkDylib.
-    IdxToJLD[0] = S.MainJD;
+    IdxToJD[0] = S.MainJD;
     S.JDSearchOrder.push_back({S.MainJD, JITDylibLookupFlags::MatchAllSymbols});
     LLVM_DEBUG(dbgs() << "  0: " << S.MainJD->getName() << "\n");
 
-    // Add any extra JITLinkDylibs from the command line.
-    std::string JDNamePrefix("lib");
-    for (auto JLDItr = JITLinkDylibs.begin(), JLDEnd = JITLinkDylibs.end();
-         JLDItr != JLDEnd; ++JLDItr) {
-      auto JD = S.ES.createJITDylib(JDNamePrefix + *JLDItr);
+    // Add any extra JITDylibs from the command line.
+    for (auto JDItr = JITDylibs.begin(), JDEnd = JITDylibs.end();
+         JDItr != JDEnd; ++JDItr) {
+      auto JD = S.ES.createJITDylib(*JDItr);
       if (!JD)
         return JD.takeError();
-      unsigned JDIdx =
-          JITLinkDylibs.getPosition(JLDItr - JITLinkDylibs.begin());
-      IdxToJLD[JDIdx] = &*JD;
+      unsigned JDIdx = JITDylibs.getPosition(JDItr - JITDylibs.begin());
+      IdxToJD[JDIdx] = &*JD;
       S.JDSearchOrder.push_back({&*JD, JITDylibLookupFlags::MatchAllSymbols});
       LLVM_DEBUG(dbgs() << "  " << JDIdx << ": " << JD->getName() << "\n");
     }
-
-    // Set every dylib to link against every other, in command line order,
-    // using exported symbols only.
-    for (auto &KV : S.JDSearchOrder) {
-      auto *JD = KV.first;
-      auto LookupFlags = JITDylibLookupFlags::MatchExportedSymbolsOnly;
-      JITDylibSearchOrder LinkOrder;
-      for (auto &KV2 : S.JDSearchOrder) {
-        auto *JD2 = KV2.first;
-        if (JD2 == JD)
-          continue;
-        LinkOrder.push_back(std::make_pair(JD2, LookupFlags));
-      }
-      JD->setLinkOrder(std::move(LinkOrder));
-    }
   }
 
-  LLVM_DEBUG(dbgs() << "Adding test harness objects...\n");
-  for (auto HarnessFile : TestHarnesses) {
-    LLVM_DEBUG(dbgs() << "  " << HarnessFile << "\n");
-    auto ObjBuffer =
-        ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(HarnessFile)));
-    ExitOnErr(S.ObjLayer.add(*S.MainJD, std::move(ObjBuffer)));
-  }
+  LLVM_DEBUG({
+    dbgs() << "Dylib search order is [ ";
+    for (auto &KV : S.JDSearchOrder)
+      dbgs() << KV.first->getName() << " ";
+    dbgs() << "]\n";
+  });
 
-  // Load each object into the corresponding JITDylib..
-  LLVM_DEBUG(dbgs() << "Adding objects...\n");
-  for (auto InputFileItr = InputFiles.begin(), InputFileEnd = InputFiles.end();
-       InputFileItr != InputFileEnd; ++InputFileItr) {
-    unsigned InputFileArgIdx =
-        InputFiles.getPosition(InputFileItr - InputFiles.begin());
-    const std::string &InputFile = *InputFileItr;
-    auto &JD = *std::prev(IdxToJLD.lower_bound(InputFileArgIdx))->second;
-    LLVM_DEBUG(dbgs() << "  " << InputFileArgIdx << ": \"" << InputFile
-                      << "\" to " << JD.getName() << "\n";);
-    auto ObjBuffer =
-        ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFile)));
-
-    auto Magic = identify_magic(ObjBuffer->getBuffer());
-    if (Magic == file_magic::archive ||
-        Magic == file_magic::macho_universal_binary)
-      JD.addGenerator(ExitOnErr(StaticLibraryDefinitionGenerator::Load(
-          S.ObjLayer, InputFile.c_str(),
-          S.ES.getExecutorProcessControl().getTargetTriple())));
-    else {
-      if (S.HarnessFiles.empty())
-        ExitOnErr(S.ObjLayer.add(JD, std::move(ObjBuffer)));
-      else {
-        // We're in -harness mode. Use a custom interface for this
-        // test object.
-        auto ObjInterface = ExitOnErr(
-            getTestObjectFileInterface(S, ObjBuffer->getMemBufferRef()));
-        ExitOnErr(
-            S.ObjLayer.add(JD, std::move(ObjBuffer), std::move(ObjInterface)));
-      }
-    }
-  }
+  return Error::success();
+}
 
+static Error addAbsoluteSymbols(Session &S,
+                                const std::map<unsigned, JITDylib *> &IdxToJD) {
   // Define absolute symbols.
   LLVM_DEBUG(dbgs() << "Defining absolute symbols...\n");
   for (auto AbsDefItr = AbsoluteDefs.begin(), AbsDefEnd = AbsoluteDefs.end();
        AbsDefItr != AbsDefEnd; ++AbsDefItr) {
     unsigned AbsDefArgIdx =
       AbsoluteDefs.getPosition(AbsDefItr - AbsoluteDefs.begin());
-    auto &JD = *std::prev(IdxToJLD.lower_bound(AbsDefArgIdx))->second;
+    auto &JD = *std::prev(IdxToJD.lower_bound(AbsDefArgIdx))->second;
 
     StringRef AbsDefStmt = *AbsDefItr;
     size_t EqIdx = AbsDefStmt.find_first_of('=');
@@ -1391,13 +1361,234 @@ static Error loadObjects(Session &S) {
     S.SymbolInfos[Name] = {ArrayRef<char>(), Addr};
   }
 
+  return Error::success();
+}
+
+static Error addTestHarnesses(Session &S) {
+  LLVM_DEBUG(dbgs() << "Adding test harness objects...\n");
+  for (auto HarnessFile : TestHarnesses) {
+    LLVM_DEBUG(dbgs() << "  " << HarnessFile << "\n");
+    auto ObjBuffer = errorOrToExpected(MemoryBuffer::getFile(HarnessFile));
+    if (!ObjBuffer)
+      return ObjBuffer.takeError();
+    if (auto Err = S.ObjLayer.add(*S.MainJD, std::move(*ObjBuffer)))
+      return Err;
+  }
+  return Error::success();
+}
+
+static Error addObjects(Session &S,
+                        const std::map<unsigned, JITDylib *> &IdxToJD) {
+
+  // Load each object into the corresponding JITDylib..
+  LLVM_DEBUG(dbgs() << "Adding objects...\n");
+  for (auto InputFileItr = InputFiles.begin(), InputFileEnd = InputFiles.end();
+       InputFileItr != InputFileEnd; ++InputFileItr) {
+    unsigned InputFileArgIdx =
+        InputFiles.getPosition(InputFileItr - InputFiles.begin());
+    const std::string &InputFile = *InputFileItr;
+    auto &JD = *std::prev(IdxToJD.lower_bound(InputFileArgIdx))->second;
+    LLVM_DEBUG(dbgs() << "  " << InputFileArgIdx << ": \"" << InputFile
+                      << "\" to " << JD.getName() << "\n";);
+    auto ObjBuffer = errorOrToExpected(MemoryBuffer::getFile(InputFile));
+    if (!ObjBuffer)
+      return ObjBuffer.takeError();
+
+    if (S.HarnessFiles.empty()) {
+      if (auto Err = S.ObjLayer.add(JD, std::move(*ObjBuffer)))
+        return Err;
+    } else {
+      // We're in -harness mode. Use a custom interface for this
+      // test object.
+      auto ObjInterface =
+          getTestObjectFileInterface(S, (*ObjBuffer)->getMemBufferRef());
+      if (!ObjInterface)
+        return ObjInterface.takeError();
+      if (auto Err = S.ObjLayer.add(JD, std::move(*ObjBuffer),
+                                    std::move(*ObjInterface)))
+        return Err;
+    }
+  }
+
+  return Error::success();
+}
+
+static Error addLibraries(Session &S,
+                          const std::map<unsigned, JITDylib *> &IdxToJD) {
+
+  DenseMap<const JITDylib *, SmallVector<StringRef, 2>> JDSearchPaths;
+
+  for (auto LSPItr = LibrarySearchPaths.begin(),
+            LSPEnd = LibrarySearchPaths.end();
+       LSPItr != LSPEnd; ++LSPItr) {
+    unsigned LibrarySearchPathIdx =
+        LibrarySearchPaths.getPosition(LSPItr - LibrarySearchPaths.begin());
+    auto &JD = *std::prev(IdxToJD.lower_bound(LibrarySearchPathIdx))->second;
+
+    StringRef LibrarySearchPath = *LSPItr;
+    if (sys::fs::get_file_type(LibrarySearchPath) !=
+        sys::fs::file_type::directory_file)
+      return make_error<StringError>("While linking " + JD.getName() + ", -L" +
+                                         LibrarySearchPath +
+                                         " does not point to a directory",
+                                     inconvertibleErrorCode());
+
+    JDSearchPaths[&JD].push_back(*LSPItr);
+  }
+
   LLVM_DEBUG({
-    dbgs() << "Dylib search order is [ ";
-    for (auto &KV : S.JDSearchOrder)
-      dbgs() << KV.first->getName() << " ";
-    dbgs() << "]\n";
+    if (!JDSearchPaths.empty())
+      dbgs() << "Search paths:\n";
+    for (auto &KV : JDSearchPaths) {
+      dbgs() << "  " << KV.first->getName() << ": [";
+      for (auto &LibSearchPath : KV.second)
+        dbgs() << " \"" << LibSearchPath << "\"";
+      dbgs() << " ]\n";
+    }
   });
 
+  for (auto LibItr = Libraries.begin(), LibEnd = Libraries.end();
+       LibItr != LibEnd; ++LibItr) {
+
+    bool LibFound = false;
+    StringRef LibName(*LibItr);
+    unsigned LibIdx = Libraries.getPosition(LibItr - Libraries.begin());
+    auto &JD = *std::prev(IdxToJD.lower_bound(LibIdx))->second;
+
+    // If this is the name of a JITDylib then link against that.
+    if (auto *LJD = S.ES.getJITDylibByName(LibName)) {
+      JD.addToLinkOrder(*LJD);
+      continue;
+    }
+
+    // Otherwise look through the search paths.
+    auto JDSearchPathsItr = JDSearchPaths.find(&JD);
+    if (JDSearchPathsItr != JDSearchPaths.end()) {
+      for (StringRef SearchPath : JDSearchPathsItr->second) {
+        for (const char *LibExt : {".dylib", ".so", ".a"}) {
+          SmallVector<char, 256> LibPath;
+          LibPath.reserve(SearchPath.size() + strlen("lib") + LibName.size() +
+                          strlen(LibExt) + 2); // +2 for pathsep, null term.
+          llvm::copy(SearchPath, std::back_inserter(LibPath));
+          sys::path::append(LibPath, "lib" + LibName + LibExt);
+          LibPath.push_back('\0');
+
+          // Skip missing or non-regular paths.
+          if (sys::fs::get_file_type(LibPath.data()) !=
+              sys::fs::file_type::regular_file) {
+            continue;
+          }
+
+          file_magic Magic;
+          if (auto EC = identify_magic(LibPath, Magic)) {
+            // If there was an error loading the file then skip it.
+            LLVM_DEBUG({
+              dbgs() << "Library search found \"" << LibPath
+                     << "\", but could not identify file type (" << EC.message()
+                     << "). Skipping.\n";
+            });
+            continue;
+          }
+
+          // We identified the magic. Assume that we can load it -- we'll reset
+          // in the default case.
+          LibFound = true;
+          switch (Magic) {
+          case file_magic::elf_shared_object:
+          case file_magic::macho_dynamically_linked_shared_lib: {
+            // TODO: On first reference to LibPath this should create a JITDylib
+            // with a generator and add it to JD's links-against list. Subsquent
+            // references should use the JITDylib created on the first
+            // reference.
+            auto G =
+                EPCDynamicLibrarySearchGenerator::Load(S.ES, LibPath.data());
+            if (!G)
+              return G.takeError();
+            LLVM_DEBUG({
+              dbgs() << "Adding generator for dynamic library "
+                     << LibPath.data() << " to " << JD.getName() << "\n";
+            });
+            JD.addGenerator(std::move(*G));
+            break;
+          }
+          case file_magic::archive:
+          case file_magic::macho_universal_binary: {
+            auto G = StaticLibraryDefinitionGenerator::Load(
+                S.ObjLayer, LibPath.data(),
+                S.ES.getExecutorProcessControl().getTargetTriple());
+            if (!G)
+              return G.takeError();
+            JD.addGenerator(std::move(*G));
+            LLVM_DEBUG({
+              dbgs() << "Adding generator for static library " << LibPath.data()
+                     << " to " << JD.getName() << "\n";
+            });
+            break;
+          }
+          default:
+            // This file isn't a recognized library kind.
+            LLVM_DEBUG({
+              dbgs() << "Library search found \"" << LibPath
+                     << "\", but file type is not supported. Skipping.\n";
+            });
+            LibFound = false;
+            break;
+          }
+          if (LibFound)
+            break;
+        }
+        if (LibFound)
+          break;
+      }
+    }
+
+    if (!LibFound)
+      return make_error<StringError>("While linking " + JD.getName() +
+                                         ", could not find library for -l" +
+                                         LibName,
+                                     inconvertibleErrorCode());
+  }
+
+  return Error::success();
+}
+
+static Error addProcessSymbols(Session &S,
+                               const std::map<unsigned, JITDylib *> &IdxToJD) {
+
+  if (NoProcessSymbols)
+    return Error::success();
+
+  for (auto &KV : IdxToJD) {
+    auto &JD = *KV.second;
+    JD.addGenerator(ExitOnErr(
+        orc::EPCDynamicLibrarySearchGenerator::GetForTargetProcess(S.ES)));
+  }
+
+  return Error::success();
+}
+
+static Error addSessionInputs(Session &S) {
+  std::map<unsigned, JITDylib *> IdxToJD;
+
+  if (auto Err = createJITDylibs(S, IdxToJD))
+    return Err;
+
+  if (auto Err = addAbsoluteSymbols(S, IdxToJD))
+    return Err;
+
+  if (!TestHarnesses.empty())
+    if (auto Err = addTestHarnesses(S))
+      return Err;
+
+  if (auto Err = addObjects(S, IdxToJD))
+    return Err;
+
+  if (auto Err = addLibraries(S, IdxToJD))
+    return Err;
+
+  if (auto Err = addProcessSymbols(S, IdxToJD))
+    return Err;
+
   return Error::success();
 }
 
@@ -1613,7 +1804,7 @@ int main(int argc, char *argv[]) {
 
   {
     TimeRegion TR(Timers ? &Timers->LoadObjectsTimer : nullptr);
-    ExitOnErr(loadObjects(*S));
+    ExitOnErr(addSessionInputs(*S));
   }
 
   if (PhonyExternals)
@@ -1644,6 +1835,9 @@ int main(int argc, char *argv[]) {
     }
   }
 
+  if (ShowEntryExecutionSessionState)
+    S->ES.dump(outs());
+
   if (ShowAddrs)
     S->dumpSessionInfo(outs());
 

diff  --git a/llvm/tools/llvm-jitlink/llvm-jitlink.h b/llvm/tools/llvm-jitlink/llvm-jitlink.h
index 7873bcaa13d4c..15c62327c8280 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.h
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.h
@@ -36,6 +36,7 @@ struct Session {
   orc::JITDylib *MainJD = nullptr;
   orc::ObjectLinkingLayer ObjLayer;
   orc::JITDylibSearchOrder JDSearchOrder;
+  std::vector<std::string> LibrarySearchPaths;
 
   ~Session();
 


        


More information about the llvm-commits mailing list