| //===-- RuntimeDyldImpl.h - Run-time dynamic linker for MC-JIT ------*- C++ -*-===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // Interface for the implementations of runtime dynamic linker facilities. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef LLVM_RUNTIME_DYLD_IMPL_H | |
| #define LLVM_RUNTIME_DYLD_IMPL_H | |
| #include "llvm/ExecutionEngine/RuntimeDyld.h" | |
| #include "llvm/Object/MachOObject.h" | |
| #include "llvm/ADT/StringMap.h" | |
| #include "llvm/ADT/Twine.h" | |
| #include "llvm/ADT/SmallVector.h" | |
| #include "llvm/ExecutionEngine/ExecutionEngine.h" | |
| #include "llvm/Support/Format.h" | |
| #include "llvm/Support/Memory.h" | |
| #include "llvm/Support/MemoryBuffer.h" | |
| #include "llvm/Support/system_error.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| #include "llvm/Support/Debug.h" | |
| #include "llvm/Support/ErrorHandling.h" | |
| using namespace llvm; | |
| using namespace llvm::object; | |
| namespace llvm { | |
| class RuntimeDyldImpl { | |
| protected: | |
| unsigned CPUType; | |
| unsigned CPUSubtype; | |
| // The MemoryManager to load objects into. | |
| RTDyldMemoryManager *MemMgr; | |
| // FIXME: This all assumes we're dealing with external symbols for anything | |
| // explicitly referenced. I.e., we can index by name and things | |
| // will work out. In practice, this may not be the case, so we | |
| // should find a way to effectively generalize. | |
| // For each function, we have a MemoryBlock of it's instruction data. | |
| StringMap<sys::MemoryBlock> Functions; | |
| // Master symbol table. As modules are loaded and external symbols are | |
| // resolved, their addresses are stored here. | |
| StringMap<uint8_t*> SymbolTable; | |
| bool HasError; | |
| std::string ErrorStr; | |
| // Set the error state and record an error string. | |
| bool Error(const Twine &Msg) { | |
| ErrorStr = Msg.str(); | |
| HasError = true; | |
| return true; | |
| } | |
| void extractFunction(StringRef Name, uint8_t *StartAddress, | |
| uint8_t *EndAddress); | |
| public: | |
| RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {} | |
| virtual ~RuntimeDyldImpl(); | |
| virtual bool loadObject(MemoryBuffer *InputBuffer) = 0; | |
| void *getSymbolAddress(StringRef Name) { | |
| // FIXME: Just look up as a function for now. Overly simple of course. | |
| // Work in progress. | |
| return SymbolTable.lookup(Name); | |
| } | |
| void resolveRelocations(); | |
| virtual void reassignSymbolAddress(StringRef Name, uint8_t *Addr) = 0; | |
| // Is the linker in an error state? | |
| bool hasError() { return HasError; } | |
| // Mark the error condition as handled and continue. | |
| void clearError() { HasError = false; } | |
| // Get the error message. | |
| StringRef getErrorString() { return ErrorStr; } | |
| virtual bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const = 0; | |
| }; | |
| class RuntimeDyldMachO : public RuntimeDyldImpl { | |
| // For each symbol, keep a list of relocations based on it. Anytime | |
| // its address is reassigned (the JIT re-compiled the function, e.g.), | |
| // the relocations get re-resolved. | |
| struct RelocationEntry { | |
| std::string Target; // Object this relocation is contained in. | |
| uint64_t Offset; // Offset into the object for the relocation. | |
| uint32_t Data; // Second word of the raw macho relocation entry. | |
| int64_t Addend; // Addend encoded in the instruction itself, if any. | |
| bool isResolved; // Has this relocation been resolved previously? | |
| RelocationEntry(StringRef t, uint64_t offset, uint32_t data, int64_t addend) | |
| : Target(t), Offset(offset), Data(data), Addend(addend), | |
| isResolved(false) {} | |
| }; | |
| typedef SmallVector<RelocationEntry, 4> RelocationList; | |
| StringMap<RelocationList> Relocations; | |
| // FIXME: Also keep a map of all the relocations contained in an object. Use | |
| // this to dynamically answer whether all of the relocations in it have | |
| // been resolved or not. | |
| bool resolveRelocation(uint8_t *Address, uint8_t *Value, bool isPCRel, | |
| unsigned Type, unsigned Size); | |
| bool resolveX86_64Relocation(uintptr_t Address, uintptr_t Value, bool isPCRel, | |
| unsigned Type, unsigned Size); | |
| bool resolveARMRelocation(uintptr_t Address, uintptr_t Value, bool isPCRel, | |
| unsigned Type, unsigned Size); | |
| bool loadSegment32(const MachOObject *Obj, | |
| const MachOObject::LoadCommandInfo *SegmentLCI, | |
| const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC); | |
| bool loadSegment64(const MachOObject *Obj, | |
| const MachOObject::LoadCommandInfo *SegmentLCI, | |
| const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC); | |
| public: | |
| RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} | |
| bool loadObject(MemoryBuffer *InputBuffer); | |
| void reassignSymbolAddress(StringRef Name, uint8_t *Addr); | |
| static bool isKnownFormat(const MemoryBuffer *InputBuffer); | |
| bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const { | |
| return isKnownFormat(InputBuffer); | |
| } | |
| }; | |
| } // end namespace llvm | |
| #endif |