Skip to content

Commit f2822bf

Browse files
Copilotxusheng6
andcommitted
Implement requested changes: use curprocess instead of cursession, cache all events, add checkbox filtering UI
Co-authored-by: xusheng6 <[email protected]>
1 parent 392a207 commit f2822bf

13 files changed

+533
-239
lines changed

api/debuggerapi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,7 @@ namespace BinaryNinjaDebuggerAPI {
759759
std::vector<TTDMemoryEvent> GetTTDMemoryAccessForAddress(uint64_t address, uint64_t size, TTDMemoryAccessType accessType = TTDMemoryRead);
760760
std::vector<TTDCallEvent> GetTTDCallsForSymbols(const std::string& symbols, uint64_t startReturnAddress = 0, uint64_t endReturnAddress = 0);
761761
std::vector<TTDEvent> GetTTDEvents(TTDEventType eventType);
762+
std::vector<TTDEvent> GetAllTTDEvents();
762763
TTDPosition GetCurrentTTDPosition();
763764
bool SetTTDPosition(const TTDPosition& position);
764765

api/debuggercontroller.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,75 @@ std::vector<TTDEvent> DebuggerController::GetTTDEvents(TTDEventType eventType)
11331133
}
11341134

11351135

1136+
std::vector<TTDEvent> DebuggerController::GetAllTTDEvents()
1137+
{
1138+
std::vector<TTDEvent> result;
1139+
1140+
size_t count = 0;
1141+
BNDebuggerTTDEvent* events = BNDebuggerGetAllTTDEvents(m_object, &count);
1142+
1143+
if (events && count > 0)
1144+
{
1145+
result.reserve(count);
1146+
for (size_t i = 0; i < count; i++)
1147+
{
1148+
TTDEvent event;
1149+
event.type = static_cast<TTDEventType>(events[i].type);
1150+
event.position.sequence = events[i].position.sequence;
1151+
event.position.step = events[i].position.step;
1152+
1153+
// Copy optional module details
1154+
if (events[i].module)
1155+
{
1156+
TTDModule module;
1157+
module.name = events[i].module->name ? std::string(events[i].module->name) : "";
1158+
module.address = events[i].module->address;
1159+
module.size = events[i].module->size;
1160+
module.checksum = events[i].module->checksum;
1161+
module.timestamp = events[i].module->timestamp;
1162+
event.module = module;
1163+
}
1164+
1165+
// Copy optional thread details
1166+
if (events[i].thread)
1167+
{
1168+
TTDThread thread;
1169+
thread.uniqueId = events[i].thread->uniqueId;
1170+
thread.id = events[i].thread->id;
1171+
thread.lifetimeStart.sequence = events[i].thread->lifetimeStart.sequence;
1172+
thread.lifetimeStart.step = events[i].thread->lifetimeStart.step;
1173+
thread.lifetimeEnd.sequence = events[i].thread->lifetimeEnd.sequence;
1174+
thread.lifetimeEnd.step = events[i].thread->lifetimeEnd.step;
1175+
thread.activeTimeStart.sequence = events[i].thread->activeTimeStart.sequence;
1176+
thread.activeTimeStart.step = events[i].thread->activeTimeStart.step;
1177+
thread.activeTimeEnd.sequence = events[i].thread->activeTimeEnd.sequence;
1178+
thread.activeTimeEnd.step = events[i].thread->activeTimeEnd.step;
1179+
event.thread = thread;
1180+
}
1181+
1182+
// Copy optional exception details
1183+
if (events[i].exception)
1184+
{
1185+
TTDException exception;
1186+
exception.type = static_cast<TTDExceptionType>(events[i].exception->type);
1187+
exception.programCounter = events[i].exception->programCounter;
1188+
exception.code = events[i].exception->code;
1189+
exception.flags = events[i].exception->flags;
1190+
exception.recordAddress = events[i].exception->recordAddress;
1191+
exception.position.sequence = events[i].exception->position.sequence;
1192+
exception.position.step = events[i].exception->position.step;
1193+
event.exception = exception;
1194+
}
1195+
1196+
result.push_back(event);
1197+
}
1198+
BNDebuggerFreeTTDEvents(events, count);
1199+
}
1200+
1201+
return result;
1202+
}
1203+
1204+
11361205
bool DebuggerController::IsInstructionExecuted(uint64_t address)
11371206
{
11381207
return BNDebuggerIsInstructionExecuted(m_object, address);

api/ffi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,7 @@ extern "C"
618618
const char* symbols, uint64_t startReturnAddress, uint64_t endReturnAddress, size_t* count);
619619
DEBUGGER_FFI_API BNDebuggerTTDEvent* BNDebuggerGetTTDEvents(BNDebuggerController* controller,
620620
BNDebuggerTTDEventType eventType, size_t* count);
621+
DEBUGGER_FFI_API BNDebuggerTTDEvent* BNDebuggerGetAllTTDEvents(BNDebuggerController* controller, size_t* count);
621622
DEBUGGER_FFI_API BNDebuggerTTDPosition BNDebuggerGetCurrentTTDPosition(BNDebuggerController* controller);
622623
DEBUGGER_FFI_API bool BNDebuggerSetTTDPosition(BNDebuggerController* controller, BNDebuggerTTDPosition position);
623624
DEBUGGER_FFI_API void BNDebuggerFreeTTDMemoryEvents(BNDebuggerTTDMemoryEvent* events, size_t count);

