Index: include/llvm/ExecutionEngine/JITEventListener.h =================================================================== --- include/llvm/ExecutionEngine/JITEventListener.h +++ include/llvm/ExecutionEngine/JITEventListener.h @@ -42,23 +42,26 @@ /// The default implementation of each method does nothing. class JITEventListener { public: + using ObjectKey = uint64_t; + JITEventListener() = default; virtual ~JITEventListener() = default; - /// NotifyObjectEmitted - Called after an object has been successfully - /// emitted to memory. NotifyFunctionEmitted will not be called for + /// notifyObjectLoaded - Called after an object has had its sections allocated + /// and addresses assigned to all symbols. Note: Section memory will not have + /// been relocated yet. notifyFunctionLoaded will not be called for /// individual functions in the object. /// /// ELF-specific information /// 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 object::ObjectFile &Obj, - const RuntimeDyld::LoadedObjectInfo &L) {} + virtual void notifyObjectLoaded(ObjectKey K, const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) {} - /// NotifyFreeingObject - Called just before the memory associated with + /// notifyFreeingObject - Called just before the memory associated with /// a previously emitted object is released. - virtual void NotifyFreeingObject(const object::ObjectFile &Obj) {} + virtual void notifyFreeingObject(ObjectKey K) {} // Get a pointe to the GDB debugger registration listener. static JITEventListener *createGDBRegistrationListener(); Index: lib/ExecutionEngine/GDBRegistrationListener.cpp =================================================================== --- lib/ExecutionEngine/GDBRegistrationListener.cpp +++ lib/ExecutionEngine/GDBRegistrationListener.cpp @@ -76,8 +76,8 @@ }; // Buffer for an in-memory object file in executable memory -typedef llvm::DenseMap< const char*, RegisteredObjectInfo> - RegisteredObjectBufferMap; +typedef llvm::DenseMap + RegisteredObjectBufferMap; /// Global access point for the JIT debugging interface designed for use with a /// singleton toolbox. Handles thread-safe registration and deregistration of @@ -99,13 +99,13 @@ /// 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; + void notifyObjectLoaded(ObjectKey K, const ObjectFile &Obj, + 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; + void notifyFreeingObject(ObjectKey K) override; private: /// Deregister the debug info for the given object file from the debugger @@ -147,11 +147,11 @@ ObjectBufferMap.clear(); } -void GDBJITRegistrationListener::NotifyObjectEmitted( - const ObjectFile &Object, - const RuntimeDyld::LoadedObjectInfo &L) { +void GDBJITRegistrationListener::notifyObjectLoaded( + ObjectKey K, const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) { - OwningBinary DebugObj = L.getObjectForDebug(Object); + OwningBinary DebugObj = L.getObjectForDebug(Obj); // Bail out if debug objects aren't supported. if (!DebugObj.getBinary()) @@ -160,11 +160,8 @@ 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() && + assert(ObjectBufferMap.find(K) == ObjectBufferMap.end() && "Second attempt to perform debug registration."); jit_code_entry* JITCodeEntry = new jit_code_entry(); @@ -175,16 +172,15 @@ JITCodeEntry->symfile_addr = Buffer; JITCodeEntry->symfile_size = Size; - ObjectBufferMap[Key] = RegisteredObjectInfo(Size, JITCodeEntry, - std::move(DebugObj)); + ObjectBufferMap[K] = + RegisteredObjectInfo(Size, JITCodeEntry, std::move(DebugObj)); NotifyDebugger(JITCodeEntry); } } -void GDBJITRegistrationListener::NotifyFreeingObject(const ObjectFile& Object) { - const char *Key = Object.getMemoryBufferRef().getBufferStart(); +void GDBJITRegistrationListener::notifyFreeingObject(ObjectKey K) { llvm::MutexGuard locked(*JITDebugLock); - RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Key); + RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(K); if (I != ObjectBufferMap.end()) { deregisterObjectInternal(I); Index: lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp =================================================================== --- lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp +++ lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp @@ -47,7 +47,7 @@ typedef DenseMap ObjectMap; ObjectMap LoadedObjectMap; - std::map> DebugObjects; + std::map> DebugObjects; public: IntelJITEventListener(IntelJITEventsWrapper* libraryWrapper) { @@ -57,10 +57,10 @@ ~IntelJITEventListener() { } - void NotifyObjectEmitted(const ObjectFile &Obj, - const RuntimeDyld::LoadedObjectInfo &L) override; + void notifyObjectLoaded(ObjectKey Key, const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) override; - void NotifyFreeingObject(const ObjectFile &Obj) override; + void notifyFreeingObject(ObjectKey Key) override; }; static LineNumberInfo DILineInfoToIntelJITFormat(uintptr_t StartAddress, @@ -96,9 +96,9 @@ return Result; } -void IntelJITEventListener::NotifyObjectEmitted( - const ObjectFile &Obj, - const RuntimeDyld::LoadedObjectInfo &L) { +void IntelJITEventListener::notifyObjectLoaded( + ObjectKey Key, const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) { OwningBinary DebugObjOwner = L.getObjectForDebug(Obj); const ObjectFile *DebugObj = DebugObjOwner.getBinary(); @@ -188,17 +188,17 @@ // 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); + DebugObjects[Key] = std::move(DebugObjOwner); } -void IntelJITEventListener::NotifyFreeingObject(const ObjectFile &Obj) { +void IntelJITEventListener::notifyFreeingObject(ObjectKey Key) { // This object may not have been registered with the listener. If it wasn't, // bail out. - if (DebugObjects.find(Obj.getData().data()) == DebugObjects.end()) + if (DebugObjects.find(Key) == DebugObjects.end()) return; // Get the address of the object image for use as a unique identifier - const ObjectFile &DebugObj = *DebugObjects[Obj.getData().data()].getBinary(); + const ObjectFile &DebugObj = *DebugObjects[Key].getBinary(); const void* ObjData = DebugObj.getData().data(); // Get the object's function list from LoadedObjectMap @@ -223,7 +223,7 @@ // Erase the object from LoadedObjectMap LoadedObjectMap.erase(OI); - DebugObjects.erase(Obj.getData().data()); + DebugObjects.erase(Key); } } // anonymous namespace. Index: lib/ExecutionEngine/MCJIT/MCJIT.h =================================================================== --- lib/ExecutionEngine/MCJIT/MCJIT.h +++ lib/ExecutionEngine/MCJIT/MCJIT.h @@ -331,9 +331,9 @@ /// the future. std::unique_ptr emitObject(Module *M); - void NotifyObjectEmitted(const object::ObjectFile& Obj, - const RuntimeDyld::LoadedObjectInfo &L); - void NotifyFreeingObject(const object::ObjectFile& Obj); + void notifyObjectLoaded(const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L); + void notifyFreeingObject(const object::ObjectFile &Obj); JITSymbol findExistingSymbol(const std::string &Name); Module *findModuleForSymbol(const std::string &Name, bool CheckFunctionsOnly); Index: lib/ExecutionEngine/MCJIT/MCJIT.cpp =================================================================== --- lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -95,7 +95,7 @@ for (auto &Obj : LoadedObjects) if (Obj) - NotifyFreeingObject(*Obj); + notifyFreeingObject(*Obj); Archives.clear(); } @@ -119,7 +119,7 @@ if (Dyld.hasError()) report_fatal_error(Dyld.getErrorString()); - NotifyObjectEmitted(*Obj, *L); + notifyObjectLoaded(*Obj, *L); LoadedObjects.push_back(std::move(Obj)); } @@ -226,7 +226,7 @@ if (Dyld.hasError()) report_fatal_error(Dyld.getErrorString()); - NotifyObjectEmitted(*LoadedObject.get(), *L); + notifyObjectLoaded(*LoadedObject.get(), *L); Buffers.push_back(std::move(ObjectToLoad)); LoadedObjects.push_back(std::move(*LoadedObject)); @@ -648,19 +648,23 @@ } } -void MCJIT::NotifyObjectEmitted(const object::ObjectFile& Obj, - const RuntimeDyld::LoadedObjectInfo &L) { +void MCJIT::notifyObjectLoaded(const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) { + uint64_t Key = + static_cast(reinterpret_cast(Obj.getData().data())); MutexGuard locked(lock); MemMgr->notifyObjectLoaded(this, Obj); for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { - EventListeners[I]->NotifyObjectEmitted(Obj, L); + EventListeners[I]->notifyObjectLoaded(Key, Obj, L); } } -void MCJIT::NotifyFreeingObject(const object::ObjectFile& Obj) { +void MCJIT::notifyFreeingObject(const object::ObjectFile &Obj) { + uint64_t Key = + static_cast(reinterpret_cast(Obj.getData().data())); MutexGuard locked(lock); for (JITEventListener *L : EventListeners) - L->NotifyFreeingObject(Obj); + L->notifyFreeingObject(Key); } JITSymbol Index: lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp =================================================================== --- lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp +++ lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp @@ -40,7 +40,7 @@ std::unique_ptr Wrapper; void initialize(); - std::map> DebugObjects; + std::map> DebugObjects; public: OProfileJITEventListener(std::unique_ptr LibraryWrapper) @@ -50,10 +50,10 @@ ~OProfileJITEventListener(); - void NotifyObjectEmitted(const ObjectFile &Obj, - const RuntimeDyld::LoadedObjectInfo &L) override; + void notifyObjectLoaded(ObjectKey Key, const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) override; - void NotifyFreeingObject(const ObjectFile &Obj) override; + void notifyFreeingObject(ObjectKey Key) override; }; void OProfileJITEventListener::initialize() { @@ -78,9 +78,9 @@ } } -void OProfileJITEventListener::NotifyObjectEmitted( - const ObjectFile &Obj, - const RuntimeDyld::LoadedObjectInfo &L) { +void OProfileJITEventListener::notifyObjectLoaded( + ObjectKey Key, const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) { if (!Wrapper->isAgentAvailable()) { return; } @@ -137,18 +137,18 @@ } } - DebugObjects[Obj.getData().data()] = std::move(DebugObjOwner); + DebugObjects[Key] = std::move(DebugObjOwner); } -void OProfileJITEventListener::NotifyFreeingObject(const ObjectFile &Obj) { +void OProfileJITEventListener::notifyFreeingObject(ObjectKey Key) { 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()) + if (DebugObjects.find(Key) == DebugObjects.end()) return; - const ObjectFile &DebugObj = *DebugObjects[Obj.getData().data()].getBinary(); + const ObjectFile &DebugObj = *DebugObjects[Key].getBinary(); // Use symbol info to iterate functions in the object. for (symbol_iterator I = DebugObj.symbol_begin(), @@ -171,7 +171,7 @@ } } - DebugObjects.erase(Obj.getData().data()); + DebugObjects.erase(Key); } } // anonymous namespace. Index: lib/ExecutionEngine/Orc/OrcCBindingsStack.h =================================================================== --- lib/ExecutionEngine/Orc/OrcCBindingsStack.h +++ lib/ExecutionEngine/Orc/OrcCBindingsStack.h @@ -492,13 +492,17 @@ void notifyFinalized(orc::VModuleKey K, const object::ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) { + uint64_t Key = static_cast( + reinterpret_cast(Obj.getData().data())); for (auto &Listener : EventListeners) - Listener->NotifyObjectEmitted(Obj, LoadedObjInfo); + Listener->notifyObjectLoaded(Key, Obj, LoadedObjInfo); } void notifyFreed(orc::VModuleKey K, const object::ObjectFile &Obj) { + uint64_t Key = static_cast( + reinterpret_cast(Obj.getData().data())); for (auto &Listener : EventListeners) - Listener->NotifyFreeingObject(Obj); + Listener->notifyFreeingObject(Key); } orc::ExecutionSession ES; Index: lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp =================================================================== --- lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp +++ lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp @@ -66,9 +66,9 @@ CloseMarker(); } - void NotifyObjectEmitted(const ObjectFile &Obj, - const RuntimeDyld::LoadedObjectInfo &L) override; - void NotifyFreeingObject(const ObjectFile &Obj) override; + void notifyObjectLoaded(ObjectKey K, const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) override; + void notifyFreeingObject(ObjectKey K) override; private: bool InitDebuggingDir(); @@ -227,8 +227,9 @@ SuccessfullyInitialized = true; } -void PerfJITEventListener::NotifyObjectEmitted( - const ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &L) { +void PerfJITEventListener::notifyObjectLoaded( + ObjectKey K, const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) { if (!SuccessfullyInitialized) return; @@ -280,7 +281,7 @@ Dumpstream->flush(); } -void PerfJITEventListener::NotifyFreeingObject(const ObjectFile &Obj) { +void PerfJITEventListener::notifyFreeingObject(ObjectKey K) { // perf currently doesn't have an interface for unloading. But munmap()ing the // code section does, so that's ok. }