mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-07 14:28:40 +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
|
//- rjf: write all traps into memory
|
||||||
//
|
//
|
||||||
U8 *trap_swap_bytes = push_array_no_zero(scratch.arena, U8, ctrls->traps.trap_count);
|
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;
|
U64 trap_idx = 0;
|
||||||
for(DMN_TrapChunkNode *n = ctrls->traps.first; n != 0; n = n->next)
|
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 *first_run_thread = 0;
|
||||||
DMN_W32_EntityNode *last_run_thread = 0;
|
DMN_W32_EntityNode *last_run_thread = 0;
|
||||||
|
ProfScope("produce list of threads which will run")
|
||||||
{
|
{
|
||||||
//- rjf: scan all processes
|
//- rjf: scan all processes
|
||||||
for(DMN_W32_Entity *process = dmn_w32_shared->entities_base->first;
|
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
|
//- 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)
|
for(DMN_W32_EntityNode *n = first_run_thread; n != 0; n = n->next)
|
||||||
{
|
{
|
||||||
DMN_W32_Entity *thread = n->v;
|
DMN_W32_Entity *thread = n->v;
|
||||||
@@ -1543,8 +1547,17 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
}break;
|
}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
|
//- rjf: choose win32 resume code
|
||||||
//
|
//
|
||||||
DWORD resume_code = DBG_CONTINUE;
|
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
|
//- rjf: inform windows that we're resuming, run, & obtain next debug event
|
||||||
//
|
//
|
||||||
DEBUG_EVENT evt = {0};
|
DEBUG_EVENT evt = {0};
|
||||||
B32 evt_good = 0;
|
B32 evt_good = 0;
|
||||||
|
ProfScope("inform windows that we're resuming, run, & obtain next debug event")
|
||||||
{
|
{
|
||||||
B32 resume_good = 1;
|
B32 resume_good = 1;
|
||||||
if(dmn_w32_shared->resume_needed)
|
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
|
//- rjf: process the new event
|
||||||
//
|
//
|
||||||
if(evt_good)
|
if(evt_good) ProfScope("process the new event")
|
||||||
{
|
{
|
||||||
switch(evt.dwDebugEventCode)
|
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;
|
U64 string_size = (U64)evt.u.DebugString.nDebugStringLength;
|
||||||
|
|
||||||
// rjf: read memory
|
// 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);
|
dmn_w32_process_read(process->handle, r1u64(string_address, string_address+string_size), buffer);
|
||||||
buffer[string_size] = 0;
|
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);
|
DMN_Event *e = dmn_event_list_push(arena, &events);
|
||||||
e->kind = DMN_EventKind_DebugString;
|
e->kind = DMN_EventKind_DebugString;
|
||||||
e->process = dmn_w32_handle_from_entity(process);
|
e->process = dmn_w32_handle_from_entity(process);
|
||||||
e->thread = dmn_w32_handle_from_entity(thread);
|
e->thread = dmn_w32_handle_from_entity(thread);
|
||||||
e->string = str8(buffer, string_size);
|
e->string = debug_strings_joined;
|
||||||
if(string_size != 0 && buffer[string_size-1] == 0)
|
keep_going = 0;
|
||||||
{
|
|
||||||
e->string.size -= 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
@@ -2206,9 +2198,58 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
}break;
|
}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
|
//- 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;
|
for(DMN_W32_Entity *process = dmn_w32_shared->entities_base->first;
|
||||||
process != &dmn_w32_entity_nil;
|
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
|
//- rjf: restore original memory at trap locations
|
||||||
//
|
//
|
||||||
|
ProfScope("restore original memory at trap locations")
|
||||||
{
|
{
|
||||||
U64 trap_idx = 0;
|
U64 trap_idx = 0;
|
||||||
for(DMN_TrapChunkNode *n = ctrls->traps.first; n != 0; n = n->next)
|
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
|
//- 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);
|
DMN_W32_Entity *thread = dmn_w32_entity_from_handle(ctrls->single_step_thread);
|
||||||
Architecture arch = thread->arch;
|
Architecture arch = thread->arch;
|
||||||
|
|||||||
Reference in New Issue
Block a user