api/python/debuggercontroller.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2344,6 +2344,85 @@ def get_ttd_events(self, event_type: int) -> List[TTDEvent]:
23442344
dbgcore.BNDebuggerFreeTTDEvents(events, count.value)
23452345
return result
23462346

2347+
def get_all_ttd_events(self) -> List[TTDEvent]:
2348+
"""
2349+
Get all TTD events from the trace.
2350+
2351+
This method is only available when debugging with TTD (Time Travel Debugging).
2352+
Use the is_ttd property to check if TTD is available before calling this method.
2353+
2354+
:return: list of all TTDEvent objects in the trace
2355+
:rtype: List[TTDEvent]
2356+
"""
2357+
if self.handle is None:
2358+
return []
2359+
2360+
count = ctypes.c_size_t()
2361+
events = dbgcore.BNDebuggerGetAllTTDEvents(self.handle, ctypes.byref(count))
2362+
2363+
result = []
2364+
if not events or count.value == 0:
2365+
return result
2366+
2367+
for i in range(count.value):
2368+
event = events[i]
2369+
2370+
position = TTDPosition(event.position.sequence, event.position.step)
2371+
2372+
# Convert optional module details
2373+
module = None
2374+
if event.module:
2375+
module = TTDModule(
2376+
name=event.module.contents.name if event.module.contents.name else "",
2377+
address=event.module.contents.address,
2378+
size=event.module.contents.size,
2379+
checksum=event.module.contents.checksum,
2380+
timestamp=event.module.contents.timestamp
2381+
)
2382+
2383+
# Convert optional thread details
2384+
thread = None
2385+
if event.thread:
2386+
lifetime_start = TTDPosition(event.thread.contents.lifetimeStart.sequence, event.thread.contents.lifetimeStart.step)
2387+
lifetime_end = TTDPosition(event.thread.contents.lifetimeEnd.sequence, event.thread.contents.lifetimeEnd.step)
2388+
active_time_start = TTDPosition(event.thread.contents.activeTimeStart.sequence, event.thread.contents.activeTimeStart.step)
2389+
active_time_end = TTDPosition(event.thread.contents.activeTimeEnd.sequence, event.thread.contents.activeTimeEnd.step)
2390+
2391+
thread = TTDThread(
2392+
unique_id=event.thread.contents.uniqueId,
2393+
id=event.thread.contents.id,
2394+
lifetime_start=lifetime_start,
2395+
lifetime_end=lifetime_end,
2396+
active_time_start=active_time_start,
2397+
active_time_end=active_time_end
2398+
)
2399+
2400+
# Convert optional exception details
2401+
exception = None
2402+
if event.exception:
2403+
exception_position = TTDPosition(event.exception.contents.position.sequence, event.exception.contents.position.step)
2404+
2405+
exception = TTDException(
2406+
type=event.exception.contents.type,
2407+
program_counter=event.exception.contents.programCounter,
2408+
code=event.exception.contents.code,
2409+
flags=event.exception.contents.flags,
2410+
record_address=event.exception.contents.recordAddress,
2411+
position=exception_position
2412+
)
2413+
2414+
ttd_event = TTDEvent(
2415+
type=event.type,
2416+
position=position,
2417+
module=module,
2418+
thread=thread,
2419+
exception=exception
2420+
)
2421+
result.append(ttd_event)
2422+
2423+
dbgcore.BNDebuggerFreeTTDEvents(events, count.value)
2424+
return result
2425+
23472426
def __del__(self):
23482427
if dbgcore is not None:
23492428
dbgcore.BNDebuggerFreeController(self.handle)

core/adapters/dbgengttdadapter.cpp

Lines changed: 84 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ using namespace std;
1111
DbgEngTTDAdapter::DbgEngTTDAdapter(BinaryView* data) : DbgEngAdapter(data)
1212
{
1313
m_usePDBFileName = false;
14+
m_eventsCached = false;
1415
GenerateDefaultAdapterSettings(data);
1516
}
1617

