From c39d3fc4c28a3222a6f0ac6fd4fb2031e3311527 Mon Sep 17 00:00:00 2001 From: Xusheng Date: Fri, 24 Jul 2026 13:14:22 -0400 Subject: [PATCH] Query IDebugDataSpaces2/4 in the TTD adapter (Fix #1141) DbgEngTTDAdapter::Start() creates its own IDebugClient7 and queries the interfaces it needs, but the base class only ever queries IDebugDataSpaces2 in ConnectToDebugServerInternal(), which the TTD adapter never goes through (it opens the trace with OpenDumpFile()). So m_debugDataSpaces2 stayed null for the whole TTD session and anything built on it silently did nothing -- GetMemoryMap() in particular returns early on a null check, so it never even called into dbgeng. Also query IDebugDataSpaces4 on both the live-debug and TTD paths. Unlike QueryVirtual, which is unimplemented for TTD replay targets, its GetValidRegionVirtual / GetNextDifferentlyValidOffsetVirtual / GetOffsetInformation do work on a trace and are useful for validating an address range. This does not fix the empty memory map widget (#1132): QueryVirtual fails on TTD targets regardless of whether the interface pointer is valid. Co-Authored-By: Claude Opus 4.8 --- core/adapters/dbgengadapter.cpp | 2 ++ core/adapters/dbgengadapter.h | 1 + core/adapters/dbgengttdadapter.cpp | 7 +++++++ 3 files changed, 10 insertions(+) diff --git a/core/adapters/dbgengadapter.cpp b/core/adapters/dbgengadapter.cpp index d5fd7dda..7cb0676f 100644 --- a/core/adapters/dbgengadapter.cpp +++ b/core/adapters/dbgengadapter.cpp @@ -331,6 +331,7 @@ bool DbgEngAdapter::ConnectToDebugServerInternal(const std::string& connectionSt QUERY_DEBUG_INTERFACE(IDebugControl7, &this->m_debugControl); QUERY_DEBUG_INTERFACE(IDebugDataSpaces, &this->m_debugDataSpaces); QUERY_DEBUG_INTERFACE(IDebugDataSpaces2, &this->m_debugDataSpaces2); + QUERY_DEBUG_INTERFACE(IDebugDataSpaces4, &this->m_debugDataSpaces4); QUERY_DEBUG_INTERFACE(IDebugRegisters, &this->m_debugRegisters); QUERY_DEBUG_INTERFACE(IDebugSymbols3, &this->m_debugSymbols); QUERY_DEBUG_INTERFACE(IDebugSystemObjects, &this->m_debugSystemObjects); @@ -424,6 +425,7 @@ void DbgEngAdapter::Reset() SAFE_RELEASE(this->m_debugControl); SAFE_RELEASE(this->m_debugDataSpaces); SAFE_RELEASE(this->m_debugDataSpaces2); + SAFE_RELEASE(this->m_debugDataSpaces4); SAFE_RELEASE(this->m_debugRegisters); SAFE_RELEASE(this->m_debugSymbols); SAFE_RELEASE(this->m_debugSystemObjects); diff --git a/core/adapters/dbgengadapter.h b/core/adapters/dbgengadapter.h index 7f007033..7dfc01d1 100644 --- a/core/adapters/dbgengadapter.h +++ b/core/adapters/dbgengadapter.h @@ -129,6 +129,7 @@ namespace BinaryNinjaDebugger { IDebugControl7* m_debugControl {nullptr}; IDebugDataSpaces* m_debugDataSpaces {nullptr}; IDebugDataSpaces2* m_debugDataSpaces2 {nullptr}; + IDebugDataSpaces4* m_debugDataSpaces4 {nullptr}; IDebugRegisters* m_debugRegisters {nullptr}; IDebugSymbols3* m_debugSymbols {nullptr}; IDebugSystemObjects* m_debugSystemObjects {nullptr}; diff --git a/core/adapters/dbgengttdadapter.cpp b/core/adapters/dbgengttdadapter.cpp index f68e1690..aee47d53 100644 --- a/core/adapters/dbgengttdadapter.cpp +++ b/core/adapters/dbgengttdadapter.cpp @@ -133,6 +133,11 @@ bool DbgEngTTDAdapter::Start() QUERY_DEBUG_INTERFACE(IDebugControl7, &this->m_debugControl); QUERY_DEBUG_INTERFACE(IDebugDataSpaces, &this->m_debugDataSpaces); + // The TTD adapter opens a trace directly instead of going through + // DbgEngAdapter::ConnectToDebugServerInternal(), so these have to be queried here too, otherwise + // they stay null and everything built on them (e.g. GetMemoryMap()) silently does nothing. + QUERY_DEBUG_INTERFACE(IDebugDataSpaces2, &this->m_debugDataSpaces2); + QUERY_DEBUG_INTERFACE(IDebugDataSpaces4, &this->m_debugDataSpaces4); QUERY_DEBUG_INTERFACE(IDebugRegisters, &this->m_debugRegisters); QUERY_DEBUG_INTERFACE(IDebugSymbols3, &this->m_debugSymbols); QUERY_DEBUG_INTERFACE(IDebugSystemObjects, &this->m_debugSystemObjects); @@ -185,6 +190,8 @@ void DbgEngTTDAdapter::Reset() // we should keep everything active. SAFE_RELEASE(this->m_debugControl); SAFE_RELEASE(this->m_debugDataSpaces); + SAFE_RELEASE(this->m_debugDataSpaces2); + SAFE_RELEASE(this->m_debugDataSpaces4); SAFE_RELEASE(this->m_debugRegisters); SAFE_RELEASE(this->m_debugSymbols); SAFE_RELEASE(this->m_dataModelManager);