diff options
Diffstat (limited to 'contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h')
-rw-r--r-- | contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h | 236 |
1 files changed, 165 insertions, 71 deletions
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 7190a3c..bf678af 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -1,4 +1,4 @@ -//===-- RuntimeDyldImpl.h - Run-time dynamic linker for MC-JIT ------*- C++ -*-===// +//===-- RuntimeDyldImpl.h - Run-time dynamic linker for MC-JIT --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,42 +15,128 @@ #define LLVM_RUNTIME_DYLD_IMPL_H #include "llvm/ExecutionEngine/RuntimeDyld.h" -#include "llvm/Object/MachOObject.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/ADT/DenseMap.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" +#include "llvm/ADT/Triple.h" +#include <map> +#include "llvm/Support/Format.h" using namespace llvm; using namespace llvm::object; namespace llvm { + +class SectionEntry { +public: + uint8_t* Address; + size_t Size; + uint64_t LoadAddress; // For each section, the address it will be + // considered to live at for relocations. The same + // as the pointer to the above memory block for + // hosted JITs. + uintptr_t StubOffset; // It's used for architecturies with stub + // functions for far relocations like ARM. + uintptr_t ObjAddress; // Section address in object file. It's use for + // calculate MachO relocation addend + SectionEntry(uint8_t* address, size_t size, uintptr_t stubOffset, + uintptr_t objAddress) + : Address(address), Size(size), LoadAddress((uintptr_t)address), + StubOffset(stubOffset), ObjAddress(objAddress) {} +}; + +class RelocationEntry { +public: + unsigned SectionID; // Section the relocation is contained in. + uintptr_t Offset; // Offset into the section for the relocation. + uint32_t Data; // Relocatino data. Including type of relocation + // and another flags and parameners from + intptr_t Addend; // Addend encoded in the instruction itself, if any, + // plus the offset into the source section for + // the symbol once the relocation is resolvable. + RelocationEntry(unsigned id, uint64_t offset, uint32_t data, int64_t addend) + : SectionID(id), Offset(offset), Data(data), Addend(addend) {} +}; + +// Raw relocation data from object file +class ObjRelocationInfo { +public: + unsigned SectionID; + uint64_t Offset; + SymbolRef Symbol; + uint64_t Type; + int64_t AdditionalInfo; +}; + +class RelocationValueRef { +public: + unsigned SectionID; + intptr_t Addend; + const char *SymbolName; + RelocationValueRef(): SectionID(0), Addend(0), SymbolName(0) {} + + inline bool operator==(const RelocationValueRef &Other) const { + return std::memcmp(this, &Other, sizeof(RelocationValueRef)) == 0; + } + inline bool operator <(const RelocationValueRef &Other) const { + return std::memcmp(this, &Other, sizeof(RelocationValueRef)) < 0; + } +}; + 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. + // A list of emmitted sections. + typedef SmallVector<SectionEntry, 64> SectionList; + SectionList Sections; - // For each function, we have a MemoryBlock of it's instruction data. - StringMap<sys::MemoryBlock> Functions; + // Keep a map of sections from object file to the SectionID which + // references it. + typedef std::map<SectionRef, unsigned> ObjSectionToIDMap; // Master symbol table. As modules are loaded and external symbols are - // resolved, their addresses are stored here. - StringMap<uint8_t*> SymbolTable; + // resolved, their addresses are stored here as a SectionID/Offset pair. + typedef std::pair<unsigned, uintptr_t> SymbolLoc; + StringMap<SymbolLoc> SymbolTable; + typedef DenseMap<const char*, SymbolLoc> LocalSymbolMap; + + // Keep a map of common symbols to their sizes + typedef std::map<SymbolRef, unsigned> CommonSymbolMap; + + // 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. + // The symbol (or section) the relocation is sourced from is the Key + // in the relocation list where it's stored. + typedef SmallVector<RelocationEntry, 64> RelocationList; + // Relocations to sections already loaded. Indexed by SectionID which is the + // source of the address. The target where the address will be writen is + // SectionID/Offset in the relocation itself. + DenseMap<unsigned, RelocationList> Relocations; + // Relocations to external symbols that are not yet resolved. + // Indexed by symbol name. + StringMap<RelocationList> SymbolRelocations; + + typedef std::map<RelocationValueRef, uintptr_t> StubMap; + + Triple::ArchType Arch; + + inline unsigned getMaxStubSize() { + if (Arch == Triple::arm || Arch == Triple::thumb) + return 8; // 32-bit instruction and 32-bit address + else + return 0; + } bool HasError; std::string ErrorStr; @@ -62,25 +148,84 @@ protected: return true; } - void extractFunction(StringRef Name, uint8_t *StartAddress, - uint8_t *EndAddress); + uint8_t *getSectionAddress(unsigned SectionID) { + return (uint8_t*)Sections[SectionID].Address; + } + /// \brief Emits a section containing common symbols. + /// \return SectionID. + unsigned emitCommonSymbols(const CommonSymbolMap &Map, + uint64_t TotalSize, + LocalSymbolMap &Symbols); + + /// \brief Emits section data from the object file to the MemoryManager. + /// \param IsCode if it's true then allocateCodeSection() will be + /// used for emmits, else allocateDataSection() will be used. + /// \return SectionID. + unsigned emitSection(const SectionRef &Section, bool IsCode); + + /// \brief Find Section in LocalSections. If the secton is not found - emit + /// it and store in LocalSections. + /// \param IsCode if it's true then allocateCodeSection() will be + /// used for emmits, else allocateDataSection() will be used. + /// \return SectionID. + unsigned findOrEmitSection(const SectionRef &Section, bool IsCode, + ObjSectionToIDMap &LocalSections); + + /// \brief If Value.SymbolName is NULL then store relocation to the + /// Relocations, else store it in the SymbolRelocations. + void AddRelocation(const RelocationValueRef &Value, unsigned SectionID, + uintptr_t Offset, uint32_t RelType); + + /// \brief Emits long jump instruction to Addr. + /// \return Pointer to the memory area for emitting target address. + uint8_t* createStubFunction(uint8_t *Addr); + + /// \brief Resolves relocations from Relocs list with address from Value. + void resolveRelocationList(const RelocationList &Relocs, uint64_t Value); + void resolveRelocationEntry(const RelocationEntry &RE, uint64_t Value); + + /// \brief A object file specific relocation resolver + /// \param Address Address to apply the relocation action + /// \param Value Target symbol address to apply the relocation action + /// \param Type object file specific relocation type + /// \param Addend A constant addend used to compute the value to be stored + /// into the relocatable field + virtual void resolveRelocation(uint8_t *LocalAddress, + uint64_t FinalAddress, + uint64_t Value, + uint32_t Type, + int64_t Addend) = 0; + + /// \brief Parses the object file relocation and store it to Relocations + /// or SymbolRelocations. Its depend from object file type. + virtual void processRelocationRef(const ObjRelocationInfo &Rel, + const ObjectFile &Obj, + ObjSectionToIDMap &ObjSectionToID, + LocalSymbolMap &Symbols, StubMap &Stubs) = 0; + + void resolveSymbols(); public: RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {} virtual ~RuntimeDyldImpl(); - virtual bool loadObject(MemoryBuffer *InputBuffer) = 0; + bool loadObject(const MemoryBuffer *InputBuffer); void *getSymbolAddress(StringRef Name) { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. - return SymbolTable.lookup(Name); + if (SymbolTable.find(Name) == SymbolTable.end()) + return 0; + SymbolLoc Loc = SymbolTable.lookup(Name); + return getSectionAddress(Loc.first) + Loc.second; } void resolveRelocations(); - virtual void reassignSymbolAddress(StringRef Name, uint8_t *Addr) = 0; + void reassignSectionAddress(unsigned SectionID, uint64_t Addr); + + void mapSectionAddress(void *LocalAddress, uint64_t TargetAddress); // Is the linker in an error state? bool hasError() { return HasError; } @@ -92,58 +237,7 @@ public: 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 |