X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FExecutionEngine%2FRuntimeDyld%2FRuntimeDyldImpl.h;h=412cf20a5c7be9b0905233f6a999875db0ae60cb;hb=b572bc1ccfc41ae7567423843a5b88f8fba270ac;hp=0628fa71802c55bf0028573b2e02a22c44ee4611;hpb=43507d026bef31100cb0c35614bcf419029a265b;p=oota-llvm.git diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 0628fa71802..412cf20a5c7 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -25,6 +25,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/Host.h" +#include "llvm/Support/Mutex.h" #include "llvm/Support/SwapByteOrder.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" @@ -38,7 +39,6 @@ namespace llvm { class ObjectBuffer; class Twine; - /// SectionEntry - represents a section emitted into memory by the dynamic /// linker. class SectionEntry { @@ -68,8 +68,9 @@ public: SectionEntry(StringRef name, uint8_t *address, size_t size, uintptr_t objAddress) - : Name(name), Address(address), Size(size), LoadAddress((uintptr_t)address), - StubOffset(size), ObjAddress(objAddress) {} + : Name(name), Address(address), Size(size), + LoadAddress((uintptr_t)address), StubOffset(size), + ObjAddress(objAddress) {} }; /// RelocationEntry - used to represent relocations internally in the dynamic @@ -89,9 +90,17 @@ public: /// used to make a relocation section relative instead of symbol relative. int64_t Addend; + struct SectionPair { + uint32_t SectionA; + uint32_t SectionB; + }; + /// SymOffset - Section offset of the relocation entry's symbol (used for GOT /// lookup). - uint64_t SymOffset; + union { + uint64_t SymOffset; + SectionPair Sections; + }; /// True if this is a PCRel relocation (MachO specific). bool IsPCRel; @@ -100,33 +109,44 @@ public: unsigned Size; RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend) - : SectionID(id), Offset(offset), RelType(type), Addend(addend), - SymOffset(0), IsPCRel(false), Size(0) {} + : SectionID(id), Offset(offset), RelType(type), Addend(addend), + SymOffset(0), IsPCRel(false), Size(0) {} RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, uint64_t symoffset) - : SectionID(id), Offset(offset), RelType(type), Addend(addend), - SymOffset(symoffset), IsPCRel(false), Size(0) {} + : SectionID(id), Offset(offset), RelType(type), Addend(addend), + SymOffset(symoffset), IsPCRel(false), Size(0) {} RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, bool IsPCRel, unsigned Size) - : SectionID(id), Offset(offset), RelType(type), Addend(addend), - SymOffset(0), IsPCRel(IsPCRel), Size(Size) {} + : SectionID(id), Offset(offset), RelType(type), Addend(addend), + SymOffset(0), IsPCRel(IsPCRel), Size(Size) {} + + RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, + unsigned SectionA, uint64_t SectionAOffset, unsigned SectionB, + uint64_t SectionBOffset, bool IsPCRel, unsigned Size) + : SectionID(id), Offset(offset), RelType(type), + Addend(SectionAOffset - SectionBOffset + addend), IsPCRel(IsPCRel), + Size(Size) { + Sections.SectionA = SectionA; + Sections.SectionB = SectionB; + } }; class RelocationValueRef { public: - unsigned SectionID; - uint64_t Offset; - int64_t Addend; + unsigned SectionID; + uint64_t Offset; + int64_t Addend; const char *SymbolName; - RelocationValueRef(): SectionID(0), Offset(0), Addend(0), SymbolName(0) {} + RelocationValueRef() : SectionID(0), Offset(0), Addend(0), + SymbolName(nullptr) {} inline bool operator==(const RelocationValueRef &Other) const { return SectionID == Other.SectionID && Offset == Other.Offset && Addend == Other.Addend && SymbolName == Other.SymbolName; } - inline bool operator <(const RelocationValueRef &Other) const { + inline bool operator<(const RelocationValueRef &Other) const { if (SectionID != Other.SectionID) return SectionID < Other.SectionID; if (Offset != Other.Offset) @@ -148,7 +168,7 @@ protected: SectionList Sections; typedef unsigned SID; // Type for SectionIDs - #define RTDYLD_INVALID_SECTION_ID ((SID)(-1)) +#define RTDYLD_INVALID_SECTION_ID ((SID)(-1)) // Keep a map of sections from object file to the SectionID which // references it. @@ -186,6 +206,22 @@ protected: Triple::ArchType Arch; bool IsTargetLittleEndian; + // True if all sections should be passed to the memory manager, false if only + // sections containing relocations should be. Defaults to 'false'. + bool ProcessAllSections; + + // This mutex prevents simultaneously loading objects from two different + // threads. This keeps us from having to protect individual data structures + // and guarantees that section allocation requests to the memory manager + // won't be interleaved between modules. It is also used in mapSectionAddress + // and resolveRelocations to protect write access to internal data structures. + // + // loadObject may be called on the same thread during the handling of of + // processRelocations, and that's OK. The handling of the relocation lists + // is written in such a way as to work correctly if new elements are added to + // the end of the list while the list is being processed. + sys::Mutex lock; + virtual unsigned getMaxStubSize() = 0; virtual unsigned getStubAlignment() = 0; @@ -204,52 +240,49 @@ protected: } uint8_t *getSectionAddress(unsigned SectionID) { - return (uint8_t*)Sections[SectionID].Address; + return (uint8_t *)Sections[SectionID].Address; } void writeInt16BE(uint8_t *Addr, uint16_t Value) { if (IsTargetLittleEndian) Value = sys::SwapByteOrder(Value); - *Addr = (Value >> 8) & 0xFF; - *(Addr+1) = Value & 0xFF; + *Addr = (Value >> 8) & 0xFF; + *(Addr + 1) = Value & 0xFF; } void writeInt32BE(uint8_t *Addr, uint32_t Value) { if (IsTargetLittleEndian) Value = sys::SwapByteOrder(Value); - *Addr = (Value >> 24) & 0xFF; - *(Addr+1) = (Value >> 16) & 0xFF; - *(Addr+2) = (Value >> 8) & 0xFF; - *(Addr+3) = Value & 0xFF; + *Addr = (Value >> 24) & 0xFF; + *(Addr + 1) = (Value >> 16) & 0xFF; + *(Addr + 2) = (Value >> 8) & 0xFF; + *(Addr + 3) = Value & 0xFF; } void writeInt64BE(uint8_t *Addr, uint64_t Value) { if (IsTargetLittleEndian) Value = sys::SwapByteOrder(Value); - *Addr = (Value >> 56) & 0xFF; - *(Addr+1) = (Value >> 48) & 0xFF; - *(Addr+2) = (Value >> 40) & 0xFF; - *(Addr+3) = (Value >> 32) & 0xFF; - *(Addr+4) = (Value >> 24) & 0xFF; - *(Addr+5) = (Value >> 16) & 0xFF; - *(Addr+6) = (Value >> 8) & 0xFF; - *(Addr+7) = Value & 0xFF; + *Addr = (Value >> 56) & 0xFF; + *(Addr + 1) = (Value >> 48) & 0xFF; + *(Addr + 2) = (Value >> 40) & 0xFF; + *(Addr + 3) = (Value >> 32) & 0xFF; + *(Addr + 4) = (Value >> 24) & 0xFF; + *(Addr + 5) = (Value >> 16) & 0xFF; + *(Addr + 6) = (Value >> 8) & 0xFF; + *(Addr + 7) = Value & 0xFF; } /// \brief Given the common symbols discovered in the object file, emit a /// new section for them and update the symbol mappings in the object and /// symbol table. - void emitCommonSymbols(ObjectImage &Obj, - const CommonSymbolMap &CommonSymbols, - uint64_t TotalSize, - SymbolTableMap &SymbolTable); + void emitCommonSymbols(ObjectImage &Obj, const CommonSymbolMap &CommonSymbols, + uint64_t TotalSize, SymbolTableMap &SymbolTable); /// \brief Emits section data from the object file to the MemoryManager. /// \param IsCode if it's true then allocateCodeSection() will be /// used for emits, else allocateDataSection() will be used. /// \return SectionID. - unsigned emitSection(ObjectImage &Obj, - const SectionRef &Section, + unsigned emitSection(ObjectImage &Obj, const SectionRef &Section, bool IsCode); /// \brief Find Section in LocalSections. If the secton is not found - emit @@ -257,10 +290,8 @@ protected: /// \param IsCode if it's true then allocateCodeSection() will be /// used for emmits, else allocateDataSection() will be used. /// \return SectionID. - unsigned findOrEmitSection(ObjectImage &Obj, - const SectionRef &Section, - bool IsCode, - ObjSectionToIDMap &LocalSections); + unsigned findOrEmitSection(ObjectImage &Obj, const SectionRef &Section, + bool IsCode, ObjSectionToIDMap &LocalSections); // \brief Add a relocation entry that uses the given section. void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID); @@ -271,7 +302,7 @@ protected: /// \brief Emits long jump instruction to Addr. /// \return Pointer to the memory area for emitting target address. - uint8_t* createStubFunction(uint8_t *Addr); + uint8_t *createStubFunction(uint8_t *Addr); /// \brief Resolves relocations from Relocs list with address from Value. void resolveRelocationList(const RelocationList &Relocs, uint64_t Value); @@ -281,14 +312,14 @@ protected: /// \param Value Target symbol address to apply the relocation action virtual void resolveRelocation(const RelocationEntry &RE, uint64_t Value) = 0; - /// \brief Parses the object file relocation and stores it to Relocations - /// or SymbolRelocations (this depends on the object file type). - virtual void processRelocationRef(unsigned SectionID, - RelocationRef RelI, - ObjectImage &Obj, - ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, - StubMap &Stubs) = 0; + /// \brief Parses one or more object file relocations (some object files use + /// relocation pairs) and stores it to Relocations or SymbolRelocations + /// (this depends on the object file type). + /// \return Iterator to the next relocation that needs to be parsed. + virtual relocation_iterator + processRelocationRef(unsigned SectionID, relocation_iterator RelI, + ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID, + const SymbolTableMap &Symbols, StubMap &Stubs) = 0; /// \brief Resolve relocations to external symbols. void resolveExternalSymbols(); @@ -297,29 +328,44 @@ protected: // The base class does nothing. ELF overrides this. virtual void updateGOTEntries(StringRef Name, uint64_t Addr) {} - virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer); + // \brief Compute an upper bound of the memory that is required to load all + // sections + void computeTotalAllocSize(ObjectImage &Obj, uint64_t &CodeSize, + uint64_t &DataSizeRO, uint64_t &DataSizeRW); + + // \brief Compute the stub buffer size required for a section + unsigned computeSectionStubBufSize(ObjectImage &Obj, + const SectionRef &Section); + public: - RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {} + RuntimeDyldImpl(RTDyldMemoryManager *mm) + : MemMgr(mm), ProcessAllSections(false), HasError(false) {} virtual ~RuntimeDyldImpl(); - ObjectImage *loadObject(ObjectBuffer *InputBuffer); + void setProcessAllSections(bool ProcessAllSections) { + this->ProcessAllSections = ProcessAllSections; + } + + ObjectImage *loadObject(ObjectImage *InputObject); void *getSymbolAddress(StringRef Name) { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. - if (GlobalSymbolTable.find(Name) == GlobalSymbolTable.end()) - return 0; - SymbolLoc Loc = GlobalSymbolTable.lookup(Name); + SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name); + if (pos == GlobalSymbolTable.end()) + return nullptr; + SymbolLoc Loc = pos->second; return getSectionAddress(Loc.first) + Loc.second; } uint64_t getSymbolLoadAddress(StringRef Name) { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. - if (GlobalSymbolTable.find(Name) == GlobalSymbolTable.end()) + SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name); + if (pos == GlobalSymbolTable.end()) return 0; - SymbolLoc Loc = GlobalSymbolTable.lookup(Name); + SymbolLoc Loc = pos->second; return getSectionLoadAddress(Loc.first) + Loc.second; } @@ -339,15 +385,15 @@ public: StringRef getErrorString() { return ErrorStr; } virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0; + virtual bool isCompatibleFile(const ObjectFile *Obj) const = 0; virtual void registerEHFrames(); virtual void deregisterEHFrames(); - virtual void finalizeLoad(ObjSectionToIDMap &SectionMap) {} + virtual void finalizeLoad(ObjectImage &ObjImg, ObjSectionToIDMap &SectionMap) {} }; } // end namespace llvm - #endif