X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FExecutionEngine%2FRuntimeDyld.h;h=afd8de64913e5a10742beb79c576f4b10f8b3fcd;hb=1a41a8ee7d262acbf2846d52a43ad91bc66cb9f2;hp=1a573171a457e73f8ce1d1ce83691bbfeb8d920c;hpb=876af64ac716ba557a25e136793b9343a24a35ad;p=oota-llvm.git diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 1a573171a45..afd8de64913 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -14,46 +14,201 @@ #ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H #define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H +#include "JITSymbolFlags.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/Memory.h" +#include "llvm/DebugInfo/DIContext.h" +#include +#include namespace llvm { +namespace object { + class ObjectFile; + template class OwningBinary; +} + class RuntimeDyldImpl; -class ObjectImage; +class RuntimeDyldCheckerImpl; class RuntimeDyld { - RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION; - void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION; + friend class RuntimeDyldCheckerImpl; + + RuntimeDyld(const RuntimeDyld &) = delete; + void operator=(const RuntimeDyld &) = delete; - // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public - // interface. - RuntimeDyldImpl *Dyld; - RTDyldMemoryManager *MM; protected: // Change the address associated with a section when resolving relocations. // Any relocations already associated with the symbol will be re-resolved. void reassignSectionAddress(unsigned SectionID, uint64_t Addr); public: - RuntimeDyld(RTDyldMemoryManager *); + + /// \brief Information about a named symbol. + class SymbolInfo : public JITSymbolBase { + public: + SymbolInfo(std::nullptr_t) : JITSymbolBase(JITSymbolFlags::None), Address(0) {} + SymbolInfo(uint64_t Address, JITSymbolFlags Flags) + : JITSymbolBase(Flags), Address(Address) {} + explicit operator bool() const { return Address != 0; } + uint64_t getAddress() const { return Address; } + private: + uint64_t Address; + }; + + /// \brief Information about the loaded object. + class LoadedObjectInfo : public llvm::LoadedObjectInfo { + friend class RuntimeDyldImpl; + public: + typedef std::map ObjSectionToIDMap; + + LoadedObjectInfo(RuntimeDyldImpl &RTDyld, ObjSectionToIDMap ObjSecToIDMap) + : RTDyld(RTDyld), ObjSecToIDMap(ObjSecToIDMap) { } + + virtual object::OwningBinary + getObjectForDebug(const object::ObjectFile &Obj) const = 0; + + uint64_t + getSectionLoadAddress(const object::SectionRef &Sec) const override; + + protected: + virtual void anchor(); + + RuntimeDyldImpl &RTDyld; + ObjSectionToIDMap ObjSecToIDMap; + }; + + template struct LoadedObjectInfoHelper : LoadedObjectInfo { + protected: + LoadedObjectInfoHelper(const LoadedObjectInfoHelper &) = default; + LoadedObjectInfoHelper() = default; + + public: + LoadedObjectInfoHelper(RuntimeDyldImpl &RTDyld, + LoadedObjectInfo::ObjSectionToIDMap ObjSecToIDMap) + : LoadedObjectInfo(RTDyld, std::move(ObjSecToIDMap)) {} + std::unique_ptr clone() const override { + return llvm::make_unique(static_cast(*this)); + } + }; + + /// \brief Memory Management. + class MemoryManager { + friend class RuntimeDyld; + public: + MemoryManager() : FinalizationLocked(false) {} + virtual ~MemoryManager() {} + + /// Allocate a memory block of (at least) the given size suitable for + /// executable code. The SectionID is a unique identifier assigned by the + /// RuntimeDyld instance, and optionally recorded by the memory manager to + /// access a loaded section. + virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName) = 0; + + /// Allocate a memory block of (at least) the given size suitable for data. + /// The SectionID is a unique identifier assigned by the JIT engine, and + /// optionally recorded by the memory manager to access a loaded section. + virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName, + bool IsReadOnly) = 0; + + /// Inform the memory manager about the total amount of memory required to + /// allocate all sections to be loaded: + /// \p CodeSize - the total size of all code sections + /// \p DataSizeRO - the total size of all read-only data sections + /// \p DataSizeRW - the total size of all read-write data sections + /// + /// Note that by default the callback is disabled. To enable it + /// redefine the method needsToReserveAllocationSpace to return true. + virtual void reserveAllocationSpace(uintptr_t CodeSize, + uintptr_t DataSizeRO, + uintptr_t DataSizeRW) {} + + /// Override to return true to enable the reserveAllocationSpace callback. + virtual bool needsToReserveAllocationSpace() { return false; } + + /// Register the EH frames with the runtime so that c++ exceptions work. + /// + /// \p Addr parameter provides the local address of the EH frame section + /// data, while \p LoadAddr provides the address of the data in the target + /// address space. If the section has not been remapped (which will usually + /// be the case for local execution) these two values will be the same. + virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, + size_t Size) = 0; + virtual void deregisterEHFrames(uint8_t *addr, uint64_t LoadAddr, + size_t Size) = 0; + + /// This method is called when object loading is complete and section page + /// permissions can be applied. It is up to the memory manager implementation + /// to decide whether or not to act on this method. The memory manager will + /// typically allocate all sections as read-write and then apply specific + /// permissions when this method is called. Code sections cannot be executed + /// until this function has been called. In addition, any cache coherency + /// operations needed to reliably use the memory are also performed. + /// + /// Returns true if an error occurred, false otherwise. + virtual bool finalizeMemory(std::string *ErrMsg = nullptr) = 0; + + private: + virtual void anchor(); + bool FinalizationLocked; + }; + + /// \brief Symbol resolution. + class SymbolResolver { + public: + virtual ~SymbolResolver() {} + + /// This method returns the address of the specified function or variable. + /// It is used to resolve symbols during module linking. + /// + /// If the returned symbol's address is equal to ~0ULL then RuntimeDyld will + /// skip all relocations for that symbol, and the client will be responsible + /// for handling them manually. + virtual SymbolInfo findSymbol(const std::string &Name) = 0; + + /// This method returns the address of the specified symbol if it exists + /// within the logical dynamic library represented by this + /// RTDyldMemoryManager. Unlike getSymbolAddress, queries through this + /// interface should return addresses for hidden symbols. + /// + /// This is of particular importance for the Orc JIT APIs, which support lazy + /// compilation by breaking up modules: Each of those broken out modules + /// must be able to resolve hidden symbols provided by the others. Clients + /// writing memory managers for MCJIT can usually ignore this method. + /// + /// This method will be queried by RuntimeDyld when checking for previous + /// definitions of common symbols. It will *not* be queried by default when + /// resolving external symbols (this minimises the link-time overhead for + /// MCJIT clients who don't care about Orc features). If you are writing a + /// RTDyldMemoryManager for Orc and want "external" symbol resolution to + /// search the logical dylib, you should override your getSymbolAddress + /// method call this method directly. + virtual SymbolInfo findSymbolInLogicalDylib(const std::string &Name) = 0; + private: + virtual void anchor(); + }; + + /// \brief Construct a RuntimeDyld instance. + RuntimeDyld(MemoryManager &MemMgr, SymbolResolver &Resolver); ~RuntimeDyld(); - /// Prepare the object contained in the input buffer for execution. - /// Ownership of the input buffer is transferred to the ObjectImage - /// instance returned from this function if successful. In the case of load - /// failure, the input buffer will be deleted. - ObjectImage *loadObject(ObjectBuffer *InputBuffer); + /// Add the referenced object file to the list of objects to be loaded and + /// relocated. + std::unique_ptr loadObject(const object::ObjectFile &O); /// Get the address of our local copy of the symbol. This may or may not /// be the address used for relocation (clients can copy the data around /// and resolve relocatons based on where they put it). - void *getSymbolAddress(StringRef Name); + void *getSymbolLocalAddress(StringRef Name) const; - /// Get the address of the target copy of the symbol. This is the address - /// used for relocation. - uint64_t getSymbolLoadAddress(StringRef Name); + /// Get the target address and flags for the named symbol. + /// This address is the one used for relocation. + SymbolInfo getSymbol(StringRef Name) const; /// Resolve the relocations for all symbols we currently know about. void resolveRelocations(); @@ -64,11 +219,60 @@ public: /// This is the address which will be used for relocation resolution. void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress); + /// Register any EH frame sections that have been loaded but not previously + /// registered with the memory manager. Note, RuntimeDyld is responsible + /// for identifying the EH frame and calling the memory manager with the + /// EH frame section data. However, the memory manager itself will handle + /// the actual target-specific EH frame registration. + void registerEHFrames(); + + void deregisterEHFrames(); + + bool hasError(); StringRef getErrorString(); - StringRef getEHFrameSection(); + /// By default, only sections that are "required for execution" are passed to + /// the RTDyldMemoryManager, and other sections are discarded. Passing 'true' + /// to this method will cause RuntimeDyld to pass all sections to its + /// memory manager regardless of whether they are "required to execute" in the + /// usual sense. This is useful for inspecting metadata sections that may not + /// contain relocations, E.g. Debug info, stackmaps. + /// + /// Must be called before the first object file is loaded. + void setProcessAllSections(bool ProcessAllSections) { + assert(!Dyld && "setProcessAllSections must be called before loadObject."); + this->ProcessAllSections = ProcessAllSections; + } + + /// Perform all actions needed to make the code owned by this RuntimeDyld + /// instance executable: + /// + /// 1) Apply relocations. + /// 2) Register EH frames. + /// 3) Update memory permissions*. + /// + /// * Finalization is potentially recursive**, and the 3rd step will only be + /// applied by the outermost call to finalize. This allows different + /// RuntimeDyld instances to share a memory manager without the innermost + /// finalization locking the memory and causing relocation fixup errors in + /// outer instances. + /// + /// ** Recursive finalization occurs when one RuntimeDyld instances needs the + /// address of a symbol owned by some other instance in order to apply + /// relocations. + /// + void finalizeWithMemoryManagerLocking(); + +private: + // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public + // interface. + std::unique_ptr Dyld; + MemoryManager &MemMgr; + SymbolResolver &Resolver; + bool ProcessAllSections; + RuntimeDyldCheckerImpl *Checker; }; } // end namespace llvm -#endif +#endif // LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H