mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-06 22:08:41 +00:00
demon tweaks / debugging; adjust call stack cache reading API to account for high-priority path, where we want to try computing the thread's call stack immediately
This commit is contained in:
+2
-1
@@ -26,8 +26,9 @@ async_init(CmdLine *cmdline)
|
|||||||
String8 work_thread_count_string = cmd_line_string(cmdline, str8_lit("work_threads_count"));
|
String8 work_thread_count_string = cmd_line_string(cmdline, str8_lit("work_threads_count"));
|
||||||
if(work_thread_count_string.size == 0 || !try_u64_from_str8_c_rules(work_thread_count_string, &async_shared->work_threads_count))
|
if(work_thread_count_string.size == 0 || !try_u64_from_str8_c_rules(work_thread_count_string, &async_shared->work_threads_count))
|
||||||
{
|
{
|
||||||
async_shared->work_threads_count = Max(1, os_get_system_info()->logical_processor_count-1);
|
async_shared->work_threads_count = Max(4, os_get_system_info()->logical_processor_count-1);
|
||||||
}
|
}
|
||||||
|
async_shared->work_threads_count = Max(4, async_shared->work_threads_count);
|
||||||
async_shared->work_threads = push_array(arena, OS_Handle, async_shared->work_threads_count);
|
async_shared->work_threads = push_array(arena, OS_Handle, async_shared->work_threads_count);
|
||||||
for EachIndex(idx, async_shared->work_threads_count)
|
for EachIndex(idx, async_shared->work_threads_count)
|
||||||
{
|
{
|
||||||
|
|||||||
+11
-1
@@ -3356,7 +3356,7 @@ ctrl_call_stack_frame_from_unwind_and_inline_depth(CTRL_CallStack *call_stack, U
|
|||||||
//~ rjf: Call Stack Cache Functions
|
//~ rjf: Call Stack Cache Functions
|
||||||
|
|
||||||
internal CTRL_CallStack
|
internal CTRL_CallStack
|
||||||
ctrl_call_stack_from_thread(CTRL_Scope *scope, CTRL_Entity *thread, B32 high_priority, U64 endt_us)
|
ctrl_call_stack_from_thread(CTRL_Scope *scope, CTRL_EntityCtx *entity_ctx, CTRL_Entity *thread, B32 high_priority, U64 endt_us)
|
||||||
{
|
{
|
||||||
CTRL_CallStack call_stack = {0};
|
CTRL_CallStack call_stack = {0};
|
||||||
{
|
{
|
||||||
@@ -3399,6 +3399,7 @@ ctrl_call_stack_from_thread(CTRL_Scope *scope, CTRL_Entity *thread, B32 high_pri
|
|||||||
//- rjf: create node if needed
|
//- rjf: create node if needed
|
||||||
if(!is_good) OS_MutexScopeRWPromote(stripe->rw_mutex)
|
if(!is_good) OS_MutexScopeRWPromote(stripe->rw_mutex)
|
||||||
{
|
{
|
||||||
|
node = 0;
|
||||||
for(CTRL_CallStackCacheNode *n = slot->first; n != 0; n = n->next)
|
for(CTRL_CallStackCacheNode *n = slot->first; n != 0; n = n->next)
|
||||||
{
|
{
|
||||||
if(ctrl_handle_match(n->thread, handle))
|
if(ctrl_handle_match(n->thread, handle))
|
||||||
@@ -4271,6 +4272,15 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
|
|||||||
log_infof("string: \"%S\"\n", ev->string);
|
log_infof("string: \"%S\"\n", ev->string);
|
||||||
log_infof("ip_vaddr: 0x%I64x\n", ev->instruction_pointer);
|
log_infof("ip_vaddr: 0x%I64x\n", ev->instruction_pointer);
|
||||||
}
|
}
|
||||||
|
raddbg_log("event:\n");
|
||||||
|
raddbg_log("kind: %S\n", dmn_event_kind_string_table[ev->kind]);
|
||||||
|
raddbg_log("process: [%I64u]\n", ev->process.u64[0]);
|
||||||
|
raddbg_log("thread: [%I64u]\n", ev->thread.u64[0]);
|
||||||
|
raddbg_log("module: [%I64u]\n", ev->module.u64[0]);
|
||||||
|
raddbg_log("pid: %I64u\n", ctrl_entity_from_handle(entity_ctx, ctrl_handle_make(CTRL_MachineID_Local, ev->process))->id);
|
||||||
|
raddbg_log("tid: %I64u\n", ctrl_entity_from_handle(entity_ctx, ctrl_handle_make(CTRL_MachineID_Local, ev->thread))->id);
|
||||||
|
raddbg_log("code: %I64u\n", ev->code);
|
||||||
|
raddbg_log("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: determine if we should filter
|
// rjf: determine if we should filter
|
||||||
|
|||||||
@@ -1045,7 +1045,7 @@ internal CTRL_CallStackFrame *ctrl_call_stack_frame_from_unwind_and_inline_depth
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Call Stack Cache Functions
|
//~ rjf: Call Stack Cache Functions
|
||||||
|
|
||||||
internal CTRL_CallStack ctrl_call_stack_from_thread(CTRL_Scope *scope, CTRL_Entity *thread, B32 high_priority, U64 endt_us);
|
internal CTRL_CallStack ctrl_call_stack_from_thread(CTRL_Scope *scope, CTRL_EntityCtx *entity_ctx, CTRL_Entity *thread, B32 high_priority, U64 endt_us);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Halting All Attached Processes
|
//~ rjf: Halting All Attached Processes
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ dmn_w32_entity_release(DMN_W32_Entity *entity)
|
|||||||
{
|
{
|
||||||
CloseHandle(t->e->handle);
|
CloseHandle(t->e->handle);
|
||||||
}
|
}
|
||||||
|
t->e->kind = DMN_W32_EntityKind_Null;
|
||||||
|
|
||||||
// rjf: remove from id -> entity map
|
// rjf: remove from id -> entity map
|
||||||
if(t->e->id != 0)
|
if(t->e->id != 0)
|
||||||
@@ -1870,13 +1871,14 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
{
|
{
|
||||||
dmn_w32_shared->resume_needed = 0;
|
dmn_w32_shared->resume_needed = 0;
|
||||||
resume_good = !!ContinueDebugEvent(dmn_w32_shared->resume_pid, dmn_w32_shared->resume_tid, resume_code);
|
resume_good = !!ContinueDebugEvent(dmn_w32_shared->resume_pid, dmn_w32_shared->resume_tid, resume_code);
|
||||||
|
DWORD error = GetLastError();
|
||||||
dmn_w32_shared->resume_needed = 0;
|
dmn_w32_shared->resume_needed = 0;
|
||||||
dmn_w32_shared->resume_tid = 0;
|
dmn_w32_shared->resume_tid = 0;
|
||||||
dmn_w32_shared->resume_pid = 0;
|
dmn_w32_shared->resume_pid = 0;
|
||||||
}
|
}
|
||||||
if(resume_good)
|
if(resume_good)
|
||||||
{
|
{
|
||||||
evt_good = !!WaitForDebugEvent(&evt, 100);
|
evt_good = !!WaitForDebugEvent(&evt, 1000);
|
||||||
if(evt_good)
|
if(evt_good)
|
||||||
{
|
{
|
||||||
dmn_w32_shared->resume_needed = 1;
|
dmn_w32_shared->resume_needed = 1;
|
||||||
@@ -1885,6 +1887,8 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
DWORD err = GetLastError();
|
||||||
|
(void)err;
|
||||||
keep_going = 1;
|
keep_going = 1;
|
||||||
}
|
}
|
||||||
ins_atomic_u64_inc_eval(&dmn_w32_shared->run_gen);
|
ins_atomic_u64_inc_eval(&dmn_w32_shared->run_gen);
|
||||||
@@ -1992,6 +1996,15 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
{
|
{
|
||||||
DMN_W32_Entity *process = dmn_w32_entity_from_kind_id(DMN_W32_EntityKind_Process, evt.dwProcessId);
|
DMN_W32_Entity *process = dmn_w32_entity_from_kind_id(DMN_W32_EntityKind_Process, evt.dwProcessId);
|
||||||
|
|
||||||
|
// rjf: if this was the process we were going to resume, then we will
|
||||||
|
// just not resume, and wait for another debug event
|
||||||
|
if(evt.dwProcessId == dmn_w32_shared->resume_pid)
|
||||||
|
{
|
||||||
|
dmn_w32_shared->resume_needed = 0;
|
||||||
|
dmn_w32_shared->resume_tid = 0;
|
||||||
|
dmn_w32_shared->resume_pid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// rjf: generate events for children
|
// rjf: generate events for children
|
||||||
for(DMN_W32_Entity *child = process->first; child != &dmn_w32_entity_nil; child = child->next)
|
for(DMN_W32_Entity *child = process->first; child != &dmn_w32_entity_nil; child = child->next)
|
||||||
{
|
{
|
||||||
@@ -2097,6 +2110,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
e->kind = DMN_EventKind_Halt;
|
e->kind = DMN_EventKind_Halt;
|
||||||
dmn_w32_shared->halter_process = dmn_handle_zero();
|
dmn_w32_shared->halter_process = dmn_handle_zero();
|
||||||
dmn_w32_shared->halter_tid = 0;
|
dmn_w32_shared->halter_tid = 0;
|
||||||
|
keep_going = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: if this thread is *not* the halter, then generate a regular exit-thread event
|
// rjf: if this thread is *not* the halter, then generate a regular exit-thread event
|
||||||
@@ -2643,6 +2657,10 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
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;
|
||||||
|
if(thread->kind != DMN_W32_EntityKind_Thread)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
DWORD suspend_result = SuspendThread(thread->handle);
|
DWORD suspend_result = SuspendThread(thread->handle);
|
||||||
switch(suspend_result)
|
switch(suspend_result)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1816,7 +1816,7 @@ rd_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range)
|
|||||||
case CTRL_EntityKind_Thread:
|
case CTRL_EntityKind_Thread:
|
||||||
{
|
{
|
||||||
CTRL_Scope *ctrl_scope = ctrl_scope_open();
|
CTRL_Scope *ctrl_scope = ctrl_scope_open();
|
||||||
CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, entity, 1, 0);
|
CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, &d_state->ctrl_entity_store->ctx, entity, 1, 0);
|
||||||
U64 concrete_frame_idx = e_interpret_ctx->reg_unwind_count;
|
U64 concrete_frame_idx = e_interpret_ctx->reg_unwind_count;
|
||||||
if(concrete_frame_idx < call_stack.concrete_frames_count)
|
if(concrete_frame_idx < call_stack.concrete_frames_count)
|
||||||
{
|
{
|
||||||
@@ -6399,7 +6399,7 @@ rd_window_frame(void)
|
|||||||
Vec4F32 code_color = ui_color_from_name(str8_lit("code_default"));
|
Vec4F32 code_color = ui_color_from_name(str8_lit("code_default"));
|
||||||
Vec4F32 symbol_color = ui_color_from_name(str8_lit("code_symbol"));
|
Vec4F32 symbol_color = ui_color_from_name(str8_lit("code_symbol"));
|
||||||
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(ctrl_entity, CTRL_EntityKind_Process);
|
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(ctrl_entity, CTRL_EntityKind_Process);
|
||||||
CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, ctrl_entity, ctrl_handle_match(ctrl_entity->handle, rd_base_regs()->thread), 0);
|
CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, &d_state->ctrl_entity_store->ctx, ctrl_entity, ctrl_handle_match(ctrl_entity->handle, rd_base_regs()->thread), 0);
|
||||||
if(call_stack.frames_count != 0)
|
if(call_stack.frames_count != 0)
|
||||||
{
|
{
|
||||||
ui_spacer(ui_em(1.5f, 1.f));
|
ui_spacer(ui_em(1.5f, 1.f));
|
||||||
@@ -15640,7 +15640,7 @@ rd_frame(void)
|
|||||||
{
|
{
|
||||||
CTRL_Scope *ctrl_scope = ctrl_scope_open();
|
CTRL_Scope *ctrl_scope = ctrl_scope_open();
|
||||||
CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_base_regs()->thread);
|
CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_base_regs()->thread);
|
||||||
CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, thread, 1, os_now_microseconds()+10000);
|
CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, &d_state->ctrl_entity_store->ctx, thread, 1, os_now_microseconds()+10000);
|
||||||
CTRL_CallStackFrame *frame = ctrl_call_stack_frame_from_unwind_and_inline_depth(&call_stack, rd_regs()->unwind_count, rd_regs()->inline_depth);
|
CTRL_CallStackFrame *frame = ctrl_call_stack_frame_from_unwind_and_inline_depth(&call_stack, rd_regs()->unwind_count, rd_regs()->inline_depth);
|
||||||
if(frame == 0)
|
if(frame == 0)
|
||||||
{
|
{
|
||||||
@@ -15659,7 +15659,7 @@ rd_frame(void)
|
|||||||
{
|
{
|
||||||
CTRL_Scope *ctrl_scope = ctrl_scope_open();
|
CTRL_Scope *ctrl_scope = ctrl_scope_open();
|
||||||
CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_base_regs()->thread);
|
CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_base_regs()->thread);
|
||||||
CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, thread, 1, os_now_microseconds()+10000);
|
CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, &d_state->ctrl_entity_store->ctx, thread, 1, os_now_microseconds()+10000);
|
||||||
CTRL_CallStackFrame *current_frame = ctrl_call_stack_frame_from_unwind_and_inline_depth(&call_stack, rd_regs()->unwind_count, rd_regs()->inline_depth);
|
CTRL_CallStackFrame *current_frame = ctrl_call_stack_frame_from_unwind_and_inline_depth(&call_stack, rd_regs()->unwind_count, rd_regs()->inline_depth);
|
||||||
CTRL_CallStackFrame *next_frame = current_frame;
|
CTRL_CallStackFrame *next_frame = current_frame;
|
||||||
if(current_frame != 0) switch(kind)
|
if(current_frame != 0) switch(kind)
|
||||||
|
|||||||
@@ -957,7 +957,7 @@ E_TYPE_IREXT_FUNCTION_DEF(call_stack)
|
|||||||
{
|
{
|
||||||
accel->arch = entity->arch;
|
accel->arch = entity->arch;
|
||||||
accel->process = ctrl_process_from_entity(entity)->handle;
|
accel->process = ctrl_process_from_entity(entity)->handle;
|
||||||
accel->call_stack = ctrl_call_stack_from_thread(rd_state->frame_ctrl_scope, entity, ctrl_handle_match(entity->handle, rd_base_regs()->thread), 0);
|
accel->call_stack = ctrl_call_stack_from_thread(rd_state->frame_ctrl_scope, &d_state->ctrl_entity_store->ctx, entity, ctrl_handle_match(entity->handle, rd_base_regs()->thread), 0);
|
||||||
}
|
}
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
- The debugger now unfocuses query bars (e.g. that opened by `Ctrl + F` in a source view) if the main view content is clicked by the mouse. The query bar can be refocused also by clicking.
|
- The debugger now unfocuses query bars (e.g. that opened by `Ctrl + F` in a source view) if the main view content is clicked by the mouse. The query bar can be refocused also by clicking.
|
||||||
- Moved call stack evaluation to occur asynchronously, so that deeper call stacks (which can be expensive to compute) do not block the UI.
|
- Moved call stack evaluation to occur asynchronously, so that deeper call stacks (which can be expensive to compute) do not block the UI.
|
||||||
- Stopped the debugger from running the default Windows message handling path for most `Alt`-based keybindings, which was causing a Windows beep sound to play.
|
- Stopped the debugger from running the default Windows message handling path for most `Alt`-based keybindings, which was causing a Windows beep sound to play.
|
||||||
|
- Fixed a bug where RDI files would sometimes fail to generate, resulting in no debug info being available on some runs.
|
||||||
- Fixed a bug which was preventing backslashes from working in file system querying interfaces correctly.
|
- Fixed a bug which was preventing backslashes from working in file system querying interfaces correctly.
|
||||||
- Fixed a bug which was preventing some recursive callstacks from fully displaying in the debugger.
|
- Fixed a bug which was preventing some recursive callstacks from fully displaying in the debugger.
|
||||||
- Fixed a bug which prevented `Space` from being used as a keybinding. Bound `Space` by default to the `Accept` command (to which `Enter` / `Return` is also defaultly bound).
|
- Fixed a bug which prevented `Space` from being used as a keybinding. Bound `Space` by default to the `Accept` command (to which `Enter` / `Return` is also defaultly bound).
|
||||||
|
|||||||
@@ -1011,7 +1011,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
|
|||||||
CTRL_Scope *ctrl_scope = ctrl_scope_open();
|
CTRL_Scope *ctrl_scope = ctrl_scope_open();
|
||||||
info.callstack_thread = entity;
|
info.callstack_thread = entity;
|
||||||
U64 frame_num = ev_block_num_from_id(block, key.child_id);
|
U64 frame_num = ev_block_num_from_id(block, key.child_id);
|
||||||
CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, entity, ctrl_handle_match(entity->handle, rd_base_regs()->thread), 0);
|
CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, &d_state->ctrl_entity_store->ctx, entity, ctrl_handle_match(entity->handle, rd_base_regs()->thread), 0);
|
||||||
if(1 <= frame_num && frame_num <= call_stack.frames_count)
|
if(1 <= frame_num && frame_num <= call_stack.frames_count)
|
||||||
{
|
{
|
||||||
CTRL_CallStackFrame *f = &call_stack.frames[frame_num-1];
|
CTRL_CallStackFrame *f = &call_stack.frames[frame_num-1];
|
||||||
@@ -2841,7 +2841,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
|
|||||||
CTRL_Scope *ctrl_scope = ctrl_scope_open();
|
CTRL_Scope *ctrl_scope = ctrl_scope_open();
|
||||||
CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread);
|
CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread);
|
||||||
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process);
|
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process);
|
||||||
CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, thread, 1, 0);
|
CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, &d_state->ctrl_entity_store->ctx, thread, 1, 0);
|
||||||
|
|
||||||
//- rjf: fill unwind frame annotations
|
//- rjf: fill unwind frame annotations
|
||||||
if(call_stack.concrete_frames_count != 0) UI_Tag(str8_lit("weak"))
|
if(call_stack.concrete_frames_count != 0) UI_Tag(str8_lit("weak"))
|
||||||
|
|||||||
@@ -525,7 +525,7 @@ rd_title_fstrs_from_ctrl_entity(Arena *arena, CTRL_Entity *entity, B32 include_e
|
|||||||
DI_Scope *di_scope = di_scope_open();
|
DI_Scope *di_scope = di_scope_open();
|
||||||
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(entity, CTRL_EntityKind_Process);
|
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(entity, CTRL_EntityKind_Process);
|
||||||
Arch arch = entity->arch;
|
Arch arch = entity->arch;
|
||||||
CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, entity, ctrl_handle_match(entity->handle, rd_base_regs()->thread), 0);
|
CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, &d_state->ctrl_entity_store->ctx, entity, ctrl_handle_match(entity->handle, rd_base_regs()->thread), 0);
|
||||||
for(U64 idx = 0, limit = 6; idx < call_stack.frames_count && idx < limit; idx += 1)
|
for(U64 idx = 0, limit = 6; idx < call_stack.frames_count && idx < limit; idx += 1)
|
||||||
{
|
{
|
||||||
CTRL_CallStackFrame *f = &call_stack.frames[call_stack.frames_count - 1 - idx];
|
CTRL_CallStackFrame *f = &call_stack.frames[call_stack.frames_count - 1 - idx];
|
||||||
|
|||||||
Reference in New Issue
Block a user