From 2d1fcd7475e8df9e639eb6931a7029d55064bfa4 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 20 May 2024 08:23:41 -0700 Subject: [PATCH] fix some unwanted frontend unwind cache behavior; fix staleness calculation in ctrl process memory cache --- src/ctrl/ctrl_core.c | 37 +++++++++++++++++---- src/ctrl/ctrl_core.h | 3 ++ src/df/core/df_core.c | 77 ++++++++++++++++++++++++------------------- 3 files changed, 78 insertions(+), 39 deletions(-) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index a24a150f..fb1cb63e 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -920,6 +920,7 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, DMN_Handle { U128 result = {0}; U64 size = dim_1u64(range); + U64 pre_mem_gen = dmn_mem_gen(); if(size != 0) for(;;) { CTRL_ProcessMemoryCache *cache = &ctrl_state->process_memory_cache; @@ -932,7 +933,7 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, DMN_Handle //- rjf: try to read from cache B32 is_good = 0; - B32 is_stale = 0; + B32 is_stale = 1; OS_MutexScopeR(process_stripe->rw_mutex) { for(CTRL_ProcessMemoryCacheNode *n = process_slot->first; n != 0; n = n->next) @@ -947,7 +948,7 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, DMN_Handle { result = range_n->hash; is_good = 1; - is_stale = (range_n->mem_gen != dmn_mem_gen()); + is_stale = (range_n->mem_gen != pre_mem_gen); goto read_cache__break_all; } } @@ -1065,6 +1066,11 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, DMN_Handle break; } } + U64 post_mem_gen = dmn_mem_gen(); + if(post_mem_gen != pre_mem_gen && out_is_stale) + { + out_is_stale[0] = 1; + } return result; } @@ -1450,6 +1456,27 @@ ctrl_thread_write_reg_block(CTRL_MachineID machine_id, DMN_Handle thread, void * //////////////////////////////// //~ rjf: Unwinding Functions +//- rjf: unwind deep copier + +internal CTRL_Unwind +ctrl_unwind_deep_copy(Arena *arena, Architecture arch, CTRL_Unwind *src) +{ + CTRL_Unwind dst = {0}; + { + dst.flags = src->flags; + dst.frames.count = src->frames.count; + dst.frames.v = push_array(arena, CTRL_UnwindFrame, dst.frames.count); + MemoryCopy(dst.frames.v, src->frames.v, sizeof(dst.frames.v[0])*dst.frames.count); + U64 block_size = regs_block_size_from_architecture(arch); + for(U64 idx = 0; idx < dst.frames.count; idx += 1) + { + dst.frames.v[idx].regs = push_array_no_zero(arena, U8, block_size); + MemoryCopy(dst.frames.v[idx].regs, src->frames.v[idx].regs, block_size); + } + } + return dst; +} + //- rjf: [x64] internal REGS_Reg64 * @@ -2480,7 +2507,6 @@ ctrl_unwind_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_MachineID ma { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); - DBGI_Scope *scope = dbgi_scope_open(); CTRL_Unwind unwind = {0}; unwind.flags |= CTRL_UnwindFlag_Error; @@ -2492,13 +2518,13 @@ ctrl_unwind_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_MachineID ma //- rjf: grab initial register block void *regs_block = ctrl_query_cached_reg_block_from_thread(scratch.arena, store, machine_id, thread); - B32 regs_block_good = (regs_block != 0); + B32 regs_block_good = (arch != Architecture_Null && regs_block != 0); //- rjf: loop & unwind CTRL_UnwindFrameNode *first_frame_node = 0; CTRL_UnwindFrameNode *last_frame_node = 0; U64 frame_node_count = 0; - if(arch != Architecture_Null && regs_block_good) + if(regs_block_good) { unwind.flags = 0; for(;;) @@ -2552,7 +2578,6 @@ ctrl_unwind_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_MachineID ma } } - dbgi_scope_close(scope); scratch_end(scratch); ProfEnd(); return unwind; diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index bef126e8..e940c0eb 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -697,6 +697,9 @@ internal B32 ctrl_thread_write_reg_block(CTRL_MachineID machine_id, DMN_Handle t //////////////////////////////// //~ rjf: Unwinding Functions +//- rjf: unwind deep copier +internal CTRL_Unwind ctrl_unwind_deep_copy(Arena *arena, Architecture arch, CTRL_Unwind *src); + //- rjf: [x64] internal REGS_Reg64 *ctrl_unwind_reg_from_pe_gpr_reg__pe_x64(REGS_RegBlockX64 *regs, PE_UnwindGprRegX64 gpr_reg); internal CTRL_UnwindStepResult ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle module, REGS_RegBlockX64 *regs, U64 endt_us); diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index ba7e8cd9..9ed6b865 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -6198,50 +6198,61 @@ df_push_active_target_list(Arena *arena) internal CTRL_Unwind df_query_cached_unwind_from_thread(DF_Entity *thread) { + Temp scratch = scratch_begin(0, 0); CTRL_Unwind result = {0}; - DF_Handle handle = df_handle_from_entity(thread); - U64 hash = df_hash_from_string(str8_struct(&handle)); - for(U64 cache_idx = 0; cache_idx < ArrayCount(df_state->unwind_caches); cache_idx += 1) { - DF_RunUnwindCache *cache = &df_state->unwind_caches[(df_state->unwind_cache_gen+cache_idx)%ArrayCount(df_state->unwind_caches)]; - if(cache_idx == 0 && cache->slots_count == 0) + DF_Handle handle = df_handle_from_entity(thread); + U64 hash = df_hash_from_string(str8_struct(&handle)); + for(U64 cache_idx = 0; cache_idx < ArrayCount(df_state->unwind_caches); cache_idx += 1) { - cache->slots_count = 1024; - cache->slots = push_array(cache->arena, DF_RunUnwindCacheSlot, cache->slots_count); - } - else if(cache->slots_count == 0) - { - break; - } - U64 slot_idx = hash%cache->slots_count; - DF_RunUnwindCacheSlot *slot = &cache->slots[slot_idx]; - DF_RunUnwindCacheNode *node = 0; - for(DF_RunUnwindCacheNode *n = slot->first; n != 0; n = n->hash_next) - { - if(df_handle_match(n->thread, handle)) + //- rjf: grab next recent cache + DF_RunUnwindCache *cache = &df_state->unwind_caches[(df_state->unwind_cache_gen+cache_idx)%ArrayCount(df_state->unwind_caches)]; + if(cache_idx == 0 && cache->slots_count == 0) + { + cache->slots_count = 1024; + cache->slots = push_array(cache->arena, DF_RunUnwindCacheSlot, cache->slots_count); + } + else if(cache->slots_count == 0) { - node = n; break; } - } - if(node != 0) - { - result = node->unwind; - break; - } - else - { - result = ctrl_unwind_from_thread(cache->arena, df_state->ctrl_entity_store, thread->ctrl_machine_id, thread->ctrl_handle, 0); - if(!(result.flags & (CTRL_UnwindFlag_Error|CTRL_UnwindFlag_Stale))) + + //- rjf: thread/hash -> node + U64 slot_idx = hash%cache->slots_count; + DF_RunUnwindCacheSlot *slot = &cache->slots[slot_idx]; + DF_RunUnwindCacheNode *node = 0; + for(DF_RunUnwindCacheNode *n = slot->first; n != 0; n = n->hash_next) { - node = push_array(cache->arena, DF_RunUnwindCacheNode, 1); - SLLQueuePush_N(slot->first, slot->last, node, hash_next); - node->thread = handle; - node->unwind = result; + if(df_handle_match(n->thread, handle)) + { + node = n; + break; + } + } + + //- rjf: no node? -> calculate unwind if needed - store if good & return + if(node == 0) + { + CTRL_Unwind current_unwind = ctrl_unwind_from_thread(scratch.arena, df_state->ctrl_entity_store, thread->ctrl_machine_id, thread->ctrl_handle, 0); + if(!(current_unwind.flags & (CTRL_UnwindFlag_Error|CTRL_UnwindFlag_Stale))) + { + Architecture arch = df_architecture_from_entity(thread); + node = push_array(cache->arena, DF_RunUnwindCacheNode, 1); + SLLQueuePush_N(slot->first, slot->last, node, hash_next); + node->thread = handle; + node->unwind = ctrl_unwind_deep_copy(cache->arena, arch, ¤t_unwind); + } + } + + //- rjf: cached node -> grab result & return + if(node != 0) + { + result = node->unwind; break; } } } + scratch_end(scratch); return result; }