sketch out unwind cache

This commit is contained in:
Ryan Fleury
2025-05-14 11:43:01 -07:00
parent a67f326f78
commit e60e0c8555
4 changed files with 118 additions and 96 deletions
+55 -71
View File
@@ -1084,7 +1084,7 @@ internal CTRL_Entity *
ctrl_module_from_thread_candidates(CTRL_EntityStore *store, CTRL_Entity *thread, CTRL_EntityList *candidates)
{
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process);
U64 thread_rip_vaddr = ctrl_query_cached_rip_from_thread(store, thread->handle);
U64 thread_rip_vaddr = ctrl_rip_from_thread(store, thread->handle);
CTRL_Entity *src_module = ctrl_module_from_process_vaddr(process, thread_rip_vaddr);
CTRL_Entity *module = &ctrl_entity_nil;
for(CTRL_EntityNode *n = candidates->first; n != 0; n = n->next)
@@ -1266,7 +1266,7 @@ ctrl_entity_store_apply_events(CTRL_EntityStore *store, CTRL_EventList *list)
}
}
thread->stack_base = event->stack_base;
ctrl_query_cached_rip_from_thread(store, event->entity);
ctrl_rip_from_thread(store, event->entity);
}break;
case CTRL_EventKind_EndThread:
{
@@ -1432,6 +1432,15 @@ ctrl_init(void)
ctrl_state->thread_reg_cache.stripes[idx].arena = arena_alloc();
ctrl_state->thread_reg_cache.stripes[idx].rw_mutex = os_rw_mutex_alloc();
}
ctrl_state->thread_unwind_cache.slots_count = 1024;
ctrl_state->thread_unwind_cache.slots = push_array(arena, CTRL_ThreadUnwindCacheSlot, ctrl_state->thread_unwind_cache.slots_count);
ctrl_state->thread_unwind_cache.stripes_count = os_get_system_info()->logical_processor_count;
ctrl_state->thread_unwind_cache.stripes = push_array(arena, CTRL_ThreadUnwindCacheStripe, ctrl_state->thread_unwind_cache.stripes_count);
for(U64 idx = 0; idx < ctrl_state->thread_unwind_cache.stripes_count; idx += 1)
{
ctrl_state->thread_unwind_cache.stripes[idx].arena = arena_alloc();
ctrl_state->thread_unwind_cache.stripes[idx].rw_mutex = os_rw_mutex_alloc();
}
ctrl_state->module_image_info_cache.slots_count = 1024;
ctrl_state->module_image_info_cache.slots = push_array(arena, CTRL_ModuleImageInfoCacheSlot, ctrl_state->module_image_info_cache.slots_count);
ctrl_state->module_image_info_cache.stripes_count = os_get_system_info()->logical_processor_count;
@@ -1686,7 +1695,7 @@ ctrl_hash_store_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range,
//- rjf: process memory cache reading helpers
internal CTRL_ProcessMemorySlice
ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_Handle process, Rng1U64 range, U64 endt_us)
ctrl_process_memory_slice_from_vaddr_range(Arena *arena, CTRL_Handle process, Rng1U64 range, U64 endt_us)
{
ProfBeginFunction();
CTRL_ProcessMemorySlice result = {0};
@@ -1829,37 +1838,12 @@ ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_Handle proces
return result;
}
internal CTRL_ProcessMemorySlice
ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_Handle process, U64 vaddr, U64 limit, U64 element_size, U64 endt_us)
{
CTRL_ProcessMemorySlice result = ctrl_query_cached_data_from_process_vaddr_range(arena, process, r1u64(vaddr, vaddr+limit), endt_us);
U64 element_count = result.data.size/element_size;
for(U64 element_idx = 0; element_idx < element_count; element_idx += 1)
{
B32 element_is_zero = 1;
for(U64 element_byte_idx = 0; element_byte_idx < element_size; element_byte_idx += 1)
{
if(result.data.str[element_idx*element_size + element_byte_idx] != 0)
{
element_is_zero = 0;
break;
}
}
if(element_is_zero)
{
result.data.size = element_idx*element_size;
break;
}
}
return result;
}
internal B32
ctrl_read_cached_process_memory(CTRL_Handle process, Rng1U64 range, B32 *is_stale_out, void *out, U64 endt_us)
ctrl_process_memory_read(CTRL_Handle process, Rng1U64 range, B32 *is_stale_out, void *out, U64 endt_us)
{
Temp scratch = scratch_begin(0, 0);
U64 needed_size = dim_1u64(range);
CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process, range, endt_us);
CTRL_ProcessMemorySlice slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process, range, endt_us);
B32 good = (slice.data.size >= needed_size && !slice.any_byte_bad);
if(good)
{
@@ -1932,7 +1916,7 @@ ctrl_process_write(CTRL_Handle process, Rng1U64 range, void *src)
for(Task *task = first_task; task != 0; task = task->next)
{
Temp temp = temp_begin(scratch.arena);
ctrl_query_cached_data_from_process_vaddr_range(temp.arena, task->process, task->range, endt_us);
ctrl_process_memory_slice_from_vaddr_range(temp.arena, task->process, task->range, endt_us);
temp_end(temp);
}
@@ -1949,7 +1933,7 @@ ctrl_process_write(CTRL_Handle process, Rng1U64 range, void *src)
//- rjf: thread register cache reading
internal void *
ctrl_query_cached_reg_block_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_Handle handle)
ctrl_reg_block_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_Handle handle)
{
CTRL_ThreadRegCache *cache = &ctrl_state->thread_reg_cache;
CTRL_Entity *thread_entity = ctrl_entity_from_handle(store, handle);
@@ -2008,31 +1992,31 @@ ctrl_query_cached_reg_block_from_thread(Arena *arena, CTRL_EntityStore *store, C
}
internal U64
ctrl_query_cached_tls_root_vaddr_from_thread(CTRL_EntityStore *store, CTRL_Handle handle)
ctrl_tls_root_vaddr_from_thread(CTRL_EntityStore *store, CTRL_Handle handle)
{
U64 result = dmn_tls_root_vaddr_from_thread(handle.dmn_handle);
return result;
}
internal U64
ctrl_query_cached_rip_from_thread(CTRL_EntityStore *store, CTRL_Handle handle)
ctrl_rip_from_thread(CTRL_EntityStore *store, CTRL_Handle handle)
{
Temp scratch = scratch_begin(0, 0);
CTRL_Entity *thread_entity = ctrl_entity_from_handle(store, handle);
Arch arch = thread_entity->arch;
void *block = ctrl_query_cached_reg_block_from_thread(scratch.arena, store, handle);
void *block = ctrl_reg_block_from_thread(scratch.arena, store, handle);
U64 result = regs_rip_from_arch_block(arch, block);
scratch_end(scratch);
return result;
}
internal U64
ctrl_query_cached_rsp_from_thread(CTRL_EntityStore *store, CTRL_Handle handle)
ctrl_rsp_from_thread(CTRL_EntityStore *store, CTRL_Handle handle)
{
Temp scratch = scratch_begin(0, 0);
CTRL_Entity *thread_entity = ctrl_entity_from_handle(store, handle);
Arch arch = thread_entity->arch;
void *block = ctrl_query_cached_reg_block_from_thread(scratch.arena, store, handle);
void *block = ctrl_reg_block_from_thread(scratch.arena, store, handle);
U64 result = regs_rsp_from_arch_block(arch, block);
scratch_end(scratch);
return result;
@@ -2294,7 +2278,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
U8 inst[4] = {0};
if(read_vaddr + sizeof(inst) <= read_vaddr_opl)
{
inst_good = ctrl_read_cached_process_memory(process_handle, r1u64(read_vaddr, read_vaddr+sizeof(inst)), &is_stale, inst, endt_us);
inst_good = ctrl_process_memory_read(process_handle, r1u64(read_vaddr, read_vaddr+sizeof(inst)), &is_stale, inst, endt_us);
inst_good = inst_good && !is_stale;
}
if(!inst_good)
@@ -2375,7 +2359,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
U8 inst_byte = 0;
if(read_vaddr + sizeof(inst_byte) <= read_vaddr_opl)
{
inst_byte_good = ctrl_read_cached_process_memory_struct(process->handle, read_vaddr, &is_stale, &inst_byte, endt_us);
inst_byte_good = ctrl_process_memory_read_struct(process->handle, read_vaddr, &is_stale, &inst_byte, endt_us);
}
if(!inst_byte_good || is_stale)
{
@@ -2391,7 +2375,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
check_vaddr = read_vaddr + 1;
if(read_vaddr + sizeof(check_inst_byte) <= read_vaddr_opl)
{
check_inst_byte_good = ctrl_read_cached_process_memory_struct(process->handle, read_vaddr, &is_stale, &check_inst_byte, endt_us);
check_inst_byte_good = ctrl_process_memory_read_struct(process->handle, read_vaddr, &is_stale, &check_inst_byte, endt_us);
}
if(!check_inst_byte_good || is_stale)
{
@@ -2427,7 +2411,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
B32 imm_good = 0;
if(read_vaddr + sizeof(imm) <= read_vaddr_opl)
{
imm_good = ctrl_read_cached_process_memory_struct(process->handle, read_vaddr, &is_stale, &imm, endt_us);
imm_good = ctrl_process_memory_read_struct(process->handle, read_vaddr, &is_stale, &imm, endt_us);
}
if(!imm_good || is_stale)
{
@@ -2456,7 +2440,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
B32 next_inst_byte_good = 0;
if(read_vaddr + sizeof(next_inst_byte) <= read_vaddr_opl)
{
next_inst_byte_good = ctrl_read_cached_process_memory_struct(process->handle, read_vaddr, &is_stale, &next_inst_byte, endt_us);
next_inst_byte_good = ctrl_process_memory_read_struct(process->handle, read_vaddr, &is_stale, &next_inst_byte, endt_us);
}
if(next_inst_byte_good)
{
@@ -2485,7 +2469,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
//- rjf: read next instruction byte
U8 inst_byte = 0;
is_good = is_good && ctrl_read_cached_process_memory_struct(process->handle, read_vaddr, &is_stale, &inst_byte, endt_us);
is_good = is_good && ctrl_process_memory_read_struct(process->handle, read_vaddr, &is_stale, &inst_byte, endt_us);
is_good = is_good && !is_stale;
read_vaddr += 1;
@@ -2494,7 +2478,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
if((inst_byte & 0xF0) == 0x40)
{
rex = inst_byte & 0xF; // rex prefix
is_good = is_good && ctrl_read_cached_process_memory_struct(process->handle, read_vaddr, &is_stale, &inst_byte, endt_us);
is_good = is_good && ctrl_process_memory_read_struct(process->handle, read_vaddr, &is_stale, &inst_byte, endt_us);
is_good = is_good && !is_stale;
read_vaddr += 1;
}
@@ -2515,7 +2499,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
// rjf: read value at rsp
U64 sp = regs->rsp.u64;
U64 value = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, sp, &is_stale, &value, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, sp, &is_stale, &value, endt_us) ||
is_stale)
{
is_good = 0;
@@ -2540,7 +2524,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
// rjf: read the 4-byte immediate
S32 imm = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, read_vaddr, &is_stale, &imm, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, read_vaddr, &is_stale, &imm, endt_us) ||
is_stale)
{
is_good = 0;
@@ -2563,7 +2547,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
// rjf: read the 4-byte immediate
S8 imm = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, read_vaddr, &is_stale, &imm, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, read_vaddr, &is_stale, &imm, endt_us) ||
is_stale)
{
is_good = 0;
@@ -2583,7 +2567,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
{
// rjf: read source register
U8 modrm = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, read_vaddr, &is_stale, &modrm, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, read_vaddr, &is_stale, &modrm, endt_us) ||
is_stale)
{
is_good = 0;
@@ -2601,7 +2585,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
if((modrm >> 6) == 1)
{
S8 imm8 = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, read_vaddr, &is_stale, &imm8, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, read_vaddr, &is_stale, &imm8, endt_us) ||
is_stale)
{
is_good = 0;
@@ -2614,7 +2598,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
// rjf: read 4-byte immediate
else
{
if(!ctrl_read_cached_process_memory_struct(process->handle, read_vaddr, &is_stale, &imm, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, read_vaddr, &is_stale, &imm, endt_us) ||
is_stale)
{
is_good = 0;
@@ -2637,7 +2621,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
// rjf: read new ip
U64 sp = regs->rsp.u64;
U64 new_ip = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, sp, &is_stale, &new_ip, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, sp, &is_stale, &new_ip, endt_us) ||
is_stale)
{
is_good = 0;
@@ -2646,7 +2630,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
// rjf: read 2-byte immediate & advance stack pointer
U16 imm = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, read_vaddr, &is_stale, &imm, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, read_vaddr, &is_stale, &imm, endt_us) ||
is_stale)
{
is_good = 0;
@@ -2669,7 +2653,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
// rjf: read new ip
U64 sp = regs->rsp.u64;
U64 new_ip = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, sp, &is_stale, &new_ip, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, sp, &is_stale, &new_ip, endt_us) ||
is_stale)
{
is_good = 0;
@@ -2716,7 +2700,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
{
U64 unwind_info_off = first_pdata->voff_unwind_info;
PE_UnwindInfo unwind_info = {0};
if(!ctrl_read_cached_process_memory_struct(process->handle, module->vaddr_range.min+unwind_info_off, &is_stale, &unwind_info, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, module->vaddr_range.min+unwind_info_off, &is_stale, &unwind_info, endt_us) ||
is_stale)
{
is_good = 0;
@@ -2740,11 +2724,11 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
B32 good_unwind_info = 1;
U64 unwind_info_off = pdata->voff_unwind_info;
PE_UnwindInfo unwind_info = {0};
good_unwind_info = good_unwind_info && ctrl_read_cached_process_memory_struct(process->handle, module->vaddr_range.min+unwind_info_off, &is_stale, &unwind_info, endt_us);
good_unwind_info = good_unwind_info && ctrl_process_memory_read_struct(process->handle, module->vaddr_range.min+unwind_info_off, &is_stale, &unwind_info, endt_us);
PE_UnwindCode *unwind_codes = push_array(scratch.arena, PE_UnwindCode, unwind_info.codes_num);
good_unwind_info = good_unwind_info && ctrl_read_cached_process_memory(process->handle, r1u64(module->vaddr_range.min+unwind_info_off+sizeof(unwind_info),
module->vaddr_range.min+unwind_info_off+sizeof(unwind_info)+sizeof(PE_UnwindCode)*unwind_info.codes_num),
&is_stale, unwind_codes, endt_us);
good_unwind_info = good_unwind_info && ctrl_process_memory_read(process->handle, r1u64(module->vaddr_range.min+unwind_info_off+sizeof(unwind_info),
module->vaddr_range.min+unwind_info_off+sizeof(unwind_info)+sizeof(PE_UnwindCode)*unwind_info.codes_num),
&is_stale, unwind_codes, endt_us);
good_unwind_info = good_unwind_info && !is_stale;
//- rjf: bad unwind info -> abort
@@ -2799,7 +2783,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
// rjf: read value from stack pointer
U64 rsp = regs->rsp.u64;
U64 value = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, rsp, &is_stale, &value, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, rsp, &is_stale, &value, endt_us) ||
is_stale)
{
keep_parsing = 0;
@@ -2861,7 +2845,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
U64 off = code_ptr[1].u16*8;
U64 addr = frame_base + off;
U64 value = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, addr, &is_stale, &value, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, addr, &is_stale, &value, endt_us) ||
is_stale)
{
keep_parsing = 0;
@@ -2880,7 +2864,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
U64 off = code_ptr[1].u16 + ((U32)code_ptr[2].u16 << 16);
U64 addr = frame_base + off;
U64 value = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, addr, &is_stale, &value, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, addr, &is_stale, &value, endt_us) ||
is_stale)
{
keep_parsing = 0;
@@ -2911,7 +2895,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
U8 buf[16];
U64 off = code_ptr[1].u16*16;
U64 addr = frame_base + off;
if(!ctrl_read_cached_process_memory(process->handle, r1u64(addr, addr+sizeof(buf)), &is_stale, buf, endt_us))
if(!ctrl_process_memory_read(process->handle, r1u64(addr, addr+sizeof(buf)), &is_stale, buf, endt_us))
{
keep_parsing = 0;
is_good = 0;
@@ -2929,7 +2913,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
U8 buf[16];
U64 off = code_ptr[1].u16 + ((U32)code_ptr[2].u16 << 16);
U64 addr = frame_base + off;
if(!ctrl_read_cached_process_memory(process->handle, r1u64(addr, addr+16), &is_stale, buf, endt_us) ||
if(!ctrl_process_memory_read(process->handle, r1u64(addr, addr+16), &is_stale, buf, endt_us) ||
is_stale)
{
keep_parsing = 0;
@@ -2961,7 +2945,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
sp_adj += 8;
}
U64 ip_value = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, sp_adj, &is_stale, &ip_value, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, sp_adj, &is_stale, &ip_value, endt_us) ||
is_stale)
{
keep_parsing = 0;
@@ -2970,7 +2954,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
}
U64 sp_after_ip = sp_adj + 8;
U16 ss_value = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, sp_after_ip, &is_stale, &ss_value, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, sp_after_ip, &is_stale, &ss_value, endt_us) ||
is_stale)
{
keep_parsing = 0;
@@ -2979,7 +2963,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
}
U64 sp_after_ss = sp_after_ip + 8;
U64 rflags_value = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, sp_after_ss, &is_stale, &rflags_value, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, sp_after_ss, &is_stale, &rflags_value, endt_us) ||
is_stale)
{
keep_parsing = 0;
@@ -2988,7 +2972,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
}
U64 sp_after_rflags = sp_after_ss + 8;
U64 sp_value = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, sp_after_rflags, &is_stale, &sp_value, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, sp_after_rflags, &is_stale, &sp_value, endt_us) ||
is_stale)
{
keep_parsing = 0;
@@ -3022,7 +3006,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
U64 chained_pdata_off = unwind_info_off + sizeof(PE_UnwindInfo) + code_size;
last_pdata = pdata;
pdata = push_array(scratch.arena, PE_IntelPdata, 1);
if(!ctrl_read_cached_process_memory_struct(process->handle, module->vaddr_range.min+chained_pdata_off, &is_stale, pdata, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, module->vaddr_range.min+chained_pdata_off, &is_stale, pdata, endt_us) ||
is_stale)
{
is_good = 0;
@@ -3040,7 +3024,7 @@ ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CT
// rjf: read rip from stack pointer
U64 rsp = regs->rsp.u64;
U64 new_rip = 0;
if(!ctrl_read_cached_process_memory_struct(process->handle, rsp, &is_stale, &new_rip, endt_us) ||
if(!ctrl_process_memory_read_struct(process->handle, rsp, &is_stale, &new_rip, endt_us) ||
is_stale)
{
is_good = 0;
@@ -3099,7 +3083,7 @@ ctrl_unwind_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_Handle threa
U64 arch_reg_block_size = regs_block_size_from_arch(arch);
//- rjf: grab initial register block
void *regs_block = ctrl_query_cached_reg_block_from_thread(scratch.arena, store, thread);
void *regs_block = ctrl_reg_block_from_thread(scratch.arena, store, thread);
B32 regs_block_good = (arch != Arch_Null && regs_block != 0);
//- rjf: loop & unwind
@@ -4724,7 +4708,7 @@ ctrl_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range)
{
Temp scratch = scratch_begin(0, 0);
U64 regs_size = regs_block_size_from_arch(entity->arch);
void *regs = ctrl_query_cached_reg_block_from_thread(scratch.arena, ctrl_state->ctrl_thread_entity_store, entity->handle);
void *regs = ctrl_reg_block_from_thread(scratch.arena, ctrl_state->ctrl_thread_entity_store, entity->handle);
Rng1U64 legal_range = r1u64(0, regs_size);
Rng1U64 read_range = intersect_1u64(legal_range, range);
U64 read_size = dim_1u64(read_range);
+46 -8
View File
@@ -593,6 +593,44 @@ struct CTRL_ThreadRegCache
CTRL_ThreadRegCacheStripe *stripes;
};
////////////////////////////////
//~ rjf: Thread Unwind Cache Types
typedef struct CTRL_ThreadUnwindCacheNode CTRL_ThreadUnwindCacheNode;
struct CTRL_ThreadUnwindCacheNode
{
CTRL_ThreadUnwindCacheNode *next;
CTRL_ThreadUnwindCacheNode *prev;
Arena *arena;
CTRL_Handle thread;
U64 reg_gen;
U64 mem_gen;
CTRL_Unwind unwind;
};
typedef struct CTRL_ThreadUnwindCacheSlot CTRL_ThreadUnwindCacheSlot;
struct CTRL_ThreadUnwindCacheSlot
{
CTRL_ThreadUnwindCacheNode *first;
CTRL_ThreadUnwindCacheNode *last;
};
typedef struct CTRL_ThreadUnwindCacheStripe CTRL_ThreadUnwindCacheStripe;
struct CTRL_ThreadUnwindCacheStripe
{
Arena *arena;
OS_Handle rw_mutex;
};
typedef struct CTRL_ThreadUnwindCache CTRL_ThreadUnwindCache;
struct CTRL_ThreadUnwindCache
{
U64 slots_count;
CTRL_ThreadUnwindCacheSlot *slots;
U64 stripes_count;
CTRL_ThreadUnwindCacheStripe *stripes;
};
////////////////////////////////
//~ rjf: Module Image Info Cache Types
@@ -686,6 +724,7 @@ struct CTRL_State
// rjf: caches
CTRL_ProcessMemoryCache process_memory_cache;
CTRL_ThreadRegCache thread_reg_cache;
CTRL_ThreadUnwindCache thread_unwind_cache;
CTRL_ModuleImageInfoCache module_image_info_cache;
// rjf: user -> ctrl msg ring buffer
@@ -885,10 +924,9 @@ internal U128 ctrl_stored_hash_from_process_vaddr_range(CTRL_Handle process, Rng
internal U128 ctrl_hash_store_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B32 zero_terminated);
//- rjf: process memory cache reading helpers
internal CTRL_ProcessMemorySlice ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_Handle process, Rng1U64 range, U64 endt_us);
internal CTRL_ProcessMemorySlice ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_Handle process, U64 vaddr, U64 limit, U64 element_size, U64 endt_us);
internal B32 ctrl_read_cached_process_memory(CTRL_Handle process, Rng1U64 range, B32 *is_stale_out, void *out, U64 endt_us);
#define ctrl_read_cached_process_memory_struct(process, vaddr, is_stale_out, ptr, endt_us) ctrl_read_cached_process_memory((process), r1u64((vaddr), (vaddr)+(sizeof(*(ptr)))), (is_stale_out), (ptr), (endt_us))
internal CTRL_ProcessMemorySlice ctrl_process_memory_slice_from_vaddr_range(Arena *arena, CTRL_Handle process, Rng1U64 range, U64 endt_us);
internal B32 ctrl_process_memory_read(CTRL_Handle process, Rng1U64 range, B32 *is_stale_out, void *out, U64 endt_us);
#define ctrl_process_memory_read_struct(process, vaddr, is_stale_out, ptr, endt_us) ctrl_process_memory_read((process), r1u64((vaddr), (vaddr)+(sizeof(*(ptr)))), (is_stale_out), (ptr), (endt_us))
//- rjf: process memory writing
internal B32 ctrl_process_write(CTRL_Handle process, Rng1U64 range, void *src);
@@ -897,10 +935,10 @@ internal B32 ctrl_process_write(CTRL_Handle process, Rng1U64 range, void *src);
//~ rjf: Thread Register Functions
//- rjf: thread register cache reading
internal void *ctrl_query_cached_reg_block_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_Handle handle);
internal U64 ctrl_query_cached_tls_root_vaddr_from_thread(CTRL_EntityStore *store, CTRL_Handle handle);
internal U64 ctrl_query_cached_rip_from_thread(CTRL_EntityStore *store, CTRL_Handle handle);
internal U64 ctrl_query_cached_rsp_from_thread(CTRL_EntityStore *store, CTRL_Handle handle);
internal void *ctrl_reg_block_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_Handle handle);
internal U64 ctrl_tls_root_vaddr_from_thread(CTRL_EntityStore *store, CTRL_Handle handle);
internal U64 ctrl_rip_from_thread(CTRL_EntityStore *store, CTRL_Handle handle);
internal U64 ctrl_rsp_from_thread(CTRL_EntityStore *store, CTRL_Handle handle);
//- rjf: thread register writing
internal B32 ctrl_thread_write_reg_block(CTRL_Handle thread, void *block);
+11 -11
View File
@@ -300,13 +300,13 @@ d_trap_net_from_thread__step_over_inst(Arena *arena, CTRL_Entity *thread)
// rjf: thread => unpacked info
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process);
Arch arch = thread->arch;
U64 ip_vaddr = ctrl_query_cached_rip_from_thread(d_state->ctrl_entity_store, thread->handle);
U64 ip_vaddr = ctrl_rip_from_thread(d_state->ctrl_entity_store, thread->handle);
// rjf: ip => machine code
String8 machine_code = {0};
{
Rng1U64 rng = r1u64(ip_vaddr, ip_vaddr+max_instruction_size_from_arch(arch));
CTRL_ProcessMemorySlice machine_code_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->handle, rng, os_now_microseconds()+5000);
CTRL_ProcessMemorySlice machine_code_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, rng, os_now_microseconds()+5000);
machine_code = machine_code_slice.data;
}
@@ -337,7 +337,7 @@ d_trap_net_from_thread__step_over_line(Arena *arena, CTRL_Entity *thread)
// rjf: thread => info
Arch arch = thread->arch;
U64 ip_vaddr = ctrl_query_cached_rip_from_thread(d_state->ctrl_entity_store, thread->handle);
U64 ip_vaddr = ctrl_rip_from_thread(d_state->ctrl_entity_store, thread->handle);
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process);
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, ip_vaddr);
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
@@ -380,7 +380,7 @@ d_trap_net_from_thread__step_over_line(Arena *arena, CTRL_Entity *thread)
String8 machine_code = {0};
if(good_line_info)
{
CTRL_ProcessMemorySlice machine_code_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->handle, line_vaddr_rng, os_now_microseconds()+50000);
CTRL_ProcessMemorySlice machine_code_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, line_vaddr_rng, os_now_microseconds()+50000);
machine_code = machine_code_slice.data;
LogInfoNamedBlockF("machine_code_slice")
{
@@ -498,7 +498,7 @@ d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread)
// rjf: thread => info
Arch arch = thread->arch;
U64 ip_vaddr = ctrl_query_cached_rip_from_thread(d_state->ctrl_entity_store, thread->handle);
U64 ip_vaddr = ctrl_rip_from_thread(d_state->ctrl_entity_store, thread->handle);
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process);
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, ip_vaddr);
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
@@ -536,7 +536,7 @@ d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread)
String8 machine_code = {0};
if(good_line_info)
{
CTRL_ProcessMemorySlice machine_code_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->handle, line_vaddr_rng, os_now_microseconds()+5000);
CTRL_ProcessMemorySlice machine_code_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, line_vaddr_rng, os_now_microseconds()+5000);
machine_code = machine_code_slice.data;
}
@@ -1073,7 +1073,7 @@ d_tls_base_vaddr_from_process_root_rip(CTRL_Entity *process, U64 root_vaddr, U64
U64 tls_index = 0;
if(addr_size != 0)
{
CTRL_ProcessMemorySlice tls_index_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->handle, tls_vaddr_range, 0);
CTRL_ProcessMemorySlice tls_index_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, tls_vaddr_range, 0);
if(tls_index_slice.data.size >= addr_size)
{
tls_index = *(U64 *)tls_index_slice.data.str;
@@ -1086,13 +1086,13 @@ d_tls_base_vaddr_from_process_root_rip(CTRL_Entity *process, U64 root_vaddr, U64
U64 thread_info_addr = root_vaddr;
U64 tls_addr_off = tls_index*addr_size;
U64 tls_addr_array = 0;
CTRL_ProcessMemorySlice tls_addr_array_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->handle, r1u64(thread_info_addr, thread_info_addr+addr_size), 0);
CTRL_ProcessMemorySlice tls_addr_array_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, r1u64(thread_info_addr, thread_info_addr+addr_size), 0);
String8 tls_addr_array_data = tls_addr_array_slice.data;
if(tls_addr_array_data.size >= 8)
{
MemoryCopy(&tls_addr_array, tls_addr_array_data.str, sizeof(U64));
}
CTRL_ProcessMemorySlice result_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->handle, r1u64(tls_addr_array + tls_addr_off, tls_addr_array + tls_addr_off + addr_size), 0);
CTRL_ProcessMemorySlice result_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, r1u64(tls_addr_array + tls_addr_off, tls_addr_array + tls_addr_off + addr_size), 0);
String8 result_data = result_slice.data;
if(result_data.size >= 8)
{
@@ -1267,7 +1267,7 @@ d_query_cached_rip_from_thread_unwind(CTRL_Entity *thread, U64 unwind_count)
U64 result = 0;
if(unwind_count == 0)
{
result = ctrl_query_cached_rip_from_thread(d_state->ctrl_entity_store, thread->handle);
result = ctrl_rip_from_thread(d_state->ctrl_entity_store, thread->handle);
}
else
{
@@ -2020,7 +2020,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
{
CTRL_Entity *thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, params->thread);
U64 vaddr = params->vaddr;
void *block = ctrl_query_cached_reg_block_from_thread(scratch.arena, d_state->ctrl_entity_store, thread->handle);
void *block = ctrl_reg_block_from_thread(scratch.arena, d_state->ctrl_entity_store, thread->handle);
regs_arch_block_write_rip(thread->arch, block, vaddr);
B32 result = ctrl_thread_write_reg_block(thread->handle, block);
+6 -6
View File
@@ -1805,7 +1805,7 @@ rd_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range)
default:{}break;
case CTRL_EntityKind_Process:
{
CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, entity->handle, range, rd_state->frame_eval_memread_endt_us);
CTRL_ProcessMemorySlice slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, entity->handle, range, rd_state->frame_eval_memread_endt_us);
String8 data = slice.data;
if(data.size == dim_1u64(range))
{
@@ -2021,7 +2021,7 @@ rd_eval_space_write(void *u, 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 = ctrl_query_cached_reg_block_from_thread(scratch.arena, d_state->ctrl_entity_store, entity->handle);
void *new_regs = ctrl_reg_block_from_thread(scratch.arena, d_state->ctrl_entity_store, entity->handle);
MemoryCopy((U8 *)new_regs + write_range.min, in, write_size);
result = ctrl_thread_write_reg_block(entity->handle, new_regs);
scratch_end(scratch);
@@ -4508,7 +4508,7 @@ rd_view_ui(Rng2F32 rect)
U64 size = e_type_byte_size_from_key(row->eval.irtree.type_key);
size = Min(size, 64);
Rng1U64 vaddr_rng = r1u64(row->eval.value.u64, row->eval.value.u64+size);
CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, space_entity->handle, vaddr_rng, rd_state->frame_eval_memread_endt_us);
CTRL_ProcessMemorySlice slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, space_entity->handle, vaddr_rng, rd_state->frame_eval_memread_endt_us);
for(U64 idx = 0; idx < (slice.data.size+63)/64; idx += 1)
{
if(slice.byte_changed_flags[idx] != 0)
@@ -11644,7 +11644,7 @@ rd_frame(void)
CTRL_Unwind unwind = d_query_cached_unwind_from_thread(thread);
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr);
U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr);
U64 tls_root_vaddr = ctrl_query_cached_tls_root_vaddr_from_thread(d_state->ctrl_entity_store, thread->handle);
U64 tls_root_vaddr = ctrl_tls_root_vaddr_from_thread(d_state->ctrl_entity_store, thread->handle);
CTRL_EntityArray all_modules = ctrl_entity_array_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Module);
U64 eval_modules_count = Max(1, all_modules.count);
E_Module *eval_modules = push_array(scratch.arena, E_Module, eval_modules_count);
@@ -15650,7 +15650,7 @@ rd_frame(void)
{
CTRL_Entity *thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->thread);
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process);
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, ctrl_query_cached_rip_from_thread(d_state->ctrl_entity_store, thread->handle));
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, ctrl_rip_from_thread(d_state->ctrl_entity_store, thread->handle));
CTRL_Entity *machine = ctrl_entity_ancestor_from_kind(process, CTRL_EntityKind_Machine);
rd_state->base_regs.v.unwind_count = 0;
rd_state->base_regs.v.inline_depth = 0;
@@ -16423,7 +16423,7 @@ rd_frame(void)
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, vaddr);
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
U64 voff = ctrl_voff_from_vaddr(module, vaddr);
U64 test_cached_vaddr = ctrl_query_cached_rip_from_thread(d_state->ctrl_entity_store, thread->handle);
U64 test_cached_vaddr = ctrl_rip_from_thread(d_state->ctrl_entity_store, thread->handle);
// rjf: valid stop thread? -> select & snap
if(need_refocus && thread != &ctrl_entity_nil && evt->cause != D_EventCause_Halt)