xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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