From fb9824dc241d221d2595aabbbad3e1f34bfb7af0 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 14 Jun 2024 07:57:46 -0700 Subject: [PATCH 01/24] remove unnecessary ctrl log flushes, which seriously bloated the ctrl thread running path --- project.4coder | 2 +- src/ctrl/ctrl_core.c | 223 +++++++++++++++-------------- src/demon/win32/demon_core_win32.c | 6 +- src/render/d3d11/render_d3d11.c | 35 +++-- 4 files changed, 145 insertions(+), 121 deletions(-) diff --git a/project.4coder b/project.4coder index f6eaee9e..b4cbff1c 100644 --- a/project.4coder +++ b/project.4coder @@ -48,7 +48,7 @@ commands = .rjf_f1 = { //.win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main.rdi && rdi_dump mule_main.rdi > mule_main.dump && popd", - .win = "build raddbg telemetry", + .win = "build raddbg telemetry release", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 6189dac8..2f04dbb4 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -3368,7 +3368,7 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, DMN_EventNode *next_event_node = ctrl_state->first_dmn_event_node; // rjf: log event - if(next_event_node != 0) CTRL_CtrlThreadLogScope + if(next_event_node != 0) { DMN_Event *ev = &next_event_node->v; log_infof("--- event ---\n"); @@ -3532,9 +3532,9 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, // rjf: run for new events ProfScope("run for new events") { - CTRL_CtrlThreadLogScope log_infof("{dmn_ctrl_run ..."); + log_infof("{dmn_ctrl_run ..."); DMN_EventList events = dmn_ctrl_run(scratch.arena, ctrl_ctx, run_ctrls); - CTRL_CtrlThreadLogScope log_infof("}\n"); + log_infof("}\n"); for(DMN_EventNode *src_n = events.first; src_n != 0; src_n = src_n->next) { DMN_EventNode *dst_n = ctrl_state->free_dmn_event_node; @@ -4184,7 +4184,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) B32 hard_stop = 0; CTRL_EventCause hard_stop_cause = ctrl_event_cause_from_dmn_event_kind(event->kind); B32 use_stepping_logic = 0; - CTRL_CtrlThreadLogScope switch(event->kind) + switch(event->kind) { default:{}break; case DMN_EventKind_Error: @@ -4501,120 +4501,123 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) B32 hit_trap_net_bp = 0; B32 hit_conditional_bp_but_filtered = 0; CTRL_TrapFlags hit_trap_flags = 0; - if(!hard_stop && use_stepping_logic) CTRL_CtrlThreadLogScope + if(!hard_stop && use_stepping_logic && event->kind == DMN_EventKind_Breakpoint) + ProfScope("for breakpoint events, gather bp info") { - if(event->kind == DMN_EventKind_Breakpoint) + Temp temp = temp_begin(scratch.arena); + String8List conditions = {0}; + + // rjf: entry breakpoints + for(DMN_TrapChunkNode *n = entry_traps.first; n != 0; n = n->next) { - Temp temp = temp_begin(scratch.arena); - String8List conditions = {0}; - - // rjf: entry breakpoints - for(DMN_TrapChunkNode *n = entry_traps.first; n != 0; n = n->next) + DMN_Trap *trap = n->v; + DMN_Trap *opl = n->v + n->count; + for(;trap < opl; trap += 1) { - DMN_Trap *trap = n->v; - DMN_Trap *opl = n->v + n->count; - for(;trap < opl; trap += 1) + if(dmn_handle_match(trap->process, event->process) && trap->vaddr == event->instruction_pointer) { - if(dmn_handle_match(trap->process, event->process) && trap->vaddr == event->instruction_pointer) + hit_entry = 1; + } + } + } + + // rjf: user breakpoints + for(DMN_TrapChunkNode *n = user_traps.first; n != 0; n = n->next) + { + DMN_Trap *trap = n->v; + DMN_Trap *opl = n->v + n->count; + for(;trap < opl; trap += 1) + { + if(dmn_handle_match(trap->process, event->process) && + trap->vaddr == event->instruction_pointer && + (!dmn_handle_match(event->thread, target_thread) || !target_thread_is_on_user_bp_and_trap_net_trap)) + { + CTRL_UserBreakpoint *user_bp = (CTRL_UserBreakpoint *)trap->id; + hit_user_bp = 1; + if(user_bp != 0 && user_bp->condition.size != 0) { - hit_entry = 1; + str8_list_push(temp.arena, &conditions, user_bp->condition); } } } - - // rjf: user breakpoints - for(DMN_TrapChunkNode *n = user_traps.first; n != 0; n = n->next) + } + + // rjf: evaluate hit stop conditions + if(conditions.node_count != 0) ProfScope("evaluate hit stop conditions") + { + DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp}; + RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, max_U64); + for(String8Node *condition_n = conditions.first; condition_n != 0; condition_n = condition_n->next) { - DMN_Trap *trap = n->v; - DMN_Trap *opl = n->v + n->count; - for(;trap < opl; trap += 1) + ProfBegin("compile expression"); + String8 string = condition_n->string; + EVAL_ParseCtx parse_ctx = zero_struct; { - if(dmn_handle_match(trap->process, event->process) && - trap->vaddr == event->instruction_pointer && - (!dmn_handle_match(event->thread, target_thread) || !target_thread_is_on_user_bp_and_trap_net_trap)) - { - CTRL_UserBreakpoint *user_bp = (CTRL_UserBreakpoint *)trap->id; - hit_user_bp = 1; - if(user_bp != 0 && user_bp->condition.size != 0) - { - str8_list_push(temp.arena, &conditions, user_bp->condition); - } - } + parse_ctx.arch = arch; + parse_ctx.ip_voff = thread_rip_voff; + parse_ctx.rdi = rdi; + parse_ctx.type_graph = tg_graph_begin(bit_size_from_arch(arch)/8, 256); + parse_ctx.regs_map = ctrl_string2reg_from_arch(arch); + parse_ctx.reg_alias_map = ctrl_string2alias_from_arch(arch); + parse_ctx.locals_map = eval_push_locals_map_from_rdi_voff(temp.arena, rdi, thread_rip_voff); + parse_ctx.member_map = eval_push_member_map_from_rdi_voff(temp.arena, rdi, thread_rip_voff); + } + EVAL_TokenArray tokens = eval_token_array_from_text(temp.arena, string); + EVAL_ParseResult parse = eval_parse_expr_from_text_tokens(temp.arena, &parse_ctx, string, &tokens); + EVAL_ErrorList errors = parse.errors; + B32 parse_has_expr = (parse.expr != &eval_expr_nil); + B32 parse_is_type = (parse_has_expr && parse.expr->kind == EVAL_ExprKind_TypeIdent); + EVAL_IRTreeAndType ir_tree_and_type = {&eval_irtree_nil}; + if(parse_has_expr && errors.count == 0) + { + ir_tree_and_type = eval_irtree_and_type_from_expr(temp.arena, parse_ctx.type_graph, rdi, &eval_string2expr_map_nil, parse.expr, &errors); + } + EVAL_OpList op_list = {0}; + if(parse_has_expr && ir_tree_and_type.tree != &eval_irtree_nil) + { + eval_oplist_from_irtree(scratch.arena, ir_tree_and_type.tree, &op_list); + } + String8 bytecode = {0}; + if(parse_has_expr && parse_is_type == 0 && op_list.encoded_size != 0) + { + bytecode = eval_bytecode_from_oplist(scratch.arena, &op_list); + } + ProfEnd(); + EVAL_Result eval = {0}; + if(bytecode.size != 0) ProfScope("evaluate expression") + { + U64 module_base = module->vaddr_range.min; + U64 tls_base = dmn_tls_root_vaddr_from_thread(event->thread); + EVAL_Machine machine = {0}; + machine.u = &event->process; + machine.arch = arch; + machine.memory_read = ctrl_eval_memory_read; + machine.reg_size = regs_block_size_from_architecture(arch); + machine.reg_data = push_array(scratch.arena, U8, machine.reg_size); + machine.module_base = &module_base; + machine.tls_base = &tls_base; + dmn_thread_read_reg_block(event->thread, machine.reg_data); + eval = eval_interpret(&machine, bytecode); + } + if(eval.code == EVAL_ResultCode_Good && eval.value.u64 == 0) + { + hit_user_bp = 0; + hit_conditional_bp_but_filtered = 1; + log_infof(">>> stepping >>> conditional breakpoint hit, but condition eval'd to 0, and so filtered\n"); + } + else + { + hit_user_bp = 1; + hit_conditional_bp_but_filtered = 0; + log_infof(">>> stepping >>> conditional breakpoint hit\n"); + break; } } - - // rjf: evaluate hit stop conditions - if(conditions.node_count != 0) - { - DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp}; - RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, max_U64); - for(String8Node *condition_n = conditions.first; condition_n != 0; condition_n = condition_n->next) - { - String8 string = condition_n->string; - EVAL_ParseCtx parse_ctx = zero_struct; - { - parse_ctx.arch = arch; - parse_ctx.ip_voff = thread_rip_voff; - parse_ctx.rdi = rdi; - parse_ctx.type_graph = tg_graph_begin(bit_size_from_arch(arch)/8, 256); - parse_ctx.regs_map = ctrl_string2reg_from_arch(arch); - parse_ctx.reg_alias_map = ctrl_string2alias_from_arch(arch); - parse_ctx.locals_map = eval_push_locals_map_from_rdi_voff(temp.arena, rdi, thread_rip_voff); - parse_ctx.member_map = eval_push_member_map_from_rdi_voff(temp.arena, rdi, thread_rip_voff); - } - EVAL_TokenArray tokens = eval_token_array_from_text(temp.arena, string); - EVAL_ParseResult parse = eval_parse_expr_from_text_tokens(temp.arena, &parse_ctx, string, &tokens); - EVAL_ErrorList errors = parse.errors; - B32 parse_has_expr = (parse.expr != &eval_expr_nil); - B32 parse_is_type = (parse_has_expr && parse.expr->kind == EVAL_ExprKind_TypeIdent); - EVAL_IRTreeAndType ir_tree_and_type = {&eval_irtree_nil}; - if(parse_has_expr && errors.count == 0) - { - ir_tree_and_type = eval_irtree_and_type_from_expr(temp.arena, parse_ctx.type_graph, rdi, &eval_string2expr_map_nil, parse.expr, &errors); - } - EVAL_OpList op_list = {0}; - if(parse_has_expr && ir_tree_and_type.tree != &eval_irtree_nil) - { - eval_oplist_from_irtree(scratch.arena, ir_tree_and_type.tree, &op_list); - } - String8 bytecode = {0}; - if(parse_has_expr && parse_is_type == 0 && op_list.encoded_size != 0) - { - bytecode = eval_bytecode_from_oplist(scratch.arena, &op_list); - } - EVAL_Result eval = {0}; - if(bytecode.size != 0) - { - U64 module_base = module->vaddr_range.min; - U64 tls_base = dmn_tls_root_vaddr_from_thread(event->thread); - EVAL_Machine machine = {0}; - machine.u = &event->process; - machine.arch = arch; - machine.memory_read = ctrl_eval_memory_read; - machine.reg_size = regs_block_size_from_architecture(arch); - machine.reg_data = push_array(scratch.arena, U8, machine.reg_size); - machine.module_base = &module_base; - machine.tls_base = &tls_base; - dmn_thread_read_reg_block(event->thread, machine.reg_data); - eval = eval_interpret(&machine, bytecode); - } - if(eval.code == EVAL_ResultCode_Good && eval.value.u64 == 0) - { - hit_user_bp = 0; - hit_conditional_bp_but_filtered = 1; - log_infof(">>> stepping >>> conditional breakpoint hit, but condition eval'd to 0, and so filtered\n"); - } - else - { - hit_user_bp = 1; - hit_conditional_bp_but_filtered = 0; - log_infof(">>> stepping >>> conditional breakpoint hit\n"); - break; - } - } - } - - // rjf: gather trap net hits + } + + // rjf: gather trap net hits + ProfScope("gather trap net hits") + { if(!hit_user_bp && dmn_handle_match(event->process, target_process)) { for(CTRL_TrapNode *node = msg->traps.first; @@ -4628,11 +4631,11 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) } } } - - log_infof(">>> stepping >>> stepping logic - BP event -> hit_user_bp: %i\n", hit_user_bp); - log_infof(">>> stepping >>> stepping logic - BP event -> hit_entry: %i\n", hit_entry); - temp_end(temp); } + + log_infof(">>> stepping >>> stepping logic - BP event -> hit_user_bp: %i\n", hit_user_bp); + log_infof(">>> stepping >>> stepping logic - BP event -> hit_entry: %i\n", hit_entry); + temp_end(temp); } //- rjf: hit conditional user bp but filtered -> single step diff --git a/src/demon/win32/demon_core_win32.c b/src/demon/win32/demon_core_win32.c index 9b66a259..a9179885 100644 --- a/src/demon/win32/demon_core_win32.c +++ b/src/demon/win32/demon_core_win32.c @@ -1342,7 +1342,9 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) B32 any_processes_live = dmn_w32_shared->new_process_pending; if(!any_processes_live) { - for(DMN_W32_Entity *process = dmn_w32_shared->entities_base->first; process != &dmn_w32_entity_nil; process = process->next) + for(DMN_W32_Entity *process = dmn_w32_shared->entities_base->first; + process != &dmn_w32_entity_nil; + process = process->next) { if(process->kind == DMN_W32_EntityKind_Process) { @@ -1382,7 +1384,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) ////////////////////////// //- rjf: set 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("set single step bit") { DMN_W32_Entity *thread = dmn_w32_entity_from_handle(ctrls->single_step_thread); Architecture arch = thread->arch; diff --git a/src/render/d3d11/render_d3d11.c b/src/render/d3d11/render_d3d11.c index 50288498..b417243d 100644 --- a/src/render/d3d11/render_d3d11.c +++ b/src/render/d3d11/render_d3d11.c @@ -168,6 +168,7 @@ r_init(CmdLine *cmdln) r_d3d11_state->device_rw_mutex = os_rw_mutex_alloc(); //- rjf: create base device + ProfBegin("create base device"); UINT creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; #if BUILD_DEBUG if(cmd_line_has_flag(cmdln, str8_lit("d3d11_debug"))) @@ -199,7 +200,6 @@ r_init(CmdLine *cmdln) D3D11_SDK_VERSION, &r_d3d11_state->base_device, 0, &r_d3d11_state->base_device_ctx); } - if(FAILED(error)) { char buffer[256] = {0}; @@ -207,10 +207,11 @@ r_init(CmdLine *cmdln) os_graphical_message(1, str8_lit("Fatal Error"), str8_cstring(buffer)); os_exit_process(1); } + ProfEnd(); //- rjf: enable break-on-error #if BUILD_DEBUG - if(cmd_line_has_flag(cmdln, str8_lit("d3d11_debug"))) + if(cmd_line_has_flag(cmdln, str8_lit("d3d11_debug"))) ProfScope("enable break-on-error") { ID3D11InfoQueue *info = 0; error = r_d3d11_state->base_device->lpVtbl->QueryInterface(r_d3d11_state->base_device, &IID_ID3D11InfoQueue, (void **)(&info)); @@ -224,15 +225,20 @@ r_init(CmdLine *cmdln) #endif //- rjf: get main device + ProfBegin("get main device"); error = r_d3d11_state->base_device->lpVtbl->QueryInterface(r_d3d11_state->base_device, &IID_ID3D11Device1, (void **)(&r_d3d11_state->device)); error = r_d3d11_state->base_device_ctx->lpVtbl->QueryInterface(r_d3d11_state->base_device_ctx, &IID_ID3D11DeviceContext1, (void **)(&r_d3d11_state->device_ctx)); + ProfEnd(); //- rjf: get dxgi device/adapter/factory + ProfBegin("get dxgi device/adapter/factory"); error = r_d3d11_state->device->lpVtbl->QueryInterface(r_d3d11_state->device, &IID_IDXGIDevice1, (void **)(&r_d3d11_state->dxgi_device)); error = r_d3d11_state->dxgi_device->lpVtbl->GetAdapter(r_d3d11_state->dxgi_device, &r_d3d11_state->dxgi_adapter); error = r_d3d11_state->dxgi_adapter->lpVtbl->GetParent(r_d3d11_state->dxgi_adapter, &IID_IDXGIFactory2, (void **)(&r_d3d11_state->dxgi_factory)); + ProfEnd(); //- rjf: create main rasterizer + ProfScope("create main rasterizer") { D3D11_RASTERIZER_DESC1 desc = {D3D11_FILL_SOLID}; { @@ -244,6 +250,7 @@ r_init(CmdLine *cmdln) } //- rjf: create main blend state + ProfScope("create main blend state") { D3D11_BLEND_DESC desc = {0}; { @@ -259,6 +266,8 @@ r_init(CmdLine *cmdln) error = r_d3d11_state->device->lpVtbl->CreateBlendState(r_d3d11_state->device, &desc, &r_d3d11_state->main_blend_state); } + //- rjf: create empty blend state + ProfScope("create empty blend state") { D3D11_BLEND_DESC desc = {0}; { @@ -269,6 +278,7 @@ r_init(CmdLine *cmdln) } //- rjf: create nearest-neighbor sampler + ProfScope("create nearest-neighbor sampler") { D3D11_SAMPLER_DESC desc = zero_struct; { @@ -282,6 +292,7 @@ r_init(CmdLine *cmdln) } //- rjf: create bilinear sampler + ProfScope("create bilinear sampler") { D3D11_SAMPLER_DESC desc = zero_struct; { @@ -295,6 +306,7 @@ r_init(CmdLine *cmdln) } //- rjf: create noop depth/stencil state + ProfScope("create noop depth/stencil state") { D3D11_DEPTH_STENCIL_DESC desc = {0}; { @@ -306,6 +318,7 @@ r_init(CmdLine *cmdln) } //- rjf: create plain depth/stencil state + ProfScope("create plain depth/stencil state") { D3D11_DEPTH_STENCIL_DESC desc = {0}; { @@ -317,6 +330,7 @@ r_init(CmdLine *cmdln) } //- rjf: create buffers + ProfScope("create buffers") { D3D11_BUFFER_DESC desc = {0}; { @@ -329,9 +343,10 @@ r_init(CmdLine *cmdln) } //- rjf: build vertex shaders & input layouts - for(R_D3D11_VShadKind kind = (R_D3D11_VShadKind)0; - kind < R_D3D11_VShadKind_COUNT; - kind = (R_D3D11_VShadKind)(kind+1)) + ProfScope("build vertex shaders & input layouts") + for(R_D3D11_VShadKind kind = (R_D3D11_VShadKind)0; + kind < R_D3D11_VShadKind_COUNT; + kind = (R_D3D11_VShadKind)(kind+1)) { String8 source = *r_d3d11_g_vshad_kind_source_table[kind]; String8 source_name = r_d3d11_g_vshad_kind_source_name_table[kind]; @@ -342,6 +357,7 @@ r_init(CmdLine *cmdln) ID3DBlob *vshad_source_blob = 0; ID3DBlob *vshad_source_errors = 0; ID3D11VertexShader *vshad = 0; + ProfScope("compile vertex shader") { error = D3DCompile(source.str, source.size, @@ -396,6 +412,7 @@ r_init(CmdLine *cmdln) ID3DBlob *pshad_source_blob = 0; ID3DBlob *pshad_source_errors = 0; ID3D11PixelShader *pshad = 0; + ProfScope("compile pixel shader") { error = D3DCompile(source.str, source.size, @@ -428,9 +445,10 @@ r_init(CmdLine *cmdln) } //- rjf: build uniform type buffers - for(R_D3D11_UniformTypeKind kind = (R_D3D11_UniformTypeKind)0; - kind < R_D3D11_UniformTypeKind_COUNT; - kind = (R_D3D11_UniformTypeKind)(kind+1)) + ProfScope("build uniform type buffers") + for(R_D3D11_UniformTypeKind kind = (R_D3D11_UniformTypeKind)0; + kind < R_D3D11_UniformTypeKind_COUNT; + kind = (R_D3D11_UniformTypeKind)(kind+1)) { ID3D11Buffer *buffer = 0; { @@ -449,6 +467,7 @@ r_init(CmdLine *cmdln) } //- rjf: create backup texture + ProfScope("create backup texture") { U32 backup_texture_data[] = { From 723c7c5d4dc00770a6b0205bafade79eed3e7051 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 14 Jun 2024 09:50:33 -0700 Subject: [PATCH 02/24] further tightening up of win32 demon run path; take a few fastpaths on x64; speeds up conditional breakpoints --- src/ctrl/ctrl_core.c | 32 +++++--- src/ctrl/ctrl_core.h | 1 + src/demon/win32/demon_core_win32.c | 122 ++++++++++++++++++++++++----- src/demon/win32/demon_core_win32.h | 10 +-- 4 files changed, 130 insertions(+), 35 deletions(-) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 2f04dbb4..33a24e57 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -1524,6 +1524,18 @@ ctrl_query_cached_rip_from_thread(CTRL_EntityStore *store, CTRL_MachineID machin return result; } +internal U64 +ctrl_query_cached_rsp_from_thread(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread) +{ + Temp scratch = scratch_begin(0, 0); + CTRL_Entity *thread_entity = ctrl_entity_from_machine_id_handle(store, machine_id, thread); + Architecture arch = thread_entity->arch; + void *block = ctrl_query_cached_reg_block_from_thread(scratch.arena, store, machine_id, thread); + U64 result = regs_rsp_from_arch_block(arch, block); + scratch_end(scratch); + return result; +} + //- rjf: thread register writing internal B32 @@ -3567,13 +3579,12 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, { CTRL_Entity *thread = ctrl_entity_from_machine_id_handle(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, spoof->thread); Architecture arch = thread->arch; - void *regs_block = push_array(scratch.arena, U8, regs_block_size_from_architecture(arch)); - dmn_thread_read_reg_block(spoof->thread, regs_block); + void *regs_block = ctrl_query_cached_reg_block_from_thread(scratch.arena, ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, spoof->thread); U64 spoof_thread_rip = regs_rip_from_arch_block(arch, regs_block); if(spoof_thread_rip == spoof->new_ip_value) { regs_arch_block_write_rip(arch, regs_block, spoof_old_ip_value); - dmn_thread_write_reg_block(spoof->thread, regs_block); + ctrl_thread_write_reg_block(CTRL_MachineID_Local, spoof->thread, regs_block); } } @@ -3983,7 +3994,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) // threads, because otherwise, their stack pointer may change, if single-stepping // causes e.g. entrance into a function via a call instruction. // - U64 sp_check_value = dmn_rsp_from_thread(target_thread); + U64 sp_check_value = ctrl_query_cached_rsp_from_thread(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, target_thread); ////////////////////////////// //- rjf: single step "stuck threads" @@ -4012,7 +4023,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) if(process->kind != CTRL_EntityKind_Process) { continue; } for(CTRL_Entity *thread = process->first; thread != &ctrl_entity_nil; thread = thread->next) { - U64 rip = dmn_rip_from_thread(thread->handle); + U64 rip = ctrl_query_cached_rip_from_thread(ctrl_state->ctrl_thread_entity_store, thread->machine_id, thread->handle); // rjf: determine if thread is frozen B32 thread_is_frozen = !msg->freeze_state_is_frozen; @@ -4432,7 +4443,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) // CTRL_Entity *thread = ctrl_entity_from_machine_id_handle(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, event->thread); Architecture arch = thread->arch; - U64 thread_rip_vaddr = dmn_rip_from_thread(event->thread); + U64 thread_rip_vaddr = ctrl_query_cached_rip_from_thread(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, event->thread); CTRL_Entity *module = &ctrl_entity_nil; { CTRL_Entity *process = ctrl_entity_from_machine_id_handle(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, event->process); @@ -4593,10 +4604,9 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) machine.arch = arch; machine.memory_read = ctrl_eval_memory_read; machine.reg_size = regs_block_size_from_architecture(arch); - machine.reg_data = push_array(scratch.arena, U8, machine.reg_size); + machine.reg_data = ctrl_query_cached_reg_block_from_thread(scratch.arena, ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, event->thread); machine.module_base = &module_base; machine.tls_base = &tls_base; - dmn_thread_read_reg_block(event->thread, machine.reg_data); eval = eval_interpret(&machine, bytecode); } if(eval.code == EVAL_ResultCode_Good && eval.value.u64 == 0) @@ -4711,7 +4721,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) B32 stack_pointer_matches = 0; if(use_trap_net_logic) { - U64 sp = dmn_rsp_from_thread(target_thread); + U64 sp = ctrl_query_cached_rsp_from_thread(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, target_thread); stack_pointer_matches = (sp == sp_check_value); } @@ -4759,7 +4769,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { // rjf: setup spoof mode begin_spoof_mode = 1; - U64 spoof_sp = dmn_rsp_from_thread(target_thread); + U64 spoof_sp = ctrl_query_cached_rsp_from_thread(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, target_thread); spoof_mode = 1; spoof.process = target_process; spoof.thread = target_thread; @@ -4777,7 +4787,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) if(stack_pointer_matches) { save_stack_pointer = 1; - sp_check_value = dmn_rsp_from_thread(target_thread); + sp_check_value = ctrl_query_cached_rsp_from_thread(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, target_thread); } } } diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index a5ad6540..40787d1e 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -743,6 +743,7 @@ internal B32 ctrl_process_write(CTRL_MachineID machine_id, DMN_Handle process, R internal void *ctrl_query_cached_reg_block_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread); internal U64 ctrl_query_cached_tls_root_vaddr_from_thread(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread); internal U64 ctrl_query_cached_rip_from_thread(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread); +internal U64 ctrl_query_cached_rsp_from_thread(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread); //- rjf: thread register writing internal B32 ctrl_thread_write_reg_block(CTRL_MachineID machine_id, DMN_Handle thread, void *block); diff --git a/src/demon/win32/demon_core_win32.c b/src/demon/win32/demon_core_win32.c index a9179885..1d865093 100644 --- a/src/demon/win32/demon_core_win32.c +++ b/src/demon/win32/demon_core_win32.c @@ -580,6 +580,7 @@ internal B32 dmn_w32_thread_read_reg_block(Architecture arch, HANDLE thread, void *reg_block) { B32 result = 0; + ProfBeginFunction(); switch(arch) { //////////////////////////// @@ -817,6 +818,7 @@ dmn_w32_thread_read_reg_block(Architecture arch, HANDLE thread, void *reg_block) scratch_end(scratch); }break; } + ProfEnd(); return result; } @@ -824,6 +826,7 @@ internal B32 dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block) { B32 result = 0; + ProfBeginFunction(); switch(arch) { //////////////////////////// @@ -1050,6 +1053,7 @@ dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block }break; } ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen); + ProfEnd(); return result; } @@ -1381,6 +1385,34 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) { Temp scratch = scratch_begin(&arena, 1); + ////////////////////////// + //- rjf: get single step thread's context (x64 single-step-set fast path) + // + CONTEXT *single_step_thread_ctx = 0; + if(!dmn_handle_match(ctrls->single_step_thread, dmn_handle_zero())) + { + DMN_W32_Entity *thread = dmn_w32_entity_from_handle(ctrls->single_step_thread); + Architecture arch = thread->arch; + switch(arch) + { + default:{}break; + case Architecture_x64: + { + U32 ctx_flags = DMN_W32_CTX_X64|DMN_W32_CTX_INTEL_CONTROL; + DWORD size = 0; + InitializeContext(0, ctx_flags, 0, &size); + if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + void *ctx_memory = push_array(scratch.arena, U8, size); + if(!InitializeContext(ctx_memory, ctx_flags, &single_step_thread_ctx, &size)) + { + single_step_thread_ctx = 0; + } + } + }break; + } + } + ////////////////////////// //- rjf: set single step bit // @@ -1398,7 +1430,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) case Architecture_arm32: {NotImplemented;}break; - //- rjf: x86/64 + //- rjf: x86 case Architecture_x86: { REGS_RegBlockX86 regs = {0}; @@ -1406,12 +1438,22 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) regs.eflags.u32 |= 0x100; dmn_thread_write_reg_block(ctrls->single_step_thread, ®s); }break; + + //- rjf: x64 case Architecture_x64: { - REGS_RegBlockX64 regs = {0}; - dmn_thread_read_reg_block(ctrls->single_step_thread, ®s); - regs.rflags.u64 |= 0x100; - dmn_thread_write_reg_block(ctrls->single_step_thread, ®s); + if(!GetThreadContext(thread->handle, single_step_thread_ctx)) + { + single_step_thread_ctx = 0; + } + if(single_step_thread_ctx != 0) + { + U64 rflags = single_step_thread_ctx->EFlags|0x2; + U64 new_rflags = rflags |= 0x100; + single_step_thread_ctx->EFlags = new_rflags; + SetThreadContext(thread->handle, single_step_thread_ctx); + ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen); + } }break; } } @@ -1983,19 +2025,53 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) B32 should_do_rollback = (hit_user_trap || (is_trap && !hit_explicit_trap)); //- rjf: roll back thread's instruction pointer - U64 post_trap_rip = 0; - if(should_do_rollback) + if(should_do_rollback) ProfScope("roll back thread's instruction pointer") { - Temp temp = temp_begin(scratch.arena); - U64 regs_block_size = regs_block_size_from_architecture(thread->arch); - void *regs_block = push_array(scratch.arena, U8, regs_block_size); - if(dmn_w32_thread_read_reg_block(thread->arch, thread->handle, regs_block)) + switch(thread->arch) { - post_trap_rip = regs_rip_from_arch_block(thread->arch, regs_block); - regs_arch_block_write_rip(thread->arch, regs_block, instruction_pointer); - dmn_w32_thread_write_reg_block(thread->arch, thread->handle, regs_block); + //- rjf: default, general path + default: + { + Temp temp = temp_begin(scratch.arena); + U64 regs_block_size = regs_block_size_from_architecture(thread->arch); + void *regs_block = push_array(scratch.arena, U8, regs_block_size); + if(dmn_w32_thread_read_reg_block(thread->arch, thread->handle, regs_block)) + { + regs_arch_block_write_rip(thread->arch, regs_block, instruction_pointer); + dmn_w32_thread_write_reg_block(thread->arch, thread->handle, regs_block); + } + temp_end(temp); + }break; + + //- rjf: x64 (fastpath) + case Architecture_x64: + { + CONTEXT *ctx = 0; + U32 ctx_flags = DMN_W32_CTX_X64|DMN_W32_CTX_INTEL_CONTROL; + DWORD size = 0; + InitializeContext(0, ctx_flags, 0, &size); + if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + void *ctx_memory = push_array(scratch.arena, U8, size); + if(!InitializeContext(ctx_memory, ctx_flags, &ctx, &size)) + { + ctx = 0; + } + } + if(!GetThreadContext(thread->handle, ctx)) + { + ctx = 0; + } + if(ctx != 0) + { + U64 rip = ctx->Rip; + U64 new_rip = instruction_pointer; + ctx->Rip = new_rip; + SetThreadContext(thread->handle, ctx); + ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen); + } + }break; } - temp_end(temp); } //- rjf: not a user trap, not an explicit trap, then it's a trap that @@ -2347,10 +2423,18 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) }break; case Architecture_x64: { - REGS_RegBlockX64 regs = {0}; - dmn_thread_read_reg_block(ctrls->single_step_thread, ®s); - regs.rflags.u64 &= ~0x100; - dmn_thread_write_reg_block(ctrls->single_step_thread, ®s); + if(!GetThreadContext(thread->handle, single_step_thread_ctx)) + { + single_step_thread_ctx = 0; + } + if(ctx != 0) + { + U64 rflags = single_step_thread_ctx->EFlags|0x2; + U64 new_rflags = rflags &= ~0x100; + single_step_thread_ctx->EFlags = new_rflags; + SetThreadContext(thread->handle, single_step_thread_ctx); + ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen); + } }break; } } diff --git a/src/demon/win32/demon_core_win32.h b/src/demon/win32/demon_core_win32.h index 285f86be..04c955c8 100644 --- a/src/demon/win32/demon_core_win32.h +++ b/src/demon/win32/demon_core_win32.h @@ -61,11 +61,11 @@ #define DMN_W32_CTX_X86 0x00010000 #define DMN_W32_CTX_X64 0x00100000 -#define DMN_W32_CTX_INTEL_CONTROL 0x0001 -#define DMN_W32_CTX_INTEL_INTEGER 0x0002 -#define DMN_W32_CTX_INTEL_SEGMENTS 0x0004 -#define DMN_W32_CTX_INTEL_FLOATS 0x0008 -#define DMN_W32_CTX_INTEL_DEBUG 0x0010 +#define DMN_W32_CTX_INTEL_CONTROL 0x0001 // segss, rsp, segcs, rip, and rflags +#define DMN_W32_CTX_INTEL_INTEGER 0x0002 // rax, rcx, rdx, rbx, rbp, rsi, rdi, and r8-r15 +#define DMN_W32_CTX_INTEL_SEGMENTS 0x0004 // segds, seges, segfs, and seggs +#define DMN_W32_CTX_INTEL_FLOATS 0x0008 // xmm0-xmm15 +#define DMN_W32_CTX_INTEL_DEBUG 0x0010 // dr0-dr3 and dr6-dr7 #define DMN_W32_CTX_INTEL_EXTENDED 0x0020 #define DMN_W32_CTX_INTEL_XSTATE 0x0040 From 794f2125014fc409d64891c9ff905b1d6c75ad1d Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 14 Jun 2024 14:17:26 -0700 Subject: [PATCH 03/24] dasm address consistency --- project.4coder | 2 +- src/dasm_cache/dasm_cache.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/project.4coder b/project.4coder index b4cbff1c..f6eaee9e 100644 --- a/project.4coder +++ b/project.4coder @@ -48,7 +48,7 @@ commands = .rjf_f1 = { //.win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main.rdi && rdi_dump mule_main.rdi > mule_main.dump && popd", - .win = "build raddbg telemetry release", + .win = "build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/dasm_cache/dasm_cache.c b/src/dasm_cache/dasm_cache.c index ae248831..54d89aba 100644 --- a/src/dasm_cache/dasm_cache.c +++ b/src/dasm_cache/dasm_cache.c @@ -537,7 +537,7 @@ dasm_parse_thread__entry_point(void *p) String8 addr_part = {0}; if(params.style_flags & DASM_StyleFlag_Addresses) { - addr_part = push_str8f(scratch.arena, "%s%016I64X ", rdi != &di_rdi_parsed_nil ? " " : "", params.vaddr+off); + addr_part = push_str8f(scratch.arena, "%s0x%016I64x ", rdi != &di_rdi_parsed_nil ? " " : "", params.vaddr+off); } String8 code_bytes_part = {0}; if(params.style_flags & DASM_StyleFlag_CodeBytes) From 0b3e3228d1feaa14ca8d4653859d6dc1d1a5c2e1 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 17 Jun 2024 09:34:27 -0700 Subject: [PATCH 04/24] rdi_from_pdb: fix incorrect bounds checks on procedure frameproc lookup for local location info --- src/lib_rdi_format/rdi_format.h | 2 +- src/rdi_format/rdi_format.mdesk | 2 +- src/rdi_from_pdb/rdi_from_pdb.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib_rdi_format/rdi_format.h b/src/lib_rdi_format/rdi_format.h index aba064e5..2924dc49 100644 --- a/src/lib_rdi_format/rdi_format.h +++ b/src/lib_rdi_format/rdi_format.h @@ -52,7 +52,7 @@ typedef int64_t RDI_S64; // \"raddbg\0\0\" #define RDI_MAGIC_CONSTANT 0x0000676264646172 -#define RDI_ENCODING_VERSION 6 +#define RDI_ENCODING_VERSION 7 //////////////////////////////////////////////////////////////// //~ Format Types & Functions diff --git a/src/rdi_format/rdi_format.mdesk b/src/rdi_format/rdi_format.mdesk index bb3931cd..e292a5c6 100644 --- a/src/rdi_format/rdi_format.mdesk +++ b/src/rdi_format/rdi_format.mdesk @@ -62,7 +62,7 @@ ""; "// \"raddbg\0\0\""; "#define RDI_MAGIC_CONSTANT 0x0000676264646172"; - "#define RDI_ENCODING_VERSION 6"; + "#define RDI_ENCODING_VERSION 7"; ""; "////////////////////////////////////////////////////////////////"; "//~ Format Types & Functions"; diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index e0eaa4ca..de944eea 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -2696,7 +2696,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) // rjf: find current procedure's frameproc CV_SymFrameproc *frameproc = 0; - if(procedure_num != 0 && procedure_frameprocs[procedure_num-1] != 0 && procedure_num < procedure_frameprocs_count) + if(procedure_num != 0 && procedure_num <= procedure_frameprocs_count && procedure_frameprocs[procedure_num-1] != 0) { frameproc = procedure_frameprocs[procedure_num-1]; } @@ -2774,7 +2774,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) // rjf: find current procedure's frameproc CV_SymFrameproc *frameproc = 0; - if(procedure_num != 0 && procedure_frameprocs[procedure_num-1] != 0 && procedure_num < procedure_frameprocs_count) + if(procedure_num != 0 && procedure_num <= procedure_frameprocs_count && procedure_frameprocs[procedure_num-1] != 0) { frameproc = procedure_frameprocs[procedure_num-1]; } From 31d7be8f8a25b9ffa4bb4b88dc37e3ae5a10b857 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 17 Jun 2024 09:42:12 -0700 Subject: [PATCH 05/24] tweak snap-to-cursor behavior when dragging --- src/df/gfx/df_views.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 9df21f5b..0bf73db0 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -6254,8 +6254,8 @@ DF_VIEW_UI_FUNCTION_DEF(Code) df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FocusPanel)); } - //- rjf: dragging? -> contain cursor - if(ui_dragging(sig.base) && sig.base.event_flags == 0) + //- rjf: dragging & outside region? -> contain cursor + if(ui_dragging(sig.base) && !contains_2f32(sig.base.box->rect, ui_mouse()) && sig.base.event_flags == 0) { tv->contain_cursor = 1; } @@ -7191,8 +7191,8 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FocusPanel)); } - //- rjf: dragging? -> contain cursor - if(ui_dragging(sig.base) && sig.base.event_flags == 0) + //- rjf: dragging & outside region? -> contain cursor + if(ui_dragging(sig.base) && !contains_2f32(sig.base.box->rect, ui_mouse()) && sig.base.event_flags == 0) { dv->contain_cursor = 1; } @@ -8077,8 +8077,8 @@ DF_VIEW_UI_FUNCTION_DEF(Output) df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FocusPanel)); } - //- rjf: dragging? -> contain cursor - if(ui_dragging(sig.base)) + //- rjf: dragging & outside region? -> contain cursor + if(ui_dragging(sig.base) && !contains_2f32(sig.base.box->rect, ui_mouse()) && sig.base.event_flags == 0) { tv->contain_cursor = 1; } From 3c2c98b08a122491ec29d9c7a0f5f3501dda3d5d Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 17 Jun 2024 10:08:11 -0700 Subject: [PATCH 06/24] rdi_make: fix incorrect line table count calculation --- src/lib_rdi_make/rdi_make.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index f491dd31..e5832efe 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -2861,7 +2861,7 @@ rdim_bake_line_tables(RDIM_Arena *arena, RDIM_LineTableChunkList *src) RDIM_LineTableBakeResult result = {0}; { result.line_tables = dst_line_tables; - result.line_tables_count = src->total_count; + result.line_tables_count = src->total_count+1; result.line_table_voffs = dst_line_voffs; result.line_table_voffs_count = (src->total_line_count + src->total_seq_count); result.line_table_lines = dst_lines; From bc5d0b18887092a0e56022b3db5ea479b1b216f4 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 17 Jun 2024 10:18:41 -0700 Subject: [PATCH 07/24] fix rich hover reset behavior --- src/df/gfx/df_gfx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index 7e9c5994..ee7bfa06 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -13290,6 +13290,8 @@ df_gfx_begin_frame(Arena *arena, DF_CmdList *cmds) arena_clear(df_gfx_state->rich_hover_info_current_arena); MemoryCopyStruct(&df_gfx_state->rich_hover_info_current, &df_gfx_state->rich_hover_info_next); df_gfx_state->rich_hover_info_current.dbgi_key = di_key_copy(df_gfx_state->rich_hover_info_current_arena, &df_gfx_state->rich_hover_info_current.dbgi_key); + arena_clear(df_gfx_state->rich_hover_info_next_arena); + MemoryZeroStruct(&df_gfx_state->rich_hover_info_next); //- rjf: animate confirmation { From 6ad94978ce165f972e647022af05736632bdd8f9 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 17 Jun 2024 10:55:17 -0700 Subject: [PATCH 08/24] correctly adjust dbgi timestamp in ctrl entity store, upon debug info changes --- src/ctrl/ctrl_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 33a24e57..91543a72 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -2893,6 +2893,7 @@ ctrl_thread__entry_point(void *p) di_close(&old_dbgi_key); ctrl_entity_equip_string(ctrl_state->ctrl_thread_entity_store, debug_info_path, path); U64 new_dbgi_timestamp = os_properties_from_file_path(path).modified; + debug_info_path->timestamp = new_dbgi_timestamp; DI_Key new_dbgi_key = {debug_info_path->string, new_dbgi_timestamp}; di_open(&new_dbgi_key); CTRL_EventList evts = {0}; @@ -2901,6 +2902,7 @@ ctrl_thread__entry_point(void *p) evt->machine_id = msg->machine_id; evt->entity = msg->entity; evt->string = path; + evt->timestamp = new_dbgi_timestamp; ctrl_c2u_push_events(&evts); }break; } From 749821dd27c7abb0dd0fc7fb6088e3cf0303268c Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 17 Jun 2024 12:14:10 -0700 Subject: [PATCH 09/24] adjust unwind loop to be robust to noop-unwind-steps that would otherwise result in infinite unwind loops --- src/ctrl/ctrl_core.c | 3 ++- src/df/gfx/df_gfx.mdesk | 10 +++++----- src/raddbg/raddbg.h | 3 +-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 91543a72..96931be3 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -2624,7 +2624,8 @@ ctrl_unwind_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_MachineID ma unwind.flags |= step.flags; if(step.flags & CTRL_UnwindFlag_Error || regs_rsp_from_arch_block(arch, regs_block) == 0 || - regs_rip_from_arch_block(arch, regs_block) == 0) + regs_rip_from_arch_block(arch, regs_block) == 0 || + regs_rip_from_arch_block(arch, regs_block) == rip) { break; } diff --git a/src/df/gfx/df_gfx.mdesk b/src/df/gfx/df_gfx.mdesk index 111f5388..581e6912 100644 --- a/src/df/gfx/df_gfx.mdesk +++ b/src/df/gfx/df_gfx.mdesk @@ -265,10 +265,10 @@ DF_GfxViewRuleTable: } //////////////////////////////// -//~ rjf: Theme Color Codes +//~ rjf: Theme Tables @table(name display_name name_lower) -DF_ThemeTable: +DF_ThemeColorTable: { {Null "Null" null } {PlainText "Plain Text" plain_text } @@ -424,7 +424,7 @@ DF_ThemePresetColorTable: @enum DF_ThemeColor: { - @expand(DF_ThemeTable a) `$(a.name)`, + @expand(DF_ThemeColorTable a) `$(a.name)`, COUNT, } @@ -590,12 +590,12 @@ DF_ThemePresetColorTable: @data(String8) df_g_theme_color_display_string_table: { - @expand(DF_ThemeTable a) `str8_lit_comp("$(a.display_name)")` + @expand(DF_ThemeColorTable a) `str8_lit_comp("$(a.display_name)")` } @data(String8) df_g_theme_color_cfg_string_table: { - @expand(DF_ThemeTable a) `str8_lit_comp("$(a.name_lower)")` + @expand(DF_ThemeColorTable a) `str8_lit_comp("$(a.name_lower)")` } //////////////////////////////// diff --git a/src/raddbg/raddbg.h b/src/raddbg/raddbg.h index cd01b5d0..091623e3 100644 --- a/src/raddbg/raddbg.h +++ b/src/raddbg/raddbg.h @@ -42,8 +42,7 @@ //////////////////////////////// //~ rjf: Hot, High Priority Tasks (Complete Unusability, Crashes, Fire-Worthy) // -// [ ] investigate heavy outputdebugstring usage causing major issues -// (both in debugger and in target application, apparently) +// [ ] asan stepping breakage // [ ] "Browse..." buttons should adopt a more relevant starting search path, // if possible // [ ] PDB files distributed with the build are not found by DbgHelp!!! From d44f098e84c10c42edbcd3462507be751d17c93b Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 17 Jun 2024 13:06:23 -0700 Subject: [PATCH 10/24] disallow override detection with nil overrides --- src/df/core/df_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 37438c21..0d2e330f 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -2322,6 +2322,7 @@ df_possible_overrides_from_entity(Arena *arena, DF_Entity *entity) // rjf: descend tree if needed, by the chain names, find override DF_Entity *override = link_overridden_sibling; + if(!df_entity_is_nil(override)) { DF_Entity *parent = override; for(String8Node *path_part_n = p_chain_names_to_entity.first; From 6cc1dfb39a8962a80a50ccd2acb58c7a13d2a066 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 18 Jun 2024 10:14:54 -0700 Subject: [PATCH 11/24] trap net generation logging; log markers --- src/ctrl/ctrl_core.c | 24 ++++++--------- src/ctrl/ctrl_core.h | 2 +- src/df/core/df_core.c | 46 ++++++++++++++++++++++++++-- src/df/core/df_core.h | 2 +- src/df/core/df_core.mdesk | 1 + src/df/core/generated/df_core.meta.c | 3 +- src/df/core/generated/df_core.meta.h | 1 + src/df/gfx/df_gfx.mdesk | 3 ++ src/df/gfx/generated/df_gfx.meta.c | 3 +- src/df/gfx/generated/df_gfx.meta.h | 2 +- 10 files changed, 64 insertions(+), 23 deletions(-) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 96931be3..b6b39e78 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -3319,7 +3319,7 @@ ctrl_thread__module_open(CTRL_MachineID machine_id, DMN_Handle process, DMN_Hand } internal void -ctrl_thread__module_close(CTRL_MachineID machine_id, DMN_Handle module, String8 path) +ctrl_thread__module_close(CTRL_MachineID machine_id, DMN_Handle module) { ////////////////////////////// //- rjf: evict module image info from cache @@ -3348,19 +3348,6 @@ ctrl_thread__module_close(CTRL_MachineID machine_id, DMN_Handle module, String8 } } } - - ////////////////////////////// - //- rjf: close debug info - // - { - CTRL_Entity *module_ent = ctrl_entity_from_machine_id_handle(ctrl_state->ctrl_thread_entity_store, machine_id, module); - CTRL_Entity *debug_info_path_ent = ctrl_entity_child_from_kind(module_ent, CTRL_EntityKind_DebugInfoPath); - if(debug_info_path_ent != &ctrl_entity_nil) - { - DI_Key dbgi_key = {debug_info_path_ent->string, debug_info_path_ent->timestamp}; - di_close(&dbgi_key); - } - } } //- rjf: attached process running/event gathering @@ -3675,12 +3662,19 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, { CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); String8 module_path = event->string; - ctrl_thread__module_close(CTRL_MachineID_Local, event->module, module_path); + ctrl_thread__module_close(CTRL_MachineID_Local, event->module); out_evt->kind = CTRL_EventKind_EndModule; out_evt->msg_id = msg->msg_id; out_evt->machine_id = CTRL_MachineID_Local; out_evt->entity = event->module; out_evt->string = module_path; + CTRL_Entity *module_ent = ctrl_entity_from_machine_id_handle(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, event->module); + CTRL_Entity *debug_info_path_ent = ctrl_entity_child_from_kind(module_ent, CTRL_EntityKind_DebugInfoPath); + if(debug_info_path_ent != &ctrl_entity_nil) + { + DI_Key dbgi_key = {debug_info_path_ent->string, debug_info_path_ent->timestamp}; + di_close(&dbgi_key); + } }break; case DMN_EventKind_DebugString: { diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index 40787d1e..758cdbf3 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -810,7 +810,7 @@ internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, C //- rjf: module lifetime open/close work internal void ctrl_thread__module_open(CTRL_MachineID machine_id, DMN_Handle process, DMN_Handle module, Rng1U64 vaddr_range, String8 path); -internal void ctrl_thread__module_close(CTRL_MachineID machine_id, DMN_Handle module, String8 path); +internal void ctrl_thread__module_close(CTRL_MachineID machine_id, DMN_Handle module); //- rjf: attached process running/event gathering internal DMN_Event *ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, DMN_RunCtrls *run_ctrls, CTRL_Spoof *spoof); diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 0d2e330f..9530fe96 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -879,7 +879,7 @@ df_ctrl_flow_info_from_vaddr_code__x64(Arena *arena, DF_InstFlags exit_points_ma point.jump_dest_vaddr = (U64)(point.vaddr + (S64)((S32)inst.rel_voff)); } DF_CtrlFlowPointNode *node = push_array(arena, DF_CtrlFlowPointNode, 1); - node->point = point; + node->v = point; SLLQueuePush(info.exit_points.first, info.exit_points.last, node); info.exit_points.count += 1; } @@ -2851,6 +2851,7 @@ internal CTRL_TrapList df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) { Temp scratch = scratch_begin(&arena, 1); + log_infof("step_over_line:\n{\n"); CTRL_TrapList result = {0}; // rjf: thread => info @@ -2859,6 +2860,8 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) DI_Key dbgi_key = df_dbgi_key_from_module(module); Architecture arch = df_architecture_from_entity(thread); U64 ip_vaddr = ctrl_query_cached_rip_from_thread(df_state->ctrl_entity_store, thread->ctrl_machine_id, thread->ctrl_handle); + log_infof(" ip_vaddr: 0x%I64x\n", ip_vaddr); + log_infof(" dbgi_key: {%S, 0x%I64x}\n", dbgi_key.path, dbgi_key.min_timestamp); // rjf: ip => line vaddr range Rng1U64 line_vaddr_rng = {0}; @@ -2870,6 +2873,8 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) { line_vaddr_rng = df_vaddr_range_from_voff_range(module, line_voff_rng); } + log_infof(" line: {%S:%I64i}\n", line_info.file->name, line_info.pt.line); + log_infof(" voff_range: {0x%I64x, 0x%I64x}\n", line_info.voff_range.min, line_info.voff_range.max); } // rjf: opl line_vaddr_rng -> 0xf00f00 or 0xfeefee? => include in line vaddr range @@ -2894,6 +2899,25 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) { CTRL_ProcessMemorySlice machine_code_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, line_vaddr_rng, os_now_microseconds()+50000); machine_code = machine_code_slice.data; + log_infof(" machine_code_slice:\n {\n"); + log_infof(" stale: %i\n", machine_code_slice.stale); + log_infof(" any_byte_bad: %i\n", machine_code_slice.any_byte_bad); + log_infof(" any_byte_changed: %i\n", machine_code_slice.any_byte_changed); + log_infof(" [\n"); + for(U64 idx = 0; idx < machine_code_slice.data.size; idx += 1) + { + if(idx%16 == 0) + { + log_infof(" "); + } + log_infof("0x%x,", machine_code_slice.data.str[idx]); + if(idx%16 == 15 || idx+1 == machine_code_slice.data.size) + { + log_infof("\n"); + } + } + log_infof(" ]\n"); + log_infof(" }\n"); } // rjf: machine code => ctrl flow analysis @@ -2909,12 +2933,21 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) arch, line_vaddr_rng.min, machine_code); + log_infof(" ctrl_flow_info:\n {\n"); + log_infof(" flags: %x\n", ctrl_flow_info.flags); + log_infof(" exit_points:\n {\n"); + for(DF_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) + { + log_infof(" {vaddr:0x%I64x, jump_dest_vaddr:0x%I64x, expected_sp_delta:0x%I64x, inst_flags:%x}\n", n->v.vaddr, n->v.jump_dest_vaddr, n->v.expected_sp_delta, n->v.inst_flags); + } + log_infof(" }\n"); + log_infof(" }\n"); } // rjf: push traps for all exit points if(good_line_info) for(DF_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) { - DF_CtrlFlowPoint *point = &n->point; + DF_CtrlFlowPoint *point = &n->v; CTRL_TrapFlags flags = 0; B32 add = 1; U64 trap_addr = point->vaddr; @@ -2969,6 +3002,7 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) } scratch_end(scratch); + log_infof("}\n\n"); return result; } @@ -3039,7 +3073,7 @@ df_trap_net_from_thread__step_into_line(Arena *arena, DF_Entity *thread) // rjf: push traps for all exit points if(good_line_info) for(DF_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) { - DF_CtrlFlowPoint *point = &n->point; + DF_CtrlFlowPoint *point = &n->v; CTRL_TrapFlags flags = 0; B32 add = 1; U64 trap_addr = point->vaddr; @@ -8948,6 +8982,12 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Error)); #endif }break; + + //- rjf: developer commands + case DF_CoreCmdKind_LogMarker: + { + log_infof("\n\n--- #marker ---\n\n"); + }break; } } scratch_end(scratch); diff --git a/src/df/core/df_core.h b/src/df/core/df_core.h index f4c8029e..240258c6 100644 --- a/src/df/core/df_core.h +++ b/src/df/core/df_core.h @@ -223,7 +223,7 @@ typedef struct DF_CtrlFlowPointNode DF_CtrlFlowPointNode; struct DF_CtrlFlowPointNode { DF_CtrlFlowPointNode *next; - DF_CtrlFlowPoint point; + DF_CtrlFlowPoint v; }; typedef struct DF_CtrlFlowPointList DF_CtrlFlowPointList; diff --git a/src/df/core/df_core.mdesk b/src/df/core/df_core.mdesk index a633106b..2b9d6ca5 100644 --- a/src/df/core/df_core.mdesk +++ b/src/df/core/df_core.mdesk @@ -412,6 +412,7 @@ DF_CoreCmdTable:// | | | //- rjf: developer commands {ToggleDevMenu 0 Null Nil 0 0 0 0 0 0 Null "toggle_dev_menu" "Toggle Developer Menu" "Opens and closes the developer menu." "" } + {LogMarker 0 Null Nil 0 0 0 0 0 0 Null "log_marker" "Log Marker" "Logs a marker in the application log, to denote specific points in time within the log." "" } } //////////////////////////////// diff --git a/src/df/core/generated/df_core.meta.c b/src/df/core/generated/df_core.meta.c index ffa020e4..156803d1 100644 --- a/src/df/core/generated/df_core.meta.c +++ b/src/df/core/generated/df_core.meta.c @@ -214,7 +214,7 @@ DF_CoreCmdKind_Null, DF_CoreCmdKind_Null, }; -DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[221] = +DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[222] = { { str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, { str8_lit_comp("exit"), str8_lit_comp("Exits the debugger."), str8_lit_comp("quit,close,abort"), str8_lit_comp("Exit"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_X}, @@ -437,6 +437,7 @@ DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[221] = { str8_lit_comp("complete_query"), str8_lit_comp("Completes a query."), str8_lit_comp(""), str8_lit_comp("Complete Query"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, { str8_lit_comp("cancel_query"), str8_lit_comp("Cancels a query."), str8_lit_comp(""), str8_lit_comp("Cancel Query"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, { str8_lit_comp("toggle_dev_menu"), str8_lit_comp("Opens and closes the developer menu."), str8_lit_comp(""), str8_lit_comp("Toggle Developer Menu"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, +{ str8_lit_comp("log_marker"), str8_lit_comp("Logs a marker in the application log, to denote specific points in time within the log."), str8_lit_comp(""), str8_lit_comp("Log Marker"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, }; DF_CoreViewRuleSpecInfo df_g_core_view_rule_spec_info_table[17] = diff --git a/src/df/core/generated/df_core.meta.h b/src/df/core/generated/df_core.meta.h index 9da5abe2..4f1f86a0 100644 --- a/src/df/core/generated/df_core.meta.h +++ b/src/df/core/generated/df_core.meta.h @@ -269,6 +269,7 @@ DF_CoreCmdKind_PickFileOrFolder, DF_CoreCmdKind_CompleteQuery, DF_CoreCmdKind_CancelQuery, DF_CoreCmdKind_ToggleDevMenu, +DF_CoreCmdKind_LogMarker, DF_CoreCmdKind_COUNT, } DF_CoreCmdKind; diff --git a/src/df/gfx/df_gfx.mdesk b/src/df/gfx/df_gfx.mdesk index 581e6912..9f3cdfa3 100644 --- a/src/df/gfx/df_gfx.mdesk +++ b/src/df/gfx/df_gfx.mdesk @@ -171,6 +171,9 @@ DF_DefaultBindingTable: //- rjf: command lister { "run_command" F1 0 0 0 } + + //- rjf: developer commands + { "log_marker" M ctrl shift alt } } //////////////////////////////// diff --git a/src/df/gfx/generated/df_gfx.meta.c b/src/df/gfx/generated/df_gfx.meta.c index 86ac3b2e..7b0ef1c8 100644 --- a/src/df/gfx/generated/df_gfx.meta.c +++ b/src/df/gfx/generated/df_gfx.meta.c @@ -598,7 +598,7 @@ str8_lit_comp("goto_name"), str8_lit_comp("function_breakpoint"), }; -DF_StringBindingPair df_g_default_binding_table[104] = +DF_StringBindingPair df_g_default_binding_table[105] = { {str8_lit_comp("kill_all"), {OS_Key_F5, 0 |OS_EventFlag_Shift }}, {str8_lit_comp("step_into_inst"), {OS_Key_F11, 0 |OS_EventFlag_Alt}}, @@ -704,6 +704,7 @@ DF_StringBindingPair df_g_default_binding_table[104] = {str8_lit_comp("attach"), {OS_Key_F6, 0 |OS_EventFlag_Shift }}, {str8_lit_comp("filter"), {OS_Key_Slash, 0 |OS_EventFlag_Ctrl }}, {str8_lit_comp("run_command"), {OS_Key_F1, 0 }}, +{str8_lit_comp("log_marker"), {OS_Key_M, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift |OS_EventFlag_Alt}}, }; String8 df_g_binding_version_remap_old_name_table[5] = diff --git a/src/df/gfx/generated/df_gfx.meta.h b/src/df/gfx/generated/df_gfx.meta.h index 8e8cfd30..d65a1898 100644 --- a/src/df/gfx/generated/df_gfx.meta.h +++ b/src/df/gfx/generated/df_gfx.meta.h @@ -290,7 +290,7 @@ extern Vec4F32* df_g_theme_preset_colors_table[9]; extern DF_CmdParamSlot df_g_cmd_param_slot_2_view_spec_src_map[7]; extern String8 df_g_cmd_param_slot_2_view_spec_dst_map[7]; extern String8 df_g_cmd_param_slot_2_view_spec_cmd_map[7]; -extern DF_StringBindingPair df_g_default_binding_table[104]; +extern DF_StringBindingPair df_g_default_binding_table[105]; extern String8 df_g_binding_version_remap_old_name_table[5]; extern String8 df_g_binding_version_remap_new_name_table[5]; extern DF_ViewSpecInfo df_g_gfx_view_kind_spec_info_table[31]; From 4fc5b61676a86ec083a8103851ce583d3026339b Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 18 Jun 2024 10:28:49 -0700 Subject: [PATCH 12/24] also disable overly-ambitious cursor centering in memory view --- src/df/gfx/df_views.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 0bf73db0..123ee7c7 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -8849,7 +8849,10 @@ DF_VIEW_UI_FUNCTION_DEF(Memory) // rjf: click & drag -> select if(ui_dragging(sig) && mouse_hover_byte_num != 0) { - mv->contain_cursor = 1; + if(!contains_2f32(sig.box->rect, ui_mouse())) + { + mv->contain_cursor = 1; + } mv->cursor = mouse_hover_byte_num-1; if(ui_pressed(sig)) { From 9461e79268ce8cb3ab904dcab4601b5408b6e9d5 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 18 Jun 2024 10:46:50 -0700 Subject: [PATCH 13/24] adjust build script to warn if valid build target was not specified --- build.bat | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/build.bat b/build.bat index 75d519e8..6f21ceef 100644 --- a/build.bat +++ b/build.bat @@ -33,7 +33,8 @@ if "%debug%"=="1" set release=0 && echo [debug mode] if "%release%"=="1" set debug=0 && echo [release mode] if "%msvc%"=="1" set clang=0 && echo [msvc compile] if "%clang%"=="1" set msvc=0 && echo [clang compile] -if "%~1"=="" echo [default mode, assuming `raddbg` build] && set raddbg=1 +if "%~1"=="" echo [default mode, assuming `raddbg` build] && set raddbg=1 +if "%~1"=="release" if "%~2"=="" echo [default mode, assuming `raddbg` build] && set raddbg=1 :: --- Unpack Command Line Build Arguments ------------------------------------ set auto_compile_flags= @@ -98,18 +99,19 @@ if not "%no_meta%"=="1" ( :: --- Build Everything (@build_targets) -------------------------------------- pushd build -if "%raddbg%"=="1" %compile% ..\src\raddbg\raddbg_main.c %compile_link% %out%raddbg.exe || exit /b 1 -if "%rdi_from_pdb%"=="1" %compile% ..\src\rdi_from_pdb\rdi_from_pdb_main.c %compile_link% %out%rdi_from_pdb.exe || exit /b 1 -if "%rdi_from_dwarf%"=="1" %compile% ..\src\rdi_from_dwarf\rdi_from_dwarf.c %compile_link% %out%rdi_from_dwarf.exe || exit /b 1 -if "%rdi_dump%"=="1" %compile% ..\src\rdi_dump\rdi_dump_main.c %compile_link% %out%rdi_dump.exe || exit /b 1 -if "%rdi_breakpad_from_pdb%"=="1" %compile% ..\src\rdi_breakpad_from_pdb\rdi_breakpad_from_pdb_main.c %compile_link% %out%rdi_breakpad_from_pdb.exe || exit /b 1 -if "%ryan_scratch%"=="1" %compile% ..\src\scratch\ryan_scratch.c %compile_link% %out%ryan_scratch.exe || exit /b 1 -if "%cpp_tests%"=="1" %compile% ..\src\scratch\i_hate_c_plus_plus.cpp %compile_link% %out%cpp_tests.exe || exit /b 1 -if "%look_at_raddbg%"=="1" %compile% ..\src\scratch\look_at_raddbg.c %compile_link% %out%look_at_raddbg.exe || exit /b 1 -if "%mule_main%"=="1" del vc*.pdb mule*.pdb && %compile_release% %only_compile% ..\src\mule\mule_inline.cpp && %compile_release% %only_compile% ..\src\mule\mule_o2.cpp && %compile_debug% %EHsc% ..\src\mule\mule_main.cpp ..\src\mule\mule_c.c mule_inline.obj mule_o2.obj %compile_link% %no_aslr% %out%mule_main.exe || exit /b 1 -if "%mule_module%"=="1" %compile% ..\src\mule\mule_module.cpp %compile_link% %link_dll% %out%mule_module.dll || exit /b 1 -if "%mule_hotload%"=="1" %compile% ..\src\mule\mule_hotload_main.c %compile_link% %out%mule_hotload.exe & %compile% ..\src\mule\mule_hotload_module_main.c %compile_link% %link_dll% %out%mule_hotload_module.dll || exit /b 1 +if "%raddbg%"=="1" set didbuild=1 && %compile% ..\src\raddbg\raddbg_main.c %compile_link% %out%raddbg.exe || exit /b 1 +if "%rdi_from_pdb%"=="1" set didbuild=1 && %compile% ..\src\rdi_from_pdb\rdi_from_pdb_main.c %compile_link% %out%rdi_from_pdb.exe || exit /b 1 +if "%rdi_from_dwarf%"=="1" set didbuild=1 && %compile% ..\src\rdi_from_dwarf\rdi_from_dwarf.c %compile_link% %out%rdi_from_dwarf.exe || exit /b 1 +if "%rdi_dump%"=="1" set didbuild=1 && %compile% ..\src\rdi_dump\rdi_dump_main.c %compile_link% %out%rdi_dump.exe || exit /b 1 +if "%rdi_breakpad_from_pdb%"=="1" set didbuild=1 && %compile% ..\src\rdi_breakpad_from_pdb\rdi_breakpad_from_pdb_main.c %compile_link% %out%rdi_breakpad_from_pdb.exe || exit /b 1 +if "%ryan_scratch%"=="1" set didbuild=1 && %compile% ..\src\scratch\ryan_scratch.c %compile_link% %out%ryan_scratch.exe || exit /b 1 +if "%cpp_tests%"=="1" set didbuild=1 && %compile% ..\src\scratch\i_hate_c_plus_plus.cpp %compile_link% %out%cpp_tests.exe || exit /b 1 +if "%look_at_raddbg%"=="1" set didbuild=1 && %compile% ..\src\scratch\look_at_raddbg.c %compile_link% %out%look_at_raddbg.exe || exit /b 1 +if "%mule_main%"=="1" set didbuild=1 && del vc*.pdb mule*.pdb && %compile_release% %only_compile% ..\src\mule\mule_inline.cpp && %compile_release% %only_compile% ..\src\mule\mule_o2.cpp && %compile_debug% %EHsc% ..\src\mule\mule_main.cpp ..\src\mule\mule_c.c mule_inline.obj mule_o2.obj %compile_link% %no_aslr% %out%mule_main.exe || exit /b 1 +if "%mule_module%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_module.cpp %compile_link% %link_dll% %out%mule_module.dll || exit /b 1 +if "%mule_hotload%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_hotload_main.c %compile_link% %out%mule_hotload.exe & %compile% ..\src\mule\mule_hotload_module_main.c %compile_link% %link_dll% %out%mule_hotload_module.dll || exit /b 1 if "%mule_peb_trample%"=="1" ( + set didbuild=1 if exist mule_peb_trample.exe move mule_peb_trample.exe mule_peb_trample_old_%random%.exe if exist mule_peb_trample_new.pdb move mule_peb_trample_new.pdb mule_peb_trample_old_%random%.pdb if exist mule_peb_trample_new.rdi move mule_peb_trample_new.rdi mule_peb_trample_old_%random%.rdi @@ -126,3 +128,10 @@ set compile_link= set out= set msvc= set debug= +set release= + +:: --- Warn On No Builds ------------------------------------------------------ +if "%didbuild%"=="" ( + echo [WARNING] no valid build target specified; must use build target names as arguments to this script, like `build raddbg` or `build rdi_from_pdb`. + exit /b 1 +) From ada1b8dfe27bc2743f109090b5414f373217a84c Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 18 Jun 2024 10:51:29 -0700 Subject: [PATCH 14/24] log final trap net --- src/df/core/df_core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 9530fe96..046449ba 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -3001,6 +3001,14 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) ctrl_trap_list_push(arena, &result, &trap); } + // rjf: log + for(CTRL_TrapNode *n = result.first; n != 0; n = n->next) + { + log_infof(" traps:\n {\n"); + log_infof(" {flags:0x%x, vaddr:0x%I64x}\n", n->v.flags, n->v.vaddr); + log_infof(" }\n"); + } + scratch_end(scratch); log_infof("}\n\n"); return result; From a8891b3ca462f0a44996cde45b2021c2d51db1ac Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 18 Jun 2024 10:55:54 -0700 Subject: [PATCH 15/24] fix rdi_from_dwarf build --- src/rdi_from_dwarf/rdi_elf.c | 2 +- src/rdi_from_dwarf/rdi_from_dwarf.c | 32 +++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/rdi_from_dwarf/rdi_elf.c b/src/rdi_from_dwarf/rdi_elf.c index ff8e3c9e..50e0f9be 100644 --- a/src/rdi_from_dwarf/rdi_elf.c +++ b/src/rdi_from_dwarf/rdi_elf.c @@ -387,7 +387,7 @@ static String8Array elf_section_name_array_from_elf(ELF_Parsed *elf){ String8Array result = {0}; if (elf != 0){ - result.strings = elf->section_names; + result.v = elf->section_names; result.count = elf->section_count; } return(result); diff --git a/src/rdi_from_dwarf/rdi_from_dwarf.c b/src/rdi_from_dwarf/rdi_from_dwarf.c index 6c89740f..f976b225 100644 --- a/src/rdi_from_dwarf/rdi_from_dwarf.c +++ b/src/rdi_from_dwarf/rdi_from_dwarf.c @@ -1,26 +1,40 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) +//////////////////////////////// +//~ rjf: Build Options + +#define BUILD_VERSION_MAJOR 0 +#define BUILD_VERSION_MINOR 9 +#define BUILD_VERSION_PATCH 10 +#define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA" +#define BUILD_TITLE "rdi_from_dwarf" +#define BUILD_CONSOLE_INTERFACE 1 + +//////////////////////////////// +//~ rjf: Includes + +//- rjf: [lib] #include "lib_rdi_format/rdi_format.h" +#include "lib_rdi_format/rdi_format.c" +#include "third_party/rad_lzb_simple/rad_lzb_simple.h" +#include "third_party/rad_lzb_simple/rad_lzb_simple.c" + +//- rjf: [h] #include "base/base_inc.h" #include "os/os_inc.h" -#include "rdi_make_local/rdi_make_local.h" - +#include "rdi_make/rdi_make_local.h" #include "rdi_elf.h" #include "rdi_dwarf.h" - #include "rdi_dwarf_stringize.h" - #include "rdi_from_dwarf.h" -#include "lib_rdi_format/rdi_format.c" +//- rjf: [c] #include "base/base_inc.c" #include "os/os_inc.c" -#include "rdi_make_local/rdi_make_local.c" - +#include "rdi_make/rdi_make_local.c" #include "rdi_elf.c" #include "rdi_dwarf.c" - #include "rdi_dwarf_stringize.c" // TODO(allen): @@ -583,7 +597,7 @@ fprintf(stdout, "error(parsing): " fmt "\n", __VA_ARGS__); \ "SECTIONS:\n")); ELF_Shdr64 *sec = section_array.sections; - String8 *sec_name = section_name_array.strings; + String8 *sec_name = section_name_array.v; U64 count = section_array.count; for (U64 i = 0 ; i < count; i += 1, sec += 1, sec_name += 1){ String8 type_string = elf_string_from_section_type(sec->sh_type); From 1a8b39ad9d64d74cf215c07879a8f31e94f08c31 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 18 Jun 2024 10:56:41 -0700 Subject: [PATCH 16/24] fix builds github workflow for new build names --- .github/workflows/builds.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index 6734ecb5..677fcb27 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -21,10 +21,10 @@ jobs: run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 call build raddbg msvc debug || exit /b 1 - call build raddbgi_from_pdb msvc debug || exit /b 1 - call build raddbgi_from_dwarf msvc debug || exit /b 1 - call build raddbgi_dump msvc debug || exit /b 1 + call build rdi_from_pdb msvc debug || exit /b 1 + call build rdi_from_dwarf msvc debug || exit /b 1 + call build rdi_dump msvc debug || exit /b 1 call build raddbg clang debug || exit /b 1 - call build raddbgi_from_pdb clang debug || exit /b 1 - call build raddbgi_from_dwarf clang debug || exit /b 1 - call build raddbgi_dump clang debug || exit /b 1 + call build rdi_from_pdb clang debug || exit /b 1 + call build rdi_from_dwarf clang debug || exit /b 1 + call build rdi_dump clang debug || exit /b 1 From c794d896c921cc05616d129f5456b4bdcfee2bff Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 18 Jun 2024 10:59:35 -0700 Subject: [PATCH 17/24] oops - fix logging for trap net --- src/df/core/df_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 046449ba..25d78c96 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -3002,12 +3002,12 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) } // rjf: log + log_infof(" traps:\n {\n"); for(CTRL_TrapNode *n = result.first; n != 0; n = n->next) { - log_infof(" traps:\n {\n"); log_infof(" {flags:0x%x, vaddr:0x%I64x}\n", n->v.flags, n->v.vaddr); - log_infof(" }\n"); } + log_infof(" }\n"); scratch_end(scratch); log_infof("}\n\n"); From 41fd224956a3d9342e32712cc4abe1624383a1e1 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 18 Jun 2024 12:07:46 -0700 Subject: [PATCH 18/24] log ctrl events on user thread; do not use cached register block reading path for ctrl stepping machine, as it must not prematurely update cache for all readers, since runs are not complete --- src/ctrl/ctrl_core.c | 48 +++++++++++++++++++++++++++++++++++-------- src/ctrl/ctrl_core.h | 1 + src/df/core/df_core.c | 5 +++++ 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index b6b39e78..cc06e979 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -43,6 +43,34 @@ ctrl_event_cause_from_dmn_event_kind(DMN_EventKind event_kind) return cause; } +internal String8 +ctrl_string_from_event_kind(CTRL_EventKind kind) +{ + String8 result = {0}; + switch(kind) + { + default:{}break; + case CTRL_EventKind_Null: { result = str8_lit("Null");}break; + case CTRL_EventKind_Error: { result = str8_lit("Error");}break; + case CTRL_EventKind_Started: { result = str8_lit("Started");}break; + case CTRL_EventKind_Stopped: { result = str8_lit("Stopped");}break; + case CTRL_EventKind_NewProc: { result = str8_lit("NewProc");}break; + case CTRL_EventKind_NewThread: { result = str8_lit("NewThread");}break; + case CTRL_EventKind_NewModule: { result = str8_lit("NewModule");}break; + case CTRL_EventKind_EndProc: { result = str8_lit("EndProc");}break; + case CTRL_EventKind_EndThread: { result = str8_lit("EndThread");}break; + case CTRL_EventKind_EndModule: { result = str8_lit("EndModule");}break; + case CTRL_EventKind_ModuleDebugInfoPathChange: { result = str8_lit("ModuleDebugInfoPathChange");}break; + case CTRL_EventKind_DebugString: { result = str8_lit("DebugString");}break; + case CTRL_EventKind_ThreadName: { result = str8_lit("ThreadName");}break; + case CTRL_EventKind_MemReserve: { result = str8_lit("MemReserve");}break; + case CTRL_EventKind_MemCommit: { result = str8_lit("MemCommit");}break; + case CTRL_EventKind_MemDecommit: { result = str8_lit("MemDecommit");}break; + case CTRL_EventKind_MemRelease: { result = str8_lit("MemRelease");}break; + } + return result; +} + internal String8 ctrl_string_from_msg_kind(CTRL_MsgKind kind) { @@ -3569,7 +3597,8 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, { CTRL_Entity *thread = ctrl_entity_from_machine_id_handle(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, spoof->thread); Architecture arch = thread->arch; - void *regs_block = ctrl_query_cached_reg_block_from_thread(scratch.arena, ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, spoof->thread); + void *regs_block = push_array(scratch.arena, U8, regs_block_size_from_architecture(arch)); + dmn_thread_read_reg_block(spoof->thread, regs_block); U64 spoof_thread_rip = regs_rip_from_arch_block(arch, regs_block); if(spoof_thread_rip == spoof->new_ip_value) { @@ -3991,7 +4020,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) // threads, because otherwise, their stack pointer may change, if single-stepping // causes e.g. entrance into a function via a call instruction. // - U64 sp_check_value = ctrl_query_cached_rsp_from_thread(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, target_thread); + U64 sp_check_value = dmn_rsp_from_thread(target_thread); ////////////////////////////// //- rjf: single step "stuck threads" @@ -4020,7 +4049,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) if(process->kind != CTRL_EntityKind_Process) { continue; } for(CTRL_Entity *thread = process->first; thread != &ctrl_entity_nil; thread = thread->next) { - U64 rip = ctrl_query_cached_rip_from_thread(ctrl_state->ctrl_thread_entity_store, thread->machine_id, thread->handle); + U64 rip = dmn_rip_from_thread(thread->handle); // rjf: determine if thread is frozen B32 thread_is_frozen = !msg->freeze_state_is_frozen; @@ -4181,7 +4210,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) run_ctrls.traps = *trap_list; ////////////////////////// - //- rjf: get next event + //- rjf: get next run-related event // DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, run_spoof); @@ -4440,7 +4469,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) // CTRL_Entity *thread = ctrl_entity_from_machine_id_handle(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, event->thread); Architecture arch = thread->arch; - U64 thread_rip_vaddr = ctrl_query_cached_rip_from_thread(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, event->thread); + U64 thread_rip_vaddr = dmn_rip_from_thread(event->thread); CTRL_Entity *module = &ctrl_entity_nil; { CTRL_Entity *process = ctrl_entity_from_machine_id_handle(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, event->process); @@ -4601,7 +4630,8 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) machine.arch = arch; machine.memory_read = ctrl_eval_memory_read; machine.reg_size = regs_block_size_from_architecture(arch); - machine.reg_data = ctrl_query_cached_reg_block_from_thread(scratch.arena, ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, event->thread); + machine.reg_data = push_array(scratch.arena, U8, machine.reg_size); + dmn_thread_read_reg_block(event->thread, machine.reg_data); machine.module_base = &module_base; machine.tls_base = &tls_base; eval = eval_interpret(&machine, bytecode); @@ -4718,7 +4748,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) B32 stack_pointer_matches = 0; if(use_trap_net_logic) { - U64 sp = ctrl_query_cached_rsp_from_thread(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, target_thread); + U64 sp = dmn_rsp_from_thread(target_thread); stack_pointer_matches = (sp == sp_check_value); } @@ -4766,7 +4796,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { // rjf: setup spoof mode begin_spoof_mode = 1; - U64 spoof_sp = ctrl_query_cached_rsp_from_thread(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, target_thread); + U64 spoof_sp = dmn_rsp_from_thread(target_thread); spoof_mode = 1; spoof.process = target_process; spoof.thread = target_thread; @@ -4784,7 +4814,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) if(stack_pointer_matches) { save_stack_pointer = 1; - sp_check_value = ctrl_query_cached_rsp_from_thread(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, target_thread); + sp_check_value = dmn_rsp_from_thread(target_thread); } } } diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index 758cdbf3..c198f579 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -637,6 +637,7 @@ read_only global CTRL_Entity ctrl_entity_nil = internal U64 ctrl_hash_from_string(String8 string); internal U64 ctrl_hash_from_machine_id_handle(CTRL_MachineID machine_id, DMN_Handle handle); internal CTRL_EventCause ctrl_event_cause_from_dmn_event_kind(DMN_EventKind event_kind); +internal String8 ctrl_string_from_event_kind(CTRL_EventKind kind); internal String8 ctrl_string_from_msg_kind(CTRL_MsgKind kind); //////////////////////////////// diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 25d78c96..f10e2d1b 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -6846,6 +6846,9 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) for(CTRL_EventNode *event_n = events.first; event_n != 0; event_n = event_n->next) { CTRL_Event *event = &event_n->v; + log_infof("ctrl_event:\n{\n"); + log_infof(" kind: \"%S\"\n", ctrl_string_from_event_kind(event->kind)); + log_infof(" entity_id: %u\n", event->entity_id); switch(event->kind) { default:{}break; @@ -6881,6 +6884,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) // rjf: select & snap to thread causing stop if(should_snap && stop_thread->kind == DF_EntityKind_Thread) { + log_infof(" stop_thread: \"%S\"\n", df_display_string_from_entity(scratch.arena, stop_thread)); DF_CmdParams params = df_cmd_params_zero(); params.entity = df_handle_from_entity(stop_thread); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); @@ -7203,6 +7207,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) case CTRL_EventKind_MemDecommit:{}break; case CTRL_EventKind_MemRelease:{}break; } + log_infof("}\n"); } //- rjf: clear tls base cache From f6eec680bcebbcba461eac0ed0260ef618c2055d Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 18 Jun 2024 17:19:17 -0700 Subject: [PATCH 19/24] adjust single stepping rule to be robust to non-single-step events; this is still not what the issue is pertaining to the stepping bug... --- src/ctrl/ctrl_core.c | 99 ++++++++++++++++++++++++------ src/demon/win32/demon_core_win32.c | 9 ++- src/demon/win32/demon_core_win32.h | 2 + 3 files changed, 86 insertions(+), 24 deletions(-) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index cc06e979..bee2f0fb 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -3562,9 +3562,15 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, // rjf: run for new events ProfScope("run for new events") { - log_infof("{dmn_ctrl_run ..."); - DMN_EventList events = dmn_ctrl_run(scratch.arena, ctrl_ctx, run_ctrls); + log_infof("dmn_ctrl_run:\n{\n"); + log_infof(" single_step_thread: [0x%I64x]\n", run_ctrls->single_step_thread); + log_infof(" ignore_previous_exception: %i\n", !!run_ctrls->ignore_previous_exception); + log_infof(" run_entities_are_unfrozen: %i\n", !!run_ctrls->run_entities_are_unfrozen); + log_infof(" run_entities_are_processes: %i\n", !!run_ctrls->run_entities_are_processes); + log_infof(" run_entity_count: %I64u\n", run_ctrls->run_entity_count); + log_infof(" trap_count: %I64u\n", run_ctrls->traps.trap_count); log_infof("}\n"); + DMN_EventList events = dmn_ctrl_run(scratch.arena, ctrl_ctx, run_ctrls); for(DMN_EventNode *src_n = events.first; src_n != 0; src_n = src_n->next) { DMN_EventNode *dst_n = ctrl_state->free_dmn_event_node; @@ -4105,11 +4111,21 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) node != 0; node = node->next) { - DMN_RunCtrls run_ctrls = {0}; - run_ctrls.single_step_thread = node->v; - for(B32 done = 0; done == 0;) + DMN_Handle thread = node->v; + U64 thread_pre_rip = dmn_rip_from_thread(thread); + U64 thread_post_rip = thread_pre_rip; + for(B32 done = 0; !done;) { + DMN_RunCtrls run_ctrls = {0}; + run_ctrls.run_entities_are_unfrozen = 1; + run_ctrls.run_entities = &thread; + run_ctrls.run_entity_count = 1; + if(thread_post_rip == thread_pre_rip) + { + run_ctrls.single_step_thread = thread; + } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0); + thread_post_rip = dmn_rip_from_thread(thread); switch(event->kind) { default:{}break; @@ -4124,7 +4140,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) }break; case DMN_EventKind_SingleStep: { - done = 1; + done = dmn_handle_match(node->v, event->thread); }break; } } @@ -4212,6 +4228,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) ////////////////////////// //- rjf: get next run-related event // + log_infof(">>> stepping >>> getting next event\n"); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, run_spoof); ////////////////////////// @@ -4680,11 +4697,21 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) CTRL_EventCause cond_bp_single_step_stop_cause = CTRL_EventCause_Null; if(hit_conditional_bp_but_filtered) { - DMN_RunCtrls single_step_ctrls = {0}; - single_step_ctrls.single_step_thread = event->thread; - for(B32 single_step_done = 0; single_step_done == 0;) + DMN_Handle thread = event->thread; + U64 thread_pre_rip = dmn_rip_from_thread(thread); + U64 thread_post_rip = thread_pre_rip; + for(B32 single_step_done = 0; !single_step_done;) { + DMN_RunCtrls single_step_ctrls = {0}; + single_step_ctrls.run_entities_are_unfrozen = 1; + single_step_ctrls.run_entities = &thread; + single_step_ctrls.run_entity_count = 1; + if(thread_post_rip == thread_pre_rip) + { + single_step_ctrls.single_step_thread = thread; + } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0); + thread_post_rip = dmn_rip_from_thread(thread); switch(event->kind) { default:{}break; @@ -4700,7 +4727,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) }break; case DMN_EventKind_SingleStep: { - single_step_done = 1; + single_step_done = dmn_handle_match(event->thread, thread); cond_bp_single_step_stop_cause = ctrl_event_cause_from_dmn_event_kind(event->kind); }break; } @@ -4759,11 +4786,21 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { if(hit_trap_flags & CTRL_TrapFlag_SingleStepAfterHit) { - DMN_RunCtrls single_step_ctrls = {0}; - single_step_ctrls.single_step_thread = target_thread; + log_infof(">>> stepping >>> trap net logic: single step after hit\n"); + U64 thread_pre_rip = dmn_rip_from_thread(target_thread); + U64 thread_post_rip = thread_pre_rip; for(B32 single_step_done = 0; single_step_done == 0;) { + DMN_RunCtrls single_step_ctrls = {0}; + single_step_ctrls.run_entities_are_unfrozen = 1; + single_step_ctrls.run_entities = &target_thread; + single_step_ctrls.run_entity_count = 1; + if(thread_post_rip == thread_pre_rip) + { + single_step_ctrls.single_step_thread = target_thread; + } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0); + thread_post_rip = dmn_rip_from_thread(target_thread); switch(event->kind) { default:{}break; @@ -4780,7 +4817,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) }break; case DMN_EventKind_SingleStep: { - single_step_done = 1; + single_step_done = dmn_handle_match(event->thread, target_thread);; single_step_stop_cause = ctrl_event_cause_from_dmn_event_kind(event->kind); }break; } @@ -4795,6 +4832,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) if(hit_trap_flags & CTRL_TrapFlag_BeginSpoofMode) { // rjf: setup spoof mode + log_infof(">>> stepping >>> trap net logic: begin spoof mode\n"); begin_spoof_mode = 1; U64 spoof_sp = dmn_rsp_from_thread(target_thread); spoof_mode = 1; @@ -4815,6 +4853,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { save_stack_pointer = 1; sp_check_value = dmn_rsp_from_thread(target_thread); + log_infof(">>> stepping >>> trap net logic: save stack pointer (0x%I64x)\n", sp_check_value); } } } @@ -4828,6 +4867,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) if((hit_trap_flags & CTRL_TrapFlag_IgnoreStackPointerCheck) || stack_pointer_matches) { + log_infof(">>> stepping >>> trap net logic: end stepping\n"); trap_net_stop = 1; use_trap_net_logic = 0; } @@ -4844,11 +4884,22 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) CTRL_EventCause step_past_trap_net_stop_cause = CTRL_EventCause_Null; if(step_past_trap_net) { - DMN_RunCtrls single_step_ctrls = {0}; - single_step_ctrls.single_step_thread = event->thread; + log_infof(">>> stepping >>> trap net logic: single-step non-target-thread (%I64x) past trap net\n", event->thread.u64[0]); + DMN_Handle thread = event->thread; + U64 thread_pre_rip = dmn_rip_from_thread(thread); + U64 thread_post_rip = thread_pre_rip; for(B32 single_step_done = 0; single_step_done == 0;) { + DMN_RunCtrls single_step_ctrls = {0}; + single_step_ctrls.run_entities_are_unfrozen = 1; + single_step_ctrls.run_entities = &thread; + single_step_ctrls.run_entity_count = 1; + if(thread_post_rip == thread_pre_rip) + { + single_step_ctrls.single_step_thread = thread; + } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0); + thread_post_rip = dmn_rip_from_thread(thread); switch(event->kind) { default:{}break; @@ -4863,7 +4914,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) }break; case DMN_EventKind_SingleStep: { - single_step_done = 1; + single_step_done = dmn_handle_match(event->thread, thread); step_past_trap_net_stop_cause = ctrl_event_cause_from_dmn_event_kind(event->kind); }break; } @@ -4955,11 +5006,21 @@ ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) DMN_Event *stop_event = 0; CTRL_EventCause stop_cause = CTRL_EventCause_Null; { - DMN_RunCtrls run_ctrls = {0}; - run_ctrls.single_step_thread = msg->entity; + DMN_Handle thread = msg->entity; + U64 thread_pre_rip = dmn_rip_from_thread(thread); + U64 thread_post_rip = thread_pre_rip; for(B32 done = 0; done == 0;) { + DMN_RunCtrls run_ctrls = {0}; + run_ctrls.run_entities_are_unfrozen = 1; + run_ctrls.run_entities = &thread; + run_ctrls.run_entity_count = 1; + if(thread_post_rip == thread_pre_rip) + { + run_ctrls.single_step_thread = msg->entity; + } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0); + thread_post_rip = dmn_rip_from_thread(msg->entity); switch(event->kind) { default:{}break; @@ -4967,8 +5028,8 @@ ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) case DMN_EventKind_Exception: {stop_cause = CTRL_EventCause_InterruptedByException;}goto end_single_step; case DMN_EventKind_Halt: {stop_cause = CTRL_EventCause_InterruptedByHalt;}goto end_single_step; case DMN_EventKind_Trap: {stop_cause = CTRL_EventCause_InterruptedByTrap;}goto end_single_step; - case DMN_EventKind_SingleStep: {stop_cause = CTRL_EventCause_Finished;}goto end_single_step; case DMN_EventKind_Breakpoint: {stop_cause = CTRL_EventCause_UserBreakpoint;}goto end_single_step; + case DMN_EventKind_SingleStep: {stop_cause = CTRL_EventCause_Finished;}goto end_single_step; end_single_step: { stop_event = event; diff --git a/src/demon/win32/demon_core_win32.c b/src/demon/win32/demon_core_win32.c index 1d865093..71679442 100644 --- a/src/demon/win32/demon_core_win32.c +++ b/src/demon/win32/demon_core_win32.c @@ -1449,7 +1449,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) if(single_step_thread_ctx != 0) { U64 rflags = single_step_thread_ctx->EFlags|0x2; - U64 new_rflags = rflags |= 0x100; + U64 new_rflags = rflags | 0x100; single_step_thread_ctx->EFlags = new_rflags; SetThreadContext(thread->handle, single_step_thread_ctx); ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen); @@ -1517,10 +1517,9 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) B32 is_frozen = 0; { // rjf: single-step? freeze if not the single-step thread. - if(!dmn_handle_match(dmn_handle_zero(), ctrls->single_step_thread) && - !dmn_handle_match(dmn_w32_handle_from_entity(thread), ctrls->single_step_thread)) + if(!dmn_handle_match(dmn_handle_zero(), ctrls->single_step_thread)) { - is_frozen = 1; + is_frozen = !dmn_handle_match(dmn_w32_handle_from_entity(thread), ctrls->single_step_thread); } // rjf: not single-stepping? determine based on run controls freezing info @@ -2430,7 +2429,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) if(ctx != 0) { U64 rflags = single_step_thread_ctx->EFlags|0x2; - U64 new_rflags = rflags &= ~0x100; + U64 new_rflags = rflags & ~0x100; single_step_thread_ctx->EFlags = new_rflags; SetThreadContext(thread->handle, single_step_thread_ctx); ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen); diff --git a/src/demon/win32/demon_core_win32.h b/src/demon/win32/demon_core_win32.h index 04c955c8..f3cbb398 100644 --- a/src/demon/win32/demon_core_win32.h +++ b/src/demon/win32/demon_core_win32.h @@ -54,6 +54,8 @@ #define DMN_W32_EXCEPTION_NO_MEMORY 0xC0000017u #define DMN_W32_EXCEPTION_THROW 0xE06D7363u #define DMN_W32_EXCEPTION_SET_THREAD_NAME 0x406d1388u +#define DMN_w32_EXCEPTION_CLRDBG_NOTIFICATION 0x04242420u +#define DMN_w32_EXCEPTION_CLR 0xE0434352u //////////////////////////////// //~ rjf: Win32 Register Codes From 376a7c48a5231c329e0d9a6385fb434fa63e1911 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Wed, 19 Jun 2024 11:12:21 -0700 Subject: [PATCH 20/24] pass over logging, include a lot of extra info in ctrl thread log; demon abstraction for target-process memory allocation/protection; switch spoofs to being in allocated page, rather than at bogus address --- src/base/base_log.c | 5 +- src/base/base_log.h | 3 + src/base/base_markup.c | 6 +- src/base/base_markup.h | 8 +- src/base/base_strings.c | 40 ++++++- src/base/base_strings.h | 7 +- src/ctrl/ctrl_core.c | 176 ++++++++++++++++++----------- src/dasm_cache/dasm_cache.c | 18 +-- src/dbgi/dbgi.c | 4 +- src/demon/demon_core.h | 5 + src/demon/win32/demon_core_win32.c | 67 +++++++++++ src/df/core/df_core.c | 111 +++++++++--------- src/raddbg/raddbg_main.c | 2 +- 13 files changed, 315 insertions(+), 137 deletions(-) diff --git a/src/base/base_log.c b/src/base/base_log.c index b04a041e..a5a917ac 100644 --- a/src/base/base_log.c +++ b/src/base/base_log.c @@ -90,7 +90,10 @@ log_scope_end(Arena *arena) { for(EachEnumVal(LogMsgKind, kind)) { - result.strings[kind] = str8_list_join(arena, &scope->strings[kind], 0); + Temp scratch = scratch_begin(&arena, 1); + String8 result_unindented = str8_list_join(scratch.arena, &scope->strings[kind], 0); + result.strings[kind] = indented_from_string(arena, result_unindented); + scratch_end(scratch); } } arena_pop_to(log_active->arena, scope->pos); diff --git a/src/base/base_log.h b/src/base/base_log.h index b5054b40..52a297d8 100644 --- a/src/base/base_log.h +++ b/src/base/base_log.h @@ -53,6 +53,9 @@ internal void log_msgf(LogMsgKind kind, char *fmt, ...); #define log_user_error(s) log_msg(LogMsgKind_UserError, (s)) #define log_user_errorf(fmt, ...) log_msgf(LogMsgKind_UserError, (fmt), __VA_ARGS__) +#define LogInfoNamedBlock(s) DeferLoop(log_infof("%S:\n{\n", (s)), log_infof("}\n")) +#define LogInfoNamedBlockF(fmt, ...) DeferLoop((log_infof(fmt, __VA_ARGS__), log_infof(":\n{\n")), log_infof("}\n")) + //////////////////////////////// //~ rjf: Log Scopes diff --git a/src/base/base_markup.c b/src/base/base_markup.c index e0ba1b2b..033fb49a 100644 --- a/src/base/base_markup.c +++ b/src/base/base_markup.c @@ -2,20 +2,20 @@ // Licensed under the MIT license (https://opensource.org/license/mit/) internal void -thread_name(String8 string) +set_thread_name(String8 string) { ProfThreadName("%.*s", str8_varg(string)); os_set_thread_name(string); } internal void -thread_namef(char *fmt, ...) +set_thread_namef(char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); - thread_name(string); + set_thread_name(string); va_end(args); scratch_end(scratch); } diff --git a/src/base/base_markup.h b/src/base/base_markup.h index 6696ff29..0f255efc 100644 --- a/src/base/base_markup.h +++ b/src/base/base_markup.h @@ -4,9 +4,9 @@ #ifndef BASE_MARKUP_H #define BASE_MARKUP_H -internal void thread_name(String8 string); -internal void thread_namef(char *fmt, ...); -#define ThreadNameF(...) (ProfThreadName(__VA_ARGS__), thread_namef(__VA_ARGS__)) -#define ThreadName(str) (ProfThreadName("%.*s", str8_varg(str)), thread_name(str)) +internal void set_thread_name(String8 string); +internal void set_thread_namef(char *fmt, ...); +#define ThreadNameF(...) (set_thread_namef(__VA_ARGS__)) +#define ThreadName(str) (set_thread_name(str)) #endif // BASE_MARKUP_H diff --git a/src/base/base_strings.c b/src/base/base_strings.c index 5a4b91fa..355cc62e 100644 --- a/src/base/base_strings.c +++ b/src/base/base_strings.c @@ -1566,7 +1566,45 @@ string_from_elapsed_time(Arena *arena, DateTime dt){ } //////////////////////////////// -//~ rjf: Textual String Wrapping +//~ rjf: Basic Text Indentation + +internal String8 +indented_from_string(Arena *arena, String8 string) +{ + Temp scratch = scratch_begin(&arena, 1); + read_only local_persist U8 indentation_bytes[] = " "; + String8List indented_strings = {0}; + S64 depth = 0; + S64 next_depth = 0; + U64 line_begin_off = 0; + for(U64 off = 0; off <= string.size; off += 1) + { + U8 byte = offmachine_id, dmn_handle_zero()); CTRL_Entity *process = ctrl_entity_alloc(store, machine, CTRL_EntityKind_Process, event->arch, event->machine_id, event->entity, (U64)event->entity_id); + process->vaddr_range = event->vaddr_rng; }break; case CTRL_EventKind_EndProc: { @@ -2887,7 +2888,7 @@ ctrl_thread__entry_point(void *p) { CTRL_Msg *msg = &msg_n->v; { - log_infof("[user -> ctrl %S message]\n", ctrl_string_from_msg_kind(msg->kind)); + log_infof("user2ctrl_msg:{kind:\"%S\"}\n", ctrl_string_from_msg_kind(msg->kind)); } MemoryCopyArray(ctrl_state->exception_code_filters, msg->exception_code_filters); switch(msg->kind) @@ -3401,16 +3402,18 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, if(next_event_node != 0) { DMN_Event *ev = &next_event_node->v; - log_infof("--- event ---\n"); - log_infof("kind: %S\n", dmn_event_kind_string_table[ev->kind]); - log_infof("exception_kind: %S\n", dmn_exception_kind_string_table[ev->exception_kind]); - log_infof("process: [%I64u]\n", ev->process.u64[0]); - log_infof("thread: [%I64u]\n", ev->thread.u64[0]); - log_infof("module: [%I64u]\n", ev->module.u64[0]); - log_infof("arch: %S\n", string_from_architecture(ev->arch)); - log_infof("address: 0x%I64x\n", ev->address); - log_infof("string: \"%S\"\n", ev->string); - log_infof("ip_vaddr: 0x%I64x\n", ev->instruction_pointer); + LogInfoNamedBlockF("dmn_event") + { + log_infof("kind: %S\n", dmn_event_kind_string_table[ev->kind]); + log_infof("exception_kind: %S\n", dmn_exception_kind_string_table[ev->exception_kind]); + log_infof("process: [%I64u]\n", ev->process.u64[0]); + log_infof("thread: [%I64u]\n", ev->thread.u64[0]); + log_infof("module: [%I64u]\n", ev->module.u64[0]); + log_infof("arch: %S\n", string_from_architecture(ev->arch)); + log_infof("address: 0x%I64x\n", ev->address); + log_infof("string: \"%S\"\n", ev->string); + log_infof("ip_vaddr: 0x%I64x\n", ev->instruction_pointer); + } } // rjf: determine if we should filter @@ -3562,14 +3565,26 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, // rjf: run for new events ProfScope("run for new events") { - log_infof("dmn_ctrl_run:\n{\n"); - log_infof(" single_step_thread: [0x%I64x]\n", run_ctrls->single_step_thread); - log_infof(" ignore_previous_exception: %i\n", !!run_ctrls->ignore_previous_exception); - log_infof(" run_entities_are_unfrozen: %i\n", !!run_ctrls->run_entities_are_unfrozen); - log_infof(" run_entities_are_processes: %i\n", !!run_ctrls->run_entities_are_processes); - log_infof(" run_entity_count: %I64u\n", run_ctrls->run_entity_count); - log_infof(" trap_count: %I64u\n", run_ctrls->traps.trap_count); - log_infof("}\n"); + LogInfoNamedBlockF("dmn_ctrl_run") + { + log_infof("single_step_thread: [0x%I64x]\n", run_ctrls->single_step_thread); + log_infof("ignore_previous_exception: %i\n", !!run_ctrls->ignore_previous_exception); + log_infof("run_entities_are_unfrozen: %i\n", !!run_ctrls->run_entities_are_unfrozen); + log_infof("run_entities_are_processes: %i\n", !!run_ctrls->run_entities_are_processes); + log_infof("run_entity_count: %I64u\n", run_ctrls->run_entity_count); + LogInfoNamedBlockF("run_entities") for(U64 idx = 0; idx < run_ctrls->run_entity_count; idx += 1) + { + log_infof("[0x%I64x]\n", run_ctrls->run_entities[idx]); + } + log_infof("trap_count: %I64u\n", run_ctrls->traps.trap_count); + LogInfoNamedBlockF("traps") for(DMN_TrapChunkNode *n = run_ctrls->traps.first; n != 0; n = n->next) + { + for(U64 idx = 0; idx < n->count; idx += 1) + { + log_infof("{process:[0x%I64x], vaddr:0x%I64x, id:0x%I64x}\n", n->v[idx].process.u64[0], n->v[idx].vaddr, n->v[idx].id); + } + } + } DMN_EventList events = dmn_ctrl_run(scratch.arena, ctrl_ctx, run_ctrls); for(DMN_EventNode *src_n = events.first; src_n != 0; src_n = src_n->next) { @@ -3606,7 +3621,7 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, void *regs_block = push_array(scratch.arena, U8, regs_block_size_from_architecture(arch)); dmn_thread_read_reg_block(spoof->thread, regs_block); U64 spoof_thread_rip = regs_rip_from_arch_block(arch, regs_block); - if(spoof_thread_rip == spoof->new_ip_value) + if(spoof_thread_rip == spoof->new_ip_value+1) { regs_arch_block_write_rip(arch, regs_block, spoof_old_ip_value); ctrl_thread_write_reg_block(CTRL_MachineID_Local, spoof->thread, regs_block); @@ -3620,6 +3635,12 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, default:{}break; case DMN_EventKind_CreateProcess: { + U64 spoof_space_size = KB(4); + U64 spoof_space_vaddr = dmn_process_memory_reserve(event->process, 0, spoof_space_size); + U64 spoof_space_code = 0xcccccccc; + dmn_process_memory_commit(event->process, spoof_space_vaddr, spoof_space_size); + dmn_process_memory_protect(event->process, spoof_space_vaddr, spoof_space_size, OS_AccessFlag_Read|OS_AccessFlag_Write|OS_AccessFlag_Execute); + dmn_process_write(event->process, r1u64(spoof_space_vaddr, spoof_space_vaddr+sizeof(spoof_space_code)), &spoof_space_code); CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); out_evt->kind = CTRL_EventKind_NewProc; out_evt->msg_id = msg->msg_id; @@ -3627,6 +3648,7 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, out_evt->entity = event->process; out_evt->arch = event->arch; out_evt->entity_id = event->code; + out_evt->vaddr_rng = r1u64(spoof_space_vaddr, spoof_space_vaddr+spoof_space_size); ctrl_state->process_counter += 1; }break; case DMN_EventKind_CreateThread: @@ -3992,7 +4014,9 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) CTRL_EventCause stop_cause = CTRL_EventCause_Null; DMN_Handle target_thread = msg->entity; DMN_Handle target_process = msg->parent; - U64 spoof_ip_vaddr = 911; + CTRL_Entity *target_process_entity = ctrl_entity_from_machine_id_handle(ctrl_state->ctrl_thread_entity_store, msg->machine_id, target_process); + U64 spoof_ip_vaddr = target_process_entity->vaddr_range.min; + log_infof("ctrl_thread__run:\n{\n"); ////////////////////////////// //- rjf: gather all initial breakpoints @@ -4027,6 +4051,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) // causes e.g. entrance into a function via a call instruction. // U64 sp_check_value = dmn_rsp_from_thread(target_thread); + log_infof("sp_check_value := 0x%I64x\n", sp_check_value); ////////////////////////////// //- rjf: single step "stuck threads" @@ -4116,6 +4141,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) U64 thread_post_rip = thread_pre_rip; for(B32 done = 0; !done;) { + log_infof("single_step_stuck_thread([0x%I64x])\n", thread.u64[0]); DMN_RunCtrls run_ctrls = {0}; run_ctrls.run_entities_are_unfrozen = 1; run_ctrls.run_entities = &thread; @@ -4228,8 +4254,9 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) ////////////////////////// //- rjf: get next run-related event // - log_infof(">>> stepping >>> getting next event\n"); + log_infof("get_next_event:\n{\n"); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, run_spoof); + log_infof("}\n\n"); ////////////////////////// //- rjf: determine event handling @@ -4244,30 +4271,44 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) case DMN_EventKind_Error: case DMN_EventKind_Halt: case DMN_EventKind_SingleStep: - case DMN_EventKind_Trap: { hard_stop = 1; - log_infof(">>> stepping >>> hard stop\n"); + log_infof("step_rule: unexpected -> hard_stop\n"); + }break; + case DMN_EventKind_Trap: + { + if(event->instruction_pointer == spoof_ip_vaddr) + { + use_stepping_logic = 1; + log_infof("step_rule: spoof trap -> stepping_logic\n"); + } + else + { + hard_stop = 1; + log_infof("step_rule: unexpected trap -> hard_stop\n"); + } }break; case DMN_EventKind_Exception: case DMN_EventKind_Breakpoint: { use_stepping_logic = 1; - log_infof(">>> stepping >>> exception or breakpoint - begin stepping logic\n"); + log_infof("step_rule: exception/breakpoint -> stepping_logic\n"); }break; case DMN_EventKind_CreateProcess: { DMN_TrapChunkList new_traps = {0}; ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, CTRL_MachineID_Local, event->process, &msg->user_bps, &new_traps); - log_infof(">>> stepping >>> create process -> resolve new BPs\n"); + log_infof("step_rule: create_process -> resolve traps\n"); + log_infof("new_traps:\n{\n"); for(DMN_TrapChunkNode *n = new_traps.first; n != 0; n = n->next) { for(U64 idx = 0; idx < n->count; idx += 1) { DMN_Trap *trap = &n->v[idx]; - log_infof(" trap: {process:%I64d, vaddr:0x%I64x}\n", trap->process.u64[0], trap->vaddr); + log_infof("{process:[0x%I64x], vaddr:0x%I64x}\n", trap->process.u64[0], trap->vaddr); } } + log_infof("}\n\n"); dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &new_traps); dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &user_traps, &new_traps); }break; @@ -4275,9 +4316,19 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { DMN_TrapChunkList new_traps = {0}; ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, CTRL_MachineID_Local, event->process, event->module, &msg->user_bps, &new_traps); + log_infof("step_rule: load_module -> resolve traps\n"); + log_infof("new_traps:\n{\n"); + for(DMN_TrapChunkNode *n = new_traps.first; n != 0; n = n->next) + { + for(U64 idx = 0; idx < n->count; idx += 1) + { + DMN_Trap *trap = &n->v[idx]; + log_infof("{process:[0x%I64x], vaddr:0x%I64x}\n", trap->process.u64[0], trap->vaddr); + } + } + log_infof("}\n\n"); dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &new_traps); dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &user_traps, &new_traps); - log_infof(">>> stepping >>> load module -> resolve new BPs\n"); }break; } @@ -4512,35 +4563,36 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) //{ ////////////////////////// - //- rjf: handle if hitting a spoof or baked in trap + //- rjf: handle if hitting an exception + // + B32 exception_stop = 0; + if(!hard_stop && use_stepping_logic && event->kind == DMN_EventKind_Exception) + { + exception_stop = 1; + use_stepping_logic = 0; + } + + ////////////////////////// + //- rjf: handle if hitting a spoof // B32 hit_spoof = 0; - B32 exception_stop = 0; - if(!hard_stop && use_stepping_logic) + if(!hard_stop && use_stepping_logic && event->kind == DMN_EventKind_Trap) { - if(event->kind == DMN_EventKind_Exception) + if(spoof_mode && + dmn_handle_match(target_process, event->process) && + dmn_handle_match(target_thread, event->thread) && + spoof.new_ip_value == event->instruction_pointer) { - // rjf: spoof check - if(spoof_mode && - dmn_handle_match(target_process, event->process) && - dmn_handle_match(target_thread, event->thread) && - spoof.new_ip_value == event->instruction_pointer) - { - hit_spoof = 1; - } - - // rjf: other exceptions cause stop - if(!hit_spoof) - { - exception_stop = 1; - use_stepping_logic = 0; - } + hit_spoof = 1; + log_infof("hit_spoof\n"); } } //- rjf: handle spoof hit if(hit_spoof) { + log_infof("exit_spoof_mode\n"); + // rjf: clear spoof mode spoof_mode = 0; MemoryZeroStruct(&spoof); @@ -4657,13 +4709,13 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { hit_user_bp = 0; hit_conditional_bp_but_filtered = 1; - log_infof(">>> stepping >>> conditional breakpoint hit, but condition eval'd to 0, and so filtered\n"); + log_infof("conditional_breakpoint_hit: 'condition eval'd to 0, and so filtered'\n"); } else { hit_user_bp = 1; hit_conditional_bp_but_filtered = 0; - log_infof(">>> stepping >>> conditional breakpoint hit\n"); + log_infof("conditional_breakpoint_hit: 'conditional eval'd to nonzero, hit'\n"); break; } } @@ -4687,15 +4739,15 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) } } - log_infof(">>> stepping >>> stepping logic - BP event -> hit_user_bp: %i\n", hit_user_bp); - log_infof(">>> stepping >>> stepping logic - BP event -> hit_entry: %i\n", hit_entry); + log_infof("user_breakpoint_hit: %i\n", hit_user_bp); + log_infof("entry_point_hit: %i\n", hit_entry); temp_end(temp); } //- rjf: hit conditional user bp but filtered -> single step B32 cond_bp_single_step_stop = 0; CTRL_EventCause cond_bp_single_step_stop_cause = CTRL_EventCause_Null; - if(hit_conditional_bp_but_filtered) + if(hit_conditional_bp_but_filtered) LogInfoNamedBlockF("conditional_bp_hit_single_step") { DMN_Handle thread = event->thread; U64 thread_pre_rip = dmn_rip_from_thread(thread); @@ -4784,9 +4836,8 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) CTRL_EventCause single_step_stop_cause = CTRL_EventCause_Null; if(!hard_stop && use_trap_net_logic) { - if(hit_trap_flags & CTRL_TrapFlag_SingleStepAfterHit) + if(hit_trap_flags & CTRL_TrapFlag_SingleStepAfterHit) LogInfoNamedBlockF("trap_net__single_step_after_hit") { - log_infof(">>> stepping >>> trap net logic: single step after hit\n"); U64 thread_pre_rip = dmn_rip_from_thread(target_thread); U64 thread_post_rip = thread_pre_rip; for(B32 single_step_done = 0; single_step_done == 0;) @@ -4829,10 +4880,9 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) B32 begin_spoof_mode = 0; if(!hard_stop && use_trap_net_logic) { - if(hit_trap_flags & CTRL_TrapFlag_BeginSpoofMode) + if(hit_trap_flags & CTRL_TrapFlag_BeginSpoofMode) LogInfoNamedBlockF("trap_net__begin_spoof_mode") { // rjf: setup spoof mode - log_infof(">>> stepping >>> trap net logic: begin spoof mode\n"); begin_spoof_mode = 1; U64 spoof_sp = dmn_rsp_from_thread(target_thread); spoof_mode = 1; @@ -4840,6 +4890,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) spoof.thread = target_thread; spoof.vaddr = spoof_sp; spoof.new_ip_value = spoof_ip_vaddr; + log_infof("spoof:{process:[0x%I64x], thread:[0x%I64x], vaddr:0x%I64x, new_ip_value:0x%I64x}\n", spoof.process.u64[0], spoof.thread.u64[0], spoof.vaddr, spoof.new_ip_value); } } @@ -4849,11 +4900,11 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { if(hit_trap_flags & CTRL_TrapFlag_SaveStackPointer) { - if(stack_pointer_matches) + if(stack_pointer_matches) LogInfoNamedBlockF("trap_net__save_sp") { save_stack_pointer = 1; sp_check_value = dmn_rsp_from_thread(target_thread); - log_infof(">>> stepping >>> trap net logic: save stack pointer (0x%I64x)\n", sp_check_value); + log_infof("sp_check_value = 0x%I64x\n", sp_check_value); } } } @@ -4862,12 +4913,11 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) B32 trap_net_stop = 0; if(!hard_stop && use_trap_net_logic) { - if(hit_trap_flags & CTRL_TrapFlag_EndStepping) + if(hit_trap_flags & CTRL_TrapFlag_EndStepping) LogInfoNamedBlockF("trap_net__end_step") { if((hit_trap_flags & CTRL_TrapFlag_IgnoreStackPointerCheck) || stack_pointer_matches) { - log_infof(">>> stepping >>> trap net logic: end stepping\n"); trap_net_stop = 1; use_trap_net_logic = 0; } @@ -4882,9 +4932,8 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) //- rjf: handle step past trap net B32 step_past_trap_net_stop = 0; CTRL_EventCause step_past_trap_net_stop_cause = CTRL_EventCause_Null; - if(step_past_trap_net) + if(step_past_trap_net) LogInfoNamedBlockF("trap_net__single_step_past_trap_net") { - log_infof(">>> stepping >>> trap net logic: single-step non-target-thread (%I64x) past trap net\n", event->thread.u64[0]); DMN_Handle thread = event->thread; U64 thread_pre_rip = dmn_rip_from_thread(thread); U64 thread_post_rip = thread_pre_rip; @@ -4955,7 +5004,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { stage_stop_cause = CTRL_EventCause_Finished; } - log_infof(">>> stepping >>> stage stop cause -> %i\n", stage_stop_cause); + log_infof("stop_cause: %i\n", stage_stop_cause); if(stage_stop_cause != CTRL_EventCause_Null) { stop_event = event; @@ -4983,6 +5032,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) ctrl_c2u_push_events(&evts); } + log_infof("}\n\n"); di_scope_close(di_scope); scratch_end(scratch); ProfEnd(); diff --git a/src/dasm_cache/dasm_cache.c b/src/dasm_cache/dasm_cache.c index 54d89aba..a0f46255 100644 --- a/src/dasm_cache/dasm_cache.c +++ b/src/dasm_cache/dasm_cache.c @@ -240,14 +240,16 @@ dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params) } if(node == 0) { - log_infof("[dasm] cache miss, creating node...\n"); - log_infof(" hash: [0x%I64x 0x%I64x]\n", hash.u64[0], hash.u64[1]); - log_infof(" vaddr: 0x%I64x\n", params->vaddr); - log_infof(" arch: %S\n", string_from_architecture(params->arch)); - log_infof(" style_flags: 0x%x\n", params->style_flags); - log_infof(" syntax: %i\n", params->syntax); - log_infof(" base_vaddr: 0x%I64x\n", params->base_vaddr); - log_infof(" dbgi_key: [%S 0x%I64x]\n", params->dbgi_key.path, params->dbgi_key.min_timestamp); + LogInfoNamedBlockF("dasm_new_node") + { + log_infof("hash: [0x%I64x 0x%I64x]\n", hash.u64[0], hash.u64[1]); + log_infof("vaddr: 0x%I64x\n", params->vaddr); + log_infof("arch: %S\n", string_from_architecture(params->arch)); + log_infof("style_flags: 0x%x\n", params->style_flags); + log_infof("syntax: %i\n", params->syntax); + log_infof("base_vaddr: 0x%I64x\n", params->base_vaddr); + log_infof("dbgi_key: [%S 0x%I64x]\n", params->dbgi_key.path, params->dbgi_key.min_timestamp); + } node = stripe->free_node; if(node) { diff --git a/src/dbgi/dbgi.c b/src/dbgi/dbgi.c index 6fa63320..e29085ad 100644 --- a/src/dbgi/dbgi.c +++ b/src/dbgi/dbgi.c @@ -294,7 +294,7 @@ di_open(DI_Key *key) U64 stripe_idx = slot_idx%di_shared->stripes_count; DI_Slot *slot = &di_shared->slots[slot_idx]; DI_Stripe *stripe = &di_shared->stripes[stripe_idx]; - log_infof("opening debug info: %S [0x%I64x]\n", key_normalized.path, key_normalized.min_timestamp); + log_infof("open_debug_info: {\"%S\", 0x%I64x}\n", key_normalized.path, key_normalized.min_timestamp); OS_MutexScopeW(stripe->rw_mutex) { //- rjf: find existing node @@ -350,7 +350,7 @@ di_close(DI_Key *key) U64 stripe_idx = slot_idx%di_shared->stripes_count; DI_Slot *slot = &di_shared->slots[slot_idx]; DI_Stripe *stripe = &di_shared->stripes[stripe_idx]; - log_infof("closing debug info: %S [0x%I64x]\n", key_normalized.path, key_normalized.min_timestamp); + log_infof("close_debug_info: {\"%S\", 0x%I64x}\n", key_normalized.path, key_normalized.min_timestamp); OS_MutexScopeW(stripe->rw_mutex) { //- rjf: find existing node diff --git a/src/demon/demon_core.h b/src/demon/demon_core.h index 53d3ef99..53866179 100644 --- a/src/demon/demon_core.h +++ b/src/demon/demon_core.h @@ -217,6 +217,11 @@ internal void dmn_access_close(void); #define DMN_AccessScope DeferLoopChecked(dmn_access_open(), dmn_access_close()) //- rjf: processes +internal U64 dmn_process_memory_reserve(DMN_Handle process, U64 vaddr, U64 size); +internal void dmn_process_memory_commit(DMN_Handle process, U64 vaddr, U64 size); +internal void dmn_process_memory_decommit(DMN_Handle process, U64 vaddr, U64 size); +internal void dmn_process_memory_release(DMN_Handle process, U64 vaddr, U64 size); +internal void dmn_process_memory_protect(DMN_Handle process, U64 vaddr, U64 size, OS_AccessFlags flags); internal U64 dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst); internal B32 dmn_process_write(DMN_Handle process, Rng1U64 range, void *src); #define dmn_process_read_struct(process, vaddr, ptr) dmn_process_read((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr) diff --git a/src/demon/win32/demon_core_win32.c b/src/demon/win32/demon_core_win32.c index 71679442..e1aa23ad 100644 --- a/src/demon/win32/demon_core_win32.c +++ b/src/demon/win32/demon_core_win32.c @@ -2581,6 +2581,73 @@ dmn_access_close(void) //- rjf: processes +internal U64 +dmn_process_memory_reserve(DMN_Handle process, U64 vaddr, U64 size) +{ + U64 result = 0; + DMN_AccessScope + { + DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); + result = (U64)VirtualAllocEx(process_entity->handle, (void *)vaddr, size, MEM_RESERVE, PAGE_READWRITE); + if(result == 0) + { + result = (U64)VirtualAllocEx(process_entity->handle, 0, size, MEM_RESERVE, PAGE_READWRITE); + } + } + return result; +} + +internal void +dmn_process_memory_commit(DMN_Handle process, U64 vaddr, U64 size) +{ + DMN_AccessScope + { + DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); + (U64)VirtualAllocEx(process_entity->handle, (void *)vaddr, size, MEM_COMMIT, PAGE_READWRITE); + } +} + +internal void +dmn_process_memory_decommit(DMN_Handle process, U64 vaddr, U64 size) +{ + DMN_AccessScope + { + DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); + VirtualFreeEx(process_entity->handle, (void *)vaddr, size, MEM_DECOMMIT); + } +} + +internal void +dmn_process_memory_release(DMN_Handle process, U64 vaddr, U64 size) +{ + DMN_AccessScope + { + DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); + VirtualFreeEx(process_entity->handle, (void *)vaddr, 0, MEM_RELEASE); + } +} + +internal void +dmn_process_memory_protect(DMN_Handle process, U64 vaddr, U64 size, OS_AccessFlags flags) +{ + DMN_AccessScope + { + DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); + DWORD old_flags = 0; + DWORD new_flags = PAGE_NOACCESS; + switch(flags) + { + default:{}break; + case OS_AccessFlag_Execute:{new_flags = PAGE_EXECUTE;}break; + case OS_AccessFlag_Execute|OS_AccessFlag_Read:{new_flags = PAGE_EXECUTE_READ;}break; + case OS_AccessFlag_Execute|OS_AccessFlag_Read|OS_AccessFlag_Write:{new_flags = PAGE_EXECUTE_READWRITE;}break; + case OS_AccessFlag_Read:{new_flags = PAGE_READONLY;}break; + case OS_AccessFlag_Read|OS_AccessFlag_Write:{new_flags = PAGE_READWRITE;}break; + } + VirtualProtectEx(process_entity->handle, (void *)vaddr, size, new_flags, &old_flags); + } +} + internal U64 dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst) { diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index f10e2d1b..92adeccf 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -1814,7 +1814,11 @@ df_entity_alloc(DF_StateDeltaHistory *hist, DF_Entity *parent, DF_EntityKind kin df_entity_notify_mutation(entity); // rjf: log - log_infof("new entity: %S $%I64d\n", df_g_entity_kind_display_string_table[kind], entity->id); + LogInfoNamedBlockF("new_entity") + { + log_infof("kind: \"%S\"\n", df_g_entity_kind_display_string_table[kind]); + log_infof("id: $0x%I64x\n", entity->id); + } return entity; } @@ -1859,7 +1863,13 @@ df_entity_release(DF_StateDeltaHistory *hist, DF_Entity *entity) t->e = child; SLLQueuePush(first_task, last_task, t); } - log_infof("end entity: %S $%I64d\n", df_g_entity_kind_display_string_table[task->e->kind], task->e->id); + LogInfoNamedBlockF("end_entity") + { + String8 name = df_display_string_from_entity(scratch.arena, task->e); + log_infof("kind: \"%S\"\n", df_g_entity_kind_display_string_table[task->e->kind]); + log_infof("id: $0x%I64x\n", task->e->id); + log_infof("display_string: \"%S\"\n", name); + } df_state_delta_history_push_struct_delta(hist, &task->e->first); df_state_delta_history_push_struct_delta(hist, &task->e->last); df_state_delta_history_push_struct_delta(hist, &task->e->next); @@ -2860,8 +2870,8 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) DI_Key dbgi_key = df_dbgi_key_from_module(module); Architecture arch = df_architecture_from_entity(thread); U64 ip_vaddr = ctrl_query_cached_rip_from_thread(df_state->ctrl_entity_store, thread->ctrl_machine_id, thread->ctrl_handle); - log_infof(" ip_vaddr: 0x%I64x\n", ip_vaddr); - log_infof(" dbgi_key: {%S, 0x%I64x}\n", dbgi_key.path, dbgi_key.min_timestamp); + log_infof("ip_vaddr: 0x%I64x\n", ip_vaddr); + log_infof("dbgi_key: {%S, 0x%I64x}\n", dbgi_key.path, dbgi_key.min_timestamp); // rjf: ip => line vaddr range Rng1U64 line_vaddr_rng = {0}; @@ -2873,8 +2883,8 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) { line_vaddr_rng = df_vaddr_range_from_voff_range(module, line_voff_rng); } - log_infof(" line: {%S:%I64i}\n", line_info.file->name, line_info.pt.line); - log_infof(" voff_range: {0x%I64x, 0x%I64x}\n", line_info.voff_range.min, line_info.voff_range.max); + log_infof("line: {%S:%I64i}\n", line_info.file->name, line_info.pt.line); + log_infof("voff_range: {0x%I64x, 0x%I64x}\n", line_info.voff_range.min, line_info.voff_range.max); } // rjf: opl line_vaddr_rng -> 0xf00f00 or 0xfeefee? => include in line vaddr range @@ -2899,25 +2909,22 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) { CTRL_ProcessMemorySlice machine_code_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, line_vaddr_rng, os_now_microseconds()+50000); machine_code = machine_code_slice.data; - log_infof(" machine_code_slice:\n {\n"); - log_infof(" stale: %i\n", machine_code_slice.stale); - log_infof(" any_byte_bad: %i\n", machine_code_slice.any_byte_bad); - log_infof(" any_byte_changed: %i\n", machine_code_slice.any_byte_changed); - log_infof(" [\n"); - for(U64 idx = 0; idx < machine_code_slice.data.size; idx += 1) + LogInfoNamedBlockF("machine_code_slice") { - if(idx%16 == 0) + log_infof("stale: %i\n", machine_code_slice.stale); + log_infof("any_byte_bad: %i\n", machine_code_slice.any_byte_bad); + log_infof("any_byte_changed: %i\n", machine_code_slice.any_byte_changed); + log_infof("bytes:\n[\n"); + for(U64 idx = 0; idx < machine_code_slice.data.size; idx += 1) { - log_infof(" "); - } - log_infof("0x%x,", machine_code_slice.data.str[idx]); - if(idx%16 == 15 || idx+1 == machine_code_slice.data.size) - { - log_infof("\n"); + log_infof("0x%x,", machine_code_slice.data.str[idx]); + if(idx%16 == 15 || idx+1 == machine_code_slice.data.size) + { + log_infof("\n"); + } } + log_infof("]\n"); } - log_infof(" ]\n"); - log_infof(" }\n"); } // rjf: machine code => ctrl flow analysis @@ -2933,15 +2940,14 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) arch, line_vaddr_rng.min, machine_code); - log_infof(" ctrl_flow_info:\n {\n"); - log_infof(" flags: %x\n", ctrl_flow_info.flags); - log_infof(" exit_points:\n {\n"); - for(DF_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) + LogInfoNamedBlockF("ctrl_flow_info") { - log_infof(" {vaddr:0x%I64x, jump_dest_vaddr:0x%I64x, expected_sp_delta:0x%I64x, inst_flags:%x}\n", n->v.vaddr, n->v.jump_dest_vaddr, n->v.expected_sp_delta, n->v.inst_flags); + log_infof("flags: %x\n", ctrl_flow_info.flags); + LogInfoNamedBlockF("exit_points") for(DF_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) + { + log_infof("{vaddr:0x%I64x, jump_dest_vaddr:0x%I64x, expected_sp_delta:0x%I64x, inst_flags:%x}\n", n->v.vaddr, n->v.jump_dest_vaddr, n->v.expected_sp_delta, n->v.inst_flags); + } } - log_infof(" }\n"); - log_infof(" }\n"); } // rjf: push traps for all exit points @@ -3002,12 +3008,10 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) } // rjf: log - log_infof(" traps:\n {\n"); - for(CTRL_TrapNode *n = result.first; n != 0; n = n->next) + LogInfoNamedBlockF("traps") for(CTRL_TrapNode *n = result.first; n != 0; n = n->next) { - log_infof(" {flags:0x%x, vaddr:0x%I64x}\n", n->v.flags, n->v.vaddr); + log_infof("{flags:0x%x, vaddr:0x%I64x}\n", n->v.flags, n->v.vaddr); } - log_infof(" }\n"); scratch_end(scratch); log_infof("}\n\n"); @@ -6600,8 +6604,9 @@ df_push_cmd__root(DF_CmdParams *params, DF_CmdSpec *spec) { Temp scratch = scratch_begin(0, 0); DF_Entity *entity = df_entity_from_handle(params->entity); - log_infof("debug frontend command pushed: \"%S\"\n", spec->info.string); -#define HandleParamPrint(mem_name) if(!df_handle_match(df_handle_zero(), params->mem_name)) { log_infof("| %s: [0x%I64x, 0x%I64x]\n", #mem_name, params->mem_name.u64[0], params->mem_name.u64[1]); } + log_infof("df_cmd:\n{\n", spec->info.string); + log_infof("spec: \"%S\"\n", spec->info.string); +#define HandleParamPrint(mem_name) if(!df_handle_match(df_handle_zero(), params->mem_name)) { log_infof("%s: [0x%I64x, 0x%I64x]\n", #mem_name, params->mem_name.u64[0], params->mem_name.u64[1]); } HandleParamPrint(window); HandleParamPrint(panel); HandleParamPrint(dest_panel); @@ -6610,7 +6615,7 @@ df_push_cmd__root(DF_CmdParams *params, DF_CmdSpec *spec) if(!df_entity_is_nil(entity)) { String8 entity_name = df_display_string_from_entity(scratch.arena, entity); - log_infof("| entity: \"%S\"\n", entity_name); + log_infof("entity: \"%S\"\n", entity_name); } U64 idx = 0; for(DF_HandleNode *n = params->entity_list.first; n != 0; n = n->next, idx += 1) @@ -6619,22 +6624,22 @@ df_push_cmd__root(DF_CmdParams *params, DF_CmdSpec *spec) if(!df_entity_is_nil(entity)) { String8 entity_name = df_display_string_from_entity(scratch.arena, entity); - log_infof("| entity_list[%I64u]: \"%S\"\n", idx, entity_name); + log_infof("entity_list[%I64u]: \"%S\"\n", idx, entity_name); } } if(!df_cmd_spec_is_nil(params->cmd_spec)) { - log_infof("| cmd_spec: \"%S\"\n", params->cmd_spec->info.string); + log_infof("cmd_spec: \"%S\"\n", params->cmd_spec->info.string); } - if(params->string.size != 0) { log_infof("| string: \"%S\"\n", params->string); } - if(params->file_path.size != 0) { log_infof("| file_path: \"%S\"\n", params->file_path); } - if(params->text_point.line != 0) { log_infof("| text_point: [line:%I64d, col:%I64d]\n", params->text_point.line, params->text_point.column); } - if(params->vaddr != 0) { log_infof("| vaddr: 0x%I64x\n", params->vaddr); } - if(params->voff != 0) { log_infof("| voff: 0x%I64x\n", params->voff); } - if(params->index != 0) { log_infof("| index: 0x%I64x\n", params->index); } - if(params->base_unwind_index != 0) { log_infof("| base_unwind_index: 0x%I64x\n", params->base_unwind_index); } - if(params->inline_unwind_index != 0){ log_infof("| inline_unwind_index: 0x%I64x\n", params->inline_unwind_index); } - if(params->id != 0) { log_infof("| id: 0x%I64x\n", params->id); } + if(params->string.size != 0) { log_infof("string: \"%S\"\n", params->string); } + if(params->file_path.size != 0) { log_infof("file_path: \"%S\"\n", params->file_path); } + if(params->text_point.line != 0) { log_infof("text_point: [line:%I64d, col:%I64d]\n", params->text_point.line, params->text_point.column); } + if(params->vaddr != 0) { log_infof("vaddr: 0x%I64x\n", params->vaddr); } + if(params->voff != 0) { log_infof("voff: 0x%I64x\n", params->voff); } + if(params->index != 0) { log_infof("index: 0x%I64x\n", params->index); } + if(params->base_unwind_index != 0) { log_infof("base_unwind_index: 0x%I64x\n", params->base_unwind_index); } + if(params->inline_unwind_index != 0){ log_infof("inline_unwind_index: 0x%I64x\n", params->inline_unwind_index); } + if(params->id != 0) { log_infof("id: 0x%I64x\n", params->id); } if(params->os_event != 0) { String8 kind_string = str8_lit(""); @@ -6651,10 +6656,10 @@ df_push_cmd__root(DF_CmdParams *params, DF_CmdSpec *spec) case OS_EventKind_FileDrop: {kind_string = str8_lit("filedrop");}break; case OS_EventKind_Wakeup: {kind_string = str8_lit("wakeup");}break; } - log_infof("| os_event->kind: %S\n", kind_string); + log_infof("os_event->kind: %S\n", kind_string); } #undef HandleParamPrint - log_infof("--------------------------------\n"); + log_infof("}\n\n"); scratch_end(scratch); } df_cmd_list_push(df_state->root_cmd_arena, &df_state->root_cmds, params, spec); @@ -6847,8 +6852,8 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) { CTRL_Event *event = &event_n->v; log_infof("ctrl_event:\n{\n"); - log_infof(" kind: \"%S\"\n", ctrl_string_from_event_kind(event->kind)); - log_infof(" entity_id: %u\n", event->entity_id); + log_infof("kind: \"%S\"\n", ctrl_string_from_event_kind(event->kind)); + log_infof("entity_id: %u\n", event->entity_id); switch(event->kind) { default:{}break; @@ -6884,7 +6889,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) // rjf: select & snap to thread causing stop if(should_snap && stop_thread->kind == DF_EntityKind_Thread) { - log_infof(" stop_thread: \"%S\"\n", df_display_string_from_entity(scratch.arena, stop_thread)); + log_infof("stop_thread: \"%S\"\n", df_display_string_from_entity(scratch.arena, stop_thread)); DF_CmdParams params = df_cmd_params_zero(); params.entity = df_handle_from_entity(stop_thread); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); @@ -7207,7 +7212,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) case CTRL_EventKind_MemDecommit:{}break; case CTRL_EventKind_MemRelease:{}break; } - log_infof("}\n"); + log_infof("}\n\n"); } //- rjf: clear tls base cache @@ -8999,7 +9004,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) //- rjf: developer commands case DF_CoreCmdKind_LogMarker: { - log_infof("\n\n--- #marker ---\n\n"); + log_infof("\"#MARKER\""); }break; } } diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index 9db07fce..212666b1 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -338,7 +338,7 @@ entry_point(CmdLine *cmd_line) } if(msg.size != 0) { - log_infof("IPC message received: \"%S\"", msg); + log_infof("ipc_msg: \"%S\"", msg); DF_Window *dst_window = df_gfx_state->first_window; for(DF_Window *window = dst_window; window != 0; window = window->next) { From 3327d733730c2e740c3ec871be4756537d073cfb Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Wed, 19 Jun 2024 11:32:44 -0700 Subject: [PATCH 21/24] notes on memory-execution-exception spoof implementation situation, and toggles to switch to old behavior, for later investigation --- src/ctrl/ctrl_core.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index d0cfcdc4..f370f687 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -1,6 +1,46 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) +//////////////////////////////// +//~ rjf: Bug Hunt Behavior Enabling (2024/06/19) +// +// NOTE(rjf): For one reason or another, our approach of "spoofs" - +// overwriting a return address in a thread's stack to get a debug +// event when the thread returns from a particular frame - seemed +// to cause issues in particular cases. We previously would overwrite +// a return address on the stack to 911, and we'd get an invalid memory +// execution debug event whenever the thread moved there. Then, we'd +// simply move the thread back to where it was before, and continue. +// +// It seemed like, possibly, some code was seeing this event and/or +// other adjacent effects (e.g. a thread attempting to execute at an +// invalid address), and was freaking out, but it is very difficult +// to know exactly what is going on, since from the debugger's +// perspective, everything was fine, but upon resuming (after this +// memory-execution exception was caught), the process would +// immediately exit. So some external code must be doing something +// that we have not accounted for. +// +// To address this unknown, I've moved the "spoofs" back to being +// implemented by allocating an extra code page in target processes, +// and writing over them with int3s, and then instead of writing 911 +// into the stack, just writing the base address of that page. Hitting +// an unexpected int3 is a much more expected debugger pattern, and +// so my theory was that this would be less suspect to code which +// could be doing e.g. validation checks over code. The spoof still +// works the same way beyond that; we simply check that the int3 is +// within the "spoof page", and if it is, we return the thread back +// to the correct address. +// +// But, given my uncertainty about the exact cause/effect situation, +// I have left this comment, and a #define below to toggle the old +// behavior, so that we can investigate in the future. +// +// @nick - this is what you'd want to change from `0` to `1` if you +// want to take a look at this. + +#define CTRL_ENABLE_MEMORY_EXECUTE_EXCEPTION_SPOOFS 0 + //////////////////////////////// //~ rjf: Generated Code @@ -3621,11 +3661,19 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, void *regs_block = push_array(scratch.arena, U8, regs_block_size_from_architecture(arch)); dmn_thread_read_reg_block(spoof->thread, regs_block); U64 spoof_thread_rip = regs_rip_from_arch_block(arch, regs_block); +#if CTRL_ENABLE_MEMORY_EXECUTE_EXCEPTION_SPOOFS + if(spoof_thread_rip == spoof->new_ip_value) + { + regs_arch_block_write_rip(arch, regs_block, spoof_old_ip_value); + ctrl_thread_write_reg_block(CTRL_MachineID_Local, spoof->thread, regs_block); + } +#else if(spoof_thread_rip == spoof->new_ip_value+1) { regs_arch_block_write_rip(arch, regs_block, spoof_old_ip_value); ctrl_thread_write_reg_block(CTRL_MachineID_Local, spoof->thread, regs_block); } +#endif } //- rjf: push ctrl events associated with this demon event @@ -4015,7 +4063,11 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) DMN_Handle target_thread = msg->entity; DMN_Handle target_process = msg->parent; CTRL_Entity *target_process_entity = ctrl_entity_from_machine_id_handle(ctrl_state->ctrl_thread_entity_store, msg->machine_id, target_process); +#if CTRL_ENABLE_MEMORY_EXECUTE_EXCEPTION_SPOOFS + U64 spoof_ip_vaddr = 911; +#else U64 spoof_ip_vaddr = target_process_entity->vaddr_range.min; +#endif log_infof("ctrl_thread__run:\n{\n"); ////////////////////////////// @@ -4562,6 +4614,29 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) // //{ +#if CTRL_ENABLE_MEMORY_EXECUTE_EXCEPTION_SPOOFS + ////////////////////////// + //- rjf: handle if hitting a spoof + // + B32 exception_stop = 0; + B32 hit_spoof = 0; + if(!hard_stop && use_stepping_logic && event->kind == DMN_EventKind_Exception) + { + if(spoof_mode && + dmn_handle_match(target_process, event->process) && + dmn_handle_match(target_thread, event->thread) && + spoof.new_ip_value == event->instruction_pointer) + { + hit_spoof = 1; + log_infof("hit_spoof\n"); + } + else + { + exception_stop = 1; + use_stepping_logic = 0; + } + } +#else ////////////////////////// //- rjf: handle if hitting an exception // @@ -4587,6 +4662,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) log_infof("hit_spoof\n"); } } +#endif //- rjf: handle spoof hit if(hit_spoof) From 435877824a7fcc56ad1d860c700d85685a7e944a Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Wed, 19 Jun 2024 11:56:47 -0700 Subject: [PATCH 22/24] oh NO... never mind... mystery solved... be VERY CAREFUL ABOUT STATE MACHINES! fixes incorrect non-resets of win32 demon 'exception not handled' state, which was buggily leading to DBG_EXCEPTION_NOT_HANDLED being passed to ContinueDebugEvent --- src/ctrl/ctrl_core.c | 102 +---------------------------- src/demon/win32/demon_core_win32.c | 2 +- 2 files changed, 2 insertions(+), 102 deletions(-) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index f370f687..631821b7 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -1,46 +1,6 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -//////////////////////////////// -//~ rjf: Bug Hunt Behavior Enabling (2024/06/19) -// -// NOTE(rjf): For one reason or another, our approach of "spoofs" - -// overwriting a return address in a thread's stack to get a debug -// event when the thread returns from a particular frame - seemed -// to cause issues in particular cases. We previously would overwrite -// a return address on the stack to 911, and we'd get an invalid memory -// execution debug event whenever the thread moved there. Then, we'd -// simply move the thread back to where it was before, and continue. -// -// It seemed like, possibly, some code was seeing this event and/or -// other adjacent effects (e.g. a thread attempting to execute at an -// invalid address), and was freaking out, but it is very difficult -// to know exactly what is going on, since from the debugger's -// perspective, everything was fine, but upon resuming (after this -// memory-execution exception was caught), the process would -// immediately exit. So some external code must be doing something -// that we have not accounted for. -// -// To address this unknown, I've moved the "spoofs" back to being -// implemented by allocating an extra code page in target processes, -// and writing over them with int3s, and then instead of writing 911 -// into the stack, just writing the base address of that page. Hitting -// an unexpected int3 is a much more expected debugger pattern, and -// so my theory was that this would be less suspect to code which -// could be doing e.g. validation checks over code. The spoof still -// works the same way beyond that; we simply check that the int3 is -// within the "spoof page", and if it is, we return the thread back -// to the correct address. -// -// But, given my uncertainty about the exact cause/effect situation, -// I have left this comment, and a #define below to toggle the old -// behavior, so that we can investigate in the future. -// -// @nick - this is what you'd want to change from `0` to `1` if you -// want to take a look at this. - -#define CTRL_ENABLE_MEMORY_EXECUTE_EXCEPTION_SPOOFS 0 - //////////////////////////////// //~ rjf: Generated Code @@ -860,7 +820,6 @@ ctrl_entity_store_apply_events(CTRL_EntityStore *store, CTRL_EventList *list) { CTRL_Entity *machine = ctrl_entity_from_machine_id_handle(store, event->machine_id, dmn_handle_zero()); CTRL_Entity *process = ctrl_entity_alloc(store, machine, CTRL_EntityKind_Process, event->arch, event->machine_id, event->entity, (U64)event->entity_id); - process->vaddr_range = event->vaddr_rng; }break; case CTRL_EventKind_EndProc: { @@ -3661,19 +3620,11 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, void *regs_block = push_array(scratch.arena, U8, regs_block_size_from_architecture(arch)); dmn_thread_read_reg_block(spoof->thread, regs_block); U64 spoof_thread_rip = regs_rip_from_arch_block(arch, regs_block); -#if CTRL_ENABLE_MEMORY_EXECUTE_EXCEPTION_SPOOFS if(spoof_thread_rip == spoof->new_ip_value) { regs_arch_block_write_rip(arch, regs_block, spoof_old_ip_value); ctrl_thread_write_reg_block(CTRL_MachineID_Local, spoof->thread, regs_block); } -#else - if(spoof_thread_rip == spoof->new_ip_value+1) - { - regs_arch_block_write_rip(arch, regs_block, spoof_old_ip_value); - ctrl_thread_write_reg_block(CTRL_MachineID_Local, spoof->thread, regs_block); - } -#endif } //- rjf: push ctrl events associated with this demon event @@ -3683,12 +3634,6 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, default:{}break; case DMN_EventKind_CreateProcess: { - U64 spoof_space_size = KB(4); - U64 spoof_space_vaddr = dmn_process_memory_reserve(event->process, 0, spoof_space_size); - U64 spoof_space_code = 0xcccccccc; - dmn_process_memory_commit(event->process, spoof_space_vaddr, spoof_space_size); - dmn_process_memory_protect(event->process, spoof_space_vaddr, spoof_space_size, OS_AccessFlag_Read|OS_AccessFlag_Write|OS_AccessFlag_Execute); - dmn_process_write(event->process, r1u64(spoof_space_vaddr, spoof_space_vaddr+sizeof(spoof_space_code)), &spoof_space_code); CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); out_evt->kind = CTRL_EventKind_NewProc; out_evt->msg_id = msg->msg_id; @@ -3696,7 +3641,6 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, out_evt->entity = event->process; out_evt->arch = event->arch; out_evt->entity_id = event->code; - out_evt->vaddr_rng = r1u64(spoof_space_vaddr, spoof_space_vaddr+spoof_space_size); ctrl_state->process_counter += 1; }break; case DMN_EventKind_CreateThread: @@ -4063,11 +4007,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) DMN_Handle target_thread = msg->entity; DMN_Handle target_process = msg->parent; CTRL_Entity *target_process_entity = ctrl_entity_from_machine_id_handle(ctrl_state->ctrl_thread_entity_store, msg->machine_id, target_process); -#if CTRL_ENABLE_MEMORY_EXECUTE_EXCEPTION_SPOOFS U64 spoof_ip_vaddr = 911; -#else - U64 spoof_ip_vaddr = target_process_entity->vaddr_range.min; -#endif log_infof("ctrl_thread__run:\n{\n"); ////////////////////////////// @@ -4323,23 +4263,11 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) case DMN_EventKind_Error: case DMN_EventKind_Halt: case DMN_EventKind_SingleStep: + case DMN_EventKind_Trap: { hard_stop = 1; log_infof("step_rule: unexpected -> hard_stop\n"); }break; - case DMN_EventKind_Trap: - { - if(event->instruction_pointer == spoof_ip_vaddr) - { - use_stepping_logic = 1; - log_infof("step_rule: spoof trap -> stepping_logic\n"); - } - else - { - hard_stop = 1; - log_infof("step_rule: unexpected trap -> hard_stop\n"); - } - }break; case DMN_EventKind_Exception: case DMN_EventKind_Breakpoint: { @@ -4614,7 +4542,6 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) // //{ -#if CTRL_ENABLE_MEMORY_EXECUTE_EXCEPTION_SPOOFS ////////////////////////// //- rjf: handle if hitting a spoof // @@ -4636,33 +4563,6 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) use_stepping_logic = 0; } } -#else - ////////////////////////// - //- rjf: handle if hitting an exception - // - B32 exception_stop = 0; - if(!hard_stop && use_stepping_logic && event->kind == DMN_EventKind_Exception) - { - exception_stop = 1; - use_stepping_logic = 0; - } - - ////////////////////////// - //- rjf: handle if hitting a spoof - // - B32 hit_spoof = 0; - if(!hard_stop && use_stepping_logic && event->kind == DMN_EventKind_Trap) - { - if(spoof_mode && - dmn_handle_match(target_process, event->process) && - dmn_handle_match(target_thread, event->thread) && - spoof.new_ip_value == event->instruction_pointer) - { - hit_spoof = 1; - log_infof("hit_spoof\n"); - } - } -#endif //- rjf: handle spoof hit if(hit_spoof) diff --git a/src/demon/win32/demon_core_win32.c b/src/demon/win32/demon_core_win32.c index e1aa23ad..fcf18d1f 100644 --- a/src/demon/win32/demon_core_win32.c +++ b/src/demon/win32/demon_core_win32.c @@ -1609,9 +1609,9 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) { if(dmn_w32_shared->exception_not_handled && !ctrls->ignore_previous_exception) { - dmn_w32_shared->exception_not_handled = 0; resume_code = DBG_EXCEPTION_NOT_HANDLED; } + dmn_w32_shared->exception_not_handled = 0; } //////////////////////// From b5b5aca69147cc64264bfac15df4f7b7caf641a7 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Wed, 19 Jun 2024 12:07:08 -0700 Subject: [PATCH 23/24] log win32 demon resume code --- src/demon/win32/demon_core_win32.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/demon/win32/demon_core_win32.c b/src/demon/win32/demon_core_win32.c index fcf18d1f..39ac97bb 100644 --- a/src/demon/win32/demon_core_win32.c +++ b/src/demon/win32/demon_core_win32.c @@ -1609,8 +1609,13 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) { if(dmn_w32_shared->exception_not_handled && !ctrls->ignore_previous_exception) { + log_infof("using DBG_EXCEPTION_NOT_HANDLED\n"); resume_code = DBG_EXCEPTION_NOT_HANDLED; } + else + { + log_infof("using DBG_CONTINUE\n"); + } dmn_w32_shared->exception_not_handled = 0; } From 6eef8c3e16219863c68d419aa5c3047c788e5cbf Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Wed, 19 Jun 2024 13:27:34 -0700 Subject: [PATCH 24/24] rdi_format_parse: prefer line info idxs with file coordinates in line mapping helper --- src/lib_rdi_format/rdi_format_parse.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib_rdi_format/rdi_format_parse.c b/src/lib_rdi_format/rdi_format_parse.c index a2a3fd2f..9a2769fb 100644 --- a/src/lib_rdi_format/rdi_format_parse.c +++ b/src/lib_rdi_format/rdi_format_parse.c @@ -302,6 +302,14 @@ rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff) { RDI_U64 count = 0; RDI_U64 result = rdi_line_info_idx_range_from_voff(line_info, voff, &count); + for(RDI_U64 idx = 0; idx < count && result+idx < line_info->count; idx += 1) + { + if(line_info->lines[result+idx].file_idx != 0) + { + result += idx; + break; + } + } return result; }