OSDN Git Service

android: ExecutionEngine/Orc: update sources list
[android-x86/external-llvm.git] / tools / llvm-jitlink / llvm-jitlink.cpp
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/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"
36
37 #include <list>
38 #include <string>
39
40 #define DEBUG_TYPE "llvm-jitlink"
41
42 using namespace llvm;
43 using namespace llvm::jitlink;
44 using namespace llvm::orc;
45
46 static cl::list<std::string> InputFiles(cl::Positional, cl::OneOrMore,
47                                         cl::desc("input files"));
48
49 static cl::opt<bool> NoExec("noexec", cl::desc("Do not execute loaded code"),
50                             cl::init(false));
51
52 static cl::list<std::string>
53     CheckFiles("check", cl::desc("File containing verifier checks"),
54                cl::ZeroOrMore);
55
56 static cl::opt<std::string>
57     EntryPointName("entry", cl::desc("Symbol to call as main entry point"),
58                    cl::init(""));
59
60 static cl::list<std::string> JITLinkDylibs(
61     "jld", cl::desc("Specifies the JITDylib to be used for any subsequent "
62                     "input file arguments"));
63
64 static cl::list<std::string>
65     Dylibs("dlopen", cl::desc("Dynamic libraries to load before linking"),
66            cl::ZeroOrMore);
67
68 static cl::list<std::string> InputArgv("args", cl::Positional,
69                                        cl::desc("<program arguments>..."),
70                                        cl::ZeroOrMore, cl::PositionalEatsArgs);
71
72 static cl::opt<bool>
73     NoProcessSymbols("no-process-syms",
74                      cl::desc("Do not resolve to llvm-jitlink process symbols"),
75                      cl::init(false));
76
77 static cl::list<std::string> AbsoluteDefs(
78     "define-abs",
79     cl::desc("Inject absolute symbol definitions (syntax: <name>=<addr>)"),
80     cl::ZeroOrMore);
81
82 static cl::opt<bool> ShowAddrs(
83     "show-addrs",
84     cl::desc("Print registered symbol, section, got and stub addresses"),
85     cl::init(false));
86
87 static cl::opt<bool> ShowAtomGraph(
88     "show-graph",
89     cl::desc("Print the atom graph after fixups have been applied"),
90     cl::init(false));
91
92 static cl::opt<bool> ShowSizes(
93     "show-sizes",
94     cl::desc("Show sizes pre- and post-dead stripping, and allocations"),
95     cl::init(false));
96
97 static cl::opt<bool> ShowRelocatedSectionContents(
98     "show-relocated-section-contents",
99     cl::desc("show section contents after fixups have been applied"),
100     cl::init(false));
101
102 ExitOnError ExitOnErr;
103
104 namespace llvm {
105
106 static raw_ostream &
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)";
113 }
114
115 static raw_ostream &
116 operator<<(raw_ostream &OS, const Session::SymbolInfoMap &SIM) {
117   OS << "Symbols:\n";
118   for (auto &SKV : SIM)
119     OS << "  \"" << SKV.first() << "\" " << SKV.second << "\n";
120   return OS;
121 }
122
123 static raw_ostream &
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";
131   return OS;
132 }
133
134 static raw_ostream &
135 operator<<(raw_ostream &OS, const Session::FileInfoMap &FIM) {
136   for (auto &FIKV : FIM)
137     OS << "File \"" << FIKV.first() << "\":\n" << FIKV.second;
138   return OS;
139 }
140
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();
146     else
147       TotalSize += DA->getContent().size();
148   return TotalSize;
149 }
150
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");
154
155   // Put sections in address order.
156   std::vector<Section *> Sections;
157   for (auto &S : G.sections())
158     Sections.push_back(&S);
159
160   std::sort(Sections.begin(), Sections.end(),
161             [](const Section *LHS, const Section *RHS) {
162               if (LHS->atoms_empty() && RHS->atoms_empty())
163                 return false;
164               if (LHS->atoms_empty())
165                 return false;
166               if (RHS->atoms_empty())
167                 return true;
168               return (*LHS->atoms().begin())->getAddress() <
169                      (*RHS->atoms().begin())->getAddress();
170             });
171
172   for (auto *S : Sections) {
173     OS << S->getName() << " content:";
174     if (S->atoms_empty()) {
175       OS << "\n  section empty\n";
176       continue;
177     }
178
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();
184               });
185
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();
195
196       // Pad any space before the atom starts.
197       while (NextAddr != AtomStart) {
198         if (NextAddr % DumpWidth == 0)
199           OS << formatv("\n{0:x16}:", NextAddr);
200         OS << "   ";
201         ++NextAddr;
202       }
203
204       // Render the atom content.
205       while (NextAddr != AtomEnd) {
206         if (NextAddr % DumpWidth == 0)
207           OS << formatv("\n{0:x16}:", NextAddr);
208         if (IsZeroFill)
209           OS << " 00";
210         else
211           OS << formatv(" {0:x-2}", AtomData[NextAddr - AtomStart]);
212         ++NextAddr;
213       }
214     }
215     OS << "\n";
216   }
217 }
218
219 Session::Session(Triple TT) : ObjLayer(ES, MemMgr), TT(std::move(TT)) {
220
221   /// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig to the
222   /// Session.
223   class JITLinkSessionPlugin : public ObjectLinkingLayer::Plugin {
224   public:
225     JITLinkSessionPlugin(Session &S) : S(S) {}
226     void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
227                           PassConfiguration &PassConfig) {
228       S.modifyPassConfig(TT, PassConfig);
229     }
230
231   private:
232     Session &S;
233   };
234
235   if (!NoExec && !TT.isOSWindows())
236     ObjLayer.addPlugin(llvm::make_unique<EHFrameRegistrationPlugin>(
237         InProcessEHFrameRegistrar::getInstance()));
238
239   ObjLayer.addPlugin(llvm::make_unique<JITLinkSessionPlugin>(*this));
240 }
241
242 void Session::dumpSessionInfo(raw_ostream &OS) {
243   OS << "Registered addresses:\n" << SymbolInfos << FileInfos;
244 }
245
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 "
253                                      "registration",
254                                      inconvertibleErrorCode());
255     });
256
257   if (ShowAtomGraph)
258     PassConfig.PostFixupPasses.push_back([](AtomGraph &G) -> Error {
259       outs() << "Atom graph post-fixup:\n";
260       G.dump(outs());
261       return Error::success();
262     });
263
264
265   if (ShowSizes) {
266     PassConfig.PrePrunePasses.push_back([this](AtomGraph &G) -> Error {
267         SizeBeforePruning += computeTotalAtomSizes(G);
268         return Error::success();
269       });
270     PassConfig.PostFixupPasses.push_back([this](AtomGraph &G) -> Error {
271         SizeAfterFixups += computeTotalAtomSizes(G);
272         return Error::success();
273       });
274   }
275
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();
281     });
282 }
283
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;
290 }
291
292 Expected<Session::MemoryRegionInfo &>
293 Session::findSectionInfo(StringRef FileName, StringRef SectionName) {
294   auto FI = findFileInfo(FileName);
295   if (!FI)
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 +
301                                        "\"",
302                                    inconvertibleErrorCode());
303   return SecInfoItr->second;
304 }
305
306 Expected<Session::MemoryRegionInfo &>
307 Session::findStubInfo(StringRef FileName, StringRef TargetName) {
308   auto FI = findFileInfo(FileName);
309   if (!FI)
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 +
315                                        "\"",
316                                    inconvertibleErrorCode());
317   return StubInfoItr->second;
318 }
319
320 Expected<Session::MemoryRegionInfo &>
321 Session::findGOTEntryInfo(StringRef FileName, StringRef TargetName) {
322   auto FI = findFileInfo(FileName);
323   if (!FI)
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 +
329                                        "\"",
330                                    inconvertibleErrorCode());
331   return GOTInfoItr->second;
332 }
333
334 bool Session::isSymbolRegistered(StringRef SymbolName) {
335   return SymbolInfos.count(SymbolName);
336 }
337
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 +
343                                        " not found",
344                                    inconvertibleErrorCode());
345   return SymInfoItr->second;
346 }
347
348 } // end namespace llvm
349
350 Triple getFirstFileTriple() {
351   assert(!InputFiles.empty() && "InputFiles can not be empty");
352   auto ObjBuffer =
353       ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFiles.front())));
354   auto Obj = ExitOnErr(
355       object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()));
356   return Obj->makeTriple();
357 }
358
359 Error sanitizeArguments(const Session &S) {
360   if (EntryPointName.empty()) {
361     if (S.TT.getObjectFormat() == Triple::MachO)
362       EntryPointName = "_main";
363     else
364       EntryPointName = "main";
365   }
366
367   if (NoExec && !InputArgv.empty())
368     outs() << "Warning: --args passed to -noexec run will be ignored.\n";
369
370   return Error::success();
371 }
372
373 Error loadProcessSymbols(Session &S) {
374   std::string ErrMsg;
375   if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr, &ErrMsg))
376     return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
377
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;
382   };
383   S.ES.getMainJITDylib().setGenerator(
384       ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
385           GlobalPrefix, FilterMainEntryPoint)));
386
387   return Error::success();
388 }
389
390 Error loadDylibs() {
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());
396     std::string ErrMsg;
397     if (sys::DynamicLibrary::LoadLibraryPermanently(Dylib.c_str(), &ErrMsg))
398       return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
399   }
400
401   return Error::success();
402 }
403
404 Error loadObjects(Session &S) {
405
406   std::map<unsigned, JITDylib *> IdxToJLD;
407
408   // First, set up JITDylibs.
409   LLVM_DEBUG(dbgs() << "Creating JITDylibs...\n");
410   {
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");
416
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);
422       unsigned JDIdx =
423           JITLinkDylibs.getPosition(JLDItr - JITLinkDylibs.begin());
424       IdxToJLD[JDIdx] = &JD;
425       S.JDSearchOrder.push_back(&JD);
426       LLVM_DEBUG(dbgs() << "  " << JDIdx << ": " << JD.getName() << "\n");
427     }
428
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) {
433         if (JD2 == JD)
434           continue;
435         O.push_back(std::make_pair(JD2, false));
436       }
437       JD->setSearchOrder(std::move(O));
438     }
439   }
440
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";);
451     auto ObjBuffer =
452         ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFile)));
453     ExitOnErr(S.ObjLayer.add(JD, std::move(ObjBuffer)));
454   }
455
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;
463
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();
472
473     uint64_t Addr;
474     if (AddrStr.getAsInteger(0, Addr))
475       return make_error<StringError>("Invalid address expression \"" + AddrStr +
476                                      "\" in absolute define \"" + AbsDefStmt +
477                                      "\"",
478                                      inconvertibleErrorCode());
479     JITEvaluatedSymbol AbsDef(Addr, JITSymbolFlags::Exported);
480     if (auto Err = JD.define(absoluteSymbols({{S.ES.intern(Name), AbsDef}})))
481       return Err;
482
483     // Register the absolute symbol with the session symbol infos.
484     S.SymbolInfos[Name] = { StringRef(), Addr };
485   }
486
487   LLVM_DEBUG({
488     dbgs() << "Dylib search order is [ ";
489     for (auto *JD : S.JDSearchOrder)
490       dbgs() << JD->getName() << " ";
491     dbgs() << "]\n";
492   });
493
494   return Error::success();
495 }
496
497 Error runChecks(Session &S) {
498
499   auto TripleName = S.TT.str();
500   std::string ErrorStr;
501   const Target *TheTarget = TargetRegistry::lookupTarget("", S.TT, ErrorStr);
502   if (!TheTarget)
503     ExitOnErr(make_error<StringError>("Error accessing target '" + TripleName +
504                                           "': " + ErrorStr,
505                                       inconvertibleErrorCode()));
506
507   std::unique_ptr<MCSubtargetInfo> STI(
508       TheTarget->createMCSubtargetInfo(TripleName, "", ""));
509   if (!STI)
510     ExitOnErr(
511         make_error<StringError>("Unable to create subtarget for " + TripleName,
512                                 inconvertibleErrorCode()));
513
514   std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
515   if (!MRI)
516     ExitOnErr(make_error<StringError>("Unable to create target register info "
517                                       "for " +
518                                           TripleName,
519                                       inconvertibleErrorCode()));
520
521   std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName));
522   if (!MAI)
523     ExitOnErr(make_error<StringError>("Unable to create target asm info " +
524                                           TripleName,
525                                       inconvertibleErrorCode()));
526
527   MCContext Ctx(MAI.get(), MRI.get(), nullptr);
528
529   std::unique_ptr<MCDisassembler> Disassembler(
530       TheTarget->createMCDisassembler(*STI, Ctx));
531   if (!Disassembler)
532     ExitOnErr(make_error<StringError>("Unable to create disassembler for " +
533                                           TripleName,
534                                       inconvertibleErrorCode()));
535
536   std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
537
538   std::unique_ptr<MCInstPrinter> InstPrinter(
539       TheTarget->createMCInstPrinter(Triple(TripleName), 0, *MAI, *MII, *MRI));
540
541   auto IsSymbolValid = [&S](StringRef Symbol) {
542     return S.isSymbolRegistered(Symbol);
543   };
544
545   auto GetSymbolInfo = [&S](StringRef Symbol) {
546     return S.findSymbolInfo(Symbol, "Can not get symbol info");
547   };
548
549   auto GetSectionInfo = [&S](StringRef FileName, StringRef SectionName) {
550     return S.findSectionInfo(FileName, SectionName);
551   };
552
553   auto GetStubInfo = [&S](StringRef FileName, StringRef SectionName) {
554     return S.findStubInfo(FileName, SectionName);
555   };
556
557   auto GetGOTInfo = [&S](StringRef FileName, StringRef SectionName) {
558     return S.findGOTEntryInfo(FileName, SectionName);
559   };
560
561   RuntimeDyldChecker Checker(
562       IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo, GetGOTInfo,
563       S.TT.isLittleEndian() ? support::little : support::big,
564       Disassembler.get(), InstPrinter.get(), dbgs());
565
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()));
572   }
573
574   return Error::success();
575 }
576
577 static void dumpSessionStats(Session &S) {
578   if (ShowSizes)
579     outs() << "Total size of all atoms before pruning: " << S.SizeBeforePruning
580            << "\nTotal size of all atoms after fixups: " << S.SizeAfterFixups
581            << "\n";
582 }
583
584 static Expected<JITEvaluatedSymbol> getMainEntryPoint(Session &S) {
585   return S.ES.lookup(S.JDSearchOrder, EntryPointName);
586 }
587
588 Expected<int> runEntryPoint(Session &S, JITEvaluatedSymbol EntryPoint) {
589   assert(EntryPoint.getAddress() && "Entry point address should not be null");
590
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);
594
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);
600
601   using MainTy = int (*)(int, const char *[]);
602   MainTy EntryPointPtr = reinterpret_cast<MainTy>(EntryPoint.getAddress());
603
604   return EntryPointPtr(EntryPointArgs.size() - 1, EntryPointArgs.data());
605 }
606
607 int main(int argc, char *argv[]) {
608   InitLLVM X(argc, argv);
609
610   InitializeAllTargetInfos();
611   InitializeAllTargetMCs();
612   InitializeAllDisassemblers();
613
614   cl::ParseCommandLineOptions(argc, argv, "llvm jitlink tool");
615   ExitOnErr.setBanner(std::string(argv[0]) + ": ");
616
617   Session S(getFirstFileTriple());
618
619   ExitOnErr(sanitizeArguments(S));
620
621   if (!NoProcessSymbols)
622     ExitOnErr(loadProcessSymbols(S));
623   ExitOnErr(loadDylibs());
624
625   ExitOnErr(loadObjects(S));
626
627   auto EntryPoint = ExitOnErr(getMainEntryPoint(S));
628
629   if (ShowAddrs)
630     S.dumpSessionInfo(outs());
631
632   ExitOnErr(runChecks(S));
633
634   dumpSessionStats(S);
635
636   if (NoExec)
637     return 0;
638
639   return ExitOnErr(runEntryPoint(S, EntryPoint));
640 }