mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-08 14:58:08 +00:00
majorly improve outputdebugstring performance
This commit is contained in:
@@ -1418,6 +1418,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
//- rjf: write all traps into memory
|
||||
//
|
||||
U8 *trap_swap_bytes = push_array_no_zero(scratch.arena, U8, ctrls->traps.trap_count);
|
||||
ProfScope("write all traps into memory")
|
||||
{
|
||||
U64 trap_idx = 0;
|
||||
for(DMN_TrapChunkNode *n = ctrls->traps.first; n != 0; n = n->next)
|
||||
@@ -1438,6 +1439,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
//
|
||||
DMN_W32_EntityNode *first_run_thread = 0;
|
||||
DMN_W32_EntityNode *last_run_thread = 0;
|
||||
ProfScope("produce list of threads which will run")
|
||||
{
|
||||
//- rjf: scan all processes
|
||||
for(DMN_W32_Entity *process = dmn_w32_shared->entities_base->first;
|
||||
@@ -1519,6 +1521,8 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
//////////////////////////
|
||||
//- rjf: resume threads which will run
|
||||
//
|
||||
ProfScope("resume threads which will run")
|
||||
{
|
||||
for(DMN_W32_EntityNode *n = first_run_thread; n != 0; n = n->next)
|
||||
{
|
||||
DMN_W32_Entity *thread = n->v;
|
||||
@@ -1543,8 +1547,17 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
//- rjf: loop, consume win32 debug events until we produce the relevant demon events
|
||||
//
|
||||
String8List debug_strings = {0};
|
||||
for(B32 keep_going = 1; keep_going;)
|
||||
{
|
||||
keep_going = 0;
|
||||
|
||||
////////////////////////
|
||||
//- rjf: choose win32 resume code
|
||||
//
|
||||
DWORD resume_code = DBG_CONTINUE;
|
||||
@@ -1556,11 +1569,12 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
////////////////////////
|
||||
//- rjf: inform windows that we're resuming, run, & obtain next debug event
|
||||
//
|
||||
DEBUG_EVENT evt = {0};
|
||||
B32 evt_good = 0;
|
||||
ProfScope("inform windows that we're resuming, run, & obtain next debug event")
|
||||
{
|
||||
B32 resume_good = 1;
|
||||
if(dmn_w32_shared->resume_needed)
|
||||
@@ -1586,43 +1600,10 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
//- rjf: suspend threads which ran
|
||||
//
|
||||
if(evt_good) for(DMN_W32_EntityNode *n = first_run_thread; n != 0; n = n->next)
|
||||
{
|
||||
DMN_W32_Entity *thread = n->v;
|
||||
DWORD suspend_result = SuspendThread(thread->handle);
|
||||
switch(suspend_result)
|
||||
{
|
||||
case 0xffffffffu:
|
||||
{
|
||||
// TODO(rjf): error - unknown cause. need to do do GetLastError, FormatMessage
|
||||
//
|
||||
// NOTE(rjf): this can happen when the event is EXIT_THREAD_DEBUG_EVENT
|
||||
// or EXIT_PROCESS_DEBUG_EVENT. after such an event, SuspendThread
|
||||
// gives error code 5 (access denied). this has no adverse effects, but
|
||||
// if we want to start reporting errors we should take care to avoid
|
||||
// calling SuspendThread in that case.
|
||||
}break;
|
||||
default:
|
||||
{
|
||||
DWORD desired_counter = 1;
|
||||
DWORD current_counter = suspend_result + 1;
|
||||
if(current_counter != desired_counter)
|
||||
{
|
||||
// NOTE(rjf): Warning. We've suspended to something higher than 1.
|
||||
// In this case, it means the user probably created the thread in
|
||||
// a suspended state, or they called SuspendThread.
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
////////////////////////
|
||||
//- rjf: process the new event
|
||||
//
|
||||
if(evt_good)
|
||||
if(evt_good) ProfScope("process the new event")
|
||||
{
|
||||
switch(evt.dwDebugEventCode)
|
||||
{
|
||||
@@ -2166,21 +2147,32 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
U64 string_size = (U64)evt.u.DebugString.nDebugStringLength;
|
||||
|
||||
// rjf: read memory
|
||||
U8 *buffer = push_array_no_zero(arena, U8, string_size + 1);
|
||||
U8 *buffer = push_array_no_zero(scratch.arena, U8, string_size + 1);
|
||||
dmn_w32_process_read(process->handle, r1u64(string_address, string_address+string_size), buffer);
|
||||
buffer[string_size] = 0;
|
||||
|
||||
// rjf: generate event
|
||||
// rjf: extract into string
|
||||
String8 debug_string = str8(buffer, string_size);
|
||||
if(debug_string.size != 0 && buffer[string_size-1] == 0)
|
||||
{
|
||||
debug_string.size -= 1;
|
||||
}
|
||||
|
||||
// rjf: push into debug strings
|
||||
str8_list_push(scratch.arena, &debug_strings, debug_string);
|
||||
keep_going = 1;
|
||||
|
||||
// rjf: generate event, given sufficient amount of text
|
||||
if(debug_strings.total_size >= KB(4))
|
||||
{
|
||||
String8 debug_strings_joined = str8_list_join(arena, &debug_strings, 0);
|
||||
MemoryZeroStruct(&debug_strings);
|
||||
DMN_Event *e = dmn_event_list_push(arena, &events);
|
||||
e->kind = DMN_EventKind_DebugString;
|
||||
e->process = dmn_w32_handle_from_entity(process);
|
||||
e->thread = dmn_w32_handle_from_entity(thread);
|
||||
e->string = str8(buffer, string_size);
|
||||
if(string_size != 0 && buffer[string_size-1] == 0)
|
||||
{
|
||||
e->string.size -= 1;
|
||||
}
|
||||
e->string = debug_strings_joined;
|
||||
keep_going = 0;
|
||||
}
|
||||
}break;
|
||||
|
||||
@@ -2206,9 +2198,58 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
//- rjf: send out event for any remaining debug strings
|
||||
//
|
||||
if(debug_strings.total_size != 0)
|
||||
{
|
||||
String8 debug_strings_joined = str8_list_join(arena, &debug_strings, 0);
|
||||
MemoryZeroStruct(&debug_strings);
|
||||
DMN_Event *e = dmn_event_list_push(arena, &events);
|
||||
e->kind = DMN_EventKind_DebugString;
|
||||
e->string = debug_strings_joined;
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
//- rjf: suspend threads which ran
|
||||
//
|
||||
ProfScope("suspend threads which ran")
|
||||
{
|
||||
for(DMN_W32_EntityNode *n = first_run_thread; n != 0; n = n->next)
|
||||
{
|
||||
DMN_W32_Entity *thread = n->v;
|
||||
DWORD suspend_result = SuspendThread(thread->handle);
|
||||
switch(suspend_result)
|
||||
{
|
||||
case 0xffffffffu:
|
||||
{
|
||||
// TODO(rjf): error - unknown cause. need to do do GetLastError, FormatMessage
|
||||
//
|
||||
// NOTE(rjf): this can happen when the event is EXIT_THREAD_DEBUG_EVENT
|
||||
// or EXIT_PROCESS_DEBUG_EVENT. after such an event, SuspendThread
|
||||
// gives error code 5 (access denied). this has no adverse effects, but
|
||||
// if we want to start reporting errors we should take care to avoid
|
||||
// calling SuspendThread in that case.
|
||||
}break;
|
||||
default:
|
||||
{
|
||||
DWORD desired_counter = 1;
|
||||
DWORD current_counter = suspend_result + 1;
|
||||
if(current_counter != desired_counter)
|
||||
{
|
||||
// NOTE(rjf): Warning. We've suspended to something higher than 1.
|
||||
// In this case, it means the user probably created the thread in
|
||||
// a suspended state, or they called SuspendThread.
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: gather new thread-names
|
||||
if(dmn_w32_GetThreadDescription != 0)
|
||||
ProfScope("gather new thread names") if(dmn_w32_GetThreadDescription != 0)
|
||||
{
|
||||
for(DMN_W32_Entity *process = dmn_w32_shared->entities_base->first;
|
||||
process != &dmn_w32_entity_nil;
|
||||
@@ -2252,6 +2293,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
//////////////////////////
|
||||
//- rjf: restore original memory at trap locations
|
||||
//
|
||||
ProfScope("restore original memory at trap locations")
|
||||
{
|
||||
U64 trap_idx = 0;
|
||||
for(DMN_TrapChunkNode *n = ctrls->traps.first; n != 0; n = n->next)
|
||||
@@ -2271,7 +2313,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
//////////////////////////
|
||||
//- rjf: unset single step bit
|
||||
//
|
||||
if(!dmn_handle_match(ctrls->single_step_thread, dmn_handle_zero()))
|
||||
if(!dmn_handle_match(ctrls->single_step_thread, dmn_handle_zero())) ProfScope("unset single step bit")
|
||||
{
|
||||
DMN_W32_Entity *thread = dmn_w32_entity_from_handle(ctrls->single_step_thread);
|
||||
Architecture arch = thread->arch;
|
||||
|
||||
Reference in New Issue
Block a user