10b57cec5SDimitry Andric //===-- RuntimeDyldImpl.h - Run-time dynamic linker for MC-JIT --*- C++ -*-===// 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 // Interface for the implementations of runtime dynamic linker facilities. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDIMPL_H 140b57cec5SDimitry Andric #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDIMPL_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 170b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h" 180b57cec5SDimitry Andric #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" 190b57cec5SDimitry Andric #include "llvm/ExecutionEngine/RuntimeDyld.h" 200b57cec5SDimitry Andric #include "llvm/ExecutionEngine/RuntimeDyldChecker.h" 210b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 220b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 230b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 240b57cec5SDimitry Andric #include "llvm/Support/Format.h" 250b57cec5SDimitry Andric #include "llvm/Support/Mutex.h" 260b57cec5SDimitry Andric #include "llvm/Support/SwapByteOrder.h" 2706c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h" 2806c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 295ffd83dbSDimitry Andric #include <deque> 300b57cec5SDimitry Andric #include <map> 310b57cec5SDimitry Andric #include <system_error> 320b57cec5SDimitry Andric #include <unordered_map> 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric using namespace llvm; 350b57cec5SDimitry Andric using namespace llvm::object; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric namespace llvm { 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric #define UNIMPLEMENTED_RELOC(RelType) \ 400b57cec5SDimitry Andric case RelType: \ 410b57cec5SDimitry Andric return make_error<RuntimeDyldError>("Unimplemented relocation: " #RelType) 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric /// SectionEntry - represents a section emitted into memory by the dynamic 440b57cec5SDimitry Andric /// linker. 450b57cec5SDimitry Andric class SectionEntry { 460b57cec5SDimitry Andric /// Name - section name. 470b57cec5SDimitry Andric std::string Name; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric /// Address - address in the linker's memory where the section resides. 500b57cec5SDimitry Andric uint8_t *Address; 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric /// Size - section size. Doesn't include the stubs. 530b57cec5SDimitry Andric size_t Size; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric /// LoadAddress - the address of the section in the target process's memory. 560b57cec5SDimitry Andric /// Used for situations in which JIT-ed code is being executed in the address 570b57cec5SDimitry Andric /// space of a separate process. If the code executes in the same address 580b57cec5SDimitry Andric /// space where it was JIT-ed, this just equals Address. 590b57cec5SDimitry Andric uint64_t LoadAddress; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric /// StubOffset - used for architectures with stub functions for far 620b57cec5SDimitry Andric /// relocations (like ARM). 630b57cec5SDimitry Andric uintptr_t StubOffset; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric /// The total amount of space allocated for this section. This includes the 660b57cec5SDimitry Andric /// section size and the maximum amount of space that the stubs can occupy. 670b57cec5SDimitry Andric size_t AllocationSize; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric /// ObjAddress - address of the section in the in-memory object file. Used 700b57cec5SDimitry Andric /// for calculating relocations in some object formats (like MachO). 710b57cec5SDimitry Andric uintptr_t ObjAddress; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric public: 740b57cec5SDimitry Andric SectionEntry(StringRef name, uint8_t *address, size_t size, 750b57cec5SDimitry Andric size_t allocationSize, uintptr_t objAddress) 765ffd83dbSDimitry Andric : Name(std::string(name)), Address(address), Size(size), 770b57cec5SDimitry Andric LoadAddress(reinterpret_cast<uintptr_t>(address)), StubOffset(size), 780b57cec5SDimitry Andric AllocationSize(allocationSize), ObjAddress(objAddress) { 790b57cec5SDimitry Andric // AllocationSize is used only in asserts, prevent an "unused private field" 800b57cec5SDimitry Andric // warning: 810b57cec5SDimitry Andric (void)AllocationSize; 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric StringRef getName() const { return Name; } 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric uint8_t *getAddress() const { return Address; } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric /// Return the address of this section with an offset. 890b57cec5SDimitry Andric uint8_t *getAddressWithOffset(unsigned OffsetBytes) const { 900b57cec5SDimitry Andric assert(OffsetBytes <= AllocationSize && "Offset out of bounds!"); 910b57cec5SDimitry Andric return Address + OffsetBytes; 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric size_t getSize() const { return Size; } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric uint64_t getLoadAddress() const { return LoadAddress; } 970b57cec5SDimitry Andric void setLoadAddress(uint64_t LA) { LoadAddress = LA; } 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric /// Return the load address of this section with an offset. 1000b57cec5SDimitry Andric uint64_t getLoadAddressWithOffset(unsigned OffsetBytes) const { 1010b57cec5SDimitry Andric assert(OffsetBytes <= AllocationSize && "Offset out of bounds!"); 1020b57cec5SDimitry Andric return LoadAddress + OffsetBytes; 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric uintptr_t getStubOffset() const { return StubOffset; } 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric void advanceStubOffset(unsigned StubSize) { 1080b57cec5SDimitry Andric StubOffset += StubSize; 1090b57cec5SDimitry Andric assert(StubOffset <= AllocationSize && "Not enough space allocated!"); 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric uintptr_t getObjAddress() const { return ObjAddress; } 1130b57cec5SDimitry Andric }; 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric /// RelocationEntry - used to represent relocations internally in the dynamic 1160b57cec5SDimitry Andric /// linker. 1170b57cec5SDimitry Andric class RelocationEntry { 1180b57cec5SDimitry Andric public: 1190b57cec5SDimitry Andric /// Offset - offset into the section. 1200b57cec5SDimitry Andric uint64_t Offset; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric /// Addend - the relocation addend encoded in the instruction itself. Also 1230b57cec5SDimitry Andric /// used to make a relocation section relative instead of symbol relative. 1240b57cec5SDimitry Andric int64_t Addend; 1250b57cec5SDimitry Andric 126*0fca6ea1SDimitry Andric /// SectionID - the section this relocation points to. 127*0fca6ea1SDimitry Andric unsigned SectionID; 128*0fca6ea1SDimitry Andric 129*0fca6ea1SDimitry Andric /// RelType - relocation type. 130*0fca6ea1SDimitry Andric uint32_t RelType; 131*0fca6ea1SDimitry Andric 1320b57cec5SDimitry Andric struct SectionPair { 1330b57cec5SDimitry Andric uint32_t SectionA; 1340b57cec5SDimitry Andric uint32_t SectionB; 1350b57cec5SDimitry Andric }; 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric /// SymOffset - Section offset of the relocation entry's symbol (used for GOT 1380b57cec5SDimitry Andric /// lookup). 1390b57cec5SDimitry Andric union { 1400b57cec5SDimitry Andric uint64_t SymOffset; 1410b57cec5SDimitry Andric SectionPair Sections; 1420b57cec5SDimitry Andric }; 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric /// The size of this relocation (MachO specific). 1450b57cec5SDimitry Andric unsigned Size; 1460b57cec5SDimitry Andric 147*0fca6ea1SDimitry Andric /// True if this is a PCRel relocation (MachO specific). 148*0fca6ea1SDimitry Andric bool IsPCRel : 1; 149*0fca6ea1SDimitry Andric 1500b57cec5SDimitry Andric // ARM (MachO and COFF) specific. 151*0fca6ea1SDimitry Andric bool IsTargetThumbFunc : 1; 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend) 154*0fca6ea1SDimitry Andric : Offset(offset), Addend(addend), SectionID(id), RelType(type), 155*0fca6ea1SDimitry Andric SymOffset(0), Size(0), IsPCRel(false), IsTargetThumbFunc(false) {} 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, 1580b57cec5SDimitry Andric uint64_t symoffset) 159*0fca6ea1SDimitry Andric : Offset(offset), Addend(addend), SectionID(id), RelType(type), 160*0fca6ea1SDimitry Andric SymOffset(symoffset), Size(0), IsPCRel(false), 1610b57cec5SDimitry Andric IsTargetThumbFunc(false) {} 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, 1640b57cec5SDimitry Andric bool IsPCRel, unsigned Size) 165*0fca6ea1SDimitry Andric : Offset(offset), Addend(addend), SectionID(id), RelType(type), 166*0fca6ea1SDimitry Andric SymOffset(0), Size(Size), IsPCRel(IsPCRel), IsTargetThumbFunc(false) {} 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, 1690b57cec5SDimitry Andric unsigned SectionA, uint64_t SectionAOffset, unsigned SectionB, 1700b57cec5SDimitry Andric uint64_t SectionBOffset, bool IsPCRel, unsigned Size) 171*0fca6ea1SDimitry Andric : Offset(offset), Addend(SectionAOffset - SectionBOffset + addend), 172*0fca6ea1SDimitry Andric SectionID(id), RelType(type), Size(Size), IsPCRel(IsPCRel), 173*0fca6ea1SDimitry Andric IsTargetThumbFunc(false) { 1740b57cec5SDimitry Andric Sections.SectionA = SectionA; 1750b57cec5SDimitry Andric Sections.SectionB = SectionB; 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, 1790b57cec5SDimitry Andric unsigned SectionA, uint64_t SectionAOffset, unsigned SectionB, 1800b57cec5SDimitry Andric uint64_t SectionBOffset, bool IsPCRel, unsigned Size, 1810b57cec5SDimitry Andric bool IsTargetThumbFunc) 182*0fca6ea1SDimitry Andric : Offset(offset), Addend(SectionAOffset - SectionBOffset + addend), 183*0fca6ea1SDimitry Andric SectionID(id), RelType(type), Size(Size), IsPCRel(IsPCRel), 184*0fca6ea1SDimitry Andric IsTargetThumbFunc(IsTargetThumbFunc) { 1850b57cec5SDimitry Andric Sections.SectionA = SectionA; 1860b57cec5SDimitry Andric Sections.SectionB = SectionB; 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric }; 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric class RelocationValueRef { 1910b57cec5SDimitry Andric public: 1925ffd83dbSDimitry Andric unsigned SectionID = 0; 1935ffd83dbSDimitry Andric uint64_t Offset = 0; 1945ffd83dbSDimitry Andric int64_t Addend = 0; 1955ffd83dbSDimitry Andric const char *SymbolName = nullptr; 1960b57cec5SDimitry Andric bool IsStubThumb = false; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric inline bool operator==(const RelocationValueRef &Other) const { 1990b57cec5SDimitry Andric return SectionID == Other.SectionID && Offset == Other.Offset && 2000b57cec5SDimitry Andric Addend == Other.Addend && SymbolName == Other.SymbolName && 2010b57cec5SDimitry Andric IsStubThumb == Other.IsStubThumb; 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric inline bool operator<(const RelocationValueRef &Other) const { 2040b57cec5SDimitry Andric if (SectionID != Other.SectionID) 2050b57cec5SDimitry Andric return SectionID < Other.SectionID; 2060b57cec5SDimitry Andric if (Offset != Other.Offset) 2070b57cec5SDimitry Andric return Offset < Other.Offset; 2080b57cec5SDimitry Andric if (Addend != Other.Addend) 2090b57cec5SDimitry Andric return Addend < Other.Addend; 2100b57cec5SDimitry Andric if (IsStubThumb != Other.IsStubThumb) 2110b57cec5SDimitry Andric return IsStubThumb < Other.IsStubThumb; 2120b57cec5SDimitry Andric return SymbolName < Other.SymbolName; 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric }; 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric /// Symbol info for RuntimeDyld. 2170b57cec5SDimitry Andric class SymbolTableEntry { 2180b57cec5SDimitry Andric public: 2190b57cec5SDimitry Andric SymbolTableEntry() = default; 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric SymbolTableEntry(unsigned SectionID, uint64_t Offset, JITSymbolFlags Flags) 2220b57cec5SDimitry Andric : Offset(Offset), SectionID(SectionID), Flags(Flags) {} 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric unsigned getSectionID() const { return SectionID; } 2250b57cec5SDimitry Andric uint64_t getOffset() const { return Offset; } 2260b57cec5SDimitry Andric void setOffset(uint64_t NewOffset) { Offset = NewOffset; } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric JITSymbolFlags getFlags() const { return Flags; } 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric private: 2310b57cec5SDimitry Andric uint64_t Offset = 0; 2320b57cec5SDimitry Andric unsigned SectionID = 0; 2330b57cec5SDimitry Andric JITSymbolFlags Flags = JITSymbolFlags::None; 2340b57cec5SDimitry Andric }; 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric typedef StringMap<SymbolTableEntry> RTDyldSymbolTable; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric class RuntimeDyldImpl { 2390b57cec5SDimitry Andric friend class RuntimeDyld::LoadedObjectInfo; 2400b57cec5SDimitry Andric protected: 2410b57cec5SDimitry Andric static const unsigned AbsoluteSymbolSection = ~0U; 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric // The MemoryManager to load objects into. 2440b57cec5SDimitry Andric RuntimeDyld::MemoryManager &MemMgr; 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric // The symbol resolver to use for external symbols. 2470b57cec5SDimitry Andric JITSymbolResolver &Resolver; 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric // A list of all sections emitted by the dynamic linker. These sections are 2500b57cec5SDimitry Andric // referenced in the code by means of their index in this list - SectionID. 2515ffd83dbSDimitry Andric // Because references may be kept while the list grows, use a container that 2525ffd83dbSDimitry Andric // guarantees reference stability. 2535ffd83dbSDimitry Andric typedef std::deque<SectionEntry> SectionList; 2540b57cec5SDimitry Andric SectionList Sections; 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric typedef unsigned SID; // Type for SectionIDs 2570b57cec5SDimitry Andric #define RTDYLD_INVALID_SECTION_ID ((RuntimeDyldImpl::SID)(-1)) 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric // Keep a map of sections from object file to the SectionID which 2600b57cec5SDimitry Andric // references it. 2610b57cec5SDimitry Andric typedef std::map<SectionRef, unsigned> ObjSectionToIDMap; 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric // A global symbol table for symbols from all loaded modules. 2640b57cec5SDimitry Andric RTDyldSymbolTable GlobalSymbolTable; 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric // Keep a map of common symbols to their info pairs 2670b57cec5SDimitry Andric typedef std::vector<SymbolRef> CommonSymbolList; 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric // For each symbol, keep a list of relocations based on it. Anytime 2700b57cec5SDimitry Andric // its address is reassigned (the JIT re-compiled the function, e.g.), 2710b57cec5SDimitry Andric // the relocations get re-resolved. 2720b57cec5SDimitry Andric // The symbol (or section) the relocation is sourced from is the Key 2730b57cec5SDimitry Andric // in the relocation list where it's stored. 2740b57cec5SDimitry Andric typedef SmallVector<RelocationEntry, 64> RelocationList; 2750b57cec5SDimitry Andric // Relocations to sections already loaded. Indexed by SectionID which is the 2760b57cec5SDimitry Andric // source of the address. The target where the address will be written is 2770b57cec5SDimitry Andric // SectionID/Offset in the relocation itself. 2780b57cec5SDimitry Andric std::unordered_map<unsigned, RelocationList> Relocations; 2790b57cec5SDimitry Andric 2800b57cec5SDimitry Andric // Relocations to external symbols that are not yet resolved. Symbols are 2810b57cec5SDimitry Andric // external when they aren't found in the global symbol table of all loaded 2820b57cec5SDimitry Andric // modules. This map is indexed by symbol name. 2830b57cec5SDimitry Andric StringMap<RelocationList> ExternalSymbolRelocations; 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric typedef std::map<RelocationValueRef, uintptr_t> StubMap; 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric Triple::ArchType Arch; 2890b57cec5SDimitry Andric bool IsTargetLittleEndian; 2900b57cec5SDimitry Andric bool IsMipsO32ABI; 2910b57cec5SDimitry Andric bool IsMipsN32ABI; 2920b57cec5SDimitry Andric bool IsMipsN64ABI; 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric // True if all sections should be passed to the memory manager, false if only 2950b57cec5SDimitry Andric // sections containing relocations should be. Defaults to 'false'. 2960b57cec5SDimitry Andric bool ProcessAllSections; 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric // This mutex prevents simultaneously loading objects from two different 2990b57cec5SDimitry Andric // threads. This keeps us from having to protect individual data structures 3000b57cec5SDimitry Andric // and guarantees that section allocation requests to the memory manager 3010b57cec5SDimitry Andric // won't be interleaved between modules. It is also used in mapSectionAddress 3020b57cec5SDimitry Andric // and resolveRelocations to protect write access to internal data structures. 3030b57cec5SDimitry Andric // 3045f757f3fSDimitry Andric // loadObject may be called on the same thread during the handling of 3050b57cec5SDimitry Andric // processRelocations, and that's OK. The handling of the relocation lists 3060b57cec5SDimitry Andric // is written in such a way as to work correctly if new elements are added to 3070b57cec5SDimitry Andric // the end of the list while the list is being processed. 3080b57cec5SDimitry Andric sys::Mutex lock; 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric using NotifyStubEmittedFunction = 3110b57cec5SDimitry Andric RuntimeDyld::NotifyStubEmittedFunction; 3120b57cec5SDimitry Andric NotifyStubEmittedFunction NotifyStubEmitted; 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric virtual unsigned getMaxStubSize() const = 0; 315bdd1243dSDimitry Andric virtual Align getStubAlignment() = 0; 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric bool HasError; 3180b57cec5SDimitry Andric std::string ErrorStr; 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric void writeInt16BE(uint8_t *Addr, uint16_t Value) { 3215f757f3fSDimitry Andric llvm::support::endian::write<uint16_t>(Addr, Value, 3225f757f3fSDimitry Andric IsTargetLittleEndian 3235f757f3fSDimitry Andric ? llvm::endianness::little 3245f757f3fSDimitry Andric : llvm::endianness::big); 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric void writeInt32BE(uint8_t *Addr, uint32_t Value) { 3285f757f3fSDimitry Andric llvm::support::endian::write<uint32_t>(Addr, Value, 3295f757f3fSDimitry Andric IsTargetLittleEndian 3305f757f3fSDimitry Andric ? llvm::endianness::little 3315f757f3fSDimitry Andric : llvm::endianness::big); 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric void writeInt64BE(uint8_t *Addr, uint64_t Value) { 3355f757f3fSDimitry Andric llvm::support::endian::write<uint64_t>(Addr, Value, 3365f757f3fSDimitry Andric IsTargetLittleEndian 3375f757f3fSDimitry Andric ? llvm::endianness::little 3385f757f3fSDimitry Andric : llvm::endianness::big); 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric virtual void setMipsABI(const ObjectFile &Obj) { 3420b57cec5SDimitry Andric IsMipsO32ABI = false; 3430b57cec5SDimitry Andric IsMipsN32ABI = false; 3440b57cec5SDimitry Andric IsMipsN64ABI = false; 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric /// Endian-aware read Read the least significant Size bytes from Src. 3480b57cec5SDimitry Andric uint64_t readBytesUnaligned(uint8_t *Src, unsigned Size) const; 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric /// Endian-aware write. Write the least significant Size bytes from Value to 3510b57cec5SDimitry Andric /// Dst. 3520b57cec5SDimitry Andric void writeBytesUnaligned(uint64_t Value, uint8_t *Dst, unsigned Size) const; 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric /// Generate JITSymbolFlags from a libObject symbol. 3550b57cec5SDimitry Andric virtual Expected<JITSymbolFlags> getJITSymbolFlags(const SymbolRef &Sym); 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric /// Modify the given target address based on the given symbol flags. 3580b57cec5SDimitry Andric /// This can be used by subclasses to tweak addresses based on symbol flags, 3590b57cec5SDimitry Andric /// For example: the MachO/ARM target uses it to set the low bit if the target 3600b57cec5SDimitry Andric /// is a thumb symbol. 3610b57cec5SDimitry Andric virtual uint64_t modifyAddressBasedOnFlags(uint64_t Addr, 3620b57cec5SDimitry Andric JITSymbolFlags Flags) const { 3630b57cec5SDimitry Andric return Addr; 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric /// Given the common symbols discovered in the object file, emit a 3670b57cec5SDimitry Andric /// new section for them and update the symbol mappings in the object and 3680b57cec5SDimitry Andric /// symbol table. 3690b57cec5SDimitry Andric Error emitCommonSymbols(const ObjectFile &Obj, 3700b57cec5SDimitry Andric CommonSymbolList &CommonSymbols, uint64_t CommonSize, 3710b57cec5SDimitry Andric uint32_t CommonAlign); 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric /// Emits section data from the object file to the MemoryManager. 3740b57cec5SDimitry Andric /// \param IsCode if it's true then allocateCodeSection() will be 3750b57cec5SDimitry Andric /// used for emits, else allocateDataSection() will be used. 3760b57cec5SDimitry Andric /// \return SectionID. 3770b57cec5SDimitry Andric Expected<unsigned> emitSection(const ObjectFile &Obj, 3780b57cec5SDimitry Andric const SectionRef &Section, 3790b57cec5SDimitry Andric bool IsCode); 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric /// Find Section in LocalSections. If the secton is not found - emit 3820b57cec5SDimitry Andric /// it and store in LocalSections. 3830b57cec5SDimitry Andric /// \param IsCode if it's true then allocateCodeSection() will be 3840b57cec5SDimitry Andric /// used for emmits, else allocateDataSection() will be used. 3850b57cec5SDimitry Andric /// \return SectionID. 3860b57cec5SDimitry Andric Expected<unsigned> findOrEmitSection(const ObjectFile &Obj, 3870b57cec5SDimitry Andric const SectionRef &Section, bool IsCode, 3880b57cec5SDimitry Andric ObjSectionToIDMap &LocalSections); 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric // Add a relocation entry that uses the given section. 3910b57cec5SDimitry Andric void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID); 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric // Add a relocation entry that uses the given symbol. This symbol may 3940b57cec5SDimitry Andric // be found in the global symbol table, or it may be external. 3950b57cec5SDimitry Andric void addRelocationForSymbol(const RelocationEntry &RE, StringRef SymbolName); 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric /// Emits long jump instruction to Addr. 3980b57cec5SDimitry Andric /// \return Pointer to the memory area for emitting target address. 3990b57cec5SDimitry Andric uint8_t *createStubFunction(uint8_t *Addr, unsigned AbiVariant = 0); 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric /// Resolves relocations from Relocs list with address from Value. 4020b57cec5SDimitry Andric void resolveRelocationList(const RelocationList &Relocs, uint64_t Value); 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric /// A object file specific relocation resolver 4050b57cec5SDimitry Andric /// \param RE The relocation to be resolved 4060b57cec5SDimitry Andric /// \param Value Target symbol address to apply the relocation action 4070b57cec5SDimitry Andric virtual void resolveRelocation(const RelocationEntry &RE, uint64_t Value) = 0; 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric /// Parses one or more object file relocations (some object files use 4100b57cec5SDimitry Andric /// relocation pairs) and stores it to Relocations or SymbolRelocations 4110b57cec5SDimitry Andric /// (this depends on the object file type). 4120b57cec5SDimitry Andric /// \return Iterator to the next relocation that needs to be parsed. 4130b57cec5SDimitry Andric virtual Expected<relocation_iterator> 4140b57cec5SDimitry Andric processRelocationRef(unsigned SectionID, relocation_iterator RelI, 4150b57cec5SDimitry Andric const ObjectFile &Obj, ObjSectionToIDMap &ObjSectionToID, 4160b57cec5SDimitry Andric StubMap &Stubs) = 0; 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric void applyExternalSymbolRelocations( 4190b57cec5SDimitry Andric const StringMap<JITEvaluatedSymbol> ExternalSymbolMap); 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric /// Resolve relocations to external symbols. 4220b57cec5SDimitry Andric Error resolveExternalSymbols(); 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric // Compute an upper bound of the memory that is required to load all 4250b57cec5SDimitry Andric // sections 426bdd1243dSDimitry Andric Error computeTotalAllocSize(const ObjectFile &Obj, uint64_t &CodeSize, 427bdd1243dSDimitry Andric Align &CodeAlign, uint64_t &RODataSize, 428bdd1243dSDimitry Andric Align &RODataAlign, uint64_t &RWDataSize, 429bdd1243dSDimitry Andric Align &RWDataAlign); 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric // Compute GOT size 4320b57cec5SDimitry Andric unsigned computeGOTSize(const ObjectFile &Obj); 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric // Compute the stub buffer size required for a section 4350b57cec5SDimitry Andric unsigned computeSectionStubBufSize(const ObjectFile &Obj, 4360b57cec5SDimitry Andric const SectionRef &Section); 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric // Implementation of the generic part of the loadObject algorithm. 4390b57cec5SDimitry Andric Expected<ObjSectionToIDMap> loadObjectImpl(const object::ObjectFile &Obj); 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric // Return size of Global Offset Table (GOT) entry 4420b57cec5SDimitry Andric virtual size_t getGOTEntrySize() { return 0; } 4430b57cec5SDimitry Andric 444bdd1243dSDimitry Andric // Hook for the subclasses to do further processing when a symbol is added to 445bdd1243dSDimitry Andric // the global symbol table. This function may modify the symbol table entry. 446bdd1243dSDimitry Andric virtual void processNewSymbol(const SymbolRef &ObjSymbol, SymbolTableEntry& Entry) {} 447bdd1243dSDimitry Andric 4480b57cec5SDimitry Andric // Return true if the relocation R may require allocating a GOT entry. 4490b57cec5SDimitry Andric virtual bool relocationNeedsGot(const RelocationRef &R) const { 4500b57cec5SDimitry Andric return false; 4510b57cec5SDimitry Andric } 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric // Return true if the relocation R may require allocating a stub. 4540b57cec5SDimitry Andric virtual bool relocationNeedsStub(const RelocationRef &R) const { 4550b57cec5SDimitry Andric return true; // Conservative answer 4560b57cec5SDimitry Andric } 4570b57cec5SDimitry Andric 4580b57cec5SDimitry Andric public: 4590b57cec5SDimitry Andric RuntimeDyldImpl(RuntimeDyld::MemoryManager &MemMgr, 4600b57cec5SDimitry Andric JITSymbolResolver &Resolver) 4610b57cec5SDimitry Andric : MemMgr(MemMgr), Resolver(Resolver), 4620b57cec5SDimitry Andric ProcessAllSections(false), HasError(false) { 4630b57cec5SDimitry Andric } 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric virtual ~RuntimeDyldImpl(); 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric void setProcessAllSections(bool ProcessAllSections) { 4680b57cec5SDimitry Andric this->ProcessAllSections = ProcessAllSections; 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric virtual std::unique_ptr<RuntimeDyld::LoadedObjectInfo> 4720b57cec5SDimitry Andric loadObject(const object::ObjectFile &Obj) = 0; 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric uint64_t getSectionLoadAddress(unsigned SectionID) const { 475fe6060f1SDimitry Andric if (SectionID == AbsoluteSymbolSection) 476fe6060f1SDimitry Andric return 0; 477fe6060f1SDimitry Andric else 4780b57cec5SDimitry Andric return Sections[SectionID].getLoadAddress(); 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric uint8_t *getSectionAddress(unsigned SectionID) const { 482fe6060f1SDimitry Andric if (SectionID == AbsoluteSymbolSection) 483fe6060f1SDimitry Andric return nullptr; 484fe6060f1SDimitry Andric else 4850b57cec5SDimitry Andric return Sections[SectionID].getAddress(); 4860b57cec5SDimitry Andric } 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric StringRef getSectionContent(unsigned SectionID) const { 489fe6060f1SDimitry Andric if (SectionID == AbsoluteSymbolSection) 490fe6060f1SDimitry Andric return {}; 491fe6060f1SDimitry Andric else 492fe6060f1SDimitry Andric return StringRef( 493fe6060f1SDimitry Andric reinterpret_cast<char *>(Sections[SectionID].getAddress()), 4940b57cec5SDimitry Andric Sections[SectionID].getStubOffset() + getMaxStubSize()); 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric uint8_t* getSymbolLocalAddress(StringRef Name) const { 4980b57cec5SDimitry Andric // FIXME: Just look up as a function for now. Overly simple of course. 4990b57cec5SDimitry Andric // Work in progress. 5000b57cec5SDimitry Andric RTDyldSymbolTable::const_iterator pos = GlobalSymbolTable.find(Name); 5010b57cec5SDimitry Andric if (pos == GlobalSymbolTable.end()) 5020b57cec5SDimitry Andric return nullptr; 5030b57cec5SDimitry Andric const auto &SymInfo = pos->second; 5040b57cec5SDimitry Andric // Absolute symbols do not have a local address. 5050b57cec5SDimitry Andric if (SymInfo.getSectionID() == AbsoluteSymbolSection) 5060b57cec5SDimitry Andric return nullptr; 5070b57cec5SDimitry Andric return getSectionAddress(SymInfo.getSectionID()) + SymInfo.getOffset(); 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric unsigned getSymbolSectionID(StringRef Name) const { 5110b57cec5SDimitry Andric auto GSTItr = GlobalSymbolTable.find(Name); 5120b57cec5SDimitry Andric if (GSTItr == GlobalSymbolTable.end()) 5130b57cec5SDimitry Andric return ~0U; 5140b57cec5SDimitry Andric return GSTItr->second.getSectionID(); 5150b57cec5SDimitry Andric } 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric JITEvaluatedSymbol getSymbol(StringRef Name) const { 5180b57cec5SDimitry Andric // FIXME: Just look up as a function for now. Overly simple of course. 5190b57cec5SDimitry Andric // Work in progress. 5200b57cec5SDimitry Andric RTDyldSymbolTable::const_iterator pos = GlobalSymbolTable.find(Name); 5210b57cec5SDimitry Andric if (pos == GlobalSymbolTable.end()) 5220b57cec5SDimitry Andric return nullptr; 5230b57cec5SDimitry Andric const auto &SymEntry = pos->second; 5240b57cec5SDimitry Andric uint64_t SectionAddr = 0; 5250b57cec5SDimitry Andric if (SymEntry.getSectionID() != AbsoluteSymbolSection) 5260b57cec5SDimitry Andric SectionAddr = getSectionLoadAddress(SymEntry.getSectionID()); 5270b57cec5SDimitry Andric uint64_t TargetAddr = SectionAddr + SymEntry.getOffset(); 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric // FIXME: Have getSymbol should return the actual address and the client 5300b57cec5SDimitry Andric // modify it based on the flags. This will require clients to be 5310b57cec5SDimitry Andric // aware of the target architecture, which we should build 5320b57cec5SDimitry Andric // infrastructure for. 5330b57cec5SDimitry Andric TargetAddr = modifyAddressBasedOnFlags(TargetAddr, SymEntry.getFlags()); 5340b57cec5SDimitry Andric return JITEvaluatedSymbol(TargetAddr, SymEntry.getFlags()); 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric 5370b57cec5SDimitry Andric std::map<StringRef, JITEvaluatedSymbol> getSymbolTable() const { 5380b57cec5SDimitry Andric std::map<StringRef, JITEvaluatedSymbol> Result; 5390b57cec5SDimitry Andric 540bdd1243dSDimitry Andric for (const auto &KV : GlobalSymbolTable) { 5410b57cec5SDimitry Andric auto SectionID = KV.second.getSectionID(); 542fe6060f1SDimitry Andric uint64_t SectionAddr = getSectionLoadAddress(SectionID); 5430b57cec5SDimitry Andric Result[KV.first()] = 5440b57cec5SDimitry Andric JITEvaluatedSymbol(SectionAddr + KV.second.getOffset(), KV.second.getFlags()); 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric return Result; 5480b57cec5SDimitry Andric } 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric void resolveRelocations(); 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric void resolveLocalRelocations(); 5530b57cec5SDimitry Andric 5545ffd83dbSDimitry Andric static void finalizeAsync( 5555ffd83dbSDimitry Andric std::unique_ptr<RuntimeDyldImpl> This, 556e8d8bef9SDimitry Andric unique_function<void(object::OwningBinary<object::ObjectFile>, 557e8d8bef9SDimitry Andric std::unique_ptr<RuntimeDyld::LoadedObjectInfo>, 558e8d8bef9SDimitry Andric Error)> 5595ffd83dbSDimitry Andric OnEmitted, 560e8d8bef9SDimitry Andric object::OwningBinary<object::ObjectFile> O, 561e8d8bef9SDimitry Andric std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info); 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric void reassignSectionAddress(unsigned SectionID, uint64_t Addr); 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress); 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric // Is the linker in an error state? 5680b57cec5SDimitry Andric bool hasError() { return HasError; } 5690b57cec5SDimitry Andric 5700b57cec5SDimitry Andric // Mark the error condition as handled and continue. 5710b57cec5SDimitry Andric void clearError() { HasError = false; } 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andric // Get the error message. 5740b57cec5SDimitry Andric StringRef getErrorString() { return ErrorStr; } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric virtual bool isCompatibleFile(const ObjectFile &Obj) const = 0; 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric void setNotifyStubEmitted(NotifyStubEmittedFunction NotifyStubEmitted) { 5790b57cec5SDimitry Andric this->NotifyStubEmitted = std::move(NotifyStubEmitted); 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric virtual void registerEHFrames(); 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric void deregisterEHFrames(); 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric virtual Error finalizeLoad(const ObjectFile &ObjImg, 5870b57cec5SDimitry Andric ObjSectionToIDMap &SectionMap) { 5880b57cec5SDimitry Andric return Error::success(); 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric }; 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric } // end namespace llvm 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric #endif 595