X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=include%2Fllvm%2FExecutionEngine%2FRuntimeDyld.h;h=a808d923116713e0554a70f4fe66bf06199de825;hp=87ba119457c0db58459bbff7ce40ef61e94d8625;hb=91383a36daa2bb1c5647f4f92e87dac2ec388331;hpb=b027105fa50c864d44873dc78daafb3db3ec9c14 diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 87ba119457c..a808d923116 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -11,62 +11,235 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_RUNTIME_DYLD_H -#define LLVM_RUNTIME_DYLD_H +#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/Support/Memory.h" +#include "llvm/DebugInfo/DIContext.h" +#include namespace llvm { +namespace object { + class ObjectFile; + template class OwningBinary; +} + class RuntimeDyldImpl; -class MemoryBuffer; - -// RuntimeDyld clients often want to handle the memory management of -// what gets placed where. For JIT clients, this is an abstraction layer -// over the JITMemoryManager, which references objects by their source -// representations in LLVM IR. -// FIXME: As the RuntimeDyld fills out, additional routines will be needed -// for the varying types of objects to be allocated. -class RTDyldMemoryManager { - RTDyldMemoryManager(const RTDyldMemoryManager&); // DO NOT IMPLEMENT - void operator=(const RTDyldMemoryManager&); // DO NOT IMPLEMENT -public: - RTDyldMemoryManager() {} - virtual ~RTDyldMemoryManager(); - - // Allocate ActualSize bytes, or more, for the named function. Return - // a pointer to the allocated memory and update Size to reflect how much - // memory was acutally allocated. - virtual uint8_t *startFunctionBody(const char *Name, uintptr_t &Size) = 0; - - // Mark the end of the function, including how much of the allocated - // memory was actually used. - virtual void endFunctionBody(const char *Name, uint8_t *FunctionStart, - uint8_t *FunctionEnd) = 0; -}; +class RuntimeDyldCheckerImpl; class RuntimeDyld { - RuntimeDyld(const RuntimeDyld &); // DO NOT IMPLEMENT - void operator=(const RuntimeDyld &); // DO NOT IMPLEMENT + friend class RuntimeDyldCheckerImpl; - // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public - // interface. - RuntimeDyldImpl *Dyld; + RuntimeDyld(const RuntimeDyld &) = delete; + void operator=(const RuntimeDyld &) = delete; + +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: + LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { } + + virtual object::OwningBinary + getObjectForDebug(const object::ObjectFile &Obj) const = 0; + + uint64_t getSectionLoadAddress(StringRef Name) const; + + protected: + virtual void anchor(); + + RuntimeDyldImpl &RTDyld; + unsigned BeginIdx, EndIdx; + }; + + template struct LoadedObjectInfoHelper : LoadedObjectInfo { + LoadedObjectInfoHelper(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {} + std::unique_ptr clone() const override { + return llvm::make_unique(static_cast(*this)); + } + }; + + /// \brief Memory Management. + class MemoryManager { + public: + 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(); + }; + + /// \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(); - bool loadObject(MemoryBuffer *InputBuffer); - // 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 reassignSymbolAddress(StringRef Name, uint64_t Addr); - // FIXME: Should be parameterized to get the memory block associated with - // a particular loaded object. - sys::MemoryBlock getMemoryBlock(); + /// 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 *getSymbolLocalAddress(StringRef Name) const; + + /// 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(); + + /// Map a section to its target address space value. + /// Map the address of a JIT section as returned from the memory manager + /// to the address in the target process as the running code will see it. + /// 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(); + + /// 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; + } + +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