diff --git a/src/arch/arch_inc.c b/src/arch/arch_inc.c index e07d1b7c..eae4b158 100644 --- a/src/arch/arch_inc.c +++ b/src/arch/arch_inc.c @@ -2,6 +2,7 @@ // Licensed under the MIT license (https://opensource.org/license/mit/) #include "arch/arch.c" +#include "arch/os/arch_os.c" #if defined(DWARF_H) # include "arch/dwarf/arch_dwarf.c" #endif diff --git a/src/arch/arch_inc.h b/src/arch/arch_inc.h index 0155cfc4..529c3893 100644 --- a/src/arch/arch_inc.h +++ b/src/arch/arch_inc.h @@ -5,6 +5,7 @@ #define ARCH_INC_H #include "arch/arch.h" +#include "arch/os/arch_os.h" #if defined(DWARF_H) # include "arch/dwarf/arch_dwarf.h" #endif diff --git a/src/arch/os/arch_os.c b/src/arch/os/arch_os.c new file mode 100644 index 00000000..2a3fe22f --- /dev/null +++ b/src/arch/os/arch_os.c @@ -0,0 +1,16 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +internal B32 +arch_os_write_reg_block_from_thread_ctx(Arch arch, OperatingSystem os, void *reg_block, void *thread_ctx) +{ + B32 result = 0; + if(0){} +#define Case(arch_, os_, impl) else if((arch) == arch_ && (os) == os_) do {result = impl(reg_block, thread_ctx);}while(0) +#if defined(X64_H) && defined(WIN32_X64_H) + Case(Arch_x64, OperatingSystem_Windows, w32_x64_write_reg_block_from_thread_ctx); +#endif +#undef Case + else{} + return result; +} diff --git a/src/arch/os/arch_os.h b/src/arch/os/arch_os.h new file mode 100644 index 00000000..6534eeff --- /dev/null +++ b/src/arch/os/arch_os.h @@ -0,0 +1,9 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef ARCH_OS_H +#define ARCH_OS_H + +internal B32 arch_os_write_reg_block_from_thread_ctx(Arch arch, OperatingSystem os, void *reg_block, void *thread_ctx); + +#endif // ARCH_OS_H diff --git a/src/dbg_engine/dbg_engine_core.c b/src/dbg_engine/dbg_engine_core.c index 4606be04..1f487512 100644 --- a/src/dbg_engine/dbg_engine_core.c +++ b/src/dbg_engine/dbg_engine_core.c @@ -80,6 +80,9 @@ d_init(void) } d_ctrl_state->ctrl_thread_log = log_alloc(); d_ctrl_state->ctrl_thread = thread_launch(d_ctrl_thread__entry_point, 0); + d_ctrl_state->dump_cache.slots_count = 64; + d_ctrl_state->dump_cache.slots = push_array(arena, D_DumpSlot, d_ctrl_state->dump_cache.slots_count); + d_ctrl_state->dump_cache.stripes = stripe_array_alloc(arena); } //- rjf: set up user state @@ -111,4 +114,7 @@ d_init(void) // rjf: set up run state d_user_state->ctrl_last_run_arena = arena_alloc(); } + + //- rjf: select user state's entity context + d_select_entity_ctx(&d_user_state->ctrl_entity_store->ctx); } diff --git a/src/dbg_engine/dbg_engine_core.h b/src/dbg_engine/dbg_engine_core.h index 95544f36..74c991da 100644 --- a/src/dbg_engine/dbg_engine_core.h +++ b/src/dbg_engine/dbg_engine_core.h @@ -10,11 +10,12 @@ typedef U64 D_MsgID; typedef U32 D_MachineID; typedef U32 D_ControllerKind; -enum +typedef enum D_ControllerKindEnum { D_ControllerKind_Demon, D_ControllerKind_Dump, -}; +} +D_ControllerKindEnum; #define D_MachineID_Local (1) @@ -234,21 +235,6 @@ 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 @@ -325,8 +311,8 @@ struct D_TrapList typedef struct D_Spoof D_Spoof; struct D_Spoof { - DMN_Handle process; - DMN_Handle thread; + D_Handle process; + D_Handle thread; U64 vaddr; U64 new_ip_value; }; diff --git a/src/dbg_engine/dbg_engine_ctrl.c b/src/dbg_engine/dbg_engine_ctrl.c index 17a0a450..b3ec728e 100644 --- a/src/dbg_engine/dbg_engine_ctrl.c +++ b/src/dbg_engine/dbg_engine_ctrl.c @@ -696,6 +696,16 @@ d_event_from_serialized_string(Arena *arena, String8 string) //////////////////////////////// //~ rjf: Entity Type Functions +//- rjf: entity context selection + +internal D_EntityCtx * +d_select_entity_ctx(D_EntityCtx *ctx) +{ + D_EntityCtx *popped = d_entity_ctx; + d_entity_ctx = ctx; + return popped; +} + //- rjf: entity list data structures internal void @@ -708,12 +718,12 @@ d_entity_list_push(Arena *arena, D_EntityList *list, D_Entity *entity) } internal D_EntityList -d_entity_list_from_handle_list(Arena *arena, D_EntityCtx *ctx, D_HandleList *list) +d_entity_list_from_handle_list(Arena *arena, D_HandleList *list) { D_EntityList result = {0}; for(D_HandleNode *n = list->first; n != 0; n = n->next) { - D_Entity *entity = d_entity_from_handle(ctx, n->v); + D_Entity *entity = d_entity_from_handle(n->v); d_entity_list_push(arena, &result, entity); } return result; @@ -738,14 +748,14 @@ d_entity_array_from_list(Arena *arena, D_EntityList *list) //- rjf: entity context (entity group read-only) functions internal D_Entity * -d_entity_from_handle(D_EntityCtx *ctx, D_Handle handle) +d_entity_from_handle(D_Handle handle) { D_Entity *entity = &d_entity_nil; if(!d_handle_match(handle, d_handle_zero())) { U64 hash = d_hash_from_handle(handle); - U64 slot_idx = hash%ctx->hash_slots_count; - D_EntityHashSlot *slot = &ctx->hash_slots[slot_idx]; + U64 slot_idx = hash%d_entity_ctx->hash_slots_count; + D_EntityHashSlot *slot = &d_entity_ctx->hash_slots[slot_idx]; D_EntityHashNode *node = 0; for(D_EntityHashNode *n = slot->first; n != 0; n = n->next) { @@ -832,10 +842,10 @@ d_dbgi_key_from_module(D_Entity *module) } internal D_Entity * -d_module_from_thread_candidates(D_EntityCtx *ctx, D_Entity *thread, D_EntityList *candidates) +d_module_from_thread_candidates(D_Entity *thread, D_EntityList *candidates) { D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process); - U64 thread_rip_vaddr = d_rip_from_thread(ctx, thread->handle); + U64 thread_rip_vaddr = d_rip_from_thread(thread->handle); D_Entity *src_module = d_module_from_process_vaddr(process, thread_rip_vaddr); D_Entity *module = &d_entity_nil; for(D_EntityNode *n = candidates->first; n != 0; n = n->next) @@ -1188,23 +1198,23 @@ d_thread_entity_ctx_lookup_accel(void) } internal D_EntityArray -d_entity_array_from_kind(D_EntityCtx *ctx, D_EntityKind kind) +d_entity_array_from_kind(D_EntityKind kind) { D_EntityCtxLookupAccel *accel = d_thread_entity_ctx_lookup_accel(); - if(accel->entity_kind_arrays_gens[kind] != ctx->entity_kind_alloc_gens[kind]) + if(accel->entity_kind_arrays_gens[kind] != d_entity_ctx->entity_kind_alloc_gens[kind]) { Temp scratch = scratch_begin(0, 0); D_EntityList entities = {0}; - for(D_Entity *e = ctx->root; + for(D_Entity *e = d_entity_ctx->root; e != &d_entity_nil; - e = d_entity_rec_depth_first_pre(e, ctx->root).next) + e = d_entity_rec_depth_first_pre(e, d_entity_ctx->root).next) { if(e->kind == kind) { d_entity_list_push(scratch.arena, &entities, e); } } - accel->entity_kind_arrays_gens[kind] = ctx->entity_kind_alloc_gens[kind]; + accel->entity_kind_arrays_gens[kind] = d_entity_ctx->entity_kind_alloc_gens[kind]; arena_clear(accel->entity_kind_arrays_arenas[kind]); accel->entity_kind_arrays[kind] = d_entity_array_from_list(accel->entity_kind_arrays_arenas[kind], &entities); scratch_end(scratch); @@ -1213,10 +1223,10 @@ d_entity_array_from_kind(D_EntityCtx *ctx, D_EntityKind kind) } internal D_EntityList -d_modules_from_dbgi_key(Arena *arena, D_EntityCtx *ctx, DI_Key dbgi_key) +d_modules_from_dbgi_key(Arena *arena, DI_Key dbgi_key) { D_EntityList list = {0}; - D_EntityArray all_modules = d_entity_array_from_kind(ctx, D_EntityKind_Module); + D_EntityArray all_modules = d_entity_array_from_kind(D_EntityKind_Module); for EachIndex(idx, all_modules.count) { D_Entity *module = all_modules.v[idx]; @@ -1230,10 +1240,10 @@ d_modules_from_dbgi_key(Arena *arena, D_EntityCtx *ctx, DI_Key dbgi_key) } internal D_Entity * -d_thread_from_id(D_EntityCtx *ctx, U64 id) +d_thread_from_id(U64 id) { D_Entity *thread = &d_entity_nil; - D_EntityArray threads = d_entity_array_from_kind(ctx, D_EntityKind_Thread); + D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread); for EachIndex(idx, threads.count) { if(threads.v[idx]->id == id) @@ -1273,6 +1283,8 @@ d_entity_rec_depth_first(D_Entity *entity, D_Entity *subtree_root, U64 sib_off, internal void d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) { + D_EntityCtx *ctx_restore = d_select_entity_ctx(&store->ctx); + //- rjf: scan events & construct entities for(D_EventNode *n = list->first; n != 0; n = n->next) { @@ -1284,7 +1296,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_from_dmn(event->entity.machine_id, dmn_handle_zero())); + D_Entity *machine = d_entity_from_handle(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); @@ -1294,7 +1306,7 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) }break; case D_EventKind_EndProc: { - D_Entity *process = d_entity_from_handle(&store->ctx, event->entity); + D_Entity *process = d_entity_from_handle(event->entity); d_entity_release(store, process); for(D_Entity *entry = store->ctx.root->first, *next = &d_entity_nil; entry != &d_entity_nil; @@ -1311,7 +1323,7 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) //- rjf: threads case D_EventKind_NewThread: { - D_Entity *process = d_entity_from_handle(&store->ctx, event->parent); + D_Entity *process = d_entity_from_handle(event->parent); if(process != &d_entity_nil) { D_Entity *thread = d_entity_alloc(store, process, D_EntityKind_Thread, event->arch, event->entity, (U64)event->entity_id); @@ -1320,7 +1332,7 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) { d_entity_equip_string(store, thread, str8_lit("main_thread")); } - D_EntityArray pending_thread_names = d_entity_array_from_kind(&store->ctx, D_EntityKind_PendingThreadName); + D_EntityArray pending_thread_names = d_entity_array_from_kind(D_EntityKind_PendingThreadName); for EachIndex(idx, pending_thread_names.count) { D_Entity *entity = pending_thread_names.v[idx]; @@ -1331,7 +1343,7 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) break; } } - D_EntityArray pending_thread_colors = d_entity_array_from_kind(&store->ctx, D_EntityKind_PendingThreadColor); + D_EntityArray pending_thread_colors = d_entity_array_from_kind(D_EntityKind_PendingThreadColor); for EachIndex(idx, pending_thread_colors.count) { D_Entity *entity = pending_thread_colors.v[idx]; @@ -1348,20 +1360,20 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) }break; case D_EventKind_EndThread: { - D_Entity *thread = d_entity_from_handle(&store->ctx, event->entity); + D_Entity *thread = d_entity_from_handle(event->entity); d_entity_release(store, thread); }break; case D_EventKind_ThreadName: { - D_Entity *process = d_entity_from_handle(&store->ctx, event->parent); + D_Entity *process = d_entity_from_handle(event->parent); D_Entity *thread = &d_entity_nil; if(event->entity_id == 0) { - thread = d_entity_from_handle(&store->ctx, event->entity); + thread = d_entity_from_handle(event->entity); } else { - thread = d_thread_from_id(&store->ctx, event->entity_id); + thread = d_thread_from_id(event->entity_id); } if(thread != &d_entity_nil) { @@ -1375,15 +1387,15 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) }break; case D_EventKind_ThreadColor: { - D_Entity *process = d_entity_from_handle(&store->ctx, event->parent); + D_Entity *process = d_entity_from_handle(event->parent); D_Entity *thread = &d_entity_nil; if(event->entity_id == 0) { - thread = d_entity_from_handle(&store->ctx, event->entity); + thread = d_entity_from_handle(event->entity); } else { - thread = d_thread_from_id(&store->ctx, event->entity_id); + thread = d_thread_from_id(event->entity_id); } if(thread != &d_entity_nil) { @@ -1397,7 +1409,7 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) }break; case D_EventKind_ThreadFrozen: { - D_Entity *thread = d_entity_from_handle(&store->ctx, event->entity); + D_Entity *thread = d_entity_from_handle(event->entity); if(thread != &d_entity_nil) { thread->is_frozen = 1; @@ -1405,7 +1417,7 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) }break; case D_EventKind_ThreadThawed: { - D_Entity *thread = d_entity_from_handle(&store->ctx, event->entity); + D_Entity *thread = d_entity_from_handle(event->entity); if(thread != &d_entity_nil) { thread->is_frozen = 0; @@ -1416,7 +1428,7 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) case D_EventKind_NewModule: { Temp scratch = scratch_begin(0, 0); - D_Entity *process = d_entity_from_handle(&store->ctx, event->parent); + D_Entity *process = d_entity_from_handle(event->parent); D_Entity *module = d_entity_alloc(store, process, D_EntityKind_Module, event->arch, event->entity, event->vaddr_rng.min); d_entity_equip_string(store, module, event->string); module->timestamp = event->timestamp; @@ -1432,13 +1444,13 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) }break; case D_EventKind_EndModule: { - D_Entity *module = d_entity_from_handle(&store->ctx, event->entity); + D_Entity *module = d_entity_from_handle(event->entity); d_entity_release(store, module); }break; case D_EventKind_ModuleDebugInfoPathChange: { Temp scratch = scratch_begin(0, 0); - D_Entity *module = d_entity_from_handle(&store->ctx, event->entity); + D_Entity *module = d_entity_from_handle(event->entity); D_Entity *debug_info_path = d_entity_child_from_kind(module, D_EntityKind_DebugInfoPath); if(debug_info_path == &d_entity_nil) { @@ -1452,14 +1464,14 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) //- rjf: dynamic, program-created breakpoints case D_EventKind_SetBreakpoint: { - D_Entity *process = d_entity_from_handle(&store->ctx, event->parent); + D_Entity *process = d_entity_from_handle(event->parent); D_Entity *bp = d_entity_alloc(store, process, D_EntityKind_Breakpoint, Arch_Null, d_handle_zero(), 0); bp->vaddr_range = event->vaddr_rng; bp->bp_flags = event->bp_flags; }break; case D_EventKind_UnsetBreakpoint: { - D_Entity *process = d_entity_from_handle(&store->ctx, event->parent); + D_Entity *process = d_entity_from_handle(event->parent); for(D_Entity *child = process->first; child != &d_entity_nil; child = child->next) { if(child->kind == D_EntityKind_Breakpoint && @@ -1476,13 +1488,15 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) //- rjf: address range annotations case D_EventKind_SetVAddrRangeNote: { - D_Entity *process = d_entity_from_handle(&store->ctx, event->parent); + D_Entity *process = d_entity_from_handle(event->parent); D_Entity *annotation = d_entity_alloc(store, process, D_EntityKind_AddressRangeAnnotation, Arch_Null, d_handle_zero(), 0); annotation->vaddr_range = event->vaddr_rng; d_entity_equip_string(store, annotation, event->string); }break; } } + + d_select_entity_ctx(ctx_restore); } //////////////////////////////// @@ -1497,13 +1511,96 @@ d_set_wakeup_hook(D_WakeupFunctionType *wakeup_hook) //////////////////////////////// //~ rjf: Thread Register Functions +//- rjf: thread handle read/write + +internal B32 +d_thread_read_reg_block(D_Handle handle, void *reg_block) +{ + B32 result = 0; + switch((D_ControllerKindEnum)handle.controller_kind) + { + case D_ControllerKind_Demon: + { + result = dmn_thread_read_reg_block(d_dmn_from_handle(handle), reg_block); + }break; + case D_ControllerKind_Dump: + { + D_Entity *thread = d_entity_from_handle(handle); + D_Entity *process = d_process_from_entity(thread); + D_DumpCache *cache = &d_ctrl_state->dump_cache; + U64 hash = d_hash_from_handle(process->handle); + U64 slot_idx = hash%cache->slots_count; + Stripe *stripe = stripe_from_slot_idx(&cache->stripes, slot_idx); + RWMutexScope(stripe->rw_mutex, 0) + { + // rjf: process -> dump node + D_DumpNode *node = 0; + for(D_DumpNode *n = cache->slots[slot_idx].first; n != 0; n = n->next) + { + if(d_handle_match(n->process, process->handle)) + { + node = n; + break; + } + } + + // rjf: thread -> context in dump + void *thread_ctx = 0; + if(node != 0) + { + for EachIndex(idx, node->threads_count) + { + if(d_handle_match(thread->handle, node->threads[idx].thread_handle)) + { + thread_ctx = (U8 *)node->base + node->threads[idx].context_foff; + } + } + } + + // rjf: read context structure into reg block + if(thread_ctx != 0) + { + Arch arch = thread->arch; + OperatingSystem os = process->target_os; + result = arch_os_write_reg_block_from_thread_ctx(arch, os, reg_block, thread_ctx); + } + } + }break; + } + return result; +} + +internal B32 +d_thread_write_reg_block(D_Handle thread, void *block) +{ + B32 result = 0; + switch((D_ControllerKindEnum)thread.controller_kind) + { + case D_ControllerKind_Demon: + { + // TODO(rjf): @callstacks immediately reflect this in the call stack cache + DMN_Handle handle_dmn = d_dmn_from_handle(thread); + B32 result = dmn_thread_write_reg_block(handle_dmn, block); + if(result) + { + ins_atomic_u64_inc_eval(&d_ctrl_state->reg_gen); + } + }break; + case D_ControllerKind_Dump: + { + // TODO(rjf) + }break; + } + return result; +} + //- rjf: thread register cache reading internal void * -d_reg_block_from_thread(Arena *arena, D_EntityCtx *ctx, D_Handle handle) +d_reg_block_from_thread(Arena *arena, D_Handle handle) { D_ThreadRegCache *cache = &d_ctrl_state->thread_reg_cache; - D_Entity *thread_entity = d_entity_from_handle(ctx, handle); + D_Entity *thread_entity = d_entity_from_handle(handle); Arch arch = thread_entity->arch; ARCH_Info *arch_info = arch_info_from_arch(arch); U64 reg_block_size = arch_info->reg_block_size; @@ -1541,8 +1638,7 @@ d_reg_block_from_thread(Arena *arena, D_EntityCtx *ctx, D_Handle handle) { U64 current_reg_gen = d_reg_gen(); B32 need_stale = 1; - 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->reg_gen != current_reg_gen && d_thread_read_reg_block(handle, result)) { if(node != 0) { @@ -1561,7 +1657,7 @@ 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) +d_tls_root_vaddr_from_thread(D_Handle handle) { DMN_Handle handle_dmn = d_dmn_from_handle(handle); U64 result = dmn_tls_root_vaddr_from_thread(handle_dmn); @@ -1569,46 +1665,31 @@ d_tls_root_vaddr_from_thread(D_EntityCtx *ctx, D_Handle handle) } internal U64 -d_rip_from_thread(D_EntityCtx *ctx, D_Handle handle) +d_rip_from_thread(D_Handle handle) { Temp scratch = scratch_begin(0, 0); - D_Entity *thread_entity = d_entity_from_handle(ctx, handle); + D_Entity *thread_entity = d_entity_from_handle(handle); Arch arch = thread_entity->arch; ARCH_Info *arch_info = arch_info_from_arch(arch); - void *block = d_reg_block_from_thread(scratch.arena, ctx, handle); + void *block = d_reg_block_from_thread(scratch.arena, handle); U64 result = arch_ip_from_reg_block(arch_info, block); scratch_end(scratch); return result; } internal U64 -d_rsp_from_thread(D_EntityCtx *ctx, D_Handle handle) +d_rsp_from_thread(D_Handle handle) { Temp scratch = scratch_begin(0, 0); - D_Entity *thread_entity = d_entity_from_handle(ctx, handle); + D_Entity *thread_entity = d_entity_from_handle(handle); Arch arch = thread_entity->arch; ARCH_Info *arch_info = arch_info_from_arch(arch); - void *block = d_reg_block_from_thread(scratch.arena, ctx, handle); + void *block = d_reg_block_from_thread(scratch.arena, handle); U64 result = arch_sp_from_reg_block(arch_info, block); scratch_end(scratch); return result; } -//- rjf: thread register writing - -internal B32 -d_thread_write_reg_block(D_Handle thread, void *block) -{ - // TODO(rjf): @callstacks immediately reflect this in the call stack cache - 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); - } - return good; -} - //////////////////////////////// //~ rjf: Module Image Info Functions @@ -2882,21 +2963,21 @@ d_unwind_step__pe_x64(D_Handle process_handle, D_Handle module_handle, U64 modul //- rjf: abstracted full unwind internal D_Unwind -d_unwind_from_thread(Arena *arena, D_EntityCtx *ctx, D_Handle thread, U64 endt_us) +d_unwind_from_thread(Arena *arena, D_Handle thread, U64 endt_us) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); D_Unwind unwind = { .flags = D_UnwindFlag_Error }; //- rjf: unpack args - D_Entity *thread_entity = d_entity_from_handle(ctx, thread); + D_Entity *thread_entity = d_entity_from_handle(thread); D_Entity *process_entity = thread_entity->parent; Arch arch = thread_entity->arch; ARCH_Info *arch_info = arch_info_from_arch(arch); U64 arch_reg_block_size = arch_info->reg_block_size; //- rjf: grab initial register block - void *regs_block = d_reg_block_from_thread(scratch.arena, ctx, thread); + void *regs_block = d_reg_block_from_thread(scratch.arena, thread); B32 regs_block_good = (arch != Arch_Null && regs_block != 0); //- rjf: loop & unwind @@ -3312,6 +3393,7 @@ d_ctrl_thread__entry_point(void *p) ProfBeginFunction(); DMN_CtrlCtx *ctrl_ctx = dmn_ctrl_begin(); log_select(d_ctrl_state->ctrl_thread_log); + d_select_entity_ctx(&d_ctrl_state->ctrl_thread_entity_store->ctx); //- rjf: loop Temp scratch = scratch_begin(0, 0); @@ -3435,7 +3517,7 @@ d_ctrl_thread__entry_point(void *p) { D_EntityCtx *entity_ctx = &d_ctrl_state->ctrl_thread_entity_store->ctx; String8 path = msg->path; - D_Entity *module = d_entity_from_handle(entity_ctx, msg->entity); + D_Entity *module = d_entity_from_handle(msg->entity); D_Entity *debug_info_path = d_entity_child_from_kind(module, D_EntityKind_DebugInfoPath); DI_Key old_dbgi_key = di_key_from_path_timestamp(debug_info_path->string, debug_info_path->timestamp); di_close(old_dbgi_key, 0); @@ -3483,13 +3565,13 @@ d_ctrl_thread__entry_point(void *p) ProfScope("update thread register cache") { D_EntityCtx *entity_ctx = &d_ctrl_state->ctrl_thread_entity_store->ctx; - D_EntityArray threads = d_entity_array_from_kind(entity_ctx, D_EntityKind_Thread); + D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread); X64_RegBlock *blocks = push_array(scratch.arena, X64_RegBlock, threads.count); { for EachIndex(idx, threads.count) { Temp scratch = scratch_begin(0, 0); - d_reg_block_from_thread(scratch.arena, entity_ctx, threads.v[idx]->handle); + d_reg_block_from_thread(scratch.arena, threads.v[idx]->handle); scratch_end(scratch); } } @@ -3512,8 +3594,7 @@ d_ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, D_EvalScope *e ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); Access *access = eval_scope->access; - 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 *module_entity = d_entity_from_handle(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); @@ -3637,7 +3718,6 @@ 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(); @@ -3663,7 +3743,7 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang //- 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, rng_1u64(vaddr_range.min, vaddr_range.min + module_sig_size), module_sig_bytes); + d_process_read(process, rng_1u64(vaddr_range.min, vaddr_range.min + module_sig_size), module_sig_bytes); ////////////////////////////// //- parse PE module @@ -3679,7 +3759,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, vaddr_range.min, &dos_header) || + if(!d_process_read_struct(process, vaddr_range.min, &dos_header) || dos_header.magic != PE_DOS_MAGIC) { is_valid = 0; @@ -3690,7 +3770,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, vaddr_range.min + dos_header.coff_file_offset, &pe_magic) || + if(!d_process_read_struct(process, vaddr_range.min + dos_header.coff_file_offset, &pe_magic) || pe_magic != PE_MAGIC) { is_valid = 0; @@ -3702,7 +3782,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, vaddr_range.min + file_header_off, &file_header)) + if(!d_process_read_struct(process, vaddr_range.min + file_header_off, &file_header)) { is_valid = 0; } @@ -3720,7 +3800,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, vaddr_range.min + opt_ext_off_range.min, &opt_ext_magic); + d_process_read_struct(process, vaddr_range.min + opt_ext_off_range.min, &opt_ext_magic); // rjf: read info U32 reported_data_dir_offset = 0; @@ -3730,7 +3810,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, vaddr_range.min + opt_ext_off_range.min, &pe_optional); + d_process_read_struct(process, 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; @@ -3738,7 +3818,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, vaddr_range.min + opt_ext_off_range.min, &pe_optional); + d_process_read_struct(process, 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; @@ -3753,18 +3833,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, vaddr_range.min + opt_ext_off_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*PE_DataDirectoryIndex_EXCEPTIONS, &dir); + d_process_read_struct(process, 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, r1u64(vaddr_range.min + pdatas_voff_range.min, vaddr_range.min + pdatas_voff_range.max), pdatas); + d_process_read(process, 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, r1u64(vaddr_range.min + sec_array_off, vaddr_range.min + sec_array_off + sec_count*sizeof(COFF_SectionHeader)), sec); + d_process_read(process, 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; @@ -3774,7 +3854,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, vaddr_range.min + opt_ext_off_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*PE_DataDirectoryIndex_DEBUG, &dir); + d_process_read_struct(process, 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) @@ -3782,46 +3862,49 @@ 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, dir_addr, &dbg_data); + d_process_read_struct(process, 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, vaddr_range.min + dbg_data.voff, &cv_magic); + d_process_read_struct(process, 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, vaddr_range.min+dbg_data.voff, &cv); + U64 read_size = d_process_read_struct(process, vaddr_range.min+dbg_data.voff, &cv); if(read_size == sizeof(cv)) { + U64 pdb_dbg_path_vaddr = vaddr_range.min + dbg_data.voff + sizeof(cv); pdb_dbg_time = cv.time_stamp; pdb_dbg_age = cv.age; - pdb_dbg_path = dmn_process_read_cstring(arena, process_dmn, vaddr_range.min + dbg_data.voff + sizeof(cv)); + pdb_dbg_path = d_data_from_process_vaddr_range(arena, process, r1u64(pdb_dbg_path_vaddr, pdb_dbg_path_vaddr+512), 1); } }break; case PE_CODEVIEW_PDB70_MAGIC: { PE_CvHeaderPDB70 cv; - U64 read_size = dmn_process_read_struct(process_dmn, vaddr_range.min + dbg_data.voff, &cv); + U64 read_size = d_process_read_struct(process, vaddr_range.min + dbg_data.voff, &cv); if(read_size == sizeof(cv)) { + U64 pdb_dbg_path_vaddr = vaddr_range.min + dbg_data.voff + sizeof(cv); pdb_dbg_guid = cv.guid; pdb_dbg_age = cv.age; - pdb_dbg_path = dmn_process_read_cstring(arena, process_dmn, vaddr_range.min + dbg_data.voff + sizeof(cv)); + pdb_dbg_path = d_data_from_process_vaddr_range(arena, process, r1u64(pdb_dbg_path_vaddr, pdb_dbg_path_vaddr+512), 1); } }break; case PE_CODEVIEW_RDI_MAGIC: { PE_CvHeaderRDI cv; - U64 read_size = dmn_process_read_struct(process_dmn, vaddr_range.min + dbg_data.voff, &cv); + U64 read_size = d_process_read_struct(process, vaddr_range.min + dbg_data.voff, &cv); if(read_size == sizeof(cv)) { + U64 rdi_dbg_path_vaddr = vaddr_range.min + dbg_data.voff + sizeof(cv); rdi_dbg_guid = cv.guid; - rdi_dbg_path = dmn_process_read_cstring(arena, process_dmn, vaddr_range.min + dbg_data.voff + sizeof(cv)); + rdi_dbg_path = d_data_from_process_vaddr_range(arena, process, r1u64(rdi_dbg_path_vaddr, rdi_dbg_path_vaddr+512), 1); } }break; } @@ -3857,15 +3940,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, r1u64(vaddr_range.min + raddbg_section_voff_range.min, - vaddr_range.min + raddbg_section_voff_range.max), raddbg_data.str); + d_process_read(process, 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, vaddr_range.min + raddbg_is_attached_section_voff_range.min, &new_value); + d_process_write_struct(process, vaddr_range.min + raddbg_is_attached_section_voff_range.min, &new_value); } } } @@ -3879,7 +3962,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, rng_1u64(vaddr_range.min, vaddr_range.min + sizeof(elf_sig[0]) * ELF_Identifier_Max)); + U8 *elf_sig = d_data_from_process_vaddr_range(scratch.arena, process, rng_1u64(vaddr_range.min, vaddr_range.min + sizeof(elf_sig[0]) * ELF_Identifier_Max), 0).str; if(elf_sig == 0) { goto elf_exit; } switch(elf_sig[ELF_Identifier_Class]) { @@ -3891,7 +3974,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, rng_1u64(vaddr_range.min, vaddr_range.min + sizeof(*ehdr))); + ELF_Hdr64 *ehdr = (ELF_Hdr64 *)d_data_from_process_vaddr_range(scratch.arena, process, r1u64(vaddr_range.min, vaddr_range.min + sizeof(*ehdr)), 0).str; if(ehdr == 0) { goto elf_exit; } e_entry = ehdr->e_entry; e_type = ehdr->e_type; @@ -3908,7 +3991,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, elf_phdr_vrange); + void *phdrs_raw = d_data_from_process_vaddr_range(scratch.arena, process, elf_phdr_vrange, 0).str; if(phdrs_raw == 0) { goto elf_exit; } if(elf_phdr_entsize == sizeof(ELF_Phdr32)) @@ -3925,7 +4008,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, eh_frame_hdr_vrange); + eh_frame_hdr_data = d_data_from_process_vaddr_range(arena, process, eh_frame_hdr_vrange, 0); is_unwind_eh = 1; break; } @@ -3934,8 +4017,7 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, Rng1U64 vaddr_rang } // parse .eh_frame_hdr - D_EntityCtx *entity_ctx = &d_ctrl_state->ctrl_thread_entity_store->ctx; - D_Entity *process_entity = d_entity_from_handle(entity_ctx, process); + D_Entity *process_entity = d_entity_from_handle(process); Arch arch = process_entity->arch; eh_ptr_ctx.pc_vaddr = eh_frame_hdr_vrange.min; eh_ptr_ctx.data_vaddr = eh_frame_hdr_vrange.min; @@ -4086,7 +4168,60 @@ 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, vaddr_range.min + raddbg_attached_marker_voff, &new_value); + d_process_write_struct(process, vaddr_range.min + raddbg_attached_marker_voff, &new_value); + } +} + +//- rjf: dump process closing work + +internal void +d_ctrl_thread__close_dump_process(D_MsgID msg_id, D_Handle process) +{ + // rjf: send debug event for process closing + { + Temp scratch = scratch_begin(0, 0); + D_EventList evts = {0}; + D_Event *evt = d_event_list_push(scratch.arena, &evts); + evt->kind = D_EventKind_EndProc; + evt->msg_id = msg_id; + evt->entity = process; + d_c2u_push_events(&evts); + scratch_end(scratch); + } + + // rjf: bump counters + ins_atomic_u64_inc_eval(&d_ctrl_state->mem_gen); + ins_atomic_u64_inc_eval(&d_ctrl_state->reg_gen); + ins_atomic_u64_inc_eval(&d_ctrl_state->run_gen); + + // rjf: eliminate dump node from cache + { + D_DumpCache *cache = &d_ctrl_state->dump_cache; + U64 hash = d_hash_from_handle(process); + U64 slot_idx = hash%cache->slots_count; + Stripe *stripe = stripe_from_slot_idx(&cache->stripes, slot_idx); + RWMutexScope(stripe->rw_mutex, 1) + { + D_DumpNode *node = 0; + for(D_DumpNode *n = cache->slots[slot_idx].first; n != 0; n = n->next) + { + if(d_handle_match(n->process, process)) + { + node = n; + break; + } + } + if(node != 0) + { + DLLRemove(cache->slots[slot_idx].first, cache->slots[slot_idx].last, node); + node->next = (D_DumpNode *)stripe->free; + stripe->free = node; + file_map_view_close(node->map, node->base, r1u64(0, node->props.size)); + file_map_close(node->map); + file_close(node->file); + arena_release(node->arena); + } + } } } @@ -4171,7 +4306,8 @@ 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_from_dmn(D_MachineID_Local, ev->process)); + D_Handle process_handle = d_handle_from_dmn(D_MachineID_Local, ev->process); + D_Entity *process = d_entity_from_handle(process_handle); D_Entity *module = &d_entity_nil; for(D_Entity *child = process->first; child != &d_entity_nil; child = child->next) { @@ -4205,7 +4341,7 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D U64 global_var_vaddr = global_var_voff + module->vaddr_range.min; Arch arch = process->arch; U64 addr_size = bit_size_from_arch(arch)/8; - dmn_process_read(ev->process, r1u64(global_var_vaddr, global_var_vaddr+addr_size), &asan_shadow_base_vaddr); + d_process_read(process_handle, 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); } } @@ -4261,16 +4397,16 @@ 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_from_dmn(D_MachineID_Local, spoof->process)); + D_Entity *spoof_process = d_entity_from_handle(spoof->process); Arch arch = spoof_process->arch; size_of_spoof = bit_size_from_arch(arch)/8; - dmn_process_read(spoof->process, r1u64(spoof->vaddr, spoof->vaddr+size_of_spoof), &spoof_old_ip_value); + d_process_read(spoof->process, r1u64(spoof->vaddr, spoof->vaddr+size_of_spoof), &spoof_old_ip_value); } // rjf: set spoof if(do_spoof) ProfScope("set spoof") { - dmn_process_write(spoof->process, r1u64(spoof->vaddr, spoof->vaddr+size_of_spoof), &spoof->new_ip_value); + d_process_write(spoof->process, r1u64(spoof->vaddr, spoof->vaddr+size_of_spoof), &spoof->new_ip_value); } // rjf: run for new events @@ -4321,7 +4457,7 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D // rjf: unset spoof if(do_spoof) ProfScope("unset spoof") { - dmn_process_write(spoof->process, r1u64(spoof->vaddr, spoof->vaddr+size_of_spoof), &spoof_old_ip_value); + d_process_write(spoof->process, r1u64(spoof->vaddr, spoof->vaddr+size_of_spoof), &spoof_old_ip_value); } } } @@ -4331,17 +4467,17 @@ 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_from_dmn(D_MachineID_Local, spoof->thread)); + D_Entity *thread = d_entity_from_handle(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; void *regs_block = push_array(scratch.arena, U8, arch_reg_block_size); - dmn_thread_read_reg_block(spoof->thread, regs_block); + d_thread_read_reg_block(spoof->thread, regs_block); U64 spoof_thread_rip = arch_ip_from_reg_block(arch_info, regs_block); 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_from_dmn(D_MachineID_Local, spoof->thread), regs_block); + d_thread_write_reg_block(spoof->thread, regs_block); } } @@ -4430,7 +4566,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); 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 *module_ent = d_entity_from_handle(module_handle); D_Entity *process_ent = d_process_from_entity(module_ent); String8 module_path = event->string; d_ctrl_thread__module_close(process_ent->handle, module_handle, module_ent->vaddr_range); @@ -4559,17 +4695,15 @@ d_ctrl_eval_space_read(E_Space space, void *out, E_SpaceRangeInfo *out_range_inf default:{}break; case D_EntityKind_Process: { - DMN_Handle handle_dmn = d_dmn_from_handle(entity->handle); - U64 read_size = dmn_process_read(handle_dmn, range, out); + U64 read_size = d_process_read(entity->handle, range, out); result = (read_size == dim_1u64(range)); }break; case D_EntityKind_Thread: { Temp scratch = scratch_begin(0, 0); - D_EntityCtx *entity_ctx = &d_ctrl_state->ctrl_thread_entity_store->ctx; ARCH_Info *arch_info = arch_info_from_arch(entity->arch); U64 regs_size = arch_info->reg_block_size; - void *regs = d_reg_block_from_thread(scratch.arena, entity_ctx, entity->handle); + void *regs = d_reg_block_from_thread(scratch.arena, entity->handle); Rng1U64 legal_range = r1u64(0, regs_size); Rng1U64 read_range = intersect_1u64(legal_range, range); U64 read_size = dim_1u64(read_range); @@ -4972,22 +5106,35 @@ 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) { + Temp scratch = scratch_begin(0, 0); + + //- rjf: unpack path 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 to parse file data as a dump file, extract abstracted (over format) dump info + B32 stored = 0; + D_EventList evts = {0}; + Arena *arena = 0; + D_DumpMemoryRange *memory_ranges = 0; + U64 memory_ranges_count = 0; + D_DumpThread *dump_threads = 0; + U64 dump_threads_count = 0; + D_Handle process = {0}; { - Temp scratch = scratch_begin(0, 0); - D_EventList evts = {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) { + stored = 1; + arena = arena_alloc(); + // rjf: extract directories U64 directories_count = 0; MDMP_Directory *directories = 0; @@ -5007,6 +5154,8 @@ d_ctrl_thread__open_crash_dump(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) U64 threads_count = 0; MDMP_Module *modules = 0; U64 modules_count = 0; + MDMP_MemoryDescriptor32 *memories = 0; + U64 memories_count = 0; { for EachIndex(idx, directories_count) { @@ -5037,6 +5186,15 @@ d_ctrl_thread__open_crash_dump(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) modules = (MDMP_Module *)(data.str + off); modules_count = Min(modules_count_32, modules_count_max); }break; + case MDMP_StreamKind_MemoryList: + { + U32 memories_count_32 = 0; + U64 off = dir->location.foff; + off += str8_deserial_read_struct(data, off, &memories_count_32); + U64 memories_count_max = (data.size - off) / sizeof(MDMP_MemoryDescriptor32); + memories = (MDMP_MemoryDescriptor32 *)(data.str + off); + memories_count = Min(memories_count_32, memories_count_max); + }break; } } } @@ -5052,7 +5210,7 @@ d_ctrl_thread__open_crash_dump(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) // rjf: process creation U64 handle_id_gen = 1; - D_Handle process = d_dump_handle_make(D_MachineID_Local, handle_id_gen); + process = d_dump_handle_make(D_MachineID_Local, handle_id_gen); handle_id_gen += 1; { D_Event *evt = d_event_list_push(scratch.arena, &evts); @@ -5060,16 +5218,22 @@ d_ctrl_thread__open_crash_dump(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) evt->msg_id = msg->msg_id; evt->entity = process; evt->arch = arch; + evt->target_os = OperatingSystem_Windows; } // rjf: thread creation + dump_threads_count = threads_count; + dump_threads = push_array(arena, D_DumpThread, dump_threads_count); for EachIndex(idx, threads_count) { MDMP_Thread *thread = &threads[idx]; + D_Handle thread_handle = d_dump_handle_make(D_MachineID_Local, handle_id_gen); + dump_threads[idx].thread_handle = thread_handle; + dump_threads[idx].context_foff = thread->thread_context.foff; D_Event *evt = d_event_list_push(scratch.arena, &evts); evt->kind = D_EventKind_NewThread; evt->msg_id = msg->msg_id; - evt->entity = d_dump_handle_make(D_MachineID_Local, handle_id_gen); + evt->entity = thread_handle; evt->parent = process; evt->arch = arch; evt->entity_id = thread->id; @@ -5105,16 +5269,70 @@ d_ctrl_thread__open_crash_dump(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) handle_id_gen += 1; } - // rjf: push events - d_c2u_push_events(&evts); + // rjf: allocate parse artifact arena + arena = arena_alloc(); - scratch_end(scratch); + // rjf: gather memory ranges + memory_ranges_count = memories_count; + memory_ranges = push_array(arena, D_DumpMemoryRange, memory_ranges_count); + for EachIndex(idx, memories_count) + { + memory_ranges[idx].base_vaddr = memories[idx].start_of_memory_range; + memory_ranges[idx].foff_range = r1u64(memories[idx].memory_location.foff, memories[idx].memory_location.foff+memories[idx].memory_location.data_size); + } } } } - file_map_view_close(map, base, r1u64(0, props.size)); - file_map_close(map); - file_close(file); + + //- rjf: push all events from the parse + ins_atomic_u64_inc_eval(&d_ctrl_state->mem_gen); + ins_atomic_u64_inc_eval(&d_ctrl_state->reg_gen); + ins_atomic_u64_inc_eval(&d_ctrl_state->run_gen); + d_c2u_push_events(&evts); + + //- rjf: store the dump parse artifacts in the dump cache, otherwise release + if(stored) + { + U64 hash = d_hash_from_handle(process); + D_DumpCache *cache = &d_ctrl_state->dump_cache; + U64 slot_idx = hash%cache->slots_count; + Stripe *stripe = stripe_from_slot_idx(&cache->stripes, slot_idx); + RWMutexScope(stripe->rw_mutex, 1) + { + D_DumpNode *node = stripe->free; + if(node != 0) + { + stripe->free = node->next; + } + else + { + node = push_array(stripe->arena, D_DumpNode, 1); + } + DLLPushBack(cache->slots[slot_idx].first, cache->slots[slot_idx].last, node); + node->process = process; + node->file = file; + node->props = props; + node->map = map; + node->base = base; + node->arena = arena; + node->memory_ranges = memory_ranges; + node->memory_ranges_count = memory_ranges_count; + node->threads = dump_threads; + node->threads_count = dump_threads_count; + } + } + else + { + if(arena != 0) + { + arena_release(arena); + } + file_map_view_close(map, base, r1u64(0, props.size)); + file_map_close(map); + file_close(file); + } + + scratch_end(scratch); } internal void @@ -5122,36 +5340,51 @@ d_ctrl_thread__kill(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); - DMN_Handle process = d_dmn_from_handle(msg->entity); - U32 exit_code = msg->exit_code; - - //- rjf: send kill - B32 kill_worked = dmn_ctrl_kill(ctrl_ctx, process, exit_code); - - //- rjf: wait for process to be dead + B32 kill_worked = 0; D_EventCause cause = D_EventCause_Finished; - if(kill_worked) + switch((D_ControllerKindEnum)msg->entity.controller_kind) { - DMN_RunCtrls run_ctrls = {0}; - run_ctrls.run_entities_are_unfrozen = 1; - run_ctrls.run_entities_are_processes = 1; - run_ctrls.run_entities = &process; - run_ctrls.run_entity_count = 1; - for(B32 done = 0; done == 0;) + //- rjf: demon kills + case D_ControllerKind_Demon: { - DMN_Event *event = d_ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0); - switch(event->kind) + DMN_Handle process = d_dmn_from_handle(msg->entity); + U32 exit_code = msg->exit_code; + + //- rjf: send kill + kill_worked = dmn_ctrl_kill(ctrl_ctx, process, exit_code); + + //- rjf: wait for process to be dead + if(kill_worked) { - default:{}break; - case DMN_EventKind_ExitProcess: - if(dmn_handle_match(event->process, process)) + DMN_RunCtrls run_ctrls = {0}; + run_ctrls.run_entities_are_unfrozen = 1; + run_ctrls.run_entities_are_processes = 1; + run_ctrls.run_entities = &process; + run_ctrls.run_entity_count = 1; + for(B32 done = 0; done == 0;) { - done = 1; - }break; - case DMN_EventKind_Error:{done = 1; cause = D_EventCause_Error;}break; - case DMN_EventKind_Halt: {done = 1; cause = D_EventCause_InterruptedByHalt;}break; + DMN_Event *event = d_ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0); + switch(event->kind) + { + default:{}break; + case DMN_EventKind_ExitProcess: + if(dmn_handle_match(event->process, process)) + { + done = 1; + }break; + case DMN_EventKind_Error:{done = 1; cause = D_EventCause_Error;}break; + case DMN_EventKind_Halt: {done = 1; cause = D_EventCause_InterruptedByHalt;}break; + } + } } - } + }break; + + //- rjf: dump kills + case D_ControllerKind_Dump: + { + kill_worked = 1; + d_ctrl_thread__close_dump_process(msg->msg_id, msg->entity); + }break; } //- rjf: record stop @@ -5178,10 +5411,9 @@ d_ctrl_thread__kill_all(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); U32 exit_code = msg->exit_code; - D_EntityCtx *entity_ctx = &d_ctrl_state->ctrl_thread_entity_store->ctx; //- rjf: gather all currently existing processes - D_EntityArray initial_processes = d_entity_array_from_kind(entity_ctx, D_EntityKind_Process); + D_EntityArray initial_processes = d_entity_array_from_kind(D_EntityKind_Process); typedef struct Task Task; struct Task { @@ -5210,7 +5442,12 @@ 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, d_dmn_from_handle(t->process->handle), exit_code); + B32 kill_worked = 0; + switch((D_ControllerKindEnum)t->process->handle.controller_kind) + { + case D_ControllerKind_Demon:{kill_worked = dmn_ctrl_kill(ctrl_ctx, d_dmn_from_handle(t->process->handle), exit_code);}break; + case D_ControllerKind_Dump: {kill_worked = 1; d_ctrl_thread__close_dump_process(msg->msg_id, t->process->handle);}break; + } if(kill_worked) { DLLRemove(first_task, last_task, t); @@ -5226,7 +5463,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_from_dmn(D_MachineID_Local, event->process)); + D_Entity *new_process = d_entity_from_handle(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); @@ -5236,7 +5473,7 @@ d_ctrl_thread__kill_all(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) } // rjf: end if all processes are gone - D_EntityArray processes = d_entity_array_from_kind(entity_ctx, D_EntityKind_Process); + D_EntityArray processes = d_entity_array_from_kind(D_EntityKind_Process); if(processes.count == 0) { done = 1; @@ -5320,7 +5557,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) 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); + D_Entity *target_process_entity = d_entity_from_handle(target_process); U64 spoof_ip_vaddr = 911; log_infof("d_ctrl_thread__run:\n{\n"); @@ -5329,7 +5566,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) // DMN_TrapChunkList user_traps = {0}; { - D_Entity *thread = d_entity_from_handle(entity_ctx, target_thread); + D_Entity *thread = d_entity_from_handle(target_thread); D_EvalScope *eval_scope = d_ctrl_thread__eval_scope_begin(scratch.arena, &msg->user_bps, thread); for(D_Entity *machine = entity_ctx->root->first; machine != &d_entity_nil; @@ -5649,7 +5886,7 @@ 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_from_dmn(D_MachineID_Local, event->thread)); + D_Entity *thread = d_entity_from_handle(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}; @@ -5674,7 +5911,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_from_dmn(D_MachineID_Local, event->process)); + D_Entity *process = d_entity_from_handle(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 && @@ -5706,7 +5943,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_from_dmn(D_MachineID_Local, event->process)); + D_Entity *process = d_entity_from_handle(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); @@ -5929,8 +6166,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_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)); + D_Entity *thread = d_entity_from_handle(d_handle_from_dmn(D_MachineID_Local, event->thread)); + D_Entity *process = d_entity_from_handle(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); @@ -6237,11 +6474,10 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) begin_spoof_mode = 1; U64 spoof_sp = dmn_rsp_from_thread(target_thread_dmn); spoof_mode = 1; - spoof.process = target_process_dmn; - spoof.thread = target_thread_dmn; + spoof.process = target_process; + 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); } } @@ -6474,6 +6710,137 @@ d_ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) //////////////////////////////// //~ rjf: Process Memory Artifact Cache Hooks / Lookups +//- rjf: synchronous process memory reading helpers + +internal U64 +d_process_read(D_Handle process, Rng1U64 range, void *dst) +{ + U64 result = 0; + switch((D_ControllerKindEnum)process.controller_kind) + { + //- rjf: demon process reads + case D_ControllerKind_Demon: + { + result = dmn_process_read(d_dmn_from_handle(process), range, dst); + }break; + + //- rjf: dump process reads + case D_ControllerKind_Dump: + { + D_DumpCache *cache = &d_ctrl_state->dump_cache; + U64 hash = d_hash_from_handle(process); + U64 slot_idx = hash%cache->slots_count; + Stripe *stripe = stripe_from_slot_idx(&cache->stripes, slot_idx); + RWMutexScope(stripe->rw_mutex, 0) + { + // rjf: handle -> node + D_DumpNode *node = 0; + for(D_DumpNode *n = cache->slots[slot_idx].first; n != 0; n = n->next) + { + if(d_handle_match(n->process, process)) + { + node = n; + break; + } + } + + // rjf: find all overlapping memory ranges, & fill respective portion of output + if(node != 0) + { + B32 range_found = 0; + for EachIndex(idx, node->memory_ranges_count) + { + D_DumpMemoryRange *r = &node->memory_ranges[idx]; + Rng1U64 foff_range = r->foff_range; + Rng1U64 vaddr_range = r1u64(r->base_vaddr, r->base_vaddr + dim_1u64(foff_range)); + Rng1U64 legal_vaddr_range = intersect_1u64(vaddr_range, range); + if(legal_vaddr_range.min < legal_vaddr_range.max) + { + range_found = 1; + Rng1U64 legal_foff_range = r1u64(legal_vaddr_range.min - r->base_vaddr + foff_range.min, legal_vaddr_range.max - r->base_vaddr + foff_range.min); + Rng1U64 dst_off_range = r1u64(legal_vaddr_range.min - range.min, legal_vaddr_range.max - range.min); + MemoryCopy((U8 *)dst + dst_off_range.min, (U8 *)node->base + legal_foff_range.min, dim_1u64(dst_off_range)); + } + } + if(range_found) + { + result = dim_1u64(range); + } + } + } + }break; + } + return result; +} + +internal B32 +d_process_write(D_Handle process, Rng1U64 range, void *src) +{ + B32 result = 0; + switch((D_ControllerKindEnum)process.controller_kind) + { + case D_ControllerKind_Demon: + { + result = dmn_process_write(d_dmn_from_handle(process), range, src); + + //- rjf: success -> bump generation + if(result) + { + ins_atomic_u64_inc_eval(&d_ctrl_state->mem_gen); + } + + //- rjf: success -> wait for cache updates, for small regions - prefer relatively seamless + // writes within calling frame's "view" of the memory, at the expense of a small amount of + // time. + if(result) + { + U64 endt_us = now_time_us()+10000; + U64 page_size = get_system_info()->page_size; // TODO(rjf): @page_size_from_process + Rng1U64 page_range = r1u64(range.min/page_size, (range.max+page_size-1)/page_size); + for EachInRange(page_idx, page_range) + { + Temp scratch = scratch_begin(0, 0); + D_ProcessMemorySlice slice = d_process_memory_slice_from_vaddr_range(scratch.arena, process, r1u64(page_idx*page_size, (page_idx+1)*page_size), 1, endt_us); + scratch_end(scratch); + if(!slice.stale || now_time_us() >= endt_us) + { + break; + } + } + } + }break; + + case D_ControllerKind_Dump: + { + // TODO(rjf) + }break; + } + + return result; +} + +internal String8 +d_data_from_process_vaddr_range(Arena *arena, D_Handle process, Rng1U64 vaddr_range, B32 zero_terminated) +{ + U64 desired_read_size = dim_1u64(vaddr_range); + void *buffer = push_array(arena, U8, desired_read_size); + U64 read_size = d_process_read(process, vaddr_range, buffer); + U64 num_bytes_overallocated = (desired_read_size - read_size); + arena_pop(arena, num_bytes_overallocated); + String8 result = str8((U8 *)buffer, read_size); + if(zero_terminated) + { + U64 pre_zero_termination_size = result.size; + result = str8_cstring_capped((U8 *)result.str, (U8 *)result.str + result.size); + U64 post_zero_termination_size = result.size; + U64 num_bytes_overallocated_after_zero_termination = post_zero_termination_size - pre_zero_termination_size; + arena_pop(arena, num_bytes_overallocated_after_zero_termination); + } + return result; +} + +//- rjf: process memory artifact cache + internal AC_Artifact d_memory_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out) { @@ -6489,7 +6856,6 @@ 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; @@ -6525,7 +6891,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, vaddr_range_clamped_retry, range_base); + bytes_read = d_process_read(process, 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; @@ -6827,44 +7193,6 @@ d_process_memory_read(D_Handle process, Rng1U64 range, B32 *is_stale_out, void * return good; } -//- rjf: process memory writing - -internal B32 -d_process_write(D_Handle process, Rng1U64 range, void *src) -{ - ProfBeginFunction(); - B32 result = dmn_process_write(d_dmn_from_handle(process), range, src); - - //- rjf: success -> bump generation - if(result) - { - ins_atomic_u64_inc_eval(&d_ctrl_state->mem_gen); - } - - //- rjf: success -> wait for cache updates, for small regions - prefer relatively seamless - // writes within calling frame's "view" of the memory, at the expense of a small amount of - // time. - if(result) - { - U64 endt_us = now_time_us()+10000; - U64 page_size = get_system_info()->page_size; // TODO(rjf): @page_size_from_process - Rng1U64 page_range = r1u64(range.min/page_size, (range.max+page_size-1)/page_size); - for EachInRange(page_idx, page_range) - { - Temp scratch = scratch_begin(0, 0); - D_ProcessMemorySlice slice = d_process_memory_slice_from_vaddr_range(scratch.arena, process, r1u64(page_idx*page_size, (page_idx+1)*page_size), 1, endt_us); - scratch_end(scratch); - if(!slice.stale || now_time_us() >= endt_us) - { - break; - } - } - } - - ProfEnd(); - return result; -} - //////////////////////////////// //~ rjf: Call Stack Artifact Cache Hooks / Lookups @@ -6884,6 +7212,7 @@ d_call_stack_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U6 MutexScopeR(d_ctrl_state->ctrl_thread_entity_ctx_rw_mutex) { D_EntityCtx *src_ctx = &d_ctrl_state->ctrl_thread_entity_store->ctx; + d_select_entity_ctx(src_ctx); D_EntityCtx *dst_ctx = entity_ctx; { dst_ctx->root = &d_entity_nil; @@ -6892,7 +7221,7 @@ d_call_stack_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U6 MemoryCopyArray(dst_ctx->entity_kind_counts, src_ctx->entity_kind_counts); MemoryCopyArray(dst_ctx->entity_kind_alloc_gens, src_ctx->entity_kind_alloc_gens); } - D_Entity *src_thread = d_entity_from_handle(src_ctx, thread_handle); + D_Entity *src_thread = d_entity_from_handle(thread_handle); D_Entity *src_process = d_process_from_entity(src_thread); { D_EntityRec rec = {0}; @@ -6976,8 +7305,11 @@ d_call_stack_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U6 } } + //- rjf: select entity context + d_select_entity_ctx(entity_ctx); + //- rjf: compute call stack - D_Entity *thread = d_entity_from_handle(entity_ctx, thread_handle); + D_Entity *thread = d_entity_from_handle(thread_handle); B32 good = 1; B32 retry = 0; Arena *arena = 0; @@ -6996,7 +7328,7 @@ d_call_stack_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U6 { pre_reg_gen = d_reg_gen(); pre_mem_gen = d_mem_gen(); - unwind = d_unwind_from_thread(arena, entity_ctx, thread_handle, now_time_us()+5000); + unwind = d_unwind_from_thread(arena, thread_handle, now_time_us()+5000); if(!(unwind.flags & D_UnwindFlag_Stale)) { good = 1; @@ -7084,8 +7416,7 @@ d_call_stack_tree_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_ou Arch *threads_arches = 0; MutexScopeR(d_ctrl_state->ctrl_thread_entity_ctx_rw_mutex) { - D_EntityCtx *ctx = &d_ctrl_state->ctrl_thread_entity_store->ctx; - D_EntityArray thread_entities = d_entity_array_from_kind(ctx, D_EntityKind_Thread); + D_EntityArray thread_entities = d_entity_array_from_kind(D_EntityKind_Thread); threads_count = thread_entities.count; threads = push_array(scratch.arena, D_Handle, threads_count); threads_processes = push_array(scratch.arena, D_Handle, threads_count); diff --git a/src/dbg_engine/dbg_engine_ctrl.h b/src/dbg_engine/dbg_engine_ctrl.h index 028384fe..054775c4 100644 --- a/src/dbg_engine/dbg_engine_ctrl.h +++ b/src/dbg_engine/dbg_engine_ctrl.h @@ -214,6 +214,55 @@ struct D_ModuleImageInfoCache D_ModuleImageInfoCacheStripe *stripes; }; +//////////////////////////////// +//~ rjf: Opened Dump Cache Types + +typedef struct D_DumpMemoryRange D_DumpMemoryRange; +struct D_DumpMemoryRange +{ + U64 base_vaddr; + Rng1U64 foff_range; +}; + +typedef struct D_DumpThread D_DumpThread; +struct D_DumpThread +{ + D_Handle thread_handle; + U64 context_foff; +}; + +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; + Arena *arena; + D_DumpMemoryRange *memory_ranges; + U64 memory_ranges_count; + D_DumpThread *threads; + U64 threads_count; +}; + +typedef struct D_DumpSlot D_DumpSlot; +struct D_DumpSlot +{ + D_DumpNode *first; + D_DumpNode *last; +}; + +typedef struct D_DumpCache D_DumpCache; +struct D_DumpCache +{ + U64 slots_count; + D_DumpSlot *slots; + StripeArray stripes; +}; + //////////////////////////////// //~ rjf: Touched Debug Info Directory Cache @@ -275,6 +324,7 @@ struct D_CtrlState // rjf: caches D_ThreadRegCache thread_reg_cache; D_ModuleImageInfoCache module_image_info_cache; + D_DumpCache dump_cache; // rjf: generations U64 run_gen; @@ -327,6 +377,7 @@ struct D_CtrlState //~ rjf: Globals global D_CtrlState *d_ctrl_state = 0; +thread_static D_EntityCtx *d_entity_ctx = 0; read_only global D_Entity d_entity_nil = { &d_entity_nil, @@ -413,9 +464,12 @@ internal D_Event d_event_from_serialized_string(Arena *arena, String8 string); //////////////////////////////// //~ rjf: Entity Type Functions +//- rjf: entity context selection +internal D_EntityCtx *d_select_entity_ctx(D_EntityCtx *ctx); + //- rjf: entity list data structures internal void d_entity_list_push(Arena *arena, D_EntityList *list, D_Entity *entity); -internal D_EntityList d_entity_list_from_handle_list(Arena *arena, D_EntityCtx *ctx, D_HandleList *list); +internal D_EntityList d_entity_list_from_handle_list(Arena *arena, D_HandleList *list); #define d_entity_list_first(list) ((list)->first ? (list)->first->v : &d_entity_nil) //- rjf: entity array data structure @@ -423,13 +477,13 @@ internal D_EntityArray d_entity_array_from_list(Arena *arena, D_EntityList *list #define d_entity_array_first(array) ((array)->count != 0 ? (array)->v[0] : &d_entity_nil) //- rjf: entity context (entity group read-only) functions -internal D_Entity *d_entity_from_handle(D_EntityCtx *ctx, D_Handle handle); +internal D_Entity *d_entity_from_handle(D_Handle handle); internal D_Entity *d_entity_child_from_kind(D_Entity *parent, D_EntityKind kind); internal D_Entity *d_entity_ancestor_from_kind(D_Entity *entity, D_EntityKind kind); internal D_Entity *d_process_from_entity(D_Entity *entity); internal D_Entity *d_module_from_process_vaddr(D_Entity *process, U64 vaddr); internal DI_Key d_dbgi_key_from_module(D_Entity *module); -internal D_Entity *d_module_from_thread_candidates(D_EntityCtx *ctx, D_Entity *thread, D_EntityList *candidates); +internal D_Entity *d_module_from_thread_candidates(D_Entity *thread, D_EntityList *candidates); internal U64 d_vaddr_from_voff(D_Entity *module, U64 voff); internal U64 d_voff_from_vaddr(D_Entity *module, U64 vaddr); internal Rng1U64 d_vaddr_range_from_voff_range(D_Entity *module, Rng1U64 voff_range); @@ -458,9 +512,9 @@ internal void d_entity_equip_string(D_EntityCtxRWStore *store, D_Entity *entity, //- rjf: accelerated entity context lookups internal D_EntityCtxLookupAccel *d_thread_entity_ctx_lookup_accel(void); -internal D_EntityArray d_entity_array_from_kind(D_EntityCtx *ctx, D_EntityKind kind); -internal D_EntityList d_modules_from_dbgi_key(Arena *arena, D_EntityCtx *ctx, DI_Key dbgi_key); -internal D_Entity *d_thread_from_id(D_EntityCtx *ctx, U64 id); +internal D_EntityArray d_entity_array_from_kind(D_EntityKind kind); +internal D_EntityList d_modules_from_dbgi_key(Arena *arena, DI_Key dbgi_key); +internal D_Entity *d_thread_from_id(U64 id); //- rjf: applying events to entity caches internal void d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list); @@ -473,14 +527,15 @@ internal void d_set_wakeup_hook(D_WakeupFunctionType *wakeup_hook); //////////////////////////////// //~ rjf: Thread Register Functions -//- rjf: thread register cache reading -internal void *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); -internal U64 d_rip_from_thread(D_EntityCtx *ctx, D_Handle handle); -internal U64 d_rsp_from_thread(D_EntityCtx *ctx, D_Handle handle); +//- rjf: thread handle read/write +internal B32 d_thread_read_reg_block(D_Handle handle, void *reg_block); +internal B32 d_thread_write_reg_block(D_Handle thread, void *reg_block); -//- rjf: thread register writing -internal B32 d_thread_write_reg_block(D_Handle thread, void *block); +//- rjf: thread register cache reading +internal void *d_reg_block_from_thread(Arena *arena, D_Handle handle); +internal U64 d_tls_root_vaddr_from_thread(D_Handle handle); +internal U64 d_rip_from_thread(D_Handle handle); +internal U64 d_rsp_from_thread(D_Handle handle); //////////////////////////////// //~ rjf: Module Image Info Functions @@ -504,7 +559,7 @@ internal U64 *d_unwind_reg_from_pe_gpr_reg__pe_x64(X64_RegBlock *regs, PE_Unwind internal D_UnwindStepResult d_unwind_step__pe_x64(D_Handle process_handle, D_Handle module_handle, U64 module_base_vaddr, X64_RegBlock *regs, U64 endt_us); //- rjf: abstracted full unwind -internal D_Unwind d_unwind_from_thread(Arena *arena, D_EntityCtx *ctx, D_Handle thread, U64 endt_us); +internal D_Unwind d_unwind_from_thread(Arena *arena, D_Handle thread, U64 endt_us); //////////////////////////////// //~ rjf: Call Stack Building Functions @@ -551,6 +606,9 @@ internal void d_ctrl_thread__append_program_defined_bp_traps(Arena *arena, D_Ent 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); internal void d_ctrl_thread__module_close(D_Handle process, D_Handle module, Rng1U64 vaddr_range); +//- rjf: dump process closing work +internal void d_ctrl_thread__close_dump_process(D_MsgID msg_id, D_Handle process); + //- rjf: attached process running/event gathering internal DMN_Event *d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, DMN_RunCtrls *run_ctrls, D_Spoof *spoof); @@ -578,6 +636,14 @@ internal void d_ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg); //////////////////////////////// //~ rjf: Process Memory Artifact Cache Hooks / Lookups +//- rjf: synchronous process memory reading helpers +internal U64 d_process_read(D_Handle process, Rng1U64 range, void *dst); +internal B32 d_process_write(D_Handle process, Rng1U64 range, void *dst); +internal String8 d_data_from_process_vaddr_range(Arena *arena, D_Handle process, Rng1U64 vaddr_range, B32 zero_terminated); +#define d_process_read_struct(process, vaddr, ptr) d_process_read((process), r1u64((vaddr), (vaddr) + sizeof(*(ptr))), (ptr)) +#define d_process_write_struct(process, vaddr, ptr) d_process_write((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), (ptr)) + +//- rjf: process memory artifact cache internal AC_Artifact d_memory_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out); internal void d_memory_artifact_destroy(AC_Artifact artifact); internal C_Key d_key_from_process_vaddr_range(D_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, B32 wait_for_fresh, U64 endt_us, B32 *out_is_stale); @@ -587,9 +653,6 @@ internal D_ProcessMemorySlice d_process_memory_slice_from_vaddr_range(Arena *are internal B32 d_process_memory_read(D_Handle process, Rng1U64 range, B32 *is_stale_out, void *out, U64 endt_us); #define d_process_memory_read_struct(process, vaddr, is_stale_out, ptr, endt_us) d_process_memory_read((process), r1u64((vaddr), (vaddr)+(sizeof(*(ptr)))), (is_stale_out), (ptr), (endt_us)) -//- rjf: process memory writing -internal B32 d_process_write(D_Handle process, Rng1U64 range, void *src); - //////////////////////////////// //~ rjf: Call Stack Artifact Cache Hooks / Lookups diff --git a/src/dbg_engine/dbg_engine_user.c b/src/dbg_engine/dbg_engine_user.c index dbcde890..1744db1c 100644 --- a/src/dbg_engine/dbg_engine_user.c +++ b/src/dbg_engine/dbg_engine_user.c @@ -297,7 +297,7 @@ d_trap_net_from_thread__step_over_inst(Arena *arena, D_Entity *thread) // rjf: thread => unpacked info D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process); Arch arch = thread->arch; - U64 ip_vaddr = d_rip_from_thread(&d_user_state->ctrl_entity_store->ctx, thread->handle); + U64 ip_vaddr = d_rip_from_thread(thread->handle); // rjf: ip => machine code String8 machine_code = {0}; @@ -336,7 +336,7 @@ d_trap_net_from_thread__step_over_line(Arena *arena, D_Entity *thread) // rjf: thread => info Arch arch = thread->arch; - U64 ip_vaddr = d_rip_from_thread(&d_user_state->ctrl_entity_store->ctx, thread->handle); + U64 ip_vaddr = d_rip_from_thread(thread->handle); D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process); D_Entity *module = d_module_from_process_vaddr(process, ip_vaddr); DI_Key dbgi_key = d_dbgi_key_from_module(module); @@ -549,7 +549,7 @@ d_trap_net_from_thread__step_into_line(Arena *arena, D_Entity *thread) // rjf: thread => info Arch arch = thread->arch; - U64 ip_vaddr = d_rip_from_thread(&d_user_state->ctrl_entity_store->ctx, thread->handle); + U64 ip_vaddr = d_rip_from_thread(thread->handle); D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process); D_Entity *module = d_module_from_process_vaddr(process, ip_vaddr); DI_Key dbgi_key = d_dbgi_key_from_module(module); @@ -750,11 +750,10 @@ d_trap_net_from_thread__step_out_scope(Arena *arena, D_Entity *thread) U64 read_endt_us = now_time_us() + 1000000; Temp scratch = scratch_begin(&arena, 1); Access *access = access_open(); - D_EntityCtx *entity_ctx = &d_user_state->ctrl_entity_store->ctx; // rjf: unpack thread Arch arch = thread->arch; - U64 ip_vaddr = d_rip_from_thread(entity_ctx, thread->handle); + U64 ip_vaddr = d_rip_from_thread(thread->handle); D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process); D_Entity *module = d_module_from_process_vaddr(process, ip_vaddr); DI_Key dbgi_key = d_dbgi_key_from_module(module); @@ -1303,7 +1302,7 @@ internal DI_KeyList d_push_active_dbgi_key_list(Arena *arena) { DI_KeyList dbgis = {0}; - D_EntityArray modules = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Module); + D_EntityArray modules = d_entity_array_from_kind(D_EntityKind_Module); for EachIndex(idx, modules.count) { D_Entity *module = modules.v[idx]; @@ -1328,7 +1327,7 @@ d_query_cached_rip_from_thread_unwind(D_Entity *thread, U64 unwind_count) U64 result = 0; if(unwind_count == 0) { - result = d_rip_from_thread(&d_user_state->ctrl_entity_store->ctx, thread->handle); + result = d_rip_from_thread(thread->handle); } else { @@ -1614,7 +1613,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P case D_EventKind_NewProc: { // rjf: the first process? -> clear session output - D_EntityArray existing_processes = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Process); + D_EntityArray existing_processes = d_entity_array_from_kind(D_EntityKind_Process); if(existing_processes.count == 1) { MTX_Op op = {r1u64(0, 0xffffffffffffffffull), str8_lit("[new session]\n")}; @@ -1678,7 +1677,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P // rjf: build data strings of all param data String8List strings = {0}; { - D_EntityArray threads = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Thread); + D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread); for EachIndex(idx, threads.count) { D_Entity *thread = threads.v[idx]; @@ -1833,7 +1832,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P }break; case D_CmdKind_Kill: { - D_Entity *process = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, params->process); + D_Entity *process = d_entity_from_handle(params->process); if(process == &d_entity_nil) { log_user_error(str8_lit("Cannot kill; no process was specified.")); @@ -1856,7 +1855,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P }break; case D_CmdKind_Detach: { - D_Entity *process = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, params->process); + D_Entity *process = d_entity_from_handle(params->process); if(process == &d_entity_nil) { log_user_error(str8_lit("Cannot detach; no process specified.")); @@ -1872,7 +1871,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P case D_CmdKind_Continue: { B32 good_to_run = 0; - D_EntityArray threads = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Thread); + D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread); if(threads.count > 0) { for EachIndex(idx, threads.count) @@ -1888,7 +1887,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P { need_run = 1; run_kind = D_RunKind_Run; - run_thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, params->thread); + run_thread = d_entity_from_handle(params->thread); } else { @@ -1902,7 +1901,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P case D_CmdKind_StepOverLine: case D_CmdKind_StepOut: { - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, params->thread); + D_Entity *thread = d_entity_from_handle(params->thread); if(thread == &d_entity_nil) { log_user_error(str8_lit("Must have a selected thread to step.")); @@ -1969,16 +1968,16 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P { need_run = 1; run_kind = d_user_state->ctrl_last_run_kind; - run_thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, d_user_state->ctrl_last_run_thread_handle); + run_thread = d_entity_from_handle(d_user_state->ctrl_last_run_thread_handle); run_flags = d_user_state->ctrl_last_run_flags; run_traps = d_user_state->ctrl_last_run_traps; }break; case D_CmdKind_SetThreadIP: { - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, params->thread); + D_Entity *thread = d_entity_from_handle(params->thread); ARCH_Info *arch_info = arch_info_from_arch(thread->arch); U64 vaddr = params->vaddr; - void *block = d_reg_block_from_thread(scratch.arena, &d_user_state->ctrl_entity_store->ctx, thread->handle); + void *block = d_reg_block_from_thread(scratch.arena, thread->handle); arch_reg_block_write_ip(arch_info, block, vaddr); B32 result = d_thread_write_reg_block(thread->handle, block); (void)result; @@ -2002,7 +2001,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P }break; case D_CmdKind_Run: { - D_EntityArray processes = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Process); + D_EntityArray processes = d_entity_array_from_kind(D_EntityKind_Process); if(processes.count != 0) { d_cmd(D_CmdKind_Continue, .machine = params->machine, .process = params->process, .thread = params->thread); @@ -2014,7 +2013,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P }break; case D_CmdKind_Restart: { - D_EntityArray processes = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Process); + D_EntityArray processes = d_entity_array_from_kind(D_EntityKind_Process); if(processes.count != 0) { d_cmd(D_CmdKind_KillAll); @@ -2024,7 +2023,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P case D_CmdKind_StepInto: case D_CmdKind_StepOver: { - D_EntityArray processes = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Process); + D_EntityArray processes = d_entity_array_from_kind(D_EntityKind_Process); if(processes.count != 0) { D_CmdKind step_cmd_kind = (cmd->kind == D_CmdKind_StepInto @@ -2074,7 +2073,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P case D_CmdKind_ThawEntity: { B32 should_freeze = (cmd->kind == D_CmdKind_FreezeEntity); - D_Entity *root = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, params->entity); + D_Entity *root = d_entity_from_handle(params->entity); for(D_Entity *e = root; e != &d_entity_nil; e = d_entity_rec_depth_first_pre(e, root).next) { if(e->kind == D_EntityKind_Thread) @@ -2089,7 +2088,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P { need_run = 1; run_kind = d_user_state->ctrl_last_run_kind; - run_thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, d_user_state->ctrl_last_run_thread_handle); + run_thread = d_entity_from_handle(d_user_state->ctrl_last_run_thread_handle); run_flags = d_user_state->ctrl_last_run_flags; run_traps = d_user_state->ctrl_last_run_traps; } @@ -2098,12 +2097,12 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P //- rjf: entity decoration case D_CmdKind_SetEntityColor: { - D_Entity *entity = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, params->entity); + D_Entity *entity = d_entity_from_handle(params->entity); entity->rgba = params->rgba; }break; case D_CmdKind_SetEntityName: { - D_Entity *entity = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, params->entity); + D_Entity *entity = d_entity_from_handle(params->entity); d_entity_equip_string(d_user_state->ctrl_entity_store, entity, params->string); }break; diff --git a/src/demon/demon_core.c b/src/demon/demon_core.c index 33748624..756f8068 100644 --- a/src/demon/demon_core.c +++ b/src/demon/demon_core.c @@ -162,53 +162,6 @@ dmn_rsp_from_thread(DMN_Handle thread) //////////////////////////////// //~ rjf: Process Reading Helper Functions (Helpers, Implemented Once) -internal String8 -dmn_process_read_cstring(Arena *arena, DMN_Handle process, U64 addr) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List block_list = {0}; - for(U64 cursor = addr, stride = 256;; cursor += stride) - { - U8 *raw_block = push_array_no_zero(scratch.arena, U8, stride); - U64 read_size = dmn_process_read(process, r1u64(cursor, cursor + stride), raw_block); - String8 block = str8_cstring_capped(raw_block, raw_block + read_size); - str8_list_push(scratch.arena, &block_list, block); - if(read_size != stride || (block.size+1 <= read_size && block.str[block.size] == 0)) - { - break; - } - } - String8 result = str8_list_join(arena, &block_list, 0); - scratch_end(scratch); - return result; -} - -internal String8 -dmn_process_read_block(Arena *arena, DMN_Handle process, Rng1U64 vrange) -{ - String8 block = {0}; - void *raw = dmn_process_read_raw(arena, process, vrange); - if(raw) - { - block = str8(raw, dim_1u64(vrange)); - } - return block; -} - -internal void * -dmn_process_read_raw(Arena *arena, DMN_Handle process, Rng1U64 vrange) -{ - Temp temp = temp_begin(arena); - void *buffer = push_array(arena, U8, dim_1u64(vrange)); - U64 read_size = dmn_process_read(process, vrange, buffer); - if(read_size != dim_1u64(vrange)) - { - buffer = 0; - temp_end(temp); - } - return buffer; -} - internal String8 dmn_get_trap_inst(void) { diff --git a/src/demon/demon_core.h b/src/demon/demon_core.h index 6878f837..fa4ed70d 100644 --- a/src/demon/demon_core.h +++ b/src/demon/demon_core.h @@ -219,9 +219,7 @@ internal U64 dmn_rsp_from_thread(DMN_Handle thread); //////////////////////////////// //~ rjf: Process Reading Helper Functions (Helpers, Implemented Once) -internal String8 dmn_process_read_cstring(Arena *arena, DMN_Handle process, U64 addr); -internal String8 dmn_process_read_block(Arena *arena, DMN_Handle process, Rng1U64 vrange); -internal void * dmn_process_read_raw(Arena *arena, DMN_Handle process, Rng1U64 vrange); +internal String8 dmn_data_from_process_vaddr_range(Arena *arena, DMN_Handle process, Rng1U64 vrange); //////////////////////////////// //~ rjf: @dmn_os_hooks Main Layer Initialization (Implemented Per-OS) @@ -262,8 +260,6 @@ 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, 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) -#define dmn_process_write_struct(process, vaddr, ptr) dmn_process_write((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr) //- rjf: threads internal Arch dmn_arch_from_thread(DMN_Handle handle); diff --git a/src/eval/eval_ir.c b/src/eval/eval_ir.c index 33f26ec6..a8c5906c 100644 --- a/src/eval/eval_ir.c +++ b/src/eval/eval_ir.c @@ -2028,7 +2028,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I if(reg_num != 0) { string_mapped = 1; - Arch arch = e_base_ctx->primary_module->arch; + Arch arch = e_base_ctx->thread_arch; ARCH_Info *arch_info = arch_info_from_arch(arch); ARCH_RegCode reg_code = reg_num; Rng1U16 reg_rng = arch_info->reg_code_rng_table[reg_code]; diff --git a/src/minidump/minidump.h b/src/minidump/minidump.h index db05a8dd..aab59e03 100644 --- a/src/minidump/minidump.h +++ b/src/minidump/minidump.h @@ -4,6 +4,8 @@ #ifndef MINIDUMP_H #define MINIDUMP_H +#pragma pack(push, 1) + typedef enum MDMP_DumpKind { MDMP_DumpKind_Normal = 0x00000000, @@ -226,4 +228,6 @@ struct MDMP_SystemInfo // CPU_INFORMATION Cpu; (architecture dependent) }; +#pragma pack(pop) + #endif // MINIDUMP_H diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 3d979886..5ccca316 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -696,7 +696,7 @@ rd_ctrl_entity_from_eval_space(E_Space space) 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); + entity = d_entity_from_handle(handle); } return entity; } @@ -793,7 +793,7 @@ rd_eval_space_read(E_Space space, void *out, E_SpaceRangeInfo *out_range_info, R void *regs_block = 0; if(e_interpret_ctx->reg_unwind_count == 0) { - regs_block = d_reg_block_from_thread(scratch.arena, &d_user_state->ctrl_entity_store->ctx, entity->handle); + regs_block = d_reg_block_from_thread(scratch.arena, entity->handle); } else { @@ -1042,7 +1042,7 @@ rd_eval_space_write(E_Space space, void *in, Rng1U64 range) Rng1U64 legal_range = r1u64(0, regs_size); Rng1U64 write_range = intersect_1u64(legal_range, range); U64 write_size = dim_1u64(write_range); - void *new_regs = d_reg_block_from_thread(scratch.arena, &d_user_state->ctrl_entity_store->ctx, entity->handle); + void *new_regs = d_reg_block_from_thread(scratch.arena, entity->handle); MemoryCopy((U8 *)new_regs + write_range.min, in, write_size); result = d_thread_write_reg_block(entity->handle, new_regs); scratch_end(scratch); @@ -1739,7 +1739,7 @@ rd_view_ui(Rng2F32 rect) UI_Padding(ui_pct(1, 0)) UI_Focus(UI_FocusKind_Null) { CFG_NodePtrList targets = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("target")); - D_EntityArray processes = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Process); + D_EntityArray processes = d_entity_array_from_kind(D_EntityKind_Process); //- rjf: icon & info UI_Padding(ui_em(2.f, 1.f)) UI_TagF("weak") @@ -2397,7 +2397,7 @@ rd_view_ui(Rng2F32 rect) String8 name = {0}; { U64 vaddr = eval.value.u64; - D_Entity *process = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->process); + D_Entity *process = d_entity_from_handle(rd_regs()->process); D_Entity *module = d_module_from_process_vaddr(process, vaddr); DI_Key dbgi_key = d_dbgi_key_from_module(module); U64 voff = d_voff_from_vaddr(module, vaddr); @@ -4772,7 +4772,7 @@ rd_arch_from_eval(E_Eval eval) D_Entity *process = d_process_from_entity(ctrl_entity); if(process == &d_entity_nil) { - process = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->process); + process = d_entity_from_handle(rd_regs()->process); } Arch arch = process->arch; if(arch == Arch_Null) @@ -5530,11 +5530,11 @@ rd_window_frame(void) //////////////////////// //- rjf: control entity tooltips // - case RD_RegSlot_Machine: {ctrl_entity = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, regs->machine); }goto ctrl_entity_tooltip; - case RD_RegSlot_Process: {ctrl_entity = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, regs->process); }goto ctrl_entity_tooltip; - case RD_RegSlot_Module: {ctrl_entity = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, regs->module); }goto ctrl_entity_tooltip; - case RD_RegSlot_Thread: {ctrl_entity = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, regs->thread); }goto ctrl_entity_tooltip; - case RD_RegSlot_CtrlEntity:{ctrl_entity = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, regs->ctrl_entity); }goto ctrl_entity_tooltip; + case RD_RegSlot_Machine: {ctrl_entity = d_entity_from_handle(regs->machine); }goto ctrl_entity_tooltip; + case RD_RegSlot_Process: {ctrl_entity = d_entity_from_handle(regs->process); }goto ctrl_entity_tooltip; + case RD_RegSlot_Module: {ctrl_entity = d_entity_from_handle(regs->module); }goto ctrl_entity_tooltip; + case RD_RegSlot_Thread: {ctrl_entity = d_entity_from_handle(regs->thread); }goto ctrl_entity_tooltip; + case RD_RegSlot_CtrlEntity:{ctrl_entity = d_entity_from_handle(regs->ctrl_entity); }goto ctrl_entity_tooltip; ctrl_entity_tooltip:; UI_Tooltip { @@ -7080,7 +7080,7 @@ rd_window_frame(void) { Temp scratch = scratch_begin(0, 0); CFG_NodePtrList targets = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("target")); - D_EntityArray processes = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Process); + D_EntityArray processes = d_entity_array_from_kind(D_EntityKind_Process); B32 can_send_signal = !d_ctrl_targets_running(); typedef struct CenterButtonTask CenterButtonTask; struct CenterButtonTask @@ -9624,7 +9624,7 @@ rd_string_from_exception_code(U32 code) internal DR_FStrList rd_stop_explanation_fstrs_from_ctrl_event(Arena *arena, D_Event *event) { - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, event->entity); + D_Entity *thread = d_entity_from_handle(event->entity); DR_FStrList thread_fstrs = rd_title_fstrs_from_ctrl_entity(arena, thread, 0); DR_FStrList fstrs = {0}; DR_FStrParams params = {ui_top_font(), ui_top_text_raster_flags(), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; @@ -9836,14 +9836,14 @@ rd_gather_auto_exprs(Arena *arena) U64 seen_expr_slots_count = 16; String8Node **seen_expr_slots = push_array(scratch.arena, String8Node *, seen_expr_slots_count); D_Handle thread_handle = rd_regs()->thread; - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, thread_handle); + D_Entity *thread = d_entity_from_handle(thread_handle); D_CallStack call_stack = d_call_stack_from_thread(access, thread->handle, 0, 0); if(call_stack.frames_count != 0) { //- rjf: unpack thread / module / debug info / lines ARCH_Info *arch_info = arch_info_from_arch(thread->arch); D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process); - U64 thread_ip_vaddr = d_rip_from_thread(&d_user_state->ctrl_entity_store->ctx, thread_handle); + U64 thread_ip_vaddr = d_rip_from_thread(thread_handle); D_Entity *module = d_module_from_process_vaddr(process, thread_ip_vaddr); DI_Key dbgi_key = d_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); @@ -11348,14 +11348,15 @@ rd_frame(void) //- rjf: unpack basic evaluation context // ProfBegin("unpack eval-dependent info"); - D_Entity *process = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->process); - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->thread); + D_Entity *process = d_entity_from_handle(rd_regs()->process); + D_Entity *thread = d_entity_from_handle(rd_regs()->thread); Arch arch = thread->arch; + E_Space primary_space = rd_eval_space_from_ctrl_entity(process, D_EvalSpaceKind_Entity); U64 unwind_count = rd_regs()->unwind_count; U64 rip_vaddr = d_query_cached_rip_from_thread_unwind(thread, unwind_count); D_Entity *module = d_module_from_process_vaddr(process, rip_vaddr); U64 rip_voff = d_voff_from_vaddr(module, rip_vaddr); - U64 tls_root_vaddr = d_tls_root_vaddr_from_thread(&d_user_state->ctrl_entity_store->ctx, thread->handle); + U64 tls_root_vaddr = d_tls_root_vaddr_from_thread(thread->handle); ProfEnd(); //////////////////////////// @@ -11378,7 +11379,7 @@ rd_frame(void) //////////////////////////// //- rjf: produce all eval modules // - D_EntityArray all_modules = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Module); + D_EntityArray all_modules = d_entity_array_from_kind(D_EntityKind_Module); U64 eval_modules_count = Max(1, all_modules.count); E_Module *eval_modules = push_array(scratch.arena, E_Module, eval_modules_count); E_Module *eval_modules_primary = &e_module_nil; @@ -11787,7 +11788,7 @@ rd_frame(void) { String8 name = evallable_ctrl_names[idx]; D_EntityKind kind = d_entity_kind_from_string(name); - D_EntityArray array = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, kind); + D_EntityArray array = d_entity_array_from_kind(kind); E_TypeKey type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, name); for EachIndex(idx, array.count) { @@ -12158,7 +12159,7 @@ rd_frame(void) //- rjf: gather config from loaded modules // CFG_NodePtrList immediate_type_views = {0}; - D_EntityArray modules = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Module); + D_EntityArray modules = d_entity_array_from_kind(D_EntityKind_Module); ProfScope("gather config from loaded modules") { for EachIndex(idx, modules.count) @@ -12262,7 +12263,7 @@ rd_frame(void) E_IRCtx *ir_ctx = push_array(scratch.arena, E_IRCtx, 1); { E_IRCtx *ctx = ir_ctx; - ctx->regs_map = d_string2reg_from_arch(eval_base_ctx->primary_module->arch); + ctx->regs_map = d_string2reg_from_arch(arch); ctx->locals_map = d_query_cached_locals_map_from_dbgi_key_voff(eval_base_ctx->primary_dbg_info->dbgi_key, rip_voff); ctx->member_map = d_query_cached_member_map_from_dbgi_key_voff(eval_base_ctx->primary_dbg_info->dbgi_key, rip_voff); ctx->macro_map = macro_map; @@ -12276,8 +12277,8 @@ rd_frame(void) E_InterpretCtx *interpret_ctx = push_array(scratch.arena, E_InterpretCtx, 1); { E_InterpretCtx *ctx = interpret_ctx; - ctx->primary_space = eval_modules_primary->space; - ctx->reg_arch = eval_modules_primary->arch; + ctx->primary_space = primary_space; + ctx->reg_arch = arch; ctx->reg_space = rd_eval_space_from_ctrl_entity(thread, D_EvalSpaceKind_Entity); ctx->reg_unwind_count = unwind_count; ctx->module_base = push_array(scratch.arena, U64, 1); @@ -12349,7 +12350,7 @@ rd_frame(void) case RD_CmdKind_Restart: { // rjf: reset hit counts - D_EntityArray processes = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Process); + D_EntityArray processes = d_entity_array_from_kind(D_EntityKind_Process); if(processes.count == 0 || kind == RD_CmdKind_Restart) { CFG_NodePtrList bps = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("breakpoint")); @@ -12569,7 +12570,7 @@ rd_frame(void) { // rjf: if control processes are live, but this is not force-confirmed, then // get confirmation from user - D_EntityArray processes = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Process); + D_EntityArray processes = d_entity_array_from_kind(D_EntityKind_Process); UI_Key key = ui_key_from_string(ui_key_zero(), str8_lit("lossy_exit_confirmation")); if(processes.count != 0 && !rd_regs()->force_confirm && !ui_key_match(rd_state->popup_key, key)) { @@ -13907,12 +13908,12 @@ rd_frame(void) //- rjf: source <-> disasm case RD_CmdKind_GoToDisassembly: { - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->thread); + D_Entity *thread = d_entity_from_handle(rd_regs()->thread); U64 vaddr = 0; for(D_LineNode *n = rd_regs()->lines.first; n != 0; n = n->next) { - D_EntityList modules = d_modules_from_dbgi_key(scratch.arena, &d_user_state->ctrl_entity_store->ctx, n->v.dbgi_key); - D_Entity *module = d_module_from_thread_candidates(&d_user_state->ctrl_entity_store->ctx, thread, &modules); + D_EntityList modules = d_modules_from_dbgi_key(scratch.arena, n->v.dbgi_key); + D_Entity *module = d_module_from_thread_candidates(thread, &modules); if(module != &d_entity_nil) { vaddr = d_vaddr_from_voff(module, n->v.voff_range.min); @@ -14195,7 +14196,7 @@ rd_frame(void) Access *access = access_open(); //- rjf: unpack thread info - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->thread); + D_Entity *thread = d_entity_from_handle(rd_regs()->thread); U64 unwind_index = rd_regs()->unwind_count; U64 inline_depth = rd_regs()->inline_depth; U64 rip_vaddr = d_query_cached_rip_from_thread_unwind(thread, unwind_index); @@ -14259,7 +14260,7 @@ rd_frame(void) }break; case RD_CmdKind_FindSelectedThread: { - D_Entity *selected_thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_base_regs()->thread); + D_Entity *selected_thread = d_entity_from_handle(rd_base_regs()->thread); rd_cmd(RD_CmdKind_FindThread, .thread = selected_thread->handle, .unwind_count = rd_base_regs()->unwind_count, @@ -14368,7 +14369,7 @@ rd_frame(void) { D_Entity *process = &d_entity_nil; U64 vaddr = 0; - D_EntityList modules = d_modules_from_dbgi_key(scratch.arena, &d_user_state->ctrl_entity_store->ctx, voff_dbgi_key); + D_EntityList modules = d_modules_from_dbgi_key(scratch.arena, voff_dbgi_key); D_Entity *module = d_entity_list_first(&modules); process = d_entity_ancestor_from_kind(module, D_EntityKind_Process); if(process != &d_entity_nil) @@ -14448,8 +14449,8 @@ rd_frame(void) { file_path = rd_mapped_from_file_path(scratch.arena, rd_regs()->file_path); point = rd_regs()->cursor; - thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->thread); - process = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->process); + thread = d_entity_from_handle(rd_regs()->thread); + process = d_entity_from_handle(rd_regs()->process); vaddr = rd_regs()->vaddr; prefer_new_tab = rd_regs()->prefer_new_tab; if(file_path.size == 0) @@ -14471,8 +14472,8 @@ rd_frame(void) D_LineList lines = d_lines_from_file_path_line_num(scratch.arena, file_path, point.line, max_U64); for(D_LineNode *n = lines.first; n != 0; n = n->next) { - D_EntityList modules = d_modules_from_dbgi_key(scratch.arena, &d_user_state->ctrl_entity_store->ctx, n->v.dbgi_key); - D_Entity *module = d_module_from_thread_candidates(&d_user_state->ctrl_entity_store->ctx, thread, &modules); + D_EntityList modules = d_modules_from_dbgi_key(scratch.arena, n->v.dbgi_key); + D_Entity *module = d_module_from_thread_candidates(thread, &modules); vaddr = d_vaddr_from_voff(module, n->v.voff_range.min); break; } @@ -15685,7 +15686,7 @@ rd_frame(void) }break; case RD_CmdKind_SetNextStatement: { - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->thread); + D_Entity *thread = d_entity_from_handle(rd_regs()->thread); String8 file_path = rd_regs()->file_path; U64 new_rip_vaddr = rd_regs()->vaddr_range.min; if(file_path.size != 0) @@ -15693,8 +15694,8 @@ rd_frame(void) D_LineList *lines = &rd_regs()->lines; for(D_LineNode *n = lines->first; n != 0; n = n->next) { - D_EntityList modules = d_modules_from_dbgi_key(scratch.arena, &d_user_state->ctrl_entity_store->ctx, n->v.dbgi_key); - D_Entity *module = d_module_from_thread_candidates(&d_user_state->ctrl_entity_store->ctx, thread, &modules); + D_EntityList modules = d_modules_from_dbgi_key(scratch.arena, n->v.dbgi_key); + D_Entity *module = d_module_from_thread_candidates(thread, &modules); if(module != &d_entity_nil) { new_rip_vaddr = d_vaddr_from_voff(module, n->v.voff_range.min); @@ -15810,9 +15811,9 @@ rd_frame(void) }break; case RD_CmdKind_SelectThread: { - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->thread); + D_Entity *thread = d_entity_from_handle(rd_regs()->thread); D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process); - D_Entity *module = d_module_from_process_vaddr(process, d_rip_from_thread(&d_user_state->ctrl_entity_store->ctx, thread->handle)); + D_Entity *module = d_module_from_process_vaddr(process, d_rip_from_thread(thread->handle)); D_Entity *machine = d_entity_ancestor_from_kind(process, D_EntityKind_Machine); rd_state->base_regs.v.unwind_count = 0; rd_state->base_regs.v.inline_depth = 0; @@ -15825,7 +15826,7 @@ rd_frame(void) case RD_CmdKind_SelectUnwind: { Access *access = access_open(); - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_base_regs()->thread); + D_Entity *thread = d_entity_from_handle(rd_base_regs()->thread); D_CallStack call_stack = d_call_stack_from_thread(access, thread->handle, 1, now_time_us()+10000); D_CallStackFrame *frame = d_call_stack_frame_from_unwind_and_inline_depth(&call_stack, rd_regs()->unwind_count, rd_regs()->inline_depth); if(frame == 0) @@ -15844,7 +15845,7 @@ rd_frame(void) case RD_CmdKind_DownOneFrame: { Access *access = access_open(); - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_base_regs()->thread); + D_Entity *thread = d_entity_from_handle(rd_base_regs()->thread); D_CallStack call_stack = d_call_stack_from_thread(access, thread->handle, 1, now_time_us()+10000); D_CallStackFrame *current_frame = d_call_stack_frame_from_unwind_and_inline_depth(&call_stack, rd_regs()->unwind_count, rd_regs()->inline_depth); D_CallStackFrame *next_frame = current_frame; @@ -16576,7 +16577,7 @@ rd_frame(void) default:{}break; case D_EventKind_NewProc: { - D_EntityArray all_processes = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Process); + D_EntityArray all_processes = d_entity_array_from_kind(D_EntityKind_Process); if(all_processes.count == 1) { MemoryZeroStruct(&rd_state->prestop_focused_window); @@ -16593,7 +16594,7 @@ rd_frame(void) }break; case D_EventKind_NewModule: { - D_Entity *module = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, evt->entity); + D_Entity *module = d_entity_from_handle(evt->entity); D_Entity *debug_info_path = d_entity_child_from_kind(module, D_EntityKind_DebugInfoPath); String8 new_path = debug_info_path->string; if(new_path.size != 0 && file_path_exists(new_path)) @@ -16637,7 +16638,7 @@ rd_frame(void) case D_EventKind_EndProc: if(rd_state->quit_after_success) { - D_EntityArray processes = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Process); + D_EntityArray processes = d_entity_array_from_kind(D_EntityKind_Process); if(evt->u64_code == 0 && processes.count == 0) { rd_cmd(RD_CmdKind_Exit); @@ -16650,12 +16651,12 @@ rd_frame(void) case D_EventKind_Stopped: { B32 need_refocus = (evt->cause != D_EventCause_InterruptedByHalt || !soft_halt_issued); - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, evt->entity); + D_Entity *thread = d_entity_from_handle(evt->entity); U64 vaddr = evt->rip_vaddr; D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process); D_Entity *module = d_module_from_process_vaddr(process, vaddr); U64 voff = d_voff_from_vaddr(module, vaddr); - U64 test_cached_vaddr = d_rip_from_thread(&d_user_state->ctrl_entity_store->ctx, thread->handle); + U64 test_cached_vaddr = d_rip_from_thread(thread->handle); // rjf: valid stop thread? -> select & snap if(need_refocus && thread->kind == D_EntityKind_Thread && evt->cause != D_EventCause_InterruptedByHalt) @@ -16664,7 +16665,7 @@ rd_frame(void) } // rjf: no stop-causing thread, but have selected thread? -> snap to selected - D_Entity *selected_thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_base_regs()->thread); + D_Entity *selected_thread = d_entity_from_handle(rd_base_regs()->thread); if(need_refocus && (evt->cause == D_EventCause_InterruptedByHalt || thread->kind != D_EntityKind_Thread) && selected_thread != &d_entity_nil) { rd_cmd(RD_CmdKind_SelectThread, .thread = selected_thread->handle); @@ -16673,7 +16674,7 @@ rd_frame(void) // rjf: no stop-causing thread, but don't have selected thread? -> snap to first available thread if(need_refocus && thread->kind != D_EntityKind_Thread && selected_thread == &d_entity_nil) { - D_EntityArray threads = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Thread); + D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread); D_Entity *first_available_thread = d_entity_array_first(&threads); rd_cmd(RD_CmdKind_SelectThread, .thread = first_available_thread->handle); } @@ -16725,7 +16726,7 @@ rd_frame(void) // rjf: update the autos-determining code range { D_Handle new_thread_handle = thread->handle; - U64 new_sp = d_rsp_from_thread(&d_user_state->ctrl_entity_store->ctx, new_thread_handle); + U64 new_sp = d_rsp_from_thread(new_thread_handle); if(thread == &d_entity_nil) { new_thread_handle = selected_thread->handle; diff --git a/src/raddbg/raddbg_eval.c b/src/raddbg/raddbg_eval.c index c911fbaf..8b34dd7a 100644 --- a/src/raddbg/raddbg_eval.c +++ b/src/raddbg/raddbg_eval.c @@ -267,7 +267,7 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(locals) E_TYPE_EXPAND_INFO_FUNCTION_DEF(registers) { Temp scratch = scratch_begin(&arena, 1); - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->thread); + D_Entity *thread = d_entity_from_handle(rd_regs()->thread); Arch arch = thread->arch; ARCH_Info *arch_info = arch_info_from_arch(arch); U64 reg_count = arch_info->reg_code_count; @@ -769,7 +769,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(control) str8_match(str8_prefix(rhs->string, 1), str8_lit("$"), 0)) { D_Handle handle = d_handle_from_string(rhs->string); - D_Entity *entity = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, handle); + D_Entity *entity = d_entity_from_handle(handle); E_Space space = rd_eval_space_from_ctrl_entity(entity, RD_EvalSpaceKind_MetaCtrlEntity); result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, 0)); result.type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, d_entity_kind_code_name_table[entity->kind]); @@ -1103,7 +1103,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(call_stack) D_CallStack *call_stack = &accel->call_stack; if(0 <= rhs_value.u64 && rhs_value.u64 < call_stack->frames_count) { - D_Entity *process = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, accel->process); + D_Entity *process = d_entity_from_handle(accel->process); ARCH_Info *arch_info = arch_info_from_arch(accel->arch); D_CallStackFrame *f = &call_stack->frames[rhs_value.u64]; result.root = e_irtree_set_space(arena, rd_eval_space_from_ctrl_entity(process, D_EvalSpaceKind_Entity), e_irtree_const_u(arena, arch_ip_from_reg_block(arch_info, f->regs))); @@ -1565,7 +1565,7 @@ E_TYPE_EXPAND_INFO_FUNCTION_DEF(unattached_processes) } else { - machines = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Machine); + machines = d_entity_array_from_kind(D_EntityKind_Machine); } //- rjf: gather system processes from this machine @@ -1662,7 +1662,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(ctrl_entities) { String8 rhs_name = expr->first->next->string; D_Handle handle = d_handle_from_string(rhs_name); - entity = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, handle); + entity = d_entity_from_handle(handle); }break; case E_ExprKind_ArrayIndex: { @@ -1670,7 +1670,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(ctrl_entities) D_EntityKind kind = d_entity_kind_from_string(rd_singular_from_code_name_plural(type->name)); E_Value rhs_value = e_value_from_expr(expr->first->next); U64 rhs_idx = rhs_value.u64; - D_EntityArray entities = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, kind); + D_EntityArray entities = d_entity_array_from_kind(kind); if(0 <= rhs_idx && rhs_idx < entities.count) { entity = entities.v[rhs_idx]; @@ -1712,7 +1712,7 @@ E_TYPE_EXPAND_INFO_FUNCTION_DEF(ctrl_entities) D_EntityArray array = {0}; if(scoping_entity == &d_entity_nil) { - array = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, entity_kind); + array = d_entity_array_from_kind(entity_kind); } else { diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index a965bd4c..53331eb0 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -292,6 +292,7 @@ //- rjf: [h] #include "base/base_inc.h" #include "x64/x64.h" +#include "win32/win32_inc.h" #include "linker/hash_table.h" #include "linker/lf_hash_table.h" #include "linker/base_ext/base_bit_array.h" @@ -347,6 +348,7 @@ //- rjf: [c] #include "base/base_inc.c" #include "x64/x64.c" +#include "win32/win32_inc.c" #include "linker/hash_table.c" #include "linker/lf_hash_table.c" #include "linker/base_ext/base_bit_array.c" diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index 417f5c98..ad4dec36 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -44,7 +44,7 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla F32 scroll_bar_dim = floor_f32(main_font_size*1.5f); Vec2F32 code_area_dim = v2f32(panel_box_dim.x - scroll_bar_dim, panel_box_dim.y - scroll_bar_dim); S64 num_possible_visible_lines = (S64)(code_area_dim.y/code_line_height)+1; - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->thread); + D_Entity *thread = d_entity_from_handle(rd_regs()->thread); D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process); B32 do_line_numbers = rd_setting_b32_from_name(str8_lit("show_line_numbers")); @@ -278,8 +278,8 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla // rjf: find live threads mapping to source code if(!dasm_lines) ProfScope("find live threads mapping to this file") { - D_Entity *selected_thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->thread); - D_EntityArray threads = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Thread); + D_Entity *selected_thread = d_entity_from_handle(rd_regs()->thread); + D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread); for EachIndex(idx, threads.count) { D_Entity *thread = threads.v[idx]; @@ -341,7 +341,7 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla if(!dasm_lines) ProfScope("find all src -> dasm info for source code") { String8 file_path = rd_regs()->file_path; - D_Entity *module = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->module); + D_Entity *module = d_entity_from_handle(rd_regs()->module); DI_Key dbgi_key = d_dbgi_key_from_module(module); D_LineListArray lines_array = d_lines_array_from_dbgi_key_file_path_line_range(scratch.arena, dbgi_key, file_path, visible_line_num_range, 8); if(lines_array.count != 0) @@ -354,8 +354,8 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla // rjf: find live threads mapping to disasm if(dasm_lines) ProfScope("find live threads mapping to this disassembly") { - D_Entity *selected_thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->thread); - D_EntityArray threads = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Thread); + D_Entity *selected_thread = d_entity_from_handle(rd_regs()->thread); + D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread); for EachIndex(idx, threads.count) { D_Entity *thread = threads.v[idx]; @@ -2102,7 +2102,7 @@ RD_VIEW_UI_FUNCTION_DEF(text) if(rd_regs()->lang_kind == TXT_LangKind_Null) { Access *access = access_open(); - D_Entity *module = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->module); + D_Entity *module = d_entity_from_handle(rd_regs()->module); DI_Key dbgi_key = d_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); if(rdi != &rdi_parsed_nil) @@ -2226,7 +2226,7 @@ RD_VIEW_UI_FUNCTION_DEF(text) // if(rd_regs()->file_path.size != 0) { - D_Entity *module = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->module); + D_Entity *module = d_entity_from_handle(rd_regs()->module); DI_Key dbgi_key = d_dbgi_key_from_module(module); rd_regs()->lines = d_lines_from_dbgi_key_file_path_line_num(rd_frame_arena(), dbgi_key, rd_regs()->file_path, rd_regs()->cursor.line, 8); } @@ -2436,13 +2436,13 @@ RD_VIEW_UI_FUNCTION_DEF(disasm) if(dv->temp_look_vaddr != 0 && dv->temp_look_run_gen == d_run_gen()) { auto_selected = 1; - auto_space = rd_eval_space_from_ctrl_entity(d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, dv->temp_look_process), D_EvalSpaceKind_Entity); + auto_space = rd_eval_space_from_ctrl_entity(d_entity_from_handle(dv->temp_look_process), D_EvalSpaceKind_Entity); eval = e_eval_from_stringf("(0x%I64x & (~(0x4000 - 1)))", dv->temp_look_vaddr); } else { auto_selected = 1; - auto_space = rd_eval_space_from_ctrl_entity(d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->process), D_EvalSpaceKind_Entity); + auto_space = rd_eval_space_from_ctrl_entity(d_entity_from_handle(rd_regs()->process), D_EvalSpaceKind_Entity); eval = e_eval_from_stringf("(reg:rip & (~(0x4000 - 1)))"); } } @@ -2683,7 +2683,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory) Rng1U64 view_range = rd_space_range_from_eval(eval); if(eval.space.kind == 0) { - eval.space = rd_eval_space_from_ctrl_entity(d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->process), D_EvalSpaceKind_Entity); + eval.space = rd_eval_space_from_ctrl_entity(d_entity_from_handle(rd_regs()->process), D_EvalSpaceKind_Entity); view_range = rd_whole_range_from_eval_space(eval.space); } @@ -3257,7 +3257,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory) AnnotationList *visible_memory_annotations = push_array(scratch.arena, AnnotationList, visible_memory_size); { Access *access = access_open(); - D_Entity *selected_thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->thread); + D_Entity *selected_thread = d_entity_from_handle(rd_regs()->thread); D_Entity *selected_process = d_entity_ancestor_from_kind(selected_thread, D_EntityKind_Process); D_CallStack selected_call_stack = d_call_stack_from_thread(access, selected_thread->handle, 1, 0); D_Entity *eval_process = &d_entity_nil; diff --git a/src/raddbg/raddbg_widgets.c b/src/raddbg/raddbg_widgets.c index 96ada8e6..857e89b1 100644 --- a/src/raddbg/raddbg_widgets.c +++ b/src/raddbg/raddbg_widgets.c @@ -109,7 +109,7 @@ rd_title_fstrs_from_cfg(Arena *arena, CFG_Node *cfg, B32 include_extras) CFG_Node *bp = cfg_node_from_id(stop_event.u64_code); if(bp == cfg) { - D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, stop_event.entity); + D_Entity *thread = d_entity_from_handle(stop_event.entity); Vec4F32 thread_color = rd_color_from_ctrl_entity(thread); if(thread_color.w == 0) { @@ -518,7 +518,7 @@ rd_title_fstrs_from_ctrl_entity(Arena *arena, D_Entity *entity, B32 include_extr if(entity->kind == D_EntityKind_Thread || entity->kind == D_EntityKind_Module) { - D_EntityArray processes = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Process); + D_EntityArray processes = d_entity_array_from_kind(D_EntityKind_Process); if(processes.count > 1) { D_Entity *process = d_entity_ancestor_from_kind(entity, D_EntityKind_Process); @@ -1264,12 +1264,12 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe RD_CodeSliceSignal result = {0}; ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); - D_Entity *selected_thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_regs()->thread); + D_Entity *selected_thread = d_entity_from_handle(rd_regs()->thread); D_Entity *selected_thread_process = d_entity_ancestor_from_kind(selected_thread, D_EntityKind_Process); U64 selected_thread_rip_unwind_vaddr = d_query_cached_rip_from_thread_unwind(selected_thread, rd_regs()->unwind_count); D_Entity *selected_thread_module = d_module_from_process_vaddr(selected_thread_process, selected_thread_rip_unwind_vaddr); D_Event stop_event = d_ctrl_last_stop_event(); - D_Entity *stopper_thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, stop_event.entity); + D_Entity *stopper_thread = d_entity_from_handle(stop_event.entity); B32 is_focused = ui_is_focus_active(); B32 ctrlified = (wm_get_modifiers() & WM_Modifier_Ctrl); Vec4F32 code_line_bgs[] = @@ -1348,7 +1348,7 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe if(rd_state->drag_drop_regs_slot == RD_RegSlot_Thread) { drop_can_hit_lines = 1; - drop_thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_state->drag_drop_regs->thread); + drop_thread = d_entity_from_handle(rd_state->drag_drop_regs->thread); drop_color = rd_color_from_ctrl_entity(drop_thread); if(drop_color.w == 0) { @@ -2113,8 +2113,8 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe D_LineList *lines = ¶ms->line_infos[line_idx]; for(D_LineNode *n = lines->first; n != 0; n = n->next) { - D_EntityList modules = d_modules_from_dbgi_key(scratch.arena, &d_user_state->ctrl_entity_store->ctx, n->v.dbgi_key); - D_Entity *module = d_module_from_thread_candidates(&d_user_state->ctrl_entity_store->ctx, thread, &modules); + D_EntityList modules = d_modules_from_dbgi_key(scratch.arena, n->v.dbgi_key); + D_Entity *module = d_module_from_thread_candidates(thread, &modules); if(module != &d_entity_nil) { new_rip_vaddr = d_vaddr_from_voff(module, n->v.voff_range.min); @@ -2723,7 +2723,7 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe Rng1U64 hover_voff_range = hover_regs->voff_range; if(hover_voff_range.min == 0 && hover_voff_range.max == 0) { - D_Entity *module = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, hover_regs->module); + D_Entity *module = d_entity_from_handle(hover_regs->module); hover_voff_range = d_voff_range_from_vaddr_range(module, hover_regs->vaddr_range); } ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); diff --git a/src/win32/demon/win32_demon.c b/src/win32/demon/win32_demon.c index 890404d7..329d0dfd 100644 --- a/src/win32/demon/win32_demon.c +++ b/src/win32/demon/win32_demon.c @@ -607,7 +607,7 @@ w32_dmn_thread_read_reg_block(Arch arch, HANDLE thread, void *reg_block) } //- rjf: unpack features available on this context - if (xstate_enabled) + if(xstate_enabled) { SetXStateFeaturesMask(ctx, XSTATE_MASK_AVX | XSTATE_MASK_AVX512 | XSTATE_MASK_CET_U); } diff --git a/src/win32/win32_inc.c b/src/win32/win32_inc.c new file mode 100644 index 00000000..6f8f5874 --- /dev/null +++ b/src/win32/win32_inc.c @@ -0,0 +1,6 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#if defined(X64_H) +# include "win32/x64/win32_x64.c" +#endif diff --git a/src/win32/win32_inc.h b/src/win32/win32_inc.h new file mode 100644 index 00000000..062fd9e5 --- /dev/null +++ b/src/win32/win32_inc.h @@ -0,0 +1,11 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef WIN32_INC_H +#define WIN32_INC_H + +#if defined(X64_H) +# include "win32/x64/win32_x64.h" +#endif + +#endif // WIN32_INC_H diff --git a/src/win32/x64/win32_x64.c b/src/win32/x64/win32_x64.c new file mode 100644 index 00000000..9cb50c40 --- /dev/null +++ b/src/win32/x64/win32_x64.c @@ -0,0 +1,139 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +internal B32 +w32_x64_write_reg_block_from_thread_ctx(void *reg_block, void *thread_ctx) +{ + X64_RegBlock *dst = (X64_RegBlock *)reg_block; + W32_X64_ThreadContext *src = (W32_X64_ThreadContext *)thread_ctx; + + //- rjf: convert context -> X64_RegBlock + W32_X64_XSaveFormat *xsave = &src->FltSave; + dst->rax = src->Rax; + dst->rcx = src->Rcx; + dst->rdx = src->Rdx; + dst->rbx = src->Rbx; + dst->rsp = src->Rsp; + dst->rbp = src->Rbp; + dst->rsi = src->Rsi; + dst->rdi = src->Rdi; + dst->r8 = src->R8; + dst->r9 = src->R9; + dst->r10 = src->R10; + dst->r11 = src->R11; + dst->r12 = src->R12; + dst->r13 = src->R13; + dst->r14 = src->R14; + dst->r15 = src->R15; + dst->rip = src->Rip; + dst->cs = src->SegCs; + dst->ds = src->SegDs; + dst->es = src->SegEs; + dst->fs = src->SegFs; + dst->gs = src->SegGs; + dst->ss = src->SegSs; + dst->dr0 = src->Dr0; + dst->dr1 = src->Dr1; + dst->dr2 = src->Dr2; + dst->dr3 = src->Dr3; + dst->dr6 = src->Dr6; + dst->dr7 = src->Dr7; + // NOTE(rjf): this bit is "supposed to always be 1", according to old info. + // may need to be investigated. + dst->rflags = src->EFlags | 0x2; + dst->fcw = xsave->ControlWord; + dst->fsw = xsave->StatusWord; + dst->ftw = xsave->TagWord; + dst->fop = xsave->ErrorOpcode; + MemoryCopy(&dst->fip, &xsave->ErrorOffset, sizeof(U64)); + MemoryCopy(&dst->fdp, &xsave->DataOffset, sizeof(U64)); + dst->mxcsr = xsave->MxCsr; + dst->mxcsr_mask = xsave->MxCsr_Mask; + { + U128 *float_s = xsave->FloatRegisters; + U80 *float_d = &dst->st0; + for(U32 n = 0; n < 8; n += 1, float_s += 1, float_d += 1) + { + MemoryCopy(float_d, float_s, sizeof(*float_d)); + } + } + { + U128 *xmm_s = xsave->XmmRegisters; + U512 *zmm_d = &dst->zmm0; + for(U32 n = 0; n < 16; n += 1, xmm_s += 1, zmm_d += 1) + { + MemoryCopy(zmm_d, xmm_s, sizeof(*xmm_s)); + } + } + + // TODO(rjf): we need to determine how to do LocateXStateFeature without + // actually running on Windows - what is that function actually looking at + // & doing? +#if 0 + // AVX + { + DWORD avx_length = 0; + U8 *avx_s = (U8 *)LocateXStateFeature(ctx, XSTATE_AVX, &avx_length); + if(avx_length == 16 * sizeof(U128)) + { + U512 *zmm_d = &dst->zmm0; + for(U32 n = 0; n < 16; n += 1, avx_s += sizeof(U128), zmm_d += 1) + { + MemoryCopy(&zmm_d->u8[16], avx_s, sizeof(U128)); + } + } + } + + // AVX-512 + { + // rjf: kmask + DWORD kmask_length = 0; + U64 *kmask_s = (U64*)LocateXStateFeature(ctx, XSTATE_AVX512_KMASK, &kmask_length); + if(kmask_length == 8 * sizeof(U64)) + { + U64 *kmask_d = &dst->k0; + for(U32 n = 0; n < 8; n += 1, kmask_s += 1, kmask_d += 1) + { + MemoryCopy(kmask_d, kmask_s, sizeof(*kmask_s)); + } + } + + // rjf: zmmh + DWORD avx512h_length = 0; + U8 *avx512h_s = (U8*)LocateXStateFeature(ctx, XSTATE_AVX512_ZMM_H, &avx512h_length); + if(avx512h_length == 16 * sizeof(U256)) + { + U512 *zmmh_d = &dst->zmm0; + for(U32 n = 0; n < 16; n += 1, avx512h_s += sizeof(U256), zmmh_d += 1) + { + MemoryCopy(&zmmh_d->u8[32], avx512h_s, sizeof(U256)); + } + } + + // rjf: zmm + DWORD avx512_length = 0; + U8 *avx512_s = (U8 *)LocateXStateFeature(ctx, XSTATE_AVX512_ZMM, &avx512_length); + if(avx512_length == 16 * sizeof(U512)) + { + U512 *zmm_d = &dst->zmm16; + for(U32 n = 0; n < 16; n += 1, avx512_s += sizeof(U512), zmm_d += 1) + { + MemoryCopy(zmm_d, avx512_s, sizeof(U512)); + } + } + } + + // CET / Shadow Stack + if(xstate_mask & XSTATE_MASK_CET_U) + { + DWORD cet_length = 0; + XSAVE_CET_U_FORMAT *cet = LocateXStateFeature(ctx, XSTATE_CET_U, &cet_length); + if (cet_length == sizeof(*cet)) + { + dst->cetmsr = cet->Ia32CetUMsr; + dst->cetssp = cet->Ia32Pl3SspMsr; + } + } +#endif + return 1; +} diff --git a/src/win32/x64/win32_x64.h b/src/win32/x64/win32_x64.h new file mode 100644 index 00000000..478852b1 --- /dev/null +++ b/src/win32/x64/win32_x64.h @@ -0,0 +1,110 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef WIN32_X64_H +#define WIN32_X64_H + +#pragma pack(push, 1) + +typedef struct W32_X64_XSaveFormat W32_X64_XSaveFormat; +struct W32_X64_XSaveFormat +{ + U16 ControlWord; + U16 StatusWord; + U8 TagWord; + U8 Reserved1; + U16 ErrorOpcode; + U32 ErrorOffset; + U16 ErrorSelector; + U16 Reserved2; + U32 DataOffset; + U16 DataSelector; + U16 Reserved3; + U32 MxCsr; + U32 MxCsr_Mask; + U128 FloatRegisters[8]; + U128 XmmRegisters[16]; + U8 Reserved4[96]; +}; + +typedef struct W32_X64_ThreadContext W32_X64_ThreadContext; +struct W32_X64_ThreadContext +{ + U64 P1Home; + U64 P2Home; + U64 P3Home; + U64 P4Home; + U64 P5Home; + U64 P6Home; + U32 ContextFlags; + U32 MxCsr; + U16 SegCs; + U16 SegDs; + U16 SegEs; + U16 SegFs; + U16 SegGs; + U16 SegSs; + U32 EFlags; + U64 Dr0; + U64 Dr1; + U64 Dr2; + U64 Dr3; + U64 Dr6; + U64 Dr7; + U64 Rax; + U64 Rcx; + U64 Rdx; + U64 Rbx; + U64 Rsp; + U64 Rbp; + U64 Rsi; + U64 Rdi; + U64 R8; + U64 R9; + U64 R10; + U64 R11; + U64 R12; + U64 R13; + U64 R14; + U64 R15; + U64 Rip; + union + { + W32_X64_XSaveFormat FltSave; + struct + { + U128 Header[2]; + U128 Legacy[8]; + U128 Xmm0; + U128 Xmm1; + U128 Xmm2; + U128 Xmm3; + U128 Xmm4; + U128 Xmm5; + U128 Xmm6; + U128 Xmm7; + U128 Xmm8; + U128 Xmm9; + U128 Xmm10; + U128 Xmm11; + U128 Xmm12; + U128 Xmm13; + U128 Xmm14; + U128 Xmm15; + U8 padding_0[96]; + }; + }; + U128 VectorRegister[26]; + U64 VectorControl; + U64 DebugControl; + U64 LastBranchToRip; + U64 LastBranchFromRip; + U64 LastExceptionToRip; + U64 LastExceptionFromRip; +}; + +#pragma pack(pop) + +internal B32 w32_x64_write_reg_block_from_thread_ctx(void *reg_block, void *thread_ctx); + +#endif // WIN32_X64_H