From fddf353ea02ebc1b817faabebcb64a9892c9f4c9 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Sat, 16 May 2026 18:26:23 -0700 Subject: [PATCH] minidump format types; open crash dump command, stub out opening path in control thread; expand d_handles to support machine id, entity id, *and* 'controller kind', which can be either a dump file or a demon - this properly separates the true process control abstraction (demon) from opening a regular dump file on any machine, which will let us trivially support any kind of dump file on any platform; also fix bad cfg tree state leak --- src/config/config_core.c | 4 +- src/dbg_engine/dbg_engine.mdesk | 3 + src/dbg_engine/dbg_engine_core.h | 26 +- src/dbg_engine/dbg_engine_ctrl.c | 341 ++++++++++++--------- src/dbg_engine/dbg_engine_ctrl.h | 4 +- src/dbg_engine/dbg_engine_user.c | 14 +- src/dbg_engine/dbg_engine_user.h | 1 + src/dbg_engine/generated/dbg_engine.meta.h | 1 + src/dbg_info/dbg_info.c | 2 +- src/minidump/minidump.c | 2 + src/minidump/minidump.h | 200 ++++++++++++ src/minidump/minidump_parse.c | 3 + src/minidump/minidump_parse.h | 28 ++ src/mule/mule_main.cpp | 6 +- src/raddbg/generated/raddbg.meta.c | 6 +- src/raddbg/generated/raddbg.meta.h | 3 +- src/raddbg/raddbg_core.c | 11 +- src/raddbg/raddbg_main.c | 4 + src/raddbg/raddbg_widgets.c | 2 +- 19 files changed, 496 insertions(+), 165 deletions(-) create mode 100644 src/minidump/minidump.c create mode 100644 src/minidump/minidump.h create mode 100644 src/minidump/minidump_parse.c create mode 100644 src/minidump/minidump_parse.h diff --git a/src/config/config_core.c b/src/config/config_core.c index 65ad565e..e58d5320 100644 --- a/src/config/config_core.c +++ b/src/config/config_core.c @@ -649,13 +649,13 @@ cfg_node_release(CFG_State *state, CFG_Node *node) for(CFG_NodePtrNode *n = nodes.first; n != 0; n = n->next) { CFG_Node *c = n->v; + U64 hash = u64_hash_from_str8(str8_struct(&c->id)); + U64 slot_idx = hash%state->ctx.id_slots_count; cfg_string_release(state, c->string); SLLStackPush(state->free, c); c->first = c->last = c->prev = c->parent = 0; c->id = 0; c->string = str8_zero(); - U64 hash = u64_hash_from_str8(str8_struct(&c->id)); - U64 slot_idx = hash%state->ctx.id_slots_count; for(CFG_NodePtrNode *n = state->ctx.id_slots[slot_idx].first; n != 0; n = n->next) { if(n->v == c) diff --git a/src/dbg_engine/dbg_engine.mdesk b/src/dbg_engine/dbg_engine.mdesk index 24328506..1424bc48 100644 --- a/src/dbg_engine/dbg_engine.mdesk +++ b/src/dbg_engine/dbg_engine.mdesk @@ -50,6 +50,9 @@ D_CmdTable: // | | | | //- rjf: attaching {Attach 1 1 0 0 "query:unattached_processes" PID null Nil Null 0 0 0 0 0 1 1 Null "attach" "Attach" "Attaches to a process that is already running on the local machine." "" "" } + + //- rjf: crash dump opening + {OpenCrashDump 1 1 0 0 `folder:\\"$input\\"` FilePath null Nil Null 0 0 0 0 0 1 1 Null "open_crash_dump" "Open Crash Dump" "Opens a crash dump file and recreates debuggee state at the time of the crash." "" "" } } @enum D_CmdKind: diff --git a/src/dbg_engine/dbg_engine_core.h b/src/dbg_engine/dbg_engine_core.h index 68b68b92..95544f36 100644 --- a/src/dbg_engine/dbg_engine_core.h +++ b/src/dbg_engine/dbg_engine_core.h @@ -8,7 +8,13 @@ //~ rjf: ID Types typedef U64 D_MsgID; -typedef U64 D_MachineID; +typedef U32 D_MachineID; +typedef U32 D_ControllerKind; +enum +{ + D_ControllerKind_Demon, + D_ControllerKind_Dump, +}; #define D_MachineID_Local (1) @@ -19,7 +25,8 @@ typedef struct D_Handle D_Handle; struct D_Handle { D_MachineID machine_id; - DMN_Handle dmn_handle; + D_ControllerKind controller_kind; + U64 entity_id; }; typedef struct D_HandleNode D_HandleNode; @@ -227,6 +234,21 @@ struct D_EntityCtxLookupAccel U64 entity_kind_arrays_gens[D_EntityKind_COUNT]; }; +//////////////////////////////// +//~ rjf: Opened Dump Cache Types + +typedef struct D_DumpNode D_DumpNode; +struct D_DumpNode +{ + D_DumpNode *next; + D_DumpNode *prev; + D_Handle process; + File file; + FileProperties props; + FileMap map; + void *base; +}; + //////////////////////////////// //~ rjf: Tick Input Types diff --git a/src/dbg_engine/dbg_engine_ctrl.c b/src/dbg_engine/dbg_engine_ctrl.c index d5b75eb2..4ab8bc62 100644 --- a/src/dbg_engine/dbg_engine_ctrl.c +++ b/src/dbg_engine/dbg_engine_ctrl.c @@ -7,8 +7,8 @@ internal U64 d_hash_from_handle(D_Handle handle) { - U64 buf[] = {handle.machine_id, handle.dmn_handle.u64[0]}; - U64 hash = u64_hash_from_str8(str8((U8 *)buf, sizeof(buf))); + U64 buf[] = {handle.machine_id, handle.controller_kind, handle.entity_id}; + U64 hash = u64_hash_from_str8(str8_struct(&handle)); return hash; } @@ -93,6 +93,7 @@ d_string_from_msg_kind(D_MsgKind kind) default:{}break; case D_MsgKind_Launch: {result = str8_lit("Launch");}break; case D_MsgKind_Attach: {result = str8_lit("Attach");}break; + case D_MsgKind_OpenCrashDump: {result = str8_lit("OpenCrashDump");}break; case D_MsgKind_Kill: {result = str8_lit("Kill");}break; case D_MsgKind_KillAll: {result = str8_lit("KillAll");}break; case D_MsgKind_Detach: {result = str8_lit("Detach");}break; @@ -149,18 +150,10 @@ d_handle_zero(void) return handle; } -internal D_Handle -d_handle_make(D_MachineID machine_id, DMN_Handle dmn_handle) -{ - D_Handle handle = {machine_id, dmn_handle}; - return handle; -} - internal B32 d_handle_match(D_Handle a, D_Handle b) { - B32 result = (a.machine_id == b.machine_id && - dmn_handle_match(a.dmn_handle, b.dmn_handle)); + B32 result = MemoryMatchStruct(&a, &b); return result; } @@ -203,7 +196,7 @@ d_handle_array_from_list(Arena *arena, D_HandleList *src) internal String8 d_string_from_handle(Arena *arena, D_Handle handle) { - String8 result = push_str8f(arena, "$%I64x$%I64x", handle.machine_id, handle.dmn_handle.u64[0]); + String8 result = str8f(arena, "$%x$%x$%I64x", handle.machine_id, handle.controller_kind, handle.entity_id); return result; } @@ -215,19 +208,43 @@ d_handle_from_string(String8 string) Temp scratch = scratch_begin(0, 0); U8 split = '$'; String8List parts = str8_split(scratch.arena, string, &split, 1, 0); - if(parts.first && parts.first->next) + if(parts.first && parts.first->next && parts.first->next->next) { - D_MachineID machine_id = u64_from_str8(parts.first->string, 16); - DMN_Handle dmn_handle = {0}; - dmn_handle.u64[0] = u64_from_str8(parts.first->next->string, 16); + D_MachineID machine_id = (U32)u64_from_str8(parts.first->string, 16); + D_ControllerKind controller_kind = (U32)u64_from_str8(parts.first->next->string, 16); + U64 entity_id = u64_from_str8(parts.first->next->next->string, 16); handle.machine_id = machine_id; - handle.dmn_handle = dmn_handle; + handle.controller_kind = controller_kind; + handle.entity_id = entity_id; } scratch_end(scratch); } return handle; } +internal DMN_Handle +d_dmn_from_handle(D_Handle handle) +{ + DMN_Handle result = {0}; + if(handle.controller_kind == D_ControllerKind_Demon) + { + result.u64[0] = handle.entity_id; + } + return result; +} + +internal D_Handle +d_handle_from_dmn(D_MachineID machine_id, DMN_Handle handle) +{ + D_Handle result = {0}; + { + result.machine_id = machine_id; + result.controller_kind = D_ControllerKind_Demon; + result.entity_id = handle.u64[0]; + } + return result; +} + //////////////////////////////// //~ rjf: Trap Type Functions @@ -883,7 +900,7 @@ d_entity_ctx_rw_store_alloc(void) store->ctx.hash_slots_count = 1024; store->ctx.hash_slots = push_array(arena, D_EntityHashSlot, store->ctx.hash_slots_count); D_Entity *root = store->ctx.root = d_entity_alloc(store, &d_entity_nil, D_EntityKind_Root, Arch_Null, d_handle_zero(), 0); - D_Entity *local_machine = d_entity_alloc(store, root, D_EntityKind_Machine, Arch_CURRENT, d_handle_make(D_MachineID_Local, dmn_handle_zero()), 0); + D_Entity *local_machine = d_entity_alloc(store, root, D_EntityKind_Machine, Arch_CURRENT, d_handle_from_dmn(D_MachineID_Local, dmn_handle_zero()), 0); Temp scratch = scratch_begin(0, 0); String8 local_machine_name = push_str8f(scratch.arena, "This PC (%S)", get_system_info()->machine_name); d_entity_equip_string(store, local_machine, local_machine_name); @@ -1255,7 +1272,7 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) //- rjf: processes case D_EventKind_NewProc: { - D_Entity *machine = d_entity_from_handle(&store->ctx, d_handle_make(event->entity.machine_id, dmn_handle_zero())); + D_Entity *machine = d_entity_from_handle(&store->ctx, d_handle_from_dmn(event->entity.machine_id, dmn_handle_zero())); if(machine != &d_entity_nil) { D_Entity *process = d_entity_alloc(store, machine, D_EntityKind_Process, event->arch, event->entity, (U64)event->entity_id); @@ -1512,8 +1529,8 @@ d_reg_block_from_thread(Arena *arena, D_EntityCtx *ctx, D_Handle handle) { U64 current_reg_gen = d_reg_gen(); B32 need_stale = 1; - if(node->reg_gen != current_reg_gen && - dmn_thread_read_reg_block(handle.dmn_handle, result)) + DMN_Handle handle_dmn = d_dmn_from_handle(handle); + if(node->reg_gen != current_reg_gen && dmn_thread_read_reg_block(handle_dmn, result)) { if(node != 0) { @@ -1534,7 +1551,8 @@ d_reg_block_from_thread(Arena *arena, D_EntityCtx *ctx, D_Handle handle) internal U64 d_tls_root_vaddr_from_thread(D_EntityCtx *ctx, D_Handle handle) { - U64 result = dmn_tls_root_vaddr_from_thread(handle.dmn_handle); + DMN_Handle handle_dmn = d_dmn_from_handle(handle); + U64 result = dmn_tls_root_vaddr_from_thread(handle_dmn); return result; } @@ -1570,7 +1588,8 @@ internal B32 d_thread_write_reg_block(D_Handle thread, void *block) { // TODO(rjf): @callstacks immediately reflect this in the call stack cache - B32 good = dmn_thread_write_reg_block(thread.dmn_handle, block); + DMN_Handle handle_dmn = d_dmn_from_handle(thread); + B32 good = dmn_thread_write_reg_block(handle_dmn, block); if(good) { ins_atomic_u64_inc_eval(&d_ctrl_state->reg_gen); @@ -3383,6 +3402,7 @@ d_ctrl_thread__entry_point(void *p) //- rjf: target operations case D_MsgKind_Launch: {d_ctrl_thread__launch (ctrl_ctx, msg);}break; case D_MsgKind_Attach: {d_ctrl_thread__attach (ctrl_ctx, msg);}break; + case D_MsgKind_OpenCrashDump: {d_ctrl_thread__open_crash_dump (ctrl_ctx, msg);}break; case D_MsgKind_Kill: {d_ctrl_thread__kill (ctrl_ctx, msg);}break; case D_MsgKind_KillAll: {d_ctrl_thread__kill_all (ctrl_ctx, msg);}break; case D_MsgKind_Detach: {d_ctrl_thread__detach (ctrl_ctx, msg);}break; @@ -3483,6 +3503,7 @@ d_ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, D_EvalScope *e D_EntityCtx *entity_ctx = &d_ctrl_state->ctrl_thread_entity_store->ctx; D_Entity *module_entity = d_entity_from_handle(entity_ctx, module); D_Entity *debug_info_path_entity = d_entity_child_from_kind(module_entity, D_EntityKind_DebugInfoPath); + DMN_Handle process_dmn = d_dmn_from_handle(process); DI_Key dbgi_key = d_dbgi_key_from_module(module_entity); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); U64 base_vaddr = module_entity->vaddr_range.min; @@ -3536,7 +3557,7 @@ d_ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, D_EvalScope *e for(U32 i = 0; i < voff_count; i += 1) { U64 vaddr = voffs[i] + base_vaddr; - DMN_Trap trap = {process.dmn_handle, vaddr, (U64)bp}; + DMN_Trap trap = {process_dmn, vaddr, (U64)bp}; dmn_trap_chunk_list_push(arena, traps_out, 256, &trap); } } @@ -3549,7 +3570,7 @@ d_ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, D_EvalScope *e E_Value value = e_value_from_string(expr); if(value.u64 != 0 || bp->flags != 0) { - DMN_Trap trap = {process.dmn_handle, value.u64, (U64)bp}; + DMN_Trap trap = {process_dmn, value.u64, (U64)bp}; trap.flags = d_dmn_trap_flags_from_breakpoint_flags(bp->flags); trap.size = bp->size; dmn_trap_chunk_list_push(arena, traps_out, 256, &trap); @@ -3563,6 +3584,7 @@ d_ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, D_EvalScope *e internal void d_ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, D_EvalScope *eval_scope, D_Handle process, D_BreakpointList *user_bps, DMN_TrapChunkList *traps_out) { + DMN_Handle process_dmn = d_dmn_from_handle(process); for(D_BreakpointNode *n = user_bps->first; n != 0; n = n->next) { D_Breakpoint *bp = &n->v; @@ -3572,7 +3594,7 @@ d_ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, D_EvalScope * E_Value value = e_value_from_string(expr); if(value.u64 != 0 || bp->flags != 0) { - DMN_Trap trap = {process.dmn_handle, value.u64, (U64)bp}; + DMN_Trap trap = {process_dmn, value.u64, (U64)bp}; trap.flags = d_dmn_trap_flags_from_breakpoint_flags(bp->flags); trap.size = bp->size; dmn_trap_chunk_list_push(arena, traps_out, 256, &trap); @@ -3585,30 +3607,25 @@ internal void d_ctrl_thread__append_program_defined_bp_traps(Arena *arena, D_Entity *bp, DMN_TrapChunkList *traps_out) { D_Entity *process = bp->parent; + DMN_Handle process_dmn = d_dmn_from_handle(process->handle); DMN_Trap trap = { - .process = process->handle.dmn_handle, - .vaddr = bp->vaddr_range.min, - .id = ((U64)bp|bit64), - .flags = d_dmn_trap_flags_from_breakpoint_flags(bp->bp_flags), - .size = (U32)dim_1u64(bp->vaddr_range), + .process = process_dmn, + .vaddr = bp->vaddr_range.min, + .id = ((U64)bp|bit64), + .flags = d_dmn_trap_flags_from_breakpoint_flags(bp->bp_flags), + .size = (U32)dim_1u64(bp->vaddr_range), }; dmn_trap_chunk_list_push(arena, traps_out, 256, &trap); } //- rjf: module lifetime open/close work -internal -MACHINE_OP_MEM_READ(ctrl_dmn_mem_read) -{ - U64 read = dmn_process_read(((D_Handle *)ud)->dmn_handle, r1u64(addr, addr + buffer_size), buffer); - return read == buffer_size ? MachineOpResult_Ok : MachineOpResult_Fail; -} - internal void d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_range, String8 path, Rng1U64 elf_phdr_vrange, U64 elf_phdr_entsize) { Temp scratch = scratch_begin(0,0); + DMN_Handle process_dmn = d_dmn_from_handle(process); //- rjf: set up per-module info Arena *arena = arena_alloc(); @@ -3632,9 +3649,9 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang EH_PtrCtx eh_ptr_ctx = { .pc_vaddr = max_U64, .text_vaddr = max_U64, .data_vaddr = max_U64, .func_vaddr = max_U64, .ptr_align = 0 }; //- read module's signature bytes - U64 module_sig_size = Max(elf_magic_string.size, sizeof(PE_DosMagic)); - U8 *module_sig_bytes = push_array(scratch.arena, U8, module_sig_size); - dmn_process_read(process.dmn_handle, rng_1u64(vaddr_range.min, vaddr_range.min + module_sig_size), module_sig_bytes); + U64 module_sig_size = Max(elf_magic_string.size, sizeof(PE_DosMagic)); + U8 *module_sig_bytes = push_array(scratch.arena, U8, module_sig_size); + dmn_process_read(process_dmn, rng_1u64(vaddr_range.min, vaddr_range.min + module_sig_size), module_sig_bytes); ////////////////////////////// //- parse PE module @@ -3650,7 +3667,7 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang PE_DosHeader dos_header = {0}; if(is_valid) { - if(!dmn_process_read_struct(process.dmn_handle, vaddr_range.min, &dos_header) || + if(!dmn_process_read_struct(process_dmn, vaddr_range.min, &dos_header) || dos_header.magic != PE_DOS_MAGIC) { is_valid = 0; @@ -3661,7 +3678,7 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang U32 pe_magic = 0; if(is_valid) { - if(!dmn_process_read_struct(process.dmn_handle, vaddr_range.min + dos_header.coff_file_offset, &pe_magic) || + if(!dmn_process_read_struct(process_dmn, vaddr_range.min + dos_header.coff_file_offset, &pe_magic) || pe_magic != PE_MAGIC) { is_valid = 0; @@ -3673,7 +3690,7 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang COFF_FileHeader file_header = {0}; if(is_valid) { - if(!dmn_process_read_struct(process.dmn_handle, vaddr_range.min + file_header_off, &file_header)) + if(!dmn_process_read_struct(process_dmn, vaddr_range.min + file_header_off, &file_header)) { is_valid = 0; } @@ -3691,7 +3708,7 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang { // rjf: read magic number U16 opt_ext_magic = 0; - dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min, &opt_ext_magic); + dmn_process_read_struct(process_dmn, vaddr_range.min + opt_ext_off_range.min, &opt_ext_magic); // rjf: read info U32 reported_data_dir_offset = 0; @@ -3701,7 +3718,7 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang case PE_PE32_MAGIC: { PE_OptionalHeader32 pe_optional = {0}; - dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min, &pe_optional); + dmn_process_read_struct(process_dmn, vaddr_range.min + opt_ext_off_range.min, &pe_optional); entry_point = pe_optional.entry_point_va; reported_data_dir_offset = sizeof(pe_optional); reported_data_dir_count = pe_optional.data_dir_count; @@ -3709,7 +3726,7 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang case PE_PE32PLUS_MAGIC: { PE_OptionalHeader32Plus pe_optional = {0}; - dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min, &pe_optional); + dmn_process_read_struct(process_dmn, vaddr_range.min + opt_ext_off_range.min, &pe_optional); entry_point = pe_optional.entry_point_va; reported_data_dir_offset = sizeof(pe_optional); reported_data_dir_count = pe_optional.data_dir_count; @@ -3724,18 +3741,18 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang if(data_dir_count > PE_DataDirectoryIndex_EXCEPTIONS) { PE_DataDirectory dir = {0}; - dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*PE_DataDirectoryIndex_EXCEPTIONS, &dir); + dmn_process_read_struct(process_dmn, vaddr_range.min + opt_ext_off_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*PE_DataDirectoryIndex_EXCEPTIONS, &dir); Rng1U64 pdatas_voff_range = r1u64((U64)dir.virt_off, (U64)dir.virt_off + (U64)dir.virt_size); pdatas_count = dim_1u64(pdatas_voff_range)/sizeof(PE_IntelPdata); pdatas = push_array(arena, PE_IntelPdata, pdatas_count); - dmn_process_read(process.dmn_handle, r1u64(vaddr_range.min + pdatas_voff_range.min, vaddr_range.min + pdatas_voff_range.max), pdatas); + dmn_process_read(process_dmn, r1u64(vaddr_range.min + pdatas_voff_range.min, vaddr_range.min + pdatas_voff_range.max), pdatas); } // rjf: extract sections U64 sec_array_off = opt_ext_off_range.max; U64 sec_count = file_header.section_count; COFF_SectionHeader *sec = push_array(scratch.arena, COFF_SectionHeader, sec_count); - dmn_process_read(process.dmn_handle, r1u64(vaddr_range.min + sec_array_off, vaddr_range.min + sec_array_off + sec_count*sizeof(COFF_SectionHeader)), sec); + dmn_process_read(process_dmn, r1u64(vaddr_range.min + sec_array_off, vaddr_range.min + sec_array_off + sec_count*sizeof(COFF_SectionHeader)), sec); // rjf: grab entry point vaddr entry_point_voff = entry_point; @@ -3745,7 +3762,7 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang { // rjf: read data dir PE_DataDirectory dir = {0}; - dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*PE_DataDirectoryIndex_DEBUG, &dir); + dmn_process_read_struct(process_dmn, vaddr_range.min + opt_ext_off_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*PE_DataDirectoryIndex_DEBUG, &dir); U64 dbg_dir_count = dir.virt_size / sizeof(PE_DebugDirectory); for(U64 dbg_dir_idx = 0; dbg_dir_idx < dbg_dir_count; dbg_dir_idx += 1) @@ -3753,46 +3770,46 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang // rjf: read debug directory U64 dir_addr = vaddr_range.min + dir.virt_off + dbg_dir_idx * sizeof(PE_DebugDirectory); PE_DebugDirectory dbg_data = {0}; - dmn_process_read_struct(process.dmn_handle, dir_addr, &dbg_data); + dmn_process_read_struct(process_dmn, dir_addr, &dbg_data); // rjf: extract external file info from codeview header if(dbg_data.type == PE_DebugDirectoryType_CODEVIEW) { U32 cv_magic = 0; - dmn_process_read_struct(process.dmn_handle, vaddr_range.min + dbg_data.voff, &cv_magic); + dmn_process_read_struct(process_dmn, vaddr_range.min + dbg_data.voff, &cv_magic); switch(cv_magic) { default:break; case PE_CODEVIEW_PDB20_MAGIC: { PE_CvHeaderPDB20 cv; - U64 read_size = dmn_process_read_struct(process.dmn_handle, vaddr_range.min+dbg_data.voff, &cv); + U64 read_size = dmn_process_read_struct(process_dmn, vaddr_range.min+dbg_data.voff, &cv); if(read_size == sizeof(cv)) { pdb_dbg_time = cv.time_stamp; pdb_dbg_age = cv.age; - pdb_dbg_path = dmn_process_read_cstring(arena, process.dmn_handle, vaddr_range.min + dbg_data.voff + sizeof(cv)); + pdb_dbg_path = dmn_process_read_cstring(arena, process_dmn, vaddr_range.min + dbg_data.voff + sizeof(cv)); } }break; case PE_CODEVIEW_PDB70_MAGIC: { PE_CvHeaderPDB70 cv; - U64 read_size = dmn_process_read_struct(process.dmn_handle, vaddr_range.min + dbg_data.voff, &cv); + U64 read_size = dmn_process_read_struct(process_dmn, vaddr_range.min + dbg_data.voff, &cv); if(read_size == sizeof(cv)) { pdb_dbg_guid = cv.guid; pdb_dbg_age = cv.age; - pdb_dbg_path = dmn_process_read_cstring(arena, process.dmn_handle, vaddr_range.min + dbg_data.voff + sizeof(cv)); + pdb_dbg_path = dmn_process_read_cstring(arena, process_dmn, vaddr_range.min + dbg_data.voff + sizeof(cv)); } }break; case PE_CODEVIEW_RDI_MAGIC: { PE_CvHeaderRDI cv; - U64 read_size = dmn_process_read_struct(process.dmn_handle, vaddr_range.min + dbg_data.voff, &cv); + U64 read_size = dmn_process_read_struct(process_dmn, vaddr_range.min + dbg_data.voff, &cv); if(read_size == sizeof(cv)) { rdi_dbg_guid = cv.guid; - rdi_dbg_path = dmn_process_read_cstring(arena, process.dmn_handle, vaddr_range.min + dbg_data.voff + sizeof(cv)); + rdi_dbg_path = dmn_process_read_cstring(arena, process_dmn, vaddr_range.min + dbg_data.voff + sizeof(cv)); } }break; } @@ -3828,15 +3845,15 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang } raddbg_data.size = dim_1u64(raddbg_section_voff_range); raddbg_data.str = push_array(arena, U8, raddbg_data.size); - dmn_process_read(process.dmn_handle, r1u64(vaddr_range.min + raddbg_section_voff_range.min, - vaddr_range.min + raddbg_section_voff_range.max), raddbg_data.str); + dmn_process_read(process_dmn, r1u64(vaddr_range.min + raddbg_section_voff_range.min, + vaddr_range.min + raddbg_section_voff_range.max), raddbg_data.str); } // rjf: if we have a "raddbg is attached" section, mark the first byte as 1, to signify attachment if(raddbg_is_attached_section_voff_range.max != raddbg_is_attached_section_voff_range.min) { U8 new_value = 1; - dmn_process_write_struct(process.dmn_handle, vaddr_range.min + raddbg_is_attached_section_voff_range.min, &new_value); + dmn_process_write_struct(process_dmn, vaddr_range.min + raddbg_is_attached_section_voff_range.min, &new_value); } } } @@ -3850,7 +3867,7 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang U64 e_entry = 0; ELF_Type e_type = ELF_Type_None; { - U8 *elf_sig = dmn_process_read_raw(scratch.arena, process.dmn_handle, rng_1u64(vaddr_range.min, vaddr_range.min + sizeof(elf_sig[0]) * ELF_Identifier_Max)); + U8 *elf_sig = dmn_process_read_raw(scratch.arena, process_dmn, rng_1u64(vaddr_range.min, vaddr_range.min + sizeof(elf_sig[0]) * ELF_Identifier_Max)); if(elf_sig == 0) { goto elf_exit; } switch(elf_sig[ELF_Identifier_Class]) { @@ -3862,7 +3879,7 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang }break; case ELF_Class_64: { - ELF_Hdr64 *ehdr = dmn_process_read_raw(scratch.arena, process.dmn_handle, rng_1u64(vaddr_range.min, vaddr_range.min + sizeof(*ehdr))); + ELF_Hdr64 *ehdr = dmn_process_read_raw(scratch.arena, process_dmn, rng_1u64(vaddr_range.min, vaddr_range.min + sizeof(*ehdr))); if(ehdr == 0) { goto elf_exit; } e_entry = ehdr->e_entry; e_type = ehdr->e_type; @@ -3879,7 +3896,7 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang Rng1U64 eh_frame_hdr_vrange = {0}; String8 eh_frame_hdr_data = {0}; { - void *phdrs_raw = dmn_process_read_raw(scratch.arena, process.dmn_handle, elf_phdr_vrange); + void *phdrs_raw = dmn_process_read_raw(scratch.arena, process_dmn, elf_phdr_vrange); if(phdrs_raw == 0) { goto elf_exit; } if(elf_phdr_entsize == sizeof(ELF_Phdr32)) @@ -3896,7 +3913,7 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang if(phdr->p_type == ELF_PType_GnuEHFrame) { eh_frame_hdr_vrange = r1u64(cfi_rebase + phdr->p_vaddr, cfi_rebase + phdr->p_vaddr + phdr->p_memsz); - eh_frame_hdr_data = dmn_process_read_block(arena, process.dmn_handle, eh_frame_hdr_vrange); + eh_frame_hdr_data = dmn_process_read_block(arena, process_dmn, eh_frame_hdr_vrange); is_unwind_eh = 1; break; } @@ -4019,6 +4036,8 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang internal void d_ctrl_thread__module_close(D_Handle process, D_Handle module, Rng1U64 vaddr_range) { + DMN_Handle process_dmn = d_dmn_from_handle(process); + ////////////////////////////// //- rjf: evict module image info from cache // @@ -4055,7 +4074,7 @@ d_ctrl_thread__module_close(D_Handle process, D_Handle module, Rng1U64 vaddr_ran if(raddbg_attached_marker_voff != 0) { U8 new_value = 0; - dmn_process_write_struct(process.dmn_handle, vaddr_range.min + raddbg_attached_marker_voff, &new_value); + dmn_process_write_struct(process_dmn, vaddr_range.min + raddbg_attached_marker_voff, &new_value); } } @@ -4140,7 +4159,7 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D (spoof == 0 || ev->instruction_pointer != spoof->new_ip_value)) { Access *access = access_open(); - D_Entity *process = d_entity_from_handle(entity_ctx, d_handle_make(D_MachineID_Local, ev->process)); + D_Entity *process = d_entity_from_handle(entity_ctx, d_handle_from_dmn(D_MachineID_Local, ev->process)); D_Entity *module = &d_entity_nil; for(D_Entity *child = process->first; child != &d_entity_nil; child = child->next) { @@ -4230,10 +4249,10 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D U64 size_of_spoof = 0; if(do_spoof) ProfScope("prep spoof") { - D_Entity *spoof_process = d_entity_from_handle(entity_ctx, d_handle_make(D_MachineID_Local, spoof->process)); + D_Entity *spoof_process = d_entity_from_handle(entity_ctx, d_handle_from_dmn(D_MachineID_Local, spoof->process)); Arch arch = spoof_process->arch; size_of_spoof = bit_size_from_arch(arch)/8; - dmn_process_read(spoof_process->handle.dmn_handle, r1u64(spoof->vaddr, spoof->vaddr+size_of_spoof), &spoof_old_ip_value); + dmn_process_read(spoof->process, r1u64(spoof->vaddr, spoof->vaddr+size_of_spoof), &spoof_old_ip_value); } // rjf: set spoof @@ -4300,7 +4319,7 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D // simply been sent other debug events first if(spoof != 0) { - D_Entity *thread = d_entity_from_handle(entity_ctx, d_handle_make(D_MachineID_Local, spoof->thread)); + D_Entity *thread = d_entity_from_handle(entity_ctx, d_handle_from_dmn(D_MachineID_Local, spoof->thread)); Arch arch = thread->arch; ARCH_Info *arch_info = arch_info_from_arch(arch); U64 arch_reg_block_size = arch_info->reg_block_size; @@ -4310,7 +4329,7 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D if(spoof_thread_rip == spoof->new_ip_value) { arch_reg_block_write_ip(arch_info, regs_block, spoof_old_ip_value); - d_thread_write_reg_block(d_handle_make(D_MachineID_Local, spoof->thread), regs_block); + d_thread_write_reg_block(d_handle_from_dmn(D_MachineID_Local, spoof->thread), regs_block); } } @@ -4324,7 +4343,7 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D D_Event *out_evt = d_event_list_push(scratch.arena, &evts); out_evt->kind = D_EventKind_NewProc; out_evt->msg_id = msg->msg_id; - out_evt->entity = d_handle_make(D_MachineID_Local, event->process); + out_evt->entity = d_handle_from_dmn(D_MachineID_Local, event->process); out_evt->arch = event->arch; out_evt->entity_id = event->code; out_evt->tls_model = d_dynamic_linker_type_from_dmn(event->tls_model); @@ -4336,8 +4355,8 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D D_Event *out_evt = d_event_list_push(scratch.arena, &evts); out_evt->kind = D_EventKind_NewThread; out_evt->msg_id = msg->msg_id; - out_evt->entity = d_handle_make(D_MachineID_Local, event->thread); - out_evt->parent = d_handle_make(D_MachineID_Local, event->process); + out_evt->entity = d_handle_from_dmn(D_MachineID_Local, event->thread); + out_evt->parent = d_handle_from_dmn(D_MachineID_Local, event->process); out_evt->arch = event->arch; out_evt->entity_id = event->code; out_evt->stack_base = dmn_stack_base_vaddr_from_thread(event->thread); @@ -4347,8 +4366,8 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D }break; case DMN_EventKind_LoadModule: { - D_Handle process_handle = d_handle_make(D_MachineID_Local, event->process); - D_Handle module_handle = d_handle_make(D_MachineID_Local, event->module); + D_Handle process_handle = d_handle_from_dmn(D_MachineID_Local, event->process); + D_Handle module_handle = d_handle_from_dmn(D_MachineID_Local, event->module); D_Event *out_evt1 = d_event_list_push(scratch.arena, &evts); String8 module_path = path_normalized_from_string(scratch.arena, event->string); U64 exe_timestamp = properties_from_file_path(module_path).modified; @@ -4382,7 +4401,7 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D D_Event *out_evt = d_event_list_push(scratch.arena, &evts); out_evt->kind = D_EventKind_EndProc; out_evt->msg_id = msg->msg_id; - out_evt->entity = d_handle_make(D_MachineID_Local, event->process); + out_evt->entity = d_handle_from_dmn(D_MachineID_Local, event->process); out_evt->u64_code = event->code; d_ctrl_state->process_counter -= 1; }break; @@ -4391,14 +4410,14 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D D_Event *out_evt = d_event_list_push(scratch.arena, &evts); out_evt->kind = D_EventKind_EndThread; out_evt->msg_id = msg->msg_id; - out_evt->entity = d_handle_make(D_MachineID_Local, event->thread); + out_evt->entity = d_handle_from_dmn(D_MachineID_Local, event->thread); out_evt->entity_id = event->code; }break; case DMN_EventKind_UnloadModule: ProfScope("unload module %.*s", str8_varg(event->string)) { D_Event *out_evt = d_event_list_push(scratch.arena, &evts); - D_Handle module_handle = d_handle_make(D_MachineID_Local, event->module); + D_Handle module_handle = d_handle_from_dmn(D_MachineID_Local, event->module); D_Entity *module_ent = d_entity_from_handle(entity_ctx, module_handle); D_Entity *process_ent = d_process_from_entity(module_ent); String8 module_path = event->string; @@ -4418,8 +4437,8 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D D_Event *out_evt = d_event_list_push(scratch.arena, &evts); out_evt->kind = D_EventKind_DebugString; out_evt->msg_id = msg->msg_id; - out_evt->entity = d_handle_make(D_MachineID_Local, event->thread); - out_evt->parent = d_handle_make(D_MachineID_Local, event->process); + out_evt->entity = d_handle_from_dmn(D_MachineID_Local, event->thread); + out_evt->parent = d_handle_from_dmn(D_MachineID_Local, event->process); out_evt->string = str8_substr(event->string, r1u64(string_idx*d_ctrl_state->c2u_ring_max_string_size, (string_idx+1)*d_ctrl_state->c2u_ring_max_string_size)); } }break; @@ -4428,8 +4447,8 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D D_Event *out_evt = d_event_list_push(scratch.arena, &evts); out_evt->kind = D_EventKind_ThreadName; out_evt->msg_id = msg->msg_id; - out_evt->entity = d_handle_make(D_MachineID_Local, event->thread); - out_evt->parent = d_handle_make(D_MachineID_Local, event->process); + out_evt->entity = d_handle_from_dmn(D_MachineID_Local, event->thread); + out_evt->parent = d_handle_from_dmn(D_MachineID_Local, event->process); out_evt->string = event->string; out_evt->entity_id = event->code; }break; @@ -4438,8 +4457,8 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D D_Event *out_evt = d_event_list_push(scratch.arena, &evts); out_evt->kind = D_EventKind_ThreadColor; out_evt->msg_id = msg->msg_id; - out_evt->entity = d_handle_make(D_MachineID_Local, event->thread); - out_evt->parent = d_handle_make(D_MachineID_Local, event->process); + out_evt->entity = d_handle_from_dmn(D_MachineID_Local, event->thread); + out_evt->parent = d_handle_from_dmn(D_MachineID_Local, event->process); out_evt->entity_id = event->code; out_evt->rgba = event->user_data; }break; @@ -4447,7 +4466,7 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D { D_Event *out_evt = d_event_list_push(scratch.arena, &evts); out_evt->kind = D_EventKind_SetVAddrRangeNote; - out_evt->parent = d_handle_make(D_MachineID_Local, event->process); + out_evt->parent = d_handle_from_dmn(D_MachineID_Local, event->process); out_evt->msg_id = msg->msg_id; out_evt->vaddr_rng = r1u64(event->address, event->address + event->size); out_evt->string = event->string; @@ -4456,8 +4475,8 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D { D_Event *out_evt = d_event_list_push(scratch.arena, &evts); out_evt->kind = D_EventKind_SetBreakpoint; - out_evt->entity = d_handle_make(D_MachineID_Local, event->thread); - out_evt->parent = d_handle_make(D_MachineID_Local, event->process); + out_evt->entity = d_handle_from_dmn(D_MachineID_Local, event->thread); + out_evt->parent = d_handle_from_dmn(D_MachineID_Local, event->process); out_evt->vaddr_rng = r1u64(event->address, event->address+event->size); out_evt->bp_flags = d_breakpoint_flags_from_dmn_trap_flags(event->flags); }break; @@ -4466,8 +4485,8 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D // TODO(rjf): this needs to be reflected in the resolved trap list too!!!!!!!! D_Event *out_evt = d_event_list_push(scratch.arena, &evts); out_evt->kind = D_EventKind_UnsetBreakpoint; - out_evt->entity = d_handle_make(D_MachineID_Local, event->thread); - out_evt->parent = d_handle_make(D_MachineID_Local, event->process); + out_evt->entity = d_handle_from_dmn(D_MachineID_Local, event->thread); + out_evt->parent = d_handle_from_dmn(D_MachineID_Local, event->process); out_evt->vaddr_rng = r1u64(event->address, event->address+event->size); out_evt->bp_flags = d_breakpoint_flags_from_dmn_trap_flags(event->flags); }break; @@ -4528,7 +4547,8 @@ d_ctrl_eval_space_read(E_Space space, void *out, E_SpaceRangeInfo *out_range_inf default:{}break; case D_EntityKind_Process: { - U64 read_size = dmn_process_read(entity->handle.dmn_handle, range, out); + DMN_Handle handle_dmn = d_dmn_from_handle(entity->handle); + U64 read_size = dmn_process_read(handle_dmn, range, out); result = (read_size == dim_1u64(range)); }break; case D_EntityKind_Thread: @@ -4559,13 +4579,14 @@ d_ctrl_thread__eval_scope_begin(Arena *arena, D_BreakpointList *user_bps, D_Enti ProfBeginFunction(); D_EntityCtx *entity_ctx = &d_ctrl_state->ctrl_thread_entity_store->ctx; D_EvalScope *scope = push_array(arena, D_EvalScope, 1); + DMN_Handle thread_dmn = d_dmn_from_handle(thread->handle); scope->access = access_open(); ////////////////////////////// //- rjf: unpack thread // Arch arch = thread->arch; - U64 thread_rip_vaddr = dmn_rip_from_thread(thread->handle.dmn_handle); + U64 thread_rip_vaddr = dmn_rip_from_thread(thread_dmn); D_Entity *process = d_process_from_entity(thread); D_Entity *module = d_module_from_process_vaddr(process, thread_rip_vaddr); U64 thread_rip_voff = d_voff_from_vaddr(module, thread_rip_vaddr); @@ -4936,12 +4957,39 @@ d_ctrl_thread__attach(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) ProfEnd(); } +internal void +d_ctrl_thread__open_crash_dump(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) +{ + String8 path = msg->path; + File file = file_open(AccessFlag_Read, path); + FileProperties props = properties_from_file(file); + FileMap map = file_map_open(AccessFlag_Read, file); + void *base = file_map_view_open(map, AccessFlag_Read, r1u64(0, props.size)); + String8 data = str8(base, base ? props.size : 0); + { + //- rjf: try minidump parse -> construct events for entity creation + { + MDMP_Header header = {0}; + str8_deserial_read_struct(data, 0, &header); + if(header.magic == MDMP_MAGIC) + { + U64 directories_foff = header.stream_directory_foff; + U64 directories_count = header.number_of_streams; + // MDMP_Directory *directories = + } + } + } + file_map_view_close(map, base, r1u64(0, props.size)); + file_map_close(map); + file_close(file); +} + internal void d_ctrl_thread__kill(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); - DMN_Handle process = msg->entity.dmn_handle; + DMN_Handle process = d_dmn_from_handle(msg->entity); U32 exit_code = msg->exit_code; //- rjf: send kill @@ -5029,7 +5077,7 @@ d_ctrl_thread__kill_all(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) for(Task *t = first_task, *next = 0; t != 0; t = next) { next = t->next; - B32 kill_worked = dmn_ctrl_kill(ctrl_ctx, t->process->handle.dmn_handle, exit_code); + B32 kill_worked = dmn_ctrl_kill(ctrl_ctx, d_dmn_from_handle(t->process->handle), exit_code); if(kill_worked) { DLLRemove(first_task, last_task, t); @@ -5045,7 +5093,7 @@ d_ctrl_thread__kill_all(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) default:{}break; case DMN_EventKind_CreateProcess: { - D_Entity *new_process = d_entity_from_handle(entity_ctx, d_handle_make(D_MachineID_Local, event->process)); + D_Entity *new_process = d_entity_from_handle(entity_ctx, d_handle_from_dmn(D_MachineID_Local, event->process)); Task *t = push_array(scratch.arena, Task, 1); t->process = new_process; DLLPushBack(first_task, last_task, t); @@ -5082,7 +5130,7 @@ d_ctrl_thread__detach(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); - DMN_Handle process = msg->entity.dmn_handle; + DMN_Handle process = d_dmn_from_handle(msg->entity); //- rjf: detach B32 detach_worked = dmn_ctrl_detach(ctrl_ctx, process); @@ -5137,6 +5185,8 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) D_EntityCtx *entity_ctx = &d_ctrl_state->ctrl_thread_entity_store->ctx; D_Handle target_thread = msg->entity; D_Handle target_process = msg->parent; + DMN_Handle target_thread_dmn = d_dmn_from_handle(target_thread); + DMN_Handle target_process_dmn = d_dmn_from_handle(target_process); D_Entity *target_process_entity = d_entity_from_handle(entity_ctx, target_process); U64 spoof_ip_vaddr = 911; log_infof("d_ctrl_thread__run:\n{\n"); @@ -5185,7 +5235,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_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.dmn_handle); + U64 sp_check_value = dmn_rsp_from_thread(target_thread_dmn); log_infof("sp_check_value := 0x%I64x\n", sp_check_value); ////////////////////////////// @@ -5216,7 +5266,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) for(D_Entity *thread = process->first; thread != &d_entity_nil; thread = thread->next) { if(thread->kind != D_EntityKind_Thread) { continue; } - U64 rip = dmn_rip_from_thread(thread->handle.dmn_handle); + U64 rip = dmn_rip_from_thread(d_dmn_from_handle(thread->handle)); // rjf: determine if thread is frozen B32 thread_is_frozen = thread->is_frozen; @@ -5229,7 +5279,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) B32 is_on_user_bp = 0; for(DMN_Trap *trap_ptr = n->v; trap_ptr < n->v+n->count; trap_ptr += 1) { - if(dmn_handle_match(trap_ptr->process, process->handle.dmn_handle) && trap_ptr->vaddr == rip) + if(dmn_handle_match(trap_ptr->process, d_dmn_from_handle(process->handle)) && trap_ptr->vaddr == rip) { is_on_user_bp = 1; } @@ -5244,12 +5294,12 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) } } - if(is_on_user_bp && (!is_on_net_trap || !dmn_handle_match(thread->handle.dmn_handle, target_thread.dmn_handle))) + if(is_on_user_bp && (!is_on_net_trap || !dmn_handle_match(d_dmn_from_handle(thread->handle), target_thread_dmn))) { - dmn_handle_list_push(scratch.arena, &stuck_threads, thread->handle.dmn_handle); + dmn_handle_list_push(scratch.arena, &stuck_threads, d_dmn_from_handle(thread->handle)); } - if(is_on_user_bp && is_on_net_trap && dmn_handle_match(thread->handle.dmn_handle, target_thread.dmn_handle)) + if(is_on_user_bp && is_on_net_trap && dmn_handle_match(d_dmn_from_handle(thread->handle), target_thread_dmn)) { target_thread_is_on_user_bp_and_trap_net_trap = 1; } @@ -5337,7 +5387,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) node != 0; node = node->next) { - DMN_Trap trap = {target_process.dmn_handle, node->v.vaddr}; + DMN_Trap trap = {d_dmn_from_handle(target_process), node->v.vaddr}; dmn_trap_chunk_list_push(scratch.arena, &trap_net_traps, 256, &trap); } @@ -5395,7 +5445,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) DMN_RunCtrls run_ctrls = {0}; if(run_loop_idx == 0) { - run_ctrls.priority_thread = target_thread.dmn_handle; + run_ctrls.priority_thread = target_thread_dmn; } run_ctrls.ignore_previous_exception = 1; run_ctrls.run_entity_count = frozen_threads.count; @@ -5405,7 +5455,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) U64 idx = 0; for(D_EntityNode *n = frozen_threads.first; n != 0; n = n->next) { - run_ctrls.run_entities[idx] = n->v->handle.dmn_handle; + run_ctrls.run_entities[idx] = d_dmn_from_handle(n->v->handle); idx += 1; } } @@ -5447,7 +5497,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) D_EvalScope *eval_scope = d_ctrl_thread__eval_scope_begin(scratch.arena, &msg->user_bps, &d_entity_nil); { DMN_TrapChunkList new_traps = {0}; - d_ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, eval_scope, d_handle_make(D_MachineID_Local, event->process), &msg->user_bps, &new_traps); + d_ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, eval_scope, d_handle_from_dmn(D_MachineID_Local, event->process), &msg->user_bps, &new_traps); 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) @@ -5466,11 +5516,11 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) }break; case DMN_EventKind_LoadModule: { - D_Entity *thread = d_entity_from_handle(entity_ctx, d_handle_make(D_MachineID_Local, event->thread)); + D_Entity *thread = d_entity_from_handle(entity_ctx, d_handle_from_dmn(D_MachineID_Local, event->thread)); D_EvalScope *eval_scope = d_ctrl_thread__eval_scope_begin(scratch.arena, &msg->user_bps, thread); { DMN_TrapChunkList new_traps = {0}; - d_ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, eval_scope, d_handle_make(D_MachineID_Local, event->process), d_handle_make(D_MachineID_Local, event->module), &msg->user_bps, &new_traps); + d_ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, eval_scope, d_handle_from_dmn(D_MachineID_Local, event->process), d_handle_from_dmn(D_MachineID_Local, 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) @@ -5491,7 +5541,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) { D_Entity *bp = &d_entity_nil; { - D_Entity *process = d_entity_from_handle(entity_ctx, d_handle_make(D_MachineID_Local, event->process)); + D_Entity *process = d_entity_from_handle(entity_ctx, d_handle_from_dmn(D_MachineID_Local, event->process)); for(D_Entity *child = process->first; child != &d_entity_nil; child = child->next) { if(child->kind == D_EntityKind_Breakpoint && @@ -5523,7 +5573,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) Access *access = access_open(); //- rjf: unpack process/module info - D_Entity *process = d_entity_from_handle(entity_ctx, d_handle_make(D_MachineID_Local, event->process)); + D_Entity *process = d_entity_from_handle(entity_ctx, d_handle_from_dmn(D_MachineID_Local, event->process)); D_Entity *module = d_entity_child_from_kind(process, D_EntityKind_Module); U64 module_base_vaddr = module->vaddr_range.min; DI_Key dbgi_key = d_dbgi_key_from_module(module); @@ -5554,7 +5604,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) if(voff != 0) { entries_found = 1; - DMN_Trap trap = {process->handle.dmn_handle, module_base_vaddr + voff}; + DMN_Trap trap = {d_dmn_from_handle(process->handle), module_base_vaddr + voff}; dmn_trap_chunk_list_push(scratch.arena, &entry_traps, 256, &trap); } } @@ -5588,7 +5638,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) if(voff != 0) { entries_found = 1; - DMN_Trap trap = {process->handle.dmn_handle, module_base_vaddr + voff}; + DMN_Trap trap = {d_dmn_from_handle(process->handle), module_base_vaddr + voff}; dmn_trap_chunk_list_push(scratch.arena, &entry_traps, 256, &trap); } } @@ -5618,7 +5668,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) if(voff != 0) { entries_found = 1; - DMN_Trap trap = {process->handle.dmn_handle, module_base_vaddr + voff}; + DMN_Trap trap = {d_dmn_from_handle(process->handle), module_base_vaddr + voff}; dmn_trap_chunk_list_push(scratch.arena, &entry_traps, 256, &trap); } } @@ -5645,7 +5695,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { - DMN_Trap trap = {process->handle.dmn_handle, module_base_vaddr + voff}; + DMN_Trap trap = {d_dmn_from_handle(process->handle), module_base_vaddr + voff}; dmn_trap_chunk_list_push(scratch.arena, &entry_traps, 256, &trap); break; } @@ -5680,7 +5730,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) if(voff != 0) { entries_found = 1; - DMN_Trap trap = {process->handle.dmn_handle, module_base_vaddr + voff}; + DMN_Trap trap = {d_dmn_from_handle(process->handle), module_base_vaddr + voff}; dmn_trap_chunk_list_push(scratch.arena, &entry_traps, 256, &trap); } } @@ -5692,7 +5742,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) U64 voff = d_entry_point_voff_from_module(module->handle); if(voff != 0) { - DMN_Trap trap = {process->handle.dmn_handle, module_base_vaddr + voff}; + DMN_Trap trap = {d_dmn_from_handle(process->handle), module_base_vaddr + voff}; dmn_trap_chunk_list_push(scratch.arena, &entry_traps, 256, &trap); } } @@ -5725,7 +5775,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) if(voff != 0) { entries_found = 1; - DMN_Trap trap = {process->handle.dmn_handle, module_base_vaddr + voff}; + DMN_Trap trap = {d_dmn_from_handle(process->handle), module_base_vaddr + voff}; dmn_trap_chunk_list_push(scratch.arena, &entry_traps, 256, &trap); } } @@ -5746,8 +5796,8 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) ////////////////////////// //- rjf: unpack info about thread attached to event // - D_Entity *thread = d_entity_from_handle(entity_ctx, d_handle_make(D_MachineID_Local, event->thread)); - D_Entity *process = d_entity_from_handle(entity_ctx, d_handle_make(D_MachineID_Local, event->process)); + D_Entity *thread = d_entity_from_handle(entity_ctx, d_handle_from_dmn(D_MachineID_Local, event->thread)); + D_Entity *process = d_entity_from_handle(entity_ctx, d_handle_from_dmn(D_MachineID_Local, event->process)); Arch arch = thread->arch; U64 thread_rip_vaddr = dmn_rip_from_thread(event->thread); D_Entity *module = d_module_from_process_vaddr(process, thread_rip_vaddr); @@ -5770,8 +5820,8 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) if(!hard_stop && use_stepping_logic && event->kind == DMN_EventKind_Exception) { if(spoof_mode && - dmn_handle_match(target_process.dmn_handle, event->process) && - dmn_handle_match(target_thread.dmn_handle, event->thread) && + dmn_handle_match(target_process_dmn, event->process) && + dmn_handle_match(target_thread_dmn, event->thread) && spoof.new_ip_value == event->address) { hit_spoof = 1; @@ -5837,7 +5887,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) { if(dmn_handle_match(trap->process, event->process) && trap->vaddr == event->instruction_pointer && - (!dmn_handle_match(event->thread, target_thread.dmn_handle) || !target_thread_is_on_user_bp_and_trap_net_trap)) + (!dmn_handle_match(event->thread, d_dmn_from_handle(target_thread)) || !target_thread_is_on_user_bp_and_trap_net_trap)) { D_Breakpoint *user_bp = (D_Breakpoint *)trap->id; hit_user_bp = 1; @@ -5892,7 +5942,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) // rjf: gather trap net hits ProfScope("gather trap net hits") { - if(!hit_user_bp && dmn_handle_match(event->process, target_process.dmn_handle)) + if(!hit_user_bp && dmn_handle_match(event->process, d_dmn_from_handle(target_process))) { for(D_TrapNode *node = msg->traps.first; node != 0; @@ -5974,7 +6024,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) B32 step_past_trap_net = 0; if(!hard_stop && use_stepping_logic && hit_trap_net_bp) { - if(!dmn_handle_match(event->thread, target_thread.dmn_handle)) + if(!dmn_handle_match(event->thread, d_dmn_from_handle(target_thread))) { step_past_trap_net = 1; use_stepping_logic = 0; @@ -5985,7 +6035,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) B32 use_trap_net_logic = 0; if(!hard_stop && use_stepping_logic && hit_trap_net_bp) { - if(dmn_handle_match(event->thread, target_thread.dmn_handle)) + if(dmn_handle_match(event->thread, d_dmn_from_handle(target_thread))) { use_trap_net_logic = 1; } @@ -5995,7 +6045,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) B32 stack_pointer_matches = 0; if(use_trap_net_logic) { - U64 sp = dmn_rsp_from_thread(target_thread.dmn_handle); + U64 sp = dmn_rsp_from_thread(d_dmn_from_handle(target_thread)); stack_pointer_matches = (sp == sp_check_value); } @@ -6006,20 +6056,20 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) { if(hit_trap_flags & D_TrapFlag_SingleStepAfterHit) LogInfoNamedBlockF("trap_net__single_step_after_hit") { - U64 thread_pre_rip = dmn_rip_from_thread(target_thread.dmn_handle); + U64 thread_pre_rip = dmn_rip_from_thread(d_dmn_from_handle(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.dmn_handle; + single_step_ctrls.run_entities = &target_thread_dmn; single_step_ctrls.run_entity_count = 1; if(thread_post_rip == thread_pre_rip) { - single_step_ctrls.single_step_thread = target_thread.dmn_handle; + single_step_ctrls.single_step_thread = target_thread_dmn; } DMN_Event *event = d_ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0); - thread_post_rip = dmn_rip_from_thread(target_thread.dmn_handle); + thread_post_rip = dmn_rip_from_thread(target_thread_dmn); switch(event->kind) { default:{}break; @@ -6036,7 +6086,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) }break; case DMN_EventKind_SingleStep: { - single_step_done = dmn_handle_match(event->thread, target_thread.dmn_handle); + single_step_done = dmn_handle_match(event->thread, target_thread_dmn); single_step_stop_cause = d_event_cause_from_dmn_event_kind(event->kind); }break; } @@ -6052,10 +6102,10 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) { // rjf: setup spoof mode begin_spoof_mode = 1; - U64 spoof_sp = dmn_rsp_from_thread(target_thread.dmn_handle); + U64 spoof_sp = dmn_rsp_from_thread(target_thread_dmn); spoof_mode = 1; - spoof.process = target_process.dmn_handle; - spoof.thread = target_thread.dmn_handle; + spoof.process = target_process_dmn; + spoof.thread = target_thread_dmn; 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); @@ -6071,7 +6121,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) if(stack_pointer_matches) LogInfoNamedBlockF("trap_net__save_sp") { save_stack_pointer = 1; - sp_check_value = dmn_rsp_from_thread(target_thread.dmn_handle); + sp_check_value = dmn_rsp_from_thread(target_thread_dmn); log_infof("sp_check_value = 0x%I64x\n", sp_check_value); } } @@ -6191,8 +6241,8 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) D_Event *event = d_event_list_push(scratch.arena, &evts); event->kind = D_EventKind_Stopped; event->cause = stop_cause; - event->entity = d_handle_make(D_MachineID_Local, stop_event->thread); - event->parent = d_handle_make(D_MachineID_Local, stop_event->process); + event->entity = d_handle_from_dmn(D_MachineID_Local, stop_event->thread); + event->parent = d_handle_from_dmn(D_MachineID_Local, stop_event->process); event->exception_code = stop_event->code; event->exception_kind = d_exception_kind_from_dmn(stop_event->exception_kind); event->vaddr_rng = r1u64(stop_event->address, stop_event->address); @@ -6228,7 +6278,7 @@ d_ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) } //- rjf: single step - DMN_Handle thread = msg->entity.dmn_handle; + DMN_Handle thread = d_dmn_from_handle(msg->entity); B32 thread_is_valid = !dmn_handle_match(thread, dmn_handle_zero()); DMN_Event *stop_event = 0; D_EventCause stop_cause = D_EventCause_Null; @@ -6244,10 +6294,10 @@ d_ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) run_ctrls.run_entity_count = 1; if(thread_post_rip == thread_pre_rip) { - run_ctrls.single_step_thread = msg->entity.dmn_handle; + run_ctrls.single_step_thread = d_dmn_from_handle(msg->entity); } DMN_Event *event = d_ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0); - thread_post_rip = dmn_rip_from_thread(msg->entity.dmn_handle); + thread_post_rip = dmn_rip_from_thread(d_dmn_from_handle(msg->entity)); switch(event->kind) { default:{}break; @@ -6274,8 +6324,8 @@ d_ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) event->cause = stop_cause; if(stop_event != 0) { - event->entity = d_handle_make(D_MachineID_Local, stop_event->thread); - event->parent = d_handle_make(D_MachineID_Local, stop_event->process); + event->entity = d_handle_from_dmn(D_MachineID_Local, stop_event->thread); + event->parent = d_handle_from_dmn(D_MachineID_Local, stop_event->process); event->exception_code = stop_event->code; event->exception_kind = d_exception_kind_from_dmn(stop_event->exception_kind); event->vaddr_rng = r1u64(stop_event->address, stop_event->address); @@ -6306,6 +6356,7 @@ d_memory_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *g key_read_off += str8_deserial_read_struct(key, key_read_off, &vaddr_range); key_read_off += str8_deserial_read_struct(key, key_read_off, &zero_terminated); } + DMN_Handle process_dmn = d_dmn_from_handle(process); //- rjf: clamp vaddr range Rng1U64 vaddr_range_clamped = vaddr_range; @@ -6341,7 +6392,7 @@ d_memory_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *g retry_count <= retry_limit; retry_count += 1) { - bytes_read = dmn_process_read(process.dmn_handle, vaddr_range_clamped_retry, range_base); + bytes_read = dmn_process_read(process_dmn, vaddr_range_clamped_retry, range_base); if(bytes_read == 0 && vaddr_range_clamped_retry.max > vaddr_range_clamped_retry.min) { U64 diff = (vaddr_range_clamped_retry.max-vaddr_range_clamped_retry.min)/2; @@ -6649,7 +6700,7 @@ internal B32 d_process_write(D_Handle process, Rng1U64 range, void *src) { ProfBeginFunction(); - B32 result = dmn_process_write(process.dmn_handle, range, src); + B32 result = dmn_process_write(d_dmn_from_handle(process), range, src); //- rjf: success -> bump generation if(result) diff --git a/src/dbg_engine/dbg_engine_ctrl.h b/src/dbg_engine/dbg_engine_ctrl.h index 02b83e8a..8ce80aa6 100644 --- a/src/dbg_engine/dbg_engine_ctrl.h +++ b/src/dbg_engine/dbg_engine_ctrl.h @@ -362,13 +362,14 @@ internal D_BreakpointFlags d_breakpoint_flags_from_dmn_trap_flags(DMN_TrapFlags //~ rjf: Handle Type Functions internal D_Handle d_handle_zero(void); -internal D_Handle d_handle_make(D_MachineID machine_id, DMN_Handle dmn_handle); internal B32 d_handle_match(D_Handle a, D_Handle b); internal void d_handle_list_push(Arena *arena, D_HandleList *list, D_Handle *pair); internal D_HandleList d_handle_list_copy(Arena *arena, D_HandleList *src); internal D_HandleArray d_handle_array_from_list(Arena *arena, D_HandleList *src); internal String8 d_string_from_handle(Arena *arena, D_Handle handle); internal D_Handle d_handle_from_string(String8 string); +internal DMN_Handle d_dmn_from_handle(D_Handle handle); +internal D_Handle d_handle_from_dmn(D_MachineID machine_id, DMN_Handle handle); //////////////////////////////// //~ rjf: Trap Type Functions @@ -566,6 +567,7 @@ internal void d_ctrl_thread__end_and_flush_log(void); //- rjf: msg kind implementations internal void d_ctrl_thread__launch(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg); internal void d_ctrl_thread__attach(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg); +internal void d_ctrl_thread__open_crash_dump(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg); internal void d_ctrl_thread__kill(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg); internal void d_ctrl_thread__kill_all(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg); internal void d_ctrl_thread__detach(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg); diff --git a/src/dbg_engine/dbg_engine_user.c b/src/dbg_engine/dbg_engine_user.c index cce39e00..dbcde890 100644 --- a/src/dbg_engine/dbg_engine_user.c +++ b/src/dbg_engine/dbg_engine_user.c @@ -2063,12 +2063,12 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P case D_CmdKind_FreezeLocalMachine: { D_MachineID machine_id = D_MachineID_Local; - d_cmd(D_CmdKind_FreezeMachine, .entity = d_handle_make(machine_id, dmn_handle_zero())); + d_cmd(D_CmdKind_FreezeMachine, .entity = d_handle_from_dmn(machine_id, dmn_handle_zero())); }break; case D_CmdKind_ThawLocalMachine: { D_MachineID machine_id = D_MachineID_Local; - d_cmd(D_CmdKind_ThawMachine, .entity = d_handle_make(machine_id, dmn_handle_zero())); + d_cmd(D_CmdKind_ThawMachine, .entity = d_handle_from_dmn(machine_id, dmn_handle_zero())); }break; case D_CmdKind_FreezeEntity: case D_CmdKind_ThawEntity: @@ -2119,6 +2119,16 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P MemoryCopyArray(msg->exception_code_filters, exception_code_filters); } }break; + + //- rjf: opening crash dumps + case D_CmdKind_OpenCrashDump: + { + String8 file_path = params->file_path; + D_Msg *msg = d_msg_list_push(scratch.arena, &ctrl_msgs); + msg->kind = D_MsgKind_OpenCrashDump; + msg->path = str8_copy(scratch.arena, file_path); + MemoryCopyArray(msg->exception_code_filters, exception_code_filters); + }break; } // rjf: do run if needed diff --git a/src/dbg_engine/dbg_engine_user.h b/src/dbg_engine/dbg_engine_user.h index 306de1a2..eac970b6 100644 --- a/src/dbg_engine/dbg_engine_user.h +++ b/src/dbg_engine/dbg_engine_user.h @@ -159,6 +159,7 @@ typedef enum D_MsgKind D_MsgKind_Null, D_MsgKind_Launch, D_MsgKind_Attach, + D_MsgKind_OpenCrashDump, D_MsgKind_Kill, D_MsgKind_KillAll, D_MsgKind_Detach, diff --git a/src/dbg_engine/generated/dbg_engine.meta.h b/src/dbg_engine/generated/dbg_engine.meta.h index 93d86b91..859bab04 100644 --- a/src/dbg_engine/generated/dbg_engine.meta.h +++ b/src/dbg_engine/generated/dbg_engine.meta.h @@ -41,6 +41,7 @@ D_CmdKind_ThawEntity, D_CmdKind_SetEntityColor, D_CmdKind_SetEntityName, D_CmdKind_Attach, +D_CmdKind_OpenCrashDump, D_CmdKind_COUNT, } D_CmdKind; diff --git a/src/dbg_info/dbg_info.c b/src/dbg_info/dbg_info.c index 5cbbf1b6..78fdcb29 100644 --- a/src/dbg_info/dbg_info.c +++ b/src/dbg_info/dbg_info.c @@ -1306,7 +1306,7 @@ di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 * } lane_sync(); - //- rjf: sort records + //- rjf: sort records if we have a query if(!cancelled) ProfScope("sort records") { //- rjf: set up common data diff --git a/src/minidump/minidump.c b/src/minidump/minidump.c new file mode 100644 index 00000000..ae447aab --- /dev/null +++ b/src/minidump/minidump.c @@ -0,0 +1,2 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) diff --git a/src/minidump/minidump.h b/src/minidump/minidump.h new file mode 100644 index 00000000..c609e468 --- /dev/null +++ b/src/minidump/minidump.h @@ -0,0 +1,200 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef MINIDUMP_H +#define MINIDUMP_H + +typedef enum MDMP_DumpKind +{ + MDMP_DumpKind_Normal = 0x00000000, + MDMP_DumpKind_WithDataSegs = 0x00000001, + MDMP_DumpKind_WithFullMemory = 0x00000002, + MDMP_DumpKind_WithHandleData = 0x00000004, + MDMP_DumpKind_FilterMemory = 0x00000008, + MDMP_DumpKind_ScanMemory = 0x00000010, + MDMP_DumpKind_WithUnloadedModules = 0x00000020, + MDMP_DumpKind_WithIndirectlyReferencedMemory = 0x00000040, + MDMP_DumpKind_FilterModulePaths = 0x00000080, + MDMP_DumpKind_WithProcessThreadData = 0x00000100, + MDMP_DumpKind_WithPrivateReadWriteMemory = 0x00000200, + MDMP_DumpKind_WithoutOptionalData = 0x00000400, + MDMP_DumpKind_WithFullMemoryInfo = 0x00000800, + MDMP_DumpKind_WithThreadInfo = 0x00001000, + MDMP_DumpKind_WithCodeSegs = 0x00002000, + MDMP_DumpKind_WithoutAuxiliaryState = 0x00004000, + MDMP_DumpKind_WithFullAuxiliaryState = 0x00008000, + MDMP_DumpKind_WithPrivateWriteCopyMemory = 0x00010000, + MDMP_DumpKind_IgnoreInaccessibleMemory = 0x00020000, + MDMP_DumpKind_WithTokenInformation = 0x00040000, + MDMP_DumpKind_WithModuleHeaders = 0x00080000, + MDMP_DumpKind_FilterTriage = 0x00100000, + MDMP_DumpKind_WithAvxXStateContext = 0x00200000, + MDMP_DumpKind_WithIptTrace = 0x00400000, + MDMP_DumpKind_ScanInaccessiblePartialPages = 0x00800000, + MDMP_DumpKind_FilterWriteCombinedMemory, + MDMP_DumpKind_ValidTypeFlags = 0x01ffffff, + MDMP_DumpKind_NoIgnoreInaccessibleMemory, + MDMP_DumpKind_ValidTypeFlagsEx +} +MDMP_DumpKind; + +typedef enum MDMP_StreamKind +{ + MDMP_StreamKind_Unused = 0, + MDMP_StreamKind_Reserved0 = 1, + MDMP_StreamKind_Reserved1 = 2, + MDMP_StreamKind_ThreadList = 3, + MDMP_StreamKind_ModuleList = 4, + MDMP_StreamKind_MemoryList = 5, + MDMP_StreamKind_Exception = 6, + MDMP_StreamKind_SystemInfo = 7, + MDMP_StreamKind_ThreadExList = 8, + MDMP_StreamKind_Memory64List = 9, + MDMP_StreamKind_CommentA = 10, + MDMP_StreamKind_CommentW = 11, + MDMP_StreamKind_HandleData = 12, + MDMP_StreamKind_FunctionTable = 13, + MDMP_StreamKind_UnloadedModuleList = 14, + MDMP_StreamKind_MiscInfo = 15, + MDMP_StreamKind_MemoryInfoList = 16, + MDMP_StreamKind_ThreadInfoList = 17, + MDMP_StreamKind_HandleOperationList = 18, + MDMP_StreamKind_Token = 19, + MDMP_StreamKind_JavaScriptData = 20, + MDMP_StreamKind_SystemMemoryInfo = 21, + MDMP_StreamKind_ProcessVmCounters = 22, + MDMP_StreamKind_IptTrace = 23, + MDMP_StreamKind_ThreadNames = 24, + MDMP_StreamKind_ceNull = 0x8000, + MDMP_StreamKind_ceSystemInfo = 0x8001, + MDMP_StreamKind_ceException = 0x8002, + MDMP_StreamKind_ceModuleList = 0x8003, + MDMP_StreamKind_ceProcessList = 0x8004, + MDMP_StreamKind_ceThreadList = 0x8005, + MDMP_StreamKind_ceThreadContextList = 0x8006, + MDMP_StreamKind_ceThreadCallStackList = 0x8007, + MDMP_StreamKind_ceMemoryVirtualList = 0x8008, + MDMP_StreamKind_ceMemoryPhysicalList = 0x8009, + MDMP_StreamKind_ceBucketParameters = 0x800A, + MDMP_StreamKind_ceProcessModuleMap = 0x800B, + MDMP_StreamKind_ceDiagnosisList = 0x800C, + MDMP_StreamKind_LastReserved = 0xffff +} +MDMP_StreamKind; + +#define MDMP_MAGIC 0x504d444d + +typedef struct MDMP_Header MDMP_Header; +struct MDMP_Header +{ + U32 magic; + U32 version; + U32 number_of_streams; + U32 stream_directory_foff; + U32 checksum; + U32 reserved_or_time_date_stamp; + U64 flags; // MDMP_DumpKind +}; + +typedef struct MDMP_LocationDescriptor32 MDMP_LocationDescriptor32; +struct MDMP_LocationDescriptor32 +{ + U32 data_size; + U32 voff; +}; + +typedef struct MDMP_LocationDescriptor64 MDMP_LocationDescriptor64; +struct MDMP_LocationDescriptor64 +{ + U64 data_size; + U64 voff; +}; + +typedef struct MDMP_Directory MDMP_Directory; +struct MDMP_Directory +{ + U32 stream_kind; + MDMP_LocationDescriptor32 location; +}; + +typedef struct MDMP_MemoryDescriptor32 MDMP_MemoryDescriptor32; +struct MDMP_MemoryDescriptor32 +{ + U64 start_of_memory_range; + MDMP_LocationDescriptor32 memory_location; +}; + +typedef struct MDMP_MemoryDescriptor64 MDMP_MemoryDescriptor64; +struct MDMP_MemoryDescriptor64 +{ + U64 start_of_memory_range; + U64 size; +}; + +typedef struct MDMP_Thread MDMP_Thread; +struct MDMP_Thread +{ + U32 id; + U32 suspend_count; + U32 priority_class; + U32 priority; + U64 teb; + MDMP_MemoryDescriptor32 stack; + MDMP_LocationDescriptor32 thread_context; +}; + +typedef struct MDMP_FixedFileInfo MDMP_FixedFileInfo; +struct MDMP_FixedFileInfo +{ + U32 signature; + U32 struct_version; + U32 file_version_ms; + U32 file_version_ls; + U32 product_version_ms; + U32 product_version_ls; + U32 file_flags_mask; + U32 file_flags; + U32 file_os; + U32 file_type; + U32 file_subtype; + U32 file_date_ms; + U32 file_date_ls; +}; + +typedef struct MDMP_Module MDMP_Module; +struct MDMP_Module +{ + U64 image_base_vaddr; + U32 image_size; + U32 checksum; + U32 time_date_stamp; + U32 module_name_voff; + MDMP_FixedFileInfo version_info; + MDMP_LocationDescriptor32 cv_record; + MDMP_LocationDescriptor32 misc_record; + U64 reserved_0; + U64 reserved_1; +}; + +typedef struct MDMP_Exception MDMP_Exception; +struct MDMP_Exception +{ + U32 exception_code; + U32 exception_flags; + U64 exception_record; + U64 exception_addr; + U32 number_parameters; + U32 unused_alignment; + U64 exception_information[15]; +}; + +typedef struct MDMP_ExceptionStream MDMP_ExceptionStream; +struct MDMP_ExceptionStream +{ + U32 thread_id; + U32 padding; + MDMP_Exception exception; + MDMP_LocationDescriptor32 thread_context; +}; + +#endif // MINIDUMP_H diff --git a/src/minidump/minidump_parse.c b/src/minidump/minidump_parse.c new file mode 100644 index 00000000..654f300c --- /dev/null +++ b/src/minidump/minidump_parse.c @@ -0,0 +1,3 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + diff --git a/src/minidump/minidump_parse.h b/src/minidump/minidump_parse.h new file mode 100644 index 00000000..8b9d4225 --- /dev/null +++ b/src/minidump/minidump_parse.h @@ -0,0 +1,28 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef MINIDUMP_PARSE_H +#define MINIDUMP_PARSE_H + +typedef struct MDMP_ThreadArray MDMP_ThreadArray; +struct MDMP_ThreadArray +{ + MDMP_Thread *v; + U64 count; +}; + +typedef struct MDMP_ModuleArray MDMP_ModuleArray; +struct MDMP_ModuleArray +{ + MDMP_Module *v; + U64 count; +}; + +typedef struct MDMP_MemoryArray MDMP_MemoryArray; +struct MDMP_MemoryArray +{ + MDMP_MemoryDescriptor64 *v; + U64 count; +}; + +#endif // MINIDUMP_PARSE_H diff --git a/src/mule/mule_main.cpp b/src/mule/mule_main.cpp index be842092..c32dc590 100644 --- a/src/mule/mule_main.cpp +++ b/src/mule/mule_main.cpp @@ -424,14 +424,14 @@ variadic_params(char *fmt, ...) static void type_coverage_eval_tests(void) { - Basics basics = {-1, 1, -2, 2, -4, 4, -8, 8, 1.5f, 1.50000000000001}; EvalTest(basics.a, -1); + Basics basics = {-1, 1, -2, 2, -4, 4, -8, 8, 1.5f, 1.50000000000001}; Basics_Stdint basics_stdint = {-1, 1, -2, 2, -4, 4, -8, 8, 1.5f, 1.50000000000001}; uint32_t a = (1<<31); int32_t b = (1<<31); - uint32_t abcd = 0xaabbccdd; EvalTest(abcd, 0xaabbccdd); - int64_t abcd64 = (int64_t)abcd; EvalTest(abcd64, 0xaabbccdd); EvalTest(abcd64, abcd); + uint32_t abcd = 0xaabbccdd; + int64_t abcd64 = (int64_t)abcd; char string[] = "Hello World!"; char longer_text[] = diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index 19b877bb..717d10fa 100644 --- a/src/raddbg/generated/raddbg.meta.c +++ b/src/raddbg/generated/raddbg.meta.c @@ -62,7 +62,7 @@ str8_lit_comp(""), str8_lit_comp(""), }; -RD_VocabInfo rd_vocab_info_table[359] = +RD_VocabInfo rd_vocab_info_table[360] = { {str8_lit_comp("type_view"), str8_lit_comp("type_views"), str8_lit_comp("Type View"), str8_lit_comp("Type Views"), RD_IconKind_Binoculars}, {str8_lit_comp("file_path_map"), str8_lit_comp("file_path_maps"), str8_lit_comp("File Path Map"), str8_lit_comp("File Path Maps"), RD_IconKind_FileOutline}, @@ -208,6 +208,7 @@ RD_VocabInfo rd_vocab_info_table[359] = {str8_lit_comp("set_entity_color"), str8_lit_comp(""), str8_lit_comp("Set Entity Color"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("set_entity_name"), str8_lit_comp(""), str8_lit_comp("Set Entity Name"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("attach"), str8_lit_comp(""), str8_lit_comp("Attach"), str8_lit_comp(""), RD_IconKind_Null}, +{str8_lit_comp("open_crash_dump"), str8_lit_comp(""), str8_lit_comp("Open Crash Dump"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("exit"), str8_lit_comp(""), str8_lit_comp("Exit"), str8_lit_comp(""), RD_IconKind_X}, {str8_lit_comp("open_palette"), str8_lit_comp(""), str8_lit_comp("Open Palette"), str8_lit_comp(""), RD_IconKind_List}, {str8_lit_comp("run_command"), str8_lit_comp(""), str8_lit_comp("Run Command"), str8_lit_comp(""), RD_IconKind_Null}, @@ -574,7 +575,7 @@ Rng1U64 rd_reg_slot_range_table[49] = {OffsetOf(RD_Regs, wm_event), OffsetOf(RD_Regs, wm_event) + sizeof(WM_Event *)}, }; -RD_CmdKindInfo rd_cmd_kind_info_table[248] = +RD_CmdKindInfo rd_cmd_kind_info_table[249] = { {0}, { str8_lit_comp("launch_and_run"), str8_lit_comp("Starts debugging a new instance of a target, then runs."), str8_lit_comp("launch,start,run,target"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:targets"), str8_lit_comp(""), D_EntityKind_Null}}, @@ -609,6 +610,7 @@ RD_CmdKindInfo rd_cmd_kind_info_table[248] = { str8_lit_comp("set_entity_color"), str8_lit_comp("Sets the passed entity's color."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, { str8_lit_comp("set_entity_name"), str8_lit_comp("Sets the passed entity's name."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, { str8_lit_comp("attach"), str8_lit_comp("Attaches to a process that is already running on the local machine."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_PID, str8_lit_comp("query:unattached_processes"), str8_lit_comp(""), D_EntityKind_Null}}, +{ str8_lit_comp("open_crash_dump"), str8_lit_comp("Opens a crash dump file and recreates debuggee state at the time of the crash."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), D_EntityKind_Null}}, { str8_lit_comp("exit"), str8_lit_comp("Exits the debugger."), str8_lit_comp("quit,close,abort"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, { str8_lit_comp("open_palette"), str8_lit_comp("Opens the palette."), str8_lit_comp("help,cmd,lister"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, { str8_lit_comp("run_command"), str8_lit_comp("Runs a command from the command palette."), str8_lit_comp("help,cmd"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_CmdName, str8_lit_comp("query:commands"), str8_lit_comp("commands"), D_EntityKind_Null}}, diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index 6cff775b..0ee04afc 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -95,6 +95,7 @@ RD_CmdKind_ThawEntity, RD_CmdKind_SetEntityColor, RD_CmdKind_SetEntityName, RD_CmdKind_Attach, +RD_CmdKind_OpenCrashDump, RD_CmdKind_Exit, RD_CmdKind_OpenPalette, RD_CmdKind_RunCommand, @@ -602,7 +603,7 @@ Z(getting_started)\ C_LINKAGE_BEGIN extern String8 rd_tab_fast_path_view_name_table[25]; extern String8 rd_tab_fast_path_query_name_table[25]; -extern RD_VocabInfo rd_vocab_info_table[359]; +extern RD_VocabInfo rd_vocab_info_table[360]; extern RD_NameSchemaInfo rd_name_schema_info_table[39]; extern String8 rd_reg_slot_code_name_table[49]; extern Rng1U64 rd_reg_slot_range_table[49]; diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 597295d6..422000bb 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -693,8 +693,9 @@ rd_ctrl_entity_from_eval_space(E_Space space) space.kind == RD_EvalSpaceKind_MetaUnattachedProcess) { D_Handle handle; - handle.machine_id = space.u64s[0]; - handle.dmn_handle.u64[0] = space.u64s[1]; + handle.machine_id = (U32)((space.u64s[0] & 0xffffffff00000000ull) >> 32); + handle.controller_kind = (U32)((space.u64s[0] & 0x00000000ffffffffull) >> 0); + handle.entity_id = space.u64s[1]; entity = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, handle); } return entity; @@ -704,8 +705,8 @@ internal E_Space rd_eval_space_from_ctrl_entity(D_Entity *entity, E_SpaceKind kind) { E_Space space = e_space_make(kind); - space.u64s[0] = entity->handle.machine_id; - space.u64s[1] = entity->handle.dmn_handle.u64[0]; + space.u64s[0] = (((U64)entity->handle.machine_id) << 32) | (((U64)entity->handle.controller_kind) << 0); + space.u64s[1] = entity->handle.entity_id; return space; } @@ -5755,7 +5756,7 @@ rd_window_frame(void) ID(panel); ID(view); #undef ID -#define Handle(name) ui_labelf("%s: [0x%I64x, 0x%I64x]", #name, (regs->name).machine_id, (regs->name).dmn_handle.u64[0]) +#define Handle(name) ui_labelf("%s: [0x%x, 0x%x, 0x%I64x]", #name, (regs->name).machine_id, (regs->name).controller_kind, (regs->name).entity_id) Handle(machine); Handle(process); Handle(module); diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index 652db922..a965bd4c 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -298,6 +298,8 @@ #include "artifact_cache/artifact_cache.h" #include "rdi/rdi_local.h" #include "rdi_make/rdi_make_local.h" +#include "minidump/minidump.h" +#include "minidump/minidump_parse.h" #include "mdesk/mdesk.h" #include "window_manager/window_manager_inc.h" #include "config/config_inc.h" @@ -351,6 +353,8 @@ #include "artifact_cache/artifact_cache.c" #include "rdi/rdi_local.c" #include "rdi_make/rdi_make_local.c" +#include "minidump/minidump.c" +#include "minidump/minidump_parse.c" #include "mdesk/mdesk.c" #include "window_manager/window_manager_inc.c" #include "config/config_inc.c" diff --git a/src/raddbg/raddbg_widgets.c b/src/raddbg/raddbg_widgets.c index ef103854..96ada8e6 100644 --- a/src/raddbg/raddbg_widgets.c +++ b/src/raddbg/raddbg_widgets.c @@ -2516,7 +2516,7 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe ui_spacer(ui_em(1.5f, 1.f)); ui_set_next_pref_width(ui_children_sum(1)); UI_Key pin_box_key = ui_key_from_stringf(ui_key_zero(), "###pin_%p", pin); - UI_Box *pin_box = ui_build_box_from_key(UI_BoxFlag_AnimatePos, pin_box_key); + UI_Box *pin_box = ui_build_box_from_key(0, pin_box_key); F32 pin_t = ui_anim(pin_box_key, 1.f, .rate = rd_state->catchall_animation_rate); UI_Parent(pin_box) UI_PrefWidth(ui_text_dim(1, 1)) {