1//===- llvm-jitlink.cpp -- Command line interface/tester for llvm-jitlink -===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This utility provides a simple command line interface to the llvm jitlink
10// library, which makes relocatable object files executable in memory. Its
11// primary function is as a testing utility for the jitlink library.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm-jitlink.h"
16
17#include "llvm/BinaryFormat/Magic.h"
18#include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
19#include "llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h"
20#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
21#include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h"
22#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupportPlugin.h"
23#include "llvm/ExecutionEngine/Orc/Debugging/PerfSupportPlugin.h"
24#include "llvm/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.h"
25#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
26#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
27#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
28#include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h"
29#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
30#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
31#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
32#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
33#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
34#include "llvm/ExecutionEngine/Orc/SectCreate.h"
35#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
36#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
37#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h"
38#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h"
39#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
40#include "llvm/MC/MCAsmInfo.h"
41#include "llvm/MC/MCContext.h"
42#include "llvm/MC/MCDisassembler/MCDisassembler.h"
43#include "llvm/MC/MCInstPrinter.h"
44#include "llvm/MC/MCInstrAnalysis.h"
45#include "llvm/MC/MCInstrInfo.h"
46#include "llvm/MC/MCRegisterInfo.h"
47#include "llvm/MC/MCSubtargetInfo.h"
48#include "llvm/MC/MCTargetOptions.h"
49#include "llvm/MC/TargetRegistry.h"
50#include "llvm/Object/COFF.h"
51#include "llvm/Object/MachO.h"
52#include "llvm/Object/ObjectFile.h"
53#include "llvm/Support/CommandLine.h"
54#include "llvm/Support/Debug.h"
55#include "llvm/Support/InitLLVM.h"
56#include "llvm/Support/MemoryBuffer.h"
57#include "llvm/Support/Path.h"
58#include "llvm/Support/Process.h"
59#include "llvm/Support/TargetSelect.h"
60#include "llvm/Support/Timer.h"
61
62#include <cstring>
63#include <deque>
64#include <string>
65
66#ifdef LLVM_ON_UNIX
67#include <netdb.h>
68#include <netinet/in.h>
69#include <sys/socket.h>
70#include <unistd.h>
71#endif // LLVM_ON_UNIX
72
73#define DEBUG_TYPE "llvm_jitlink"
74
75using namespace llvm;
76using namespace llvm::jitlink;
77using namespace llvm::orc;
78
79static cl::OptionCategory JITLinkCategory("JITLink Options");
80
81static cl::list<std::string> InputFiles(cl::Positional, cl::OneOrMore,
82 cl::desc("input files"),
83 cl::cat(JITLinkCategory));
84
85static cl::list<std::string>
86 LibrarySearchPaths("L",
87 cl::desc("Add dir to the list of library search paths"),
88 cl::Prefix, cl::cat(JITLinkCategory));
89
90static cl::list<std::string>
91 Libraries("l",
92 cl::desc("Link against library X in the library search paths"),
93 cl::Prefix, cl::cat(JITLinkCategory));
94
95static cl::list<std::string>
96 LibrariesHidden("hidden-l",
97 cl::desc("Link against library X in the library search "
98 "paths with hidden visibility"),
99 cl::Prefix, cl::cat(JITLinkCategory));
100
101static cl::list<std::string>
102 LoadHidden("load_hidden",
103 cl::desc("Link against library X with hidden visibility"),
104 cl::cat(JITLinkCategory));
105
106static cl::opt<bool> SearchSystemLibrary(
107 "search-sys-lib",
108 cl::desc("Add system library paths to library search paths"),
109 cl::init(Val: false), cl::cat(JITLinkCategory));
110
111static cl::opt<bool> NoExec("noexec", cl::desc("Do not execute loaded code"),
112 cl::init(Val: false), cl::cat(JITLinkCategory));
113
114static cl::list<std::string>
115 CheckFiles("check", cl::desc("File containing verifier checks"),
116 cl::cat(JITLinkCategory));
117
118static cl::opt<std::string>
119 CheckName("check-name", cl::desc("Name of checks to match against"),
120 cl::init(Val: "jitlink-check"), cl::cat(JITLinkCategory));
121
122static cl::opt<std::string>
123 EntryPointName("entry", cl::desc("Symbol to call as main entry point"),
124 cl::init(Val: ""), cl::cat(JITLinkCategory));
125
126static cl::list<std::string> JITDylibs(
127 "jd",
128 cl::desc("Specifies the JITDylib to be used for any subsequent "
129 "input file, -L<seacrh-path>, and -l<library> arguments"),
130 cl::cat(JITLinkCategory));
131
132static cl::list<std::string>
133 Dylibs("preload",
134 cl::desc("Pre-load dynamic libraries (e.g. language runtimes "
135 "required by the ORC runtime)"),
136 cl::cat(JITLinkCategory));
137
138static cl::list<std::string> InputArgv("args", cl::Positional,
139 cl::desc("<program arguments>..."),
140 cl::PositionalEatsArgs,
141 cl::cat(JITLinkCategory));
142
143static cl::opt<bool>
144 DebuggerSupport("debugger-support",
145 cl::desc("Enable debugger suppport (default = !-noexec)"),
146 cl::init(Val: true), cl::Hidden, cl::cat(JITLinkCategory));
147
148static cl::opt<bool> PerfSupport("perf-support",
149 cl::desc("Enable perf profiling support"),
150 cl::init(Val: false), cl::Hidden,
151 cl::cat(JITLinkCategory));
152
153static cl::opt<bool> VTuneSupport("vtune-support",
154 cl::desc("Enable vtune profiling support"),
155 cl::init(Val: false), cl::Hidden,
156 cl::cat(JITLinkCategory));
157static cl::opt<bool>
158 NoProcessSymbols("no-process-syms",
159 cl::desc("Do not resolve to llvm-jitlink process symbols"),
160 cl::init(Val: false), cl::cat(JITLinkCategory));
161
162static cl::list<std::string> AbsoluteDefs(
163 "abs",
164 cl::desc("Inject absolute symbol definitions (syntax: <name>=<addr>)"),
165 cl::cat(JITLinkCategory));
166
167static cl::list<std::string>
168 Aliases("alias",
169 cl::desc("Inject symbol aliases (syntax: <alias-name>=<aliasee>)"),
170 cl::cat(JITLinkCategory));
171
172static cl::list<std::string>
173 SectCreate("sectcreate",
174 cl::desc("given <sectname>,<filename>[@<sym>=<offset>,...] "
175 "add the content of <filename> to <sectname>"),
176 cl::cat(JITLinkCategory));
177
178static cl::list<std::string> TestHarnesses("harness", cl::Positional,
179 cl::desc("Test harness files"),
180 cl::PositionalEatsArgs,
181 cl::cat(JITLinkCategory));
182
183static cl::opt<bool> ShowInitialExecutionSessionState(
184 "show-init-es",
185 cl::desc("Print ExecutionSession state before resolving entry point"),
186 cl::init(Val: false), cl::cat(JITLinkCategory));
187
188static cl::opt<bool> ShowEntryExecutionSessionState(
189 "show-entry-es",
190 cl::desc("Print ExecutionSession state after resolving entry point"),
191 cl::init(Val: false), cl::cat(JITLinkCategory));
192
193static cl::opt<bool> ShowAddrs(
194 "show-addrs",
195 cl::desc("Print registered symbol, section, got and stub addresses"),
196 cl::init(Val: false), cl::cat(JITLinkCategory));
197
198static cl::opt<std::string> ShowLinkGraphs(
199 "show-graphs",
200 cl::desc("Takes a posix regex and prints the link graphs of all files "
201 "matching that regex after fixups have been applied"),
202 cl::Optional, cl::cat(JITLinkCategory));
203
204static cl::opt<bool> ShowTimes("show-times",
205 cl::desc("Show times for llvm-jitlink phases"),
206 cl::init(Val: false), cl::cat(JITLinkCategory));
207
208static cl::opt<std::string> SlabAllocateSizeString(
209 "slab-allocate",
210 cl::desc("Allocate from a slab of the given size "
211 "(allowable suffixes: Kb, Mb, Gb. default = "
212 "Kb)"),
213 cl::init(Val: ""), cl::cat(JITLinkCategory));
214
215static cl::opt<uint64_t> SlabAddress(
216 "slab-address",
217 cl::desc("Set slab target address (requires -slab-allocate and -noexec)"),
218 cl::init(Val: ~0ULL), cl::cat(JITLinkCategory));
219
220static cl::opt<uint64_t> SlabPageSize(
221 "slab-page-size",
222 cl::desc("Set page size for slab (requires -slab-allocate and -noexec)"),
223 cl::init(Val: 0), cl::cat(JITLinkCategory));
224
225static cl::opt<bool> ShowRelocatedSectionContents(
226 "show-relocated-section-contents",
227 cl::desc("show section contents after fixups have been applied"),
228 cl::init(Val: false), cl::cat(JITLinkCategory));
229
230static cl::opt<bool> PhonyExternals(
231 "phony-externals",
232 cl::desc("resolve all otherwise unresolved externals to null"),
233 cl::init(Val: false), cl::cat(JITLinkCategory));
234
235static cl::opt<std::string> OutOfProcessExecutor(
236 "oop-executor", cl::desc("Launch an out-of-process executor to run code"),
237 cl::ValueOptional, cl::cat(JITLinkCategory));
238
239static cl::opt<std::string> OutOfProcessExecutorConnect(
240 "oop-executor-connect",
241 cl::desc("Connect to an out-of-process executor via TCP"),
242 cl::cat(JITLinkCategory));
243
244static cl::opt<std::string>
245 OrcRuntime("orc-runtime", cl::desc("Use ORC runtime from given path"),
246 cl::init(Val: ""), cl::cat(JITLinkCategory));
247
248static cl::opt<bool> AddSelfRelocations(
249 "add-self-relocations",
250 cl::desc("Add relocations to function pointers to the current function"),
251 cl::init(Val: false), cl::cat(JITLinkCategory));
252
253static cl::opt<bool>
254 ShowErrFailedToMaterialize("show-err-failed-to-materialize",
255 cl::desc("Show FailedToMaterialize errors"),
256 cl::init(Val: false), cl::cat(JITLinkCategory));
257
258static cl::opt<bool> UseSharedMemory(
259 "use-shared-memory",
260 cl::desc("Use shared memory to transfer generated code and data"),
261 cl::init(Val: false), cl::cat(JITLinkCategory));
262
263static ExitOnError ExitOnErr;
264
265static LLVM_ATTRIBUTE_USED void linkComponents() {
266 errs() << "Linking in runtime functions\n"
267 << (void *)&llvm_orc_registerEHFrameSectionWrapper << '\n'
268 << (void *)&llvm_orc_deregisterEHFrameSectionWrapper << '\n'
269 << (void *)&llvm_orc_registerJITLoaderGDBWrapper << '\n'
270 << (void *)&llvm_orc_registerJITLoaderGDBAllocAction << '\n'
271 << (void *)&llvm_orc_registerJITLoaderPerfStart << '\n'
272 << (void *)&llvm_orc_registerJITLoaderPerfEnd << '\n'
273 << (void *)&llvm_orc_registerJITLoaderPerfImpl << '\n'
274 << (void *)&llvm_orc_registerVTuneImpl << '\n'
275 << (void *)&llvm_orc_unregisterVTuneImpl << '\n'
276 << (void *)&llvm_orc_test_registerVTuneImpl << '\n';
277}
278
279static bool UseTestResultOverride = false;
280static int64_t TestResultOverride = 0;
281
282extern "C" LLVM_ATTRIBUTE_USED void
283llvm_jitlink_setTestResultOverride(int64_t Value) {
284 TestResultOverride = Value;
285 UseTestResultOverride = true;
286}
287
288static Error addSelfRelocations(LinkGraph &G);
289
290namespace {
291
292template <typename ErrT>
293
294class ConditionalPrintErr {
295public:
296 ConditionalPrintErr(bool C) : C(C) {}
297 void operator()(ErrT &EI) {
298 if (C) {
299 errs() << "llvm-jitlink error: ";
300 EI.log(errs());
301 errs() << "\n";
302 }
303 }
304
305private:
306 bool C;
307};
308
309Expected<std::unique_ptr<MemoryBuffer>> getFile(const Twine &FileName) {
310 if (auto F = MemoryBuffer::getFile(Filename: FileName))
311 return std::move(*F);
312 else
313 return createFileError(F: FileName, EC: F.getError());
314}
315
316void reportLLVMJITLinkError(Error Err) {
317 handleAllErrors(
318 E: std::move(Err),
319 Handlers: ConditionalPrintErr<orc::FailedToMaterialize>(ShowErrFailedToMaterialize),
320 Handlers: ConditionalPrintErr<ErrorInfoBase>(true));
321}
322
323} // end anonymous namespace
324
325namespace llvm {
326
327static raw_ostream &
328operator<<(raw_ostream &OS, const Session::MemoryRegionInfo &MRI) {
329 return OS << "target addr = "
330 << format(Fmt: "0x%016" PRIx64, Vals: MRI.getTargetAddress())
331 << ", content: " << (const void *)MRI.getContent().data() << " -- "
332 << (const void *)(MRI.getContent().data() + MRI.getContent().size())
333 << " (" << MRI.getContent().size() << " bytes)";
334}
335
336static raw_ostream &
337operator<<(raw_ostream &OS, const Session::SymbolInfoMap &SIM) {
338 OS << "Symbols:\n";
339 for (auto &SKV : SIM)
340 OS << " \"" << SKV.first() << "\" " << SKV.second << "\n";
341 return OS;
342}
343
344static raw_ostream &
345operator<<(raw_ostream &OS, const Session::FileInfo &FI) {
346 for (auto &SIKV : FI.SectionInfos)
347 OS << " Section \"" << SIKV.first() << "\": " << SIKV.second << "\n";
348 for (auto &GOTKV : FI.GOTEntryInfos)
349 OS << " GOT \"" << GOTKV.first() << "\": " << GOTKV.second << "\n";
350 for (auto &StubKVs : FI.StubInfos) {
351 OS << " Stubs \"" << StubKVs.first() << "\":";
352 for (auto MemRegion : StubKVs.second)
353 OS << " " << MemRegion;
354 OS << "\n";
355 }
356 return OS;
357}
358
359static raw_ostream &
360operator<<(raw_ostream &OS, const Session::FileInfoMap &FIM) {
361 for (auto &FIKV : FIM)
362 OS << "File \"" << FIKV.first() << "\":\n" << FIKV.second;
363 return OS;
364}
365
366static Error applyHarnessPromotions(Session &S, LinkGraph &G) {
367
368 // If this graph is part of the test harness there's nothing to do.
369 if (S.HarnessFiles.empty() || S.HarnessFiles.count(Key: G.getName()))
370 return Error::success();
371
372 LLVM_DEBUG(dbgs() << "Applying promotions to graph " << G.getName() << "\n");
373
374 // If this graph is part of the test then promote any symbols referenced by
375 // the harness to default scope, remove all symbols that clash with harness
376 // definitions.
377 std::vector<Symbol *> DefinitionsToRemove;
378 for (auto *Sym : G.defined_symbols()) {
379
380 if (!Sym->hasName())
381 continue;
382
383 if (Sym->getLinkage() == Linkage::Weak) {
384 if (!S.CanonicalWeakDefs.count(Val: Sym->getName()) ||
385 S.CanonicalWeakDefs[Sym->getName()] != G.getName()) {
386 LLVM_DEBUG({
387 dbgs() << " Externalizing weak symbol " << Sym->getName() << "\n";
388 });
389 DefinitionsToRemove.push_back(x: Sym);
390 } else {
391 LLVM_DEBUG({
392 dbgs() << " Making weak symbol " << Sym->getName() << " strong\n";
393 });
394 if (S.HarnessExternals.count(Key: Sym->getName()))
395 Sym->setScope(Scope::Default);
396 else
397 Sym->setScope(Scope::Hidden);
398 Sym->setLinkage(Linkage::Strong);
399 }
400 } else if (S.HarnessExternals.count(Key: Sym->getName())) {
401 LLVM_DEBUG(dbgs() << " Promoting " << Sym->getName() << "\n");
402 Sym->setScope(Scope::Default);
403 Sym->setLive(true);
404 continue;
405 } else if (S.HarnessDefinitions.count(Key: Sym->getName())) {
406 LLVM_DEBUG(dbgs() << " Externalizing " << Sym->getName() << "\n");
407 DefinitionsToRemove.push_back(x: Sym);
408 }
409 }
410
411 for (auto *Sym : DefinitionsToRemove)
412 G.makeExternal(Sym&: *Sym);
413
414 return Error::success();
415}
416
417static void dumpSectionContents(raw_ostream &OS, LinkGraph &G) {
418 constexpr orc::ExecutorAddrDiff DumpWidth = 16;
419 static_assert(isPowerOf2_64(Value: DumpWidth), "DumpWidth must be a power of two");
420
421 // Put sections in address order.
422 std::vector<Section *> Sections;
423 for (auto &S : G.sections())
424 Sections.push_back(x: &S);
425
426 llvm::sort(C&: Sections, Comp: [](const Section *LHS, const Section *RHS) {
427 if (LHS->symbols().empty() && RHS->symbols().empty())
428 return false;
429 if (LHS->symbols().empty())
430 return false;
431 if (RHS->symbols().empty())
432 return true;
433 SectionRange LHSRange(*LHS);
434 SectionRange RHSRange(*RHS);
435 return LHSRange.getStart() < RHSRange.getStart();
436 });
437
438 for (auto *S : Sections) {
439 OS << S->getName() << " content:";
440 if (S->symbols().empty()) {
441 OS << "\n section empty\n";
442 continue;
443 }
444
445 // Sort symbols into order, then render.
446 std::vector<Symbol *> Syms(S->symbols().begin(), S->symbols().end());
447 llvm::sort(C&: Syms, Comp: [](const Symbol *LHS, const Symbol *RHS) {
448 return LHS->getAddress() < RHS->getAddress();
449 });
450
451 orc::ExecutorAddr NextAddr(Syms.front()->getAddress().getValue() &
452 ~(DumpWidth - 1));
453 for (auto *Sym : Syms) {
454 bool IsZeroFill = Sym->getBlock().isZeroFill();
455 auto SymStart = Sym->getAddress();
456 auto SymSize = Sym->getSize();
457 auto SymEnd = SymStart + SymSize;
458 const uint8_t *SymData = IsZeroFill ? nullptr
459 : reinterpret_cast<const uint8_t *>(
460 Sym->getSymbolContent().data());
461
462 // Pad any space before the symbol starts.
463 while (NextAddr != SymStart) {
464 if (NextAddr % DumpWidth == 0)
465 OS << formatv(Fmt: "\n{0:x16}:", Vals&: NextAddr);
466 OS << " ";
467 ++NextAddr;
468 }
469
470 // Render the symbol content.
471 while (NextAddr != SymEnd) {
472 if (NextAddr % DumpWidth == 0)
473 OS << formatv(Fmt: "\n{0:x16}:", Vals&: NextAddr);
474 if (IsZeroFill)
475 OS << " 00";
476 else
477 OS << formatv(Fmt: " {0:x-2}", Vals: SymData[NextAddr - SymStart]);
478 ++NextAddr;
479 }
480 }
481 OS << "\n";
482 }
483}
484
485// A memory mapper with a fake offset applied only used for -noexec testing
486class InProcessDeltaMapper final : public InProcessMemoryMapper {
487public:
488 InProcessDeltaMapper(size_t PageSize, uint64_t TargetAddr)
489 : InProcessMemoryMapper(PageSize), TargetMapAddr(TargetAddr),
490 DeltaAddr(0) {}
491
492 static Expected<std::unique_ptr<InProcessDeltaMapper>> Create() {
493 size_t PageSize = SlabPageSize;
494 if (!PageSize) {
495 if (auto PageSizeOrErr = sys::Process::getPageSize())
496 PageSize = *PageSizeOrErr;
497 else
498 return PageSizeOrErr.takeError();
499 }
500
501 if (PageSize == 0)
502 return make_error<StringError>(Args: "Page size is zero",
503 Args: inconvertibleErrorCode());
504
505 return std::make_unique<InProcessDeltaMapper>(args&: PageSize, args&: SlabAddress);
506 }
507
508 void reserve(size_t NumBytes, OnReservedFunction OnReserved) override {
509 InProcessMemoryMapper::reserve(
510 NumBytes, OnReserved: [this, OnReserved = std::move(OnReserved)](
511 Expected<ExecutorAddrRange> Result) mutable {
512 if (!Result)
513 return OnReserved(Result.takeError());
514
515 assert(DeltaAddr == 0 && "Overwriting previous offset");
516 if (TargetMapAddr != ~0ULL)
517 DeltaAddr = TargetMapAddr - Result->Start.getValue();
518 auto OffsetRange = ExecutorAddrRange(Result->Start + DeltaAddr,
519 Result->End + DeltaAddr);
520
521 OnReserved(OffsetRange);
522 });
523 }
524
525 char *prepare(ExecutorAddr Addr, size_t ContentSize) override {
526 return InProcessMemoryMapper::prepare(Addr: Addr - DeltaAddr, ContentSize);
527 }
528
529 void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override {
530 // Slide mapping based on delta, make all segments read-writable, and
531 // discard allocation actions.
532 auto FixedAI = std::move(AI);
533 FixedAI.MappingBase -= DeltaAddr;
534 for (auto &Seg : FixedAI.Segments)
535 Seg.AG = {MemProt::Read | MemProt::Write, Seg.AG.getMemLifetime()};
536 FixedAI.Actions.clear();
537 InProcessMemoryMapper::initialize(
538 AI&: FixedAI, OnInitialized: [this, OnInitialized = std::move(OnInitialized)](
539 Expected<ExecutorAddr> Result) mutable {
540 if (!Result)
541 return OnInitialized(Result.takeError());
542
543 OnInitialized(ExecutorAddr(Result->getValue() + DeltaAddr));
544 });
545 }
546
547 void deinitialize(ArrayRef<ExecutorAddr> Allocations,
548 OnDeinitializedFunction OnDeInitialized) override {
549 std::vector<ExecutorAddr> Addrs(Allocations.size());
550 for (const auto Base : Allocations) {
551 Addrs.push_back(x: Base - DeltaAddr);
552 }
553
554 InProcessMemoryMapper::deinitialize(Allocations: Addrs, OnDeInitialized: std::move(OnDeInitialized));
555 }
556
557 void release(ArrayRef<ExecutorAddr> Reservations,
558 OnReleasedFunction OnRelease) override {
559 std::vector<ExecutorAddr> Addrs(Reservations.size());
560 for (const auto Base : Reservations) {
561 Addrs.push_back(x: Base - DeltaAddr);
562 }
563 InProcessMemoryMapper::release(Reservations: Addrs, OnRelease: std::move(OnRelease));
564 }
565
566private:
567 uint64_t TargetMapAddr;
568 uint64_t DeltaAddr;
569};
570
571Expected<uint64_t> getSlabAllocSize(StringRef SizeString) {
572 SizeString = SizeString.trim();
573
574 uint64_t Units = 1024;
575
576 if (SizeString.ends_with_insensitive(Suffix: "kb"))
577 SizeString = SizeString.drop_back(N: 2).rtrim();
578 else if (SizeString.ends_with_insensitive(Suffix: "mb")) {
579 Units = 1024 * 1024;
580 SizeString = SizeString.drop_back(N: 2).rtrim();
581 } else if (SizeString.ends_with_insensitive(Suffix: "gb")) {
582 Units = 1024 * 1024 * 1024;
583 SizeString = SizeString.drop_back(N: 2).rtrim();
584 }
585
586 uint64_t SlabSize = 0;
587 if (SizeString.getAsInteger(Radix: 10, Result&: SlabSize))
588 return make_error<StringError>(Args: "Invalid numeric format for slab size",
589 Args: inconvertibleErrorCode());
590
591 return SlabSize * Units;
592}
593
594static std::unique_ptr<JITLinkMemoryManager> createInProcessMemoryManager() {
595 uint64_t SlabSize;
596#ifdef _WIN32
597 SlabSize = 1024 * 1024;
598#else
599 SlabSize = 1024 * 1024 * 1024;
600#endif
601
602 if (!SlabAllocateSizeString.empty())
603 SlabSize = ExitOnErr(getSlabAllocSize(SizeString: SlabAllocateSizeString));
604
605 // If this is a -no-exec case and we're tweaking the slab address or size then
606 // use the delta mapper.
607 if (NoExec && (SlabAddress || SlabPageSize))
608 return ExitOnErr(
609 MapperJITLinkMemoryManager::CreateWithMapper<InProcessDeltaMapper>(
610 ReservationGranularity: SlabSize));
611
612 // Otherwise use the standard in-process mapper.
613 return ExitOnErr(
614 MapperJITLinkMemoryManager::CreateWithMapper<InProcessMemoryMapper>(
615 ReservationGranularity: SlabSize));
616}
617
618Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
619createSharedMemoryManager(SimpleRemoteEPC &SREPC) {
620 SharedMemoryMapper::SymbolAddrs SAs;
621 if (auto Err = SREPC.getBootstrapSymbols(
622 Pairs: {{SAs.Instance, rt::ExecutorSharedMemoryMapperServiceInstanceName},
623 {SAs.Reserve,
624 rt::ExecutorSharedMemoryMapperServiceReserveWrapperName},
625 {SAs.Initialize,
626 rt::ExecutorSharedMemoryMapperServiceInitializeWrapperName},
627 {SAs.Deinitialize,
628 rt::ExecutorSharedMemoryMapperServiceDeinitializeWrapperName},
629 {SAs.Release,
630 rt::ExecutorSharedMemoryMapperServiceReleaseWrapperName}}))
631 return std::move(Err);
632
633#ifdef _WIN32
634 size_t SlabSize = 1024 * 1024;
635#else
636 size_t SlabSize = 1024 * 1024 * 1024;
637#endif
638
639 if (!SlabAllocateSizeString.empty())
640 SlabSize = ExitOnErr(getSlabAllocSize(SizeString: SlabAllocateSizeString));
641
642 return MapperJITLinkMemoryManager::CreateWithMapper<SharedMemoryMapper>(
643 ReservationGranularity: SlabSize, A&: SREPC, A&: SAs);
644}
645
646
647static Expected<MaterializationUnit::Interface>
648getTestObjectFileInterface(Session &S, MemoryBufferRef O) {
649
650 // Get the standard interface for this object, but ignore the symbols field.
651 // We'll handle that manually to include promotion.
652 auto I = getObjectFileInterface(ES&: S.ES, ObjBuffer: O);
653 if (!I)
654 return I.takeError();
655 I->SymbolFlags.clear();
656
657 // If creating an object file was going to fail it would have happened above,
658 // so we can 'cantFail' this.
659 auto Obj = cantFail(ValOrErr: object::ObjectFile::createObjectFile(Object: O));
660
661 // The init symbol must be included in the SymbolFlags map if present.
662 if (I->InitSymbol)
663 I->SymbolFlags[I->InitSymbol] =
664 JITSymbolFlags::MaterializationSideEffectsOnly;
665
666 for (auto &Sym : Obj->symbols()) {
667 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
668 if (!SymFlagsOrErr)
669 // TODO: Test this error.
670 return SymFlagsOrErr.takeError();
671
672 // Skip symbols not defined in this object file.
673 if ((*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined))
674 continue;
675
676 auto Name = Sym.getName();
677 if (!Name)
678 return Name.takeError();
679
680 // Skip symbols that have type SF_File.
681 if (auto SymType = Sym.getType()) {
682 if (*SymType == object::SymbolRef::ST_File)
683 continue;
684 } else
685 return SymType.takeError();
686
687 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Symbol: Sym);
688 if (!SymFlags)
689 return SymFlags.takeError();
690
691 if (SymFlags->isWeak()) {
692 // If this is a weak symbol that's not defined in the harness then we
693 // need to either mark it as strong (if this is the first definition
694 // that we've seen) or discard it.
695 if (S.HarnessDefinitions.count(Key: *Name) || S.CanonicalWeakDefs.count(Val: *Name))
696 continue;
697 S.CanonicalWeakDefs[*Name] = O.getBufferIdentifier();
698 *SymFlags &= ~JITSymbolFlags::Weak;
699 if (!S.HarnessExternals.count(Key: *Name))
700 *SymFlags &= ~JITSymbolFlags::Exported;
701 } else if (S.HarnessExternals.count(Key: *Name)) {
702 *SymFlags |= JITSymbolFlags::Exported;
703 } else if (S.HarnessDefinitions.count(Key: *Name) ||
704 !(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
705 continue;
706
707 auto InternedName = S.ES.intern(SymName: *Name);
708 I->SymbolFlags[InternedName] = std::move(*SymFlags);
709 }
710
711 return I;
712}
713
714static Error loadProcessSymbols(Session &S) {
715 S.ProcessSymsJD = &S.ES.createBareJITDylib(Name: "Process");
716 auto FilterMainEntryPoint =
717 [EPName = S.ES.intern(SymName: EntryPointName)](SymbolStringPtr Name) {
718 return Name != EPName;
719 };
720 S.ProcessSymsJD->addGenerator(
721 DefGenerator: ExitOnErr(orc::EPCDynamicLibrarySearchGenerator::GetForTargetProcess(
722 ES&: S.ES, Allow: std::move(FilterMainEntryPoint))));
723
724 return Error::success();
725}
726
727static Error loadDylibs(Session &S) {
728 LLVM_DEBUG(dbgs() << "Loading dylibs...\n");
729 for (const auto &Dylib : Dylibs) {
730 LLVM_DEBUG(dbgs() << " " << Dylib << "\n");
731 auto DL = S.getOrLoadDynamicLibrary(LibPath: Dylib);
732 if (!DL)
733 return DL.takeError();
734 }
735
736 return Error::success();
737}
738
739static Expected<std::unique_ptr<ExecutorProcessControl>> launchExecutor() {
740#ifndef LLVM_ON_UNIX
741 // FIXME: Add support for Windows.
742 return make_error<StringError>("-" + OutOfProcessExecutor.ArgStr +
743 " not supported on non-unix platforms",
744 inconvertibleErrorCode());
745#elif !LLVM_ENABLE_THREADS
746 // Out of process mode using SimpleRemoteEPC depends on threads.
747 return make_error<StringError>(
748 "-" + OutOfProcessExecutor.ArgStr +
749 " requires threads, but LLVM was built with "
750 "LLVM_ENABLE_THREADS=Off",
751 inconvertibleErrorCode());
752#else
753
754 constexpr int ReadEnd = 0;
755 constexpr int WriteEnd = 1;
756
757 // Pipe FDs.
758 int ToExecutor[2];
759 int FromExecutor[2];
760
761 pid_t ChildPID;
762
763 // Create pipes to/from the executor..
764 if (pipe(pipedes: ToExecutor) != 0 || pipe(pipedes: FromExecutor) != 0)
765 return make_error<StringError>(Args: "Unable to create pipe for executor",
766 Args: inconvertibleErrorCode());
767
768 ChildPID = fork();
769
770 if (ChildPID == 0) {
771 // In the child...
772
773 // Close the parent ends of the pipes
774 close(fd: ToExecutor[WriteEnd]);
775 close(fd: FromExecutor[ReadEnd]);
776
777 // Execute the child process.
778 std::unique_ptr<char[]> ExecutorPath, FDSpecifier;
779 {
780 ExecutorPath = std::make_unique<char[]>(num: OutOfProcessExecutor.size() + 1);
781 strcpy(dest: ExecutorPath.get(), src: OutOfProcessExecutor.data());
782
783 std::string FDSpecifierStr("filedescs=");
784 FDSpecifierStr += utostr(X: ToExecutor[ReadEnd]);
785 FDSpecifierStr += ',';
786 FDSpecifierStr += utostr(X: FromExecutor[WriteEnd]);
787 FDSpecifier = std::make_unique<char[]>(num: FDSpecifierStr.size() + 1);
788 strcpy(dest: FDSpecifier.get(), src: FDSpecifierStr.c_str());
789 }
790
791 char *const Args[] = {ExecutorPath.get(), FDSpecifier.get(), nullptr};
792 int RC = execvp(file: ExecutorPath.get(), argv: Args);
793 if (RC != 0) {
794 errs() << "unable to launch out-of-process executor \""
795 << ExecutorPath.get() << "\"\n";
796 exit(status: 1);
797 }
798 }
799 // else we're the parent...
800
801 // Close the child ends of the pipes
802 close(fd: ToExecutor[ReadEnd]);
803 close(fd: FromExecutor[WriteEnd]);
804
805 auto S = SimpleRemoteEPC::Setup();
806 if (UseSharedMemory)
807 S.CreateMemoryManager = createSharedMemoryManager;
808
809 return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
810 D: std::make_unique<DynamicThreadPoolTaskDispatcher>(args: std::nullopt),
811 S: std::move(S), TransportTCtorArgs&: FromExecutor[ReadEnd], TransportTCtorArgs&: ToExecutor[WriteEnd]);
812#endif
813}
814
815#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
816static Error createTCPSocketError(Twine Details) {
817 return make_error<StringError>(
818 Args: formatv(Fmt: "Failed to connect TCP socket '{0}': {1}",
819 Vals&: OutOfProcessExecutorConnect, Vals&: Details),
820 Args: inconvertibleErrorCode());
821}
822
823static Expected<int> connectTCPSocket(std::string Host, std::string PortStr) {
824 addrinfo *AI;
825 addrinfo Hints{};
826 Hints.ai_family = AF_INET;
827 Hints.ai_socktype = SOCK_STREAM;
828 Hints.ai_flags = AI_NUMERICSERV;
829
830 if (int EC = getaddrinfo(name: Host.c_str(), service: PortStr.c_str(), req: &Hints, pai: &AI))
831 return createTCPSocketError(Details: "Address resolution failed (" +
832 StringRef(gai_strerror(ecode: EC)) + ")");
833
834 // Cycle through the returned addrinfo structures and connect to the first
835 // reachable endpoint.
836 int SockFD;
837 addrinfo *Server;
838 for (Server = AI; Server != nullptr; Server = Server->ai_next) {
839 // socket might fail, e.g. if the address family is not supported. Skip to
840 // the next addrinfo structure in such a case.
841 if ((SockFD = socket(domain: AI->ai_family, type: AI->ai_socktype, protocol: AI->ai_protocol)) < 0)
842 continue;
843
844 // If connect returns null, we exit the loop with a working socket.
845 if (connect(fd: SockFD, addr: Server->ai_addr, len: Server->ai_addrlen) == 0)
846 break;
847
848 close(fd: SockFD);
849 }
850 freeaddrinfo(ai: AI);
851
852 // If we reached the end of the loop without connecting to a valid endpoint,
853 // dump the last error that was logged in socket() or connect().
854 if (Server == nullptr)
855 return createTCPSocketError(Details: std::strerror(errno));
856
857 return SockFD;
858}
859#endif
860
861static Expected<std::unique_ptr<ExecutorProcessControl>> connectToExecutor() {
862#ifndef LLVM_ON_UNIX
863 // FIXME: Add TCP support for Windows.
864 return make_error<StringError>("-" + OutOfProcessExecutorConnect.ArgStr +
865 " not supported on non-unix platforms",
866 inconvertibleErrorCode());
867#elif !LLVM_ENABLE_THREADS
868 // Out of process mode using SimpleRemoteEPC depends on threads.
869 return make_error<StringError>(
870 "-" + OutOfProcessExecutorConnect.ArgStr +
871 " requires threads, but LLVM was built with "
872 "LLVM_ENABLE_THREADS=Off",
873 inconvertibleErrorCode());
874#else
875
876 StringRef Host, PortStr;
877 std::tie(args&: Host, args&: PortStr) = StringRef(OutOfProcessExecutorConnect).split(Separator: ':');
878 if (Host.empty())
879 return createTCPSocketError(Details: "Host name for -" +
880 OutOfProcessExecutorConnect.ArgStr +
881 " can not be empty");
882 if (PortStr.empty())
883 return createTCPSocketError(Details: "Port number in -" +
884 OutOfProcessExecutorConnect.ArgStr +
885 " can not be empty");
886 int Port = 0;
887 if (PortStr.getAsInteger(Radix: 10, Result&: Port))
888 return createTCPSocketError(Details: "Port number '" + PortStr +
889 "' is not a valid integer");
890
891 Expected<int> SockFD = connectTCPSocket(Host: Host.str(), PortStr: PortStr.str());
892 if (!SockFD)
893 return SockFD.takeError();
894
895 auto S = SimpleRemoteEPC::Setup();
896 if (UseSharedMemory)
897 S.CreateMemoryManager = createSharedMemoryManager;
898
899 return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
900 D: std::make_unique<DynamicThreadPoolTaskDispatcher>(args: std::nullopt),
901 S: std::move(S), TransportTCtorArgs&: *SockFD, TransportTCtorArgs&: *SockFD);
902#endif
903}
904
905class PhonyExternalsGenerator : public DefinitionGenerator {
906public:
907 Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
908 JITDylibLookupFlags JDLookupFlags,
909 const SymbolLookupSet &LookupSet) override {
910 SymbolMap PhonySymbols;
911 for (auto &KV : LookupSet)
912 PhonySymbols[KV.first] = {ExecutorAddr(), JITSymbolFlags::Exported};
913 return JD.define(MU: absoluteSymbols(Symbols: std::move(PhonySymbols)));
914 }
915};
916
917Expected<std::unique_ptr<Session>> Session::Create(Triple TT,
918 SubtargetFeatures Features) {
919
920 std::unique_ptr<ExecutorProcessControl> EPC;
921 if (OutOfProcessExecutor.getNumOccurrences()) {
922 /// If -oop-executor is passed then launch the executor.
923 if (auto REPC = launchExecutor())
924 EPC = std::move(*REPC);
925 else
926 return REPC.takeError();
927 } else if (OutOfProcessExecutorConnect.getNumOccurrences()) {
928 /// If -oop-executor-connect is passed then connect to the executor.
929 if (auto REPC = connectToExecutor())
930 EPC = std::move(*REPC);
931 else
932 return REPC.takeError();
933 } else {
934 /// Otherwise use SelfExecutorProcessControl to target the current process.
935 auto PageSize = sys::Process::getPageSize();
936 if (!PageSize)
937 return PageSize.takeError();
938 EPC = std::make_unique<SelfExecutorProcessControl>(
939 args: std::make_shared<SymbolStringPool>(),
940 args: std::make_unique<InPlaceTaskDispatcher>(), args: std::move(TT), args&: *PageSize,
941 args: createInProcessMemoryManager());
942 }
943
944 Error Err = Error::success();
945 std::unique_ptr<Session> S(new Session(std::move(EPC), Err));
946 if (Err)
947 return std::move(Err);
948 S->Features = std::move(Features);
949 return std::move(S);
950}
951
952Session::~Session() {
953 if (auto Err = ES.endSession())
954 ES.reportError(Err: std::move(Err));
955}
956
957Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err)
958 : ES(std::move(EPC)),
959 ObjLayer(ES, ES.getExecutorProcessControl().getMemMgr()) {
960
961 /// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig to the
962 /// Session.
963 class JITLinkSessionPlugin : public ObjectLinkingLayer::Plugin {
964 public:
965 JITLinkSessionPlugin(Session &S) : S(S) {}
966 void modifyPassConfig(MaterializationResponsibility &MR, LinkGraph &G,
967 PassConfiguration &PassConfig) override {
968 S.modifyPassConfig(FTT: G.getTargetTriple(), PassConfig);
969 }
970
971 Error notifyFailed(MaterializationResponsibility &MR) override {
972 return Error::success();
973 }
974 Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
975 return Error::success();
976 }
977 void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
978 ResourceKey SrcKey) override {}
979
980 private:
981 Session &S;
982 };
983
984 ErrorAsOutParameter _(&Err);
985
986 ES.setErrorReporter(reportLLVMJITLinkError);
987
988 if (!NoProcessSymbols)
989 ExitOnErr(loadProcessSymbols(S&: *this));
990
991 ExitOnErr(loadDylibs(S&: *this));
992
993 auto &TT = ES.getTargetTriple();
994
995 if (DebuggerSupport && TT.isOSBinFormatMachO()) {
996 if (!ProcessSymsJD) {
997 Err = make_error<StringError>(Args: "MachO debugging requires process symbols",
998 Args: inconvertibleErrorCode());
999 return;
1000 }
1001 ObjLayer.addPlugin(P: ExitOnErr(GDBJITDebugInfoRegistrationPlugin::Create(
1002 ES&: this->ES, ProcessJD&: *ProcessSymsJD, TT)));
1003 }
1004
1005 if (PerfSupport && TT.isOSBinFormatELF()) {
1006 if (!ProcessSymsJD) {
1007 Err = make_error<StringError>(Args: "MachO debugging requires process symbols",
1008 Args: inconvertibleErrorCode());
1009 return;
1010 }
1011 ObjLayer.addPlugin(P: ExitOnErr(DebugInfoPreservationPlugin::Create()));
1012 ObjLayer.addPlugin(P: ExitOnErr(PerfSupportPlugin::Create(
1013 EPC&: this->ES.getExecutorProcessControl(), JD&: *ProcessSymsJD, EmitDebugInfo: true, EmitUnwindInfo: true)));
1014 }
1015
1016 if (VTuneSupport && TT.isOSBinFormatELF()) {
1017 ObjLayer.addPlugin(P: ExitOnErr(DebugInfoPreservationPlugin::Create()));
1018 ObjLayer.addPlugin(P: ExitOnErr(
1019 VTuneSupportPlugin::Create(EPC&: this->ES.getExecutorProcessControl(),
1020 JD&: *ProcessSymsJD, /*EmitDebugInfo=*/true,
1021 /*TestMode=*/true)));
1022 }
1023
1024 // Set up the platform.
1025 if (!OrcRuntime.empty()) {
1026 assert(ProcessSymsJD && "ProcessSymsJD should have been set");
1027 PlatformJD = &ES.createBareJITDylib(Name: "Platform");
1028 PlatformJD->addToLinkOrder(JD&: *ProcessSymsJD);
1029
1030 if (TT.isOSBinFormatMachO()) {
1031 if (auto P = MachOPlatform::Create(ES, ObjLinkingLayer&: ObjLayer, PlatformJD&: *PlatformJD,
1032 OrcRuntimePath: OrcRuntime.c_str()))
1033 ES.setPlatform(std::move(*P));
1034 else {
1035 Err = P.takeError();
1036 return;
1037 }
1038 } else if (TT.isOSBinFormatELF()) {
1039 if (auto P = ELFNixPlatform::Create(ES, ObjLinkingLayer&: ObjLayer, PlatformJD&: *PlatformJD,
1040 OrcRuntimePath: OrcRuntime.c_str()))
1041 ES.setPlatform(std::move(*P));
1042 else {
1043 Err = P.takeError();
1044 return;
1045 }
1046 } else if (TT.isOSBinFormatCOFF()) {
1047 auto LoadDynLibrary = [&, this](JITDylib &JD,
1048 StringRef DLLName) -> Error {
1049 if (!DLLName.ends_with_insensitive(Suffix: ".dll"))
1050 return make_error<StringError>(Args: "DLLName not ending with .dll",
1051 Args: inconvertibleErrorCode());
1052 return loadAndLinkDynamicLibrary(JD, LibPath: DLLName);
1053 };
1054
1055 if (auto P = COFFPlatform::Create(ES, ObjLinkingLayer&: ObjLayer, PlatformJD&: *PlatformJD,
1056 OrcRuntimePath: OrcRuntime.c_str(),
1057 LoadDynLibrary: std::move(LoadDynLibrary)))
1058 ES.setPlatform(std::move(*P));
1059 else {
1060 Err = P.takeError();
1061 return;
1062 }
1063 } else {
1064 Err = make_error<StringError>(
1065 Args: "-" + OrcRuntime.ArgStr + " specified, but format " +
1066 Triple::getObjectFormatTypeName(ObjectFormat: TT.getObjectFormat()) +
1067 " not supported",
1068 Args: inconvertibleErrorCode());
1069 return;
1070 }
1071 } else if (TT.isOSBinFormatELF()) {
1072 if (!NoExec)
1073 ObjLayer.addPlugin(P: std::make_unique<EHFrameRegistrationPlugin>(
1074 args&: ES, args: ExitOnErr(EPCEHFrameRegistrar::Create(ES&: this->ES))));
1075 if (DebuggerSupport)
1076 ObjLayer.addPlugin(P: std::make_unique<DebugObjectManagerPlugin>(
1077 args&: ES, args: ExitOnErr(createJITLoaderGDBRegistrar(ES&: this->ES)), args: true, args: true));
1078 }
1079
1080 if (auto MainJDOrErr = ES.createJITDylib(Name: "main"))
1081 MainJD = &*MainJDOrErr;
1082 else {
1083 Err = MainJDOrErr.takeError();
1084 return;
1085 }
1086
1087 if (NoProcessSymbols) {
1088 // This symbol is used in testcases, but we're not reflecting process
1089 // symbols so we'll need to make it available some other way.
1090 auto &TestResultJD = ES.createBareJITDylib(Name: "<TestResultJD>");
1091 ExitOnErr(TestResultJD.define(MU: absoluteSymbols(
1092 Symbols: {{ES.intern(SymName: "llvm_jitlink_setTestResultOverride"),
1093 {ExecutorAddr::fromPtr(Ptr: llvm_jitlink_setTestResultOverride),
1094 JITSymbolFlags::Exported}}})));
1095 MainJD->addToLinkOrder(JD&: TestResultJD);
1096 }
1097
1098 ObjLayer.addPlugin(P: std::make_unique<JITLinkSessionPlugin>(args&: *this));
1099
1100 // Process any harness files.
1101 for (auto &HarnessFile : TestHarnesses) {
1102 HarnessFiles.insert(key: HarnessFile);
1103
1104 auto ObjBuffer = ExitOnErr(getFile(FileName: HarnessFile));
1105
1106 auto ObjInterface =
1107 ExitOnErr(getObjectFileInterface(ES, ObjBuffer: ObjBuffer->getMemBufferRef()));
1108
1109 for (auto &KV : ObjInterface.SymbolFlags)
1110 HarnessDefinitions.insert(key: *KV.first);
1111
1112 auto Obj = ExitOnErr(
1113 object::ObjectFile::createObjectFile(Object: ObjBuffer->getMemBufferRef()));
1114
1115 for (auto &Sym : Obj->symbols()) {
1116 uint32_t SymFlags = ExitOnErr(Sym.getFlags());
1117 auto Name = ExitOnErr(Sym.getName());
1118
1119 if (Name.empty())
1120 continue;
1121
1122 if (SymFlags & object::BasicSymbolRef::SF_Undefined)
1123 HarnessExternals.insert(key: Name);
1124 }
1125 }
1126
1127 // If a name is defined by some harness file then it's a definition, not an
1128 // external.
1129 for (auto &DefName : HarnessDefinitions)
1130 HarnessExternals.erase(Key: DefName.getKey());
1131
1132 if (!ShowLinkGraphs.empty())
1133 ShowGraphsRegex = Regex(ShowLinkGraphs);
1134}
1135
1136void Session::dumpSessionInfo(raw_ostream &OS) {
1137 OS << "Registered addresses:\n" << SymbolInfos << FileInfos;
1138}
1139
1140void Session::modifyPassConfig(const Triple &TT,
1141 PassConfiguration &PassConfig) {
1142 if (!CheckFiles.empty())
1143 PassConfig.PostFixupPasses.push_back(x: [this](LinkGraph &G) {
1144 if (ES.getTargetTriple().getObjectFormat() == Triple::ELF)
1145 return registerELFGraphInfo(S&: *this, G);
1146
1147 if (ES.getTargetTriple().getObjectFormat() == Triple::MachO)
1148 return registerMachOGraphInfo(S&: *this, G);
1149
1150 if (ES.getTargetTriple().getObjectFormat() == Triple::COFF)
1151 return registerCOFFGraphInfo(S&: *this, G);
1152
1153 return make_error<StringError>(Args: "Unsupported object format for GOT/stub "
1154 "registration",
1155 Args: inconvertibleErrorCode());
1156 });
1157
1158 if (ShowGraphsRegex)
1159 PassConfig.PostFixupPasses.push_back(x: [this](LinkGraph &G) -> Error {
1160 // Print graph if ShowLinkGraphs is specified-but-empty, or if
1161 // it contains the given graph.
1162 if (ShowGraphsRegex->match(String: G.getName())) {
1163 outs() << "Link graph \"" << G.getName() << "\" post-fixup:\n";
1164 G.dump(OS&: outs());
1165 }
1166 return Error::success();
1167 });
1168
1169 PassConfig.PrePrunePasses.push_back(
1170 x: [this](LinkGraph &G) { return applyHarnessPromotions(S&: *this, G); });
1171
1172 if (ShowRelocatedSectionContents)
1173 PassConfig.PostFixupPasses.push_back(x: [](LinkGraph &G) -> Error {
1174 outs() << "Relocated section contents for " << G.getName() << ":\n";
1175 dumpSectionContents(OS&: outs(), G);
1176 return Error::success();
1177 });
1178
1179 if (AddSelfRelocations)
1180 PassConfig.PostPrunePasses.push_back(x: addSelfRelocations);
1181}
1182
1183Expected<JITDylib *> Session::getOrLoadDynamicLibrary(StringRef LibPath) {
1184 auto It = DynLibJDs.find(x: LibPath.str());
1185 if (It != DynLibJDs.end()) {
1186 return It->second;
1187 }
1188 auto G = EPCDynamicLibrarySearchGenerator::Load(ES, LibraryPath: LibPath.data());
1189 if (!G)
1190 return G.takeError();
1191 auto JD = &ES.createBareJITDylib(Name: LibPath.str());
1192
1193 JD->addGenerator(DefGenerator: std::move(*G));
1194 DynLibJDs.emplace(args: LibPath.str(), args&: JD);
1195 LLVM_DEBUG({
1196 dbgs() << "Loaded dynamic library " << LibPath.data() << " for " << LibPath
1197 << "\n";
1198 });
1199 return JD;
1200}
1201
1202Error Session::loadAndLinkDynamicLibrary(JITDylib &JD, StringRef LibPath) {
1203 auto DL = getOrLoadDynamicLibrary(LibPath);
1204 if (!DL)
1205 return DL.takeError();
1206 JD.addToLinkOrder(JD&: **DL);
1207 LLVM_DEBUG({
1208 dbgs() << "Linking dynamic library " << LibPath << " to " << JD.getName()
1209 << "\n";
1210 });
1211 return Error::success();
1212}
1213
1214Error Session::FileInfo::registerGOTEntry(
1215 LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget) {
1216 if (Sym.isSymbolZeroFill())
1217 return make_error<StringError>(Args: "Unexpected zero-fill symbol in section " +
1218 Sym.getBlock().getSection().getName(),
1219 Args: inconvertibleErrorCode());
1220 auto TS = GetSymbolTarget(G, Sym.getBlock());
1221 if (!TS)
1222 return TS.takeError();
1223 GOTEntryInfos[TS->getName()] = {Sym.getSymbolContent(),
1224 Sym.getAddress().getValue(),
1225 Sym.getTargetFlags()};
1226 return Error::success();
1227}
1228
1229Error Session::FileInfo::registerStubEntry(
1230 LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget) {
1231 if (Sym.isSymbolZeroFill())
1232 return make_error<StringError>(Args: "Unexpected zero-fill symbol in section " +
1233 Sym.getBlock().getSection().getName(),
1234 Args: inconvertibleErrorCode());
1235 auto TS = GetSymbolTarget(G, Sym.getBlock());
1236 if (!TS)
1237 return TS.takeError();
1238
1239 SmallVectorImpl<MemoryRegionInfo> &Entry = StubInfos[TS->getName()];
1240 Entry.insert(I: Entry.begin(),
1241 Elt: {Sym.getSymbolContent(), Sym.getAddress().getValue(),
1242 Sym.getTargetFlags()});
1243 return Error::success();
1244}
1245
1246Error Session::FileInfo::registerMultiStubEntry(
1247 LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget) {
1248 if (Sym.isSymbolZeroFill())
1249 return make_error<StringError>(Args: "Unexpected zero-fill symbol in section " +
1250 Sym.getBlock().getSection().getName(),
1251 Args: inconvertibleErrorCode());
1252
1253 auto Target = GetSymbolTarget(G, Sym.getBlock());
1254 if (!Target)
1255 return Target.takeError();
1256
1257 SmallVectorImpl<MemoryRegionInfo> &Entry = StubInfos[Target->getName()];
1258 Entry.emplace_back(Args: Sym.getSymbolContent(), Args: Sym.getAddress().getValue(),
1259 Args: Sym.getTargetFlags());
1260
1261 // Let's keep stubs ordered by ascending address.
1262 std::sort(first: Entry.begin(), last: Entry.end(),
1263 comp: [](const MemoryRegionInfo &L, const MemoryRegionInfo &R) {
1264 return L.getTargetAddress() < R.getTargetAddress();
1265 });
1266
1267 return Error::success();
1268}
1269
1270Expected<Session::FileInfo &> Session::findFileInfo(StringRef FileName) {
1271 auto FileInfoItr = FileInfos.find(Key: FileName);
1272 if (FileInfoItr == FileInfos.end())
1273 return make_error<StringError>(Args: "file \"" + FileName + "\" not recognized",
1274 Args: inconvertibleErrorCode());
1275 return FileInfoItr->second;
1276}
1277
1278Expected<Session::MemoryRegionInfo &>
1279Session::findSectionInfo(StringRef FileName, StringRef SectionName) {
1280 auto FI = findFileInfo(FileName);
1281 if (!FI)
1282 return FI.takeError();
1283 auto SecInfoItr = FI->SectionInfos.find(Key: SectionName);
1284 if (SecInfoItr == FI->SectionInfos.end())
1285 return make_error<StringError>(Args: "no section \"" + SectionName +
1286 "\" registered for file \"" + FileName +
1287 "\"",
1288 Args: inconvertibleErrorCode());
1289 return SecInfoItr->second;
1290}
1291
1292class MemoryMatcher {
1293public:
1294 MemoryMatcher(ArrayRef<char> Content)
1295 : Pos(Content.data()), End(Pos + Content.size()) {}
1296
1297 template <typename MaskType> bool matchMask(MaskType Mask) {
1298 if (Mask == (Mask & *reinterpret_cast<const MaskType *>(Pos))) {
1299 Pos += sizeof(MaskType);
1300 return true;
1301 }
1302 return false;
1303 }
1304
1305 template <typename ValueType> bool matchEqual(ValueType Value) {
1306 if (Value == *reinterpret_cast<const ValueType *>(Pos)) {
1307 Pos += sizeof(ValueType);
1308 return true;
1309 }
1310 return false;
1311 }
1312
1313 bool done() const { return Pos == End; }
1314
1315private:
1316 const char *Pos;
1317 const char *End;
1318};
1319
1320static StringRef detectStubKind(const Session::MemoryRegionInfo &Stub) {
1321 using namespace support::endian;
1322 auto Armv7MovWTle = byte_swap<uint32_t, endianness::little>(value: 0xe300c000);
1323 auto Armv7BxR12le = byte_swap<uint32_t, endianness::little>(value: 0xe12fff1c);
1324 auto Thumbv7MovWTle = byte_swap<uint32_t, endianness::little>(value: 0x0c00f240);
1325 auto Thumbv7BxR12le = byte_swap<uint16_t, endianness::little>(value: 0x4760);
1326
1327 MemoryMatcher M(Stub.getContent());
1328 if (M.matchMask(Mask: Thumbv7MovWTle)) {
1329 if (M.matchMask(Mask: Thumbv7MovWTle))
1330 if (M.matchEqual(Value: Thumbv7BxR12le))
1331 if (M.done())
1332 return "thumbv7_abs_le";
1333 } else if (M.matchMask(Mask: Armv7MovWTle)) {
1334 if (M.matchMask(Mask: Armv7MovWTle))
1335 if (M.matchEqual(Value: Armv7BxR12le))
1336 if (M.done())
1337 return "armv7_abs_le";
1338 }
1339 return "";
1340}
1341
1342Expected<Session::MemoryRegionInfo &>
1343Session::findStubInfo(StringRef FileName, StringRef TargetName,
1344 StringRef KindNameFilter) {
1345 auto FI = findFileInfo(FileName);
1346 if (!FI)
1347 return FI.takeError();
1348 auto StubInfoItr = FI->StubInfos.find(Key: TargetName);
1349 if (StubInfoItr == FI->StubInfos.end())
1350 return make_error<StringError>(Args: "no stub for \"" + TargetName +
1351 "\" registered for file \"" + FileName +
1352 "\"",
1353 Args: inconvertibleErrorCode());
1354 auto &StubsForTarget = StubInfoItr->second;
1355 assert(!StubsForTarget.empty() && "At least 1 stub in each entry");
1356 if (KindNameFilter.empty() && StubsForTarget.size() == 1)
1357 return StubsForTarget[0]; // Regular single-stub match
1358
1359 std::string KindsStr;
1360 SmallVector<MemoryRegionInfo *, 1> Matches;
1361 Regex KindNameMatcher(KindNameFilter.empty() ? ".*" : KindNameFilter);
1362 for (MemoryRegionInfo &Stub : StubsForTarget) {
1363 StringRef Kind = detectStubKind(Stub);
1364 if (KindNameMatcher.match(String: Kind))
1365 Matches.push_back(Elt: &Stub);
1366 KindsStr += "\"" + (Kind.empty() ? "<unknown>" : Kind.str()) + "\", ";
1367 }
1368 if (Matches.empty())
1369 return make_error<StringError>(
1370 Args: "\"" + TargetName + "\" has " + Twine(StubsForTarget.size()) +
1371 " stubs in file \"" + FileName +
1372 "\", but none of them matches the stub-kind filter \"" +
1373 KindNameFilter + "\" (all encountered kinds are " +
1374 StringRef(KindsStr.data(), KindsStr.size() - 2) + ").",
1375 Args: inconvertibleErrorCode());
1376 if (Matches.size() > 1)
1377 return make_error<StringError>(
1378 Args: "\"" + TargetName + "\" has " + Twine(Matches.size()) +
1379 " candidate stubs in file \"" + FileName +
1380 "\". Please refine stub-kind filter \"" + KindNameFilter +
1381 "\" for disambiguation (encountered kinds are " +
1382 StringRef(KindsStr.data(), KindsStr.size() - 2) + ").",
1383 Args: inconvertibleErrorCode());
1384
1385 return *Matches[0];
1386}
1387
1388Expected<Session::MemoryRegionInfo &>
1389Session::findGOTEntryInfo(StringRef FileName, StringRef TargetName) {
1390 auto FI = findFileInfo(FileName);
1391 if (!FI)
1392 return FI.takeError();
1393 auto GOTInfoItr = FI->GOTEntryInfos.find(Key: TargetName);
1394 if (GOTInfoItr == FI->GOTEntryInfos.end())
1395 return make_error<StringError>(Args: "no GOT entry for \"" + TargetName +
1396 "\" registered for file \"" + FileName +
1397 "\"",
1398 Args: inconvertibleErrorCode());
1399 return GOTInfoItr->second;
1400}
1401
1402bool Session::isSymbolRegistered(StringRef SymbolName) {
1403 return SymbolInfos.count(Key: SymbolName);
1404}
1405
1406Expected<Session::MemoryRegionInfo &>
1407Session::findSymbolInfo(StringRef SymbolName, Twine ErrorMsgStem) {
1408 auto SymInfoItr = SymbolInfos.find(Key: SymbolName);
1409 if (SymInfoItr == SymbolInfos.end())
1410 return make_error<StringError>(Args: ErrorMsgStem + ": symbol " + SymbolName +
1411 " not found",
1412 Args: inconvertibleErrorCode());
1413 return SymInfoItr->second;
1414}
1415
1416} // end namespace llvm
1417
1418static std::pair<Triple, SubtargetFeatures> getFirstFileTripleAndFeatures() {
1419 static std::pair<Triple, SubtargetFeatures> FirstTTAndFeatures = []() {
1420 assert(!InputFiles.empty() && "InputFiles can not be empty");
1421 for (auto InputFile : InputFiles) {
1422 auto ObjBuffer = ExitOnErr(getFile(FileName: InputFile));
1423 file_magic Magic = identify_magic(magic: ObjBuffer->getBuffer());
1424 switch (Magic) {
1425 case file_magic::coff_object:
1426 case file_magic::elf_relocatable:
1427 case file_magic::macho_object: {
1428 auto Obj = ExitOnErr(
1429 object::ObjectFile::createObjectFile(Object: ObjBuffer->getMemBufferRef()));
1430 Triple TT = Obj->makeTriple();
1431 if (Magic == file_magic::coff_object) {
1432 // TODO: Move this to makeTriple() if possible.
1433 TT.setObjectFormat(Triple::COFF);
1434 TT.setOS(Triple::OSType::Win32);
1435 }
1436 SubtargetFeatures Features;
1437 if (auto ObjFeatures = Obj->getFeatures())
1438 Features = std::move(*ObjFeatures);
1439 return std::make_pair(x&: TT, y&: Features);
1440 }
1441 default:
1442 break;
1443 }
1444 }
1445 return std::make_pair(x: Triple(), y: SubtargetFeatures());
1446 }();
1447
1448 return FirstTTAndFeatures;
1449}
1450
1451static Error sanitizeArguments(const Triple &TT, const char *ArgV0) {
1452
1453 // -noexec and --args should not be used together.
1454 if (NoExec && !InputArgv.empty())
1455 errs() << "Warning: --args passed to -noexec run will be ignored.\n";
1456
1457 // Set the entry point name if not specified.
1458 if (EntryPointName.empty())
1459 EntryPointName = TT.getObjectFormat() == Triple::MachO ? "_main" : "main";
1460
1461 // Disable debugger support by default in noexec tests.
1462 if (DebuggerSupport.getNumOccurrences() == 0 && NoExec)
1463 DebuggerSupport = false;
1464
1465 if (!OrcRuntime.empty() && NoProcessSymbols)
1466 return make_error<StringError>(Args: "-orc-runtime requires process symbols",
1467 Args: inconvertibleErrorCode());
1468
1469 // If -slab-allocate is passed, check that we're not trying to use it in
1470 // -oop-executor or -oop-executor-connect mode.
1471 //
1472 // FIXME: Remove once we enable remote slab allocation.
1473 if (SlabAllocateSizeString != "") {
1474 if (OutOfProcessExecutor.getNumOccurrences() ||
1475 OutOfProcessExecutorConnect.getNumOccurrences())
1476 return make_error<StringError>(
1477 Args: "-slab-allocate cannot be used with -oop-executor or "
1478 "-oop-executor-connect",
1479 Args: inconvertibleErrorCode());
1480 }
1481
1482 // If -slab-address is passed, require -slab-allocate and -noexec
1483 if (SlabAddress != ~0ULL) {
1484 if (SlabAllocateSizeString == "" || !NoExec)
1485 return make_error<StringError>(
1486 Args: "-slab-address requires -slab-allocate and -noexec",
1487 Args: inconvertibleErrorCode());
1488
1489 if (SlabPageSize == 0)
1490 errs() << "Warning: -slab-address used without -slab-page-size.\n";
1491 }
1492
1493 if (SlabPageSize != 0) {
1494 // -slab-page-size requires slab alloc.
1495 if (SlabAllocateSizeString == "")
1496 return make_error<StringError>(Args: "-slab-page-size requires -slab-allocate",
1497 Args: inconvertibleErrorCode());
1498
1499 // Check -slab-page-size / -noexec interactions.
1500 if (!NoExec) {
1501 if (auto RealPageSize = sys::Process::getPageSize()) {
1502 if (SlabPageSize % *RealPageSize)
1503 return make_error<StringError>(
1504 Args: "-slab-page-size must be a multiple of real page size for exec "
1505 "tests (did you mean to use -noexec ?)\n",
1506 Args: inconvertibleErrorCode());
1507 } else {
1508 errs() << "Could not retrieve process page size:\n";
1509 logAllUnhandledErrors(E: RealPageSize.takeError(), OS&: errs(), ErrorBanner: "");
1510 errs() << "Executing with slab page size = "
1511 << formatv(Fmt: "{0:x}", Vals&: SlabPageSize) << ".\n"
1512 << "Tool may crash if " << formatv(Fmt: "{0:x}", Vals&: SlabPageSize)
1513 << " is not a multiple of the real process page size.\n"
1514 << "(did you mean to use -noexec ?)";
1515 }
1516 }
1517 }
1518
1519 // Only one of -oop-executor and -oop-executor-connect can be used.
1520 if (!!OutOfProcessExecutor.getNumOccurrences() &&
1521 !!OutOfProcessExecutorConnect.getNumOccurrences())
1522 return make_error<StringError>(
1523 Args: "Only one of -" + OutOfProcessExecutor.ArgStr + " and -" +
1524 OutOfProcessExecutorConnect.ArgStr + " can be specified",
1525 Args: inconvertibleErrorCode());
1526
1527 // If -oop-executor was used but no value was specified then use a sensible
1528 // default.
1529 if (!!OutOfProcessExecutor.getNumOccurrences() &&
1530 OutOfProcessExecutor.empty()) {
1531 SmallString<256> OOPExecutorPath(sys::fs::getMainExecutable(
1532 argv0: ArgV0, MainExecAddr: reinterpret_cast<void *>(&sanitizeArguments)));
1533 sys::path::remove_filename(path&: OOPExecutorPath);
1534 sys::path::append(path&: OOPExecutorPath, a: "llvm-jitlink-executor");
1535 OutOfProcessExecutor = OOPExecutorPath.str().str();
1536 }
1537
1538 return Error::success();
1539}
1540
1541static void addPhonyExternalsGenerator(Session &S) {
1542 S.MainJD->addGenerator(DefGenerator: std::make_unique<PhonyExternalsGenerator>());
1543}
1544
1545static Error createJITDylibs(Session &S,
1546 std::map<unsigned, JITDylib *> &IdxToJD) {
1547 // First, set up JITDylibs.
1548 LLVM_DEBUG(dbgs() << "Creating JITDylibs...\n");
1549 {
1550 // Create a "main" JITLinkDylib.
1551 IdxToJD[0] = S.MainJD;
1552 S.JDSearchOrder.push_back(x: {S.MainJD, JITDylibLookupFlags::MatchAllSymbols});
1553 LLVM_DEBUG(dbgs() << " 0: " << S.MainJD->getName() << "\n");
1554
1555 // Add any extra JITDylibs from the command line.
1556 for (auto JDItr = JITDylibs.begin(), JDEnd = JITDylibs.end();
1557 JDItr != JDEnd; ++JDItr) {
1558 auto JD = S.ES.createJITDylib(Name: *JDItr);
1559 if (!JD)
1560 return JD.takeError();
1561 unsigned JDIdx = JITDylibs.getPosition(optnum: JDItr - JITDylibs.begin());
1562 IdxToJD[JDIdx] = &*JD;
1563 S.JDSearchOrder.push_back(x: {&*JD, JITDylibLookupFlags::MatchAllSymbols});
1564 LLVM_DEBUG(dbgs() << " " << JDIdx << ": " << JD->getName() << "\n");
1565 }
1566 }
1567
1568 if (S.PlatformJD)
1569 S.JDSearchOrder.push_back(
1570 x: {S.PlatformJD, JITDylibLookupFlags::MatchExportedSymbolsOnly});
1571 if (S.ProcessSymsJD)
1572 S.JDSearchOrder.push_back(
1573 x: {S.ProcessSymsJD, JITDylibLookupFlags::MatchExportedSymbolsOnly});
1574
1575 LLVM_DEBUG({
1576 dbgs() << "Dylib search order is [ ";
1577 for (auto &KV : S.JDSearchOrder)
1578 dbgs() << KV.first->getName() << " ";
1579 dbgs() << "]\n";
1580 });
1581
1582 return Error::success();
1583}
1584
1585static Error addAbsoluteSymbols(Session &S,
1586 const std::map<unsigned, JITDylib *> &IdxToJD) {
1587 // Define absolute symbols.
1588 LLVM_DEBUG(dbgs() << "Defining absolute symbols...\n");
1589 for (auto AbsDefItr = AbsoluteDefs.begin(), AbsDefEnd = AbsoluteDefs.end();
1590 AbsDefItr != AbsDefEnd; ++AbsDefItr) {
1591 unsigned AbsDefArgIdx =
1592 AbsoluteDefs.getPosition(optnum: AbsDefItr - AbsoluteDefs.begin());
1593 auto &JD = *std::prev(x: IdxToJD.lower_bound(x: AbsDefArgIdx))->second;
1594
1595 StringRef AbsDefStmt = *AbsDefItr;
1596 size_t EqIdx = AbsDefStmt.find_first_of(C: '=');
1597 if (EqIdx == StringRef::npos)
1598 return make_error<StringError>(Args: "Invalid absolute define \"" + AbsDefStmt +
1599 "\". Syntax: <name>=<addr>",
1600 Args: inconvertibleErrorCode());
1601 StringRef Name = AbsDefStmt.substr(Start: 0, N: EqIdx).trim();
1602 StringRef AddrStr = AbsDefStmt.substr(Start: EqIdx + 1).trim();
1603
1604 uint64_t Addr;
1605 if (AddrStr.getAsInteger(Radix: 0, Result&: Addr))
1606 return make_error<StringError>(Args: "Invalid address expression \"" + AddrStr +
1607 "\" in absolute symbol definition \"" +
1608 AbsDefStmt + "\"",
1609 Args: inconvertibleErrorCode());
1610 ExecutorSymbolDef AbsDef(ExecutorAddr(Addr), JITSymbolFlags::Exported);
1611 if (auto Err = JD.define(MU: absoluteSymbols(Symbols: {{S.ES.intern(SymName: Name), AbsDef}})))
1612 return Err;
1613
1614 // Register the absolute symbol with the session symbol infos.
1615 S.SymbolInfos[Name] = {ArrayRef<char>(), Addr,
1616 AbsDef.getFlags().getTargetFlags()};
1617 }
1618
1619 return Error::success();
1620}
1621
1622static Error addAliases(Session &S,
1623 const std::map<unsigned, JITDylib *> &IdxToJD) {
1624 // Define absolute symbols.
1625 LLVM_DEBUG(dbgs() << "Defining aliases...\n");
1626
1627 DenseMap<std::pair<JITDylib *, JITDylib *>, SymbolAliasMap> Reexports;
1628 for (auto AliasItr = Aliases.begin(), AliasEnd = Aliases.end();
1629 AliasItr != AliasEnd; ++AliasItr) {
1630
1631 auto BadExpr = [&]() {
1632 return make_error<StringError>(
1633 Args: "Invalid alias definition \"" + *AliasItr +
1634 "\". Syntax: [<dst-jd>:]<alias>=[<src-jd>:]<aliasee>",
1635 Args: inconvertibleErrorCode());
1636 };
1637
1638 auto GetJD = [&](StringRef JDName) -> Expected<JITDylib *> {
1639 if (JDName.empty()) {
1640 unsigned AliasArgIdx = Aliases.getPosition(optnum: AliasItr - Aliases.begin());
1641 return std::prev(x: IdxToJD.lower_bound(x: AliasArgIdx))->second;
1642 }
1643
1644 auto *JD = S.ES.getJITDylibByName(Name: JDName);
1645 if (!JD)
1646 return make_error<StringError>(Args: StringRef("In alias definition \"") +
1647 *AliasItr + "\" no dylib named " +
1648 JDName,
1649 Args: inconvertibleErrorCode());
1650
1651 return JD;
1652 };
1653
1654 {
1655 // First split on '=' to get alias and aliasee.
1656 StringRef AliasStmt = *AliasItr;
1657 auto [AliasExpr, AliaseeExpr] = AliasStmt.split(Separator: '=');
1658 if (AliaseeExpr.empty())
1659 return BadExpr();
1660
1661 auto [AliasJDName, Alias] = AliasExpr.split(Separator: ':');
1662 if (Alias.empty())
1663 std::swap(a&: AliasJDName, b&: Alias);
1664
1665 auto AliasJD = GetJD(AliasJDName);
1666 if (!AliasJD)
1667 return AliasJD.takeError();
1668
1669 auto [AliaseeJDName, Aliasee] = AliaseeExpr.split(Separator: ':');
1670 if (Aliasee.empty())
1671 std::swap(a&: AliaseeJDName, b&: Aliasee);
1672
1673 if (AliaseeJDName.empty() && !AliasJDName.empty())
1674 AliaseeJDName = AliasJDName;
1675 auto AliaseeJD = GetJD(AliaseeJDName);
1676 if (!AliaseeJD)
1677 return AliaseeJD.takeError();
1678
1679 Reexports[{*AliasJD, *AliaseeJD}][S.ES.intern(SymName: Alias)] = {
1680 S.ES.intern(SymName: Aliasee), JITSymbolFlags::Exported};
1681 }
1682 }
1683
1684 for (auto &[JDs, AliasMap] : Reexports) {
1685 auto [DstJD, SrcJD] = JDs;
1686 if (auto Err = DstJD->define(MU: reexports(SourceJD&: *SrcJD, Aliases: std::move(AliasMap))))
1687 return Err;
1688 }
1689
1690 return Error::success();
1691}
1692
1693static Error addSectCreates(Session &S,
1694 const std::map<unsigned, JITDylib *> &IdxToJD) {
1695 for (auto SCItr = SectCreate.begin(), SCEnd = SectCreate.end();
1696 SCItr != SCEnd; ++SCItr) {
1697
1698 unsigned SCArgIdx = SectCreate.getPosition(optnum: SCItr - SectCreate.begin());
1699 auto &JD = *std::prev(x: IdxToJD.lower_bound(x: SCArgIdx))->second;
1700
1701 StringRef SCArg(*SCItr);
1702
1703 auto [SectAndFileName, ExtraSymbolsString] = SCArg.split(Separator: '@');
1704 auto [SectName, FileName] = SectAndFileName.rsplit(Separator: ',');
1705 if (SectName.empty())
1706 return make_error<StringError>(Args: "In -sectcreate=" + SCArg +
1707 ", filename component cannot be empty",
1708 Args: inconvertibleErrorCode());
1709 if (FileName.empty())
1710 return make_error<StringError>(Args: "In -sectcreate=" + SCArg +
1711 ", filename component cannot be empty",
1712 Args: inconvertibleErrorCode());
1713
1714 auto Content = MemoryBuffer::getFile(Filename: FileName);
1715 if (!Content)
1716 return createFileError(F: FileName, E: errorCodeToError(EC: Content.getError()));
1717
1718 SectCreateMaterializationUnit::ExtraSymbolsMap ExtraSymbols;
1719 while (!ExtraSymbolsString.empty()) {
1720 StringRef NextSymPair;
1721 std::tie(args&: NextSymPair, args&: ExtraSymbolsString) = ExtraSymbolsString.split(Separator: ',');
1722
1723 auto [Sym, OffsetString] = NextSymPair.split(Separator: '=');
1724 size_t Offset;
1725
1726 if (OffsetString.getAsInteger(Radix: 0, Result&: Offset))
1727 return make_error<StringError>(Args: "In -sectcreate=" + SCArg + ", " +
1728 OffsetString +
1729 " is not a valid integer",
1730 Args: inconvertibleErrorCode());
1731
1732 ExtraSymbols[S.ES.intern(SymName: Sym)] = {.Flags: JITSymbolFlags::Exported, .Offset: Offset};
1733 }
1734
1735 if (auto Err = JD.define(MU: std::make_unique<SectCreateMaterializationUnit>(
1736 args&: S.ObjLayer, args: SectName.str(), args: MemProt::Read, args: 16, args: std::move(*Content),
1737 args: std::move(ExtraSymbols))))
1738 return Err;
1739 }
1740
1741 return Error::success();
1742}
1743
1744static Error addTestHarnesses(Session &S) {
1745 LLVM_DEBUG(dbgs() << "Adding test harness objects...\n");
1746 for (auto HarnessFile : TestHarnesses) {
1747 LLVM_DEBUG(dbgs() << " " << HarnessFile << "\n");
1748 auto ObjBuffer = getFile(FileName: HarnessFile);
1749 if (!ObjBuffer)
1750 return ObjBuffer.takeError();
1751 if (auto Err = S.ObjLayer.add(JD&: *S.MainJD, O: std::move(*ObjBuffer)))
1752 return Err;
1753 }
1754 return Error::success();
1755}
1756
1757static Error addObjects(Session &S,
1758 const std::map<unsigned, JITDylib *> &IdxToJD) {
1759
1760 // Load each object into the corresponding JITDylib..
1761 LLVM_DEBUG(dbgs() << "Adding objects...\n");
1762 for (auto InputFileItr = InputFiles.begin(), InputFileEnd = InputFiles.end();
1763 InputFileItr != InputFileEnd; ++InputFileItr) {
1764 unsigned InputFileArgIdx =
1765 InputFiles.getPosition(optnum: InputFileItr - InputFiles.begin());
1766 const std::string &InputFile = *InputFileItr;
1767 if (StringRef(InputFile).ends_with(Suffix: ".a") ||
1768 StringRef(InputFile).ends_with(Suffix: ".lib"))
1769 continue;
1770 auto &JD = *std::prev(x: IdxToJD.lower_bound(x: InputFileArgIdx))->second;
1771 LLVM_DEBUG(dbgs() << " " << InputFileArgIdx << ": \"" << InputFile
1772 << "\" to " << JD.getName() << "\n";);
1773 auto ObjBuffer = getFile(FileName: InputFile);
1774 if (!ObjBuffer)
1775 return ObjBuffer.takeError();
1776
1777 if (S.HarnessFiles.empty()) {
1778 if (auto Err = S.ObjLayer.add(JD, O: std::move(*ObjBuffer)))
1779 return Err;
1780 } else {
1781 // We're in -harness mode. Use a custom interface for this
1782 // test object.
1783 auto ObjInterface =
1784 getTestObjectFileInterface(S, O: (*ObjBuffer)->getMemBufferRef());
1785 if (!ObjInterface)
1786 return ObjInterface.takeError();
1787 if (auto Err = S.ObjLayer.add(JD, O: std::move(*ObjBuffer),
1788 I: std::move(*ObjInterface)))
1789 return Err;
1790 }
1791 }
1792
1793 return Error::success();
1794}
1795
1796static Expected<MaterializationUnit::Interface>
1797getObjectFileInterfaceHidden(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
1798 auto I = getObjectFileInterface(ES, ObjBuffer);
1799 if (I) {
1800 for (auto &KV : I->SymbolFlags)
1801 KV.second &= ~JITSymbolFlags::Exported;
1802 }
1803 return I;
1804}
1805
1806static SmallVector<StringRef, 5> getSearchPathsFromEnvVar(Session &S) {
1807 // FIXME: Handle EPC environment.
1808 SmallVector<StringRef, 5> PathVec;
1809 auto TT = S.ES.getTargetTriple();
1810 if (TT.isOSBinFormatCOFF())
1811 StringRef(getenv(name: "PATH")).split(A&: PathVec, Separator: ";");
1812 else if (TT.isOSBinFormatELF())
1813 StringRef(getenv(name: "LD_LIBRARY_PATH")).split(A&: PathVec, Separator: ":");
1814
1815 return PathVec;
1816}
1817
1818static Error addLibraries(Session &S,
1819 const std::map<unsigned, JITDylib *> &IdxToJD) {
1820
1821 // 1. Collect search paths for each JITDylib.
1822 DenseMap<const JITDylib *, SmallVector<StringRef, 2>> JDSearchPaths;
1823
1824 for (auto LSPItr = LibrarySearchPaths.begin(),
1825 LSPEnd = LibrarySearchPaths.end();
1826 LSPItr != LSPEnd; ++LSPItr) {
1827 unsigned LibrarySearchPathIdx =
1828 LibrarySearchPaths.getPosition(optnum: LSPItr - LibrarySearchPaths.begin());
1829 auto &JD = *std::prev(x: IdxToJD.lower_bound(x: LibrarySearchPathIdx))->second;
1830
1831 StringRef LibrarySearchPath = *LSPItr;
1832 if (sys::fs::get_file_type(Path: LibrarySearchPath) !=
1833 sys::fs::file_type::directory_file)
1834 return make_error<StringError>(Args: "While linking " + JD.getName() + ", -L" +
1835 LibrarySearchPath +
1836 " does not point to a directory",
1837 Args: inconvertibleErrorCode());
1838
1839 JDSearchPaths[&JD].push_back(Elt: *LSPItr);
1840 }
1841
1842 LLVM_DEBUG({
1843 if (!JDSearchPaths.empty())
1844 dbgs() << "Search paths:\n";
1845 for (auto &KV : JDSearchPaths) {
1846 dbgs() << " " << KV.first->getName() << ": [";
1847 for (auto &LibSearchPath : KV.second)
1848 dbgs() << " \"" << LibSearchPath << "\"";
1849 dbgs() << " ]\n";
1850 }
1851 });
1852
1853 // 2. Collect library loads
1854 struct LibraryLoad {
1855 std::string LibName;
1856 bool IsPath = false;
1857 unsigned Position;
1858 StringRef *CandidateExtensions;
1859 enum { Standard, Hidden } Modifier;
1860 };
1861
1862 // Queue to load library as in the order as it appears in the argument list.
1863 std::deque<LibraryLoad> LibraryLoadQueue;
1864 // Add archive files from the inputs to LibraryLoads.
1865 for (auto InputFileItr = InputFiles.begin(), InputFileEnd = InputFiles.end();
1866 InputFileItr != InputFileEnd; ++InputFileItr) {
1867 StringRef InputFile = *InputFileItr;
1868 if (!InputFile.ends_with(Suffix: ".a") && !InputFile.ends_with(Suffix: ".lib"))
1869 continue;
1870 LibraryLoad LL;
1871 LL.LibName = InputFile.str();
1872 LL.IsPath = true;
1873 LL.Position = InputFiles.getPosition(optnum: InputFileItr - InputFiles.begin());
1874 LL.CandidateExtensions = nullptr;
1875 LL.Modifier = LibraryLoad::Standard;
1876 LibraryLoadQueue.push_back(x: std::move(LL));
1877 }
1878
1879 // Add -load_hidden arguments to LibraryLoads.
1880 for (auto LibItr = LoadHidden.begin(), LibEnd = LoadHidden.end();
1881 LibItr != LibEnd; ++LibItr) {
1882 LibraryLoad LL;
1883 LL.LibName = *LibItr;
1884 LL.IsPath = true;
1885 LL.Position = LoadHidden.getPosition(optnum: LibItr - LoadHidden.begin());
1886 LL.CandidateExtensions = nullptr;
1887 LL.Modifier = LibraryLoad::Hidden;
1888 LibraryLoadQueue.push_back(x: std::move(LL));
1889 }
1890 StringRef StandardExtensions[] = {".so", ".dylib", ".dll", ".a", ".lib"};
1891 StringRef DynLibExtensionsOnly[] = {".so", ".dylib", ".dll"};
1892 StringRef ArchiveExtensionsOnly[] = {".a", ".lib"};
1893
1894 // Add -lx arguments to LibraryLoads.
1895 for (auto LibItr = Libraries.begin(), LibEnd = Libraries.end();
1896 LibItr != LibEnd; ++LibItr) {
1897 LibraryLoad LL;
1898 LL.LibName = *LibItr;
1899 LL.Position = Libraries.getPosition(optnum: LibItr - Libraries.begin());
1900 LL.CandidateExtensions = StandardExtensions;
1901 LL.Modifier = LibraryLoad::Standard;
1902 LibraryLoadQueue.push_back(x: std::move(LL));
1903 }
1904
1905 // Add -hidden-lx arguments to LibraryLoads.
1906 for (auto LibHiddenItr = LibrariesHidden.begin(),
1907 LibHiddenEnd = LibrariesHidden.end();
1908 LibHiddenItr != LibHiddenEnd; ++LibHiddenItr) {
1909 LibraryLoad LL;
1910 LL.LibName = *LibHiddenItr;
1911 LL.Position =
1912 LibrariesHidden.getPosition(optnum: LibHiddenItr - LibrariesHidden.begin());
1913 LL.CandidateExtensions = ArchiveExtensionsOnly;
1914 LL.Modifier = LibraryLoad::Hidden;
1915 LibraryLoadQueue.push_back(x: std::move(LL));
1916 }
1917
1918 // If there are any load-<modified> options then turn on flag overrides
1919 // to avoid flag mismatch errors.
1920 if (!LibrariesHidden.empty() || !LoadHidden.empty())
1921 S.ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true);
1922
1923 // Sort library loads by position in the argument list.
1924 llvm::sort(C&: LibraryLoadQueue,
1925 Comp: [](const LibraryLoad &LHS, const LibraryLoad &RHS) {
1926 return LHS.Position < RHS.Position;
1927 });
1928
1929 // 3. Process library loads.
1930 auto AddArchive = [&](const char *Path, const LibraryLoad &LL)
1931 -> Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> {
1932 unique_function<Expected<MaterializationUnit::Interface>(
1933 ExecutionSession & ES, MemoryBufferRef ObjBuffer)>
1934 GetObjFileInterface;
1935 switch (LL.Modifier) {
1936 case LibraryLoad::Standard:
1937 GetObjFileInterface = getObjectFileInterface;
1938 break;
1939 case LibraryLoad::Hidden:
1940 GetObjFileInterface = getObjectFileInterfaceHidden;
1941 break;
1942 }
1943 auto G = StaticLibraryDefinitionGenerator::Load(
1944 L&: S.ObjLayer, FileName: Path, GetObjFileInterface: std::move(GetObjFileInterface));
1945 if (!G)
1946 return G.takeError();
1947
1948 // Push additional dynamic libraries to search.
1949 // Note that this mechanism only happens in COFF.
1950 for (auto FileName : (*G)->getImportedDynamicLibraries()) {
1951 LibraryLoad NewLL;
1952 auto FileNameRef = StringRef(FileName);
1953 if (!FileNameRef.ends_with_insensitive(Suffix: ".dll"))
1954 return make_error<StringError>(
1955 Args: "COFF Imported library not ending with dll extension?",
1956 Args: inconvertibleErrorCode());
1957 NewLL.LibName = FileNameRef.drop_back(N: strlen(s: ".dll")).str();
1958 NewLL.Position = LL.Position;
1959 NewLL.CandidateExtensions = DynLibExtensionsOnly;
1960 NewLL.Modifier = LibraryLoad::Standard;
1961 LibraryLoadQueue.push_front(x: std::move(NewLL));
1962 }
1963 return G;
1964 };
1965
1966 SmallVector<StringRef, 5> SystemSearchPaths;
1967 if (SearchSystemLibrary.getValue())
1968 SystemSearchPaths = getSearchPathsFromEnvVar(S);
1969 while (!LibraryLoadQueue.empty()) {
1970 bool LibFound = false;
1971 auto LL = LibraryLoadQueue.front();
1972 LibraryLoadQueue.pop_front();
1973 auto &JD = *std::prev(x: IdxToJD.lower_bound(x: LL.Position))->second;
1974
1975 // If this is the name of a JITDylib then link against that.
1976 if (auto *LJD = S.ES.getJITDylibByName(Name: LL.LibName)) {
1977 JD.addToLinkOrder(JD&: *LJD);
1978 continue;
1979 }
1980
1981 if (LL.IsPath) {
1982 auto G = AddArchive(LL.LibName.c_str(), LL);
1983 if (!G)
1984 return createFileError(F: LL.LibName, E: G.takeError());
1985 JD.addGenerator(DefGenerator: std::move(*G));
1986 LLVM_DEBUG({
1987 dbgs() << "Adding generator for static library " << LL.LibName << " to "
1988 << JD.getName() << "\n";
1989 });
1990 continue;
1991 }
1992
1993 // Otherwise look through the search paths.
1994 auto CurJDSearchPaths = JDSearchPaths[&JD];
1995 for (StringRef SearchPath :
1996 concat<StringRef>(Ranges&: CurJDSearchPaths, Ranges&: SystemSearchPaths)) {
1997 for (const char *LibExt : {".dylib", ".so", ".dll", ".a", ".lib"}) {
1998 SmallVector<char, 256> LibPath;
1999 LibPath.reserve(N: SearchPath.size() + strlen(s: "lib") + LL.LibName.size() +
2000 strlen(s: LibExt) + 2); // +2 for pathsep, null term.
2001 llvm::copy(Range&: SearchPath, Out: std::back_inserter(x&: LibPath));
2002 if (StringRef(LibExt) != ".lib" && StringRef(LibExt) != ".dll")
2003 sys::path::append(path&: LibPath, a: "lib" + LL.LibName + LibExt);
2004 else
2005 sys::path::append(path&: LibPath, a: LL.LibName + LibExt);
2006 LibPath.push_back(Elt: '\0');
2007
2008 // Skip missing or non-regular paths.
2009 if (sys::fs::get_file_type(Path: LibPath.data()) !=
2010 sys::fs::file_type::regular_file) {
2011 continue;
2012 }
2013
2014 file_magic Magic;
2015 if (auto EC = identify_magic(path: LibPath, result&: Magic)) {
2016 // If there was an error loading the file then skip it.
2017 LLVM_DEBUG({
2018 dbgs() << "Library search found \"" << LibPath
2019 << "\", but could not identify file type (" << EC.message()
2020 << "). Skipping.\n";
2021 });
2022 continue;
2023 }
2024
2025 // We identified the magic. Assume that we can load it -- we'll reset
2026 // in the default case.
2027 LibFound = true;
2028 switch (Magic) {
2029 case file_magic::pecoff_executable:
2030 case file_magic::elf_shared_object:
2031 case file_magic::macho_dynamically_linked_shared_lib: {
2032 if (auto Err = S.loadAndLinkDynamicLibrary(JD, LibPath: LibPath.data()))
2033 return Err;
2034 break;
2035 }
2036 case file_magic::archive:
2037 case file_magic::macho_universal_binary: {
2038 auto G = AddArchive(LibPath.data(), LL);
2039 if (!G)
2040 return G.takeError();
2041 JD.addGenerator(DefGenerator: std::move(*G));
2042 LLVM_DEBUG({
2043 dbgs() << "Adding generator for static library " << LibPath.data()
2044 << " to " << JD.getName() << "\n";
2045 });
2046 break;
2047 }
2048 default:
2049 // This file isn't a recognized library kind.
2050 LLVM_DEBUG({
2051 dbgs() << "Library search found \"" << LibPath
2052 << "\", but file type is not supported. Skipping.\n";
2053 });
2054 LibFound = false;
2055 break;
2056 }
2057 if (LibFound)
2058 break;
2059 }
2060 if (LibFound)
2061 break;
2062 }
2063
2064 if (!LibFound)
2065 return make_error<StringError>(Args: "While linking " + JD.getName() +
2066 ", could not find library for -l" +
2067 LL.LibName,
2068 Args: inconvertibleErrorCode());
2069 }
2070
2071 // Add platform and process symbols if available.
2072 for (auto &[Idx, JD] : IdxToJD) {
2073 if (S.PlatformJD)
2074 JD->addToLinkOrder(JD&: *S.PlatformJD);
2075 if (S.ProcessSymsJD)
2076 JD->addToLinkOrder(JD&: *S.ProcessSymsJD);
2077 }
2078
2079 return Error::success();
2080}
2081
2082static Error addSessionInputs(Session &S) {
2083 std::map<unsigned, JITDylib *> IdxToJD;
2084
2085 if (auto Err = createJITDylibs(S, IdxToJD))
2086 return Err;
2087
2088 if (auto Err = addAbsoluteSymbols(S, IdxToJD))
2089 return Err;
2090
2091 if (auto Err = addAliases(S, IdxToJD))
2092 return Err;
2093
2094 if (auto Err = addSectCreates(S, IdxToJD))
2095 return Err;
2096
2097 if (!TestHarnesses.empty())
2098 if (auto Err = addTestHarnesses(S))
2099 return Err;
2100
2101 if (auto Err = addObjects(S, IdxToJD))
2102 return Err;
2103
2104 if (auto Err = addLibraries(S, IdxToJD))
2105 return Err;
2106
2107 return Error::success();
2108}
2109
2110namespace {
2111struct TargetInfo {
2112 const Target *TheTarget;
2113 std::unique_ptr<MCSubtargetInfo> STI;
2114 std::unique_ptr<MCRegisterInfo> MRI;
2115 std::unique_ptr<MCAsmInfo> MAI;
2116 std::unique_ptr<MCContext> Ctx;
2117 std::unique_ptr<MCDisassembler> Disassembler;
2118 std::unique_ptr<MCInstrInfo> MII;
2119 std::unique_ptr<MCInstrAnalysis> MIA;
2120 std::unique_ptr<MCInstPrinter> InstPrinter;
2121};
2122} // anonymous namespace
2123
2124static TargetInfo
2125getTargetInfo(const Triple &TT,
2126 const SubtargetFeatures &TF = SubtargetFeatures()) {
2127 auto TripleName = TT.str();
2128 std::string ErrorStr;
2129 const Target *TheTarget = TargetRegistry::lookupTarget(Triple: TripleName, Error&: ErrorStr);
2130 if (!TheTarget)
2131 ExitOnErr(make_error<StringError>(Args: "Error accessing target '" + TripleName +
2132 "': " + ErrorStr,
2133 Args: inconvertibleErrorCode()));
2134
2135 std::unique_ptr<MCSubtargetInfo> STI(
2136 TheTarget->createMCSubtargetInfo(TheTriple: TripleName, CPU: "", Features: TF.getString()));
2137 if (!STI)
2138 ExitOnErr(
2139 make_error<StringError>(Args: "Unable to create subtarget for " + TripleName,
2140 Args: inconvertibleErrorCode()));
2141
2142 std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT: TripleName));
2143 if (!MRI)
2144 ExitOnErr(make_error<StringError>(Args: "Unable to create target register info "
2145 "for " +
2146 TripleName,
2147 Args: inconvertibleErrorCode()));
2148
2149 MCTargetOptions MCOptions;
2150 std::unique_ptr<MCAsmInfo> MAI(
2151 TheTarget->createMCAsmInfo(MRI: *MRI, TheTriple: TripleName, Options: MCOptions));
2152 if (!MAI)
2153 ExitOnErr(make_error<StringError>(Args: "Unable to create target asm info " +
2154 TripleName,
2155 Args: inconvertibleErrorCode()));
2156
2157 auto Ctx = std::make_unique<MCContext>(args: Triple(TripleName), args: MAI.get(),
2158 args: MRI.get(), args: STI.get());
2159
2160 std::unique_ptr<MCDisassembler> Disassembler(
2161 TheTarget->createMCDisassembler(STI: *STI, Ctx&: *Ctx));
2162 if (!Disassembler)
2163 ExitOnErr(make_error<StringError>(Args: "Unable to create disassembler for " +
2164 TripleName,
2165 Args: inconvertibleErrorCode()));
2166
2167 std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
2168 if (!MII)
2169 ExitOnErr(make_error<StringError>(Args: "Unable to create instruction info for" +
2170 TripleName,
2171 Args: inconvertibleErrorCode()));
2172
2173 std::unique_ptr<MCInstrAnalysis> MIA(
2174 TheTarget->createMCInstrAnalysis(Info: MII.get()));
2175 if (!MIA)
2176 ExitOnErr(make_error<StringError>(
2177 Args: "Unable to create instruction analysis for" + TripleName,
2178 Args: inconvertibleErrorCode()));
2179
2180 std::unique_ptr<MCInstPrinter> InstPrinter(
2181 TheTarget->createMCInstPrinter(T: Triple(TripleName), SyntaxVariant: 0, MAI: *MAI, MII: *MII, MRI: *MRI));
2182 if (!InstPrinter)
2183 ExitOnErr(make_error<StringError>(
2184 Args: "Unable to create instruction printer for" + TripleName,
2185 Args: inconvertibleErrorCode()));
2186 return {.TheTarget: TheTarget, .STI: std::move(STI), .MRI: std::move(MRI),
2187 .MAI: std::move(MAI), .Ctx: std::move(Ctx), .Disassembler: std::move(Disassembler),
2188 .MII: std::move(MII), .MIA: std::move(MIA), .InstPrinter: std::move(InstPrinter)};
2189}
2190static Error runChecks(Session &S, Triple TT, SubtargetFeatures Features) {
2191 if (CheckFiles.empty())
2192 return Error::success();
2193
2194 LLVM_DEBUG(dbgs() << "Running checks...\n");
2195
2196 auto IsSymbolValid = [&S](StringRef Symbol) {
2197 return S.isSymbolRegistered(SymbolName: Symbol);
2198 };
2199
2200 auto GetSymbolInfo = [&S](StringRef Symbol) {
2201 return S.findSymbolInfo(SymbolName: Symbol, ErrorMsgStem: "Can not get symbol info");
2202 };
2203
2204 auto GetSectionInfo = [&S](StringRef FileName, StringRef SectionName) {
2205 return S.findSectionInfo(FileName, SectionName);
2206 };
2207
2208 auto GetStubInfo = [&S](StringRef FileName, StringRef SectionName,
2209 StringRef KindNameFilter) {
2210 return S.findStubInfo(FileName, TargetName: SectionName, KindNameFilter);
2211 };
2212
2213 auto GetGOTInfo = [&S](StringRef FileName, StringRef SectionName) {
2214 return S.findGOTEntryInfo(FileName, TargetName: SectionName);
2215 };
2216
2217 RuntimeDyldChecker Checker(
2218 IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo, GetGOTInfo,
2219 S.ES.getTargetTriple().isLittleEndian() ? llvm::endianness::little
2220 : llvm::endianness::big,
2221 TT, StringRef(), Features, dbgs());
2222
2223 std::string CheckLineStart = "# " + CheckName + ":";
2224 for (auto &CheckFile : CheckFiles) {
2225 auto CheckerFileBuf = ExitOnErr(getFile(FileName: CheckFile));
2226 if (!Checker.checkAllRulesInBuffer(RulePrefix: CheckLineStart, MemBuf: &*CheckerFileBuf))
2227 ExitOnErr(make_error<StringError>(
2228 Args: "Some checks in " + CheckFile + " failed", Args: inconvertibleErrorCode()));
2229 }
2230
2231 return Error::success();
2232}
2233
2234static Error addSelfRelocations(LinkGraph &G) {
2235 auto TI = getTargetInfo(TT: G.getTargetTriple());
2236 for (auto *Sym : G.defined_symbols())
2237 if (Sym->isCallable())
2238 if (auto Err = addFunctionPointerRelocationsToCurrentSymbol(
2239 Sym&: *Sym, G, Disassembler&: *TI.Disassembler, MIA&: *TI.MIA))
2240 return Err;
2241 return Error::success();
2242}
2243
2244static Expected<ExecutorSymbolDef> getMainEntryPoint(Session &S) {
2245 return S.ES.lookup(SearchOrder: S.JDSearchOrder, Symbol: S.ES.intern(SymName: EntryPointName));
2246}
2247
2248static Expected<ExecutorSymbolDef> getOrcRuntimeEntryPoint(Session &S) {
2249 std::string RuntimeEntryPoint = "__orc_rt_run_program_wrapper";
2250 if (S.ES.getTargetTriple().getObjectFormat() == Triple::MachO)
2251 RuntimeEntryPoint = '_' + RuntimeEntryPoint;
2252 return S.ES.lookup(SearchOrder: S.JDSearchOrder, Symbol: S.ES.intern(SymName: RuntimeEntryPoint));
2253}
2254
2255static Expected<ExecutorSymbolDef> getEntryPoint(Session &S) {
2256 ExecutorSymbolDef EntryPoint;
2257
2258 // Find the entry-point function unconditionally, since we want to force
2259 // it to be materialized to collect stats.
2260 if (auto EP = getMainEntryPoint(S))
2261 EntryPoint = *EP;
2262 else
2263 return EP.takeError();
2264 LLVM_DEBUG({
2265 dbgs() << "Using entry point \"" << EntryPointName
2266 << "\": " << formatv("{0:x16}", EntryPoint.getAddress()) << "\n";
2267 });
2268
2269 // If we're running with the ORC runtime then replace the entry-point
2270 // with the __orc_rt_run_program symbol.
2271 if (!OrcRuntime.empty()) {
2272 if (auto EP = getOrcRuntimeEntryPoint(S))
2273 EntryPoint = *EP;
2274 else
2275 return EP.takeError();
2276 LLVM_DEBUG({
2277 dbgs() << "(called via __orc_rt_run_program_wrapper at "
2278 << formatv("{0:x16}", EntryPoint.getAddress()) << ")\n";
2279 });
2280 }
2281
2282 return EntryPoint;
2283}
2284
2285static Expected<int> runWithRuntime(Session &S, ExecutorAddr EntryPointAddr) {
2286 StringRef DemangledEntryPoint = EntryPointName;
2287 if (S.ES.getTargetTriple().getObjectFormat() == Triple::MachO &&
2288 DemangledEntryPoint.front() == '_')
2289 DemangledEntryPoint = DemangledEntryPoint.drop_front();
2290 using llvm::orc::shared::SPSString;
2291 using SPSRunProgramSig =
2292 int64_t(SPSString, SPSString, shared::SPSSequence<SPSString>);
2293 int64_t Result;
2294 if (auto Err = S.ES.callSPSWrapper<SPSRunProgramSig>(
2295 WrapperFnAddr: EntryPointAddr, WrapperCallArgs&: Result, WrapperCallArgs: S.MainJD->getName(), WrapperCallArgs&: DemangledEntryPoint,
2296 WrapperCallArgs&: static_cast<std::vector<std::string> &>(InputArgv)))
2297 return std::move(Err);
2298 return Result;
2299}
2300
2301static Expected<int> runWithoutRuntime(Session &S,
2302 ExecutorAddr EntryPointAddr) {
2303 return S.ES.getExecutorProcessControl().runAsMain(MainFnAddr: EntryPointAddr, Args: InputArgv);
2304}
2305
2306namespace {
2307struct JITLinkTimers {
2308 TimerGroup JITLinkTG{"llvm-jitlink timers", "timers for llvm-jitlink phases"};
2309 Timer LoadObjectsTimer{"load", "time to load/add object files", JITLinkTG};
2310 Timer LinkTimer{"link", "time to link object files", JITLinkTG};
2311 Timer RunTimer{"run", "time to execute jitlink'd code", JITLinkTG};
2312};
2313} // namespace
2314
2315int main(int argc, char *argv[]) {
2316 InitLLVM X(argc, argv);
2317
2318 InitializeAllTargetInfos();
2319 InitializeAllTargetMCs();
2320 InitializeAllDisassemblers();
2321
2322 cl::HideUnrelatedOptions(Categories: {&JITLinkCategory, &getColorCategory()});
2323 cl::ParseCommandLineOptions(argc, argv, Overview: "llvm jitlink tool");
2324 ExitOnErr.setBanner(std::string(argv[0]) + ": ");
2325
2326 /// If timers are enabled, create a JITLinkTimers instance.
2327 std::unique_ptr<JITLinkTimers> Timers =
2328 ShowTimes ? std::make_unique<JITLinkTimers>() : nullptr;
2329
2330 auto [TT, Features] = getFirstFileTripleAndFeatures();
2331 ExitOnErr(sanitizeArguments(TT, ArgV0: argv[0]));
2332
2333 auto S = ExitOnErr(Session::Create(TT, Features));
2334
2335 enableStatistics(S&: *S, UsingOrcRuntime: !OrcRuntime.empty());
2336
2337 {
2338 TimeRegion TR(Timers ? &Timers->LoadObjectsTimer : nullptr);
2339 ExitOnErr(addSessionInputs(S&: *S));
2340 }
2341
2342 if (PhonyExternals)
2343 addPhonyExternalsGenerator(S&: *S);
2344
2345 if (ShowInitialExecutionSessionState)
2346 S->ES.dump(OS&: outs());
2347
2348 Expected<ExecutorSymbolDef> EntryPoint((ExecutorSymbolDef()));
2349 {
2350 ExpectedAsOutParameter<ExecutorSymbolDef> _(&EntryPoint);
2351 TimeRegion TR(Timers ? &Timers->LinkTimer : nullptr);
2352 EntryPoint = getEntryPoint(S&: *S);
2353 }
2354
2355 // Print any reports regardless of whether we succeeded or failed.
2356 if (ShowEntryExecutionSessionState)
2357 S->ES.dump(OS&: outs());
2358
2359 if (ShowAddrs)
2360 S->dumpSessionInfo(OS&: outs());
2361
2362 if (!EntryPoint) {
2363 if (Timers)
2364 Timers->JITLinkTG.printAll(OS&: errs());
2365 reportLLVMJITLinkError(Err: EntryPoint.takeError());
2366 exit(status: 1);
2367 }
2368
2369 ExitOnErr(runChecks(S&: *S, TT: std::move(TT), Features: std::move(Features)));
2370
2371 int Result = 0;
2372 if (!NoExec) {
2373 LLVM_DEBUG(dbgs() << "Running \"" << EntryPointName << "\"...\n");
2374 TimeRegion TR(Timers ? &Timers->RunTimer : nullptr);
2375 if (!OrcRuntime.empty())
2376 Result =
2377 ExitOnErr(runWithRuntime(S&: *S, EntryPointAddr: ExecutorAddr(EntryPoint->getAddress())));
2378 else
2379 Result = ExitOnErr(
2380 runWithoutRuntime(S&: *S, EntryPointAddr: ExecutorAddr(EntryPoint->getAddress())));
2381 }
2382
2383 // Destroy the session.
2384 ExitOnErr(S->ES.endSession());
2385 S.reset();
2386
2387 if (Timers)
2388 Timers->JITLinkTG.printAll(OS&: errs());
2389
2390 // If the executing code set a test result override then use that.
2391 if (UseTestResultOverride)
2392 Result = TestResultOverride;
2393
2394 return Result;
2395}
2396

source code of llvm/tools/llvm-jitlink/llvm-jitlink.cpp