diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index e201843a..6b14633f 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -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); diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index 4c33c20d..5304759e 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -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); diff --git a/src/dbg_engine/dbg_engine_core.c b/src/dbg_engine/dbg_engine_core.c index f8b15ef2..a28216d9 100644 --- a/src/dbg_engine/dbg_engine_core.c +++ b/src/dbg_engine/dbg_engine_core.c @@ -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); diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 292988ab..5f550abc 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -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)