diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 65d42656..49f6be97 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -800,6 +800,7 @@ ctrl_init(void) Arena *arena = arena_alloc(); ctrl_state = push_array(arena, CTRL_State, 1); ctrl_state->arena = arena; + ctrl_state->ctrl_run_mutex = os_mutex_alloc(); for(Architecture arch = (Architecture)0; arch < Architecture_COUNT; arch = (Architecture)(arch+1)) { String8 *reg_names = regs_reg_code_string_table_from_architecture(arch); @@ -1344,12 +1345,17 @@ ctrl_query_cached_reg_block_from_thread(Arena *arena, CTRL_MachineID machine_id, if(node) { U64 current_reg_gen = dmn_reg_gen(); - if(node->reg_gen != current_reg_gen && dmn_thread_read_reg_block(thread, result)) + B32 need_stale = 1; + if(node->reg_gen != current_reg_gen) { - node->reg_gen = current_reg_gen; - MemoryCopy(node->block, result, reg_block_size); + OS_MutexScope(ctrl_state->ctrl_run_mutex) if(ctrl_state->ctrl_run_state == 0 && dmn_thread_read_reg_block(thread, result)) + { + need_stale = 0; + node->reg_gen = current_reg_gen; + MemoryCopy(node->block, result, reg_block_size); + } } - else + if(need_stale) { MemoryCopy(result, node->block, reg_block_size); } @@ -1719,6 +1725,12 @@ ctrl_thread__entry_point(void *p) //- rjf: get next messages CTRL_MsgList msgs = ctrl_u2c_pop_msgs(scratch.arena); + //- rjf: begin run state + OS_MutexScope(ctrl_state->ctrl_run_mutex) + { + ctrl_state->ctrl_run_state = 1; + } + //- rjf: process messages { B32 done = 0; @@ -1753,6 +1765,12 @@ ctrl_thread__entry_point(void *p) } } } + + //- rjf: end run state + OS_MutexScope(ctrl_state->ctrl_run_mutex) + { + ctrl_state->ctrl_run_state = 0; + } } scratch_end(scratch); @@ -2879,7 +2897,7 @@ ctrl_thread__run(CTRL_Msg *msg) if(process->kind != CTRL_EntityKind_Process) { continue; } for(CTRL_Entity *thread = process->first; thread != &ctrl_entity_nil; thread = thread->next) { - U64 rip = ctrl_query_cached_rip_from_thread(thread->machine_id, thread->handle); + U64 rip = dmn_rip_from_thread(thread->handle); // rjf: determine if thread is frozen B32 thread_is_frozen = !msg->freeze_state_is_frozen; @@ -2998,7 +3016,7 @@ ctrl_thread__run(CTRL_Msg *msg) // if(stop_event == 0) { - U64 sp_check_value = ctrl_query_cached_rsp_from_thread(CTRL_MachineID_Local, target_thread); + U64 sp_check_value = dmn_rsp_from_thread(target_thread); B32 spoof_mode = 0; CTRL_Spoof spoof = {0}; for(;;) @@ -3085,9 +3103,7 @@ ctrl_thread__run(CTRL_Msg *msg) // CTRL_Entity *thread = ctrl_entity_from_machine_id_handle(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, event->thread); Architecture arch = thread->arch; - U64 reg_size = regs_block_size_from_architecture(arch); - void *thread_regs_block = ctrl_query_cached_reg_block_from_thread(scratch.arena, CTRL_MachineID_Local, event->thread); - U64 thread_rip_vaddr = regs_rip_from_arch_block(arch, thread_regs_block); + U64 thread_rip_vaddr = dmn_rsp_from_thread(event->thread); DMN_Handle module = {0}; String8 module_name = {0}; U64 module_base_vaddr = 0; @@ -3226,15 +3242,16 @@ ctrl_thread__run(CTRL_Msg *msg) if(bytecode.size != 0) { U64 module_base = module_base_vaddr; - U64 tls_base = ctrl_query_cached_tls_root_vaddr_from_thread(CTRL_MachineID_Local, event->thread); + U64 tls_base = dmn_tls_root_vaddr_from_thread(event->thread); EVAL_Machine machine = {0}; machine.u = &event->process; machine.arch = arch; machine.memory_read = ctrl_eval_memory_read; - machine.reg_data = thread_regs_block; - machine.reg_size = reg_size; + machine.reg_size = regs_block_size_from_architecture(arch); + machine.reg_data = push_array(scratch.arena, U8, machine.reg_size); machine.module_base = &module_base; machine.tls_base = &tls_base; + dmn_thread_read_reg_block(event->thread, machine.reg_data); eval = eval_interpret(&machine, bytecode); } if(eval.code == EVAL_ResultCode_Good && eval.value.u64 == 0) @@ -3335,7 +3352,7 @@ ctrl_thread__run(CTRL_Msg *msg) B32 stack_pointer_matches = 0; if(use_trap_net_logic) { - U64 sp = ctrl_query_cached_rsp_from_thread(CTRL_MachineID_Local, target_thread); + U64 sp = dmn_rsp_from_thread(target_thread); stack_pointer_matches = (sp == sp_check_value); } @@ -3383,7 +3400,7 @@ ctrl_thread__run(CTRL_Msg *msg) { // rjf: setup spoof mode begin_spoof_mode = 1; - U64 spoof_sp = ctrl_query_cached_rsp_from_thread(CTRL_MachineID_Local, target_thread); + U64 spoof_sp = dmn_rsp_from_thread(target_thread); spoof_mode = 1; spoof.process = target_process; spoof.thread = target_thread; @@ -3401,7 +3418,7 @@ ctrl_thread__run(CTRL_Msg *msg) if(stack_pointer_matches) { save_stack_pointer = 1; - sp_check_value = ctrl_query_cached_rsp_from_thread(CTRL_MachineID_Local, target_thread); + sp_check_value = dmn_rsp_from_thread(target_thread); } } } diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index 916f3db4..f74f2a83 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -491,6 +491,10 @@ struct CTRL_State EVAL_String2NumMap arch_string2reg_tables[Architecture_COUNT]; EVAL_String2NumMap arch_string2alias_tables[Architecture_COUNT]; + // rjf: access locking mechanism + OS_Handle ctrl_run_mutex; + B32 ctrl_run_state; + // rjf: caches CTRL_ProcessMemoryCache process_memory_cache; CTRL_ThreadRegCache thread_reg_cache; diff --git a/src/demon2/demon2_core.c b/src/demon2/demon2_core.c index ee3b7ed6..86c1c3c6 100644 --- a/src/demon2/demon2_core.c +++ b/src/demon2/demon2_core.c @@ -116,3 +116,38 @@ dmn_event_list_push(Arena *arena, DMN_EventList *list) DMN_Event *result = &n->v; return result; } + +//////////////////////////////// +//~ rjf: Thread Reading Helper Functions (Helpers, Implemented Once) + +internal U64 +dmn_rip_from_thread(DMN_Handle thread) +{ + U64 result = 0; + Temp scratch = scratch_begin(0, 0); + { + Architecture arch = dmn_arch_from_thread(thread); + U64 reg_block_size = regs_block_size_from_architecture(arch); + void *reg_block = push_array(scratch.arena, U8, reg_block_size); + dmn_thread_read_reg_block(thread, reg_block); + result = regs_rip_from_arch_block(arch, reg_block); + } + scratch_end(scratch); + return result; +} + +internal U64 +dmn_rsp_from_thread(DMN_Handle thread) +{ + U64 result = 0; + Temp scratch = scratch_begin(0, 0); + { + Architecture arch = dmn_arch_from_thread(thread); + U64 reg_block_size = regs_block_size_from_architecture(arch); + void *reg_block = push_array(scratch.arena, U8, reg_block_size); + dmn_thread_read_reg_block(thread, reg_block); + result = regs_rsp_from_arch_block(arch, reg_block); + } + scratch_end(scratch); + return result; +} diff --git a/src/demon2/demon2_core.h b/src/demon2/demon2_core.h index dc79b254..2ae5efc8 100644 --- a/src/demon2/demon2_core.h +++ b/src/demon2/demon2_core.h @@ -160,6 +160,12 @@ internal DMN_HandleArray dmn_handle_array_copy(Arena *arena, DMN_HandleArray *sr //- rjf: event list building internal DMN_Event *dmn_event_list_push(Arena *arena, DMN_EventList *list); +//////////////////////////////// +//~ rjf: Thread Reading Helper Functions (Helpers, Implemented Once) + +internal U64 dmn_rip_from_thread(DMN_Handle thread); +internal U64 dmn_rsp_from_thread(DMN_Handle thread); + //////////////////////////////// //~ rjf: @dmn_os_hooks Main Layer Initialization (Implemented Per-OS) diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 75c2525d..1d7c255c 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -6217,13 +6217,18 @@ internal U64 df_query_cached_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64 rip_vaddr) { U64 result = 0; + for(U64 cache_idx = 0; cache_idx < ArrayCount(df_state->tls_base_caches); cache_idx += 1) { - DF_RunTLSBaseCache *cache = &df_state->tls_base_cache; - if(cache->slots_count == 0) + DF_RunTLSBaseCache *cache = &df_state->tls_base_caches[(df_state->tls_base_cache_gen+cache_idx)%ArrayCount(df_state->tls_base_caches)]; + if(cache_idx == 0 && cache->slots_count == 0) { cache->slots_count = 256; cache->slots = push_array(cache->arena, DF_RunTLSBaseCacheSlot, cache->slots_count); } + else if(cache->slots_count == 0) + { + break; + } DF_Handle handle = df_handle_from_entity(process); U64 hash = df_hash_from_seed_string(df_hash_from_string(str8_struct(&handle)), str8_struct(&rip_vaddr)); U64 slot_idx = hash%cache->slots_count; @@ -6239,14 +6244,22 @@ df_query_cached_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 roo } if(node == 0) { - node = push_array(cache->arena, DF_RunTLSBaseCacheNode, 1); - SLLQueuePush_N(slot->first, slot->last, node, hash_next); - node->process = handle; - node->root_vaddr = root_vaddr; - node->rip_vaddr = rip_vaddr; - node->tls_base_vaddr = df_tls_base_vaddr_from_process_root_rip(process, root_vaddr, rip_vaddr); + U64 tls_base_vaddr = df_tls_base_vaddr_from_process_root_rip(process, root_vaddr, rip_vaddr); + if(tls_base_vaddr != 0) + { + node = push_array(cache->arena, DF_RunTLSBaseCacheNode, 1); + SLLQueuePush_N(slot->first, slot->last, node, hash_next); + node->process = handle; + node->root_vaddr = root_vaddr; + node->rip_vaddr = rip_vaddr; + node->tls_base_vaddr = tls_base_vaddr; + } + } + if(node != 0 && node->tls_base_vaddr != 0) + { + result = node->tls_base_vaddr; + break; } - result = node->tls_base_vaddr; } return result; } @@ -6256,13 +6269,18 @@ df_query_cached_locals_map_from_binary_voff(DF_Entity *binary, U64 voff) { ProfBeginFunction(); EVAL_String2NumMap *map = &eval_string2num_map_nil; + for(U64 cache_idx = 0; cache_idx < ArrayCount(df_state->locals_caches); cache_idx += 1) { - DF_RunLocalsCache *cache = &df_state->locals_cache; - if(cache->table_size == 0) + DF_RunLocalsCache *cache = &df_state->locals_caches[(df_state->locals_cache_gen+cache_idx)%ArrayCount(df_state->locals_caches)]; + if(cache_idx == 0 && cache->table_size == 0) { cache->table_size = 256; cache->table = push_array(cache->arena, DF_RunLocalsCacheSlot, cache->table_size); } + else if(cache->table_size == 0) + { + break; + } DF_Handle handle = df_handle_from_entity(binary); U64 hash = df_hash_from_string(str8_struct(&handle)); U64 slot_idx = hash % cache->table_size; @@ -6290,9 +6308,10 @@ df_query_cached_locals_map_from_binary_voff(DF_Entity *binary, U64 voff) } dbgi_scope_close(scope); } - if(node != 0) + if(node != 0 && node->locals_map->slots_count != 0) { map = node->locals_map; + break; } } ProfEnd(); @@ -6413,8 +6432,14 @@ df_core_init(CmdLine *cmdln, DF_StateDeltaHistory *hist) { df_state->unwind_caches[idx].arena = arena_alloc(); } - df_state->tls_base_cache.arena = arena_alloc(); - df_state->locals_cache.arena = arena_alloc(); + for(U64 idx = 0; idx < ArrayCount(df_state->tls_base_caches); idx += 1) + { + df_state->tls_base_caches[idx].arena = arena_alloc(); + } + for(U64 idx = 0; idx < ArrayCount(df_state->locals_caches); idx += 1) + { + df_state->locals_caches[idx].arena = arena_alloc(); + } df_state->member_cache.arena = arena_alloc(); // rjf: set up eval view cache @@ -6901,7 +6926,8 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) df_state->tls_base_cache_memgen_idx != new_mem_gen) && !df_ctrl_targets_running()) { - DF_RunTLSBaseCache *cache = &df_state->tls_base_cache; + df_state->tls_base_cache_gen += 1; + DF_RunTLSBaseCache *cache = &df_state->tls_base_caches[df_state->tls_base_cache_gen%ArrayCount(df_state->tls_base_caches)]; arena_clear(cache->arena); cache->slots_count = 0; cache->slots = 0; @@ -6910,9 +6936,11 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) } //- rjf: clear locals cache - if(df_state->locals_cache_reggen_idx != new_reg_gen && !df_ctrl_targets_running()) + if(df_state->locals_cache_reggen_idx != new_reg_gen && + !df_ctrl_targets_running()) { - DF_RunLocalsCache *cache = &df_state->locals_cache; + df_state->locals_cache_gen += 1; + DF_RunLocalsCache *cache = &df_state->locals_caches[df_state->locals_cache_gen%ArrayCount(df_state->locals_caches)]; arena_clear(cache->arena); cache->table_size = 0; cache->table = 0; diff --git a/src/df/core/df_core.h b/src/df/core/df_core.h index 76c97340..4df932cd 100644 --- a/src/df/core/df_core.h +++ b/src/df/core/df_core.h @@ -1139,9 +1139,11 @@ struct DF_State U64 unwind_cache_gen; U64 tls_base_cache_reggen_idx; U64 tls_base_cache_memgen_idx; - DF_RunTLSBaseCache tls_base_cache; + DF_RunTLSBaseCache tls_base_caches[2]; + U64 tls_base_cache_gen; U64 locals_cache_reggen_idx; - DF_RunLocalsCache locals_cache; + DF_RunLocalsCache locals_caches[2]; + U64 locals_cache_gen; U64 member_cache_reggen_idx; DF_RunLocalsCache member_cache; diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index d411c08c..a6f1eacb 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -6244,7 +6244,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) DF_Entity *thread = thread_n->entity; U64 unwind_count = (thread == selected_thread) ? ctrl_ctx.unwind_count : 0; U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count); - if(contains_1u64(disasm_vaddr_rng, rip_vaddr)) ProfScope("in-range rip scan") + if(contains_1u64(disasm_vaddr_rng, rip_vaddr)) { U64 rip_off = rip_vaddr - disasm_vaddr_rng.min; S64 line_num = dasm_inst_array_idx_from_off__linear_scan(&insts, rip_off)+1;