10b57cec5SDimitry Andric //===-- llvm-rtdyld.cpp - MCJIT Testing Tool ------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This is a testing tool for use with the MC-JIT LLVM components.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h"
140b57cec5SDimitry Andric #include "llvm/DebugInfo/DIContext.h"
150b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h"
160b57cec5SDimitry Andric #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
170b57cec5SDimitry Andric #include "llvm/ExecutionEngine/RuntimeDyld.h"
180b57cec5SDimitry Andric #include "llvm/ExecutionEngine/RuntimeDyldChecker.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCInstPrinter.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
26480093f4SDimitry Andric #include "llvm/MC/MCTargetOptions.h"
27349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
280b57cec5SDimitry Andric #include "llvm/Object/SymbolSize.h"
290b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
300b57cec5SDimitry Andric #include "llvm/Support/DynamicLibrary.h"
31fe6060f1SDimitry Andric #include "llvm/Support/FileSystem.h"
320b57cec5SDimitry Andric #include "llvm/Support/InitLLVM.h"
338bcb0991SDimitry Andric #include "llvm/Support/MSVCErrorWorkarounds.h"
340b57cec5SDimitry Andric #include "llvm/Support/Memory.h"
350b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
360b57cec5SDimitry Andric #include "llvm/Support/Path.h"
370b57cec5SDimitry Andric #include "llvm/Support/TargetSelect.h"
388bcb0991SDimitry Andric #include "llvm/Support/Timer.h"
390b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric #include <future>
420b57cec5SDimitry Andric #include <list>
430b57cec5SDimitry Andric
440b57cec5SDimitry Andric using namespace llvm;
450b57cec5SDimitry Andric using namespace llvm::object;
460b57cec5SDimitry Andric
47fe6060f1SDimitry Andric static cl::OptionCategory RTDyldCategory("RTDyld Options");
48fe6060f1SDimitry Andric
4981ad6265SDimitry Andric static cl::list<std::string> InputFileList(cl::Positional,
50fe6060f1SDimitry Andric cl::desc("<input files>"),
51fe6060f1SDimitry Andric cl::cat(RTDyldCategory));
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric enum ActionType {
540b57cec5SDimitry Andric AC_Execute,
550b57cec5SDimitry Andric AC_PrintObjectLineInfo,
560b57cec5SDimitry Andric AC_PrintLineInfo,
570b57cec5SDimitry Andric AC_PrintDebugLineInfo,
580b57cec5SDimitry Andric AC_Verify
590b57cec5SDimitry Andric };
600b57cec5SDimitry Andric
61fe6060f1SDimitry Andric static cl::opt<ActionType> Action(
62fe6060f1SDimitry Andric cl::desc("Action to perform:"), cl::init(AC_Execute),
63fe6060f1SDimitry Andric cl::values(
64fe6060f1SDimitry Andric clEnumValN(AC_Execute, "execute",
650b57cec5SDimitry Andric "Load, link, and execute the inputs."),
660b57cec5SDimitry Andric clEnumValN(AC_PrintLineInfo, "printline",
670b57cec5SDimitry Andric "Load, link, and print line information for each function."),
680b57cec5SDimitry Andric clEnumValN(AC_PrintDebugLineInfo, "printdebugline",
69fe6060f1SDimitry Andric "Load, link, and print line information for each function "
70fe6060f1SDimitry Andric "using the debug object"),
710b57cec5SDimitry Andric clEnumValN(AC_PrintObjectLineInfo, "printobjline",
720b57cec5SDimitry Andric "Like -printlineinfo but does not load the object first"),
730b57cec5SDimitry Andric clEnumValN(AC_Verify, "verify",
74fe6060f1SDimitry Andric "Load, link and verify the resulting memory image.")),
75fe6060f1SDimitry Andric cl::cat(RTDyldCategory));
760b57cec5SDimitry Andric
770b57cec5SDimitry Andric static cl::opt<std::string>
78fe6060f1SDimitry Andric EntryPoint("entry", cl::desc("Function to call as entry point."),
79fe6060f1SDimitry Andric cl::init("_main"), cl::cat(RTDyldCategory));
800b57cec5SDimitry Andric
81fe6060f1SDimitry Andric static cl::list<std::string> Dylibs("dylib", cl::desc("Add library."),
8281ad6265SDimitry Andric cl::cat(RTDyldCategory));
830b57cec5SDimitry Andric
840b57cec5SDimitry Andric static cl::list<std::string> InputArgv("args", cl::Positional,
850b57cec5SDimitry Andric cl::desc("<program arguments>..."),
8681ad6265SDimitry Andric cl::PositionalEatsArgs,
87fe6060f1SDimitry Andric cl::cat(RTDyldCategory));
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric static cl::opt<std::string>
90fe6060f1SDimitry Andric TripleName("triple", cl::desc("Target triple for disassembler"),
91fe6060f1SDimitry Andric cl::cat(RTDyldCategory));
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric static cl::opt<std::string>
940b57cec5SDimitry Andric MCPU("mcpu",
950b57cec5SDimitry Andric cl::desc("Target a specific cpu type (-mcpu=help for details)"),
96fe6060f1SDimitry Andric cl::value_desc("cpu-name"), cl::init(""), cl::cat(RTDyldCategory));
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric static cl::list<std::string>
990b57cec5SDimitry Andric CheckFiles("check",
1000b57cec5SDimitry Andric cl::desc("File containing RuntimeDyld verifier checks."),
10181ad6265SDimitry Andric cl::cat(RTDyldCategory));
1020b57cec5SDimitry Andric
1030b57cec5SDimitry Andric static cl::opt<uint64_t>
1040b57cec5SDimitry Andric PreallocMemory("preallocate",
1050b57cec5SDimitry Andric cl::desc("Allocate memory upfront rather than on-demand"),
106fe6060f1SDimitry Andric cl::init(0), cl::cat(RTDyldCategory));
1070b57cec5SDimitry Andric
1080b57cec5SDimitry Andric static cl::opt<uint64_t> TargetAddrStart(
1090b57cec5SDimitry Andric "target-addr-start",
1100b57cec5SDimitry Andric cl::desc("For -verify only: start of phony target address "
1110b57cec5SDimitry Andric "range."),
1120b57cec5SDimitry Andric cl::init(4096), // Start at "page 1" - no allocating at "null".
113fe6060f1SDimitry Andric cl::Hidden, cl::cat(RTDyldCategory));
1140b57cec5SDimitry Andric
1150b57cec5SDimitry Andric static cl::opt<uint64_t> TargetAddrEnd(
1160b57cec5SDimitry Andric "target-addr-end",
1170b57cec5SDimitry Andric cl::desc("For -verify only: end of phony target address range."),
118fe6060f1SDimitry Andric cl::init(~0ULL), cl::Hidden, cl::cat(RTDyldCategory));
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric static cl::opt<uint64_t> TargetSectionSep(
1210b57cec5SDimitry Andric "target-section-sep",
1220b57cec5SDimitry Andric cl::desc("For -verify only: Separation between sections in "
1230b57cec5SDimitry Andric "phony target address space."),
124fe6060f1SDimitry Andric cl::init(0), cl::Hidden, cl::cat(RTDyldCategory));
1250b57cec5SDimitry Andric
1260b57cec5SDimitry Andric static cl::list<std::string>
1270b57cec5SDimitry Andric SpecificSectionMappings("map-section",
1280b57cec5SDimitry Andric cl::desc("For -verify only: Map a section to a "
1290b57cec5SDimitry Andric "specific address."),
13081ad6265SDimitry Andric cl::Hidden, cl::cat(RTDyldCategory));
1310b57cec5SDimitry Andric
132fe6060f1SDimitry Andric static cl::list<std::string> DummySymbolMappings(
133fe6060f1SDimitry Andric "dummy-extern",
1340b57cec5SDimitry Andric cl::desc("For -verify only: Inject a symbol into the extern "
1350b57cec5SDimitry Andric "symbol table."),
13681ad6265SDimitry Andric cl::Hidden, cl::cat(RTDyldCategory));
1370b57cec5SDimitry Andric
138fe6060f1SDimitry Andric static cl::opt<bool> PrintAllocationRequests(
139fe6060f1SDimitry Andric "print-alloc-requests",
1400b57cec5SDimitry Andric cl::desc("Print allocation requests made to the memory "
1410b57cec5SDimitry Andric "manager by RuntimeDyld"),
142fe6060f1SDimitry Andric cl::Hidden, cl::cat(RTDyldCategory));
1430b57cec5SDimitry Andric
1448bcb0991SDimitry Andric static cl::opt<bool> ShowTimes("show-times",
1458bcb0991SDimitry Andric cl::desc("Show times for llvm-rtdyld phases"),
146fe6060f1SDimitry Andric cl::init(false), cl::cat(RTDyldCategory));
1478bcb0991SDimitry Andric
1480b57cec5SDimitry Andric ExitOnError ExitOnErr;
1490b57cec5SDimitry Andric
1508bcb0991SDimitry Andric struct RTDyldTimers {
1518bcb0991SDimitry Andric TimerGroup RTDyldTG{"llvm-rtdyld timers", "timers for llvm-rtdyld phases"};
1528bcb0991SDimitry Andric Timer LoadObjectsTimer{"load", "time to load/add object files", RTDyldTG};
1538bcb0991SDimitry Andric Timer LinkTimer{"link", "time to link object files", RTDyldTG};
1548bcb0991SDimitry Andric Timer RunTimer{"run", "time to execute jitlink'd code", RTDyldTG};
1558bcb0991SDimitry Andric };
1568bcb0991SDimitry Andric
1578bcb0991SDimitry Andric std::unique_ptr<RTDyldTimers> Timers;
1588bcb0991SDimitry Andric
1590b57cec5SDimitry Andric /* *** */
1600b57cec5SDimitry Andric
1610b57cec5SDimitry Andric using SectionIDMap = StringMap<unsigned>;
1620b57cec5SDimitry Andric using FileToSectionIDMap = StringMap<SectionIDMap>;
1630b57cec5SDimitry Andric
dumpFileToSectionIDMap(const FileToSectionIDMap & FileToSecIDMap)1640b57cec5SDimitry Andric void dumpFileToSectionIDMap(const FileToSectionIDMap &FileToSecIDMap) {
1650b57cec5SDimitry Andric for (const auto &KV : FileToSecIDMap) {
1660b57cec5SDimitry Andric llvm::dbgs() << "In " << KV.first() << "\n";
1670b57cec5SDimitry Andric for (auto &KV2 : KV.second)
1680b57cec5SDimitry Andric llvm::dbgs() << " \"" << KV2.first() << "\" -> " << KV2.second << "\n";
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric
getSectionId(const FileToSectionIDMap & FileToSecIDMap,StringRef FileName,StringRef SectionName)1720b57cec5SDimitry Andric Expected<unsigned> getSectionId(const FileToSectionIDMap &FileToSecIDMap,
1730b57cec5SDimitry Andric StringRef FileName, StringRef SectionName) {
1740b57cec5SDimitry Andric auto I = FileToSecIDMap.find(FileName);
1750b57cec5SDimitry Andric if (I == FileToSecIDMap.end())
1760b57cec5SDimitry Andric return make_error<StringError>("No file named " + FileName,
1770b57cec5SDimitry Andric inconvertibleErrorCode());
1780b57cec5SDimitry Andric auto &SectionIDs = I->second;
1790b57cec5SDimitry Andric auto J = SectionIDs.find(SectionName);
1800b57cec5SDimitry Andric if (J == SectionIDs.end())
1810b57cec5SDimitry Andric return make_error<StringError>("No section named \"" + SectionName +
1820b57cec5SDimitry Andric "\" in file " + FileName,
1830b57cec5SDimitry Andric inconvertibleErrorCode());
1840b57cec5SDimitry Andric return J->second;
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andric // A trivial memory manager that doesn't do anything fancy, just uses the
1880b57cec5SDimitry Andric // support library allocation routines directly.
1890b57cec5SDimitry Andric class TrivialMemoryManager : public RTDyldMemoryManager {
1900b57cec5SDimitry Andric public:
1910b57cec5SDimitry Andric struct SectionInfo {
SectionInfoTrivialMemoryManager::SectionInfo1920b57cec5SDimitry Andric SectionInfo(StringRef Name, sys::MemoryBlock MB, unsigned SectionID)
1935ffd83dbSDimitry Andric : Name(std::string(Name)), MB(std::move(MB)), SectionID(SectionID) {}
1940b57cec5SDimitry Andric std::string Name;
1950b57cec5SDimitry Andric sys::MemoryBlock MB;
1960b57cec5SDimitry Andric unsigned SectionID = ~0U;
1970b57cec5SDimitry Andric };
1980b57cec5SDimitry Andric
1990b57cec5SDimitry Andric SmallVector<SectionInfo, 16> FunctionMemory;
2000b57cec5SDimitry Andric SmallVector<SectionInfo, 16> DataMemory;
2010b57cec5SDimitry Andric
2020b57cec5SDimitry Andric uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
2030b57cec5SDimitry Andric unsigned SectionID,
2040b57cec5SDimitry Andric StringRef SectionName) override;
2050b57cec5SDimitry Andric uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
2060b57cec5SDimitry Andric unsigned SectionID, StringRef SectionName,
2070b57cec5SDimitry Andric bool IsReadOnly) override;
208349cc55cSDimitry Andric TrivialMemoryManager::TLSSection
209349cc55cSDimitry Andric allocateTLSSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
210349cc55cSDimitry Andric StringRef SectionName) override;
2110b57cec5SDimitry Andric
2120b57cec5SDimitry Andric /// If non null, records subsequent Name -> SectionID mappings.
setSectionIDsMap(SectionIDMap * SecIDMap)2130b57cec5SDimitry Andric void setSectionIDsMap(SectionIDMap *SecIDMap) {
2140b57cec5SDimitry Andric this->SecIDMap = SecIDMap;
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric
getPointerToNamedFunction(const std::string & Name,bool AbortOnFailure=true)2170b57cec5SDimitry Andric void *getPointerToNamedFunction(const std::string &Name,
2180b57cec5SDimitry Andric bool AbortOnFailure = true) override {
2190b57cec5SDimitry Andric return nullptr;
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric
finalizeMemory(std::string * ErrMsg)2220b57cec5SDimitry Andric bool finalizeMemory(std::string *ErrMsg) override { return false; }
2230b57cec5SDimitry Andric
addDummySymbol(const std::string & Name,uint64_t Addr)2240b57cec5SDimitry Andric void addDummySymbol(const std::string &Name, uint64_t Addr) {
2250b57cec5SDimitry Andric DummyExterns[Name] = Addr;
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric
findSymbol(const std::string & Name)2280b57cec5SDimitry Andric JITSymbol findSymbol(const std::string &Name) override {
2290b57cec5SDimitry Andric auto I = DummyExterns.find(Name);
2300b57cec5SDimitry Andric
2310b57cec5SDimitry Andric if (I != DummyExterns.end())
2320b57cec5SDimitry Andric return JITSymbol(I->second, JITSymbolFlags::Exported);
2330b57cec5SDimitry Andric
2340b57cec5SDimitry Andric if (auto Sym = RTDyldMemoryManager::findSymbol(Name))
2350b57cec5SDimitry Andric return Sym;
2360b57cec5SDimitry Andric else if (auto Err = Sym.takeError())
2370b57cec5SDimitry Andric ExitOnErr(std::move(Err));
2380b57cec5SDimitry Andric else
2390b57cec5SDimitry Andric ExitOnErr(make_error<StringError>("Could not find definition for \"" +
2400b57cec5SDimitry Andric Name + "\"",
2410b57cec5SDimitry Andric inconvertibleErrorCode()));
2420b57cec5SDimitry Andric llvm_unreachable("Should have returned or exited by now");
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric
registerEHFrames(uint8_t * Addr,uint64_t LoadAddr,size_t Size)2450b57cec5SDimitry Andric void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
2460b57cec5SDimitry Andric size_t Size) override {}
deregisterEHFrames()2470b57cec5SDimitry Andric void deregisterEHFrames() override {}
2480b57cec5SDimitry Andric
preallocateSlab(uint64_t Size)2490b57cec5SDimitry Andric void preallocateSlab(uint64_t Size) {
2500b57cec5SDimitry Andric std::error_code EC;
2510b57cec5SDimitry Andric sys::MemoryBlock MB =
2520b57cec5SDimitry Andric sys::Memory::allocateMappedMemory(Size, nullptr,
2530b57cec5SDimitry Andric sys::Memory::MF_READ |
2540b57cec5SDimitry Andric sys::Memory::MF_WRITE,
2550b57cec5SDimitry Andric EC);
2560b57cec5SDimitry Andric if (!MB.base())
257349cc55cSDimitry Andric report_fatal_error(Twine("Can't allocate enough memory: ") +
258349cc55cSDimitry Andric EC.message());
2590b57cec5SDimitry Andric
2600b57cec5SDimitry Andric PreallocSlab = MB;
2610b57cec5SDimitry Andric UsePreallocation = true;
2620b57cec5SDimitry Andric SlabSize = Size;
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric
allocateFromSlab(uintptr_t Size,unsigned Alignment,bool isCode,StringRef SectionName,unsigned SectionID)2650b57cec5SDimitry Andric uint8_t *allocateFromSlab(uintptr_t Size, unsigned Alignment, bool isCode,
2660b57cec5SDimitry Andric StringRef SectionName, unsigned SectionID) {
2670b57cec5SDimitry Andric Size = alignTo(Size, Alignment);
2680b57cec5SDimitry Andric if (CurrentSlabOffset + Size > SlabSize)
2690b57cec5SDimitry Andric report_fatal_error("Can't allocate enough memory. Tune --preallocate");
2700b57cec5SDimitry Andric
2710b57cec5SDimitry Andric uintptr_t OldSlabOffset = CurrentSlabOffset;
2720b57cec5SDimitry Andric sys::MemoryBlock MB((void *)OldSlabOffset, Size);
2730b57cec5SDimitry Andric if (isCode)
2740b57cec5SDimitry Andric FunctionMemory.push_back(SectionInfo(SectionName, MB, SectionID));
2750b57cec5SDimitry Andric else
2760b57cec5SDimitry Andric DataMemory.push_back(SectionInfo(SectionName, MB, SectionID));
2770b57cec5SDimitry Andric CurrentSlabOffset += Size;
2780b57cec5SDimitry Andric return (uint8_t*)OldSlabOffset;
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric
2810b57cec5SDimitry Andric private:
2820b57cec5SDimitry Andric std::map<std::string, uint64_t> DummyExterns;
2830b57cec5SDimitry Andric sys::MemoryBlock PreallocSlab;
2840b57cec5SDimitry Andric bool UsePreallocation = false;
2850b57cec5SDimitry Andric uintptr_t SlabSize = 0;
2860b57cec5SDimitry Andric uintptr_t CurrentSlabOffset = 0;
2870b57cec5SDimitry Andric SectionIDMap *SecIDMap = nullptr;
288d781ede6SDimitry Andric #if defined(__x86_64__) && defined(__ELF__) && defined(__linux__)
289349cc55cSDimitry Andric unsigned UsedTLSStorage = 0;
290349cc55cSDimitry Andric #endif
2910b57cec5SDimitry Andric };
2920b57cec5SDimitry Andric
allocateCodeSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,StringRef SectionName)2930b57cec5SDimitry Andric uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size,
2940b57cec5SDimitry Andric unsigned Alignment,
2950b57cec5SDimitry Andric unsigned SectionID,
2960b57cec5SDimitry Andric StringRef SectionName) {
2970b57cec5SDimitry Andric if (PrintAllocationRequests)
2980b57cec5SDimitry Andric outs() << "allocateCodeSection(Size = " << Size << ", Alignment = "
2990b57cec5SDimitry Andric << Alignment << ", SectionName = " << SectionName << ")\n";
3000b57cec5SDimitry Andric
3010b57cec5SDimitry Andric if (SecIDMap)
3020b57cec5SDimitry Andric (*SecIDMap)[SectionName] = SectionID;
3030b57cec5SDimitry Andric
3040b57cec5SDimitry Andric if (UsePreallocation)
3050b57cec5SDimitry Andric return allocateFromSlab(Size, Alignment, true /* isCode */,
3060b57cec5SDimitry Andric SectionName, SectionID);
3070b57cec5SDimitry Andric
3080b57cec5SDimitry Andric std::error_code EC;
3090b57cec5SDimitry Andric sys::MemoryBlock MB =
3100b57cec5SDimitry Andric sys::Memory::allocateMappedMemory(Size, nullptr,
3110b57cec5SDimitry Andric sys::Memory::MF_READ |
3120b57cec5SDimitry Andric sys::Memory::MF_WRITE,
3130b57cec5SDimitry Andric EC);
3140b57cec5SDimitry Andric if (!MB.base())
315349cc55cSDimitry Andric report_fatal_error(Twine("MemoryManager allocation failed: ") +
316349cc55cSDimitry Andric EC.message());
3170b57cec5SDimitry Andric FunctionMemory.push_back(SectionInfo(SectionName, MB, SectionID));
3180b57cec5SDimitry Andric return (uint8_t*)MB.base();
3190b57cec5SDimitry Andric }
3200b57cec5SDimitry Andric
allocateDataSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,StringRef SectionName,bool IsReadOnly)3210b57cec5SDimitry Andric uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size,
3220b57cec5SDimitry Andric unsigned Alignment,
3230b57cec5SDimitry Andric unsigned SectionID,
3240b57cec5SDimitry Andric StringRef SectionName,
3250b57cec5SDimitry Andric bool IsReadOnly) {
3260b57cec5SDimitry Andric if (PrintAllocationRequests)
3270b57cec5SDimitry Andric outs() << "allocateDataSection(Size = " << Size << ", Alignment = "
3280b57cec5SDimitry Andric << Alignment << ", SectionName = " << SectionName << ")\n";
3290b57cec5SDimitry Andric
3300b57cec5SDimitry Andric if (SecIDMap)
3310b57cec5SDimitry Andric (*SecIDMap)[SectionName] = SectionID;
3320b57cec5SDimitry Andric
3330b57cec5SDimitry Andric if (UsePreallocation)
3340b57cec5SDimitry Andric return allocateFromSlab(Size, Alignment, false /* isCode */, SectionName,
3350b57cec5SDimitry Andric SectionID);
3360b57cec5SDimitry Andric
3370b57cec5SDimitry Andric std::error_code EC;
3380b57cec5SDimitry Andric sys::MemoryBlock MB =
3390b57cec5SDimitry Andric sys::Memory::allocateMappedMemory(Size, nullptr,
3400b57cec5SDimitry Andric sys::Memory::MF_READ |
3410b57cec5SDimitry Andric sys::Memory::MF_WRITE,
3420b57cec5SDimitry Andric EC);
3430b57cec5SDimitry Andric if (!MB.base())
344349cc55cSDimitry Andric report_fatal_error(Twine("MemoryManager allocation failed: ") +
345349cc55cSDimitry Andric EC.message());
3460b57cec5SDimitry Andric DataMemory.push_back(SectionInfo(SectionName, MB, SectionID));
3470b57cec5SDimitry Andric return (uint8_t*)MB.base();
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric
350349cc55cSDimitry Andric // In case the execution needs TLS storage, we define a very small TLS memory
351349cc55cSDimitry Andric // area here that will be used in allocateTLSSection().
352d781ede6SDimitry Andric #if defined(__x86_64__) && defined(__ELF__) && defined(__linux__)
353349cc55cSDimitry Andric extern "C" {
354349cc55cSDimitry Andric alignas(16) __attribute__((visibility("hidden"), tls_model("initial-exec"),
355349cc55cSDimitry Andric used)) thread_local char LLVMRTDyldTLSSpace[16];
356349cc55cSDimitry Andric }
357349cc55cSDimitry Andric #endif
358349cc55cSDimitry Andric
359349cc55cSDimitry Andric TrivialMemoryManager::TLSSection
allocateTLSSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,StringRef SectionName)360349cc55cSDimitry Andric TrivialMemoryManager::allocateTLSSection(uintptr_t Size, unsigned Alignment,
361349cc55cSDimitry Andric unsigned SectionID,
362349cc55cSDimitry Andric StringRef SectionName) {
363d781ede6SDimitry Andric #if defined(__x86_64__) && defined(__ELF__) && defined(__linux__)
364349cc55cSDimitry Andric if (Size + UsedTLSStorage > sizeof(LLVMRTDyldTLSSpace)) {
365349cc55cSDimitry Andric return {};
366349cc55cSDimitry Andric }
367349cc55cSDimitry Andric
368349cc55cSDimitry Andric // Get the offset of the TLSSpace in the TLS block by using a tpoff
369349cc55cSDimitry Andric // relocation here.
370349cc55cSDimitry Andric int64_t TLSOffset;
371349cc55cSDimitry Andric asm("leaq LLVMRTDyldTLSSpace@tpoff, %0" : "=r"(TLSOffset));
372349cc55cSDimitry Andric
373349cc55cSDimitry Andric TLSSection Section;
374349cc55cSDimitry Andric // We use the storage directly as the initialization image. This means that
375349cc55cSDimitry Andric // when a new thread is spawned after this allocation, it will not be
376349cc55cSDimitry Andric // initialized correctly. This means, llvm-rtdyld will only support TLS in a
377349cc55cSDimitry Andric // single thread.
378349cc55cSDimitry Andric Section.InitializationImage =
379349cc55cSDimitry Andric reinterpret_cast<uint8_t *>(LLVMRTDyldTLSSpace + UsedTLSStorage);
380349cc55cSDimitry Andric Section.Offset = TLSOffset + UsedTLSStorage;
381349cc55cSDimitry Andric
382349cc55cSDimitry Andric UsedTLSStorage += Size;
383349cc55cSDimitry Andric
384349cc55cSDimitry Andric return Section;
385349cc55cSDimitry Andric #else
386349cc55cSDimitry Andric return {};
387349cc55cSDimitry Andric #endif
388349cc55cSDimitry Andric }
389349cc55cSDimitry Andric
3900b57cec5SDimitry Andric static const char *ProgramName;
3910b57cec5SDimitry Andric
ErrorAndExit(const Twine & Msg)3920b57cec5SDimitry Andric static void ErrorAndExit(const Twine &Msg) {
3930b57cec5SDimitry Andric errs() << ProgramName << ": error: " << Msg << "\n";
3940b57cec5SDimitry Andric exit(1);
3950b57cec5SDimitry Andric }
3960b57cec5SDimitry Andric
loadDylibs()3970b57cec5SDimitry Andric static void loadDylibs() {
3980b57cec5SDimitry Andric for (const std::string &Dylib : Dylibs) {
3990b57cec5SDimitry Andric if (!sys::fs::is_regular_file(Dylib))
400349cc55cSDimitry Andric report_fatal_error(Twine("Dylib not found: '") + Dylib + "'.");
4010b57cec5SDimitry Andric std::string ErrMsg;
4020b57cec5SDimitry Andric if (sys::DynamicLibrary::LoadLibraryPermanently(Dylib.c_str(), &ErrMsg))
403349cc55cSDimitry Andric report_fatal_error(Twine("Error loading '") + Dylib + "': " + ErrMsg);
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric }
4060b57cec5SDimitry Andric
4070b57cec5SDimitry Andric /* *** */
4080b57cec5SDimitry Andric
printLineInfoForInput(bool LoadObjects,bool UseDebugObj)4090b57cec5SDimitry Andric static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
4100b57cec5SDimitry Andric assert(LoadObjects || !UseDebugObj);
4110b57cec5SDimitry Andric
4120b57cec5SDimitry Andric // Load any dylibs requested on the command line.
4130b57cec5SDimitry Andric loadDylibs();
4140b57cec5SDimitry Andric
4150b57cec5SDimitry Andric // If we don't have any input files, read from stdin.
4160b57cec5SDimitry Andric if (!InputFileList.size())
4170b57cec5SDimitry Andric InputFileList.push_back("-");
4180b57cec5SDimitry Andric for (auto &File : InputFileList) {
4190b57cec5SDimitry Andric // Instantiate a dynamic linker.
4200b57cec5SDimitry Andric TrivialMemoryManager MemMgr;
4210b57cec5SDimitry Andric RuntimeDyld Dyld(MemMgr, MemMgr);
4220b57cec5SDimitry Andric
4230b57cec5SDimitry Andric // Load the input memory buffer.
4240b57cec5SDimitry Andric
4250b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer =
4260b57cec5SDimitry Andric MemoryBuffer::getFileOrSTDIN(File);
4270b57cec5SDimitry Andric if (std::error_code EC = InputBuffer.getError())
4280b57cec5SDimitry Andric ErrorAndExit("unable to read input: '" + EC.message() + "'");
4290b57cec5SDimitry Andric
4300b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>> MaybeObj(
4310b57cec5SDimitry Andric ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef()));
4320b57cec5SDimitry Andric
4330b57cec5SDimitry Andric if (!MaybeObj) {
4340b57cec5SDimitry Andric std::string Buf;
4350b57cec5SDimitry Andric raw_string_ostream OS(Buf);
4360b57cec5SDimitry Andric logAllUnhandledErrors(MaybeObj.takeError(), OS);
4370b57cec5SDimitry Andric OS.flush();
4380b57cec5SDimitry Andric ErrorAndExit("unable to create object file: '" + Buf + "'");
4390b57cec5SDimitry Andric }
4400b57cec5SDimitry Andric
4410b57cec5SDimitry Andric ObjectFile &Obj = **MaybeObj;
4420b57cec5SDimitry Andric
4430b57cec5SDimitry Andric OwningBinary<ObjectFile> DebugObj;
4440b57cec5SDimitry Andric std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo = nullptr;
4450b57cec5SDimitry Andric ObjectFile *SymbolObj = &Obj;
4460b57cec5SDimitry Andric if (LoadObjects) {
4470b57cec5SDimitry Andric // Load the object file
4480b57cec5SDimitry Andric LoadedObjInfo =
4490b57cec5SDimitry Andric Dyld.loadObject(Obj);
4500b57cec5SDimitry Andric
4510b57cec5SDimitry Andric if (Dyld.hasError())
4520b57cec5SDimitry Andric ErrorAndExit(Dyld.getErrorString());
4530b57cec5SDimitry Andric
4540b57cec5SDimitry Andric // Resolve all the relocations we can.
4550b57cec5SDimitry Andric Dyld.resolveRelocations();
4560b57cec5SDimitry Andric
4570b57cec5SDimitry Andric if (UseDebugObj) {
4580b57cec5SDimitry Andric DebugObj = LoadedObjInfo->getObjectForDebug(Obj);
4590b57cec5SDimitry Andric SymbolObj = DebugObj.getBinary();
4600b57cec5SDimitry Andric LoadedObjInfo.reset();
4610b57cec5SDimitry Andric }
4620b57cec5SDimitry Andric }
4630b57cec5SDimitry Andric
464349cc55cSDimitry Andric std::unique_ptr<DIContext> Context = DWARFContext::create(
465349cc55cSDimitry Andric *SymbolObj, DWARFContext::ProcessDebugRelocations::Process,
466349cc55cSDimitry Andric LoadedObjInfo.get());
4670b57cec5SDimitry Andric
4680b57cec5SDimitry Andric std::vector<std::pair<SymbolRef, uint64_t>> SymAddr =
4690b57cec5SDimitry Andric object::computeSymbolSizes(*SymbolObj);
4700b57cec5SDimitry Andric
4710b57cec5SDimitry Andric // Use symbol info to iterate functions in the object.
4720b57cec5SDimitry Andric for (const auto &P : SymAddr) {
4730b57cec5SDimitry Andric object::SymbolRef Sym = P.first;
4740b57cec5SDimitry Andric Expected<SymbolRef::Type> TypeOrErr = Sym.getType();
4750b57cec5SDimitry Andric if (!TypeOrErr) {
4760b57cec5SDimitry Andric // TODO: Actually report errors helpfully.
4770b57cec5SDimitry Andric consumeError(TypeOrErr.takeError());
4780b57cec5SDimitry Andric continue;
4790b57cec5SDimitry Andric }
4800b57cec5SDimitry Andric SymbolRef::Type Type = *TypeOrErr;
4810b57cec5SDimitry Andric if (Type == object::SymbolRef::ST_Function) {
4820b57cec5SDimitry Andric Expected<StringRef> Name = Sym.getName();
4830b57cec5SDimitry Andric if (!Name) {
4840b57cec5SDimitry Andric // TODO: Actually report errors helpfully.
4850b57cec5SDimitry Andric consumeError(Name.takeError());
4860b57cec5SDimitry Andric continue;
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric Expected<uint64_t> AddrOrErr = Sym.getAddress();
4890b57cec5SDimitry Andric if (!AddrOrErr) {
4900b57cec5SDimitry Andric // TODO: Actually report errors helpfully.
4910b57cec5SDimitry Andric consumeError(AddrOrErr.takeError());
4920b57cec5SDimitry Andric continue;
4930b57cec5SDimitry Andric }
4940b57cec5SDimitry Andric uint64_t Addr = *AddrOrErr;
4950b57cec5SDimitry Andric
4960b57cec5SDimitry Andric object::SectionedAddress Address;
4970b57cec5SDimitry Andric
4980b57cec5SDimitry Andric uint64_t Size = P.second;
4990b57cec5SDimitry Andric // If we're not using the debug object, compute the address of the
5000b57cec5SDimitry Andric // symbol in memory (rather than that in the unrelocated object file)
5010b57cec5SDimitry Andric // and use that to query the DWARFContext.
5020b57cec5SDimitry Andric if (!UseDebugObj && LoadObjects) {
5030b57cec5SDimitry Andric auto SecOrErr = Sym.getSection();
5040b57cec5SDimitry Andric if (!SecOrErr) {
5050b57cec5SDimitry Andric // TODO: Actually report errors helpfully.
5060b57cec5SDimitry Andric consumeError(SecOrErr.takeError());
5070b57cec5SDimitry Andric continue;
5080b57cec5SDimitry Andric }
5090b57cec5SDimitry Andric object::section_iterator Sec = *SecOrErr;
5100b57cec5SDimitry Andric Address.SectionIndex = Sec->getIndex();
5110b57cec5SDimitry Andric uint64_t SectionLoadAddress =
5120b57cec5SDimitry Andric LoadedObjInfo->getSectionLoadAddress(*Sec);
5130b57cec5SDimitry Andric if (SectionLoadAddress != 0)
5140b57cec5SDimitry Andric Addr += SectionLoadAddress - Sec->getAddress();
5150b57cec5SDimitry Andric } else if (auto SecOrErr = Sym.getSection())
5160b57cec5SDimitry Andric Address.SectionIndex = SecOrErr.get()->getIndex();
5170b57cec5SDimitry Andric
5180b57cec5SDimitry Andric outs() << "Function: " << *Name << ", Size = " << Size
5190b57cec5SDimitry Andric << ", Addr = " << Addr << "\n";
5200b57cec5SDimitry Andric
5210b57cec5SDimitry Andric Address.Address = Addr;
5220b57cec5SDimitry Andric DILineInfoTable Lines =
5230b57cec5SDimitry Andric Context->getLineInfoForAddressRange(Address, Size);
5240b57cec5SDimitry Andric for (auto &D : Lines) {
5250b57cec5SDimitry Andric outs() << " Line info @ " << D.first - Addr << ": "
5260b57cec5SDimitry Andric << D.second.FileName << ", line:" << D.second.Line << "\n";
5270b57cec5SDimitry Andric }
5280b57cec5SDimitry Andric }
5290b57cec5SDimitry Andric }
5300b57cec5SDimitry Andric }
5310b57cec5SDimitry Andric
5320b57cec5SDimitry Andric return 0;
5330b57cec5SDimitry Andric }
5340b57cec5SDimitry Andric
doPreallocation(TrivialMemoryManager & MemMgr)5350b57cec5SDimitry Andric static void doPreallocation(TrivialMemoryManager &MemMgr) {
5360b57cec5SDimitry Andric // Allocate a slab of memory upfront, if required. This is used if
5370b57cec5SDimitry Andric // we want to test small code models.
5380b57cec5SDimitry Andric if (static_cast<intptr_t>(PreallocMemory) < 0)
5390b57cec5SDimitry Andric report_fatal_error("Pre-allocated bytes of memory must be a positive integer.");
5400b57cec5SDimitry Andric
5410b57cec5SDimitry Andric // FIXME: Limit the amount of memory that can be preallocated?
5420b57cec5SDimitry Andric if (PreallocMemory != 0)
5430b57cec5SDimitry Andric MemMgr.preallocateSlab(PreallocMemory);
5440b57cec5SDimitry Andric }
5450b57cec5SDimitry Andric
executeInput()5460b57cec5SDimitry Andric static int executeInput() {
5470b57cec5SDimitry Andric // Load any dylibs requested on the command line.
5480b57cec5SDimitry Andric loadDylibs();
5490b57cec5SDimitry Andric
5500b57cec5SDimitry Andric // Instantiate a dynamic linker.
5510b57cec5SDimitry Andric TrivialMemoryManager MemMgr;
5520b57cec5SDimitry Andric doPreallocation(MemMgr);
5530b57cec5SDimitry Andric RuntimeDyld Dyld(MemMgr, MemMgr);
5540b57cec5SDimitry Andric
5550b57cec5SDimitry Andric // If we don't have any input files, read from stdin.
5560b57cec5SDimitry Andric if (!InputFileList.size())
5570b57cec5SDimitry Andric InputFileList.push_back("-");
5588bcb0991SDimitry Andric {
5598bcb0991SDimitry Andric TimeRegion TR(Timers ? &Timers->LoadObjectsTimer : nullptr);
5600b57cec5SDimitry Andric for (auto &File : InputFileList) {
5610b57cec5SDimitry Andric // Load the input memory buffer.
5620b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer =
5630b57cec5SDimitry Andric MemoryBuffer::getFileOrSTDIN(File);
5640b57cec5SDimitry Andric if (std::error_code EC = InputBuffer.getError())
5650b57cec5SDimitry Andric ErrorAndExit("unable to read input: '" + EC.message() + "'");
5660b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>> MaybeObj(
5670b57cec5SDimitry Andric ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef()));
5680b57cec5SDimitry Andric
5690b57cec5SDimitry Andric if (!MaybeObj) {
5700b57cec5SDimitry Andric std::string Buf;
5710b57cec5SDimitry Andric raw_string_ostream OS(Buf);
5720b57cec5SDimitry Andric logAllUnhandledErrors(MaybeObj.takeError(), OS);
5730b57cec5SDimitry Andric OS.flush();
5740b57cec5SDimitry Andric ErrorAndExit("unable to create object file: '" + Buf + "'");
5750b57cec5SDimitry Andric }
5760b57cec5SDimitry Andric
5770b57cec5SDimitry Andric ObjectFile &Obj = **MaybeObj;
5780b57cec5SDimitry Andric
5790b57cec5SDimitry Andric // Load the object file
5800b57cec5SDimitry Andric Dyld.loadObject(Obj);
5810b57cec5SDimitry Andric if (Dyld.hasError()) {
5820b57cec5SDimitry Andric ErrorAndExit(Dyld.getErrorString());
5830b57cec5SDimitry Andric }
5840b57cec5SDimitry Andric }
5858bcb0991SDimitry Andric }
5860b57cec5SDimitry Andric
5878bcb0991SDimitry Andric {
5888bcb0991SDimitry Andric TimeRegion TR(Timers ? &Timers->LinkTimer : nullptr);
5890b57cec5SDimitry Andric // Resove all the relocations we can.
5900b57cec5SDimitry Andric // FIXME: Error out if there are unresolved relocations.
5910b57cec5SDimitry Andric Dyld.resolveRelocations();
5928bcb0991SDimitry Andric }
5930b57cec5SDimitry Andric
5940b57cec5SDimitry Andric // Get the address of the entry point (_main by default).
5950b57cec5SDimitry Andric void *MainAddress = Dyld.getSymbolLocalAddress(EntryPoint);
5960b57cec5SDimitry Andric if (!MainAddress)
5970b57cec5SDimitry Andric ErrorAndExit("no definition for '" + EntryPoint + "'");
5980b57cec5SDimitry Andric
5990b57cec5SDimitry Andric // Invalidate the instruction cache for each loaded function.
6000b57cec5SDimitry Andric for (auto &FM : MemMgr.FunctionMemory) {
6010b57cec5SDimitry Andric
6020b57cec5SDimitry Andric auto &FM_MB = FM.MB;
6030b57cec5SDimitry Andric
6040b57cec5SDimitry Andric // Make sure the memory is executable.
6050b57cec5SDimitry Andric // setExecutable will call InvalidateInstructionCache.
6060b57cec5SDimitry Andric if (auto EC = sys::Memory::protectMappedMemory(FM_MB,
6070b57cec5SDimitry Andric sys::Memory::MF_READ |
6080b57cec5SDimitry Andric sys::Memory::MF_EXEC))
6090b57cec5SDimitry Andric ErrorAndExit("unable to mark function executable: '" + EC.message() +
6100b57cec5SDimitry Andric "'");
6110b57cec5SDimitry Andric }
6120b57cec5SDimitry Andric
6130b57cec5SDimitry Andric // Dispatch to _main().
6140b57cec5SDimitry Andric errs() << "loaded '" << EntryPoint << "' at: " << (void*)MainAddress << "\n";
6150b57cec5SDimitry Andric
6160b57cec5SDimitry Andric int (*Main)(int, const char**) =
6170b57cec5SDimitry Andric (int(*)(int,const char**)) uintptr_t(MainAddress);
6180b57cec5SDimitry Andric std::vector<const char *> Argv;
6190b57cec5SDimitry Andric // Use the name of the first input object module as argv[0] for the target.
6200b57cec5SDimitry Andric Argv.push_back(InputFileList[0].data());
6210b57cec5SDimitry Andric for (auto &Arg : InputArgv)
6220b57cec5SDimitry Andric Argv.push_back(Arg.data());
6230b57cec5SDimitry Andric Argv.push_back(nullptr);
6248bcb0991SDimitry Andric int Result = 0;
6258bcb0991SDimitry Andric {
6268bcb0991SDimitry Andric TimeRegion TR(Timers ? &Timers->RunTimer : nullptr);
6278bcb0991SDimitry Andric Result = Main(Argv.size() - 1, Argv.data());
6288bcb0991SDimitry Andric }
6298bcb0991SDimitry Andric
6308bcb0991SDimitry Andric return Result;
6310b57cec5SDimitry Andric }
6320b57cec5SDimitry Andric
checkAllExpressions(RuntimeDyldChecker & Checker)6330b57cec5SDimitry Andric static int checkAllExpressions(RuntimeDyldChecker &Checker) {
6340b57cec5SDimitry Andric for (const auto& CheckerFileName : CheckFiles) {
6350b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> CheckerFileBuf =
6360b57cec5SDimitry Andric MemoryBuffer::getFileOrSTDIN(CheckerFileName);
6370b57cec5SDimitry Andric if (std::error_code EC = CheckerFileBuf.getError())
6380b57cec5SDimitry Andric ErrorAndExit("unable to read input '" + CheckerFileName + "': " +
6390b57cec5SDimitry Andric EC.message());
6400b57cec5SDimitry Andric
6410b57cec5SDimitry Andric if (!Checker.checkAllRulesInBuffer("# rtdyld-check:",
6420b57cec5SDimitry Andric CheckerFileBuf.get().get()))
6430b57cec5SDimitry Andric ErrorAndExit("some checks in '" + CheckerFileName + "' failed");
6440b57cec5SDimitry Andric }
6450b57cec5SDimitry Andric return 0;
6460b57cec5SDimitry Andric }
6470b57cec5SDimitry Andric
applySpecificSectionMappings(RuntimeDyld & Dyld,const FileToSectionIDMap & FileToSecIDMap)6480b57cec5SDimitry Andric void applySpecificSectionMappings(RuntimeDyld &Dyld,
6490b57cec5SDimitry Andric const FileToSectionIDMap &FileToSecIDMap) {
6500b57cec5SDimitry Andric
6510b57cec5SDimitry Andric for (StringRef Mapping : SpecificSectionMappings) {
652*0fca6ea1SDimitry Andric size_t EqualsIdx = Mapping.find_first_of('=');
6535ffd83dbSDimitry Andric std::string SectionIDStr = std::string(Mapping.substr(0, EqualsIdx));
654*0fca6ea1SDimitry Andric size_t ComaIdx = Mapping.find_first_of(',');
6550b57cec5SDimitry Andric
6560b57cec5SDimitry Andric if (ComaIdx == StringRef::npos)
6570b57cec5SDimitry Andric report_fatal_error("Invalid section specification '" + Mapping +
6580b57cec5SDimitry Andric "'. Should be '<file name>,<section name>=<addr>'");
6590b57cec5SDimitry Andric
6600b57cec5SDimitry Andric std::string FileName = SectionIDStr.substr(0, ComaIdx);
6610b57cec5SDimitry Andric std::string SectionName = SectionIDStr.substr(ComaIdx + 1);
6620b57cec5SDimitry Andric unsigned SectionID =
6630b57cec5SDimitry Andric ExitOnErr(getSectionId(FileToSecIDMap, FileName, SectionName));
6640b57cec5SDimitry Andric
6650b57cec5SDimitry Andric auto* OldAddr = Dyld.getSectionContent(SectionID).data();
6665ffd83dbSDimitry Andric std::string NewAddrStr = std::string(Mapping.substr(EqualsIdx + 1));
6670b57cec5SDimitry Andric uint64_t NewAddr;
6680b57cec5SDimitry Andric
6690b57cec5SDimitry Andric if (StringRef(NewAddrStr).getAsInteger(0, NewAddr))
6700b57cec5SDimitry Andric report_fatal_error("Invalid section address in mapping '" + Mapping +
6710b57cec5SDimitry Andric "'.");
6720b57cec5SDimitry Andric
6730b57cec5SDimitry Andric Dyld.mapSectionAddress(OldAddr, NewAddr);
6740b57cec5SDimitry Andric }
6750b57cec5SDimitry Andric }
6760b57cec5SDimitry Andric
6770b57cec5SDimitry Andric // Scatter sections in all directions!
6780b57cec5SDimitry Andric // Remaps section addresses for -verify mode. The following command line options
6790b57cec5SDimitry Andric // can be used to customize the layout of the memory within the phony target's
6800b57cec5SDimitry Andric // address space:
6810b57cec5SDimitry Andric // -target-addr-start <s> -- Specify where the phony target address range starts.
6820b57cec5SDimitry Andric // -target-addr-end <e> -- Specify where the phony target address range ends.
6830b57cec5SDimitry Andric // -target-section-sep <d> -- Specify how big a gap should be left between the
6840b57cec5SDimitry Andric // end of one section and the start of the next.
6850b57cec5SDimitry Andric // Defaults to zero. Set to something big
6860b57cec5SDimitry Andric // (e.g. 1 << 32) to stress-test stubs, GOTs, etc.
6870b57cec5SDimitry Andric //
remapSectionsAndSymbols(const llvm::Triple & TargetTriple,RuntimeDyld & Dyld,TrivialMemoryManager & MemMgr)6880b57cec5SDimitry Andric static void remapSectionsAndSymbols(const llvm::Triple &TargetTriple,
6890b57cec5SDimitry Andric RuntimeDyld &Dyld,
6900b57cec5SDimitry Andric TrivialMemoryManager &MemMgr) {
6910b57cec5SDimitry Andric
6920b57cec5SDimitry Andric // Set up a work list (section addr/size pairs).
6930b57cec5SDimitry Andric typedef std::list<const TrivialMemoryManager::SectionInfo*> WorklistT;
6940b57cec5SDimitry Andric WorklistT Worklist;
6950b57cec5SDimitry Andric
6960b57cec5SDimitry Andric for (const auto& CodeSection : MemMgr.FunctionMemory)
6970b57cec5SDimitry Andric Worklist.push_back(&CodeSection);
6980b57cec5SDimitry Andric for (const auto& DataSection : MemMgr.DataMemory)
6990b57cec5SDimitry Andric Worklist.push_back(&DataSection);
7000b57cec5SDimitry Andric
7010b57cec5SDimitry Andric // Keep an "already allocated" mapping of section target addresses to sizes.
7020b57cec5SDimitry Andric // Sections whose address mappings aren't specified on the command line will
7030b57cec5SDimitry Andric // allocated around the explicitly mapped sections while maintaining the
7040b57cec5SDimitry Andric // minimum separation.
7050b57cec5SDimitry Andric std::map<uint64_t, uint64_t> AlreadyAllocated;
7060b57cec5SDimitry Andric
7070b57cec5SDimitry Andric // Move the previously applied mappings (whether explicitly specified on the
7080b57cec5SDimitry Andric // command line, or implicitly set by RuntimeDyld) into the already-allocated
7090b57cec5SDimitry Andric // map.
7100b57cec5SDimitry Andric for (WorklistT::iterator I = Worklist.begin(), E = Worklist.end();
7110b57cec5SDimitry Andric I != E;) {
7120b57cec5SDimitry Andric WorklistT::iterator Tmp = I;
7130b57cec5SDimitry Andric ++I;
7140b57cec5SDimitry Andric
7150b57cec5SDimitry Andric auto LoadAddr = Dyld.getSectionLoadAddress((*Tmp)->SectionID);
7160b57cec5SDimitry Andric
7170b57cec5SDimitry Andric if (LoadAddr != static_cast<uint64_t>(
7180b57cec5SDimitry Andric reinterpret_cast<uintptr_t>((*Tmp)->MB.base()))) {
7190b57cec5SDimitry Andric // A section will have a LoadAddr of 0 if it wasn't loaded for whatever
7200b57cec5SDimitry Andric // reason (e.g. zero byte COFF sections). Don't include those sections in
7210b57cec5SDimitry Andric // the allocation map.
7220b57cec5SDimitry Andric if (LoadAddr != 0)
7230b57cec5SDimitry Andric AlreadyAllocated[LoadAddr] = (*Tmp)->MB.allocatedSize();
7240b57cec5SDimitry Andric Worklist.erase(Tmp);
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric }
7270b57cec5SDimitry Andric
7280b57cec5SDimitry Andric // If the -target-addr-end option wasn't explicitly passed, then set it to a
7290b57cec5SDimitry Andric // sensible default based on the target triple.
7300b57cec5SDimitry Andric if (TargetAddrEnd.getNumOccurrences() == 0) {
7310b57cec5SDimitry Andric if (TargetTriple.isArch16Bit())
7320b57cec5SDimitry Andric TargetAddrEnd = (1ULL << 16) - 1;
7330b57cec5SDimitry Andric else if (TargetTriple.isArch32Bit())
7340b57cec5SDimitry Andric TargetAddrEnd = (1ULL << 32) - 1;
7350b57cec5SDimitry Andric // TargetAddrEnd already has a sensible default for 64-bit systems, so
7360b57cec5SDimitry Andric // there's nothing to do in the 64-bit case.
7370b57cec5SDimitry Andric }
7380b57cec5SDimitry Andric
7390b57cec5SDimitry Andric // Process any elements remaining in the worklist.
7400b57cec5SDimitry Andric while (!Worklist.empty()) {
7410b57cec5SDimitry Andric auto *CurEntry = Worklist.front();
7420b57cec5SDimitry Andric Worklist.pop_front();
7430b57cec5SDimitry Andric
7440b57cec5SDimitry Andric uint64_t NextSectionAddr = TargetAddrStart;
7450b57cec5SDimitry Andric
7460b57cec5SDimitry Andric for (const auto &Alloc : AlreadyAllocated)
7470b57cec5SDimitry Andric if (NextSectionAddr + CurEntry->MB.allocatedSize() + TargetSectionSep <=
7480b57cec5SDimitry Andric Alloc.first)
7490b57cec5SDimitry Andric break;
7500b57cec5SDimitry Andric else
7510b57cec5SDimitry Andric NextSectionAddr = Alloc.first + Alloc.second + TargetSectionSep;
7520b57cec5SDimitry Andric
7530b57cec5SDimitry Andric Dyld.mapSectionAddress(CurEntry->MB.base(), NextSectionAddr);
7540b57cec5SDimitry Andric AlreadyAllocated[NextSectionAddr] = CurEntry->MB.allocatedSize();
7550b57cec5SDimitry Andric }
7560b57cec5SDimitry Andric
7570b57cec5SDimitry Andric // Add dummy symbols to the memory manager.
7580b57cec5SDimitry Andric for (const auto &Mapping : DummySymbolMappings) {
7590b57cec5SDimitry Andric size_t EqualsIdx = Mapping.find_first_of('=');
7600b57cec5SDimitry Andric
7610b57cec5SDimitry Andric if (EqualsIdx == StringRef::npos)
762349cc55cSDimitry Andric report_fatal_error(Twine("Invalid dummy symbol specification '") +
763349cc55cSDimitry Andric Mapping + "'. Should be '<symbol name>=<addr>'");
7640b57cec5SDimitry Andric
7650b57cec5SDimitry Andric std::string Symbol = Mapping.substr(0, EqualsIdx);
7660b57cec5SDimitry Andric std::string AddrStr = Mapping.substr(EqualsIdx + 1);
7670b57cec5SDimitry Andric
7680b57cec5SDimitry Andric uint64_t Addr;
7690b57cec5SDimitry Andric if (StringRef(AddrStr).getAsInteger(0, Addr))
770349cc55cSDimitry Andric report_fatal_error(Twine("Invalid symbol mapping '") + Mapping + "'.");
7710b57cec5SDimitry Andric
7720b57cec5SDimitry Andric MemMgr.addDummySymbol(Symbol, Addr);
7730b57cec5SDimitry Andric }
7740b57cec5SDimitry Andric }
7750b57cec5SDimitry Andric
7760b57cec5SDimitry Andric // Load and link the objects specified on the command line, but do not execute
7770b57cec5SDimitry Andric // anything. Instead, attach a RuntimeDyldChecker instance and call it to
7780b57cec5SDimitry Andric // verify the correctness of the linked memory.
linkAndVerify()7790b57cec5SDimitry Andric static int linkAndVerify() {
7800b57cec5SDimitry Andric
7810b57cec5SDimitry Andric // Check for missing triple.
7820b57cec5SDimitry Andric if (TripleName == "")
7830b57cec5SDimitry Andric ErrorAndExit("-triple required when running in -verify mode.");
7840b57cec5SDimitry Andric
7850b57cec5SDimitry Andric // Look up the target and build the disassembler.
7860b57cec5SDimitry Andric Triple TheTriple(Triple::normalize(TripleName));
7870b57cec5SDimitry Andric std::string ErrorStr;
7880b57cec5SDimitry Andric const Target *TheTarget =
7890b57cec5SDimitry Andric TargetRegistry::lookupTarget("", TheTriple, ErrorStr);
7900b57cec5SDimitry Andric if (!TheTarget)
7910b57cec5SDimitry Andric ErrorAndExit("Error accessing target '" + TripleName + "': " + ErrorStr);
7920b57cec5SDimitry Andric
7930b57cec5SDimitry Andric TripleName = TheTriple.getTriple();
7940b57cec5SDimitry Andric
7950b57cec5SDimitry Andric std::unique_ptr<MCSubtargetInfo> STI(
7960b57cec5SDimitry Andric TheTarget->createMCSubtargetInfo(TripleName, MCPU, ""));
7970b57cec5SDimitry Andric if (!STI)
7980b57cec5SDimitry Andric ErrorAndExit("Unable to create subtarget info!");
7990b57cec5SDimitry Andric
8000b57cec5SDimitry Andric std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
8010b57cec5SDimitry Andric if (!MRI)
8020b57cec5SDimitry Andric ErrorAndExit("Unable to create target register info!");
8030b57cec5SDimitry Andric
804480093f4SDimitry Andric MCTargetOptions MCOptions;
805480093f4SDimitry Andric std::unique_ptr<MCAsmInfo> MAI(
806480093f4SDimitry Andric TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
8070b57cec5SDimitry Andric if (!MAI)
8080b57cec5SDimitry Andric ErrorAndExit("Unable to create target asm info!");
8090b57cec5SDimitry Andric
810fe6060f1SDimitry Andric MCContext Ctx(Triple(TripleName), MAI.get(), MRI.get(), STI.get());
8110b57cec5SDimitry Andric
8120b57cec5SDimitry Andric std::unique_ptr<MCDisassembler> Disassembler(
8130b57cec5SDimitry Andric TheTarget->createMCDisassembler(*STI, Ctx));
8140b57cec5SDimitry Andric if (!Disassembler)
8150b57cec5SDimitry Andric ErrorAndExit("Unable to create disassembler!");
8160b57cec5SDimitry Andric
8170b57cec5SDimitry Andric std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
818e8d8bef9SDimitry Andric if (!MII)
819e8d8bef9SDimitry Andric ErrorAndExit("Unable to create target instruction info!");
8200b57cec5SDimitry Andric
8210b57cec5SDimitry Andric std::unique_ptr<MCInstPrinter> InstPrinter(
8220b57cec5SDimitry Andric TheTarget->createMCInstPrinter(Triple(TripleName), 0, *MAI, *MII, *MRI));
8230b57cec5SDimitry Andric
8240b57cec5SDimitry Andric // Load any dylibs requested on the command line.
8250b57cec5SDimitry Andric loadDylibs();
8260b57cec5SDimitry Andric
8270b57cec5SDimitry Andric // Instantiate a dynamic linker.
8280b57cec5SDimitry Andric TrivialMemoryManager MemMgr;
8290b57cec5SDimitry Andric doPreallocation(MemMgr);
8300b57cec5SDimitry Andric
8310b57cec5SDimitry Andric struct StubID {
8320b57cec5SDimitry Andric unsigned SectionID;
8330b57cec5SDimitry Andric uint32_t Offset;
8340b57cec5SDimitry Andric };
8350b57cec5SDimitry Andric using StubInfos = StringMap<StubID>;
8360b57cec5SDimitry Andric using StubContainers = StringMap<StubInfos>;
8370b57cec5SDimitry Andric
8380b57cec5SDimitry Andric StubContainers StubMap;
8390b57cec5SDimitry Andric RuntimeDyld Dyld(MemMgr, MemMgr);
8400b57cec5SDimitry Andric Dyld.setProcessAllSections(true);
8410b57cec5SDimitry Andric
8420b57cec5SDimitry Andric Dyld.setNotifyStubEmitted([&StubMap](StringRef FilePath,
8430b57cec5SDimitry Andric StringRef SectionName,
8440b57cec5SDimitry Andric StringRef SymbolName, unsigned SectionID,
8450b57cec5SDimitry Andric uint32_t StubOffset) {
8460b57cec5SDimitry Andric std::string ContainerName =
8470b57cec5SDimitry Andric (sys::path::filename(FilePath) + "/" + SectionName).str();
8480b57cec5SDimitry Andric StubMap[ContainerName][SymbolName] = {SectionID, StubOffset};
8490b57cec5SDimitry Andric });
8500b57cec5SDimitry Andric
8510b57cec5SDimitry Andric auto GetSymbolInfo =
8520b57cec5SDimitry Andric [&Dyld, &MemMgr](
8530b57cec5SDimitry Andric StringRef Symbol) -> Expected<RuntimeDyldChecker::MemoryRegionInfo> {
8540b57cec5SDimitry Andric RuntimeDyldChecker::MemoryRegionInfo SymInfo;
8550b57cec5SDimitry Andric
8560b57cec5SDimitry Andric // First get the target address.
8570b57cec5SDimitry Andric if (auto InternalSymbol = Dyld.getSymbol(Symbol))
8580b57cec5SDimitry Andric SymInfo.setTargetAddress(InternalSymbol.getAddress());
8590b57cec5SDimitry Andric else {
8600b57cec5SDimitry Andric // Symbol not found in RuntimeDyld. Fall back to external lookup.
8610b57cec5SDimitry Andric #ifdef _MSC_VER
8620b57cec5SDimitry Andric using ExpectedLookupResult =
8630b57cec5SDimitry Andric MSVCPExpected<JITSymbolResolver::LookupResult>;
8640b57cec5SDimitry Andric #else
8650b57cec5SDimitry Andric using ExpectedLookupResult = Expected<JITSymbolResolver::LookupResult>;
8660b57cec5SDimitry Andric #endif
8670b57cec5SDimitry Andric
8680b57cec5SDimitry Andric auto ResultP = std::make_shared<std::promise<ExpectedLookupResult>>();
8690b57cec5SDimitry Andric auto ResultF = ResultP->get_future();
8700b57cec5SDimitry Andric
8710b57cec5SDimitry Andric MemMgr.lookup(JITSymbolResolver::LookupSet({Symbol}),
8720b57cec5SDimitry Andric [=](Expected<JITSymbolResolver::LookupResult> Result) {
8730b57cec5SDimitry Andric ResultP->set_value(std::move(Result));
8740b57cec5SDimitry Andric });
8750b57cec5SDimitry Andric
8760b57cec5SDimitry Andric auto Result = ResultF.get();
8770b57cec5SDimitry Andric if (!Result)
8780b57cec5SDimitry Andric return Result.takeError();
8790b57cec5SDimitry Andric
8800b57cec5SDimitry Andric auto I = Result->find(Symbol);
8810b57cec5SDimitry Andric assert(I != Result->end() &&
8820b57cec5SDimitry Andric "Expected symbol address if no error occurred");
8830b57cec5SDimitry Andric SymInfo.setTargetAddress(I->second.getAddress());
8840b57cec5SDimitry Andric }
8850b57cec5SDimitry Andric
8860b57cec5SDimitry Andric // Now find the symbol content if possible (otherwise leave content as a
8870b57cec5SDimitry Andric // default-constructed StringRef).
8880b57cec5SDimitry Andric if (auto *SymAddr = Dyld.getSymbolLocalAddress(Symbol)) {
8890b57cec5SDimitry Andric unsigned SectionID = Dyld.getSymbolSectionID(Symbol);
8900b57cec5SDimitry Andric if (SectionID != ~0U) {
8910b57cec5SDimitry Andric char *CSymAddr = static_cast<char *>(SymAddr);
8920b57cec5SDimitry Andric StringRef SecContent = Dyld.getSectionContent(SectionID);
8930b57cec5SDimitry Andric uint64_t SymSize = SecContent.size() - (CSymAddr - SecContent.data());
894fe6060f1SDimitry Andric SymInfo.setContent(ArrayRef<char>(CSymAddr, SymSize));
8955f757f3fSDimitry Andric SymInfo.setTargetFlags(
8965f757f3fSDimitry Andric Dyld.getSymbol(Symbol).getFlags().getTargetFlags());
8970b57cec5SDimitry Andric }
8980b57cec5SDimitry Andric }
8990b57cec5SDimitry Andric return SymInfo;
9000b57cec5SDimitry Andric };
9010b57cec5SDimitry Andric
9020b57cec5SDimitry Andric auto IsSymbolValid = [&Dyld, GetSymbolInfo](StringRef Symbol) {
9030b57cec5SDimitry Andric if (Dyld.getSymbol(Symbol))
9040b57cec5SDimitry Andric return true;
9050b57cec5SDimitry Andric auto SymInfo = GetSymbolInfo(Symbol);
9060b57cec5SDimitry Andric if (!SymInfo) {
9070b57cec5SDimitry Andric logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
9080b57cec5SDimitry Andric return false;
9090b57cec5SDimitry Andric }
9100b57cec5SDimitry Andric return SymInfo->getTargetAddress() != 0;
9110b57cec5SDimitry Andric };
9120b57cec5SDimitry Andric
9130b57cec5SDimitry Andric FileToSectionIDMap FileToSecIDMap;
9140b57cec5SDimitry Andric
9150b57cec5SDimitry Andric auto GetSectionInfo = [&Dyld, &FileToSecIDMap](StringRef FileName,
9160b57cec5SDimitry Andric StringRef SectionName)
9170b57cec5SDimitry Andric -> Expected<RuntimeDyldChecker::MemoryRegionInfo> {
9180b57cec5SDimitry Andric auto SectionID = getSectionId(FileToSecIDMap, FileName, SectionName);
9190b57cec5SDimitry Andric if (!SectionID)
9200b57cec5SDimitry Andric return SectionID.takeError();
9210b57cec5SDimitry Andric RuntimeDyldChecker::MemoryRegionInfo SecInfo;
9220b57cec5SDimitry Andric SecInfo.setTargetAddress(Dyld.getSectionLoadAddress(*SectionID));
923fe6060f1SDimitry Andric StringRef SecContent = Dyld.getSectionContent(*SectionID);
924fe6060f1SDimitry Andric SecInfo.setContent(ArrayRef<char>(SecContent.data(), SecContent.size()));
9250b57cec5SDimitry Andric return SecInfo;
9260b57cec5SDimitry Andric };
9270b57cec5SDimitry Andric
9280b57cec5SDimitry Andric auto GetStubInfo = [&Dyld, &StubMap](StringRef StubContainer,
9297a6dacacSDimitry Andric StringRef SymbolName,
9307a6dacacSDimitry Andric StringRef KindNameFilter)
9310b57cec5SDimitry Andric -> Expected<RuntimeDyldChecker::MemoryRegionInfo> {
9320b57cec5SDimitry Andric if (!StubMap.count(StubContainer))
9330b57cec5SDimitry Andric return make_error<StringError>("Stub container not found: " +
9340b57cec5SDimitry Andric StubContainer,
9350b57cec5SDimitry Andric inconvertibleErrorCode());
9360b57cec5SDimitry Andric if (!StubMap[StubContainer].count(SymbolName))
9370b57cec5SDimitry Andric return make_error<StringError>("Symbol name " + SymbolName +
9380b57cec5SDimitry Andric " in stub container " + StubContainer,
9390b57cec5SDimitry Andric inconvertibleErrorCode());
9400b57cec5SDimitry Andric auto &SI = StubMap[StubContainer][SymbolName];
9410b57cec5SDimitry Andric RuntimeDyldChecker::MemoryRegionInfo StubMemInfo;
9420b57cec5SDimitry Andric StubMemInfo.setTargetAddress(Dyld.getSectionLoadAddress(SI.SectionID) +
9430b57cec5SDimitry Andric SI.Offset);
944fe6060f1SDimitry Andric StringRef SecContent =
945fe6060f1SDimitry Andric Dyld.getSectionContent(SI.SectionID).substr(SI.Offset);
9460b57cec5SDimitry Andric StubMemInfo.setContent(
947fe6060f1SDimitry Andric ArrayRef<char>(SecContent.data(), SecContent.size()));
9480b57cec5SDimitry Andric return StubMemInfo;
9490b57cec5SDimitry Andric };
9500b57cec5SDimitry Andric
9517a6dacacSDimitry Andric auto GetGOTInfo = [&GetStubInfo](StringRef StubContainer,
9527a6dacacSDimitry Andric StringRef SymbolName) {
9537a6dacacSDimitry Andric return GetStubInfo(StubContainer, SymbolName, "");
9547a6dacacSDimitry Andric };
9557a6dacacSDimitry Andric
9560b57cec5SDimitry Andric // We will initialize this below once we have the first object file and can
9570b57cec5SDimitry Andric // know the endianness.
9580b57cec5SDimitry Andric std::unique_ptr<RuntimeDyldChecker> Checker;
9590b57cec5SDimitry Andric
9600b57cec5SDimitry Andric // If we don't have any input files, read from stdin.
9610b57cec5SDimitry Andric if (!InputFileList.size())
9620b57cec5SDimitry Andric InputFileList.push_back("-");
9630b57cec5SDimitry Andric for (auto &InputFile : InputFileList) {
9640b57cec5SDimitry Andric // Load the input memory buffer.
9650b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer =
9660b57cec5SDimitry Andric MemoryBuffer::getFileOrSTDIN(InputFile);
9670b57cec5SDimitry Andric
9680b57cec5SDimitry Andric if (std::error_code EC = InputBuffer.getError())
9690b57cec5SDimitry Andric ErrorAndExit("unable to read input: '" + EC.message() + "'");
9700b57cec5SDimitry Andric
9710b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>> MaybeObj(
9720b57cec5SDimitry Andric ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef()));
9730b57cec5SDimitry Andric
9740b57cec5SDimitry Andric if (!MaybeObj) {
9750b57cec5SDimitry Andric std::string Buf;
9760b57cec5SDimitry Andric raw_string_ostream OS(Buf);
9770b57cec5SDimitry Andric logAllUnhandledErrors(MaybeObj.takeError(), OS);
9780b57cec5SDimitry Andric OS.flush();
9790b57cec5SDimitry Andric ErrorAndExit("unable to create object file: '" + Buf + "'");
9800b57cec5SDimitry Andric }
9810b57cec5SDimitry Andric
9820b57cec5SDimitry Andric ObjectFile &Obj = **MaybeObj;
9830b57cec5SDimitry Andric
9840b57cec5SDimitry Andric if (!Checker)
9858bcb0991SDimitry Andric Checker = std::make_unique<RuntimeDyldChecker>(
9867a6dacacSDimitry Andric IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo, GetGOTInfo,
9875f757f3fSDimitry Andric Obj.isLittleEndian() ? llvm::endianness::little
9885f757f3fSDimitry Andric : llvm::endianness::big,
9895f757f3fSDimitry Andric TheTriple, MCPU, SubtargetFeatures(), dbgs());
9900b57cec5SDimitry Andric
9910b57cec5SDimitry Andric auto FileName = sys::path::filename(InputFile);
9920b57cec5SDimitry Andric MemMgr.setSectionIDsMap(&FileToSecIDMap[FileName]);
9930b57cec5SDimitry Andric
9940b57cec5SDimitry Andric // Load the object file
9950b57cec5SDimitry Andric Dyld.loadObject(Obj);
9960b57cec5SDimitry Andric if (Dyld.hasError()) {
9970b57cec5SDimitry Andric ErrorAndExit(Dyld.getErrorString());
9980b57cec5SDimitry Andric }
9990b57cec5SDimitry Andric }
10000b57cec5SDimitry Andric
10010b57cec5SDimitry Andric // Re-map the section addresses into the phony target address space and add
10020b57cec5SDimitry Andric // dummy symbols.
10030b57cec5SDimitry Andric applySpecificSectionMappings(Dyld, FileToSecIDMap);
10040b57cec5SDimitry Andric remapSectionsAndSymbols(TheTriple, Dyld, MemMgr);
10050b57cec5SDimitry Andric
10060b57cec5SDimitry Andric // Resolve all the relocations we can.
10070b57cec5SDimitry Andric Dyld.resolveRelocations();
10080b57cec5SDimitry Andric
10090b57cec5SDimitry Andric // Register EH frames.
10100b57cec5SDimitry Andric Dyld.registerEHFrames();
10110b57cec5SDimitry Andric
10120b57cec5SDimitry Andric int ErrorCode = checkAllExpressions(*Checker);
10130b57cec5SDimitry Andric if (Dyld.hasError())
10140b57cec5SDimitry Andric ErrorAndExit("RTDyld reported an error applying relocations:\n " +
10150b57cec5SDimitry Andric Dyld.getErrorString());
10160b57cec5SDimitry Andric
10170b57cec5SDimitry Andric return ErrorCode;
10180b57cec5SDimitry Andric }
10190b57cec5SDimitry Andric
main(int argc,char ** argv)10200b57cec5SDimitry Andric int main(int argc, char **argv) {
10210b57cec5SDimitry Andric InitLLVM X(argc, argv);
10220b57cec5SDimitry Andric ProgramName = argv[0];
10230b57cec5SDimitry Andric
10240b57cec5SDimitry Andric llvm::InitializeAllTargetInfos();
10250b57cec5SDimitry Andric llvm::InitializeAllTargetMCs();
10260b57cec5SDimitry Andric llvm::InitializeAllDisassemblers();
10270b57cec5SDimitry Andric
1028fe6060f1SDimitry Andric cl::HideUnrelatedOptions({&RTDyldCategory, &getColorCategory()});
10290b57cec5SDimitry Andric cl::ParseCommandLineOptions(argc, argv, "llvm MC-JIT tool\n");
10300b57cec5SDimitry Andric
10310b57cec5SDimitry Andric ExitOnErr.setBanner(std::string(argv[0]) + ": ");
10320b57cec5SDimitry Andric
10338bcb0991SDimitry Andric Timers = ShowTimes ? std::make_unique<RTDyldTimers>() : nullptr;
10348bcb0991SDimitry Andric
1035349cc55cSDimitry Andric int Result = 0;
10360b57cec5SDimitry Andric switch (Action) {
10370b57cec5SDimitry Andric case AC_Execute:
10388bcb0991SDimitry Andric Result = executeInput();
10398bcb0991SDimitry Andric break;
10400b57cec5SDimitry Andric case AC_PrintDebugLineInfo:
10418bcb0991SDimitry Andric Result =
10428bcb0991SDimitry Andric printLineInfoForInput(/* LoadObjects */ true, /* UseDebugObj */ true);
10438bcb0991SDimitry Andric break;
10440b57cec5SDimitry Andric case AC_PrintLineInfo:
10458bcb0991SDimitry Andric Result =
10468bcb0991SDimitry Andric printLineInfoForInput(/* LoadObjects */ true, /* UseDebugObj */ false);
10478bcb0991SDimitry Andric break;
10480b57cec5SDimitry Andric case AC_PrintObjectLineInfo:
10498bcb0991SDimitry Andric Result =
10508bcb0991SDimitry Andric printLineInfoForInput(/* LoadObjects */ false, /* UseDebugObj */ false);
10518bcb0991SDimitry Andric break;
10520b57cec5SDimitry Andric case AC_Verify:
10538bcb0991SDimitry Andric Result = linkAndVerify();
10548bcb0991SDimitry Andric break;
10550b57cec5SDimitry Andric }
10568bcb0991SDimitry Andric return Result;
10570b57cec5SDimitry Andric }
1058