mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-13 07:32:23 -07:00
eliminate old debug engine unwind cache
This commit is contained in:
@@ -2091,6 +2091,7 @@ ctrl_rsp_from_thread(CTRL_EntityCtx *ctx, CTRL_Handle handle)
|
||||
internal B32
|
||||
ctrl_thread_write_reg_block(CTRL_Handle thread, void *block)
|
||||
{
|
||||
// TODO(rjf): @callstacks immediately reflect this in the call stack cache
|
||||
B32 good = dmn_thread_write_reg_block(thread.dmn_handle, block);
|
||||
return good;
|
||||
}
|
||||
|
||||
@@ -1160,61 +1160,6 @@ d_push_active_dbgi_key_list(Arena *arena)
|
||||
|
||||
//- rjf: per-run caches
|
||||
|
||||
internal CTRL_Unwind
|
||||
d_query_cached_unwind_from_thread(CTRL_Entity *thread)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
CTRL_Unwind result = {0};
|
||||
if(thread->kind == CTRL_EntityKind_Thread)
|
||||
{
|
||||
U64 reg_gen = ctrl_reg_gen();
|
||||
U64 mem_gen = ctrl_mem_gen();
|
||||
D_UnwindCache *cache = &d_state->unwind_cache;
|
||||
CTRL_Handle handle = thread->handle;
|
||||
U64 hash = d_hash_from_string(str8_struct(&handle));
|
||||
U64 slot_idx = hash%cache->slots_count;
|
||||
D_UnwindCacheSlot *slot = &cache->slots[slot_idx];
|
||||
D_UnwindCacheNode *node = 0;
|
||||
for(D_UnwindCacheNode *n = slot->first; n != 0; n = n->next)
|
||||
{
|
||||
if(ctrl_handle_match(handle, n->thread))
|
||||
{
|
||||
node = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(node == 0)
|
||||
{
|
||||
node = cache->free_node;
|
||||
if(node != 0)
|
||||
{
|
||||
SLLStackPop(cache->free_node);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = push_array_no_zero(d_state->arena, D_UnwindCacheNode, 1);
|
||||
}
|
||||
MemoryZeroStruct(node);
|
||||
DLLPushBack(slot->first, slot->last, node);
|
||||
node->arena = arena_alloc();
|
||||
node->thread = handle;
|
||||
}
|
||||
if(!d_state->ctrl_is_running && (node->reggen != reg_gen || node->memgen != mem_gen))
|
||||
{
|
||||
CTRL_Unwind new_unwind = ctrl_unwind_from_thread(scratch.arena, &d_state->ctrl_entity_store->ctx, thread->handle, os_now_microseconds()+100);
|
||||
if(!(new_unwind.flags & (CTRL_UnwindFlag_Error|CTRL_UnwindFlag_Stale)) && new_unwind.frames.count != 0)
|
||||
{
|
||||
node->unwind = ctrl_unwind_deep_copy(node->arena, thread->arch, &new_unwind);
|
||||
node->reggen = reg_gen;
|
||||
node->memgen = mem_gen;
|
||||
}
|
||||
}
|
||||
result = node->unwind;
|
||||
}
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
d_query_cached_rip_from_thread(CTRL_Entity *thread)
|
||||
{
|
||||
@@ -1232,10 +1177,11 @@ d_query_cached_rip_from_thread_unwind(CTRL_Entity *thread, U64 unwind_count)
|
||||
}
|
||||
else
|
||||
{
|
||||
CTRL_Unwind unwind = d_query_cached_unwind_from_thread(thread);
|
||||
if(unwind.frames.count != 0)
|
||||
CTRL_Scope *ctrl_scope = ctrl_scope_open();
|
||||
CTRL_CallStack callstack = ctrl_call_stack_from_thread(ctrl_scope, &d_state->ctrl_entity_store->ctx, thread, 1, 0);
|
||||
if(callstack.concrete_frames_count != 0)
|
||||
{
|
||||
result = regs_rip_from_arch_block(thread->arch, unwind.frames.v[unwind_count%unwind.frames.count].regs);
|
||||
result = regs_rip_from_arch_block(thread->arch, callstack.concrete_frames[unwind_count%callstack.concrete_frames_count]->regs);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -1450,8 +1396,6 @@ d_init(void)
|
||||
d_state->ctrl_msg_arena = arena_alloc();
|
||||
|
||||
// rjf: set up caches
|
||||
d_state->unwind_cache.slots_count = 1024;
|
||||
d_state->unwind_cache.slots = push_array(arena, D_UnwindCacheSlot, d_state->unwind_cache.slots_count);
|
||||
for(U64 idx = 0; idx < ArrayCount(d_state->tls_base_caches); idx += 1)
|
||||
{
|
||||
d_state->tls_base_caches[idx].arena = arena_alloc();
|
||||
@@ -1695,24 +1639,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
d_cmd(D_CmdKind_SoftHaltRefresh);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: garbage collect eliminated thread unwinds
|
||||
//
|
||||
for(U64 slot_idx = 0; slot_idx < d_state->unwind_cache.slots_count; slot_idx += 1)
|
||||
{
|
||||
D_UnwindCacheSlot *slot = &d_state->unwind_cache.slots[slot_idx];
|
||||
for(D_UnwindCacheNode *n = slot->first, *next = 0; n != 0; n = next)
|
||||
{
|
||||
next = n->next;
|
||||
if(ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, n->thread) == &ctrl_entity_nil)
|
||||
{
|
||||
DLLRemove(slot->first, slot->last, n);
|
||||
arena_release(n->arena);
|
||||
SLLStackPush(d_state->unwind_cache.free_node, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: process top-level commands
|
||||
//
|
||||
@@ -1928,13 +1854,15 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
case D_CmdKind_StepOverLine: {traps = d_trap_net_from_thread__step_over_line(scratch.arena, thread);}break;
|
||||
case D_CmdKind_StepOut:
|
||||
{
|
||||
// rjf: thread => full unwind
|
||||
CTRL_Unwind unwind = ctrl_unwind_from_thread(scratch.arena, &d_state->ctrl_entity_store->ctx, thread->handle, os_now_microseconds()+10000);
|
||||
CTRL_Scope *ctrl_scope = ctrl_scope_open();
|
||||
|
||||
// rjf: thread => call stack
|
||||
CTRL_CallStack callstack = ctrl_call_stack_from_thread(ctrl_scope, &d_state->ctrl_entity_store->ctx, thread, 1, os_now_microseconds()+10000);
|
||||
|
||||
// rjf: use first unwind frame to generate trap
|
||||
if(unwind.flags == 0 && unwind.frames.count > 1)
|
||||
if(callstack.concrete_frames_count > 1)
|
||||
{
|
||||
U64 vaddr = regs_rip_from_arch_block(thread->arch, unwind.frames.v[1].regs);
|
||||
U64 vaddr = regs_rip_from_arch_block(thread->arch, callstack.concrete_frames[1]->regs);
|
||||
CTRL_Trap trap = {CTRL_TrapFlag_EndStepping|CTRL_TrapFlag_IgnoreStackPointerCheck, vaddr};
|
||||
ctrl_trap_list_push(scratch.arena, &traps, &trap);
|
||||
}
|
||||
@@ -1943,6 +1871,8 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
log_user_error(str8_lit("Could not find the return address of the current callstack frame successfully."));
|
||||
good = 0;
|
||||
}
|
||||
|
||||
ctrl_scope_close(ctrl_scope);
|
||||
}break;
|
||||
}
|
||||
if(good && traps.count != 0)
|
||||
@@ -1984,27 +1914,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
void *block = ctrl_reg_block_from_thread(scratch.arena, &d_state->ctrl_entity_store->ctx, thread->handle);
|
||||
regs_arch_block_write_rip(thread->arch, block, vaddr);
|
||||
B32 result = ctrl_thread_write_reg_block(thread->handle, block);
|
||||
|
||||
// rjf: early mutation of unwind cache for immediate frontend effect
|
||||
if(result)
|
||||
{
|
||||
D_UnwindCache *cache = &d_state->unwind_cache;
|
||||
if(cache->slots_count != 0)
|
||||
{
|
||||
CTRL_Handle thread_handle = thread->handle;
|
||||
U64 hash = d_hash_from_string(str8_struct(&thread_handle));
|
||||
U64 slot_idx = hash%cache->slots_count;
|
||||
D_UnwindCacheSlot *slot = &cache->slots[slot_idx];
|
||||
for(D_UnwindCacheNode *n = slot->first; n != 0; n = n->next)
|
||||
{
|
||||
if(ctrl_handle_match(n->thread, thread_handle) && n->unwind.frames.count != 0)
|
||||
{
|
||||
regs_arch_block_write_rip(thread->arch, n->unwind.frames.v[0].regs, vaddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(void)result;
|
||||
}break;
|
||||
|
||||
//- rjf: high-level composite target control operations
|
||||
|
||||
@@ -215,35 +215,6 @@ struct D_CmdList
|
||||
////////////////////////////////
|
||||
//~ rjf: Main State Caches
|
||||
|
||||
//- rjf: per-thread unwind cache
|
||||
|
||||
typedef struct D_UnwindCacheNode D_UnwindCacheNode;
|
||||
struct D_UnwindCacheNode
|
||||
{
|
||||
D_UnwindCacheNode *next;
|
||||
D_UnwindCacheNode *prev;
|
||||
U64 reggen;
|
||||
U64 memgen;
|
||||
Arena *arena;
|
||||
CTRL_Handle thread;
|
||||
CTRL_Unwind unwind;
|
||||
};
|
||||
|
||||
typedef struct D_UnwindCacheSlot D_UnwindCacheSlot;
|
||||
struct D_UnwindCacheSlot
|
||||
{
|
||||
D_UnwindCacheNode *first;
|
||||
D_UnwindCacheNode *last;
|
||||
};
|
||||
|
||||
typedef struct D_UnwindCache D_UnwindCache;
|
||||
struct D_UnwindCache
|
||||
{
|
||||
U64 slots_count;
|
||||
D_UnwindCacheSlot *slots;
|
||||
D_UnwindCacheNode *free_node;
|
||||
};
|
||||
|
||||
//- rjf: per-run tls-base-vaddr cache
|
||||
|
||||
typedef struct D_RunTLSBaseCacheNode D_RunTLSBaseCacheNode;
|
||||
@@ -315,7 +286,6 @@ struct D_State
|
||||
HS_Key output_log_key;
|
||||
|
||||
// rjf: per-run caches
|
||||
D_UnwindCache unwind_cache;
|
||||
U64 tls_base_cache_reggen_idx;
|
||||
U64 tls_base_cache_memgen_idx;
|
||||
D_RunTLSBaseCache tls_base_caches[2];
|
||||
@@ -435,7 +405,6 @@ internal B32 d_ctrl_targets_running(void);
|
||||
internal DI_KeyList d_push_active_dbgi_key_list(Arena *arena);
|
||||
|
||||
//- rjf: per-run caches
|
||||
internal CTRL_Unwind d_query_cached_unwind_from_thread(CTRL_Entity *thread);
|
||||
internal U64 d_query_cached_rip_from_thread(CTRL_Entity *thread);
|
||||
internal U64 d_query_cached_rip_from_thread_unwind(CTRL_Entity *thread, U64 unwind_count);
|
||||
internal U64 d_query_cached_tls_base_vaddr_from_process_root_rip(CTRL_Entity *process, U64 root_vaddr, U64 rip_vaddr);
|
||||
|
||||
Reference in New Issue
Block a user