1 //===-- RuntimeDyldImpl.h - Run-time dynamic linker for MC-JIT ------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Interface for the implementations of runtime dynamic linker facilities. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_RUNTIME_DYLD_IMPL_H 15 #define LLVM_RUNTIME_DYLD_IMPL_H 16 17 #include "llvm/ExecutionEngine/RuntimeDyld.h" 18 #include "llvm/Object/MachOObject.h" 19 #include "llvm/ADT/StringMap.h" 20 #include "llvm/ADT/Twine.h" 21 #include "llvm/ADT/SmallVector.h" 22 #include "llvm/ExecutionEngine/ExecutionEngine.h" 23 #include "llvm/Support/Format.h" 24 #include "llvm/Support/Memory.h" 25 #include "llvm/Support/MemoryBuffer.h" 26 #include "llvm/Support/system_error.h" 27 #include "llvm/Support/raw_ostream.h" 28 #include "llvm/Support/Debug.h" 29 #include "llvm/Support/ErrorHandling.h" 30 31 using namespace llvm; 32 using namespace llvm::object; 33 34 namespace llvm { 35 class RuntimeDyldImpl { 36 protected: 37 unsigned CPUType; 38 unsigned CPUSubtype; 39 40 // The MemoryManager to load objects into. 41 RTDyldMemoryManager *MemMgr; 42 43 // FIXME: This all assumes we're dealing with external symbols for anything 44 // explicitly referenced. I.e., we can index by name and things 45 // will work out. In practice, this may not be the case, so we 46 // should find a way to effectively generalize. 47 48 // For each function, we have a MemoryBlock of it's instruction data. 49 StringMap<sys::MemoryBlock> Functions; 50 51 // Master symbol table. As modules are loaded and external symbols are 52 // resolved, their addresses are stored here. 53 StringMap<uint8_t*> SymbolTable; 54 55 bool HasError; 56 std::string ErrorStr; 57 58 // Set the error state and record an error string. Error(const Twine & Msg)59 bool Error(const Twine &Msg) { 60 ErrorStr = Msg.str(); 61 HasError = true; 62 return true; 63 } 64 65 void extractFunction(StringRef Name, uint8_t *StartAddress, 66 uint8_t *EndAddress); 67 68 public: RuntimeDyldImpl(RTDyldMemoryManager * mm)69 RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {} 70 71 virtual ~RuntimeDyldImpl(); 72 73 virtual bool loadObject(MemoryBuffer *InputBuffer) = 0; 74 getSymbolAddress(StringRef Name)75 void *getSymbolAddress(StringRef Name) { 76 // FIXME: Just look up as a function for now. Overly simple of course. 77 // Work in progress. 78 return SymbolTable.lookup(Name); 79 } 80 81 void resolveRelocations(); 82 83 virtual void reassignSymbolAddress(StringRef Name, uint8_t *Addr) = 0; 84 85 // Is the linker in an error state? hasError()86 bool hasError() { return HasError; } 87 88 // Mark the error condition as handled and continue. clearError()89 void clearError() { HasError = false; } 90 91 // Get the error message. getErrorString()92 StringRef getErrorString() { return ErrorStr; } 93 94 virtual bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const = 0; 95 }; 96 97 98 class RuntimeDyldMachO : public RuntimeDyldImpl { 99 100 // For each symbol, keep a list of relocations based on it. Anytime 101 // its address is reassigned (the JIT re-compiled the function, e.g.), 102 // the relocations get re-resolved. 103 struct RelocationEntry { 104 std::string Target; // Object this relocation is contained in. 105 uint64_t Offset; // Offset into the object for the relocation. 106 uint32_t Data; // Second word of the raw macho relocation entry. 107 int64_t Addend; // Addend encoded in the instruction itself, if any. 108 bool isResolved; // Has this relocation been resolved previously? 109 RelocationEntryRelocationEntry110 RelocationEntry(StringRef t, uint64_t offset, uint32_t data, int64_t addend) 111 : Target(t), Offset(offset), Data(data), Addend(addend), 112 isResolved(false) {} 113 }; 114 typedef SmallVector<RelocationEntry, 4> RelocationList; 115 StringMap<RelocationList> Relocations; 116 117 // FIXME: Also keep a map of all the relocations contained in an object. Use 118 // this to dynamically answer whether all of the relocations in it have 119 // been resolved or not. 120 121 bool resolveRelocation(uint8_t *Address, uint8_t *Value, bool isPCRel, 122 unsigned Type, unsigned Size); 123 bool resolveX86_64Relocation(uintptr_t Address, uintptr_t Value, bool isPCRel, 124 unsigned Type, unsigned Size); 125 bool resolveARMRelocation(uintptr_t Address, uintptr_t Value, bool isPCRel, 126 unsigned Type, unsigned Size); 127 128 bool loadSegment32(const MachOObject *Obj, 129 const MachOObject::LoadCommandInfo *SegmentLCI, 130 const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC); 131 bool loadSegment64(const MachOObject *Obj, 132 const MachOObject::LoadCommandInfo *SegmentLCI, 133 const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC); 134 135 public: RuntimeDyldMachO(RTDyldMemoryManager * mm)136 RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} 137 138 bool loadObject(MemoryBuffer *InputBuffer); 139 140 void reassignSymbolAddress(StringRef Name, uint8_t *Addr); 141 142 static bool isKnownFormat(const MemoryBuffer *InputBuffer); 143 isCompatibleFormat(const MemoryBuffer * InputBuffer)144 bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const { 145 return isKnownFormat(InputBuffer); 146 } 147 }; 148 149 } // end namespace llvm 150 151 152 #endif 153