blob: 9058a7907b0f9ebc4f18490f0cf0fda38bbe7127 [file] [log] [blame]
Lang Hames11c8dfa52019-04-20 17:10:34 +00001//===- 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
Lang Hamesf5a885f2019-07-04 00:05:12 +000017#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
Lang Hames11c8dfa52019-04-20 17:10:34 +000018#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"
Mirko Brkusanin4b63ca12019-10-23 12:24:35 +020026#include "llvm/MC/MCTargetOptions.h"
Lang Hames11c8dfa52019-04-20 17:10:34 +000027#include "llvm/Object/COFF.h"
28#include "llvm/Object/MachO.h"
29#include "llvm/Object/ObjectFile.h"
30#include "llvm/Support/CommandLine.h"
31#include "llvm/Support/Debug.h"
32#include "llvm/Support/DynamicLibrary.h"
33#include "llvm/Support/InitLLVM.h"
34#include "llvm/Support/MemoryBuffer.h"
Lang Hames335676e2019-09-06 19:21:55 +000035#include "llvm/Support/Process.h"
Lang Hames11c8dfa52019-04-20 17:10:34 +000036#include "llvm/Support/TargetRegistry.h"
37#include "llvm/Support/TargetSelect.h"
Lang Hames6fd39602019-08-27 15:51:19 +000038#include "llvm/Support/Timer.h"
Lang Hames11c8dfa52019-04-20 17:10:34 +000039
40#include <list>
41#include <string>
42
Lang Hames66128c42020-03-01 09:34:31 -080043#define DEBUG_TYPE "llvm_jitlink"
Lang Hames11c8dfa52019-04-20 17:10:34 +000044
45using namespace llvm;
46using namespace llvm::jitlink;
47using namespace llvm::orc;
48
49static cl::list<std::string> InputFiles(cl::Positional, cl::OneOrMore,
50 cl::desc("input files"));
51
52static cl::opt<bool> NoExec("noexec", cl::desc("Do not execute loaded code"),
53 cl::init(false));
54
55static cl::list<std::string>
56 CheckFiles("check", cl::desc("File containing verifier checks"),
57 cl::ZeroOrMore);
58
59static cl::opt<std::string>
Lang Hames674df132019-11-25 21:57:27 -080060 CheckName("check-name", cl::desc("Name of checks to match against"),
61 cl::init("jitlink-check"));
62
63static cl::opt<std::string>
Lang Hames11c8dfa52019-04-20 17:10:34 +000064 EntryPointName("entry", cl::desc("Symbol to call as main entry point"),
65 cl::init(""));
66
67static cl::list<std::string> JITLinkDylibs(
68 "jld", cl::desc("Specifies the JITDylib to be used for any subsequent "
69 "input file arguments"));
70
71static cl::list<std::string>
72 Dylibs("dlopen", cl::desc("Dynamic libraries to load before linking"),
73 cl::ZeroOrMore);
74
Lang Hamesd959a602019-04-24 17:23:05 +000075static cl::list<std::string> InputArgv("args", cl::Positional,
76 cl::desc("<program arguments>..."),
77 cl::ZeroOrMore, cl::PositionalEatsArgs);
78
Lang Hames11c8dfa52019-04-20 17:10:34 +000079static cl::opt<bool>
80 NoProcessSymbols("no-process-syms",
81 cl::desc("Do not resolve to llvm-jitlink process symbols"),
82 cl::init(false));
83
Nico Weber405e62b2019-04-21 23:50:24 +000084static cl::list<std::string> AbsoluteDefs(
85 "define-abs",
86 cl::desc("Inject absolute symbol definitions (syntax: <name>=<addr>)"),
87 cl::ZeroOrMore);
Lang Hames11c8dfa52019-04-20 17:10:34 +000088
Lang Hamesf75e04b2020-03-14 16:07:46 -070089static cl::opt<bool> ShowInitialExecutionSessionState(
90 "show-init-es",
91 cl::desc("Print ExecutionSession state before resolving entry point"),
92 cl::init(false));
93
Lang Hames11c8dfa52019-04-20 17:10:34 +000094static cl::opt<bool> ShowAddrs(
95 "show-addrs",
96 cl::desc("Print registered symbol, section, got and stub addresses"),
97 cl::init(false));
98
Lang Hames4e920e52019-10-04 03:55:26 +000099static cl::opt<bool> ShowLinkGraph(
Lang Hames11c8dfa52019-04-20 17:10:34 +0000100 "show-graph",
Lang Hames4e920e52019-10-04 03:55:26 +0000101 cl::desc("Print the link graph after fixups have been applied"),
Lang Hames11c8dfa52019-04-20 17:10:34 +0000102 cl::init(false));
103
104static cl::opt<bool> ShowSizes(
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000105 "show-sizes",
106 cl::desc("Show sizes pre- and post-dead stripping, and allocations"),
107 cl::init(false));
108
Lang Hames6fd39602019-08-27 15:51:19 +0000109static cl::opt<bool> ShowTimes("show-times",
110 cl::desc("Show times for llvm-jitlink phases"),
111 cl::init(false));
112
Lang Hames335676e2019-09-06 19:21:55 +0000113static cl::opt<std::string> SlabAllocateSizeString(
114 "slab-allocate",
115 cl::desc("Allocate from a slab of the given size "
116 "(allowable suffixes: Kb, Mb, Gb. default = "
117 "Kb)"),
118 cl::init(""));
119
Lang Hames14ac84e2020-03-03 14:18:12 -0800120static cl::opt<uint64_t> SlabAddress(
121 "slab-address",
122 cl::desc("Set slab target address (requires -slab-allocate and -noexec)"),
123 cl::init(~0ULL));
124
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000125static cl::opt<bool> ShowRelocatedSectionContents(
126 "show-relocated-section-contents",
127 cl::desc("show section contents after fixups have been applied"),
128 cl::init(false));
Lang Hames11c8dfa52019-04-20 17:10:34 +0000129
130ExitOnError ExitOnErr;
131
132namespace llvm {
133
134static raw_ostream &
135operator<<(raw_ostream &OS, const Session::MemoryRegionInfo &MRI) {
Lang Hames23085ec2019-05-12 22:26:33 +0000136 return OS << "target addr = "
137 << format("0x%016" PRIx64, MRI.getTargetAddress())
138 << ", content: " << (const void *)MRI.getContent().data() << " -- "
139 << (const void *)(MRI.getContent().data() + MRI.getContent().size())
140 << " (" << MRI.getContent().size() << " bytes)";
Lang Hames11c8dfa52019-04-20 17:10:34 +0000141}
142
143static raw_ostream &
144operator<<(raw_ostream &OS, const Session::SymbolInfoMap &SIM) {
145 OS << "Symbols:\n";
146 for (auto &SKV : SIM)
147 OS << " \"" << SKV.first() << "\" " << SKV.second << "\n";
148 return OS;
149}
150
151static raw_ostream &
152operator<<(raw_ostream &OS, const Session::FileInfo &FI) {
153 for (auto &SIKV : FI.SectionInfos)
154 OS << " Section \"" << SIKV.first() << "\": " << SIKV.second << "\n";
155 for (auto &GOTKV : FI.GOTEntryInfos)
156 OS << " GOT \"" << GOTKV.first() << "\": " << GOTKV.second << "\n";
157 for (auto &StubKV : FI.StubInfos)
158 OS << " Stub \"" << StubKV.first() << "\": " << StubKV.second << "\n";
159 return OS;
160}
161
162static raw_ostream &
163operator<<(raw_ostream &OS, const Session::FileInfoMap &FIM) {
164 for (auto &FIKV : FIM)
165 OS << "File \"" << FIKV.first() << "\":\n" << FIKV.second;
166 return OS;
167}
168
Lang Hames4e920e52019-10-04 03:55:26 +0000169static uint64_t computeTotalBlockSizes(LinkGraph &G) {
Lang Hames11c8dfa52019-04-20 17:10:34 +0000170 uint64_t TotalSize = 0;
Lang Hames4e920e52019-10-04 03:55:26 +0000171 for (auto *B : G.blocks())
172 TotalSize += B->getSize();
Lang Hames11c8dfa52019-04-20 17:10:34 +0000173 return TotalSize;
174}
175
Lang Hames4e920e52019-10-04 03:55:26 +0000176static void dumpSectionContents(raw_ostream &OS, LinkGraph &G) {
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000177 constexpr JITTargetAddress DumpWidth = 16;
178 static_assert(isPowerOf2_64(DumpWidth), "DumpWidth must be a power of two");
179
180 // Put sections in address order.
181 std::vector<Section *> Sections;
182 for (auto &S : G.sections())
183 Sections.push_back(&S);
184
185 std::sort(Sections.begin(), Sections.end(),
186 [](const Section *LHS, const Section *RHS) {
Lang Hames8c4f0482019-12-05 19:57:51 -0800187 if (llvm::empty(LHS->symbols()) && llvm::empty(RHS->symbols()))
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000188 return false;
Lang Hames8c4f0482019-12-05 19:57:51 -0800189 if (llvm::empty(LHS->symbols()))
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000190 return false;
Lang Hames8c4f0482019-12-05 19:57:51 -0800191 if (llvm::empty(RHS->symbols()))
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000192 return true;
Lang Hames4e920e52019-10-04 03:55:26 +0000193 SectionRange LHSRange(*LHS);
194 SectionRange RHSRange(*RHS);
195 return LHSRange.getStart() < RHSRange.getStart();
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000196 });
197
198 for (auto *S : Sections) {
199 OS << S->getName() << " content:";
Lang Hames8c4f0482019-12-05 19:57:51 -0800200 if (llvm::empty(S->symbols())) {
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000201 OS << "\n section empty\n";
202 continue;
203 }
204
Lang Hames4e920e52019-10-04 03:55:26 +0000205 // Sort symbols into order, then render.
206 std::vector<Symbol *> Syms(S->symbols().begin(), S->symbols().end());
207 llvm::sort(Syms, [](const Symbol *LHS, const Symbol *RHS) {
208 return LHS->getAddress() < RHS->getAddress();
209 });
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000210
Lang Hames4e920e52019-10-04 03:55:26 +0000211 JITTargetAddress NextAddr = Syms.front()->getAddress() & ~(DumpWidth - 1);
212 for (auto *Sym : Syms) {
213 bool IsZeroFill = Sym->getBlock().isZeroFill();
214 JITTargetAddress SymStart = Sym->getAddress();
215 JITTargetAddress SymSize = Sym->getSize();
216 JITTargetAddress SymEnd = SymStart + SymSize;
217 const uint8_t *SymData =
218 IsZeroFill ? nullptr : Sym->getSymbolContent().bytes_begin();
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000219
Lang Hames4e920e52019-10-04 03:55:26 +0000220 // Pad any space before the symbol starts.
221 while (NextAddr != SymStart) {
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000222 if (NextAddr % DumpWidth == 0)
223 OS << formatv("\n{0:x16}:", NextAddr);
224 OS << " ";
225 ++NextAddr;
226 }
227
Lang Hames4e920e52019-10-04 03:55:26 +0000228 // Render the symbol content.
229 while (NextAddr != SymEnd) {
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000230 if (NextAddr % DumpWidth == 0)
231 OS << formatv("\n{0:x16}:", NextAddr);
232 if (IsZeroFill)
233 OS << " 00";
234 else
Lang Hames4e920e52019-10-04 03:55:26 +0000235 OS << formatv(" {0:x-2}", SymData[NextAddr - SymStart]);
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000236 ++NextAddr;
237 }
238 }
239 OS << "\n";
240 }
241}
242
Lang Hames335676e2019-09-06 19:21:55 +0000243class JITLinkSlabAllocator final : public JITLinkMemoryManager {
244public:
245 static Expected<std::unique_ptr<JITLinkSlabAllocator>>
246 Create(uint64_t SlabSize) {
247 Error Err = Error::success();
248 std::unique_ptr<JITLinkSlabAllocator> Allocator(
249 new JITLinkSlabAllocator(SlabSize, Err));
250 if (Err)
Bill Wendlingc55cf4a2020-02-10 07:06:45 -0800251 return std::move(Err);
252 return std::move(Allocator);
Lang Hames335676e2019-09-06 19:21:55 +0000253 }
254
255 Expected<std::unique_ptr<JITLinkMemoryManager::Allocation>>
256 allocate(const SegmentsRequestMap &Request) override {
257
258 using AllocationMap = DenseMap<unsigned, sys::MemoryBlock>;
259
260 // Local class for allocation.
261 class IPMMAlloc : public Allocation {
262 public:
Lang Hames14ac84e2020-03-03 14:18:12 -0800263 IPMMAlloc(JITLinkSlabAllocator &Parent, AllocationMap SegBlocks)
264 : Parent(Parent), SegBlocks(std::move(SegBlocks)) {}
Lang Hames335676e2019-09-06 19:21:55 +0000265 MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) override {
266 assert(SegBlocks.count(Seg) && "No allocation for segment");
267 return {static_cast<char *>(SegBlocks[Seg].base()),
268 SegBlocks[Seg].allocatedSize()};
269 }
270 JITTargetAddress getTargetMemory(ProtectionFlags Seg) override {
271 assert(SegBlocks.count(Seg) && "No allocation for segment");
Lang Hames14ac84e2020-03-03 14:18:12 -0800272 return pointerToJITTargetAddress(SegBlocks[Seg].base()) +
273 Parent.TargetDelta;
Lang Hames335676e2019-09-06 19:21:55 +0000274 }
275 void finalizeAsync(FinalizeContinuation OnFinalize) override {
276 OnFinalize(applyProtections());
277 }
278 Error deallocate() override {
279 for (auto &KV : SegBlocks)
280 if (auto EC = sys::Memory::releaseMappedMemory(KV.second))
281 return errorCodeToError(EC);
282 return Error::success();
283 }
284
285 private:
286 Error applyProtections() {
287 for (auto &KV : SegBlocks) {
288 auto &Prot = KV.first;
289 auto &Block = KV.second;
290 if (auto EC = sys::Memory::protectMappedMemory(Block, Prot))
291 return errorCodeToError(EC);
292 if (Prot & sys::Memory::MF_EXEC)
293 sys::Memory::InvalidateInstructionCache(Block.base(),
294 Block.allocatedSize());
295 }
296 return Error::success();
297 }
298
Lang Hames14ac84e2020-03-03 14:18:12 -0800299 JITLinkSlabAllocator &Parent;
Lang Hames335676e2019-09-06 19:21:55 +0000300 AllocationMap SegBlocks;
301 };
302
303 AllocationMap Blocks;
304
305 for (auto &KV : Request) {
306 auto &Seg = KV.second;
307
Lang Hames4e920e52019-10-04 03:55:26 +0000308 if (Seg.getAlignment() > PageSize)
Lang Hames335676e2019-09-06 19:21:55 +0000309 return make_error<StringError>("Cannot request higher than page "
310 "alignment",
311 inconvertibleErrorCode());
312
Lang Hames4e920e52019-10-04 03:55:26 +0000313 if (PageSize % Seg.getAlignment() != 0)
Lang Hames335676e2019-09-06 19:21:55 +0000314 return make_error<StringError>("Page size is not a multiple of "
315 "alignment",
316 inconvertibleErrorCode());
317
Lang Hames4e920e52019-10-04 03:55:26 +0000318 uint64_t ZeroFillStart = Seg.getContentSize();
Lang Hames335676e2019-09-06 19:21:55 +0000319 uint64_t SegmentSize = ZeroFillStart + Seg.getZeroFillSize();
320
321 // Round segment size up to page boundary.
322 SegmentSize = (SegmentSize + PageSize - 1) & ~(PageSize - 1);
323
324 // Take segment bytes from the front of the slab.
325 void *SlabBase = SlabRemaining.base();
326 uint64_t SlabRemainingSize = SlabRemaining.allocatedSize();
327
328 if (SegmentSize > SlabRemainingSize)
329 return make_error<StringError>("Slab allocator out of memory",
330 inconvertibleErrorCode());
331
332 sys::MemoryBlock SegMem(SlabBase, SegmentSize);
333 SlabRemaining =
334 sys::MemoryBlock(reinterpret_cast<char *>(SlabBase) + SegmentSize,
335 SlabRemainingSize - SegmentSize);
336
337 // Zero out the zero-fill memory.
338 memset(static_cast<char *>(SegMem.base()) + ZeroFillStart, 0,
339 Seg.getZeroFillSize());
340
341 // Record the block for this segment.
342 Blocks[KV.first] = std::move(SegMem);
343 }
344 return std::unique_ptr<InProcessMemoryManager::Allocation>(
Lang Hames14ac84e2020-03-03 14:18:12 -0800345 new IPMMAlloc(*this, std::move(Blocks)));
Lang Hames335676e2019-09-06 19:21:55 +0000346 }
347
348private:
349 JITLinkSlabAllocator(uint64_t SlabSize, Error &Err) {
350 ErrorAsOutParameter _(&Err);
351
352 PageSize = sys::Process::getPageSizeEstimate();
353
354 if (!isPowerOf2_64(PageSize)) {
355 Err = make_error<StringError>("Page size is not a power of 2",
356 inconvertibleErrorCode());
357 return;
358 }
359
360 // Round slab request up to page size.
361 SlabSize = (SlabSize + PageSize - 1) & ~(PageSize - 1);
362
363 const sys::Memory::ProtectionFlags ReadWrite =
364 static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
365 sys::Memory::MF_WRITE);
366
367 std::error_code EC;
368 SlabRemaining =
369 sys::Memory::allocateMappedMemory(SlabSize, nullptr, ReadWrite, EC);
370
371 if (EC) {
372 Err = errorCodeToError(EC);
373 return;
374 }
Lang Hames14ac84e2020-03-03 14:18:12 -0800375
376 // Calculate the target address delta to link as-if slab were at
377 // SlabAddress.
378 if (SlabAddress != ~0ULL)
379 TargetDelta =
380 SlabAddress - pointerToJITTargetAddress(SlabRemaining.base());
Lang Hames335676e2019-09-06 19:21:55 +0000381 }
382
383 sys::MemoryBlock SlabRemaining;
384 uint64_t PageSize = 0;
Lang Hames14ac84e2020-03-03 14:18:12 -0800385 int64_t TargetDelta = 0;
Lang Hames335676e2019-09-06 19:21:55 +0000386};
387
388Expected<uint64_t> getSlabAllocSize(StringRef SizeString) {
389 SizeString = SizeString.trim();
390
391 uint64_t Units = 1024;
392
393 if (SizeString.endswith_lower("kb"))
394 SizeString = SizeString.drop_back(2).rtrim();
395 else if (SizeString.endswith_lower("mb")) {
396 Units = 1024 * 1024;
397 SizeString = SizeString.drop_back(2).rtrim();
398 } else if (SizeString.endswith_lower("gb")) {
399 Units = 1024 * 1024 * 1024;
400 SizeString = SizeString.drop_back(2).rtrim();
401 }
402
403 uint64_t SlabSize = 0;
404 if (SizeString.getAsInteger(10, SlabSize))
405 return make_error<StringError>("Invalid numeric format for slab size",
406 inconvertibleErrorCode());
407
408 return SlabSize * Units;
409}
410
411static std::unique_ptr<jitlink::JITLinkMemoryManager> createMemoryManager() {
412 if (!SlabAllocateSizeString.empty()) {
413 auto SlabSize = ExitOnErr(getSlabAllocSize(SlabAllocateSizeString));
414 return ExitOnErr(JITLinkSlabAllocator::Create(SlabSize));
415 }
416 return std::make_unique<jitlink::InProcessMemoryManager>();
417}
418
Lang Hames85fb9972019-12-16 02:50:40 -0800419Expected<std::unique_ptr<Session>> Session::Create(Triple TT) {
420 Error Err = Error::success();
421 std::unique_ptr<Session> S(new Session(std::move(TT), Err));
422 if (Err)
423 return std::move(Err);
424 return std::move(S);
425}
426
427// FIXME: Move to createJITDylib if/when we start using Platform support in
428// llvm-jitlink.
429Session::Session(Triple TT, Error &Err)
430 : ObjLayer(ES, createMemoryManager()), TT(std::move(TT)) {
Lang Hamesa9fdf372019-04-26 22:58:39 +0000431
432 /// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig to the
433 /// Session.
434 class JITLinkSessionPlugin : public ObjectLinkingLayer::Plugin {
435 public:
436 JITLinkSessionPlugin(Session &S) : S(S) {}
437 void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
438 PassConfiguration &PassConfig) {
439 S.modifyPassConfig(TT, PassConfig);
440 }
441
442 private:
443 Session &S;
444 };
445
Lang Hames85fb9972019-12-16 02:50:40 -0800446 ErrorAsOutParameter _(&Err);
447
448 if (auto MainJDOrErr = ES.createJITDylib("main"))
449 MainJD = &*MainJDOrErr;
450 else {
451 Err = MainJDOrErr.takeError();
452 return;
453 }
454
Lang Hamesa9fdf372019-04-26 22:58:39 +0000455 if (!NoExec && !TT.isOSWindows())
Jonas Devlieghere0eaee542019-08-15 15:54:37 +0000456 ObjLayer.addPlugin(std::make_unique<EHFrameRegistrationPlugin>(
Lang Hamesf5a885f2019-07-04 00:05:12 +0000457 InProcessEHFrameRegistrar::getInstance()));
Lang Hamesa9fdf372019-04-26 22:58:39 +0000458
Jonas Devlieghere0eaee542019-08-15 15:54:37 +0000459 ObjLayer.addPlugin(std::make_unique<JITLinkSessionPlugin>(*this));
Lang Hamesa9fdf372019-04-26 22:58:39 +0000460}
Lang Hames11c8dfa52019-04-20 17:10:34 +0000461
462void Session::dumpSessionInfo(raw_ostream &OS) {
463 OS << "Registered addresses:\n" << SymbolInfos << FileInfos;
464}
465
466void Session::modifyPassConfig(const Triple &FTT,
467 PassConfiguration &PassConfig) {
468 if (!CheckFiles.empty())
Lang Hames4e920e52019-10-04 03:55:26 +0000469 PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) {
Lang Hames11c8dfa52019-04-20 17:10:34 +0000470 if (TT.getObjectFormat() == Triple::MachO)
471 return registerMachOStubsAndGOT(*this, G);
472 return make_error<StringError>("Unsupported object format for GOT/stub "
473 "registration",
474 inconvertibleErrorCode());
475 });
476
Lang Hames4e920e52019-10-04 03:55:26 +0000477 if (ShowLinkGraph)
478 PassConfig.PostFixupPasses.push_back([](LinkGraph &G) -> Error {
479 outs() << "Link graph post-fixup:\n";
Lang Hames11c8dfa52019-04-20 17:10:34 +0000480 G.dump(outs());
481 return Error::success();
482 });
483
Lang Hames11c8dfa52019-04-20 17:10:34 +0000484 if (ShowSizes) {
Lang Hames4e920e52019-10-04 03:55:26 +0000485 PassConfig.PrePrunePasses.push_back([this](LinkGraph &G) -> Error {
486 SizeBeforePruning += computeTotalBlockSizes(G);
487 return Error::success();
488 });
489 PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) -> Error {
490 SizeAfterFixups += computeTotalBlockSizes(G);
491 return Error::success();
492 });
Lang Hames11c8dfa52019-04-20 17:10:34 +0000493 }
494
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000495 if (ShowRelocatedSectionContents)
Lang Hames4e920e52019-10-04 03:55:26 +0000496 PassConfig.PostFixupPasses.push_back([](LinkGraph &G) -> Error {
Lang Hamesbc76bbc2019-04-21 20:34:19 +0000497 outs() << "Relocated section contents for " << G.getName() << ":\n";
498 dumpSectionContents(outs(), G);
499 return Error::success();
500 });
Lang Hames11c8dfa52019-04-20 17:10:34 +0000501}
502
503Expected<Session::FileInfo &> Session::findFileInfo(StringRef FileName) {
504 auto FileInfoItr = FileInfos.find(FileName);
505 if (FileInfoItr == FileInfos.end())
506 return make_error<StringError>("file \"" + FileName + "\" not recognized",
507 inconvertibleErrorCode());
508 return FileInfoItr->second;
509}
510
511Expected<Session::MemoryRegionInfo &>
512Session::findSectionInfo(StringRef FileName, StringRef SectionName) {
513 auto FI = findFileInfo(FileName);
514 if (!FI)
515 return FI.takeError();
516 auto SecInfoItr = FI->SectionInfos.find(SectionName);
517 if (SecInfoItr == FI->SectionInfos.end())
518 return make_error<StringError>("no section \"" + SectionName +
519 "\" registered for file \"" + FileName +
520 "\"",
521 inconvertibleErrorCode());
522 return SecInfoItr->second;
523}
524
525Expected<Session::MemoryRegionInfo &>
526Session::findStubInfo(StringRef FileName, StringRef TargetName) {
527 auto FI = findFileInfo(FileName);
528 if (!FI)
529 return FI.takeError();
530 auto StubInfoItr = FI->StubInfos.find(TargetName);
531 if (StubInfoItr == FI->StubInfos.end())
532 return make_error<StringError>("no stub for \"" + TargetName +
533 "\" registered for file \"" + FileName +
534 "\"",
535 inconvertibleErrorCode());
536 return StubInfoItr->second;
537}
538
539Expected<Session::MemoryRegionInfo &>
540Session::findGOTEntryInfo(StringRef FileName, StringRef TargetName) {
541 auto FI = findFileInfo(FileName);
542 if (!FI)
543 return FI.takeError();
544 auto GOTInfoItr = FI->GOTEntryInfos.find(TargetName);
545 if (GOTInfoItr == FI->GOTEntryInfos.end())
546 return make_error<StringError>("no GOT entry for \"" + TargetName +
547 "\" registered for file \"" + FileName +
548 "\"",
549 inconvertibleErrorCode());
550 return GOTInfoItr->second;
551}
552
553bool Session::isSymbolRegistered(StringRef SymbolName) {
554 return SymbolInfos.count(SymbolName);
555}
556
557Expected<Session::MemoryRegionInfo &>
558Session::findSymbolInfo(StringRef SymbolName, Twine ErrorMsgStem) {
559 auto SymInfoItr = SymbolInfos.find(SymbolName);
560 if (SymInfoItr == SymbolInfos.end())
561 return make_error<StringError>(ErrorMsgStem + ": symbol " + SymbolName +
562 " not found",
563 inconvertibleErrorCode());
564 return SymInfoItr->second;
565}
566
567} // end namespace llvm
568
Lang Hamesb1ba4d82019-04-24 15:15:55 +0000569Triple getFirstFileTriple() {
570 assert(!InputFiles.empty() && "InputFiles can not be empty");
571 auto ObjBuffer =
572 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFiles.front())));
573 auto Obj = ExitOnErr(
574 object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()));
575 return Obj->makeTriple();
576}
577
Lang Hamesd959a602019-04-24 17:23:05 +0000578Error sanitizeArguments(const Session &S) {
Lang Hamesb1ba4d82019-04-24 15:15:55 +0000579 if (EntryPointName.empty()) {
580 if (S.TT.getObjectFormat() == Triple::MachO)
581 EntryPointName = "_main";
582 else
583 EntryPointName = "main";
584 }
Lang Hamesd959a602019-04-24 17:23:05 +0000585
586 if (NoExec && !InputArgv.empty())
587 outs() << "Warning: --args passed to -noexec run will be ignored.\n";
588
Lang Hames14ac84e2020-03-03 14:18:12 -0800589 // If -slab-address is passed, require -slab-allocate and -noexec
590 if (SlabAddress != ~0ULL) {
591 if (SlabAllocateSizeString == "" || !NoExec)
592 return make_error<StringError>(
593 "-slab-address requires -slab-allocate and -noexec",
594 inconvertibleErrorCode());
595 }
596
Lang Hamesd959a602019-04-24 17:23:05 +0000597 return Error::success();
Lang Hamesb1ba4d82019-04-24 15:15:55 +0000598}
599
Lang Hames11c8dfa52019-04-20 17:10:34 +0000600Error loadProcessSymbols(Session &S) {
601 std::string ErrMsg;
602 if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr, &ErrMsg))
603 return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
604
605 char GlobalPrefix = S.TT.getObjectFormat() == Triple::MachO ? '_' : '\0';
Lang Hamesb1ba4d82019-04-24 15:15:55 +0000606 auto InternedEntryPointName = S.ES.intern(EntryPointName);
607 auto FilterMainEntryPoint = [InternedEntryPointName](SymbolStringPtr Name) {
608 return Name != InternedEntryPointName;
609 };
Lang Hames85fb9972019-12-16 02:50:40 -0800610 S.MainJD->addGenerator(
Lang Hamesb1ba4d82019-04-24 15:15:55 +0000611 ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
612 GlobalPrefix, FilterMainEntryPoint)));
Lang Hames11c8dfa52019-04-20 17:10:34 +0000613
614 return Error::success();
615}
616
617Error loadDylibs() {
618 // FIXME: This should all be handled inside DynamicLibrary.
619 for (const auto &Dylib : Dylibs) {
620 if (!sys::fs::is_regular_file(Dylib))
621 return make_error<StringError>("\"" + Dylib + "\" is not a regular file",
622 inconvertibleErrorCode());
623 std::string ErrMsg;
624 if (sys::DynamicLibrary::LoadLibraryPermanently(Dylib.c_str(), &ErrMsg))
625 return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
626 }
627
628 return Error::success();
629}
630
Lang Hames11c8dfa52019-04-20 17:10:34 +0000631Error loadObjects(Session &S) {
632
633 std::map<unsigned, JITDylib *> IdxToJLD;
634
635 // First, set up JITDylibs.
636 LLVM_DEBUG(dbgs() << "Creating JITDylibs...\n");
637 {
638 // Create a "main" JITLinkDylib.
Lang Hames85fb9972019-12-16 02:50:40 -0800639 IdxToJLD[0] = S.MainJD;
640 S.JDSearchOrder.push_back(S.MainJD);
641 LLVM_DEBUG(dbgs() << " 0: " << S.MainJD->getName() << "\n");
Lang Hames11c8dfa52019-04-20 17:10:34 +0000642
643 // Add any extra JITLinkDylibs from the command line.
644 std::string JDNamePrefix("lib");
645 for (auto JLDItr = JITLinkDylibs.begin(), JLDEnd = JITLinkDylibs.end();
646 JLDItr != JLDEnd; ++JLDItr) {
Lang Hames85fb9972019-12-16 02:50:40 -0800647 auto JD = S.ES.createJITDylib(JDNamePrefix + *JLDItr);
648 if (!JD)
649 return JD.takeError();
Lang Hames11c8dfa52019-04-20 17:10:34 +0000650 unsigned JDIdx =
651 JITLinkDylibs.getPosition(JLDItr - JITLinkDylibs.begin());
Lang Hames85fb9972019-12-16 02:50:40 -0800652 IdxToJLD[JDIdx] = &*JD;
653 S.JDSearchOrder.push_back(&*JD);
654 LLVM_DEBUG(dbgs() << " " << JDIdx << ": " << JD->getName() << "\n");
Lang Hames11c8dfa52019-04-20 17:10:34 +0000655 }
656
657 // Set every dylib to link against every other, in command line order.
658 for (auto *JD : S.JDSearchOrder) {
Lang Hames674df132019-11-25 21:57:27 -0800659 auto LookupFlags = JITDylibLookupFlags::MatchExportedSymbolsOnly;
660 JITDylibSearchOrder O;
Lang Hames11c8dfa52019-04-20 17:10:34 +0000661 for (auto *JD2 : S.JDSearchOrder) {
662 if (JD2 == JD)
663 continue;
Lang Hames674df132019-11-25 21:57:27 -0800664 O.push_back(std::make_pair(JD2, LookupFlags));
Lang Hames11c8dfa52019-04-20 17:10:34 +0000665 }
666 JD->setSearchOrder(std::move(O));
667 }
668 }
669
670 // Load each object into the corresponding JITDylib..
671 LLVM_DEBUG(dbgs() << "Adding objects...\n");
672 for (auto InputFileItr = InputFiles.begin(), InputFileEnd = InputFiles.end();
673 InputFileItr != InputFileEnd; ++InputFileItr) {
674 unsigned InputFileArgIdx =
675 InputFiles.getPosition(InputFileItr - InputFiles.begin());
676 StringRef InputFile = *InputFileItr;
677 auto &JD = *std::prev(IdxToJLD.lower_bound(InputFileArgIdx))->second;
678 LLVM_DEBUG(dbgs() << " " << InputFileArgIdx << ": \"" << InputFile
679 << "\" to " << JD.getName() << "\n";);
680 auto ObjBuffer =
681 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFile)));
682 ExitOnErr(S.ObjLayer.add(JD, std::move(ObjBuffer)));
683 }
684
685 // Define absolute symbols.
686 LLVM_DEBUG(dbgs() << "Defining absolute symbols...\n");
687 for (auto AbsDefItr = AbsoluteDefs.begin(), AbsDefEnd = AbsoluteDefs.end();
688 AbsDefItr != AbsDefEnd; ++AbsDefItr) {
689 unsigned AbsDefArgIdx =
690 AbsoluteDefs.getPosition(AbsDefItr - AbsoluteDefs.begin());
691 auto &JD = *std::prev(IdxToJLD.lower_bound(AbsDefArgIdx))->second;
692
693 StringRef AbsDefStmt = *AbsDefItr;
694 size_t EqIdx = AbsDefStmt.find_first_of('=');
695 if (EqIdx == StringRef::npos)
696 return make_error<StringError>("Invalid absolute define \"" + AbsDefStmt +
697 "\". Syntax: <name>=<addr>",
698 inconvertibleErrorCode());
699 StringRef Name = AbsDefStmt.substr(0, EqIdx).trim();
700 StringRef AddrStr = AbsDefStmt.substr(EqIdx + 1).trim();
701
702 uint64_t Addr;
703 if (AddrStr.getAsInteger(0, Addr))
704 return make_error<StringError>("Invalid address expression \"" + AddrStr +
705 "\" in absolute define \"" + AbsDefStmt +
706 "\"",
707 inconvertibleErrorCode());
708 JITEvaluatedSymbol AbsDef(Addr, JITSymbolFlags::Exported);
709 if (auto Err = JD.define(absoluteSymbols({{S.ES.intern(Name), AbsDef}})))
710 return Err;
711
712 // Register the absolute symbol with the session symbol infos.
713 S.SymbolInfos[Name] = { StringRef(), Addr };
714 }
715
716 LLVM_DEBUG({
717 dbgs() << "Dylib search order is [ ";
718 for (auto *JD : S.JDSearchOrder)
719 dbgs() << JD->getName() << " ";
720 dbgs() << "]\n";
721 });
722
723 return Error::success();
724}
725
726Error runChecks(Session &S) {
727
728 auto TripleName = S.TT.str();
729 std::string ErrorStr;
730 const Target *TheTarget = TargetRegistry::lookupTarget("", S.TT, ErrorStr);
731 if (!TheTarget)
732 ExitOnErr(make_error<StringError>("Error accessing target '" + TripleName +
733 "': " + ErrorStr,
734 inconvertibleErrorCode()));
735
736 std::unique_ptr<MCSubtargetInfo> STI(
737 TheTarget->createMCSubtargetInfo(TripleName, "", ""));
738 if (!STI)
739 ExitOnErr(
740 make_error<StringError>("Unable to create subtarget for " + TripleName,
741 inconvertibleErrorCode()));
742
743 std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
744 if (!MRI)
745 ExitOnErr(make_error<StringError>("Unable to create target register info "
746 "for " +
747 TripleName,
748 inconvertibleErrorCode()));
749
Mirko Brkusanin4b63ca12019-10-23 12:24:35 +0200750 MCTargetOptions MCOptions;
751 std::unique_ptr<MCAsmInfo> MAI(
752 TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
Lang Hames11c8dfa52019-04-20 17:10:34 +0000753 if (!MAI)
754 ExitOnErr(make_error<StringError>("Unable to create target asm info " +
755 TripleName,
756 inconvertibleErrorCode()));
757
758 MCContext Ctx(MAI.get(), MRI.get(), nullptr);
759
760 std::unique_ptr<MCDisassembler> Disassembler(
761 TheTarget->createMCDisassembler(*STI, Ctx));
762 if (!Disassembler)
763 ExitOnErr(make_error<StringError>("Unable to create disassembler for " +
764 TripleName,
765 inconvertibleErrorCode()));
766
767 std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
768
769 std::unique_ptr<MCInstPrinter> InstPrinter(
770 TheTarget->createMCInstPrinter(Triple(TripleName), 0, *MAI, *MII, *MRI));
771
772 auto IsSymbolValid = [&S](StringRef Symbol) {
773 return S.isSymbolRegistered(Symbol);
774 };
775
776 auto GetSymbolInfo = [&S](StringRef Symbol) {
777 return S.findSymbolInfo(Symbol, "Can not get symbol info");
778 };
779
780 auto GetSectionInfo = [&S](StringRef FileName, StringRef SectionName) {
781 return S.findSectionInfo(FileName, SectionName);
782 };
783
784 auto GetStubInfo = [&S](StringRef FileName, StringRef SectionName) {
785 return S.findStubInfo(FileName, SectionName);
786 };
787
788 auto GetGOTInfo = [&S](StringRef FileName, StringRef SectionName) {
789 return S.findGOTEntryInfo(FileName, SectionName);
790 };
791
792 RuntimeDyldChecker Checker(
793 IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo, GetGOTInfo,
794 S.TT.isLittleEndian() ? support::little : support::big,
795 Disassembler.get(), InstPrinter.get(), dbgs());
796
Lang Hames674df132019-11-25 21:57:27 -0800797 std::string CheckLineStart = "# " + CheckName + ":";
Lang Hames11c8dfa52019-04-20 17:10:34 +0000798 for (auto &CheckFile : CheckFiles) {
799 auto CheckerFileBuf =
800 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(CheckFile)));
Lang Hames674df132019-11-25 21:57:27 -0800801 if (!Checker.checkAllRulesInBuffer(CheckLineStart, &*CheckerFileBuf))
Lang Hames11c8dfa52019-04-20 17:10:34 +0000802 ExitOnErr(make_error<StringError>(
803 "Some checks in " + CheckFile + " failed", inconvertibleErrorCode()));
804 }
805
806 return Error::success();
807}
808
809static void dumpSessionStats(Session &S) {
810 if (ShowSizes)
Lang Hames4e920e52019-10-04 03:55:26 +0000811 outs() << "Total size of all blocks before pruning: " << S.SizeBeforePruning
812 << "\nTotal size of all blocks after fixups: " << S.SizeAfterFixups
Lang Hames11c8dfa52019-04-20 17:10:34 +0000813 << "\n";
814}
815
816static Expected<JITEvaluatedSymbol> getMainEntryPoint(Session &S) {
Lang Hames11c8dfa52019-04-20 17:10:34 +0000817 return S.ES.lookup(S.JDSearchOrder, EntryPointName);
818}
819
Lang Hames200415c2019-09-04 18:38:29 +0000820struct JITLinkTimers {
Lang Hames41adc372019-09-04 20:26:26 +0000821 TimerGroup JITLinkTG{"llvm-jitlink timers", "timers for llvm-jitlink phases"};
822 Timer LoadObjectsTimer{"load", "time to load/add object files", JITLinkTG};
823 Timer LinkTimer{"link", "time to link object files", JITLinkTG};
824 Timer RunTimer{"run", "time to execute jitlink'd code", JITLinkTG};
Lang Hames200415c2019-09-04 18:38:29 +0000825};
826
Lang Hames11c8dfa52019-04-20 17:10:34 +0000827int main(int argc, char *argv[]) {
828 InitLLVM X(argc, argv);
829
830 InitializeAllTargetInfos();
831 InitializeAllTargetMCs();
832 InitializeAllDisassemblers();
833
834 cl::ParseCommandLineOptions(argc, argv, "llvm jitlink tool");
835 ExitOnErr.setBanner(std::string(argv[0]) + ": ");
836
Lang Hames200415c2019-09-04 18:38:29 +0000837 /// If timers are enabled, create a JITLinkTimers instance.
838 std::unique_ptr<JITLinkTimers> Timers =
839 ShowTimes ? std::make_unique<JITLinkTimers>() : nullptr;
840
Lang Hames85fb9972019-12-16 02:50:40 -0800841 auto S = ExitOnErr(Session::Create(getFirstFileTriple()));
Lang Hames11c8dfa52019-04-20 17:10:34 +0000842
Lang Hames85fb9972019-12-16 02:50:40 -0800843 ExitOnErr(sanitizeArguments(*S));
Lang Hamesb1ba4d82019-04-24 15:15:55 +0000844
Lang Hames11c8dfa52019-04-20 17:10:34 +0000845 if (!NoProcessSymbols)
Lang Hames85fb9972019-12-16 02:50:40 -0800846 ExitOnErr(loadProcessSymbols(*S));
Lang Hames11c8dfa52019-04-20 17:10:34 +0000847 ExitOnErr(loadDylibs());
848
Lang Hames6fd39602019-08-27 15:51:19 +0000849 {
Lang Hames200415c2019-09-04 18:38:29 +0000850 TimeRegion TR(Timers ? &Timers->LoadObjectsTimer : nullptr);
Lang Hames85fb9972019-12-16 02:50:40 -0800851 ExitOnErr(loadObjects(*S));
Lang Hames6fd39602019-08-27 15:51:19 +0000852 }
853
Lang Hamesf75e04b2020-03-14 16:07:46 -0700854 if (ShowInitialExecutionSessionState)
855 S->ES.dump(outs());
856
Lang Hames6fd39602019-08-27 15:51:19 +0000857 JITEvaluatedSymbol EntryPoint = 0;
858 {
Lang Hames200415c2019-09-04 18:38:29 +0000859 TimeRegion TR(Timers ? &Timers->LinkTimer : nullptr);
Lang Hames85fb9972019-12-16 02:50:40 -0800860 EntryPoint = ExitOnErr(getMainEntryPoint(*S));
Lang Hames6fd39602019-08-27 15:51:19 +0000861 }
Lang Hames11c8dfa52019-04-20 17:10:34 +0000862
863 if (ShowAddrs)
Lang Hames85fb9972019-12-16 02:50:40 -0800864 S->dumpSessionInfo(outs());
Lang Hames11c8dfa52019-04-20 17:10:34 +0000865
Lang Hames85fb9972019-12-16 02:50:40 -0800866 ExitOnErr(runChecks(*S));
Lang Hames11c8dfa52019-04-20 17:10:34 +0000867
Lang Hames85fb9972019-12-16 02:50:40 -0800868 dumpSessionStats(*S);
Lang Hames11c8dfa52019-04-20 17:10:34 +0000869
870 if (NoExec)
871 return 0;
872
Lang Hames6fd39602019-08-27 15:51:19 +0000873 int Result = 0;
874 {
Lang Hamesece8fed2019-12-02 01:45:49 -0800875 using MainTy = int (*)(int, char *[]);
876 auto EntryFn = jitTargetAddressToFunction<MainTy>(EntryPoint.getAddress());
Lang Hames200415c2019-09-04 18:38:29 +0000877 TimeRegion TR(Timers ? &Timers->RunTimer : nullptr);
Lang Hamesece8fed2019-12-02 01:45:49 -0800878 Result = runAsMain(EntryFn, InputArgv, StringRef(InputFiles.front()));
Lang Hames6fd39602019-08-27 15:51:19 +0000879 }
880
Lang Hames6fd39602019-08-27 15:51:19 +0000881 return Result;
Lang Hames11c8dfa52019-04-20 17:10:34 +0000882}