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/ExecutionEngine/JITLink/EHFrameSupport.h"
18 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
19 #include "llvm/MC/MCAsmInfo.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
22 #include "llvm/MC/MCInstPrinter.h"
23 #include "llvm/MC/MCInstrInfo.h"
24 #include "llvm/MC/MCRegisterInfo.h"
25 #include "llvm/MC/MCSubtargetInfo.h"
26 #include "llvm/Object/COFF.h"
27 #include "llvm/Object/MachO.h"
28 #include "llvm/Object/ObjectFile.h"
29 #include "llvm/Support/CommandLine.h"
30 #include "llvm/Support/Debug.h"
31 #include "llvm/Support/DynamicLibrary.h"
32 #include "llvm/Support/InitLLVM.h"
33 #include "llvm/Support/MemoryBuffer.h"
34 #include "llvm/Support/TargetRegistry.h"
35 #include "llvm/Support/TargetSelect.h"
40 #define DEBUG_TYPE "llvm-jitlink"
43 using namespace llvm::jitlink
;
44 using namespace llvm::orc
;
46 static cl::list
<std::string
> InputFiles(cl::Positional
, cl::OneOrMore
,
47 cl::desc("input files"));
49 static cl::opt
<bool> NoExec("noexec", cl::desc("Do not execute loaded code"),
52 static cl::list
<std::string
>
53 CheckFiles("check", cl::desc("File containing verifier checks"),
56 static cl::opt
<std::string
>
57 EntryPointName("entry", cl::desc("Symbol to call as main entry point"),
60 static cl::list
<std::string
> JITLinkDylibs(
61 "jld", cl::desc("Specifies the JITDylib to be used for any subsequent "
62 "input file arguments"));
64 static cl::list
<std::string
>
65 Dylibs("dlopen", cl::desc("Dynamic libraries to load before linking"),
68 static cl::list
<std::string
> InputArgv("args", cl::Positional
,
69 cl::desc("<program arguments>..."),
70 cl::ZeroOrMore
, cl::PositionalEatsArgs
);
73 NoProcessSymbols("no-process-syms",
74 cl::desc("Do not resolve to llvm-jitlink process symbols"),
77 static cl::list
<std::string
> AbsoluteDefs(
79 cl::desc("Inject absolute symbol definitions (syntax: <name>=<addr>)"),
82 static cl::opt
<bool> ShowAddrs(
84 cl::desc("Print registered symbol, section, got and stub addresses"),
87 static cl::opt
<bool> ShowAtomGraph(
89 cl::desc("Print the atom graph after fixups have been applied"),
92 static cl::opt
<bool> ShowSizes(
94 cl::desc("Show sizes pre- and post-dead stripping, and allocations"),
97 static cl::opt
<bool> ShowRelocatedSectionContents(
98 "show-relocated-section-contents",
99 cl::desc("show section contents after fixups have been applied"),
102 ExitOnError ExitOnErr
;
107 operator<<(raw_ostream
&OS
, const Session::MemoryRegionInfo
&MRI
) {
108 return OS
<< "target addr = "
109 << format("0x%016" PRIx64
, MRI
.getTargetAddress())
110 << ", content: " << (const void *)MRI
.getContent().data() << " -- "
111 << (const void *)(MRI
.getContent().data() + MRI
.getContent().size())
112 << " (" << MRI
.getContent().size() << " bytes)";
116 operator<<(raw_ostream
&OS
, const Session::SymbolInfoMap
&SIM
) {
118 for (auto &SKV
: SIM
)
119 OS
<< " \"" << SKV
.first() << "\" " << SKV
.second
<< "\n";
124 operator<<(raw_ostream
&OS
, const Session::FileInfo
&FI
) {
125 for (auto &SIKV
: FI
.SectionInfos
)
126 OS
<< " Section \"" << SIKV
.first() << "\": " << SIKV
.second
<< "\n";
127 for (auto &GOTKV
: FI
.GOTEntryInfos
)
128 OS
<< " GOT \"" << GOTKV
.first() << "\": " << GOTKV
.second
<< "\n";
129 for (auto &StubKV
: FI
.StubInfos
)
130 OS
<< " Stub \"" << StubKV
.first() << "\": " << StubKV
.second
<< "\n";
135 operator<<(raw_ostream
&OS
, const Session::FileInfoMap
&FIM
) {
136 for (auto &FIKV
: FIM
)
137 OS
<< "File \"" << FIKV
.first() << "\":\n" << FIKV
.second
;
141 static uint64_t computeTotalAtomSizes(AtomGraph
&G
) {
142 uint64_t TotalSize
= 0;
143 for (auto *DA
: G
.defined_atoms())
144 if (DA
->isZeroFill())
145 TotalSize
+= DA
->getZeroFillSize();
147 TotalSize
+= DA
->getContent().size();
151 static void dumpSectionContents(raw_ostream
&OS
, AtomGraph
&G
) {
152 constexpr JITTargetAddress DumpWidth
= 16;
153 static_assert(isPowerOf2_64(DumpWidth
), "DumpWidth must be a power of two");
155 // Put sections in address order.
156 std::vector
<Section
*> Sections
;
157 for (auto &S
: G
.sections())
158 Sections
.push_back(&S
);
160 std::sort(Sections
.begin(), Sections
.end(),
161 [](const Section
*LHS
, const Section
*RHS
) {
162 if (LHS
->atoms_empty() && RHS
->atoms_empty())
164 if (LHS
->atoms_empty())
166 if (RHS
->atoms_empty())
168 return (*LHS
->atoms().begin())->getAddress() <
169 (*RHS
->atoms().begin())->getAddress();
172 for (auto *S
: Sections
) {
173 OS
<< S
->getName() << " content:";
174 if (S
->atoms_empty()) {
175 OS
<< "\n section empty\n";
179 // Sort atoms into order, then render.
180 std::vector
<DefinedAtom
*> Atoms(S
->atoms().begin(), S
->atoms().end());
181 std::sort(Atoms
.begin(), Atoms
.end(),
182 [](const DefinedAtom
*LHS
, const DefinedAtom
*RHS
) {
183 return LHS
->getAddress() < RHS
->getAddress();
186 JITTargetAddress NextAddr
= Atoms
.front()->getAddress() & ~(DumpWidth
- 1);
187 for (auto *DA
: Atoms
) {
188 bool IsZeroFill
= DA
->isZeroFill();
189 JITTargetAddress AtomStart
= DA
->getAddress();
190 JITTargetAddress AtomSize
=
191 IsZeroFill
? DA
->getZeroFillSize() : DA
->getContent().size();
192 JITTargetAddress AtomEnd
= AtomStart
+ AtomSize
;
193 const uint8_t *AtomData
=
194 IsZeroFill
? nullptr : DA
->getContent().bytes_begin();
196 // Pad any space before the atom starts.
197 while (NextAddr
!= AtomStart
) {
198 if (NextAddr
% DumpWidth
== 0)
199 OS
<< formatv("\n{0:x16}:", NextAddr
);
204 // Render the atom content.
205 while (NextAddr
!= AtomEnd
) {
206 if (NextAddr
% DumpWidth
== 0)
207 OS
<< formatv("\n{0:x16}:", NextAddr
);
211 OS
<< formatv(" {0:x-2}", AtomData
[NextAddr
- AtomStart
]);
219 Session::Session(Triple TT
) : ObjLayer(ES
, MemMgr
), TT(std::move(TT
)) {
221 /// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig to the
223 class JITLinkSessionPlugin
: public ObjectLinkingLayer::Plugin
{
225 JITLinkSessionPlugin(Session
&S
) : S(S
) {}
226 void modifyPassConfig(MaterializationResponsibility
&MR
, const Triple
&TT
,
227 PassConfiguration
&PassConfig
) {
228 S
.modifyPassConfig(TT
, PassConfig
);
235 if (!NoExec
&& !TT
.isOSWindows())
236 ObjLayer
.addPlugin(llvm::make_unique
<EHFrameRegistrationPlugin
>(
237 InProcessEHFrameRegistrar::getInstance()));
239 ObjLayer
.addPlugin(llvm::make_unique
<JITLinkSessionPlugin
>(*this));
242 void Session::dumpSessionInfo(raw_ostream
&OS
) {
243 OS
<< "Registered addresses:\n" << SymbolInfos
<< FileInfos
;
246 void Session::modifyPassConfig(const Triple
&FTT
,
247 PassConfiguration
&PassConfig
) {
248 if (!CheckFiles
.empty())
249 PassConfig
.PostFixupPasses
.push_back([this](AtomGraph
&G
) {
250 if (TT
.getObjectFormat() == Triple::MachO
)
251 return registerMachOStubsAndGOT(*this, G
);
252 return make_error
<StringError
>("Unsupported object format for GOT/stub "
254 inconvertibleErrorCode());
258 PassConfig
.PostFixupPasses
.push_back([](AtomGraph
&G
) -> Error
{
259 outs() << "Atom graph post-fixup:\n";
261 return Error::success();
266 PassConfig
.PrePrunePasses
.push_back([this](AtomGraph
&G
) -> Error
{
267 SizeBeforePruning
+= computeTotalAtomSizes(G
);
268 return Error::success();
270 PassConfig
.PostFixupPasses
.push_back([this](AtomGraph
&G
) -> Error
{
271 SizeAfterFixups
+= computeTotalAtomSizes(G
);
272 return Error::success();
276 if (ShowRelocatedSectionContents
)
277 PassConfig
.PostFixupPasses
.push_back([](AtomGraph
&G
) -> Error
{
278 outs() << "Relocated section contents for " << G
.getName() << ":\n";
279 dumpSectionContents(outs(), G
);
280 return Error::success();
284 Expected
<Session::FileInfo
&> Session::findFileInfo(StringRef FileName
) {
285 auto FileInfoItr
= FileInfos
.find(FileName
);
286 if (FileInfoItr
== FileInfos
.end())
287 return make_error
<StringError
>("file \"" + FileName
+ "\" not recognized",
288 inconvertibleErrorCode());
289 return FileInfoItr
->second
;
292 Expected
<Session::MemoryRegionInfo
&>
293 Session::findSectionInfo(StringRef FileName
, StringRef SectionName
) {
294 auto FI
= findFileInfo(FileName
);
296 return FI
.takeError();
297 auto SecInfoItr
= FI
->SectionInfos
.find(SectionName
);
298 if (SecInfoItr
== FI
->SectionInfos
.end())
299 return make_error
<StringError
>("no section \"" + SectionName
+
300 "\" registered for file \"" + FileName
+
302 inconvertibleErrorCode());
303 return SecInfoItr
->second
;
306 Expected
<Session::MemoryRegionInfo
&>
307 Session::findStubInfo(StringRef FileName
, StringRef TargetName
) {
308 auto FI
= findFileInfo(FileName
);
310 return FI
.takeError();
311 auto StubInfoItr
= FI
->StubInfos
.find(TargetName
);
312 if (StubInfoItr
== FI
->StubInfos
.end())
313 return make_error
<StringError
>("no stub for \"" + TargetName
+
314 "\" registered for file \"" + FileName
+
316 inconvertibleErrorCode());
317 return StubInfoItr
->second
;
320 Expected
<Session::MemoryRegionInfo
&>
321 Session::findGOTEntryInfo(StringRef FileName
, StringRef TargetName
) {
322 auto FI
= findFileInfo(FileName
);
324 return FI
.takeError();
325 auto GOTInfoItr
= FI
->GOTEntryInfos
.find(TargetName
);
326 if (GOTInfoItr
== FI
->GOTEntryInfos
.end())
327 return make_error
<StringError
>("no GOT entry for \"" + TargetName
+
328 "\" registered for file \"" + FileName
+
330 inconvertibleErrorCode());
331 return GOTInfoItr
->second
;
334 bool Session::isSymbolRegistered(StringRef SymbolName
) {
335 return SymbolInfos
.count(SymbolName
);
338 Expected
<Session::MemoryRegionInfo
&>
339 Session::findSymbolInfo(StringRef SymbolName
, Twine ErrorMsgStem
) {
340 auto SymInfoItr
= SymbolInfos
.find(SymbolName
);
341 if (SymInfoItr
== SymbolInfos
.end())
342 return make_error
<StringError
>(ErrorMsgStem
+ ": symbol " + SymbolName
+
344 inconvertibleErrorCode());
345 return SymInfoItr
->second
;
348 } // end namespace llvm
350 Triple
getFirstFileTriple() {
351 assert(!InputFiles
.empty() && "InputFiles can not be empty");
353 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFiles
.front())));
354 auto Obj
= ExitOnErr(
355 object::ObjectFile::createObjectFile(ObjBuffer
->getMemBufferRef()));
356 return Obj
->makeTriple();
359 Error
sanitizeArguments(const Session
&S
) {
360 if (EntryPointName
.empty()) {
361 if (S
.TT
.getObjectFormat() == Triple::MachO
)
362 EntryPointName
= "_main";
364 EntryPointName
= "main";
367 if (NoExec
&& !InputArgv
.empty())
368 outs() << "Warning: --args passed to -noexec run will be ignored.\n";
370 return Error::success();
373 Error
loadProcessSymbols(Session
&S
) {
375 if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr, &ErrMsg
))
376 return make_error
<StringError
>(std::move(ErrMsg
), inconvertibleErrorCode());
378 char GlobalPrefix
= S
.TT
.getObjectFormat() == Triple::MachO
? '_' : '\0';
379 auto InternedEntryPointName
= S
.ES
.intern(EntryPointName
);
380 auto FilterMainEntryPoint
= [InternedEntryPointName
](SymbolStringPtr Name
) {
381 return Name
!= InternedEntryPointName
;
383 S
.ES
.getMainJITDylib().setGenerator(
384 ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
385 GlobalPrefix
, FilterMainEntryPoint
)));
387 return Error::success();
391 // FIXME: This should all be handled inside DynamicLibrary.
392 for (const auto &Dylib
: Dylibs
) {
393 if (!sys::fs::is_regular_file(Dylib
))
394 return make_error
<StringError
>("\"" + Dylib
+ "\" is not a regular file",
395 inconvertibleErrorCode());
397 if (sys::DynamicLibrary::LoadLibraryPermanently(Dylib
.c_str(), &ErrMsg
))
398 return make_error
<StringError
>(ErrMsg
, inconvertibleErrorCode());
401 return Error::success();
404 Error
loadObjects(Session
&S
) {
406 std::map
<unsigned, JITDylib
*> IdxToJLD
;
408 // First, set up JITDylibs.
409 LLVM_DEBUG(dbgs() << "Creating JITDylibs...\n");
411 // Create a "main" JITLinkDylib.
412 auto &MainJD
= S
.ES
.getMainJITDylib();
413 IdxToJLD
[0] = &MainJD
;
414 S
.JDSearchOrder
.push_back(&MainJD
);
415 LLVM_DEBUG(dbgs() << " 0: " << MainJD
.getName() << "\n");
417 // Add any extra JITLinkDylibs from the command line.
418 std::string
JDNamePrefix("lib");
419 for (auto JLDItr
= JITLinkDylibs
.begin(), JLDEnd
= JITLinkDylibs
.end();
420 JLDItr
!= JLDEnd
; ++JLDItr
) {
421 auto &JD
= S
.ES
.createJITDylib(JDNamePrefix
+ *JLDItr
);
423 JITLinkDylibs
.getPosition(JLDItr
- JITLinkDylibs
.begin());
424 IdxToJLD
[JDIdx
] = &JD
;
425 S
.JDSearchOrder
.push_back(&JD
);
426 LLVM_DEBUG(dbgs() << " " << JDIdx
<< ": " << JD
.getName() << "\n");
429 // Set every dylib to link against every other, in command line order.
430 for (auto *JD
: S
.JDSearchOrder
) {
431 JITDylibSearchList O
;
432 for (auto *JD2
: S
.JDSearchOrder
) {
435 O
.push_back(std::make_pair(JD2
, false));
437 JD
->setSearchOrder(std::move(O
));
441 // Load each object into the corresponding JITDylib..
442 LLVM_DEBUG(dbgs() << "Adding objects...\n");
443 for (auto InputFileItr
= InputFiles
.begin(), InputFileEnd
= InputFiles
.end();
444 InputFileItr
!= InputFileEnd
; ++InputFileItr
) {
445 unsigned InputFileArgIdx
=
446 InputFiles
.getPosition(InputFileItr
- InputFiles
.begin());
447 StringRef InputFile
= *InputFileItr
;
448 auto &JD
= *std::prev(IdxToJLD
.lower_bound(InputFileArgIdx
))->second
;
449 LLVM_DEBUG(dbgs() << " " << InputFileArgIdx
<< ": \"" << InputFile
450 << "\" to " << JD
.getName() << "\n";);
452 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFile
)));
453 ExitOnErr(S
.ObjLayer
.add(JD
, std::move(ObjBuffer
)));
456 // Define absolute symbols.
457 LLVM_DEBUG(dbgs() << "Defining absolute symbols...\n");
458 for (auto AbsDefItr
= AbsoluteDefs
.begin(), AbsDefEnd
= AbsoluteDefs
.end();
459 AbsDefItr
!= AbsDefEnd
; ++AbsDefItr
) {
460 unsigned AbsDefArgIdx
=
461 AbsoluteDefs
.getPosition(AbsDefItr
- AbsoluteDefs
.begin());
462 auto &JD
= *std::prev(IdxToJLD
.lower_bound(AbsDefArgIdx
))->second
;
464 StringRef AbsDefStmt
= *AbsDefItr
;
465 size_t EqIdx
= AbsDefStmt
.find_first_of('=');
466 if (EqIdx
== StringRef::npos
)
467 return make_error
<StringError
>("Invalid absolute define \"" + AbsDefStmt
+
468 "\". Syntax: <name>=<addr>",
469 inconvertibleErrorCode());
470 StringRef Name
= AbsDefStmt
.substr(0, EqIdx
).trim();
471 StringRef AddrStr
= AbsDefStmt
.substr(EqIdx
+ 1).trim();
474 if (AddrStr
.getAsInteger(0, Addr
))
475 return make_error
<StringError
>("Invalid address expression \"" + AddrStr
+
476 "\" in absolute define \"" + AbsDefStmt
+
478 inconvertibleErrorCode());
479 JITEvaluatedSymbol
AbsDef(Addr
, JITSymbolFlags::Exported
);
480 if (auto Err
= JD
.define(absoluteSymbols({{S
.ES
.intern(Name
), AbsDef
}})))
483 // Register the absolute symbol with the session symbol infos.
484 S
.SymbolInfos
[Name
] = { StringRef(), Addr
};
488 dbgs() << "Dylib search order is [ ";
489 for (auto *JD
: S
.JDSearchOrder
)
490 dbgs() << JD
->getName() << " ";
494 return Error::success();
497 Error
runChecks(Session
&S
) {
499 auto TripleName
= S
.TT
.str();
500 std::string ErrorStr
;
501 const Target
*TheTarget
= TargetRegistry::lookupTarget("", S
.TT
, ErrorStr
);
503 ExitOnErr(make_error
<StringError
>("Error accessing target '" + TripleName
+
505 inconvertibleErrorCode()));
507 std::unique_ptr
<MCSubtargetInfo
> STI(
508 TheTarget
->createMCSubtargetInfo(TripleName
, "", ""));
511 make_error
<StringError
>("Unable to create subtarget for " + TripleName
,
512 inconvertibleErrorCode()));
514 std::unique_ptr
<MCRegisterInfo
> MRI(TheTarget
->createMCRegInfo(TripleName
));
516 ExitOnErr(make_error
<StringError
>("Unable to create target register info "
519 inconvertibleErrorCode()));
521 std::unique_ptr
<MCAsmInfo
> MAI(TheTarget
->createMCAsmInfo(*MRI
, TripleName
));
523 ExitOnErr(make_error
<StringError
>("Unable to create target asm info " +
525 inconvertibleErrorCode()));
527 MCContext
Ctx(MAI
.get(), MRI
.get(), nullptr);
529 std::unique_ptr
<MCDisassembler
> Disassembler(
530 TheTarget
->createMCDisassembler(*STI
, Ctx
));
532 ExitOnErr(make_error
<StringError
>("Unable to create disassembler for " +
534 inconvertibleErrorCode()));
536 std::unique_ptr
<MCInstrInfo
> MII(TheTarget
->createMCInstrInfo());
538 std::unique_ptr
<MCInstPrinter
> InstPrinter(
539 TheTarget
->createMCInstPrinter(Triple(TripleName
), 0, *MAI
, *MII
, *MRI
));
541 auto IsSymbolValid
= [&S
](StringRef Symbol
) {
542 return S
.isSymbolRegistered(Symbol
);
545 auto GetSymbolInfo
= [&S
](StringRef Symbol
) {
546 return S
.findSymbolInfo(Symbol
, "Can not get symbol info");
549 auto GetSectionInfo
= [&S
](StringRef FileName
, StringRef SectionName
) {
550 return S
.findSectionInfo(FileName
, SectionName
);
553 auto GetStubInfo
= [&S
](StringRef FileName
, StringRef SectionName
) {
554 return S
.findStubInfo(FileName
, SectionName
);
557 auto GetGOTInfo
= [&S
](StringRef FileName
, StringRef SectionName
) {
558 return S
.findGOTEntryInfo(FileName
, SectionName
);
561 RuntimeDyldChecker
Checker(
562 IsSymbolValid
, GetSymbolInfo
, GetSectionInfo
, GetStubInfo
, GetGOTInfo
,
563 S
.TT
.isLittleEndian() ? support::little
: support::big
,
564 Disassembler
.get(), InstPrinter
.get(), dbgs());
566 for (auto &CheckFile
: CheckFiles
) {
567 auto CheckerFileBuf
=
568 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(CheckFile
)));
569 if (!Checker
.checkAllRulesInBuffer("# jitlink-check:", &*CheckerFileBuf
))
570 ExitOnErr(make_error
<StringError
>(
571 "Some checks in " + CheckFile
+ " failed", inconvertibleErrorCode()));
574 return Error::success();
577 static void dumpSessionStats(Session
&S
) {
579 outs() << "Total size of all atoms before pruning: " << S
.SizeBeforePruning
580 << "\nTotal size of all atoms after fixups: " << S
.SizeAfterFixups
584 static Expected
<JITEvaluatedSymbol
> getMainEntryPoint(Session
&S
) {
585 return S
.ES
.lookup(S
.JDSearchOrder
, EntryPointName
);
588 Expected
<int> runEntryPoint(Session
&S
, JITEvaluatedSymbol EntryPoint
) {
589 assert(EntryPoint
.getAddress() && "Entry point address should not be null");
591 constexpr const char *JITProgramName
= "<llvm-jitlink jit'd code>";
592 auto PNStorage
= llvm::make_unique
<char[]>(strlen(JITProgramName
) + 1);
593 strcpy(PNStorage
.get(), JITProgramName
);
595 std::vector
<const char *> EntryPointArgs
;
596 EntryPointArgs
.push_back(PNStorage
.get());
597 for (auto &InputArg
: InputArgv
)
598 EntryPointArgs
.push_back(InputArg
.data());
599 EntryPointArgs
.push_back(nullptr);
601 using MainTy
= int (*)(int, const char *[]);
602 MainTy EntryPointPtr
= reinterpret_cast<MainTy
>(EntryPoint
.getAddress());
604 return EntryPointPtr(EntryPointArgs
.size() - 1, EntryPointArgs
.data());
607 int main(int argc
, char *argv
[]) {
608 InitLLVM
X(argc
, argv
);
610 InitializeAllTargetInfos();
611 InitializeAllTargetMCs();
612 InitializeAllDisassemblers();
614 cl::ParseCommandLineOptions(argc
, argv
, "llvm jitlink tool");
615 ExitOnErr
.setBanner(std::string(argv
[0]) + ": ");
617 Session
S(getFirstFileTriple());
619 ExitOnErr(sanitizeArguments(S
));
621 if (!NoProcessSymbols
)
622 ExitOnErr(loadProcessSymbols(S
));
623 ExitOnErr(loadDylibs());
625 ExitOnErr(loadObjects(S
));
627 auto EntryPoint
= ExitOnErr(getMainEntryPoint(S
));
630 S
.dumpSessionInfo(outs());
632 ExitOnErr(runChecks(S
));
639 return ExitOnErr(runEntryPoint(S
, EntryPoint
));