@@ -173,6 +174,9 @@ bool DbgEngTTDAdapter::Start()
173174
void DbgEngTTDAdapter::Reset()
174175
{
175176
m_aboutToBeKilled = false;
177+
178+
// Clear TTD events cache when resetting
179+
ClearTTDEventsCache();
176180

177181
if (!this->m_dbgengInitialized)
178182
return;
@@ -1354,18 +1358,48 @@ std::vector<TTDEvent> DbgEngTTDAdapter::GetTTDEvents(TTDEventType eventType)
13541358
{
13551359
std::vector<TTDEvent> events;
13561360

1357-
if (!QueryEventsForType(eventType, events))
1361+
// Cache all events if not already cached
1362+
if (!m_eventsCached)
13581363
{
1359-
LogError("Failed to query TTD events for type %d", eventType);
1360-
return events;
1364+
if (!QueryAllTTDEvents())
1365+
{
1366+
LogError("Failed to query all TTD events");
1367+
return events;
1368+
}
1369+
}
1370+
1371+
// Filter cached events by type
1372+
for (const auto& event : m_cachedEvents)
1373+
{
1374+
if (event.type == eventType)
1375+
{
1376+
events.push_back(event);
1377+
}
13611378
}
13621379

1363-
LogInfo("Successfully retrieved %zu TTD events", events.size());
1380+
LogInfo("Successfully retrieved %zu TTD events of type %d from cache", events.size(), eventType);
13641381
return events;
13651382
}
13661383

13671384

1368-
bool DbgEngTTDAdapter::QueryEventsForType(TTDEventType eventType, std::vector<TTDEvent>& events)
1385+
std::vector<TTDEvent> DbgEngTTDAdapter::GetAllTTDEvents()
1386+
{
1387+
// Cache all events if not already cached
1388+
if (!m_eventsCached)
1389+
{
1390+
if (!QueryAllTTDEvents())
1391+
{
1392+
LogError("Failed to query all TTD events");
1393+
return {};
1394+
}
1395+
}
1396+
1397+
LogInfo("Successfully retrieved %zu total TTD events from cache", m_cachedEvents.size());
1398+
return m_cachedEvents;
1399+
}
1400+
1401+
1402+
bool DbgEngTTDAdapter::QueryAllTTDEvents()
13691403
{
13701404
if (!m_debugHost || !m_hostEvaluator)
13711405
{
@@ -1375,45 +1409,28 @@ bool DbgEngTTDAdapter::QueryEventsForType(TTDEventType eventType, std::vector<TT
13751409

13761410
try
13771411
{
1378-
// Build the TTD.Events query expression based on event type
1379-
std::string expression = GetEventTypeExpression(eventType);
1412+
// Build the TTD.Events query expression to get all events (using curprocess instead of cursession)
1413+
std::string expression = "@$curprocess.TTD.Events";
13801414

13811415
LogInfo("Executing TTD events query: %s", expression.c_str());
13821416

1383-
return ParseTTDEventObjects(expression, eventType, events);
1417+
m_cachedEvents.clear();
1418+
if (ParseTTDEventObjects(expression, m_cachedEvents))
1419+
{
1420+
m_eventsCached = true;
1421+
return true;
1422+
}
1423+
return false;
13841424
}
13851425
catch (const std::exception& e)
13861426
{
1387-
LogError("Exception in QueryEventsForType: %s", e.what());
1427+
LogError("Exception in QueryAllTTDEvents: %s", e.what());
13881428
return false;
13891429
}
13901430
}
13911431

13921432

1393-
std::string DbgEngTTDAdapter::GetEventTypeExpression(TTDEventType eventType)
1394-
{
1395-
std::string baseExpression = "@$cursession.TTD.Events";
1396-
1397-
switch (eventType)
1398-
{
1399-
case TTDEventThreadCreated:
1400-
return baseExpression + ".Where(e => e.Type == \"ThreadCreated\")";
1401-
case TTDEventThreadTerminated:
1402-
return baseExpression + ".Where(e => e.Type == \"ThreadTerminated\")";
1403-
case TTDEventModuleLoaded:
1404-
return baseExpression + ".Where(e => e.Type == \"ModuleLoaded\")";
1405-
case TTDEventModuleUnloaded:
1406-
return baseExpression + ".Where(e => e.Type == \"ModuleUnloaded\")";
1407-
case TTDEventException:
1408-
return baseExpression + ".Where(e => e.Type == \"Exception\")";
1409-
default:
1410-
LogError("Unknown TTD event type: %d", eventType);
1411-
return baseExpression;
1412-
}
1413-
}
1414-
1415-
1416-
bool DbgEngTTDAdapter::ParseTTDEventObjects(const std::string& expression, TTDEventType eventType, std::vector<TTDEvent>& events)
1433+
bool DbgEngTTDAdapter::ParseTTDEventObjects(const std::string& expression, std::vector<TTDEvent>& events)
14171434
{
14181435
try
14191436
{
@@ -1490,6 +1507,33 @@ bool DbgEngTTDAdapter::ParseTTDEventObjects(const std::string& expression, TTDEv
14901507
break;
14911508
}
14921509

1510+
// Parse event type from the event object first
1511+
TTDEventType eventType = TTDEventThreadCreated; // default
1512+
1513+
ComPtr<IModelObject> typeObj;
1514+
if (SUCCEEDED(eventObject->GetKeyValue(L"Type", &typeObj, nullptr)))
1515+
{
1516+
VARIANT vtType;
1517+
VariantInit(&vtType);
1518+
if (SUCCEEDED(typeObj->GetIntrinsicValueAs(VT_BSTR, &vtType)))
1519+
{
1520+
_bstr_t bstr(vtType.bstrVal);
1521+
std::string typeStr = std::string(bstr);
1522+
1523+
if (typeStr == "ThreadCreated")
1524+
eventType = TTDEventThreadCreated;
1525+
else if (typeStr == "ThreadTerminated")
1526+
eventType = TTDEventThreadTerminated;
1527+
else if (typeStr == "ModuleLoaded")
1528+
eventType = TTDEventModuleLoaded;
1529+
else if (typeStr == "ModuleUnloaded")
1530+
eventType = TTDEventModuleUnloaded;
1531+
else if (typeStr == "Exception")
1532+
eventType = TTDEventException;
1533+
}
1534+
VariantClear(&vtType);
1535+
}
1536+
14931537
TTDEvent event(eventType);
14941538

14951539
// Parse Position
@@ -1838,6 +1882,13 @@ void DbgEngTTDAdapter::ParseTTDPosition(IModelObject* positionObj, TTDPosition&
18381882
}
18391883

18401884

1885+
void DbgEngTTDAdapter::ClearTTDEventsCache()
1886+
{
1887+
m_cachedEvents.clear();
1888+
m_eventsCached = false;
1889+
}
1890+
1891+
18411892
void BinaryNinjaDebugger::InitDbgEngTTDAdapterType()
18421893
{
18431894
static DbgEngTTDAdapterType localType;

core/adapters/dbgengttdadapter.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ namespace BinaryNinjaDebugger {
5656

5757
// TTD Events Analysis Methods
5858
std::vector<TTDEvent> GetTTDEvents(TTDEventType eventType) override;
59+
std::vector<TTDEvent> GetAllTTDEvents() override;
5960

6061
void GenerateDefaultAdapterSettings(BinaryView* data);
6162
Ref<Settings> GetAdapterSettings() override;
@@ -69,13 +70,19 @@ namespace BinaryNinjaDebugger {
6970
bool ParseTTDCallObjects(const std::string& expression, std::vector<TTDCallEvent>& events);
7071

7172
// Helper methods for TTD events analysis
72-
bool QueryEventsForType(TTDEventType eventType, std::vector<TTDEvent>& events);
73-
bool ParseTTDEventObjects(const std::string& expression, TTDEventType eventType, std::vector<TTDEvent>& events);
74-
std::string GetEventTypeExpression(TTDEventType eventType);
73+
bool QueryAllTTDEvents();
74+
bool ParseTTDEventObjects(const std::string& expression, std::vector<TTDEvent>& events);
7575
void ParseThreadDetails(IModelObject* eventObject, TTDEvent& event);
7676
void ParseModuleDetails(IModelObject* eventObject, TTDEvent& event);
7777
void ParseExceptionDetails(IModelObject* eventObject, TTDEvent& event);
7878
void ParseTTDPosition(IModelObject* positionObj, TTDPosition& position);
79+
80+
// TTD Events cache
81+
std::vector<TTDEvent> m_cachedEvents;
82+
bool m_eventsCached;
83+
84+
// Method to clear TTD events cache
85+
void ClearTTDEventsCache();
7986

8087
// Data model helper methods
8188
std::string EvaluateDataModelExpression(const std::string& expression);

core/debugadapter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,13 @@ std::vector<TTDEvent> DebugAdapter::GetTTDEvents(TTDEventType eventType)
200200
}
201201

202202

203+
std::vector<TTDEvent> DebugAdapter::GetAllTTDEvents()
204+
{
205+
// Default implementation returns empty results for adapters that don't support TTD
206+
return {};
207+
}
208+
209+
203210
TTDPosition DebugAdapter::GetCurrentTTDPosition()
204211
{
205212
// Default implementation returns an empty position for adapters that don't support TTD

0 commit comments

Comments
 (0)