diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 88e92774..ad04c82f 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -1110,6 +1110,146 @@ ctrl_tls_root_vaddr_from_thread(CTRL_MachineID machine_id, CTRL_Handle thread) return result; } +//- rjf: process * vaddr -> module + +internal CTRL_Handle +ctrl_module_from_process_vaddr(CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr) +{ + CTRL_Handle handle = {0}; + { + Temp scratch = scratch_begin(0, 0); + DEMON_HandleArray modules = demon_modules_from_process(scratch.arena, ctrl_demon_handle_from_ctrl(process)); + for(U64 idx = 0; idx < modules.count; idx += 1) + { + DEMON_Handle m = modules.handles[idx]; + Rng1U64 m_vaddr_rng = demon_vaddr_range_from_module(m); + if(contains_1u64(m_vaddr_rng, vaddr)) + { + handle = ctrl_handle_from_demon(m); + break; + } + } + scratch_end(scratch); + } + return handle; +} + +//- rjf: unwinding + +internal CTRL_Unwind +ctrl_unwind_from_process_thread(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, CTRL_Handle thread) +{ + ProfBeginFunction(); + Temp scratch = scratch_begin(&arena, 1); + DBGI_Scope *scope = dbgi_scope_open(); + Architecture arch = demon_arch_from_object(ctrl_demon_handle_from_ctrl(thread)); + U64 arch_reg_block_size = regs_block_size_from_architecture(arch); + CTRL_Unwind unwind = {0}; + unwind.error = 1; + switch(arch) + { + default:{}break; + case Architecture_x64: + { + // rjf: grab initial register block + void *regs_block = push_array(scratch.arena, U8, arch_reg_block_size); + B32 regs_block_good = 0; + { + void *regs_raw = ctrl_reg_block_from_thread(machine_id, thread); + if(regs_raw != 0) + { + MemoryCopy(regs_block, regs_raw, arch_reg_block_size); + regs_block_good = 1; + } + } + + // rjf: grab initial memory view + B32 stack_memview_good = 0; + UNW_MemView stack_memview = {0}; + if(regs_block_good) + { + U64 stack_base_unrounded = demon_stack_base_vaddr_from_thread(ctrl_demon_handle_from_ctrl(thread)); + U64 stack_top_unrounded = regs_rsp_from_arch_block(arch, regs_block); + U64 stack_base = AlignPow2(stack_base_unrounded, KB(4)); + U64 stack_top = AlignDownPow2(stack_top_unrounded, KB(4)); + U64 stack_size = stack_base - stack_top; + if(stack_base >= stack_top) + { + String8 stack_memory = {0}; + stack_memory.str = push_array_no_zero(scratch.arena, U8, stack_size); + stack_memory.size = ctrl_process_read(machine_id, process, r1u64(stack_top, stack_top+stack_size), stack_memory.str); + if(stack_memory.size != 0) + { + stack_memview_good = 1; + stack_memview.data = stack_memory.str; + stack_memview.addr_first = stack_top; + stack_memview.addr_opl = stack_base; + } + } + } + + // rjf: loop & unwind + UNW_MemView memview = stack_memview; + if(stack_memview_good) for(;;) + { + unwind.error = 0; + + // rjf: regs -> rip*module*binary + U64 rip = regs_rip_from_arch_block(arch, regs_block); + CTRL_Handle module = ctrl_module_from_process_vaddr(machine_id, process, rip); + + // rjf: cancel on 0 rip + if(rip == 0) + { + break; + } + + // rjf: binary -> all the binary info + String8 binary_full_path = demon_full_path_from_module(scratch.arena, ctrl_demon_handle_from_ctrl(module)); + DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, binary_full_path, 0); + String8 binary_data = str8((U8 *)dbgi->exe_base, dbgi->exe_props.size); + + // rjf: cancel on bad data + if(binary_data.size == 0) + { + unwind.error = 1; + break; + } + + // rjf: valid step -> push frame + CTRL_UnwindFrame *frame = push_array(arena, CTRL_UnwindFrame, 1); + frame->rip = rip; + frame->regs = push_array_no_zero(arena, U8, arch_reg_block_size); + MemoryCopy(frame->regs, regs_block, arch_reg_block_size); + SLLQueuePush(unwind.first, unwind.last, frame); + unwind.count += 1; + + // rjf: unwind one step + UNW_Result unwind_step = unw_pe_x64(binary_data, &dbgi->pe, demon_vaddr_range_from_module(ctrl_demon_handle_from_ctrl(module)).min, &memview, (UNW_X64_Regs *)regs_block); + + // rjf: cancel on bad step + if(unwind_step.dead != 0) + { + break; + } + if(unwind_step.missed_read != 0) + { + unwind.error = 1; + break; + } + if(unwind_step.stack_pointer == 0) + { + break; + } + } + }break; + } + dbgi_scope_close(scope); + scratch_end(scratch); + ProfEnd(); + return unwind; +} + //- rjf: name -> register/alias hash tables, for eval internal EVAL_String2NumMap * @@ -1419,6 +1559,67 @@ ctrl_thread__next_demon_event(Arena *arena, CTRL_Msg *msg, DEMON_RunCtrls *run_c should_filter_event = 0; } } + + // rjf: special case: be gracious with ASan modules or symbols if + // they do their cute little 0xc0000005 exception trick... + if(!should_filter_event && ev->code == 0xc0000005 && + (spoof == 0 || ev->instruction_pointer != spoof->new_ip_value)) + { + DBGI_Scope *scope = dbgi_scope_open(); + DEMON_HandleArray modules = demon_modules_from_process(scratch.arena, ev->process); + if(modules.count != 0) + { + // rjf: determine base address of asan shadow space + U64 asan_shadow_base_vaddr = 0; + B32 asan_shadow_variable_exists_but_is_zero = 0; + CTRL_Handle module = ctrl_handle_from_demon(modules.handles[0]); + String8 module_path = demon_full_path_from_module(scratch.arena, ctrl_demon_handle_from_ctrl(module)); + DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, module_path, max_U64); + RADDBG_Parsed *rdbg = &dbgi->rdbg; + RADDBG_NameMap *unparsed_map = raddbg_name_map_from_kind(rdbg, RADDBG_NameMapKind_GlobalVariables); + if(rdbg->global_variables != 0 && unparsed_map != 0) + { + RADDBG_ParsedNameMap map = {0}; + raddbg_name_map_parse(rdbg, unparsed_map, &map); + String8 name = str8_lit("__asan_shadow_memory_dynamic_address"); + RADDBG_NameMapNode *node = raddbg_name_map_lookup(rdbg, &map, name.str, name.size); + if(node != 0) + { + U32 id_count = 0; + U32 *ids = raddbg_matches_from_map_node(rdbg, node, &id_count); + if(id_count > 0 && 0 < ids[0] && ids[0] < rdbg->global_variable_count) + { + RADDBG_GlobalVariable *global_var = &rdbg->global_variables[ids[0]]; + U64 global_var_voff = global_var->voff; + U64 global_var_vaddr = global_var->voff + demon_base_vaddr_from_module(ctrl_demon_handle_from_ctrl(module)); + Architecture arch = demon_arch_from_object(ev->thread); + U64 addr_size = bit_size_from_arch(arch)/8; + ctrl_process_read(CTRL_MachineID_Client, ctrl_handle_from_demon(ev->process), r1u64(global_var_vaddr, global_var_vaddr+addr_size), &asan_shadow_base_vaddr); + asan_shadow_variable_exists_but_is_zero = (asan_shadow_base_vaddr == 0); + } + } + } + + // rjf: determine if this was a read/write to the shadow space + B32 violation_in_shadow_space = 0; + if(asan_shadow_base_vaddr != 0) + { + U64 asan_shadow_space_size = TB(128)/8; + if(asan_shadow_base_vaddr <= ev->address && ev->address < asan_shadow_base_vaddr+asan_shadow_space_size) + { + violation_in_shadow_space = 1; + } + } + + // rjf: filter event if this violation occurred in asan's shadow space + if(violation_in_shadow_space || asan_shadow_variable_exists_but_is_zero) + { + should_filter_event = 1; + } + } + + dbgi_scope_close(scope); + } }break; } } diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index baea3a53..6947bde7 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -46,6 +46,26 @@ struct CTRL_MachineIDHandlePairList U64 count; }; +//////////////////////////////// +//~ rjf: Unwind Types + +typedef struct CTRL_UnwindFrame CTRL_UnwindFrame; +struct CTRL_UnwindFrame +{ + CTRL_UnwindFrame *next; + U64 rip; + void *regs; +}; + +typedef struct CTRL_Unwind CTRL_Unwind; +struct CTRL_Unwind +{ + CTRL_UnwindFrame *first; + CTRL_UnwindFrame *last; + U64 count; + B32 error; +}; + //////////////////////////////// //~ rjf: Trap Types @@ -552,6 +572,12 @@ internal U64 ctrl_rip_from_thread(CTRL_MachineID machine_id, CTRL_Handle thread) internal B32 ctrl_thread_write_rip(CTRL_MachineID machine_id, CTRL_Handle thread, U64 rip); internal U64 ctrl_tls_root_vaddr_from_thread(CTRL_MachineID machine_id, CTRL_Handle thread); +//- rjf: process * vaddr -> module +internal CTRL_Handle ctrl_module_from_process_vaddr(CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr); + +//- rjf: unwinding +internal CTRL_Unwind ctrl_unwind_from_thread(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle thread); + //- rjf: name -> register/alias hash tables, for eval internal EVAL_String2NumMap *ctrl_string2reg_from_arch(Architecture arch); internal EVAL_String2NumMap *ctrl_string2alias_from_arch(Architecture arch); diff --git a/src/demon/win32/demon_os_win32.c b/src/demon/win32/demon_os_win32.c index d4911e65..45d3775c 100644 --- a/src/demon/win32/demon_os_win32.c +++ b/src/demon/win32/demon_os_win32.c @@ -861,6 +861,7 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){ // init new entity DEMON_Entity *module = demon_ent_new(process, DEMON_EntityKind_Module, module_base); + module->addr_range_dim = image_info.size; demon_module_count += 1; DEMON_W32_Ext *module_ext = demon_w32_ext_alloc(); module->ext = module_ext; diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index 23543b74..64e659c6 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -3501,14 +3501,14 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D color.y *= 0.7f; color.z *= 0.7f; ui_set_next_background_color(color); - if(is_frozen && df_icon_buttonf(DF_IconKind_Locked, "Thaw").clicked) + if(is_frozen && df_icon_buttonf(DF_IconKind_Locked, "Thaw###freeze_thaw").clicked) { DF_CmdParams params = df_cmd_params_from_window(ws); params.entity = df_handle_from_entity(entity); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_ThawEntity)); } - if(!is_frozen && df_icon_buttonf(DF_IconKind_Unlocked, "Freeze").clicked) + if(!is_frozen && df_icon_buttonf(DF_IconKind_Unlocked, "Freeze###freeze_thaw").clicked) { DF_CmdParams params = df_cmd_params_from_window(ws); params.entity = df_handle_from_entity(entity); @@ -3603,9 +3603,9 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D B32 is_selected = df_handle_match(ctrl_ctx.thread, df_handle_from_entity(entity)); if(is_selected) { - df_icon_buttonf(DF_IconKind_Thread, "[Selected]"); + df_icon_buttonf(DF_IconKind_Thread, "[Selected]###select_entity"); } - else if(df_icon_buttonf(DF_IconKind_Thread, "Select").clicked) + else if(df_icon_buttonf(DF_IconKind_Thread, "Select###select_entity").clicked) { DF_CmdParams params = df_cmd_params_from_window(ws); params.entity = df_handle_from_entity(entity); diff --git a/src/mule/mule_main.cpp b/src/mule/mule_main.cpp index 08c591aa..acb7f802 100644 --- a/src/mule/mule_main.cpp +++ b/src/mule/mule_main.cpp @@ -1402,7 +1402,6 @@ extended_type_coverage_eval_tests(void){ non_virtual_derived->x += 1; non_virtual_derived->x += 1; non_virtual_derived->x += 1; - delete non_virtual_derived; Base *base_array[1024] = {0}; for(int i = 0; i < sizeof(base_array)/sizeof(base_array[0]); i += 1) diff --git a/src/raddbg/raddbg.h b/src/raddbg/raddbg.h index 81ea052a..85a57473 100644 --- a/src/raddbg/raddbg.h +++ b/src/raddbg/raddbg.h @@ -17,8 +17,6 @@ // progress bar in the disassembly window. I had to close and restart. Is // console app debugging not working yet, perhaps? // -// [ ] register value committing in watch -// // [ ] Setting the code_font/main_font values to a font name doesn't work. // Should probably make note that you have to set it to a path to a TTF, // since that's not normally how Windows fonts work. @@ -27,7 +25,6 @@ // // [ ] disasm animation & go-to-address // -// [ ] visualize mismatched source code and debug info // [ ] visualize remapped files (via path map) ////////////////////////////////