1 //===- llvm-jitlink.cpp -- Command line interface/tester for llvm-jitlink -===//
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
7 //===----------------------------------------------------------------------===//
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.
13 //===----------------------------------------------------------------------===//
15 #include "llvm-jitlink.h"
17 #include "llvm/BinaryFormat/Magic.h"
18 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
19 #include "llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h"
20 #include "llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h"
21 #include "llvm/MC/MCAsmInfo.h"
22 #include "llvm/MC/MCContext.h"
23 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
24 #include "llvm/MC/MCInstPrinter.h"
25 #include "llvm/MC/MCInstrInfo.h"
26 #include "llvm/MC/MCRegisterInfo.h"
27 #include "llvm/MC/MCSubtargetInfo.h"
28 #include "llvm/MC/MCTargetOptions.h"
29 #include "llvm/Object/COFF.h"
30 #include "llvm/Object/MachO.h"
31 #include "llvm/Object/ObjectFile.h"
32 #include "llvm/Support/CommandLine.h"
33 #include "llvm/Support/Debug.h"
34 #include "llvm/Support/InitLLVM.h"
35 #include "llvm/Support/MemoryBuffer.h"
36 #include "llvm/Support/Process.h"
37 #include "llvm/Support/TargetRegistry.h"
38 #include "llvm/Support/TargetSelect.h"
39 #include "llvm/Support/Timer.h"
46 #include <netinet/in.h>
47 #include <sys/socket.h>
49 #endif // LLVM_ON_UNIX
51 #define DEBUG_TYPE "llvm_jitlink"
54 using namespace llvm::jitlink
;
55 using namespace llvm::orc
;
57 static cl::list
<std::string
> InputFiles(cl::Positional
, cl::OneOrMore
,
58 cl::desc("input files"));
60 static cl::opt
<bool> NoExec("noexec", cl::desc("Do not execute loaded code"),
63 static cl::list
<std::string
>
64 CheckFiles("check", cl::desc("File containing verifier checks"),
67 static cl::opt
<std::string
>
68 CheckName("check-name", cl::desc("Name of checks to match against"),
69 cl::init("jitlink-check"));
71 static cl::opt
<std::string
>
72 EntryPointName("entry", cl::desc("Symbol to call as main entry point"),
75 static cl::list
<std::string
> JITLinkDylibs(
76 "jld", cl::desc("Specifies the JITDylib to be used for any subsequent "
77 "input file arguments"));
79 static cl::list
<std::string
>
80 Dylibs("dlopen", cl::desc("Dynamic libraries to load before linking"),
83 static cl::list
<std::string
> InputArgv("args", cl::Positional
,
84 cl::desc("<program arguments>..."),
85 cl::ZeroOrMore
, cl::PositionalEatsArgs
);
88 NoProcessSymbols("no-process-syms",
89 cl::desc("Do not resolve to llvm-jitlink process symbols"),
92 static cl::list
<std::string
> AbsoluteDefs(
94 cl::desc("Inject absolute symbol definitions (syntax: <name>=<addr>)"),
97 static cl::list
<std::string
> TestHarnesses("harness", cl::Positional
,
98 cl::desc("Test harness files"),
100 cl::PositionalEatsArgs
);
102 static cl::opt
<bool> ShowInitialExecutionSessionState(
104 cl::desc("Print ExecutionSession state before resolving entry point"),
107 static cl::opt
<bool> ShowAddrs(
109 cl::desc("Print registered symbol, section, got and stub addresses"),
112 static cl::opt
<bool> ShowLinkGraph(
114 cl::desc("Print the link graph after fixups have been applied"),
117 static cl::opt
<bool> ShowSizes(
119 cl::desc("Show sizes pre- and post-dead stripping, and allocations"),
122 static cl::opt
<bool> ShowTimes("show-times",
123 cl::desc("Show times for llvm-jitlink phases"),
126 static cl::opt
<std::string
> SlabAllocateSizeString(
128 cl::desc("Allocate from a slab of the given size "
129 "(allowable suffixes: Kb, Mb, Gb. default = "
133 static cl::opt
<uint64_t> SlabAddress(
135 cl::desc("Set slab target address (requires -slab-allocate and -noexec)"),
138 static cl::opt
<bool> ShowRelocatedSectionContents(
139 "show-relocated-section-contents",
140 cl::desc("show section contents after fixups have been applied"),
143 static cl::opt
<bool> PhonyExternals(
145 cl::desc("resolve all otherwise unresolved externals to null"),
148 static cl::opt
<std::string
> OutOfProcessExecutor(
149 "oop-executor", cl::desc("Launch an out-of-process executor to run code"),
152 static cl::opt
<std::string
> OutOfProcessExecutorConnect(
153 "oop-executor-connect",
154 cl::desc("Connect to an out-of-process executor via TCP"));
156 ExitOnError ExitOnErr
;
161 operator<<(raw_ostream
&OS
, const Session::MemoryRegionInfo
&MRI
) {
162 return OS
<< "target addr = "
163 << format("0x%016" PRIx64
, MRI
.getTargetAddress())
164 << ", content: " << (const void *)MRI
.getContent().data() << " -- "
165 << (const void *)(MRI
.getContent().data() + MRI
.getContent().size())
166 << " (" << MRI
.getContent().size() << " bytes)";
170 operator<<(raw_ostream
&OS
, const Session::SymbolInfoMap
&SIM
) {
172 for (auto &SKV
: SIM
)
173 OS
<< " \"" << SKV
.first() << "\" " << SKV
.second
<< "\n";
178 operator<<(raw_ostream
&OS
, const Session::FileInfo
&FI
) {
179 for (auto &SIKV
: FI
.SectionInfos
)
180 OS
<< " Section \"" << SIKV
.first() << "\": " << SIKV
.second
<< "\n";
181 for (auto &GOTKV
: FI
.GOTEntryInfos
)
182 OS
<< " GOT \"" << GOTKV
.first() << "\": " << GOTKV
.second
<< "\n";
183 for (auto &StubKV
: FI
.StubInfos
)
184 OS
<< " Stub \"" << StubKV
.first() << "\": " << StubKV
.second
<< "\n";
189 operator<<(raw_ostream
&OS
, const Session::FileInfoMap
&FIM
) {
190 for (auto &FIKV
: FIM
)
191 OS
<< "File \"" << FIKV
.first() << "\":\n" << FIKV
.second
;
195 static Error
applyHarnessPromotions(Session
&S
, LinkGraph
&G
) {
197 // If this graph is part of the test harness there's nothing to do.
198 if (S
.HarnessFiles
.empty() || S
.HarnessFiles
.count(G
.getName()))
199 return Error::success();
201 LLVM_DEBUG(dbgs() << "Appling promotions to graph " << G
.getName() << "\n");
203 // If this graph is part of the test then promote any symbols referenced by
204 // the harness to default scope, remove all symbols that clash with harness
206 std::vector
<Symbol
*> DefinitionsToRemove
;
207 for (auto *Sym
: G
.defined_symbols()) {
212 if (Sym
->getLinkage() == Linkage::Weak
) {
213 if (!S
.CanonicalWeakDefs
.count(Sym
->getName()) ||
214 S
.CanonicalWeakDefs
[Sym
->getName()] != G
.getName()) {
216 dbgs() << " Externalizing weak symbol " << Sym
->getName() << "\n";
218 DefinitionsToRemove
.push_back(Sym
);
221 dbgs() << " Making weak symbol " << Sym
->getName() << " strong\n";
223 if (S
.HarnessExternals
.count(Sym
->getName()))
224 Sym
->setScope(Scope::Default
);
226 Sym
->setScope(Scope::Hidden
);
227 Sym
->setLinkage(Linkage::Strong
);
229 } else if (S
.HarnessExternals
.count(Sym
->getName())) {
230 LLVM_DEBUG(dbgs() << " Promoting " << Sym
->getName() << "\n");
231 Sym
->setScope(Scope::Default
);
234 } else if (S
.HarnessDefinitions
.count(Sym
->getName())) {
235 LLVM_DEBUG(dbgs() << " Externalizing " << Sym
->getName() << "\n");
236 DefinitionsToRemove
.push_back(Sym
);
240 for (auto *Sym
: DefinitionsToRemove
)
241 G
.makeExternal(*Sym
);
243 return Error::success();
246 static uint64_t computeTotalBlockSizes(LinkGraph
&G
) {
247 uint64_t TotalSize
= 0;
248 for (auto *B
: G
.blocks())
249 TotalSize
+= B
->getSize();
253 static void dumpSectionContents(raw_ostream
&OS
, LinkGraph
&G
) {
254 constexpr JITTargetAddress DumpWidth
= 16;
255 static_assert(isPowerOf2_64(DumpWidth
), "DumpWidth must be a power of two");
257 // Put sections in address order.
258 std::vector
<Section
*> Sections
;
259 for (auto &S
: G
.sections())
260 Sections
.push_back(&S
);
262 std::sort(Sections
.begin(), Sections
.end(),
263 [](const Section
*LHS
, const Section
*RHS
) {
264 if (llvm::empty(LHS
->symbols()) && llvm::empty(RHS
->symbols()))
266 if (llvm::empty(LHS
->symbols()))
268 if (llvm::empty(RHS
->symbols()))
270 SectionRange
LHSRange(*LHS
);
271 SectionRange
RHSRange(*RHS
);
272 return LHSRange
.getStart() < RHSRange
.getStart();
275 for (auto *S
: Sections
) {
276 OS
<< S
->getName() << " content:";
277 if (llvm::empty(S
->symbols())) {
278 OS
<< "\n section empty\n";
282 // Sort symbols into order, then render.
283 std::vector
<Symbol
*> Syms(S
->symbols().begin(), S
->symbols().end());
284 llvm::sort(Syms
, [](const Symbol
*LHS
, const Symbol
*RHS
) {
285 return LHS
->getAddress() < RHS
->getAddress();
288 JITTargetAddress NextAddr
= Syms
.front()->getAddress() & ~(DumpWidth
- 1);
289 for (auto *Sym
: Syms
) {
290 bool IsZeroFill
= Sym
->getBlock().isZeroFill();
291 JITTargetAddress SymStart
= Sym
->getAddress();
292 JITTargetAddress SymSize
= Sym
->getSize();
293 JITTargetAddress SymEnd
= SymStart
+ SymSize
;
294 const uint8_t *SymData
=
295 IsZeroFill
? nullptr : Sym
->getSymbolContent().bytes_begin();
297 // Pad any space before the symbol starts.
298 while (NextAddr
!= SymStart
) {
299 if (NextAddr
% DumpWidth
== 0)
300 OS
<< formatv("\n{0:x16}:", NextAddr
);
305 // Render the symbol content.
306 while (NextAddr
!= SymEnd
) {
307 if (NextAddr
% DumpWidth
== 0)
308 OS
<< formatv("\n{0:x16}:", NextAddr
);
312 OS
<< formatv(" {0:x-2}", SymData
[NextAddr
- SymStart
]);
320 class JITLinkSlabAllocator final
: public JITLinkMemoryManager
{
322 static Expected
<std::unique_ptr
<JITLinkSlabAllocator
>>
323 Create(uint64_t SlabSize
) {
324 Error Err
= Error::success();
325 std::unique_ptr
<JITLinkSlabAllocator
> Allocator(
326 new JITLinkSlabAllocator(SlabSize
, Err
));
328 return std::move(Err
);
329 return std::move(Allocator
);
332 Expected
<std::unique_ptr
<JITLinkMemoryManager::Allocation
>>
333 allocate(const JITLinkDylib
*JD
, const SegmentsRequestMap
&Request
) override
{
335 using AllocationMap
= DenseMap
<unsigned, sys::MemoryBlock
>;
337 // Local class for allocation.
338 class IPMMAlloc
: public Allocation
{
340 IPMMAlloc(JITLinkSlabAllocator
&Parent
, AllocationMap SegBlocks
)
341 : Parent(Parent
), SegBlocks(std::move(SegBlocks
)) {}
342 MutableArrayRef
<char> getWorkingMemory(ProtectionFlags Seg
) override
{
343 assert(SegBlocks
.count(Seg
) && "No allocation for segment");
344 return {static_cast<char *>(SegBlocks
[Seg
].base()),
345 SegBlocks
[Seg
].allocatedSize()};
347 JITTargetAddress
getTargetMemory(ProtectionFlags Seg
) override
{
348 assert(SegBlocks
.count(Seg
) && "No allocation for segment");
349 return pointerToJITTargetAddress(SegBlocks
[Seg
].base()) +
352 void finalizeAsync(FinalizeContinuation OnFinalize
) override
{
353 OnFinalize(applyProtections());
355 Error
deallocate() override
{
356 for (auto &KV
: SegBlocks
)
357 if (auto EC
= sys::Memory::releaseMappedMemory(KV
.second
))
358 return errorCodeToError(EC
);
359 return Error::success();
363 Error
applyProtections() {
364 for (auto &KV
: SegBlocks
) {
365 auto &Prot
= KV
.first
;
366 auto &Block
= KV
.second
;
367 if (auto EC
= sys::Memory::protectMappedMemory(Block
, Prot
))
368 return errorCodeToError(EC
);
369 if (Prot
& sys::Memory::MF_EXEC
)
370 sys::Memory::InvalidateInstructionCache(Block
.base(),
371 Block
.allocatedSize());
373 return Error::success();
376 JITLinkSlabAllocator
&Parent
;
377 AllocationMap SegBlocks
;
380 AllocationMap Blocks
;
382 for (auto &KV
: Request
) {
383 auto &Seg
= KV
.second
;
385 if (Seg
.getAlignment() > PageSize
)
386 return make_error
<StringError
>("Cannot request higher than page "
388 inconvertibleErrorCode());
390 if (PageSize
% Seg
.getAlignment() != 0)
391 return make_error
<StringError
>("Page size is not a multiple of "
393 inconvertibleErrorCode());
395 uint64_t ZeroFillStart
= Seg
.getContentSize();
396 uint64_t SegmentSize
= ZeroFillStart
+ Seg
.getZeroFillSize();
398 // Round segment size up to page boundary.
399 SegmentSize
= (SegmentSize
+ PageSize
- 1) & ~(PageSize
- 1);
401 // Take segment bytes from the front of the slab.
402 void *SlabBase
= SlabRemaining
.base();
403 uint64_t SlabRemainingSize
= SlabRemaining
.allocatedSize();
405 if (SegmentSize
> SlabRemainingSize
)
406 return make_error
<StringError
>("Slab allocator out of memory",
407 inconvertibleErrorCode());
409 sys::MemoryBlock
SegMem(SlabBase
, SegmentSize
);
411 sys::MemoryBlock(reinterpret_cast<char *>(SlabBase
) + SegmentSize
,
412 SlabRemainingSize
- SegmentSize
);
414 // Zero out the zero-fill memory.
415 memset(static_cast<char *>(SegMem
.base()) + ZeroFillStart
, 0,
416 Seg
.getZeroFillSize());
418 // Record the block for this segment.
419 Blocks
[KV
.first
] = std::move(SegMem
);
421 return std::unique_ptr
<InProcessMemoryManager::Allocation
>(
422 new IPMMAlloc(*this, std::move(Blocks
)));
426 JITLinkSlabAllocator(uint64_t SlabSize
, Error
&Err
) {
427 ErrorAsOutParameter
_(&Err
);
429 PageSize
= sys::Process::getPageSizeEstimate();
431 if (!isPowerOf2_64(PageSize
)) {
432 Err
= make_error
<StringError
>("Page size is not a power of 2",
433 inconvertibleErrorCode());
437 // Round slab request up to page size.
438 SlabSize
= (SlabSize
+ PageSize
- 1) & ~(PageSize
- 1);
440 const sys::Memory::ProtectionFlags ReadWrite
=
441 static_cast<sys::Memory::ProtectionFlags
>(sys::Memory::MF_READ
|
442 sys::Memory::MF_WRITE
);
446 sys::Memory::allocateMappedMemory(SlabSize
, nullptr, ReadWrite
, EC
);
449 Err
= errorCodeToError(EC
);
453 // Calculate the target address delta to link as-if slab were at
455 if (SlabAddress
!= ~0ULL)
457 SlabAddress
- pointerToJITTargetAddress(SlabRemaining
.base());
460 sys::MemoryBlock SlabRemaining
;
461 uint64_t PageSize
= 0;
462 int64_t TargetDelta
= 0;
465 Expected
<uint64_t> getSlabAllocSize(StringRef SizeString
) {
466 SizeString
= SizeString
.trim();
468 uint64_t Units
= 1024;
470 if (SizeString
.endswith_lower("kb"))
471 SizeString
= SizeString
.drop_back(2).rtrim();
472 else if (SizeString
.endswith_lower("mb")) {
474 SizeString
= SizeString
.drop_back(2).rtrim();
475 } else if (SizeString
.endswith_lower("gb")) {
476 Units
= 1024 * 1024 * 1024;
477 SizeString
= SizeString
.drop_back(2).rtrim();
480 uint64_t SlabSize
= 0;
481 if (SizeString
.getAsInteger(10, SlabSize
))
482 return make_error
<StringError
>("Invalid numeric format for slab size",
483 inconvertibleErrorCode());
485 return SlabSize
* Units
;
488 static std::unique_ptr
<JITLinkMemoryManager
> createMemoryManager() {
489 if (!SlabAllocateSizeString
.empty()) {
490 auto SlabSize
= ExitOnErr(getSlabAllocSize(SlabAllocateSizeString
));
491 return ExitOnErr(JITLinkSlabAllocator::Create(SlabSize
));
493 return std::make_unique
<InProcessMemoryManager
>();
496 LLVMJITLinkObjectLinkingLayer::LLVMJITLinkObjectLinkingLayer(
497 Session
&S
, JITLinkMemoryManager
&MemMgr
)
498 : ObjectLinkingLayer(S
.ES
, MemMgr
), S(S
) {}
500 Error
LLVMJITLinkObjectLinkingLayer::add(ResourceTrackerSP RT
,
501 std::unique_ptr
<MemoryBuffer
> O
) {
503 if (S
.HarnessFiles
.empty() || S
.HarnessFiles
.count(O
->getBufferIdentifier()))
504 return ObjectLinkingLayer::add(std::move(RT
), std::move(O
));
506 // Use getObjectSymbolInfo to compute the init symbol, but ignore
507 // the symbols field. We'll handle that manually to include promotion.
509 getObjectSymbolInfo(getExecutionSession(), O
->getMemBufferRef());
512 return ObjSymInfo
.takeError();
514 auto &InitSymbol
= ObjSymInfo
->second
;
516 // If creating an object file was going to fail it would have happened above,
517 // so we can 'cantFail' this.
519 cantFail(object::ObjectFile::createObjectFile(O
->getMemBufferRef()));
521 SymbolFlagsMap SymbolFlags
;
523 // The init symbol must be included in the SymbolFlags map if present.
525 SymbolFlags
[InitSymbol
] = JITSymbolFlags::MaterializationSideEffectsOnly
;
527 for (auto &Sym
: Obj
->symbols()) {
528 Expected
<uint32_t> SymFlagsOrErr
= Sym
.getFlags();
530 // TODO: Test this error.
531 return SymFlagsOrErr
.takeError();
533 // Skip symbols not defined in this object file.
534 if ((*SymFlagsOrErr
& object::BasicSymbolRef::SF_Undefined
))
537 auto Name
= Sym
.getName();
539 return Name
.takeError();
541 // Skip symbols that have type SF_File.
542 if (auto SymType
= Sym
.getType()) {
543 if (*SymType
== object::SymbolRef::ST_File
)
546 return SymType
.takeError();
548 auto SymFlags
= JITSymbolFlags::fromObjectSymbol(Sym
);
550 return SymFlags
.takeError();
552 if (SymFlags
->isWeak()) {
553 // If this is a weak symbol that's not defined in the harness then we
554 // need to either mark it as strong (if this is the first definition
555 // that we've seen) or discard it.
556 if (S
.HarnessDefinitions
.count(*Name
) || S
.CanonicalWeakDefs
.count(*Name
))
558 S
.CanonicalWeakDefs
[*Name
] = O
->getBufferIdentifier();
559 *SymFlags
&= ~JITSymbolFlags::Weak
;
560 if (!S
.HarnessExternals
.count(*Name
))
561 *SymFlags
&= ~JITSymbolFlags::Exported
;
562 } else if (S
.HarnessExternals
.count(*Name
)) {
563 *SymFlags
|= JITSymbolFlags::Exported
;
564 } else if (S
.HarnessDefinitions
.count(*Name
) ||
565 !(*SymFlagsOrErr
& object::BasicSymbolRef::SF_Global
))
568 auto InternedName
= S
.ES
.intern(*Name
);
569 SymbolFlags
[InternedName
] = std::move(*SymFlags
);
572 auto MU
= std::make_unique
<BasicObjectLayerMaterializationUnit
>(
573 *this, std::move(O
), std::move(SymbolFlags
), std::move(InitSymbol
));
575 auto &JD
= RT
->getJITDylib();
576 return JD
.define(std::move(MU
), std::move(RT
));
579 Expected
<std::unique_ptr
<TargetProcessControl
>>
580 LLVMJITLinkRemoteTargetProcessControl::LaunchExecutor() {
582 // FIXME: Add support for Windows.
583 return make_error
<StringError
>("-" + OutOfProcessExecutor
.ArgStr
+
584 " not supported on non-unix platforms",
585 inconvertibleErrorCode());
588 rpc::registerStringError
<LLVMJITLinkChannel
>();
590 constexpr int ReadEnd
= 0;
591 constexpr int WriteEnd
= 1;
599 // Create pipes to/from the executor..
600 if (pipe(ToExecutor
) != 0 || pipe(FromExecutor
) != 0)
601 return make_error
<StringError
>("Unable to create pipe for executor",
602 inconvertibleErrorCode());
609 // Close the parent ends of the pipes
610 close(ToExecutor
[WriteEnd
]);
611 close(FromExecutor
[ReadEnd
]);
613 // Execute the child process.
614 std::unique_ptr
<char[]> ExecutorPath
, FDSpecifier
;
616 ExecutorPath
= std::make_unique
<char[]>(OutOfProcessExecutor
.size() + 1);
617 strcpy(ExecutorPath
.get(), OutOfProcessExecutor
.data());
619 std::string
FDSpecifierStr("filedescs=");
620 FDSpecifierStr
+= utostr(ToExecutor
[ReadEnd
]);
621 FDSpecifierStr
+= ',';
622 FDSpecifierStr
+= utostr(FromExecutor
[WriteEnd
]);
623 FDSpecifier
= std::make_unique
<char[]>(FDSpecifierStr
.size() + 1);
624 strcpy(FDSpecifier
.get(), FDSpecifierStr
.c_str());
627 char *const Args
[] = {ExecutorPath
.get(), FDSpecifier
.get(), nullptr};
628 int RC
= execvp(ExecutorPath
.get(), Args
);
630 errs() << "unable to launch out-of-process executor \""
631 << ExecutorPath
.get() << "\"\n";
635 // else we're the parent...
637 // Close the child ends of the pipes
638 close(ToExecutor
[ReadEnd
]);
639 close(FromExecutor
[WriteEnd
]);
641 // Return an RPC channel connected to our end of the pipes.
642 auto SSP
= std::make_shared
<SymbolStringPool
>();
643 auto Channel
= std::make_unique
<rpc::FDRawByteChannel
>(FromExecutor
[ReadEnd
],
644 ToExecutor
[WriteEnd
]);
645 auto Endpoint
= std::make_unique
<LLVMJITLinkRPCEndpoint
>(*Channel
, true);
647 auto ReportError
= [](Error Err
) {
648 logAllUnhandledErrors(std::move(Err
), errs(), "");
651 Error Err
= Error::success();
652 std::unique_ptr
<LLVMJITLinkRemoteTargetProcessControl
> RTPC(
653 new LLVMJITLinkRemoteTargetProcessControl(
654 std::move(SSP
), std::move(Channel
), std::move(Endpoint
),
655 std::move(ReportError
), Err
));
657 return std::move(Err
);
658 return std::move(RTPC
);
662 Expected
<std::unique_ptr
<TargetProcessControl
>>
663 LLVMJITLinkRemoteTargetProcessControl::ConnectToExecutor() {
665 // FIXME: Add TCP support for Windows.
666 return make_error
<StringError
>("-" + OutOfProcessExecutorConnect
.ArgStr
+
667 " not supported on non-unix platforms",
668 inconvertibleErrorCode());
671 rpc::registerStringError
<LLVMJITLinkChannel
>();
673 StringRef HostNameStr
, PortStr
;
674 std::tie(HostNameStr
, PortStr
) =
675 StringRef(OutOfProcessExecutorConnect
).split(':');
677 if (HostNameStr
.empty())
678 return make_error
<StringError
>("host name for -" +
679 OutOfProcessExecutorConnect
.ArgStr
+
681 inconvertibleErrorCode());
683 return make_error
<StringError
>(
684 "port for -" + OutOfProcessExecutorConnect
.ArgStr
+ " can not be empty",
685 inconvertibleErrorCode());
687 std::string HostName
= HostNameStr
.str();
689 if (PortStr
.getAsInteger(10, Port
))
690 return make_error
<StringError
>("port number " + PortStr
+
691 " is not a valid integer",
692 inconvertibleErrorCode());
694 int SockFD
= socket(PF_INET
, SOCK_STREAM
, 0);
695 hostent
*Server
= gethostbyname(HostName
.c_str());
696 sockaddr_in ServAddr
;
697 memset(&ServAddr
, 0, sizeof(ServAddr
));
698 ServAddr
.sin_family
= PF_INET
;
699 memmove(&Server
->h_addr
, &ServAddr
.sin_addr
.s_addr
, Server
->h_length
);
700 ServAddr
.sin_port
= htons(Port
);
701 if (connect(SockFD
, reinterpret_cast<sockaddr
*>(&ServAddr
),
702 sizeof(ServAddr
)) < 0)
703 return make_error
<StringError
>("Failed to connect to " + HostName
+ ":" +
705 inconvertibleErrorCode());
707 auto SSP
= std::make_shared
<SymbolStringPool
>();
708 auto Channel
= std::make_unique
<rpc::FDRawByteChannel
>(SockFD
, SockFD
);
709 auto Endpoint
= std::make_unique
<LLVMJITLinkRPCEndpoint
>(*Channel
, true);
711 auto ReportError
= [](Error Err
) {
712 logAllUnhandledErrors(std::move(Err
), errs(), "");
715 Error Err
= Error::success();
716 std::unique_ptr
<LLVMJITLinkRemoteTargetProcessControl
> RTPC(
717 new LLVMJITLinkRemoteTargetProcessControl(
718 std::move(SSP
), std::move(Channel
), std::move(Endpoint
),
719 std::move(ReportError
), Err
));
721 return std::move(Err
);
722 return std::move(RTPC
);
726 Error
LLVMJITLinkRemoteTargetProcessControl::disconnect() {
727 std::promise
<MSVCPError
> P
;
728 auto F
= P
.get_future();
729 auto Err
= closeConnection([&](Error Err
) -> Error
{
730 P
.set_value(std::move(Err
));
732 return Error::success();
734 ListenerThread
.join();
735 return joinErrors(std::move(Err
), F
.get());
738 class PhonyExternalsGenerator
: public DefinitionGenerator
{
740 Error
tryToGenerate(LookupState
&LS
, LookupKind K
, JITDylib
&JD
,
741 JITDylibLookupFlags JDLookupFlags
,
742 const SymbolLookupSet
&LookupSet
) override
{
743 SymbolMap PhonySymbols
;
744 for (auto &KV
: LookupSet
)
745 PhonySymbols
[KV
.first
] = JITEvaluatedSymbol(0, JITSymbolFlags::Exported
);
746 return JD
.define(absoluteSymbols(std::move(PhonySymbols
)));
750 Expected
<std::unique_ptr
<Session
>> Session::Create(Triple TT
) {
752 auto PageSize
= sys::Process::getPageSize();
754 return PageSize
.takeError();
756 /// If -oop-executor is passed then launch the executor.
757 std::unique_ptr
<TargetProcessControl
> TPC
;
758 if (OutOfProcessExecutor
.getNumOccurrences()) {
759 if (auto RTPC
= LLVMJITLinkRemoteTargetProcessControl::LaunchExecutor())
760 TPC
= std::move(*RTPC
);
762 return RTPC
.takeError();
763 } else if (OutOfProcessExecutorConnect
.getNumOccurrences()) {
764 if (auto RTPC
= LLVMJITLinkRemoteTargetProcessControl::ConnectToExecutor())
765 TPC
= std::move(*RTPC
);
767 return RTPC
.takeError();
769 TPC
= std::make_unique
<SelfTargetProcessControl
>(
770 std::make_shared
<SymbolStringPool
>(), std::move(TT
), *PageSize
,
771 createMemoryManager());
773 Error Err
= Error::success();
774 std::unique_ptr
<Session
> S(new Session(std::move(TPC
), Err
));
776 return std::move(Err
);
780 Session::~Session() {
781 if (auto Err
= ES
.endSession())
782 ES
.reportError(std::move(Err
));
785 // FIXME: Move to createJITDylib if/when we start using Platform support in
787 Session::Session(std::unique_ptr
<TargetProcessControl
> TPC
, Error
&Err
)
788 : TPC(std::move(TPC
)), ObjLayer(*this, this->TPC
->getMemMgr()) {
790 /// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig to the
792 class JITLinkSessionPlugin
: public ObjectLinkingLayer::Plugin
{
794 JITLinkSessionPlugin(Session
&S
) : S(S
) {}
795 void modifyPassConfig(MaterializationResponsibility
&MR
, const Triple
&TT
,
796 PassConfiguration
&PassConfig
) override
{
797 S
.modifyPassConfig(TT
, PassConfig
);
800 Error
notifyFailed(MaterializationResponsibility
&MR
) override
{
801 return Error::success();
803 Error
notifyRemovingResources(ResourceKey K
) override
{
804 return Error::success();
806 void notifyTransferringResources(ResourceKey DstKey
,
807 ResourceKey SrcKey
) override
{}
813 ErrorAsOutParameter
_(&Err
);
815 if (auto MainJDOrErr
= ES
.createJITDylib("main"))
816 MainJD
= &*MainJDOrErr
;
818 Err
= MainJDOrErr
.takeError();
822 if (!NoExec
&& !this->TPC
->getTargetTriple().isOSWindows())
823 ObjLayer
.addPlugin(std::make_unique
<EHFrameRegistrationPlugin
>(
824 ES
, ExitOnErr(TPCEHFrameRegistrar::Create(*this->TPC
))));
826 ObjLayer
.addPlugin(std::make_unique
<JITLinkSessionPlugin
>(*this));
828 // Process any harness files.
829 for (auto &HarnessFile
: TestHarnesses
) {
830 HarnessFiles
.insert(HarnessFile
);
833 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(HarnessFile
)));
836 ExitOnErr(getObjectSymbolInfo(ES
, ObjBuffer
->getMemBufferRef()));
838 for (auto &KV
: ObjSymbolInfo
.first
)
839 HarnessDefinitions
.insert(*KV
.first
);
841 auto Obj
= ExitOnErr(
842 object::ObjectFile::createObjectFile(ObjBuffer
->getMemBufferRef()));
844 for (auto &Sym
: Obj
->symbols()) {
845 uint32_t SymFlags
= ExitOnErr(Sym
.getFlags());
846 auto Name
= ExitOnErr(Sym
.getName());
851 if (SymFlags
& object::BasicSymbolRef::SF_Undefined
)
852 HarnessExternals
.insert(Name
);
856 // If a name is defined by some harness file then it's a definition, not an
858 for (auto &DefName
: HarnessDefinitions
)
859 HarnessExternals
.erase(DefName
.getKey());
862 void Session::dumpSessionInfo(raw_ostream
&OS
) {
863 OS
<< "Registered addresses:\n" << SymbolInfos
<< FileInfos
;
866 void Session::modifyPassConfig(const Triple
&TT
,
867 PassConfiguration
&PassConfig
) {
868 if (!CheckFiles
.empty())
869 PassConfig
.PostFixupPasses
.push_back([this](LinkGraph
&G
) {
870 if (TPC
->getTargetTriple().getObjectFormat() == Triple::ELF
)
871 return registerELFGraphInfo(*this, G
);
873 if (TPC
->getTargetTriple().getObjectFormat() == Triple::MachO
)
874 return registerMachOGraphInfo(*this, G
);
876 return make_error
<StringError
>("Unsupported object format for GOT/stub "
878 inconvertibleErrorCode());
882 PassConfig
.PostFixupPasses
.push_back([](LinkGraph
&G
) -> Error
{
883 outs() << "Link graph \"" << G
.getName() << "\" post-fixup:\n";
885 return Error::success();
888 PassConfig
.PrePrunePasses
.push_back(
889 [this](LinkGraph
&G
) { return applyHarnessPromotions(*this, G
); });
892 PassConfig
.PrePrunePasses
.push_back([this](LinkGraph
&G
) -> Error
{
893 SizeBeforePruning
+= computeTotalBlockSizes(G
);
894 return Error::success();
896 PassConfig
.PostFixupPasses
.push_back([this](LinkGraph
&G
) -> Error
{
897 SizeAfterFixups
+= computeTotalBlockSizes(G
);
898 return Error::success();
902 if (ShowRelocatedSectionContents
)
903 PassConfig
.PostFixupPasses
.push_back([](LinkGraph
&G
) -> Error
{
904 outs() << "Relocated section contents for " << G
.getName() << ":\n";
905 dumpSectionContents(outs(), G
);
906 return Error::success();
910 Expected
<Session::FileInfo
&> Session::findFileInfo(StringRef FileName
) {
911 auto FileInfoItr
= FileInfos
.find(FileName
);
912 if (FileInfoItr
== FileInfos
.end())
913 return make_error
<StringError
>("file \"" + FileName
+ "\" not recognized",
914 inconvertibleErrorCode());
915 return FileInfoItr
->second
;
918 Expected
<Session::MemoryRegionInfo
&>
919 Session::findSectionInfo(StringRef FileName
, StringRef SectionName
) {
920 auto FI
= findFileInfo(FileName
);
922 return FI
.takeError();
923 auto SecInfoItr
= FI
->SectionInfos
.find(SectionName
);
924 if (SecInfoItr
== FI
->SectionInfos
.end())
925 return make_error
<StringError
>("no section \"" + SectionName
+
926 "\" registered for file \"" + FileName
+
928 inconvertibleErrorCode());
929 return SecInfoItr
->second
;
932 Expected
<Session::MemoryRegionInfo
&>
933 Session::findStubInfo(StringRef FileName
, StringRef TargetName
) {
934 auto FI
= findFileInfo(FileName
);
936 return FI
.takeError();
937 auto StubInfoItr
= FI
->StubInfos
.find(TargetName
);
938 if (StubInfoItr
== FI
->StubInfos
.end())
939 return make_error
<StringError
>("no stub for \"" + TargetName
+
940 "\" registered for file \"" + FileName
+
942 inconvertibleErrorCode());
943 return StubInfoItr
->second
;
946 Expected
<Session::MemoryRegionInfo
&>
947 Session::findGOTEntryInfo(StringRef FileName
, StringRef TargetName
) {
948 auto FI
= findFileInfo(FileName
);
950 return FI
.takeError();
951 auto GOTInfoItr
= FI
->GOTEntryInfos
.find(TargetName
);
952 if (GOTInfoItr
== FI
->GOTEntryInfos
.end())
953 return make_error
<StringError
>("no GOT entry for \"" + TargetName
+
954 "\" registered for file \"" + FileName
+
956 inconvertibleErrorCode());
957 return GOTInfoItr
->second
;
960 bool Session::isSymbolRegistered(StringRef SymbolName
) {
961 return SymbolInfos
.count(SymbolName
);
964 Expected
<Session::MemoryRegionInfo
&>
965 Session::findSymbolInfo(StringRef SymbolName
, Twine ErrorMsgStem
) {
966 auto SymInfoItr
= SymbolInfos
.find(SymbolName
);
967 if (SymInfoItr
== SymbolInfos
.end())
968 return make_error
<StringError
>(ErrorMsgStem
+ ": symbol " + SymbolName
+
970 inconvertibleErrorCode());
971 return SymInfoItr
->second
;
974 } // end namespace llvm
976 static Triple
getFirstFileTriple() {
977 static Triple FirstTT
= []() {
978 assert(!InputFiles
.empty() && "InputFiles can not be empty");
980 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFiles
.front())));
981 auto Obj
= ExitOnErr(
982 object::ObjectFile::createObjectFile(ObjBuffer
->getMemBufferRef()));
983 return Obj
->makeTriple();
989 static Error
sanitizeArguments(const Triple
&TT
, const char *ArgV0
) {
990 // Set the entry point name if not specified.
991 if (EntryPointName
.empty()) {
992 if (TT
.getObjectFormat() == Triple::MachO
)
993 EntryPointName
= "_main";
995 EntryPointName
= "main";
998 // -noexec and --args should not be used together.
999 if (NoExec
&& !InputArgv
.empty())
1000 outs() << "Warning: --args passed to -noexec run will be ignored.\n";
1002 // If -slab-address is passed, require -slab-allocate and -noexec
1003 if (SlabAddress
!= ~0ULL) {
1004 if (SlabAllocateSizeString
== "" || !NoExec
)
1005 return make_error
<StringError
>(
1006 "-slab-address requires -slab-allocate and -noexec",
1007 inconvertibleErrorCode());
1010 // Only one of -oop-executor and -oop-executor-connect can be used.
1011 if (!!OutOfProcessExecutor
.getNumOccurrences() &&
1012 !!OutOfProcessExecutorConnect
.getNumOccurrences())
1013 return make_error
<StringError
>(
1014 "Only one of -" + OutOfProcessExecutor
.ArgStr
+ " and -" +
1015 OutOfProcessExecutorConnect
.ArgStr
+ " can be specified",
1016 inconvertibleErrorCode());
1018 // If -oop-executor was used but no value was specified then use a sensible
1020 if (!!OutOfProcessExecutor
.getNumOccurrences() &&
1021 OutOfProcessExecutor
.empty()) {
1022 SmallString
<256> OOPExecutorPath(sys::fs::getMainExecutable(
1023 ArgV0
, reinterpret_cast<void *>(&sanitizeArguments
)));
1024 sys::path::remove_filename(OOPExecutorPath
);
1025 if (OOPExecutorPath
.back() != '/')
1026 OOPExecutorPath
+= '/';
1027 OOPExecutorPath
+= "llvm-jitlink-executor";
1028 OutOfProcessExecutor
= OOPExecutorPath
.str().str();
1031 return Error::success();
1034 static Error
loadProcessSymbols(Session
&S
) {
1035 auto FilterMainEntryPoint
=
1036 [EPName
= S
.ES
.intern(EntryPointName
)](SymbolStringPtr Name
) {
1037 return Name
!= EPName
;
1039 S
.MainJD
->addGenerator(
1040 ExitOnErr(orc::TPCDynamicLibrarySearchGenerator::GetForTargetProcess(
1041 *S
.TPC
, std::move(FilterMainEntryPoint
))));
1043 return Error::success();
1046 static Error
loadDylibs(Session
&S
) {
1047 for (const auto &Dylib
: Dylibs
) {
1048 auto G
= orc::TPCDynamicLibrarySearchGenerator::Load(*S
.TPC
, Dylib
.c_str());
1050 return G
.takeError();
1051 S
.MainJD
->addGenerator(std::move(*G
));
1054 return Error::success();
1057 static void addPhonyExternalsGenerator(Session
&S
) {
1058 S
.MainJD
->addGenerator(std::make_unique
<PhonyExternalsGenerator
>());
1061 static Error
loadObjects(Session
&S
) {
1062 std::map
<unsigned, JITDylib
*> IdxToJLD
;
1064 // First, set up JITDylibs.
1065 LLVM_DEBUG(dbgs() << "Creating JITDylibs...\n");
1067 // Create a "main" JITLinkDylib.
1068 IdxToJLD
[0] = S
.MainJD
;
1069 S
.JDSearchOrder
.push_back(S
.MainJD
);
1070 LLVM_DEBUG(dbgs() << " 0: " << S
.MainJD
->getName() << "\n");
1072 // Add any extra JITLinkDylibs from the command line.
1073 std::string
JDNamePrefix("lib");
1074 for (auto JLDItr
= JITLinkDylibs
.begin(), JLDEnd
= JITLinkDylibs
.end();
1075 JLDItr
!= JLDEnd
; ++JLDItr
) {
1076 auto JD
= S
.ES
.createJITDylib(JDNamePrefix
+ *JLDItr
);
1078 return JD
.takeError();
1080 JITLinkDylibs
.getPosition(JLDItr
- JITLinkDylibs
.begin());
1081 IdxToJLD
[JDIdx
] = &*JD
;
1082 S
.JDSearchOrder
.push_back(&*JD
);
1083 LLVM_DEBUG(dbgs() << " " << JDIdx
<< ": " << JD
->getName() << "\n");
1086 // Set every dylib to link against every other, in command line order.
1087 for (auto *JD
: S
.JDSearchOrder
) {
1088 auto LookupFlags
= JITDylibLookupFlags::MatchExportedSymbolsOnly
;
1089 JITDylibSearchOrder LinkOrder
;
1090 for (auto *JD2
: S
.JDSearchOrder
) {
1093 LinkOrder
.push_back(std::make_pair(JD2
, LookupFlags
));
1095 JD
->setLinkOrder(std::move(LinkOrder
));
1099 LLVM_DEBUG(dbgs() << "Adding test harness objects...\n");
1100 for (auto HarnessFile
: TestHarnesses
) {
1101 LLVM_DEBUG(dbgs() << " " << HarnessFile
<< "\n");
1103 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(HarnessFile
)));
1104 ExitOnErr(S
.ObjLayer
.add(*S
.MainJD
, std::move(ObjBuffer
)));
1107 // Load each object into the corresponding JITDylib..
1108 LLVM_DEBUG(dbgs() << "Adding objects...\n");
1109 for (auto InputFileItr
= InputFiles
.begin(), InputFileEnd
= InputFiles
.end();
1110 InputFileItr
!= InputFileEnd
; ++InputFileItr
) {
1111 unsigned InputFileArgIdx
=
1112 InputFiles
.getPosition(InputFileItr
- InputFiles
.begin());
1113 const std::string
&InputFile
= *InputFileItr
;
1114 auto &JD
= *std::prev(IdxToJLD
.lower_bound(InputFileArgIdx
))->second
;
1115 LLVM_DEBUG(dbgs() << " " << InputFileArgIdx
<< ": \"" << InputFile
1116 << "\" to " << JD
.getName() << "\n";);
1118 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFile
)));
1120 auto Magic
= identify_magic(ObjBuffer
->getBuffer());
1121 if (Magic
== file_magic::archive
||
1122 Magic
== file_magic::macho_universal_binary
)
1123 JD
.addGenerator(ExitOnErr(StaticLibraryDefinitionGenerator::Load(
1124 S
.ObjLayer
, InputFile
.c_str(), S
.TPC
->getTargetTriple())));
1126 ExitOnErr(S
.ObjLayer
.add(JD
, std::move(ObjBuffer
)));
1129 // Define absolute symbols.
1130 LLVM_DEBUG(dbgs() << "Defining absolute symbols...\n");
1131 for (auto AbsDefItr
= AbsoluteDefs
.begin(), AbsDefEnd
= AbsoluteDefs
.end();
1132 AbsDefItr
!= AbsDefEnd
; ++AbsDefItr
) {
1133 unsigned AbsDefArgIdx
=
1134 AbsoluteDefs
.getPosition(AbsDefItr
- AbsoluteDefs
.begin());
1135 auto &JD
= *std::prev(IdxToJLD
.lower_bound(AbsDefArgIdx
))->second
;
1137 StringRef AbsDefStmt
= *AbsDefItr
;
1138 size_t EqIdx
= AbsDefStmt
.find_first_of('=');
1139 if (EqIdx
== StringRef::npos
)
1140 return make_error
<StringError
>("Invalid absolute define \"" + AbsDefStmt
+
1141 "\". Syntax: <name>=<addr>",
1142 inconvertibleErrorCode());
1143 StringRef Name
= AbsDefStmt
.substr(0, EqIdx
).trim();
1144 StringRef AddrStr
= AbsDefStmt
.substr(EqIdx
+ 1).trim();
1147 if (AddrStr
.getAsInteger(0, Addr
))
1148 return make_error
<StringError
>("Invalid address expression \"" + AddrStr
+
1149 "\" in absolute define \"" + AbsDefStmt
+
1151 inconvertibleErrorCode());
1152 JITEvaluatedSymbol
AbsDef(Addr
, JITSymbolFlags::Exported
);
1153 if (auto Err
= JD
.define(absoluteSymbols({{S
.ES
.intern(Name
), AbsDef
}})))
1156 // Register the absolute symbol with the session symbol infos.
1157 S
.SymbolInfos
[Name
] = { StringRef(), Addr
};
1161 dbgs() << "Dylib search order is [ ";
1162 for (auto *JD
: S
.JDSearchOrder
)
1163 dbgs() << JD
->getName() << " ";
1167 return Error::success();
1170 static Error
runChecks(Session
&S
) {
1172 auto TripleName
= S
.TPC
->getTargetTriple().str();
1173 std::string ErrorStr
;
1174 const Target
*TheTarget
= TargetRegistry::lookupTarget(TripleName
, ErrorStr
);
1176 ExitOnErr(make_error
<StringError
>("Error accessing target '" + TripleName
+
1178 inconvertibleErrorCode()));
1180 std::unique_ptr
<MCSubtargetInfo
> STI(
1181 TheTarget
->createMCSubtargetInfo(TripleName
, "", ""));
1184 make_error
<StringError
>("Unable to create subtarget for " + TripleName
,
1185 inconvertibleErrorCode()));
1187 std::unique_ptr
<MCRegisterInfo
> MRI(TheTarget
->createMCRegInfo(TripleName
));
1189 ExitOnErr(make_error
<StringError
>("Unable to create target register info "
1192 inconvertibleErrorCode()));
1194 MCTargetOptions MCOptions
;
1195 std::unique_ptr
<MCAsmInfo
> MAI(
1196 TheTarget
->createMCAsmInfo(*MRI
, TripleName
, MCOptions
));
1198 ExitOnErr(make_error
<StringError
>("Unable to create target asm info " +
1200 inconvertibleErrorCode()));
1202 MCContext
Ctx(MAI
.get(), MRI
.get(), nullptr);
1204 std::unique_ptr
<MCDisassembler
> Disassembler(
1205 TheTarget
->createMCDisassembler(*STI
, Ctx
));
1207 ExitOnErr(make_error
<StringError
>("Unable to create disassembler for " +
1209 inconvertibleErrorCode()));
1211 std::unique_ptr
<MCInstrInfo
> MII(TheTarget
->createMCInstrInfo());
1213 std::unique_ptr
<MCInstPrinter
> InstPrinter(
1214 TheTarget
->createMCInstPrinter(Triple(TripleName
), 0, *MAI
, *MII
, *MRI
));
1216 auto IsSymbolValid
= [&S
](StringRef Symbol
) {
1217 return S
.isSymbolRegistered(Symbol
);
1220 auto GetSymbolInfo
= [&S
](StringRef Symbol
) {
1221 return S
.findSymbolInfo(Symbol
, "Can not get symbol info");
1224 auto GetSectionInfo
= [&S
](StringRef FileName
, StringRef SectionName
) {
1225 return S
.findSectionInfo(FileName
, SectionName
);
1228 auto GetStubInfo
= [&S
](StringRef FileName
, StringRef SectionName
) {
1229 return S
.findStubInfo(FileName
, SectionName
);
1232 auto GetGOTInfo
= [&S
](StringRef FileName
, StringRef SectionName
) {
1233 return S
.findGOTEntryInfo(FileName
, SectionName
);
1236 RuntimeDyldChecker
Checker(
1237 IsSymbolValid
, GetSymbolInfo
, GetSectionInfo
, GetStubInfo
, GetGOTInfo
,
1238 S
.TPC
->getTargetTriple().isLittleEndian() ? support::little
1240 Disassembler
.get(), InstPrinter
.get(), dbgs());
1242 std::string CheckLineStart
= "# " + CheckName
+ ":";
1243 for (auto &CheckFile
: CheckFiles
) {
1244 auto CheckerFileBuf
=
1245 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(CheckFile
)));
1246 if (!Checker
.checkAllRulesInBuffer(CheckLineStart
, &*CheckerFileBuf
))
1247 ExitOnErr(make_error
<StringError
>(
1248 "Some checks in " + CheckFile
+ " failed", inconvertibleErrorCode()));
1251 return Error::success();
1254 static void dumpSessionStats(Session
&S
) {
1256 outs() << "Total size of all blocks before pruning: " << S
.SizeBeforePruning
1257 << "\nTotal size of all blocks after fixups: " << S
.SizeAfterFixups
1261 static Expected
<JITEvaluatedSymbol
> getMainEntryPoint(Session
&S
) {
1262 return S
.ES
.lookup(S
.JDSearchOrder
, EntryPointName
);
1266 struct JITLinkTimers
{
1267 TimerGroup JITLinkTG
{"llvm-jitlink timers", "timers for llvm-jitlink phases"};
1268 Timer LoadObjectsTimer
{"load", "time to load/add object files", JITLinkTG
};
1269 Timer LinkTimer
{"link", "time to link object files", JITLinkTG
};
1270 Timer RunTimer
{"run", "time to execute jitlink'd code", JITLinkTG
};
1274 int main(int argc
, char *argv
[]) {
1275 InitLLVM
X(argc
, argv
);
1277 InitializeAllTargetInfos();
1278 InitializeAllTargetMCs();
1279 InitializeAllDisassemblers();
1281 cl::ParseCommandLineOptions(argc
, argv
, "llvm jitlink tool");
1282 ExitOnErr
.setBanner(std::string(argv
[0]) + ": ");
1284 /// If timers are enabled, create a JITLinkTimers instance.
1285 std::unique_ptr
<JITLinkTimers
> Timers
=
1286 ShowTimes
? std::make_unique
<JITLinkTimers
>() : nullptr;
1288 ExitOnErr(sanitizeArguments(getFirstFileTriple(), argv
[0]));
1290 auto S
= ExitOnErr(Session::Create(getFirstFileTriple()));
1293 TimeRegion
TR(Timers
? &Timers
->LoadObjectsTimer
: nullptr);
1294 ExitOnErr(loadObjects(*S
));
1297 if (!NoProcessSymbols
)
1298 ExitOnErr(loadProcessSymbols(*S
));
1299 ExitOnErr(loadDylibs(*S
));
1302 addPhonyExternalsGenerator(*S
);
1305 if (ShowInitialExecutionSessionState
)
1308 JITEvaluatedSymbol EntryPoint
= 0;
1310 TimeRegion
TR(Timers
? &Timers
->LinkTimer
: nullptr);
1311 EntryPoint
= ExitOnErr(getMainEntryPoint(*S
));
1315 S
->dumpSessionInfo(outs());
1317 ExitOnErr(runChecks(*S
));
1319 dumpSessionStats(*S
);
1326 TimeRegion
TR(Timers
? &Timers
->RunTimer
: nullptr);
1327 Result
= ExitOnErr(S
->TPC
->runAsMain(EntryPoint
.getAddress(), InputArgv
));
1330 ExitOnErr(S
->ES
.endSession());
1331 ExitOnErr(S
->TPC
->disconnect());