From: Lang Hames Date: Wed, 26 Nov 2014 16:54:40 +0000 (+0000) Subject: [MCJIT] Reapply r222828 and r222810-r222812 with fix for MSVC move-op issues. X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=216e532dc182273b33b16228ee3c608389480523 [MCJIT] Reapply r222828 and r222810-r222812 with fix for MSVC move-op issues. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222840 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ExecutionEngine/JITEventListener.h b/include/llvm/ExecutionEngine/JITEventListener.h index cef3aa27d5c..c3edec86878 100644 --- a/include/llvm/ExecutionEngine/JITEventListener.h +++ b/include/llvm/ExecutionEngine/JITEventListener.h @@ -15,6 +15,7 @@ #ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H #define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H +#include "RuntimeDyld.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Support/DataTypes.h" @@ -25,7 +26,10 @@ class Function; class MachineFunction; class OProfileWrapper; class IntelJITEventsWrapper; -class ObjectImage; + +namespace object { + class ObjectFile; +} /// JITEvent_EmittedFunctionDetails - Helper struct for containing information /// about a generated machine code function. @@ -57,7 +61,7 @@ public: public: JITEventListener() {} - virtual ~JITEventListener(); + virtual ~JITEventListener() {} /// NotifyObjectEmitted - Called after an object has been successfully /// emitted to memory. NotifyFunctionEmitted will not be called for @@ -67,11 +71,15 @@ public: /// The ObjectImage contains the generated object image /// with section headers updated to reflect the address at which sections /// were loaded and with relocations performed in-place on debug sections. - virtual void NotifyObjectEmitted(const ObjectImage &Obj) {} + virtual void NotifyObjectEmitted(const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) {} /// NotifyFreeingObject - Called just before the memory associated with /// a previously emitted object is released. - virtual void NotifyFreeingObject(const ObjectImage &Obj) {} + virtual void NotifyFreeingObject(const object::ObjectFile &Obj) {} + + // Get a pointe to the GDB debugger registration listener. + static JITEventListener *createGDBRegistrationListener(); #if LLVM_USE_INTEL_JITEVENTS // Construct an IntelJITEventListener @@ -105,7 +113,8 @@ public: return nullptr; } #endif // USE_OPROFILE - +private: + virtual void anchor(); }; } // end namespace llvm. diff --git a/include/llvm/ExecutionEngine/ObjectBuffer.h b/include/llvm/ExecutionEngine/ObjectBuffer.h deleted file mode 100644 index ee4820aa6ee..00000000000 --- a/include/llvm/ExecutionEngine/ObjectBuffer.h +++ /dev/null @@ -1,76 +0,0 @@ -//===---- ObjectBuffer.h - Utility class to wrap object image memory -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares a wrapper class to hold the memory into which an -// object will be generated. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_OBJECTBUFFER_H -#define LLVM_EXECUTIONENGINE_OBJECTBUFFER_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { - -/// This class acts as a container for the memory buffer used during generation -/// and loading of executable objects using MCJIT and RuntimeDyld. The -/// underlying memory for the object will be owned by the ObjectBuffer instance -/// throughout its lifetime. -class ObjectBuffer { - virtual void anchor(); -public: - ObjectBuffer() {} - ObjectBuffer(std::unique_ptr Buf) : Buffer(std::move(Buf)) {} - virtual ~ObjectBuffer() {} - - MemoryBufferRef getMemBuffer() const { return Buffer->getMemBufferRef(); } - - const char *getBufferStart() const { return Buffer->getBufferStart(); } - size_t getBufferSize() const { return Buffer->getBufferSize(); } - StringRef getBuffer() const { return Buffer->getBuffer(); } - StringRef getBufferIdentifier() const { - return Buffer->getBufferIdentifier(); - } - -protected: - // The memory contained in an ObjectBuffer - std::unique_ptr Buffer; -}; - -/// This class encapsulates the SmallVector and raw_svector_ostream needed to -/// generate an object using MC code emission while providing a common -/// ObjectBuffer interface for access to the memory once the object has been -/// generated. -class ObjectBufferStream : public ObjectBuffer { - void anchor() override; -public: - ObjectBufferStream() : OS(SV) {} - virtual ~ObjectBufferStream() {} - - raw_ostream &getOStream() { return OS; } - void flush() - { - OS.flush(); - - // Make the data accessible via the ObjectBuffer::Buffer - Buffer = - MemoryBuffer::getMemBuffer(StringRef(SV.data(), SV.size()), "", false); - } - -protected: - SmallVector SV; // Working buffer into which we JIT. - raw_svector_ostream OS; // streaming wrapper -}; - -} // namespace llvm - -#endif diff --git a/include/llvm/ExecutionEngine/ObjectImage.h b/include/llvm/ExecutionEngine/ObjectImage.h deleted file mode 100644 index dc142bd70af..00000000000 --- a/include/llvm/ExecutionEngine/ObjectImage.h +++ /dev/null @@ -1,76 +0,0 @@ -//===---- ObjectImage.h - Format independent executuable object image -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares a file format independent ObjectImage class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_OBJECTIMAGE_H -#define LLVM_EXECUTIONENGINE_OBJECTIMAGE_H - -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/Object/ObjectFile.h" - -namespace llvm { - - -/// ObjectImage - A container class that represents an ObjectFile that has been -/// or is in the process of being loaded into memory for execution. -class ObjectImage { - ObjectImage() LLVM_DELETED_FUNCTION; - ObjectImage(const ObjectImage &other) LLVM_DELETED_FUNCTION; - virtual void anchor(); - -protected: - std::unique_ptr Buffer; - -public: - ObjectImage(std::unique_ptr Input) : Buffer(std::move(Input)) {} - virtual ~ObjectImage() {} - - virtual object::symbol_iterator begin_symbols() const = 0; - virtual object::symbol_iterator end_symbols() const = 0; - iterator_range symbols() const { - return iterator_range(begin_symbols(), - end_symbols()); - } - - virtual object::section_iterator begin_sections() const = 0; - virtual object::section_iterator end_sections() const = 0; - iterator_range sections() const { - return iterator_range(begin_sections(), - end_sections()); - } - - virtual /* Triple::ArchType */ unsigned getArch() const = 0; - - // Return the name associated with this ObjectImage. - // This is usually the name of the file or MemoryBuffer that the the - // ObjectBuffer was constructed from. - StringRef getImageName() const { return Buffer->getBufferIdentifier(); } - - // Subclasses can override these methods to update the image with loaded - // addresses for sections and common symbols - virtual void updateSectionAddress(const object::SectionRef &Sec, - uint64_t Addr) = 0; - virtual void updateSymbolAddress(const object::SymbolRef &Sym, - uint64_t Addr) = 0; - - virtual StringRef getData() const = 0; - - virtual object::ObjectFile* getObjectFile() const = 0; - - // Subclasses can override these methods to provide JIT debugging support - virtual void registerWithDebugger() = 0; - virtual void deregisterWithDebugger() = 0; -}; - -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_OBJECTIMAGE_H diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index b941efcad01..ef81cd328bd 100644 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -22,7 +22,10 @@ namespace llvm { class ExecutionEngine; -class ObjectImage; + + namespace object { + class ObjectFile; + } // RuntimeDyld clients often want to handle the memory management of // what gets placed where. For JIT clients, this is the subset of @@ -109,7 +112,7 @@ public: /// address space can use this call to remap the section addresses for the /// newly loaded object. virtual void notifyObjectLoaded(ExecutionEngine *EE, - const ObjectImage *) {} + const object::ObjectFile &) {} /// This method is called when object loading is complete and section page /// permissions can be applied. It is up to the memory manager implementation diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 3605b9e44d7..799fc34eb65 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -15,19 +15,19 @@ #define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H #include "llvm/ADT/StringRef.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/Memory.h" +#include namespace llvm { namespace object { class ObjectFile; + template class OwningBinary; } class RuntimeDyldImpl; class RuntimeDyldCheckerImpl; -class ObjectImage; class RuntimeDyld { friend class RuntimeDyldCheckerImpl; @@ -46,22 +46,35 @@ protected: // Any relocations already associated with the symbol will be re-resolved. void reassignSectionAddress(unsigned SectionID, uint64_t Addr); public: + + /// \brief Information about the loaded object. + class LoadedObjectInfo { + friend class RuntimeDyldImpl; + public: + LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { } + + virtual ~LoadedObjectInfo() {} + + 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; + }; + RuntimeDyld(RTDyldMemoryManager *); ~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. - std::unique_ptr - loadObject(std::unique_ptr InputBuffer); - - /// Prepare the referenced object file for execution. - /// Ownership of the input object is transferred to the ObjectImage - /// instance returned from this function if successful. In the case of load - /// failure, the input object will be deleted. - std::unique_ptr - loadObject(std::unique_ptr InputObject); + /// 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 diff --git a/lib/ExecutionEngine/CMakeLists.txt b/lib/ExecutionEngine/CMakeLists.txt index fae5bb900b9..208495c8847 100644 --- a/lib/ExecutionEngine/CMakeLists.txt +++ b/lib/ExecutionEngine/CMakeLists.txt @@ -3,7 +3,6 @@ add_llvm_library(LLVMExecutionEngine ExecutionEngine.cpp ExecutionEngineBindings.cpp - JITEventListener.cpp RTDyldMemoryManager.cpp TargetSelect.cpp ) diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 5a6d65624be..4d4cb2a26d8 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -16,8 +16,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" #include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/ExecutionEngine/ObjectCache.h" +#include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" @@ -43,17 +42,15 @@ using namespace llvm; STATISTIC(NumInitBytes, "Number of bytes of global vars initialized"); STATISTIC(NumGlobals , "Number of global vars initialized"); -// Pin the vtable to this file. -void ObjectCache::anchor() {} -void ObjectBuffer::anchor() {} -void ObjectBufferStream::anchor() {} - ExecutionEngine *(*ExecutionEngine::MCJITCtor)( std::unique_ptr M, std::string *ErrorStr, RTDyldMemoryManager *MCJMM, std::unique_ptr TM) = nullptr; ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr M, std::string *ErrorStr) =nullptr; +// Anchor for the JITEventListener class. +void JITEventListener::anchor() {} + ExecutionEngine::ExecutionEngine(std::unique_ptr M) : EEState(*this), LazyFunctionCreator(nullptr) { diff --git a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp index b23ca88baf1..c35e5244ecd 100644 --- a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp +++ b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp @@ -21,7 +21,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/DebugInfo/DIContext.h" -#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -32,6 +31,7 @@ using namespace llvm; using namespace llvm::jitprofiling; +using namespace llvm::object; #define DEBUG_TYPE "amplifier-jit-event-listener" @@ -48,6 +48,7 @@ class IntelJITEventListener : public JITEventListener { typedef DenseMap ObjectMap; ObjectMap LoadedObjectMap; + std::map> DebugObjects; public: IntelJITEventListener(IntelJITEventsWrapper* libraryWrapper) { @@ -57,9 +58,10 @@ public: ~IntelJITEventListener() { } - virtual void NotifyObjectEmitted(const ObjectImage &Obj); + void NotifyObjectEmitted(const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) override; - virtual void NotifyFreeingObject(const ObjectImage &Obj); + void NotifyFreeingObject(const ObjectFile &Obj) override; }; static LineNumberInfo DILineInfoToIntelJITFormat(uintptr_t StartAddress, @@ -95,23 +97,29 @@ static iJIT_Method_Load FunctionDescToIntelJITFormat( return Result; } -void IntelJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { +void IntelJITEventListener::NotifyObjectEmitted( + const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) { + + OwningBinary DebugObjOwner = L.getObjectForDebug(Obj); + const ObjectFile &DebugObj = *DebugObjOwner.getBinary(); + // Get the address of the object image for use as a unique identifier - const void* ObjData = Obj.getData().data(); - DIContext* Context = DIContext::getDWARFContext(*Obj.getObjectFile()); + const void* ObjData = DebugObj.getData().data(); + DIContext* Context = DIContext::getDWARFContext(DebugObj); MethodAddressVector Functions; // Use symbol info to iterate functions in the object. - for (object::symbol_iterator I = Obj.begin_symbols(), - E = Obj.end_symbols(); + for (symbol_iterator I = DebugObj.symbol_begin(), + E = DebugObj.symbol_end(); I != E; ++I) { std::vector LineInfo; std::string SourceFileName; - object::SymbolRef::Type SymType; + SymbolRef::Type SymType; if (I->getType(SymType)) continue; - if (SymType == object::SymbolRef::ST_Function) { + if (SymType == SymbolRef::ST_Function) { StringRef Name; uint64_t Addr; uint64_t Size; @@ -162,11 +170,18 @@ void IntelJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { // registered function addresses for each loaded object. We will // use the MethodIDs map to get the registered ID for each function. LoadedObjectMap[ObjData] = Functions; + DebugObjects[Obj.getData().data()] = std::move(DebugObjOwner); } -void IntelJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) { +void IntelJITEventListener::NotifyFreeingObject(const ObjectFile &Obj) { + // This object may not have been registered with the listener. If it wasn't, + // bail out. + if (DebugObjects.find(Obj.getData().data()) == DebugObjects.end()) + return; + // Get the address of the object image for use as a unique identifier - const void* ObjData = Obj.getData().data(); + const ObjectFile &DebugObj = *DebugObjects[Obj.getData().data()].getBinary(); + const void* ObjData = DebugObj.getData().data(); // Get the object's function list from LoadedObjectMap ObjectMap::iterator OI = LoadedObjectMap.find(ObjData); @@ -190,6 +205,7 @@ void IntelJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) { // Erase the object from LoadedObjectMap LoadedObjectMap.erase(OI); + DebugObjects.erase(Obj.getData().data()); } } // anonymous namespace. diff --git a/lib/ExecutionEngine/JITEventListener.cpp b/lib/ExecutionEngine/JITEventListener.cpp deleted file mode 100644 index 2a6a0070d97..00000000000 --- a/lib/ExecutionEngine/JITEventListener.cpp +++ /dev/null @@ -1,15 +0,0 @@ -//===-- JITEventListener.cpp ----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JITEventListener.h" - -using namespace llvm; - -// Out-of-line definition of the virtual destructor as this is the key function. -JITEventListener::~JITEventListener() {} diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index da5f03799e3..58cf4e5e6dd 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -11,8 +11,6 @@ #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/MCJIT.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" @@ -21,6 +19,7 @@ #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/PassManager.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ErrorHandling.h" @@ -31,6 +30,8 @@ using namespace llvm; +void ObjectCache::anchor() {} + namespace { static struct RegisterJIT { @@ -74,6 +75,7 @@ MCJIT::MCJIT(std::unique_ptr M, std::unique_ptr tm, OwnedModules.addModule(std::move(First)); setDataLayout(TM->getSubtargetImpl()->getDataLayout()); + RegisterJITEventListener(JITEventListener::createGDBRegistrationListener()); } MCJIT::~MCJIT() { @@ -99,13 +101,13 @@ bool MCJIT::removeModule(Module *M) { } void MCJIT::addObjectFile(std::unique_ptr Obj) { - std::unique_ptr LoadedObject = Dyld.loadObject(std::move(Obj)); - if (!LoadedObject || Dyld.hasError()) + std::unique_ptr L = Dyld.loadObject(*Obj); + if (Dyld.hasError()) report_fatal_error(Dyld.getErrorString()); - NotifyObjectEmitted(*LoadedObject); + NotifyObjectEmitted(*Obj, *L); - LoadedObjects.push_back(std::move(LoadedObject)); + LoadedObjects.push_back(std::move(Obj)); } void MCJIT::addObjectFile(object::OwningBinary Obj) { @@ -125,7 +127,7 @@ void MCJIT::setObjectCache(ObjectCache* NewCache) { ObjCache = NewCache; } -std::unique_ptr MCJIT::emitObject(Module *M) { +std::unique_ptr MCJIT::emitObject(Module *M) { MutexGuard locked(lock); // This must be a module which has already been added but not loaded to this @@ -138,30 +140,32 @@ std::unique_ptr MCJIT::emitObject(Module *M) { PM.add(new DataLayoutPass()); // The RuntimeDyld will take ownership of this shortly - std::unique_ptr CompiledObject(new ObjectBufferStream()); + SmallVector ObjBufferSV; + raw_svector_ostream ObjStream(ObjBufferSV); // Turn the machine code intermediate representation into bytes in memory // that may be executed. - if (TM->addPassesToEmitMC(PM, Ctx, CompiledObject->getOStream(), - !getVerifyModules())) { + if (TM->addPassesToEmitMC(PM, Ctx, ObjStream, !getVerifyModules())) report_fatal_error("Target does not support MC emission!"); - } // Initialize passes. PM.run(*M); // Flush the output buffer to get the generated code into memory - CompiledObject->flush(); + ObjStream.flush(); + + std::unique_ptr CompiledObjBuffer( + new ObjectMemoryBuffer(std::move(ObjBufferSV))); // If we have an object cache, tell it about the new object. // Note that we're using the compiled image, not the loaded image (as below). if (ObjCache) { // MemoryBuffer is a thin wrapper around the actual memory, so it's OK // to create a temporary object here and delete it after the call. - MemoryBufferRef MB = CompiledObject->getMemBuffer(); + MemoryBufferRef MB = CompiledObjBuffer->getMemBufferRef(); ObjCache->notifyObjectCompiled(M, MB); } - return CompiledObject; + return CompiledObjBuffer; } void MCJIT::generateCodeForModule(Module *M) { @@ -176,14 +180,10 @@ void MCJIT::generateCodeForModule(Module *M) { if (OwnedModules.hasModuleBeenLoaded(M)) return; - std::unique_ptr ObjectToLoad; + std::unique_ptr ObjectToLoad; // Try to load the pre-compiled object from cache if possible - if (ObjCache) { - if (std::unique_ptr PreCompiledObject = - ObjCache->getObject(M)) - ObjectToLoad = - llvm::make_unique(std::move(PreCompiledObject)); - } + if (ObjCache) + ObjectToLoad = ObjCache->getObject(M); // If the cache did not contain a suitable object, compile the object if (!ObjectToLoad) { @@ -193,17 +193,18 @@ void MCJIT::generateCodeForModule(Module *M) { // Load the object into the dynamic linker. // MCJIT now owns the ObjectImage pointer (via its LoadedObjects list). - std::unique_ptr LoadedObject = - Dyld.loadObject(std::move(ObjectToLoad)); - if (!LoadedObject) - report_fatal_error(Dyld.getErrorString()); + ErrorOr> LoadedObject = + object::ObjectFile::createObjectFile(ObjectToLoad->getMemBufferRef()); + std::unique_ptr L = + Dyld.loadObject(*LoadedObject.get()); - // FIXME: Make this optional, maybe even move it to a JIT event listener - LoadedObject->registerWithDebugger(); + if (Dyld.hasError()) + report_fatal_error(Dyld.getErrorString()); - NotifyObjectEmitted(*LoadedObject); + NotifyObjectEmitted(*LoadedObject.get(), *L); - LoadedObjects.push_back(std::move(LoadedObject)); + Buffers.push_back(std::move(ObjectToLoad)); + LoadedObjects.push_back(std::move(*LoadedObject)); OwnedModules.markModuleAsLoaded(M); } @@ -549,6 +550,7 @@ void MCJIT::RegisterJITEventListener(JITEventListener *L) { MutexGuard locked(lock); EventListeners.push_back(L); } + void MCJIT::UnregisterJITEventListener(JITEventListener *L) { if (!L) return; @@ -559,14 +561,17 @@ void MCJIT::UnregisterJITEventListener(JITEventListener *L) { EventListeners.pop_back(); } } -void MCJIT::NotifyObjectEmitted(const ObjectImage& Obj) { + +void MCJIT::NotifyObjectEmitted(const object::ObjectFile& Obj, + const RuntimeDyld::LoadedObjectInfo &L) { MutexGuard locked(lock); - MemMgr.notifyObjectLoaded(this, &Obj); + MemMgr.notifyObjectLoaded(this, Obj); for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { - EventListeners[I]->NotifyObjectEmitted(Obj); + EventListeners[I]->NotifyObjectEmitted(Obj, L); } } -void MCJIT::NotifyFreeingObject(const ObjectImage& Obj) { + +void MCJIT::NotifyFreeingObject(const object::ObjectFile& Obj) { MutexGuard locked(lock); for (JITEventListener *L : EventListeners) L->NotifyFreeingObject(Obj); diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h index bc943b9b886..6f92e51b64c 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -10,12 +10,12 @@ #ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H #define LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H +#include "ObjectBuffer.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/ObjectCache.h" -#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/Module.h" @@ -57,7 +57,7 @@ public: } void notifyObjectLoaded(ExecutionEngine *EE, - const ObjectImage *Obj) override { + const object::ObjectFile &Obj) override { ClientMM->notifyObjectLoaded(EE, Obj); } @@ -222,7 +222,7 @@ class MCJIT : public ExecutionEngine { SmallVector, 2> Archives; SmallVector, 2> Buffers; - SmallVector, 2> LoadedObjects; + SmallVector, 2> LoadedObjects; // An optional ObjectCache to be notified of compiled objects and used to // perform lookup of pre-compiled code to avoid re-compilation. @@ -341,10 +341,11 @@ protected: /// this function call is expected to be the contained module. The module /// is passed as a parameter here to prepare for multiple module support in /// the future. - std::unique_ptr emitObject(Module *M); + std::unique_ptr emitObject(Module *M); - void NotifyObjectEmitted(const ObjectImage& Obj); - void NotifyFreeingObject(const ObjectImage& Obj); + void NotifyObjectEmitted(const object::ObjectFile& Obj, + const RuntimeDyld::LoadedObjectInfo &L); + void NotifyFreeingObject(const object::ObjectFile& Obj); uint64_t getExistingSymbolAddress(const std::string &Name); Module *findModuleForSymbol(const std::string &Name, diff --git a/lib/ExecutionEngine/MCJIT/ObjectBuffer.h b/lib/ExecutionEngine/MCJIT/ObjectBuffer.h new file mode 100644 index 00000000000..92310f3eb54 --- /dev/null +++ b/lib/ExecutionEngine/MCJIT/ObjectBuffer.h @@ -0,0 +1,48 @@ +//===--- ObjectBuffer.h - Utility class to wrap object memory ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares a wrapper class to hold the memory into which an +// object will be generated. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_OBJECTBUFFER_H +#define LLVM_EXECUTIONENGINE_OBJECTBUFFER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class ObjectMemoryBuffer : public MemoryBuffer { +public: + template + ObjectMemoryBuffer(SmallVector SV) + : SV(SV), BufferName("") { + init(this->SV.begin(), this->SV.end(), false); + } + + template + ObjectMemoryBuffer(SmallVector SV, StringRef Name) + : SV(SV), BufferName(Name) { + init(this->SV.begin(), this->SV.end(), false); + } + const char* getBufferIdentifier() const override { return BufferName.c_str(); } + + BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; } + +private: + SmallVector SV; + std::string BufferName; +}; + +} // namespace llvm + +#endif diff --git a/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp b/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp index 5a8ccb66e52..92a67b9b2a6 100644 --- a/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp +++ b/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp @@ -18,8 +18,8 @@ #include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" #include "llvm/CodeGen/MachineFunction.h" -#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/OProfileWrapper.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -31,31 +31,34 @@ using namespace llvm; using namespace llvm::jitprofiling; +using namespace llvm::object; #define DEBUG_TYPE "oprofile-jit-event-listener" namespace { class OProfileJITEventListener : public JITEventListener { - OProfileWrapper& Wrapper; + std::unique_ptr Wrapper; void initialize(); + std::map> DebugObjects; public: - OProfileJITEventListener(OProfileWrapper& LibraryWrapper) - : Wrapper(LibraryWrapper) { + OProfileJITEventListener(std::unique_ptr LibraryWrapper) + : Wrapper(std::move(LibraryWrapper)) { initialize(); } ~OProfileJITEventListener(); - virtual void NotifyObjectEmitted(const ObjectImage &Obj); + void NotifyObjectEmitted(const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) override; - virtual void NotifyFreeingObject(const ObjectImage &Obj); + void NotifyFreeingObject(const ObjectFile &Obj) override; }; void OProfileJITEventListener::initialize() { - if (!Wrapper.op_open_agent()) { + if (!Wrapper->op_open_agent()) { const std::string err_str = sys::StrError(); DEBUG(dbgs() << "Failed to connect to OProfile agent: " << err_str << "\n"); } else { @@ -64,8 +67,8 @@ void OProfileJITEventListener::initialize() { } OProfileJITEventListener::~OProfileJITEventListener() { - if (Wrapper.isAgentAvailable()) { - if (Wrapper.op_close_agent() == -1) { + if (Wrapper->isAgentAvailable()) { + if (Wrapper->op_close_agent() == -1) { const std::string err_str = sys::StrError(); DEBUG(dbgs() << "Failed to disconnect from OProfile agent: " << err_str << "\n"); @@ -75,17 +78,22 @@ OProfileJITEventListener::~OProfileJITEventListener() { } } -void OProfileJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { - if (!Wrapper.isAgentAvailable()) { +void OProfileJITEventListener::NotifyObjectEmitted( + const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) { + if (!Wrapper->isAgentAvailable()) { return; } + OwningBinary DebugObjOwner = L.getObjectForDebug(Obj); + const ObjectFile &DebugObj = *DebugObjOwner.getBinary(); + // Use symbol info to iterate functions in the object. - for (object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); + for (symbol_iterator I = DebugObj.symbol_begin(), E = DebugObj.symbol_end(); I != E; ++I) { - object::SymbolRef::Type SymType; + SymbolRef::Type SymType; if (I->getType(SymType)) continue; - if (SymType == object::SymbolRef::ST_Function) { + if (SymType == SymbolRef::ST_Function) { StringRef Name; uint64_t Addr; uint64_t Size; @@ -93,7 +101,7 @@ void OProfileJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { if (I->getAddress(Addr)) continue; if (I->getSize(Size)) continue; - if (Wrapper.op_write_native_code(Name.data(), Addr, (void*)Addr, Size) + if (Wrapper->op_write_native_code(Name.data(), Addr, (void*)Addr, Size) == -1) { DEBUG(dbgs() << "Failed to tell OProfile about native function " << Name << " at [" @@ -103,45 +111,48 @@ void OProfileJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { // TODO: support line number info (similar to IntelJITEventListener.cpp) } } -} - -void OProfileJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) { - if (!Wrapper.isAgentAvailable()) { - return; - } - // Use symbol info to iterate functions in the object. - for (object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); - I != E; ++I) { - object::SymbolRef::Type SymType; - if (I->getType(SymType)) continue; - if (SymType == object::SymbolRef::ST_Function) { - uint64_t Addr; - if (I->getAddress(Addr)) continue; + DebugObjects[Obj.getData().data()] = std::move(DebugObjOwner); +} - if (Wrapper.op_unload_native_code(Addr) == -1) { - DEBUG(dbgs() - << "Failed to tell OProfile about unload of native function at " - << (void*)Addr << "\n"); - continue; +void OProfileJITEventListener::NotifyFreeingObject(const ObjectFile &Obj) { + if (Wrapper->isAgentAvailable()) { + + // If there was no agent registered when the original object was loaded then + // we won't have created a debug object for it, so bail out. + if (DebugObjects.find(Obj.getData().data()) == DebugObjects.end()) + return; + + const ObjectFile &DebugObj = *DebugObjects[Obj.getData().data()].getBinary(); + + // Use symbol info to iterate functions in the object. + for (symbol_iterator I = DebugObj.symbol_begin(), + E = DebugObj.symbol_end(); + I != E; ++I) { + SymbolRef::Type SymType; + if (I->getType(SymType)) continue; + if (SymType == SymbolRef::ST_Function) { + uint64_t Addr; + if (I->getAddress(Addr)) continue; + + if (Wrapper->op_unload_native_code(Addr) == -1) { + DEBUG(dbgs() + << "Failed to tell OProfile about unload of native function at " + << (void*)Addr << "\n"); + continue; + } } } } + + DebugObjects.erase(Obj.getData().data()); } } // anonymous namespace. namespace llvm { JITEventListener *JITEventListener::createOProfileJITEventListener() { - static std::unique_ptr JITProfilingWrapper( - new OProfileWrapper); - return new OProfileJITEventListener(*JITProfilingWrapper); -} - -// for testing -JITEventListener *JITEventListener::createOProfileJITEventListener( - OProfileWrapper* TestImpl) { - return new OProfileJITEventListener(*TestImpl); + return new OProfileJITEventListener(llvm::make_unique()); } } // namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt b/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt index eb1a60b60d0..583d7a0aa41 100644 --- a/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt +++ b/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt @@ -1,5 +1,5 @@ add_llvm_library(LLVMRuntimeDyld - GDBRegistrar.cpp + GDBRegistrationListener.cpp RuntimeDyld.cpp RuntimeDyldChecker.cpp RuntimeDyldELF.cpp diff --git a/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp b/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp deleted file mode 100644 index dfa3a203ac3..00000000000 --- a/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp +++ /dev/null @@ -1,213 +0,0 @@ -//===-- GDBRegistrar.cpp - Registers objects with GDB ---------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "JITRegistrar.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Mutex.h" -#include "llvm/Support/MutexGuard.h" -#include "llvm/Support/ManagedStatic.h" - -using namespace llvm; - -// This must be kept in sync with gdb/gdb/jit.h . -extern "C" { - - typedef enum { - JIT_NOACTION = 0, - JIT_REGISTER_FN, - JIT_UNREGISTER_FN - } jit_actions_t; - - struct jit_code_entry { - struct jit_code_entry *next_entry; - struct jit_code_entry *prev_entry; - const char *symfile_addr; - uint64_t symfile_size; - }; - - struct jit_descriptor { - uint32_t version; - // This should be jit_actions_t, but we want to be specific about the - // bit-width. - uint32_t action_flag; - struct jit_code_entry *relevant_entry; - struct jit_code_entry *first_entry; - }; - - // We put information about the JITed function in this global, which the - // debugger reads. Make sure to specify the version statically, because the - // debugger checks the version before we can set it during runtime. - struct jit_descriptor __jit_debug_descriptor = { 1, 0, nullptr, nullptr }; - - // Debuggers puts a breakpoint in this function. - LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() { - // The noinline and the asm prevent calls to this function from being - // optimized out. -#if !defined(_MSC_VER) - asm volatile("":::"memory"); -#endif - } - -} - -namespace { - -// Buffer for an in-memory object file in executable memory -typedef llvm::DenseMap< const char*, - std::pair > - RegisteredObjectBufferMap; - -/// Global access point for the JIT debugging interface designed for use with a -/// singleton toolbox. Handles thread-safe registration and deregistration of -/// object files that are in executable memory managed by the client of this -/// class. -class GDBJITRegistrar : public JITRegistrar { - /// A map of in-memory object files that have been registered with the - /// JIT interface. - RegisteredObjectBufferMap ObjectBufferMap; - -public: - /// Instantiates the JIT service. - GDBJITRegistrar() : ObjectBufferMap() {} - - /// Unregisters each object that was previously registered and releases all - /// internal resources. - virtual ~GDBJITRegistrar(); - - /// Creates an entry in the JIT registry for the buffer @p Object, - /// which must contain an object file in executable memory with any - /// debug information for the debugger. - void registerObject(const ObjectBuffer &Object) override; - - /// Removes the internal registration of @p Object, and - /// frees associated resources. - /// Returns true if @p Object was found in ObjectBufferMap. - bool deregisterObject(const ObjectBuffer &Object) override; - -private: - /// Deregister the debug info for the given object file from the debugger - /// and delete any temporary copies. This private method does not remove - /// the function from Map so that it can be called while iterating over Map. - void deregisterObjectInternal(RegisteredObjectBufferMap::iterator I); -}; - -/// Lock used to serialize all jit registration events, since they -/// modify global variables. -ManagedStatic JITDebugLock; - -/// Do the registration. -void NotifyDebugger(jit_code_entry* JITCodeEntry) { - __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; - - // Insert this entry at the head of the list. - JITCodeEntry->prev_entry = nullptr; - jit_code_entry* NextEntry = __jit_debug_descriptor.first_entry; - JITCodeEntry->next_entry = NextEntry; - if (NextEntry) { - NextEntry->prev_entry = JITCodeEntry; - } - __jit_debug_descriptor.first_entry = JITCodeEntry; - __jit_debug_descriptor.relevant_entry = JITCodeEntry; - __jit_debug_register_code(); -} - -GDBJITRegistrar::~GDBJITRegistrar() { - // Free all registered object files. - llvm::MutexGuard locked(*JITDebugLock); - for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(), E = ObjectBufferMap.end(); - I != E; ++I) { - // Call the private method that doesn't update the map so our iterator - // doesn't break. - deregisterObjectInternal(I); - } - ObjectBufferMap.clear(); -} - -void GDBJITRegistrar::registerObject(const ObjectBuffer &Object) { - - const char *Buffer = Object.getBufferStart(); - size_t Size = Object.getBufferSize(); - - assert(Buffer && "Attempt to register a null object with a debugger."); - llvm::MutexGuard locked(*JITDebugLock); - assert(ObjectBufferMap.find(Buffer) == ObjectBufferMap.end() && - "Second attempt to perform debug registration."); - jit_code_entry* JITCodeEntry = new jit_code_entry(); - - if (!JITCodeEntry) { - llvm::report_fatal_error( - "Allocation failed when registering a JIT entry!\n"); - } else { - JITCodeEntry->symfile_addr = Buffer; - JITCodeEntry->symfile_size = Size; - - ObjectBufferMap[Buffer] = std::make_pair(Size, JITCodeEntry); - NotifyDebugger(JITCodeEntry); - } -} - -bool GDBJITRegistrar::deregisterObject(const ObjectBuffer& Object) { - const char *Buffer = Object.getBufferStart(); - llvm::MutexGuard locked(*JITDebugLock); - RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Buffer); - - if (I != ObjectBufferMap.end()) { - deregisterObjectInternal(I); - ObjectBufferMap.erase(I); - return true; - } - return false; -} - -void GDBJITRegistrar::deregisterObjectInternal( - RegisteredObjectBufferMap::iterator I) { - - jit_code_entry*& JITCodeEntry = I->second.second; - - // Do the unregistration. - { - __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN; - - // Remove the jit_code_entry from the linked list. - jit_code_entry* PrevEntry = JITCodeEntry->prev_entry; - jit_code_entry* NextEntry = JITCodeEntry->next_entry; - - if (NextEntry) { - NextEntry->prev_entry = PrevEntry; - } - if (PrevEntry) { - PrevEntry->next_entry = NextEntry; - } - else { - assert(__jit_debug_descriptor.first_entry == JITCodeEntry); - __jit_debug_descriptor.first_entry = NextEntry; - } - - // Tell the debugger which entry we removed, and unregister the code. - __jit_debug_descriptor.relevant_entry = JITCodeEntry; - __jit_debug_register_code(); - } - - delete JITCodeEntry; - JITCodeEntry = nullptr; -} - -llvm::ManagedStatic TheRegistrar; - -} // end namespace - -namespace llvm { - -JITRegistrar& JITRegistrar::getGDBRegistrar() { - return *TheRegistrar; -} - -} // namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/GDBRegistrationListener.cpp b/lib/ExecutionEngine/RuntimeDyld/GDBRegistrationListener.cpp new file mode 100644 index 00000000000..34f5962dd3b --- /dev/null +++ b/lib/ExecutionEngine/RuntimeDyld/GDBRegistrationListener.cpp @@ -0,0 +1,246 @@ +//===----- GDBRegistrationListener.cpp - Registers objects with GDB -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/MutexGuard.h" +#include "llvm/Support/ManagedStatic.h" + +using namespace llvm; +using namespace llvm::object; + +// This must be kept in sync with gdb/gdb/jit.h . +extern "C" { + + typedef enum { + JIT_NOACTION = 0, + JIT_REGISTER_FN, + JIT_UNREGISTER_FN + } jit_actions_t; + + struct jit_code_entry { + struct jit_code_entry *next_entry; + struct jit_code_entry *prev_entry; + const char *symfile_addr; + uint64_t symfile_size; + }; + + struct jit_descriptor { + uint32_t version; + // This should be jit_actions_t, but we want to be specific about the + // bit-width. + uint32_t action_flag; + struct jit_code_entry *relevant_entry; + struct jit_code_entry *first_entry; + }; + + // We put information about the JITed function in this global, which the + // debugger reads. Make sure to specify the version statically, because the + // debugger checks the version before we can set it during runtime. + struct jit_descriptor __jit_debug_descriptor = { 1, 0, nullptr, nullptr }; + + // Debuggers puts a breakpoint in this function. + LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() { + // The noinline and the asm prevent calls to this function from being + // optimized out. +#if !defined(_MSC_VER) + asm volatile("":::"memory"); +#endif + } + +} + +namespace { + +struct RegisteredObjectInfo { + RegisteredObjectInfo() {} + + RegisteredObjectInfo(std::size_t Size, jit_code_entry *Entry, + OwningBinary Obj) + : Size(Size), Entry(Entry), Obj(std::move(Obj)) {} + + RegisteredObjectInfo(RegisteredObjectInfo &&Other) + : Size(Other.Size), Entry(Other.Entry), Obj(std::move(Other.Obj)) {} + + RegisteredObjectInfo& operator=(RegisteredObjectInfo &&Other) { + Size = Other.Size; + Entry = Other.Entry; + Obj = std::move(Other.Obj); + } + + std::size_t Size; + jit_code_entry *Entry; + OwningBinary Obj; +}; + +// Buffer for an in-memory object file in executable memory +typedef llvm::DenseMap< const char*, RegisteredObjectInfo> + RegisteredObjectBufferMap; + +/// Global access point for the JIT debugging interface designed for use with a +/// singleton toolbox. Handles thread-safe registration and deregistration of +/// object files that are in executable memory managed by the client of this +/// class. +class GDBJITRegistrationListener : public JITEventListener { + /// A map of in-memory object files that have been registered with the + /// JIT interface. + RegisteredObjectBufferMap ObjectBufferMap; + +public: + /// Instantiates the JIT service. + GDBJITRegistrationListener() : ObjectBufferMap() {} + + /// Unregisters each object that was previously registered and releases all + /// internal resources. + virtual ~GDBJITRegistrationListener(); + + /// Creates an entry in the JIT registry for the buffer @p Object, + /// which must contain an object file in executable memory with any + /// debug information for the debugger. + void NotifyObjectEmitted(const ObjectFile &Object, + const RuntimeDyld::LoadedObjectInfo &L) override; + + /// Removes the internal registration of @p Object, and + /// frees associated resources. + /// Returns true if @p Object was found in ObjectBufferMap. + void NotifyFreeingObject(const ObjectFile &Object) override; + +private: + /// Deregister the debug info for the given object file from the debugger + /// and delete any temporary copies. This private method does not remove + /// the function from Map so that it can be called while iterating over Map. + void deregisterObjectInternal(RegisteredObjectBufferMap::iterator I); +}; + +/// Lock used to serialize all jit registration events, since they +/// modify global variables. +ManagedStatic JITDebugLock; + +/// Do the registration. +void NotifyDebugger(jit_code_entry* JITCodeEntry) { + __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; + + // Insert this entry at the head of the list. + JITCodeEntry->prev_entry = nullptr; + jit_code_entry* NextEntry = __jit_debug_descriptor.first_entry; + JITCodeEntry->next_entry = NextEntry; + if (NextEntry) { + NextEntry->prev_entry = JITCodeEntry; + } + __jit_debug_descriptor.first_entry = JITCodeEntry; + __jit_debug_descriptor.relevant_entry = JITCodeEntry; + __jit_debug_register_code(); +} + +GDBJITRegistrationListener::~GDBJITRegistrationListener() { + // Free all registered object files. + llvm::MutexGuard locked(*JITDebugLock); + for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(), + E = ObjectBufferMap.end(); + I != E; ++I) { + // Call the private method that doesn't update the map so our iterator + // doesn't break. + deregisterObjectInternal(I); + } + ObjectBufferMap.clear(); +} + +void GDBJITRegistrationListener::NotifyObjectEmitted( + const ObjectFile &Object, + const RuntimeDyld::LoadedObjectInfo &L) { + + OwningBinary DebugObj = L.getObjectForDebug(Object); + + // Bail out if debug objects aren't supported. + if (!DebugObj.getBinary()) + return; + + const char *Buffer = DebugObj.getBinary()->getMemoryBufferRef().getBufferStart(); + size_t Size = DebugObj.getBinary()->getMemoryBufferRef().getBufferSize(); + + const char *Key = Object.getMemoryBufferRef().getBufferStart(); + + assert(Key && "Attempt to register a null object with a debugger."); + llvm::MutexGuard locked(*JITDebugLock); + assert(ObjectBufferMap.find(Key) == ObjectBufferMap.end() && + "Second attempt to perform debug registration."); + jit_code_entry* JITCodeEntry = new jit_code_entry(); + + if (!JITCodeEntry) { + llvm::report_fatal_error( + "Allocation failed when registering a JIT entry!\n"); + } else { + JITCodeEntry->symfile_addr = Buffer; + JITCodeEntry->symfile_size = Size; + + ObjectBufferMap[Key] = RegisteredObjectInfo(Size, JITCodeEntry, + std::move(DebugObj)); + NotifyDebugger(JITCodeEntry); + } +} + +void GDBJITRegistrationListener::NotifyFreeingObject(const ObjectFile& Object) { + const char *Key = Object.getMemoryBufferRef().getBufferStart(); + llvm::MutexGuard locked(*JITDebugLock); + RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Key); + + if (I != ObjectBufferMap.end()) { + deregisterObjectInternal(I); + ObjectBufferMap.erase(I); + } +} + +void GDBJITRegistrationListener::deregisterObjectInternal( + RegisteredObjectBufferMap::iterator I) { + + jit_code_entry*& JITCodeEntry = I->second.Entry; + + // Do the unregistration. + { + __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN; + + // Remove the jit_code_entry from the linked list. + jit_code_entry* PrevEntry = JITCodeEntry->prev_entry; + jit_code_entry* NextEntry = JITCodeEntry->next_entry; + + if (NextEntry) { + NextEntry->prev_entry = PrevEntry; + } + if (PrevEntry) { + PrevEntry->next_entry = NextEntry; + } + else { + assert(__jit_debug_descriptor.first_entry == JITCodeEntry); + __jit_debug_descriptor.first_entry = NextEntry; + } + + // Tell the debugger which entry we removed, and unregister the code. + __jit_debug_descriptor.relevant_entry = JITCodeEntry; + __jit_debug_register_code(); + } + + delete JITCodeEntry; + JITCodeEntry = nullptr; +} + +llvm::ManagedStatic GDBRegListener; + +} // end namespace + +namespace llvm { + +JITEventListener* JITEventListener::createGDBRegistrationListener() { + return &*GDBRegListener; +} + +} // namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h b/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h deleted file mode 100644 index 636011f7efe..00000000000 --- a/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h +++ /dev/null @@ -1,44 +0,0 @@ -//===-- JITRegistrar.h - Registers objects with a debugger ----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_JITREGISTRAR_H -#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_JITREGISTRAR_H - -#include "llvm/ExecutionEngine/ObjectBuffer.h" - -namespace llvm { - -/// Global access point for the JIT debugging interface. -class JITRegistrar { - virtual void anchor(); -public: - /// Instantiates the JIT service. - JITRegistrar() {} - - /// Unregisters each object that was previously registered and releases all - /// internal resources. - virtual ~JITRegistrar() {} - - /// Creates an entry in the JIT registry for the buffer @p Object, - /// which must contain an object file in executable memory with any - /// debug information for the debugger. - virtual void registerObject(const ObjectBuffer &Object) = 0; - - /// Removes the internal registration of @p Object, and - /// frees associated resources. - /// Returns true if @p Object was previously registered. - virtual bool deregisterObject(const ObjectBuffer &Object) = 0; - - /// Returns a reference to a GDB JIT registrar singleton - static JITRegistrar& getGDBRegistrar(); -}; - -} // end namespace llvm - -#endif diff --git a/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h b/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h deleted file mode 100644 index 9bbf6a0d809..00000000000 --- a/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h +++ /dev/null @@ -1,86 +0,0 @@ -//===-- ObjectImageCommon.h - Format independent executuable object image -===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares a file format independent ObjectImage class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_OBJECTIMAGECOMMON_H -#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_OBJECTIMAGECOMMON_H - -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/ExecutionEngine/ObjectImage.h" -#include "llvm/Object/ObjectFile.h" - -#include - -namespace llvm { - -namespace object { - class ObjectFile; -} - -class ObjectImageCommon : public ObjectImage { - ObjectImageCommon(); // = delete - ObjectImageCommon(const ObjectImageCommon &other); // = delete - void anchor() override; - -protected: - std::unique_ptr ObjFile; - - // This form of the constructor allows subclasses to use - // format-specific subclasses of ObjectFile directly - ObjectImageCommon(std::unique_ptr Input, - std::unique_ptr Obj) - : ObjectImage(std::move(Input)), ObjFile(std::move(Obj)) {} - -public: - ObjectImageCommon(std::unique_ptr Input) - : ObjectImage(std::move(Input)) { - // FIXME: error checking? createObjectFile returns an ErrorOr - // and should probably be checked for failure. - MemoryBufferRef Buf = Buffer->getMemBuffer(); - ObjFile = std::move(object::ObjectFile::createObjectFile(Buf).get()); - } - ObjectImageCommon(std::unique_ptr Input) - : ObjectImage(nullptr), ObjFile(std::move(Input)) {} - virtual ~ObjectImageCommon() { } - - object::symbol_iterator begin_symbols() const override - { return ObjFile->symbol_begin(); } - object::symbol_iterator end_symbols() const override - { return ObjFile->symbol_end(); } - - object::section_iterator begin_sections() const override - { return ObjFile->section_begin(); } - object::section_iterator end_sections() const override - { return ObjFile->section_end(); } - - /* Triple::ArchType */ unsigned getArch() const override - { return ObjFile->getArch(); } - - StringRef getData() const override { return ObjFile->getData(); } - - object::ObjectFile* getObjectFile() const override { return ObjFile.get(); } - - // Subclasses can override these methods to update the image with loaded - // addresses for sections and common symbols - void updateSectionAddress(const object::SectionRef &Sec, - uint64_t Addr) override {} - void updateSymbolAddress(const object::SymbolRef &Sym, - uint64_t Addr) override {} - - // Subclasses can override these methods to provide JIT debugging support - void registerWithDebugger() override {} - void deregisterWithDebugger() override {} -}; - -} // end namespace llvm - -#endif diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index c7c67f6a1e4..af9a80504d5 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -12,8 +12,6 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/RuntimeDyld.h" -#include "JITRegistrar.h" -#include "ObjectImageCommon.h" #include "RuntimeDyldCheckerImpl.h" #include "RuntimeDyldELF.h" #include "RuntimeDyldImpl.h" @@ -30,10 +28,8 @@ using namespace llvm::object; // Empty out-of-line virtual destructor as the key function. RuntimeDyldImpl::~RuntimeDyldImpl() {} -// Pin the JITRegistrar's and ObjectImage*'s vtables to this file. -void JITRegistrar::anchor() {} -void ObjectImage::anchor() {} -void ObjectImageCommon::anchor() {} +// Pin LoadedObjectInfo's vtables to this file. +void RuntimeDyld::LoadedObjectInfo::anchor() {} namespace llvm { @@ -139,22 +135,23 @@ static std::error_code getOffset(const SymbolRef &Sym, uint64_t &Result) { return object_error::success; } -std::unique_ptr -RuntimeDyldImpl::loadObject(std::unique_ptr Obj) { +std::pair +RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { MutexGuard locked(lock); - if (!Obj) - return nullptr; + // Grab the first Section ID. We'll use this later to construct the underlying + // range for the returned LoadedObjectInfo. + unsigned SectionsAddedBeginIdx = Sections.size(); // Save information about our target - Arch = (Triple::ArchType)Obj->getArch(); - IsTargetLittleEndian = Obj->getObjectFile()->isLittleEndian(); + Arch = (Triple::ArchType)Obj.getArch(); + IsTargetLittleEndian = Obj.isLittleEndian(); // Compute the memory size required to load all sections to be loaded // and pass this information to the memory manager if (MemMgr->needsToReserveAllocationSpace()) { uint64_t CodeSize = 0, DataSizeRO = 0, DataSizeRW = 0; - computeTotalAllocSize(*Obj, CodeSize, DataSizeRO, DataSizeRW); + computeTotalAllocSize(Obj, CodeSize, DataSizeRO, DataSizeRW); MemMgr->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); } @@ -170,7 +167,7 @@ RuntimeDyldImpl::loadObject(std::unique_ptr Obj) { // Parse symbols DEBUG(dbgs() << "Parse symbols:\n"); - for (symbol_iterator I = Obj->begin_symbols(), E = Obj->end_symbols(); I != E; + for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { object::SymbolRef::Type SymType; StringRef Name; @@ -196,15 +193,15 @@ RuntimeDyldImpl::loadObject(std::unique_ptr Obj) { SymType == object::SymbolRef::ST_Unknown) { uint64_t SectOffset; StringRef SectionData; - section_iterator SI = Obj->end_sections(); + section_iterator SI = Obj.section_end(); Check(getOffset(*I, SectOffset)); Check(I->getSection(SI)); - if (SI == Obj->end_sections()) + if (SI == Obj.section_end()) continue; Check(SI->getContents(SectionData)); bool IsCode = SI->isText(); unsigned SectionID = - findOrEmitSection(*Obj, *SI, IsCode, LocalSections); + findOrEmitSection(Obj, *SI, IsCode, LocalSections); LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); DEBUG(dbgs() << "\tOffset: " << format("%p", (uintptr_t)SectOffset) << " flags: " << Flags << " SID: " << SectionID); @@ -216,11 +213,11 @@ RuntimeDyldImpl::loadObject(std::unique_ptr Obj) { // Allocate common symbols if (CommonSize != 0) - emitCommonSymbols(*Obj, CommonSymbols, CommonSize, GlobalSymbolTable); + emitCommonSymbols(Obj, CommonSymbols, CommonSize, GlobalSymbolTable); // Parse and process relocations DEBUG(dbgs() << "Parse relocations:\n"); - for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections(); + for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { unsigned SectionID = 0; StubMap Stubs; @@ -234,23 +231,25 @@ RuntimeDyldImpl::loadObject(std::unique_ptr Obj) { bool IsCode = RelocatedSection->isText(); SectionID = - findOrEmitSection(*Obj, *RelocatedSection, IsCode, LocalSections); + findOrEmitSection(Obj, *RelocatedSection, IsCode, LocalSections); DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); for (; I != E;) - I = processRelocationRef(SectionID, I, *Obj, LocalSections, LocalSymbols, + I = processRelocationRef(SectionID, I, Obj, LocalSections, LocalSymbols, Stubs); // If there is an attached checker, notify it about the stubs for this // section so that they can be verified. if (Checker) - Checker->registerStubMap(Obj->getImageName(), SectionID, Stubs); + Checker->registerStubMap(Obj.getFileName(), SectionID, Stubs); } // Give the subclasses a chance to tie-up any loose ends. - finalizeLoad(*Obj, LocalSections); + finalizeLoad(Obj, LocalSections); + + unsigned SectionsAddedEndIdx = Sections.size(); - return Obj; + return std::make_pair(SectionsAddedBeginIdx, SectionsAddedEndIdx); } // A helper method for computeTotalAllocSize. @@ -270,7 +269,7 @@ computeAllocationSizeForSections(std::vector &SectionSizes, // Compute an upper bound of the memory size that is required to load all // sections -void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, +void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, uint64_t &CodeSize, uint64_t &DataSizeRO, uint64_t &DataSizeRW) { @@ -282,7 +281,7 @@ void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, // Collect sizes of all sections to be loaded; // also determine the max alignment of all sections - for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections(); + for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { const SectionRef &Section = *SI; @@ -328,7 +327,7 @@ void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, // Compute the size of all common symbols uint64_t CommonSize = 0; - for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E; + for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { uint32_t Flags = I->getFlags(); if (Flags & SymbolRef::SF_Common) { @@ -353,7 +352,7 @@ void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, } // compute stub buffer size for the given section -unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj, +unsigned RuntimeDyldImpl::computeSectionStubBufSize(const ObjectFile &Obj, const SectionRef &Section) { unsigned StubSize = getMaxStubSize(); if (StubSize == 0) { @@ -363,7 +362,7 @@ unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj, // necessary section allocation size in loadObject by walking all the sections // once. unsigned StubBufSize = 0; - for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections(); + for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { section_iterator RelSecI = SI->getRelocatedSection(); if (!(RelSecI == Section)) @@ -418,7 +417,7 @@ void RuntimeDyldImpl::writeBytesUnaligned(uint64_t Value, uint8_t *Dst, } } -void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, +void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, const CommonSymbolMap &CommonSymbols, uint64_t TotalSize, SymbolTableMap &SymbolTable) { @@ -450,14 +449,13 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, DEBUG(dbgs() << "Allocating common symbol " << Name << " address " << format("%p\n", Addr)); } - Obj.updateSymbolAddress(it->first, (uint64_t)Addr); SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset); Offset += Size; Addr += Size; } } -unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, +unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode) { StringRef data; @@ -521,7 +519,6 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, << " new addr: " << format("%p", Addr) << " DataSize: " << DataSize << " StubBufSize: " << StubBufSize << " Allocate: " << Allocate << "\n"); - Obj.updateSectionAddress(Section, (uint64_t)Addr); } else { // Even if we didn't load the section, we need to record an entry for it // to handle later processing (and by 'handle' I mean don't do anything @@ -537,12 +534,12 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData)); if (Checker) - Checker->registerSection(Obj.getImageName(), SectionID); + Checker->registerSection(Obj.getFileName(), SectionID); return SectionID; } -unsigned RuntimeDyldImpl::findOrEmitSection(ObjectImage &Obj, +unsigned RuntimeDyldImpl::findOrEmitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode, ObjSectionToIDMap &LocalSections) { @@ -739,6 +736,16 @@ void RuntimeDyldImpl::resolveExternalSymbols() { //===----------------------------------------------------------------------===// // RuntimeDyld class implementation + +uint64_t RuntimeDyld::LoadedObjectInfo::getSectionLoadAddress( + StringRef SectionName) const { + for (unsigned I = BeginIdx; I != EndIdx; ++I) + if (RTDyld.Sections[I].Name == SectionName) + return RTDyld.Sections[I].LoadAddress; + + return 0; +} + RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { // FIXME: There's a potential issue lurking here if a single instance of // RuntimeDyld is used to load multiple objects. The current implementation @@ -772,78 +779,23 @@ createRuntimeDyldMachO(Triple::ArchType Arch, RTDyldMemoryManager *MM, return Dyld; } -std::unique_ptr -RuntimeDyld::loadObject(std::unique_ptr InputObject) { - std::unique_ptr InputImage; - - ObjectFile &Obj = *InputObject; - - if (InputObject->isELF()) { - InputImage.reset(RuntimeDyldELF::createObjectImageFromFile(std::move(InputObject))); - if (!Dyld) +std::unique_ptr +RuntimeDyld::loadObject(const ObjectFile &Obj) { + if (!Dyld) { + if (Obj.isELF()) Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker); - } else if (InputObject->isMachO()) { - InputImage.reset(RuntimeDyldMachO::createObjectImageFromFile(std::move(InputObject))); - if (!Dyld) + else if (Obj.isMachO()) Dyld = createRuntimeDyldMachO( - static_cast(InputImage->getArch()), MM, - ProcessAllSections, Checker); - } else - report_fatal_error("Incompatible object format!"); - - if (!Dyld->isCompatibleFile(&Obj)) - report_fatal_error("Incompatible object format!"); - - return Dyld->loadObject(std::move(InputImage)); -} - -std::unique_ptr -RuntimeDyld::loadObject(std::unique_ptr InputBuffer) { - std::unique_ptr InputImage; - sys::fs::file_magic Type = sys::fs::identify_magic(InputBuffer->getBuffer()); - auto *InputBufferPtr = InputBuffer.get(); - - switch (Type) { - case sys::fs::file_magic::elf: - case sys::fs::file_magic::elf_relocatable: - case sys::fs::file_magic::elf_executable: - case sys::fs::file_magic::elf_shared_object: - case sys::fs::file_magic::elf_core: - InputImage = RuntimeDyldELF::createObjectImage(std::move(InputBuffer)); - if (!Dyld) - Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker); - break; - case sys::fs::file_magic::macho_object: - case sys::fs::file_magic::macho_executable: - case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: - case sys::fs::file_magic::macho_core: - case sys::fs::file_magic::macho_preload_executable: - case sys::fs::file_magic::macho_dynamically_linked_shared_lib: - case sys::fs::file_magic::macho_dynamic_linker: - case sys::fs::file_magic::macho_bundle: - case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: - case sys::fs::file_magic::macho_dsym_companion: - InputImage = RuntimeDyldMachO::createObjectImage(std::move(InputBuffer)); - if (!Dyld) - Dyld = createRuntimeDyldMachO( - static_cast(InputImage->getArch()), MM, - ProcessAllSections, Checker); - break; - case sys::fs::file_magic::unknown: - case sys::fs::file_magic::bitcode: - case sys::fs::file_magic::archive: - case sys::fs::file_magic::coff_object: - case sys::fs::file_magic::coff_import_library: - case sys::fs::file_magic::pecoff_executable: - case sys::fs::file_magic::macho_universal_binary: - case sys::fs::file_magic::windows_resource: - report_fatal_error("Incompatible object format!"); + static_cast(Obj.getArch()), MM, + ProcessAllSections, Checker); + else + report_fatal_error("Incompatible object format!"); } - if (!Dyld->isCompatibleFormat(InputBufferPtr)) + if (!Dyld->isCompatibleFile(Obj)) report_fatal_error("Incompatible object format!"); - return Dyld->loadObject(std::move(InputImage)); + return Dyld->loadObject(Obj); } void *RuntimeDyld::getSymbolAddress(StringRef Name) const { diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index d95cffef03f..d213cc93793 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -12,27 +12,23 @@ //===----------------------------------------------------------------------===// #include "RuntimeDyldELF.h" -#include "JITRegistrar.h" -#include "ObjectImageCommon.h" #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/ExecutionEngine/ObjectImage.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/TargetRegistry.h" using namespace llvm; using namespace llvm::object; #define DEBUG_TYPE "dyld" -namespace { - static inline std::error_code check(std::error_code Err) { if (Err) { report_fatal_error(Err.message()); @@ -40,6 +36,8 @@ static inline std::error_code check(std::error_code Err) { return Err; } +namespace { + template class DyldELFObject : public ELFObjectFile { LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) @@ -52,16 +50,12 @@ template class DyldELFObject : public ELFObjectFile { typedef typename ELFDataTypeTypedefHelper::value_type addr_type; - std::unique_ptr UnderlyingFile; - public: - DyldELFObject(std::unique_ptr UnderlyingFile, - MemoryBufferRef Wrapper, std::error_code &ec); - DyldELFObject(MemoryBufferRef Wrapper, std::error_code &ec); void updateSectionAddress(const SectionRef &Sec, uint64_t Addr); - void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr); + + void updateSymbolAddress(const SymbolRef &SymRef, uint64_t Addr); // Methods for type inquiry through isa, cast and dyn_cast static inline bool classof(const Binary *v) { @@ -71,42 +65,10 @@ public: static inline bool classof(const ELFObjectFile *v) { return v->isDyldType(); } -}; - -template class ELFObjectImage : public ObjectImageCommon { - bool Registered; -public: - ELFObjectImage(std::unique_ptr Input, - std::unique_ptr> Obj) - : ObjectImageCommon(std::move(Input), std::move(Obj)), Registered(false) { - } - - virtual ~ELFObjectImage() { - if (Registered) - deregisterWithDebugger(); - } - - // Subclasses can override these methods to update the image with loaded - // addresses for sections and common symbols - void updateSectionAddress(const SectionRef &Sec, uint64_t Addr) override { - static_cast*>(getObjectFile()) - ->updateSectionAddress(Sec, Addr); - } +}; - void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr) override { - static_cast*>(getObjectFile()) - ->updateSymbolAddress(Sym, Addr); - } - void registerWithDebugger() override { - JITRegistrar::getGDBRegistrar().registerObject(*Buffer); - Registered = true; - } - void deregisterWithDebugger() override { - JITRegistrar::getGDBRegistrar().deregisterObject(*Buffer); - } -}; // The MemoryBuffer passed into this constructor is just a wrapper around the // actual memory. Ultimately, the Binary parent class will take ownership of @@ -117,14 +79,6 @@ DyldELFObject::DyldELFObject(MemoryBufferRef Wrapper, std::error_code &EC) this->isDyldELFObject = true; } -template -DyldELFObject::DyldELFObject(std::unique_ptr UnderlyingFile, - MemoryBufferRef Wrapper, std::error_code &EC) - : ELFObjectFile(Wrapper, EC), - UnderlyingFile(std::move(UnderlyingFile)) { - this->isDyldELFObject = true; -} - template void DyldELFObject::updateSectionAddress(const SectionRef &Sec, uint64_t Addr) { @@ -149,10 +103,89 @@ void DyldELFObject::updateSymbolAddress(const SymbolRef &SymRef, sym->st_value = static_cast(Addr); } +class LoadedELFObjectInfo : public RuntimeDyld::LoadedObjectInfo { +public: + LoadedELFObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {} + + OwningBinary + getObjectForDebug(const ObjectFile &Obj) const override; +}; + +template +std::unique_ptr> +createRTDyldELFObject(MemoryBufferRef Buffer, + const LoadedELFObjectInfo &L, + std::error_code &ec) { + typedef typename ELFFile::Elf_Shdr Elf_Shdr; + typedef typename ELFDataTypeTypedefHelper::value_type addr_type; + + std::unique_ptr> Obj = + llvm::make_unique>(Buffer, ec); + + // Iterate over all sections in the object. + for (const auto &Sec : Obj->sections()) { + StringRef SectionName; + Sec.getName(SectionName); + if (SectionName != "") { + DataRefImpl ShdrRef = Sec.getRawDataRefImpl(); + Elf_Shdr *shdr = const_cast( + reinterpret_cast(ShdrRef.p)); + + if (uint64_t SecLoadAddr = L.getSectionLoadAddress(SectionName)) { + // This assumes that the address passed in matches the target address + // bitness. The template-based type cast handles everything else. + shdr->sh_addr = static_cast(SecLoadAddr); + } + } + } + + return Obj; +} + +OwningBinary createELFDebugObject(const ObjectFile &Obj, + const LoadedELFObjectInfo &L) { + assert(Obj.isELF() && "Not an ELF object file."); + + std::unique_ptr Buffer = + MemoryBuffer::getMemBufferCopy(Obj.getData(), Obj.getFileName()); + + std::error_code ec; + + std::unique_ptr DebugObj; + if (Obj.getBytesInAddress() == 4 && Obj.isLittleEndian()) { + typedef ELFType ELF32LE; + DebugObj = createRTDyldELFObject(Buffer->getMemBufferRef(), L, ec); + } else if (Obj.getBytesInAddress() == 4 && !Obj.isLittleEndian()) { + typedef ELFType ELF32BE; + DebugObj = createRTDyldELFObject(Buffer->getMemBufferRef(), L, ec); + } else if (Obj.getBytesInAddress() == 8 && !Obj.isLittleEndian()) { + typedef ELFType ELF64BE; + DebugObj = createRTDyldELFObject(Buffer->getMemBufferRef(), L, ec); + } else if (Obj.getBytesInAddress() == 8 && Obj.isLittleEndian()) { + typedef ELFType ELF64LE; + DebugObj = createRTDyldELFObject(Buffer->getMemBufferRef(), L, ec); + } else + llvm_unreachable("Unexpected ELF format"); + + assert(!ec && "Could not construct copy ELF object file"); + + return OwningBinary(std::move(DebugObj), std::move(Buffer)); +} + +OwningBinary +LoadedELFObjectInfo::getObjectForDebug(const ObjectFile &Obj) const { + return createELFDebugObject(Obj, *this); +} + } // namespace namespace llvm { +RuntimeDyldELF::RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} +RuntimeDyldELF::~RuntimeDyldELF() {} + void RuntimeDyldELF::registerEHFrames() { if (!MemMgr) return; @@ -180,83 +213,14 @@ void RuntimeDyldELF::deregisterEHFrames() { RegisteredEHFrameSections.clear(); } -ObjectImage * -RuntimeDyldELF::createObjectImageFromFile(std::unique_ptr ObjFile) { - if (!ObjFile) - return nullptr; - - std::error_code ec; - MemoryBufferRef Buffer = ObjFile->getMemoryBufferRef(); - - if (ObjFile->getBytesInAddress() == 4 && ObjFile->isLittleEndian()) { - auto Obj = - llvm::make_unique>>( - std::move(ObjFile), Buffer, ec); - return new ELFObjectImage>( - nullptr, std::move(Obj)); - } else if (ObjFile->getBytesInAddress() == 4 && !ObjFile->isLittleEndian()) { - auto Obj = - llvm::make_unique>>( - std::move(ObjFile), Buffer, ec); - return new ELFObjectImage>(nullptr, std::move(Obj)); - } else if (ObjFile->getBytesInAddress() == 8 && !ObjFile->isLittleEndian()) { - auto Obj = llvm::make_unique>>( - std::move(ObjFile), Buffer, ec); - return new ELFObjectImage>(nullptr, - std::move(Obj)); - } else if (ObjFile->getBytesInAddress() == 8 && ObjFile->isLittleEndian()) { - auto Obj = - llvm::make_unique>>( - std::move(ObjFile), Buffer, ec); - return new ELFObjectImage>( - nullptr, std::move(Obj)); - } else - llvm_unreachable("Unexpected ELF format"); +std::unique_ptr +RuntimeDyldELF::loadObject(const object::ObjectFile &O) { + unsigned SectionStartIdx, SectionEndIdx; + std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O); + return llvm::make_unique(*this, SectionStartIdx, + SectionEndIdx); } -std::unique_ptr -RuntimeDyldELF::createObjectImage(std::unique_ptr Buffer) { - if (Buffer->getBufferSize() < ELF::EI_NIDENT) - llvm_unreachable("Unexpected ELF object size"); - std::pair Ident = - std::make_pair((uint8_t)Buffer->getBufferStart()[ELF::EI_CLASS], - (uint8_t)Buffer->getBufferStart()[ELF::EI_DATA]); - std::error_code ec; - - MemoryBufferRef Buf = Buffer->getMemBuffer(); - - if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) { - auto Obj = - llvm::make_unique>>( - Buf, ec); - return llvm::make_unique< - ELFObjectImage>>(std::move(Buffer), - std::move(Obj)); - } - if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) { - auto Obj = - llvm::make_unique>>(Buf, - ec); - return llvm::make_unique>>( - std::move(Buffer), std::move(Obj)); - } - if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) { - auto Obj = llvm::make_unique>>( - Buf, ec); - return llvm::make_unique>>( - std::move(Buffer), std::move(Obj)); - } - assert(Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB && - "Unexpected ELF format"); - auto Obj = - llvm::make_unique>>(Buf, - ec); - return llvm::make_unique>>( - std::move(Buffer), std::move(Obj)); -} - -RuntimeDyldELF::~RuntimeDyldELF() {} - void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend, @@ -615,7 +579,7 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, } // Return the .TOC. section and offset. -void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj, +void RuntimeDyldELF::findPPC64TOCSection(const ObjectFile &Obj, ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel) { // Set a default SectionID in case we do not find a TOC section below. @@ -628,7 +592,7 @@ void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj, // The TOC consists of sections .got, .toc, .tocbss, .plt in that // order. The TOC starts where the first of these sections starts. - for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections(); + for (section_iterator si = Obj.section_begin(), se = Obj.section_end(); si != se; ++si) { StringRef SectionName; @@ -650,15 +614,15 @@ void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj, // Returns the sections and offset associated with the ODP entry referenced // by Symbol. -void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, +void RuntimeDyldELF::findOPDEntrySection(const ObjectFile &Obj, ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel) { // Get the ELF symbol value (st_value) to compare with Relocation offset in // .opd entries - for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections(); + for (section_iterator si = Obj.section_begin(), se = Obj.section_end(); si != se; ++si) { section_iterator RelSecI = si->getRelocatedSection(); - if (RelSecI == Obj.end_sections()) + if (RelSecI == Obj.section_end()) continue; StringRef RelSectionName; @@ -700,7 +664,7 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, if (Rel.Addend != (int64_t)TargetSymbolOffset) continue; - section_iterator tsi(Obj.end_sections()); + section_iterator tsi(Obj.section_end()); check(TargetSymbol->getSection(tsi)); bool IsCode = tsi->isText(); Rel.SectionID = findOrEmitSection(Obj, (*tsi), IsCode, LocalSections); @@ -935,7 +899,8 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, } relocation_iterator RuntimeDyldELF::processRelocationRef( - unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj, + unsigned SectionID, relocation_iterator RelI, + const ObjectFile &Obj, ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, StubMap &Stubs) { uint64_t RelType; @@ -946,7 +911,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( // Obtain the symbol name which is referenced in the relocation StringRef TargetName; - if (Symbol != Obj.end_symbols()) + if (Symbol != Obj.symbol_end()) Symbol->getName(TargetName); DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend << " TargetName: " << TargetName << "\n"); @@ -954,7 +919,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( // First search for the symbol in the local symbol table SymbolTableMap::const_iterator lsi = Symbols.end(); SymbolRef::Type SymType = SymbolRef::ST_Unknown; - if (Symbol != Obj.end_symbols()) { + if (Symbol != Obj.symbol_end()) { lsi = Symbols.find(TargetName.data()); Symbol->getType(SymType); } @@ -965,7 +930,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( } else { // Search for the symbol in the global symbol table SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end(); - if (Symbol != Obj.end_symbols()) + if (Symbol != Obj.symbol_end()) gsi = GlobalSymbolTable.find(TargetName.data()); if (gsi != GlobalSymbolTable.end()) { Value.SectionID = gsi->second.first; @@ -977,9 +942,9 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously // and can be changed by another developers. Maybe best way is add // a new symbol type ST_Section to SymbolRef and use it. - section_iterator si(Obj.end_sections()); + section_iterator si(Obj.section_end()); Symbol->getSection(si); - if (si == Obj.end_sections()) + if (si == Obj.section_end()) llvm_unreachable("Symbol section not found, bad object file format!"); DEBUG(dbgs() << "\t\tThis is section symbol\n"); bool isCode = si->isText(); @@ -1135,7 +1100,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( if (RelType == ELF::R_PPC64_REL24) { // Determine ABI variant in use for this object. unsigned AbiVariant; - Obj.getObjectFile()->getPlatformFlags(AbiVariant); + Obj.getPlatformFlags(AbiVariant); AbiVariant &= ELF::EF_PPC64_ABI; // A PPC branch relocation will need a stub function if the target is // an external symbol (Symbol::ST_Unknown) or if the target address @@ -1495,7 +1460,7 @@ uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, uint64_t Offset) { return 0; } -void RuntimeDyldELF::finalizeLoad(ObjectImage &ObjImg, +void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) { // If necessary, allocate the global offset table if (MemMgr) { @@ -1533,15 +1498,8 @@ void RuntimeDyldELF::finalizeLoad(ObjectImage &ObjImg, } } -bool RuntimeDyldELF::isCompatibleFormat(const ObjectBuffer *Buffer) const { - if (Buffer->getBufferSize() < strlen(ELF::ElfMagic)) - return false; - return (memcmp(Buffer->getBufferStart(), ELF::ElfMagic, - strlen(ELF::ElfMagic))) == 0; -} - -bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile *Obj) const { - return Obj->isELF(); +bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const { + return Obj.isELF(); } } // namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index 4aeab819179..f9c1d4db30b 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -28,9 +28,11 @@ std::error_code Check(std::error_code Err) { } return Err; } + } // end anonymous namespace class RuntimeDyldELF : public RuntimeDyldImpl { + void resolveRelocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend, uint64_t SymOffset = 0); @@ -81,9 +83,11 @@ class RuntimeDyldELF : public RuntimeDyldImpl { return 1; } - void findPPC64TOCSection(ObjectImage &Obj, ObjSectionToIDMap &LocalSections, + void findPPC64TOCSection(const ObjectFile &Obj, + ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel); - void findOPDEntrySection(ObjectImage &Obj, ObjSectionToIDMap &LocalSections, + void findOPDEntrySection(const ObjectFile &Obj, + ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel); uint64_t findGOTEntry(uint64_t LoadAddr, uint64_t Offset); @@ -104,24 +108,23 @@ class RuntimeDyldELF : public RuntimeDyldImpl { SmallVector RegisteredEHFrameSections; public: - RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} + RuntimeDyldELF(RTDyldMemoryManager *mm); + virtual ~RuntimeDyldELF(); + + std::unique_ptr + loadObject(const object::ObjectFile &O) override; void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override; relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID, + const ObjectFile &Obj, + ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, StubMap &Stubs) override; - bool isCompatibleFormat(const ObjectBuffer *Buffer) const override; - bool isCompatibleFile(const object::ObjectFile *Buffer) const override; + bool isCompatibleFile(const object::ObjectFile &Obj) const override; void registerEHFrames() override; void deregisterEHFrames() override; - void finalizeLoad(ObjectImage &ObjImg, + void finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) override; - virtual ~RuntimeDyldELF(); - - static std::unique_ptr - createObjectImage(std::unique_ptr InputBuffer); - static ObjectImage *createObjectImageFromFile(std::unique_ptr Obj); }; } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 69ea3b4f4e6..22d39408a59 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -18,7 +18,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Triple.h" -#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/ExecutionEngine/RuntimeDyldChecker.h" #include "llvm/Object/ObjectFile.h" @@ -37,7 +36,6 @@ using namespace llvm::object; namespace llvm { -class ObjectBuffer; class Twine; /// SectionEntry - represents a section emitted into memory by the dynamic @@ -159,6 +157,7 @@ public: }; class RuntimeDyldImpl { + friend class RuntimeDyld::LoadedObjectInfo; friend class RuntimeDyldCheckerImpl; private: @@ -296,14 +295,15 @@ protected: /// \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, + void emitCommonSymbols(const ObjectFile &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(const ObjectFile &Obj, const SectionRef &Section, bool IsCode); /// \brief Find Section in LocalSections. If the secton is not found - emit @@ -311,7 +311,7 @@ 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, + unsigned findOrEmitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode, ObjSectionToIDMap &LocalSections); // \brief Add a relocation entry that uses the given section. @@ -339,7 +339,7 @@ protected: /// \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 ObjectFile &Obj, ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, StubMap &Stubs) = 0; /// \brief Resolve relocations to external symbols. @@ -351,13 +351,16 @@ protected: // \brief Compute an upper bound of the memory that is required to load all // sections - void computeTotalAllocSize(ObjectImage &Obj, uint64_t &CodeSize, + void computeTotalAllocSize(const ObjectFile &Obj, uint64_t &CodeSize, uint64_t &DataSizeRO, uint64_t &DataSizeRW); // \brief Compute the stub buffer size required for a section - unsigned computeSectionStubBufSize(ObjectImage &Obj, + unsigned computeSectionStubBufSize(const ObjectFile &Obj, const SectionRef &Section); + // \brief Implementation of the generic part of the loadObject algorithm. + std::pair loadObjectImpl(const object::ObjectFile &Obj); + public: RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), Checker(nullptr), ProcessAllSections(false), HasError(false) { @@ -373,8 +376,8 @@ public: this->Checker = Checker; } - std::unique_ptr - loadObject(std::unique_ptr InputObject); + virtual std::unique_ptr + loadObject(const object::ObjectFile &Obj) = 0; uint8_t* getSymbolAddress(StringRef Name) const { // FIXME: Just look up as a function for now. Overly simple of course. @@ -411,14 +414,14 @@ public: // Get the error message. StringRef getErrorString() { return ErrorStr; } - virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0; - virtual bool isCompatibleFile(const ObjectFile *Obj) const = 0; + virtual bool isCompatibleFile(const ObjectFile &Obj) const = 0; virtual void registerEHFrames(); virtual void deregisterEHFrames(); - virtual void finalizeLoad(ObjectImage &ObjImg, ObjSectionToIDMap &SectionMap) {} + virtual void finalizeLoad(const ObjectFile &ObjImg, + ObjSectionToIDMap &SectionMap) {} }; } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index d3d6f5d2546..81020dc7712 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -25,6 +25,22 @@ using namespace llvm::object; #define DEBUG_TYPE "dyld" +namespace { + +class LoadedMachOObjectInfo : public RuntimeDyld::LoadedObjectInfo { +public: + LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {} + + OwningBinary + getObjectForDebug(const ObjectFile &Obj) const override { + return OwningBinary(); + } +}; + +} + namespace llvm { int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const { @@ -35,12 +51,12 @@ int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const { } RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( - ObjectImage &ObjImg, const relocation_iterator &RI, + const ObjectFile &BaseTObj, const relocation_iterator &RI, const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols) { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseTObj); MachO::any_relocation_info RelInfo = Obj.getRelocation(RI->getRawDataRefImpl()); RelocationValueRef Value; @@ -67,7 +83,7 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( } else { SectionRef Sec = Obj.getRelocationSection(RelInfo); bool IsCode = Sec.isText(); - Value.SectionID = findOrEmitSection(ObjImg, Sec, IsCode, ObjSectionToID); + Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); uint64_t Addr = Sec.getAddress(); Value.Offset = RE.Addend - Addr; } @@ -76,11 +92,11 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( } void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value, - ObjectImage &ObjImg, + const ObjectFile &BaseTObj, const relocation_iterator &RI, unsigned OffsetToNextPC) { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseTObj); MachO::any_relocation_info RelInfo = Obj.getRelocation(RI->getRawDataRefImpl()); @@ -125,7 +141,7 @@ RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj, // Populate __pointers section. void RuntimeDyldMachO::populateIndirectSymbolPointersSection( - MachOObjectFile &Obj, + const MachOObjectFile &Obj, const SectionRef &PTSection, unsigned PTSectionID) { assert(!Obj.is64Bit() && @@ -163,28 +179,12 @@ void RuntimeDyldMachO::populateIndirectSymbolPointersSection( } } -bool -RuntimeDyldMachO::isCompatibleFormat(const ObjectBuffer *InputBuffer) const { - if (InputBuffer->getBufferSize() < 4) - return false; - StringRef Magic(InputBuffer->getBufferStart(), 4); - if (Magic == "\xFE\xED\xFA\xCE") - return true; - if (Magic == "\xCE\xFA\xED\xFE") - return true; - if (Magic == "\xFE\xED\xFA\xCF") - return true; - if (Magic == "\xCF\xFA\xED\xFE") - return true; - return false; -} - -bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile *Obj) const { - return Obj->isMachO(); +bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const { + return Obj.isMachO(); } template -void RuntimeDyldMachOCRTPBase::finalizeLoad(ObjectImage &ObjImg, +void RuntimeDyldMachOCRTPBase::finalizeLoad(const ObjectFile &ObjImg, ObjSectionToIDMap &SectionMap) { unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; unsigned TextSID = RTDYLD_INVALID_SECTION_ID; @@ -284,7 +284,7 @@ void RuntimeDyldMachOCRTPBase::registerEHFrames() { } std::unique_ptr -llvm::RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { +RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { switch (Arch) { default: llvm_unreachable("Unsupported target for RuntimeDyldMachO."); @@ -296,4 +296,12 @@ llvm::RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { } } +std::unique_ptr +RuntimeDyldMachO::loadObject(const object::ObjectFile &O) { + unsigned SectionStartIdx, SectionEndIdx; + std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O); + return llvm::make_unique(*this, SectionStartIdx, + SectionEndIdx); +} + } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index 7583474757d..ff102ffea6a 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -14,7 +14,6 @@ #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDMACHO_H #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDMACHO_H -#include "ObjectImageCommon.h" #include "RuntimeDyldImpl.h" #include "llvm/Object/MachO.h" #include "llvm/Support/Format.h" @@ -61,10 +60,11 @@ protected: /// filled in, since immediate encodings are highly target/opcode specific. /// For targets/opcodes with simple, contiguous immediates (e.g. X86) the /// memcpyAddend method can be used to read the immediate. - RelocationEntry getRelocationEntry(unsigned SectionID, ObjectImage &ObjImg, + RelocationEntry getRelocationEntry(unsigned SectionID, + const ObjectFile &BaseTObj, const relocation_iterator &RI) const { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseTObj); MachO::any_relocation_info RelInfo = Obj.getRelocation(RI->getRawDataRefImpl()); @@ -87,14 +87,15 @@ protected: /// In both cases the Addend field is *NOT* fixed up to be PC-relative. That /// should be done by the caller where appropriate by calling makePCRel on /// the RelocationValueRef. - RelocationValueRef getRelocationValueRef(ObjectImage &ObjImg, + RelocationValueRef getRelocationValueRef(const ObjectFile &BaseTObj, const relocation_iterator &RI, const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols); /// Make the RelocationValueRef addend PC-relative. - void makeValueAddendPCRel(RelocationValueRef &Value, ObjectImage &ObjImg, + void makeValueAddendPCRel(RelocationValueRef &Value, + const ObjectFile &BaseTObj, const relocation_iterator &RI, unsigned OffsetToNextPC); @@ -107,31 +108,22 @@ protected: // Populate __pointers section. - void populateIndirectSymbolPointersSection(MachOObjectFile &Obj, + void populateIndirectSymbolPointersSection(const MachOObjectFile &Obj, const SectionRef &PTSection, unsigned PTSectionID); public: - /// Create an ObjectImage from the given ObjectBuffer. - static std::unique_ptr - createObjectImage(std::unique_ptr InputBuffer) { - return llvm::make_unique(std::move(InputBuffer)); - } - - /// Create an ObjectImage from the given ObjectFile. - static ObjectImage * - createObjectImageFromFile(std::unique_ptr InputObject) { - return new ObjectImageCommon(std::move(InputObject)); - } /// Create a RuntimeDyldMachO instance for the given target architecture. static std::unique_ptr create(Triple::ArchType Arch, RTDyldMemoryManager *mm); + std::unique_ptr + loadObject(const object::ObjectFile &O) override; + SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; } - bool isCompatibleFormat(const ObjectBuffer *Buffer) const override; - bool isCompatibleFile(const object::ObjectFile *Obj) const override; + bool isCompatibleFile(const object::ObjectFile &Obj) const override; }; /// RuntimeDyldMachOTarget - Templated base class for generic MachO linker @@ -153,7 +145,7 @@ private: public: RuntimeDyldMachOCRTPBase(RTDyldMemoryManager *mm) : RuntimeDyldMachO(mm) {} - void finalizeLoad(ObjectImage &ObjImg, + void finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) override; void registerEHFrames() override; }; diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h index f5cf9ac29bf..8c1efef722d 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h @@ -243,10 +243,11 @@ public: relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, + const ObjectFile &BaseObjT, + ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, StubMap &Stubs) override { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseObjT); MachO::any_relocation_info RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); @@ -268,10 +269,10 @@ public: RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); } - RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI)); + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); RE.Addend = decodeAddend(RE); RelocationValueRef Value( - getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); + getRelocationValueRef(Obj, RelI, RE, ObjSectionToID, Symbols)); assert((ExplicitAddend == 0 || RE.Addend == 0) && "Relocation has "\ "ARM64_RELOC_ADDEND and embedded addend in the instruction."); @@ -282,7 +283,7 @@ public: bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); if (!IsExtern && RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI, 1 << RE.Size); + makeValueAddendPCRel(Value, Obj, RelI, 1 << RE.Size); RE.Addend = Value.Offset; @@ -359,7 +360,7 @@ public: } } - void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, + void finalizeSection(const ObjectFile &Obj, unsigned SectionID, const SectionRef &Section) {} private: diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h index 9766751c43d..d7e623697bb 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h @@ -49,29 +49,30 @@ public: relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, + const ObjectFile &BaseObjT, + ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, StubMap &Stubs) override { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseObjT); MachO::any_relocation_info RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); uint32_t RelType = Obj.getAnyRelocationType(RelInfo); if (Obj.isRelocationScattered(RelInfo)) { if (RelType == MachO::ARM_RELOC_HALF_SECTDIFF) - return processHALFSECTDIFFRelocation(SectionID, RelI, ObjImg, + return processHALFSECTDIFFRelocation(SectionID, RelI, Obj, ObjSectionToID); else return ++++RelI; } - RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI)); + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); RE.Addend = decodeAddend(RE); RelocationValueRef Value( - getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); + getRelocationValueRef(Obj, RelI, RE, ObjSectionToID, Symbols)); if (RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI, 8); + makeValueAddendPCRel(Value, Obj, RelI, 8); if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24) processBranchRelocation(RE, Value, Stubs); @@ -154,15 +155,14 @@ public: } } - void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, + void finalizeSection(const ObjectFile &Obj, unsigned SectionID, const SectionRef &Section) { StringRef Name; Section.getName(Name); if (Name == "__nl_symbol_ptr") - populateIndirectSymbolPointersSection( - cast(*ObjImg.getObjectFile()), - Section, SectionID); + populateIndirectSymbolPointersSection(cast(Obj), + Section, SectionID); } private: @@ -199,25 +199,25 @@ private: relocation_iterator processHALFSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, - ObjectImage &Obj, + const ObjectFile &BaseTObj, ObjSectionToIDMap &ObjSectionToID) { - const MachOObjectFile *MachO = - static_cast(Obj.getObjectFile()); + const MachOObjectFile &MachO = + static_cast(BaseTObj); MachO::any_relocation_info RE = - MachO->getRelocation(RelI->getRawDataRefImpl()); + MachO.getRelocation(RelI->getRawDataRefImpl()); // For a half-diff relocation the length bits actually record whether this // is a movw/movt, and whether this is arm or thumb. // Bit 0 indicates movw (b0 == 0) or movt (b0 == 1). // Bit 1 indicates arm (b1 == 0) or thumb (b1 == 1). - unsigned HalfDiffKindBits = MachO->getAnyRelocationLength(RE); + unsigned HalfDiffKindBits = MachO.getAnyRelocationLength(RE); if (HalfDiffKindBits & 0x2) llvm_unreachable("Thumb not yet supported."); SectionEntry &Section = Sections[SectionID]; - uint32_t RelocType = MachO->getAnyRelocationType(RE); - bool IsPCRel = MachO->getAnyRelocationPCRel(RE); + uint32_t RelocType = MachO.getAnyRelocationType(RE); + bool IsPCRel = MachO.getAnyRelocationPCRel(RE); uint64_t Offset; RelI->getOffset(Offset); uint8_t *LocalAddress = Section.Address + Offset; @@ -226,27 +226,27 @@ private: ++RelI; MachO::any_relocation_info RE2 = - MachO->getRelocation(RelI->getRawDataRefImpl()); - uint32_t AddrA = MachO->getScatteredRelocationValue(RE); - section_iterator SAI = getSectionByAddress(*MachO, AddrA); - assert(SAI != MachO->section_end() && "Can't find section for address A"); + MachO.getRelocation(RelI->getRawDataRefImpl()); + uint32_t AddrA = MachO.getScatteredRelocationValue(RE); + section_iterator SAI = getSectionByAddress(MachO, AddrA); + assert(SAI != MachO.section_end() && "Can't find section for address A"); uint64_t SectionABase = SAI->getAddress(); uint64_t SectionAOffset = AddrA - SectionABase; SectionRef SectionA = *SAI; bool IsCode = SectionA.isText(); uint32_t SectionAID = - findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID); + findOrEmitSection(MachO, SectionA, IsCode, ObjSectionToID); - uint32_t AddrB = MachO->getScatteredRelocationValue(RE2); - section_iterator SBI = getSectionByAddress(*MachO, AddrB); - assert(SBI != MachO->section_end() && "Can't find section for address B"); + uint32_t AddrB = MachO.getScatteredRelocationValue(RE2); + section_iterator SBI = getSectionByAddress(MachO, AddrB); + assert(SBI != MachO.section_end() && "Can't find section for address B"); uint64_t SectionBBase = SBI->getAddress(); uint64_t SectionBOffset = AddrB - SectionBBase; SectionRef SectionB = *SBI; uint32_t SectionBID = - findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID); + findOrEmitSection(MachO, SectionB, IsCode, ObjSectionToID); - uint32_t OtherHalf = MachO->getAnyRelocationAddress(RE2) & 0xffff; + uint32_t OtherHalf = MachO.getAnyRelocationAddress(RE2) & 0xffff; unsigned Shift = (HalfDiffKindBits & 0x1) ? 16 : 0; uint32_t FullImmVal = (Immediate << Shift) | (OtherHalf << (16 - Shift)); int64_t Addend = FullImmVal - (AddrA - AddrB); diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h index 258b8476d42..78ac911f442 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h @@ -31,10 +31,11 @@ public: relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, + const ObjectFile &BaseObjT, + ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, StubMap &Stubs) override { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseObjT); MachO::any_relocation_info RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); uint32_t RelType = Obj.getAnyRelocationType(RelInfo); @@ -42,18 +43,18 @@ public: if (Obj.isRelocationScattered(RelInfo)) { if (RelType == MachO::GENERIC_RELOC_SECTDIFF || RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) - return processSECTDIFFRelocation(SectionID, RelI, ObjImg, + return processSECTDIFFRelocation(SectionID, RelI, Obj, ObjSectionToID); else if (RelType == MachO::GENERIC_RELOC_VANILLA) - return processI386ScatteredVANILLA(SectionID, RelI, ObjImg, + return processI386ScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID); llvm_unreachable("Unhandled scattered relocation."); } - RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI)); + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); RE.Addend = memcpyAddend(RE); RelocationValueRef Value( - getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); + getRelocationValueRef(Obj, RelI, RE, ObjSectionToID, Symbols)); // Addends for external, PC-rel relocations on i386 point back to the zero // offset. Calculate the final offset from the relocation target instead. @@ -66,7 +67,7 @@ public: // Value.Addend += RelocAddr + 4; // } if (RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI, 1 << RE.Size); + makeValueAddendPCRel(Value, Obj, RelI, 1 << RE.Size); RE.Addend = Value.Offset; @@ -110,34 +111,32 @@ public: } } - void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, + void finalizeSection(const ObjectFile &Obj, unsigned SectionID, const SectionRef &Section) { StringRef Name; Section.getName(Name); if (Name == "__jump_table") - populateJumpTable(cast(*ObjImg.getObjectFile()), Section, - SectionID); + populateJumpTable(cast(Obj), Section, SectionID); else if (Name == "__pointers") - populateIndirectSymbolPointersSection( - cast(*ObjImg.getObjectFile()), - Section, SectionID); + populateIndirectSymbolPointersSection(cast(Obj), + Section, SectionID); } private: relocation_iterator processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, - ObjectImage &Obj, + const ObjectFile &BaseObjT, ObjSectionToIDMap &ObjSectionToID) { - const MachOObjectFile *MachO = - static_cast(Obj.getObjectFile()); + const MachOObjectFile &Obj = + static_cast(BaseObjT); MachO::any_relocation_info RE = - MachO->getRelocation(RelI->getRawDataRefImpl()); + Obj.getRelocation(RelI->getRawDataRefImpl()); SectionEntry &Section = Sections[SectionID]; - uint32_t RelocType = MachO->getAnyRelocationType(RE); - bool IsPCRel = MachO->getAnyRelocationPCRel(RE); - unsigned Size = MachO->getAnyRelocationLength(RE); + uint32_t RelocType = Obj.getAnyRelocationType(RE); + bool IsPCRel = Obj.getAnyRelocationPCRel(RE); + unsigned Size = Obj.getAnyRelocationLength(RE); uint64_t Offset; RelI->getOffset(Offset); uint8_t *LocalAddress = Section.Address + Offset; @@ -146,11 +145,11 @@ private: ++RelI; MachO::any_relocation_info RE2 = - MachO->getRelocation(RelI->getRawDataRefImpl()); + Obj.getRelocation(RelI->getRawDataRefImpl()); - uint32_t AddrA = MachO->getScatteredRelocationValue(RE); - section_iterator SAI = getSectionByAddress(*MachO, AddrA); - assert(SAI != MachO->section_end() && "Can't find section for address A"); + uint32_t AddrA = Obj.getScatteredRelocationValue(RE); + section_iterator SAI = getSectionByAddress(Obj, AddrA); + assert(SAI != Obj.section_end() && "Can't find section for address A"); uint64_t SectionABase = SAI->getAddress(); uint64_t SectionAOffset = AddrA - SectionABase; SectionRef SectionA = *SAI; @@ -158,9 +157,9 @@ private: uint32_t SectionAID = findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID); - uint32_t AddrB = MachO->getScatteredRelocationValue(RE2); - section_iterator SBI = getSectionByAddress(*MachO, AddrB); - assert(SBI != MachO->section_end() && "Can't find section for address B"); + uint32_t AddrB = Obj.getScatteredRelocationValue(RE2); + section_iterator SBI = getSectionByAddress(Obj, AddrB); + assert(SBI != Obj.section_end() && "Can't find section for address B"); uint64_t SectionBBase = SBI->getAddress(); uint64_t SectionBOffset = AddrB - SectionBBase; SectionRef SectionB = *SBI; @@ -186,26 +185,27 @@ private: } relocation_iterator processI386ScatteredVANILLA( - unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj, + unsigned SectionID, relocation_iterator RelI, + const ObjectFile &BaseObjT, RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) { - const MachOObjectFile *MachO = - static_cast(Obj.getObjectFile()); + const MachOObjectFile &Obj = + static_cast(BaseObjT); MachO::any_relocation_info RE = - MachO->getRelocation(RelI->getRawDataRefImpl()); + Obj.getRelocation(RelI->getRawDataRefImpl()); SectionEntry &Section = Sections[SectionID]; - uint32_t RelocType = MachO->getAnyRelocationType(RE); - bool IsPCRel = MachO->getAnyRelocationPCRel(RE); - unsigned Size = MachO->getAnyRelocationLength(RE); + uint32_t RelocType = Obj.getAnyRelocationType(RE); + bool IsPCRel = Obj.getAnyRelocationPCRel(RE); + unsigned Size = Obj.getAnyRelocationLength(RE); uint64_t Offset; RelI->getOffset(Offset); uint8_t *LocalAddress = Section.Address + Offset; unsigned NumBytes = 1 << Size; int64_t Addend = readBytesUnaligned(LocalAddress, NumBytes); - unsigned SymbolBaseAddr = MachO->getScatteredRelocationValue(RE); - section_iterator TargetSI = getSectionByAddress(*MachO, SymbolBaseAddr); - assert(TargetSI != MachO->section_end() && "Can't find section for symbol"); + unsigned SymbolBaseAddr = Obj.getScatteredRelocationValue(RE); + section_iterator TargetSI = getSectionByAddress(Obj, SymbolBaseAddr); + assert(TargetSI != Obj.section_end() && "Can't find section for symbol"); uint64_t SectionBaseAddr = TargetSI->getAddress(); SectionRef TargetSection = *TargetSI; bool IsCode = TargetSection.isText(); @@ -221,7 +221,7 @@ private: } // Populate stubs in __jump_table section. - void populateJumpTable(MachOObjectFile &Obj, const SectionRef &JTSection, + void populateJumpTable(const MachOObjectFile &Obj, const SectionRef &JTSection, unsigned JTSectionID) { assert(!Obj.is64Bit() && "__jump_table section not supported in 64-bit MachO."); diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h index 84d9e809a17..a38867e7b6a 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h @@ -31,24 +31,25 @@ public: relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, + const ObjectFile &BaseObjT, + ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, StubMap &Stubs) override { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseObjT); MachO::any_relocation_info RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); assert(!Obj.isRelocationScattered(RelInfo) && "Scattered relocations not supported on X86_64"); - RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI)); + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); RE.Addend = memcpyAddend(RE); RelocationValueRef Value( - getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); + getRelocationValueRef(Obj, RelI, RE, ObjSectionToID, Symbols)); bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); if (!IsExtern && RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI, 1 << RE.Size); + makeValueAddendPCRel(Value, Obj, RelI, 1 << RE.Size); if (RE.RelType == MachO::X86_64_RELOC_GOT || RE.RelType == MachO::X86_64_RELOC_GOT_LOAD) @@ -97,7 +98,7 @@ public: } } - void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, + void finalizeSection(const ObjectFile &Obj, unsigned SectionID, const SectionRef &Section) {} private: diff --git a/tools/lli/RemoteMemoryManager.cpp b/tools/lli/RemoteMemoryManager.cpp index 5a135eabd73..47da8fb60c9 100644 --- a/tools/lli/RemoteMemoryManager.cpp +++ b/tools/lli/RemoteMemoryManager.cpp @@ -14,7 +14,6 @@ #include "RemoteMemoryManager.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" @@ -78,7 +77,7 @@ sys::MemoryBlock RemoteMemoryManager::allocateSection(uintptr_t Size) { } void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE, - const ObjectImage *Obj) { + const object::ObjectFile &Obj) { // The client should have called setRemoteTarget() before triggering any // code generation. assert(Target); diff --git a/tools/lli/RemoteMemoryManager.h b/tools/lli/RemoteMemoryManager.h index 0bdb4e2ad12..895bcdac4d1 100644 --- a/tools/lli/RemoteMemoryManager.h +++ b/tools/lli/RemoteMemoryManager.h @@ -80,7 +80,8 @@ public: // symbols from Modules it contains. uint64_t getSymbolAddress(const std::string &Name) override { return 0; } - void notifyObjectLoaded(ExecutionEngine *EE, const ObjectImage *Obj) override; + void notifyObjectLoaded(ExecutionEngine *EE, + const object::ObjectFile &Obj) override; bool finalizeMemory(std::string *ErrMsg) override; diff --git a/tools/llvm-jitlistener/llvm-jitlistener.cpp b/tools/llvm-jitlistener/llvm-jitlistener.cpp index 0bb6e8bc886..0f85a85e19c 100644 --- a/tools/llvm-jitlistener/llvm-jitlistener.cpp +++ b/tools/llvm-jitlistener/llvm-jitlistener.cpp @@ -19,10 +19,10 @@ #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/ExecutionEngine/MCJIT.h" -#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/IR/Module.h" #include "llvm/IRReader/IRReader.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/Host.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index 87d381e994f..c38e42307dd 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -13,8 +13,6 @@ #include "llvm/ADT/StringMap.h" #include "llvm/DebugInfo/DIContext.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/ExecutionEngine/RuntimeDyldChecker.h" #include "llvm/MC/MCAsmInfo.h" @@ -207,23 +205,32 @@ static int printLineInfoForInput() { if (std::error_code EC = InputBuffer.getError()) return Error("unable to read input: '" + EC.message() + "'"); - std::unique_ptr LoadedObject; + ErrorOr> MaybeObj( + ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef())); + + if (std::error_code EC = MaybeObj.getError()) + return Error("unable to create object file: '" + EC.message() + "'"); + + ObjectFile &Obj = **MaybeObj; + // Load the object file - LoadedObject = Dyld.loadObject( - llvm::make_unique(std::move(*InputBuffer))); - if (!LoadedObject) { + std::unique_ptr LoadedObjInfo = + Dyld.loadObject(Obj); + + if (Dyld.hasError()) return Error(Dyld.getErrorString()); - } // Resolve all the relocations we can. Dyld.resolveRelocations(); + OwningBinary DebugObj = LoadedObjInfo->getObjectForDebug(Obj); + std::unique_ptr Context( - DIContext::getDWARFContext(*LoadedObject->getObjectFile())); + DIContext::getDWARFContext(*DebugObj.getBinary())); // Use symbol info to iterate functions in the object. - for (object::symbol_iterator I = LoadedObject->begin_symbols(), - E = LoadedObject->end_symbols(); + for (object::symbol_iterator I = DebugObj.getBinary()->symbol_begin(), + E = DebugObj.getBinary()->symbol_end(); I != E; ++I) { object::SymbolRef::Type SymType; if (I->getType(SymType)) continue; @@ -268,11 +275,17 @@ static int executeInput() { MemoryBuffer::getFileOrSTDIN(InputFileList[i]); if (std::error_code EC = InputBuffer.getError()) return Error("unable to read input: '" + EC.message() + "'"); - std::unique_ptr LoadedObject; + ErrorOr> MaybeObj( + ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef())); + + if (std::error_code EC = MaybeObj.getError()) + return Error("unable to create object file: '" + EC.message() + "'"); + + ObjectFile &Obj = **MaybeObj; + // Load the object file - LoadedObject = Dyld.loadObject( - llvm::make_unique(std::move(*InputBuffer))); - if (!LoadedObject) { + Dyld.loadObject(Obj); + if (Dyld.hasError()) { return Error(Dyld.getErrorString()); } } @@ -512,14 +525,21 @@ static int linkAndVerify() { // Load the input memory buffer. ErrorOr> InputBuffer = MemoryBuffer::getFileOrSTDIN(InputFileList[i]); + if (std::error_code EC = InputBuffer.getError()) return Error("unable to read input: '" + EC.message() + "'"); - std::unique_ptr LoadedObject; + ErrorOr> MaybeObj( + ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef())); + + if (std::error_code EC = MaybeObj.getError()) + return Error("unable to create object file: '" + EC.message() + "'"); + + ObjectFile &Obj = **MaybeObj; + // Load the object file - LoadedObject = Dyld.loadObject( - llvm::make_unique(std::move(*InputBuffer))); - if (!LoadedObject) { + Dyld.loadObject(Obj); + if (Dyld.hasError()) { return Error(Dyld.getErrorString()); } }