mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
lift wait-for-process-memory-cache-update out of d_process_write, since that path runs on control thread now too as the general 'process handle write' abstraction - just move into the rd_eval_space_write path, since that wait was only for UI benefit anyways
This commit is contained in:
@@ -14,12 +14,14 @@ arch_info_from_arch(Arch arch)
|
|||||||
#if defined(X64_H)
|
#if defined(X64_H)
|
||||||
case Arch_x64:
|
case Arch_x64:
|
||||||
{
|
{
|
||||||
|
local_persist U8 trap_inst_bytes[] = {0xcc};
|
||||||
local_persist read_only ARCH_Info info =
|
local_persist read_only ARCH_Info info =
|
||||||
{
|
{
|
||||||
.reg_block_size = sizeof(X64_RegBlock),
|
.reg_block_size = sizeof(X64_RegBlock),
|
||||||
.instruction_pointer_reg_code = X64_RegCode_rip,
|
.instruction_pointer_reg_code = X64_RegCode_rip,
|
||||||
.stack_pointer_reg_code = X64_RegCode_rsp,
|
.stack_pointer_reg_code = X64_RegCode_rsp,
|
||||||
.reg_code_count = X64_RegCode_COUNT,
|
.reg_code_count = X64_RegCode_COUNT,
|
||||||
|
.trap_instruction = {trap_inst_bytes, sizeof(trap_inst_bytes)},
|
||||||
.reg_code_rng_table = x64_reg_code_rng_table,
|
.reg_code_rng_table = x64_reg_code_rng_table,
|
||||||
.reg_code_name_table = x64_reg_code_name_table,
|
.reg_code_name_table = x64_reg_code_name_table,
|
||||||
.reg_code_base_table = x64_reg_code_base_table,
|
.reg_code_base_table = x64_reg_code_base_table,
|
||||||
|
|||||||
+2
-1
@@ -16,6 +16,7 @@ struct ARCH_Info
|
|||||||
ARCH_RegCode instruction_pointer_reg_code;
|
ARCH_RegCode instruction_pointer_reg_code;
|
||||||
ARCH_RegCode stack_pointer_reg_code;
|
ARCH_RegCode stack_pointer_reg_code;
|
||||||
U16 reg_code_count;
|
U16 reg_code_count;
|
||||||
|
String8 trap_instruction;
|
||||||
Rng1U16 *reg_code_rng_table;
|
Rng1U16 *reg_code_rng_table;
|
||||||
String8 *reg_code_name_table;
|
String8 *reg_code_name_table;
|
||||||
U8 *reg_code_base_table;
|
U8 *reg_code_base_table;
|
||||||
@@ -29,7 +30,7 @@ global read_only Rng1U16 arch_reg_code_rng_nil = {0};
|
|||||||
global read_only String8 arch_reg_code_name_nil = {0};
|
global read_only String8 arch_reg_code_name_nil = {0};
|
||||||
global read_only U8 arch_reg_code_u8_nil = 0;
|
global read_only U8 arch_reg_code_u8_nil = 0;
|
||||||
global read_only B8 arch_reg_code_b8_nil = 0;
|
global read_only B8 arch_reg_code_b8_nil = 0;
|
||||||
global read_only ARCH_Info arch_info_nil = {0, 0, 0, 0, &arch_reg_code_rng_nil, &arch_reg_code_name_nil, &arch_reg_code_u8_nil, &arch_reg_code_b8_nil};
|
global read_only ARCH_Info arch_info_nil = {0, 0, 0, 0, {0}, &arch_reg_code_rng_nil, &arch_reg_code_name_nil, &arch_reg_code_u8_nil, &arch_reg_code_b8_nil};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Abstracted Architecture Functions
|
//~ rjf: Abstracted Architecture Functions
|
||||||
|
|||||||
@@ -845,7 +845,7 @@ internal D_Entity *
|
|||||||
d_module_from_thread_candidates(D_Entity *thread, D_EntityList *candidates)
|
d_module_from_thread_candidates(D_Entity *thread, D_EntityList *candidates)
|
||||||
{
|
{
|
||||||
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||||
U64 thread_rip_vaddr = d_rip_from_thread(thread->handle);
|
U64 thread_rip_vaddr = d_cached_ip_from_thread(thread->handle);
|
||||||
D_Entity *src_module = d_module_from_process_vaddr(process, thread_rip_vaddr);
|
D_Entity *src_module = d_module_from_process_vaddr(process, thread_rip_vaddr);
|
||||||
D_Entity *module = &d_entity_nil;
|
D_Entity *module = &d_entity_nil;
|
||||||
for(D_EntityNode *n = candidates->first; n != 0; n = n->next)
|
for(D_EntityNode *n = candidates->first; n != 0; n = n->next)
|
||||||
@@ -1357,7 +1357,7 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list)
|
|||||||
}
|
}
|
||||||
thread->stack_base = event->stack_base;
|
thread->stack_base = event->stack_base;
|
||||||
}
|
}
|
||||||
//d_rip_from_thread(&store->ctx, event->entity);
|
//d_cached_ip_from_thread(&store->ctx, event->entity);
|
||||||
}break;
|
}break;
|
||||||
case D_EventKind_EndThread:
|
case D_EventKind_EndThread:
|
||||||
{
|
{
|
||||||
@@ -1595,10 +1595,46 @@ d_thread_write_reg_block(D_Handle thread, void *block)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
d_ip_from_thread(D_Handle handle)
|
||||||
|
{
|
||||||
|
U64 result = 0;
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
D_Entity *thread = d_entity_from_handle(handle);
|
||||||
|
Arch arch = thread->arch;
|
||||||
|
ARCH_Info *arch_info = arch_info_from_arch(arch);
|
||||||
|
U64 reg_block_size = arch_info->reg_block_size;
|
||||||
|
void *reg_block = push_array(scratch.arena, U8, reg_block_size);
|
||||||
|
if(d_thread_read_reg_block(handle, reg_block))
|
||||||
|
{
|
||||||
|
result = arch_ip_from_reg_block(arch_info, reg_block);
|
||||||
|
}
|
||||||
|
scratch_end(scratch);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
d_sp_from_thread(D_Handle handle)
|
||||||
|
{
|
||||||
|
U64 result = 0;
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
D_Entity *thread = d_entity_from_handle(handle);
|
||||||
|
Arch arch = thread->arch;
|
||||||
|
ARCH_Info *arch_info = arch_info_from_arch(arch);
|
||||||
|
U64 reg_block_size = arch_info->reg_block_size;
|
||||||
|
void *reg_block = push_array(scratch.arena, U8, reg_block_size);
|
||||||
|
if(d_thread_read_reg_block(handle, reg_block))
|
||||||
|
{
|
||||||
|
result = arch_sp_from_reg_block(arch_info, reg_block);
|
||||||
|
}
|
||||||
|
scratch_end(scratch);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
//- rjf: thread register cache reading
|
//- rjf: thread register cache reading
|
||||||
|
|
||||||
internal void *
|
internal void *
|
||||||
d_reg_block_from_thread(Arena *arena, D_Handle handle)
|
d_cached_reg_block_from_thread(Arena *arena, D_Handle handle)
|
||||||
{
|
{
|
||||||
D_ThreadRegCache *cache = &d_ctrl_state->thread_reg_cache;
|
D_ThreadRegCache *cache = &d_ctrl_state->thread_reg_cache;
|
||||||
D_Entity *thread_entity = d_entity_from_handle(handle);
|
D_Entity *thread_entity = d_entity_from_handle(handle);
|
||||||
@@ -1658,7 +1694,7 @@ d_reg_block_from_thread(Arena *arena, D_Handle handle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal U64
|
internal U64
|
||||||
d_tls_root_vaddr_from_thread(D_Handle handle)
|
d_cached_tls_root_vaddr_from_thread(D_Handle handle)
|
||||||
{
|
{
|
||||||
DMN_Handle handle_dmn = d_dmn_from_handle(handle);
|
DMN_Handle handle_dmn = d_dmn_from_handle(handle);
|
||||||
U64 result = dmn_tls_root_vaddr_from_thread(handle_dmn);
|
U64 result = dmn_tls_root_vaddr_from_thread(handle_dmn);
|
||||||
@@ -1666,26 +1702,26 @@ d_tls_root_vaddr_from_thread(D_Handle handle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal U64
|
internal U64
|
||||||
d_rip_from_thread(D_Handle handle)
|
d_cached_ip_from_thread(D_Handle handle)
|
||||||
{
|
{
|
||||||
Temp scratch = scratch_begin(0, 0);
|
Temp scratch = scratch_begin(0, 0);
|
||||||
D_Entity *thread_entity = d_entity_from_handle(handle);
|
D_Entity *thread_entity = d_entity_from_handle(handle);
|
||||||
Arch arch = thread_entity->arch;
|
Arch arch = thread_entity->arch;
|
||||||
ARCH_Info *arch_info = arch_info_from_arch(arch);
|
ARCH_Info *arch_info = arch_info_from_arch(arch);
|
||||||
void *block = d_reg_block_from_thread(scratch.arena, handle);
|
void *block = d_cached_reg_block_from_thread(scratch.arena, handle);
|
||||||
U64 result = arch_ip_from_reg_block(arch_info, block);
|
U64 result = arch_ip_from_reg_block(arch_info, block);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal U64
|
internal U64
|
||||||
d_rsp_from_thread(D_Handle handle)
|
d_cached_sp_from_thread(D_Handle handle)
|
||||||
{
|
{
|
||||||
Temp scratch = scratch_begin(0, 0);
|
Temp scratch = scratch_begin(0, 0);
|
||||||
D_Entity *thread_entity = d_entity_from_handle(handle);
|
D_Entity *thread_entity = d_entity_from_handle(handle);
|
||||||
Arch arch = thread_entity->arch;
|
Arch arch = thread_entity->arch;
|
||||||
ARCH_Info *arch_info = arch_info_from_arch(arch);
|
ARCH_Info *arch_info = arch_info_from_arch(arch);
|
||||||
void *block = d_reg_block_from_thread(scratch.arena, handle);
|
void *block = d_cached_reg_block_from_thread(scratch.arena, handle);
|
||||||
U64 result = arch_sp_from_reg_block(arch_info, block);
|
U64 result = arch_sp_from_reg_block(arch_info, block);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
return result;
|
return result;
|
||||||
@@ -2978,7 +3014,7 @@ d_unwind_from_thread(Arena *arena, D_Handle thread, U64 endt_us)
|
|||||||
U64 arch_reg_block_size = arch_info->reg_block_size;
|
U64 arch_reg_block_size = arch_info->reg_block_size;
|
||||||
|
|
||||||
//- rjf: grab initial register block
|
//- rjf: grab initial register block
|
||||||
void *regs_block = d_reg_block_from_thread(scratch.arena, thread);
|
void *regs_block = d_cached_reg_block_from_thread(scratch.arena, thread);
|
||||||
B32 regs_block_good = (arch != Arch_Null && regs_block != 0);
|
B32 regs_block_good = (arch != Arch_Null && regs_block != 0);
|
||||||
|
|
||||||
//- rjf: loop & unwind
|
//- rjf: loop & unwind
|
||||||
@@ -3572,7 +3608,7 @@ d_ctrl_thread__entry_point(void *p)
|
|||||||
for EachIndex(idx, threads.count)
|
for EachIndex(idx, threads.count)
|
||||||
{
|
{
|
||||||
Temp scratch = scratch_begin(0, 0);
|
Temp scratch = scratch_begin(0, 0);
|
||||||
d_reg_block_from_thread(scratch.arena, threads.v[idx]->handle);
|
d_cached_reg_block_from_thread(scratch.arena, threads.v[idx]->handle);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4715,7 +4751,7 @@ d_ctrl_eval_space_read(E_Space space, void *out, E_SpaceRangeInfo *out_range_inf
|
|||||||
Temp scratch = scratch_begin(0, 0);
|
Temp scratch = scratch_begin(0, 0);
|
||||||
ARCH_Info *arch_info = arch_info_from_arch(entity->arch);
|
ARCH_Info *arch_info = arch_info_from_arch(entity->arch);
|
||||||
U64 regs_size = arch_info->reg_block_size;
|
U64 regs_size = arch_info->reg_block_size;
|
||||||
void *regs = d_reg_block_from_thread(scratch.arena, entity->handle);
|
void *regs = d_cached_reg_block_from_thread(scratch.arena, entity->handle);
|
||||||
Rng1U64 legal_range = r1u64(0, regs_size);
|
Rng1U64 legal_range = r1u64(0, regs_size);
|
||||||
Rng1U64 read_range = intersect_1u64(legal_range, range);
|
Rng1U64 read_range = intersect_1u64(legal_range, range);
|
||||||
U64 read_size = dim_1u64(read_range);
|
U64 read_size = dim_1u64(read_range);
|
||||||
@@ -4737,14 +4773,13 @@ d_ctrl_thread__eval_scope_begin(Arena *arena, D_BreakpointList *user_bps, D_Enti
|
|||||||
ProfBeginFunction();
|
ProfBeginFunction();
|
||||||
D_EntityCtx *entity_ctx = &d_ctrl_state->ctrl_thread_entity_store->ctx;
|
D_EntityCtx *entity_ctx = &d_ctrl_state->ctrl_thread_entity_store->ctx;
|
||||||
D_EvalScope *scope = push_array(arena, D_EvalScope, 1);
|
D_EvalScope *scope = push_array(arena, D_EvalScope, 1);
|
||||||
DMN_Handle thread_dmn = d_dmn_from_handle(thread->handle);
|
|
||||||
scope->access = access_open();
|
scope->access = access_open();
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- rjf: unpack thread
|
//- rjf: unpack thread
|
||||||
//
|
//
|
||||||
Arch arch = thread->arch;
|
Arch arch = thread->arch;
|
||||||
U64 thread_rip_vaddr = dmn_rip_from_thread(thread_dmn);
|
U64 thread_rip_vaddr = d_ip_from_thread(thread->handle);
|
||||||
D_Entity *process = d_process_from_entity(thread);
|
D_Entity *process = d_process_from_entity(thread);
|
||||||
D_Entity *module = d_module_from_process_vaddr(process, thread_rip_vaddr);
|
D_Entity *module = d_module_from_process_vaddr(process, thread_rip_vaddr);
|
||||||
U64 thread_rip_voff = d_voff_from_vaddr(module, thread_rip_vaddr);
|
U64 thread_rip_voff = d_voff_from_vaddr(module, thread_rip_vaddr);
|
||||||
@@ -5709,7 +5744,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
|
|||||||
// threads, because otherwise, their stack pointer may change, if single-stepping
|
// threads, because otherwise, their stack pointer may change, if single-stepping
|
||||||
// causes e.g. entrance into a function via a call instruction.
|
// causes e.g. entrance into a function via a call instruction.
|
||||||
//
|
//
|
||||||
U64 sp_check_value = dmn_rsp_from_thread(target_thread_dmn);
|
U64 sp_check_value = d_sp_from_thread(target_thread);
|
||||||
log_infof("sp_check_value := 0x%I64x\n", sp_check_value);
|
log_infof("sp_check_value := 0x%I64x\n", sp_check_value);
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
@@ -5740,7 +5775,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
|
|||||||
for(D_Entity *thread = process->first; thread != &d_entity_nil; thread = thread->next)
|
for(D_Entity *thread = process->first; thread != &d_entity_nil; thread = thread->next)
|
||||||
{
|
{
|
||||||
if(thread->kind != D_EntityKind_Thread) { continue; }
|
if(thread->kind != D_EntityKind_Thread) { continue; }
|
||||||
U64 rip = dmn_rip_from_thread(d_dmn_from_handle(thread->handle));
|
U64 rip = d_ip_from_thread(thread->handle);
|
||||||
|
|
||||||
// rjf: determine if thread is frozen
|
// rjf: determine if thread is frozen
|
||||||
B32 thread_is_frozen = thread->is_frozen;
|
B32 thread_is_frozen = thread->is_frozen;
|
||||||
@@ -5788,27 +5823,26 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
|
|||||||
node != 0;
|
node != 0;
|
||||||
node = node->next)
|
node = node->next)
|
||||||
{
|
{
|
||||||
DMN_Handle thread = node->v;
|
D_Handle thread = d_handle_from_dmn(D_MachineID_Local, node->v);
|
||||||
U64 thread_pre_rip = dmn_rip_from_thread(thread);
|
U64 thread_pre_rip = d_ip_from_thread(thread);
|
||||||
U64 thread_post_rip = thread_pre_rip;
|
U64 thread_post_rip = thread_pre_rip;
|
||||||
for(B32 done = 0; !done;)
|
for(B32 done = 0; !done;)
|
||||||
{
|
{
|
||||||
log_infof("single_step_stuck_thread([0x%I64x])\n", thread.u64[0]);
|
|
||||||
DMN_RunCtrls run_ctrls = {0};
|
DMN_RunCtrls run_ctrls = {0};
|
||||||
run_ctrls.run_entities_are_unfrozen = 1;
|
run_ctrls.run_entities_are_unfrozen = 1;
|
||||||
run_ctrls.run_entities = &thread;
|
run_ctrls.run_entities = &node->v;
|
||||||
run_ctrls.run_entity_count = 1;
|
run_ctrls.run_entity_count = 1;
|
||||||
if(thread_post_rip == thread_pre_rip)
|
if(thread_post_rip == thread_pre_rip)
|
||||||
{
|
{
|
||||||
run_ctrls.single_step_thread = thread;
|
run_ctrls.single_step_thread = node->v;
|
||||||
}
|
}
|
||||||
DMN_Event *event = d_ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0);
|
DMN_Event *event = d_ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0);
|
||||||
thread_post_rip = dmn_rip_from_thread(thread);
|
thread_post_rip = d_ip_from_thread(thread);
|
||||||
switch(event->kind)
|
switch(event->kind)
|
||||||
{
|
{
|
||||||
default:{}break;
|
default:{}break;
|
||||||
case DMN_EventKind_ExitThread:
|
case DMN_EventKind_ExitThread:
|
||||||
if(dmn_handle_match(event->thread, thread))
|
if(d_handle_match(d_handle_from_dmn(D_MachineID_Local, event->thread), thread))
|
||||||
{
|
{
|
||||||
stop_cause = D_EventCause_Error;
|
stop_cause = D_EventCause_Error;
|
||||||
goto stop;
|
goto stop;
|
||||||
@@ -6273,7 +6307,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
|
|||||||
D_Entity *thread = d_entity_from_handle(d_handle_from_dmn(D_MachineID_Local, event->thread));
|
D_Entity *thread = d_entity_from_handle(d_handle_from_dmn(D_MachineID_Local, event->thread));
|
||||||
D_Entity *process = d_entity_from_handle(d_handle_from_dmn(D_MachineID_Local, event->process));
|
D_Entity *process = d_entity_from_handle(d_handle_from_dmn(D_MachineID_Local, event->process));
|
||||||
Arch arch = thread->arch;
|
Arch arch = thread->arch;
|
||||||
U64 thread_rip_vaddr = dmn_rip_from_thread(event->thread);
|
U64 thread_rip_vaddr = d_ip_from_thread(thread->handle);
|
||||||
D_Entity *module = d_module_from_process_vaddr(process, thread_rip_vaddr);
|
D_Entity *module = d_module_from_process_vaddr(process, thread_rip_vaddr);
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
@@ -6441,21 +6475,21 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
|
|||||||
D_EventCause cond_bp_single_step_stop_cause = D_EventCause_Null;
|
D_EventCause cond_bp_single_step_stop_cause = D_EventCause_Null;
|
||||||
if(hit_conditional_bp_but_filtered) LogInfoNamedBlockF("conditional_bp_hit_single_step")
|
if(hit_conditional_bp_but_filtered) LogInfoNamedBlockF("conditional_bp_hit_single_step")
|
||||||
{
|
{
|
||||||
DMN_Handle thread = event->thread;
|
D_Handle thread = d_handle_from_dmn(D_MachineID_Local, event->thread);
|
||||||
U64 thread_pre_rip = dmn_rip_from_thread(thread);
|
U64 thread_pre_rip = d_ip_from_thread(thread);
|
||||||
U64 thread_post_rip = thread_pre_rip;
|
U64 thread_post_rip = thread_pre_rip;
|
||||||
for(B32 single_step_done = 0; !single_step_done;)
|
for(B32 single_step_done = 0; !single_step_done;)
|
||||||
{
|
{
|
||||||
DMN_RunCtrls single_step_ctrls = {0};
|
DMN_RunCtrls single_step_ctrls = {0};
|
||||||
single_step_ctrls.run_entities_are_unfrozen = 1;
|
single_step_ctrls.run_entities_are_unfrozen = 1;
|
||||||
single_step_ctrls.run_entities = &thread;
|
single_step_ctrls.run_entities = &event->thread;
|
||||||
single_step_ctrls.run_entity_count = 1;
|
single_step_ctrls.run_entity_count = 1;
|
||||||
if(thread_post_rip == thread_pre_rip)
|
if(thread_post_rip == thread_pre_rip)
|
||||||
{
|
{
|
||||||
single_step_ctrls.single_step_thread = thread;
|
single_step_ctrls.single_step_thread = event->thread;
|
||||||
}
|
}
|
||||||
DMN_Event *event = d_ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0);
|
DMN_Event *event = d_ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0);
|
||||||
thread_post_rip = dmn_rip_from_thread(thread);
|
thread_post_rip = d_ip_from_thread(thread);
|
||||||
switch(event->kind)
|
switch(event->kind)
|
||||||
{
|
{
|
||||||
default:{}break;
|
default:{}break;
|
||||||
@@ -6471,7 +6505,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
|
|||||||
}break;
|
}break;
|
||||||
case DMN_EventKind_SingleStep:
|
case DMN_EventKind_SingleStep:
|
||||||
{
|
{
|
||||||
single_step_done = dmn_handle_match(event->thread, thread);
|
single_step_done = d_handle_match(d_handle_from_dmn(D_MachineID_Local, event->thread), thread);
|
||||||
cond_bp_single_step_stop_cause = d_event_cause_from_dmn_event_kind(event->kind);
|
cond_bp_single_step_stop_cause = d_event_cause_from_dmn_event_kind(event->kind);
|
||||||
}break;
|
}break;
|
||||||
}
|
}
|
||||||
@@ -6519,7 +6553,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
|
|||||||
B32 stack_pointer_matches = 0;
|
B32 stack_pointer_matches = 0;
|
||||||
if(use_trap_net_logic)
|
if(use_trap_net_logic)
|
||||||
{
|
{
|
||||||
U64 sp = dmn_rsp_from_thread(d_dmn_from_handle(target_thread));
|
U64 sp = d_sp_from_thread(target_thread);
|
||||||
stack_pointer_matches = (sp == sp_check_value);
|
stack_pointer_matches = (sp == sp_check_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6530,7 +6564,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
|
|||||||
{
|
{
|
||||||
if(hit_trap_flags & D_TrapFlag_SingleStepAfterHit) LogInfoNamedBlockF("trap_net__single_step_after_hit")
|
if(hit_trap_flags & D_TrapFlag_SingleStepAfterHit) LogInfoNamedBlockF("trap_net__single_step_after_hit")
|
||||||
{
|
{
|
||||||
U64 thread_pre_rip = dmn_rip_from_thread(d_dmn_from_handle(target_thread));
|
U64 thread_pre_rip = d_ip_from_thread(target_thread);
|
||||||
U64 thread_post_rip = thread_pre_rip;
|
U64 thread_post_rip = thread_pre_rip;
|
||||||
for(B32 single_step_done = 0; single_step_done == 0;)
|
for(B32 single_step_done = 0; single_step_done == 0;)
|
||||||
{
|
{
|
||||||
@@ -6543,7 +6577,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
|
|||||||
single_step_ctrls.single_step_thread = target_thread_dmn;
|
single_step_ctrls.single_step_thread = target_thread_dmn;
|
||||||
}
|
}
|
||||||
DMN_Event *event = d_ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0);
|
DMN_Event *event = d_ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0);
|
||||||
thread_post_rip = dmn_rip_from_thread(target_thread_dmn);
|
thread_post_rip = d_ip_from_thread(target_thread);
|
||||||
switch(event->kind)
|
switch(event->kind)
|
||||||
{
|
{
|
||||||
default:{}break;
|
default:{}break;
|
||||||
@@ -6576,7 +6610,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
|
|||||||
{
|
{
|
||||||
// rjf: setup spoof mode
|
// rjf: setup spoof mode
|
||||||
begin_spoof_mode = 1;
|
begin_spoof_mode = 1;
|
||||||
U64 spoof_sp = dmn_rsp_from_thread(target_thread_dmn);
|
U64 spoof_sp = d_sp_from_thread(target_thread);
|
||||||
spoof_mode = 1;
|
spoof_mode = 1;
|
||||||
spoof.process = target_process;
|
spoof.process = target_process;
|
||||||
spoof.thread = target_thread;
|
spoof.thread = target_thread;
|
||||||
@@ -6594,7 +6628,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
|
|||||||
if(stack_pointer_matches) LogInfoNamedBlockF("trap_net__save_sp")
|
if(stack_pointer_matches) LogInfoNamedBlockF("trap_net__save_sp")
|
||||||
{
|
{
|
||||||
save_stack_pointer = 1;
|
save_stack_pointer = 1;
|
||||||
sp_check_value = dmn_rsp_from_thread(target_thread_dmn);
|
sp_check_value = d_sp_from_thread(target_thread);
|
||||||
log_infof("sp_check_value = 0x%I64x\n", sp_check_value);
|
log_infof("sp_check_value = 0x%I64x\n", sp_check_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6625,21 +6659,21 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
|
|||||||
D_EventCause step_past_trap_net_stop_cause = D_EventCause_Null;
|
D_EventCause step_past_trap_net_stop_cause = D_EventCause_Null;
|
||||||
if(step_past_trap_net) LogInfoNamedBlockF("trap_net__single_step_past_trap_net")
|
if(step_past_trap_net) LogInfoNamedBlockF("trap_net__single_step_past_trap_net")
|
||||||
{
|
{
|
||||||
DMN_Handle thread = event->thread;
|
D_Handle thread = d_handle_from_dmn(D_MachineID_Local, event->thread);
|
||||||
U64 thread_pre_rip = dmn_rip_from_thread(thread);
|
U64 thread_pre_rip = d_ip_from_thread(thread);
|
||||||
U64 thread_post_rip = thread_pre_rip;
|
U64 thread_post_rip = thread_pre_rip;
|
||||||
for(B32 single_step_done = 0; single_step_done == 0;)
|
for(B32 single_step_done = 0; single_step_done == 0;)
|
||||||
{
|
{
|
||||||
DMN_RunCtrls single_step_ctrls = {0};
|
DMN_RunCtrls single_step_ctrls = {0};
|
||||||
single_step_ctrls.run_entities_are_unfrozen = 1;
|
single_step_ctrls.run_entities_are_unfrozen = 1;
|
||||||
single_step_ctrls.run_entities = &thread;
|
single_step_ctrls.run_entities = &event->thread;
|
||||||
single_step_ctrls.run_entity_count = 1;
|
single_step_ctrls.run_entity_count = 1;
|
||||||
if(thread_post_rip == thread_pre_rip)
|
if(thread_post_rip == thread_pre_rip)
|
||||||
{
|
{
|
||||||
single_step_ctrls.single_step_thread = thread;
|
single_step_ctrls.single_step_thread = event->thread;
|
||||||
}
|
}
|
||||||
DMN_Event *event = d_ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0);
|
DMN_Event *event = d_ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0);
|
||||||
thread_post_rip = dmn_rip_from_thread(thread);
|
thread_post_rip = d_ip_from_thread(thread);
|
||||||
switch(event->kind)
|
switch(event->kind)
|
||||||
{
|
{
|
||||||
default:{}break;
|
default:{}break;
|
||||||
@@ -6654,7 +6688,7 @@ d_ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
|
|||||||
}break;
|
}break;
|
||||||
case DMN_EventKind_SingleStep:
|
case DMN_EventKind_SingleStep:
|
||||||
{
|
{
|
||||||
single_step_done = dmn_handle_match(event->thread, thread);
|
single_step_done = d_handle_match(d_handle_from_dmn(D_MachineID_Local, event->thread), thread);
|
||||||
step_past_trap_net_stop_cause = d_event_cause_from_dmn_event_kind(event->kind);
|
step_past_trap_net_stop_cause = d_event_cause_from_dmn_event_kind(event->kind);
|
||||||
}break;
|
}break;
|
||||||
}
|
}
|
||||||
@@ -6751,26 +6785,27 @@ d_ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: single step
|
//- rjf: single step
|
||||||
DMN_Handle thread = d_dmn_from_handle(msg->entity);
|
D_Handle thread = msg->entity;
|
||||||
B32 thread_is_valid = !dmn_handle_match(thread, dmn_handle_zero());
|
B32 thread_is_valid = !d_handle_match(thread, d_handle_zero());
|
||||||
DMN_Event *stop_event = 0;
|
DMN_Event *stop_event = 0;
|
||||||
D_EventCause stop_cause = D_EventCause_Null;
|
D_EventCause stop_cause = D_EventCause_Null;
|
||||||
if(thread_is_valid)
|
if(thread_is_valid)
|
||||||
{
|
{
|
||||||
U64 thread_pre_rip = dmn_rip_from_thread(thread);
|
U64 thread_pre_rip = d_ip_from_thread(thread);
|
||||||
U64 thread_post_rip = thread_pre_rip;
|
U64 thread_post_rip = thread_pre_rip;
|
||||||
for(B32 done = 0; done == 0;)
|
for(B32 done = 0; done == 0;)
|
||||||
{
|
{
|
||||||
|
DMN_Handle thread_dmn = d_dmn_from_handle(thread);
|
||||||
DMN_RunCtrls run_ctrls = {0};
|
DMN_RunCtrls run_ctrls = {0};
|
||||||
run_ctrls.run_entities_are_unfrozen = 1;
|
run_ctrls.run_entities_are_unfrozen = 1;
|
||||||
run_ctrls.run_entities = &thread;
|
run_ctrls.run_entities = &thread_dmn;
|
||||||
run_ctrls.run_entity_count = 1;
|
run_ctrls.run_entity_count = 1;
|
||||||
if(thread_post_rip == thread_pre_rip)
|
if(thread_post_rip == thread_pre_rip)
|
||||||
{
|
{
|
||||||
run_ctrls.single_step_thread = d_dmn_from_handle(msg->entity);
|
run_ctrls.single_step_thread = thread_dmn;
|
||||||
}
|
}
|
||||||
DMN_Event *event = d_ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0);
|
DMN_Event *event = d_ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0);
|
||||||
thread_post_rip = dmn_rip_from_thread(d_dmn_from_handle(msg->entity));
|
thread_post_rip = d_ip_from_thread(thread);
|
||||||
switch(event->kind)
|
switch(event->kind)
|
||||||
{
|
{
|
||||||
default:{}break;
|
default:{}break;
|
||||||
@@ -6886,32 +6921,10 @@ d_process_write(D_Handle process, Rng1U64 range, void *src)
|
|||||||
case D_ControllerKind_Demon:
|
case D_ControllerKind_Demon:
|
||||||
{
|
{
|
||||||
result = dmn_process_write(d_dmn_from_handle(process), range, src);
|
result = dmn_process_write(d_dmn_from_handle(process), range, src);
|
||||||
|
|
||||||
//- rjf: success -> bump generation
|
|
||||||
if(result)
|
if(result)
|
||||||
{
|
{
|
||||||
ins_atomic_u64_inc_eval(&d_ctrl_state->mem_gen);
|
ins_atomic_u64_inc_eval(&d_ctrl_state->mem_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: success -> wait for cache updates, for small regions - prefer relatively seamless
|
|
||||||
// writes within calling frame's "view" of the memory, at the expense of a small amount of
|
|
||||||
// time.
|
|
||||||
if(result)
|
|
||||||
{
|
|
||||||
U64 endt_us = now_time_us()+10000;
|
|
||||||
U64 page_size = get_system_info()->page_size; // TODO(rjf): @page_size_from_process
|
|
||||||
Rng1U64 page_range = r1u64(range.min/page_size, (range.max+page_size-1)/page_size);
|
|
||||||
for EachInRange(page_idx, page_range)
|
|
||||||
{
|
|
||||||
Temp scratch = scratch_begin(0, 0);
|
|
||||||
D_ProcessMemorySlice slice = d_process_memory_slice_from_vaddr_range(scratch.arena, process, r1u64(page_idx*page_size, (page_idx+1)*page_size), 1, endt_us);
|
|
||||||
scratch_end(scratch);
|
|
||||||
if(!slice.stale || now_time_us() >= endt_us)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case D_ControllerKind_Dump:
|
case D_ControllerKind_Dump:
|
||||||
|
|||||||
@@ -546,12 +546,14 @@ internal void d_set_wakeup_hook(D_WakeupFunctionType *wakeup_hook);
|
|||||||
//- rjf: thread handle read/write
|
//- rjf: thread handle read/write
|
||||||
internal B32 d_thread_read_reg_block(D_Handle handle, void *reg_block);
|
internal B32 d_thread_read_reg_block(D_Handle handle, void *reg_block);
|
||||||
internal B32 d_thread_write_reg_block(D_Handle thread, void *reg_block);
|
internal B32 d_thread_write_reg_block(D_Handle thread, void *reg_block);
|
||||||
|
internal U64 d_ip_from_thread(D_Handle handle);
|
||||||
|
internal U64 d_sp_from_thread(D_Handle handle);
|
||||||
|
|
||||||
//- rjf: thread register cache reading
|
//- rjf: thread register cache reading
|
||||||
internal void *d_reg_block_from_thread(Arena *arena, D_Handle handle);
|
internal void *d_cached_reg_block_from_thread(Arena *arena, D_Handle handle);
|
||||||
internal U64 d_tls_root_vaddr_from_thread(D_Handle handle);
|
internal U64 d_cached_tls_root_vaddr_from_thread(D_Handle handle);
|
||||||
internal U64 d_rip_from_thread(D_Handle handle);
|
internal U64 d_cached_ip_from_thread(D_Handle handle);
|
||||||
internal U64 d_rsp_from_thread(D_Handle handle);
|
internal U64 d_cached_sp_from_thread(D_Handle handle);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Module Image Info Functions
|
//~ rjf: Module Image Info Functions
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ d_trap_net_from_thread__step_over_inst(Arena *arena, D_Entity *thread)
|
|||||||
// rjf: thread => unpacked info
|
// rjf: thread => unpacked info
|
||||||
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||||
Arch arch = thread->arch;
|
Arch arch = thread->arch;
|
||||||
U64 ip_vaddr = d_rip_from_thread(thread->handle);
|
U64 ip_vaddr = d_cached_ip_from_thread(thread->handle);
|
||||||
|
|
||||||
// rjf: ip => machine code
|
// rjf: ip => machine code
|
||||||
String8 machine_code = {0};
|
String8 machine_code = {0};
|
||||||
@@ -336,7 +336,7 @@ d_trap_net_from_thread__step_over_line(Arena *arena, D_Entity *thread)
|
|||||||
|
|
||||||
// rjf: thread => info
|
// rjf: thread => info
|
||||||
Arch arch = thread->arch;
|
Arch arch = thread->arch;
|
||||||
U64 ip_vaddr = d_rip_from_thread(thread->handle);
|
U64 ip_vaddr = d_cached_ip_from_thread(thread->handle);
|
||||||
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||||
D_Entity *module = d_module_from_process_vaddr(process, ip_vaddr);
|
D_Entity *module = d_module_from_process_vaddr(process, ip_vaddr);
|
||||||
DI_Key dbgi_key = d_dbgi_key_from_module(module);
|
DI_Key dbgi_key = d_dbgi_key_from_module(module);
|
||||||
@@ -549,7 +549,7 @@ d_trap_net_from_thread__step_into_line(Arena *arena, D_Entity *thread)
|
|||||||
|
|
||||||
// rjf: thread => info
|
// rjf: thread => info
|
||||||
Arch arch = thread->arch;
|
Arch arch = thread->arch;
|
||||||
U64 ip_vaddr = d_rip_from_thread(thread->handle);
|
U64 ip_vaddr = d_cached_ip_from_thread(thread->handle);
|
||||||
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||||
D_Entity *module = d_module_from_process_vaddr(process, ip_vaddr);
|
D_Entity *module = d_module_from_process_vaddr(process, ip_vaddr);
|
||||||
DI_Key dbgi_key = d_dbgi_key_from_module(module);
|
DI_Key dbgi_key = d_dbgi_key_from_module(module);
|
||||||
@@ -753,7 +753,7 @@ d_trap_net_from_thread__step_out_scope(Arena *arena, D_Entity *thread)
|
|||||||
|
|
||||||
// rjf: unpack thread
|
// rjf: unpack thread
|
||||||
Arch arch = thread->arch;
|
Arch arch = thread->arch;
|
||||||
U64 ip_vaddr = d_rip_from_thread(thread->handle);
|
U64 ip_vaddr = d_cached_ip_from_thread(thread->handle);
|
||||||
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||||
D_Entity *module = d_module_from_process_vaddr(process, ip_vaddr);
|
D_Entity *module = d_module_from_process_vaddr(process, ip_vaddr);
|
||||||
DI_Key dbgi_key = d_dbgi_key_from_module(module);
|
DI_Key dbgi_key = d_dbgi_key_from_module(module);
|
||||||
@@ -1327,7 +1327,7 @@ d_query_cached_rip_from_thread_unwind(D_Entity *thread, U64 unwind_count)
|
|||||||
U64 result = 0;
|
U64 result = 0;
|
||||||
if(unwind_count == 0)
|
if(unwind_count == 0)
|
||||||
{
|
{
|
||||||
result = d_rip_from_thread(thread->handle);
|
result = d_cached_ip_from_thread(thread->handle);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1977,7 +1977,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
|||||||
D_Entity *thread = d_entity_from_handle(params->thread);
|
D_Entity *thread = d_entity_from_handle(params->thread);
|
||||||
ARCH_Info *arch_info = arch_info_from_arch(thread->arch);
|
ARCH_Info *arch_info = arch_info_from_arch(thread->arch);
|
||||||
U64 vaddr = params->vaddr;
|
U64 vaddr = params->vaddr;
|
||||||
void *block = d_reg_block_from_thread(scratch.arena, thread->handle);
|
void *block = d_cached_reg_block_from_thread(scratch.arena, thread->handle);
|
||||||
arch_reg_block_write_ip(arch_info, block, vaddr);
|
arch_reg_block_write_ip(arch_info, block, vaddr);
|
||||||
B32 result = d_thread_write_reg_block(thread->handle, block);
|
B32 result = d_thread_write_reg_block(thread->handle, block);
|
||||||
(void)result;
|
(void)result;
|
||||||
|
|||||||
@@ -121,72 +121,3 @@ dmn_event_list_push(Arena *arena, DMN_EventList *list)
|
|||||||
DMN_Event *result = &n->v;
|
DMN_Event *result = &n->v;
|
||||||
return result;
|
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);
|
|
||||||
{
|
|
||||||
Arch arch = dmn_arch_from_thread(thread);
|
|
||||||
ARCH_Info *arch_info = arch_info_from_arch(arch);
|
|
||||||
U64 reg_block_size = arch_info->reg_block_size;
|
|
||||||
void *reg_block = push_array(scratch.arena, U8, reg_block_size);
|
|
||||||
dmn_thread_read_reg_block(thread, reg_block);
|
|
||||||
result = arch_ip_from_reg_block(arch_info, 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);
|
|
||||||
{
|
|
||||||
Arch arch = dmn_arch_from_thread(thread);
|
|
||||||
ARCH_Info *arch_info = arch_info_from_arch(arch);
|
|
||||||
U64 reg_block_size = arch_info->reg_block_size;
|
|
||||||
void *reg_block = push_array(scratch.arena, U8, reg_block_size);
|
|
||||||
dmn_thread_read_reg_block(thread, reg_block);
|
|
||||||
result = arch_sp_from_reg_block(arch_info, reg_block);
|
|
||||||
}
|
|
||||||
scratch_end(scratch);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Process Reading Helper Functions (Helpers, Implemented Once)
|
|
||||||
|
|
||||||
internal String8
|
|
||||||
dmn_get_trap_inst(void)
|
|
||||||
{
|
|
||||||
#if ARCH_X64
|
|
||||||
local_persist U8 inst[] = { 0xcc };
|
|
||||||
#else
|
|
||||||
# error "trap instruction is not defined for this arch"
|
|
||||||
#endif
|
|
||||||
return str8_array_fixed(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal DMN_ActiveTrap *
|
|
||||||
dmn_set_trap(Arena *arena, DMN_Trap *trap)
|
|
||||||
{
|
|
||||||
String8 trap_inst = dmn_get_trap_inst();
|
|
||||||
U8 *swap_bytes = push_array(arena, U8, trap_inst.size);
|
|
||||||
B32 good_read = dmn_process_read(trap->process, r1u64(trap->vaddr, trap->vaddr + trap_inst.size), swap_bytes);
|
|
||||||
B32 good_write = 0;
|
|
||||||
if(good_read)
|
|
||||||
{
|
|
||||||
good_write = dmn_process_write(trap->process, r1u64(trap->vaddr, trap->vaddr + trap_inst.size), trap_inst.str);
|
|
||||||
}
|
|
||||||
DMN_ActiveTrap *result = push_array(arena, DMN_ActiveTrap, 1);
|
|
||||||
result->good = (good_read && good_write);
|
|
||||||
result->trap = trap;
|
|
||||||
result->swap_bytes = str8(swap_bytes, trap_inst.size);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -152,15 +152,6 @@ struct DMN_TrapChunkList
|
|||||||
U64 trap_count;
|
U64 trap_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct DMN_ActiveTrap DMN_ActiveTrap;
|
|
||||||
struct DMN_ActiveTrap
|
|
||||||
{
|
|
||||||
DMN_ActiveTrap *next;
|
|
||||||
B32 good;
|
|
||||||
DMN_Trap *trap;
|
|
||||||
String8 swap_bytes;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct DMN_RunCtrls DMN_RunCtrls;
|
typedef struct DMN_RunCtrls DMN_RunCtrls;
|
||||||
struct DMN_RunCtrls
|
struct DMN_RunCtrls
|
||||||
{
|
{
|
||||||
@@ -210,12 +201,6 @@ internal DMN_HandleArray dmn_handle_array_copy(Arena *arena, DMN_HandleArray *sr
|
|||||||
//- rjf: event list building
|
//- rjf: event list building
|
||||||
internal DMN_Event *dmn_event_list_push(Arena *arena, DMN_EventList *list);
|
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: Process Reading Helper Functions (Helpers, Implemented Once)
|
//~ rjf: Process Reading Helper Functions (Helpers, Implemented Once)
|
||||||
|
|
||||||
@@ -273,9 +258,4 @@ internal void dmn_process_iter_begin(DMN_ProcessIter *iter);
|
|||||||
internal B32 dmn_process_iter_next(Arena *arena, DMN_ProcessIter *iter, DMN_ProcessInfo *info_out);
|
internal B32 dmn_process_iter_next(Arena *arena, DMN_ProcessIter *iter, DMN_ProcessInfo *info_out);
|
||||||
internal void dmn_process_iter_end(DMN_ProcessIter *iter);
|
internal void dmn_process_iter_end(DMN_ProcessIter *iter);
|
||||||
|
|
||||||
//- arch trap
|
|
||||||
internal String8 dmn_get_trap_inst(void);
|
|
||||||
|
|
||||||
internal DMN_ActiveTrap * dmn_set_trap(Arena *arena, DMN_Trap *trap);
|
|
||||||
|
|
||||||
#endif // DEMON_CORE_H
|
#endif // DEMON_CORE_H
|
||||||
|
|||||||
@@ -292,6 +292,28 @@ lnx_dmn_process_from_pid(pid_t pid)
|
|||||||
return hash_table_search_u64_raw(lnx_dmn_state->pid_ht, pid);
|
return hash_table_search_u64_raw(lnx_dmn_state->pid_ht, pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Trap Setting
|
||||||
|
|
||||||
|
internal LNX_DMN_ActiveTrap *
|
||||||
|
lnx_dmn_set_trap(Arena *arena, DMN_Trap *trap)
|
||||||
|
{
|
||||||
|
ARCH_Info *arch = arch_info_from_arch(Arch_CURRENT);
|
||||||
|
String8 trap_inst = arch->trap_instruction;
|
||||||
|
U8 *swap_bytes = push_array(arena, U8, trap_inst.size);
|
||||||
|
B32 good_read = dmn_process_read(trap->process, r1u64(trap->vaddr, trap->vaddr + trap_inst.size), swap_bytes);
|
||||||
|
B32 good_write = 0;
|
||||||
|
if(good_read)
|
||||||
|
{
|
||||||
|
good_write = dmn_process_write(trap->process, r1u64(trap->vaddr, trap->vaddr + trap_inst.size), trap_inst.str);
|
||||||
|
}
|
||||||
|
LNX_DMN_ActiveTrap *result = push_array(arena, LNX_DMN_ActiveTrap, 1);
|
||||||
|
result->good = (good_read && good_write);
|
||||||
|
result->trap = trap;
|
||||||
|
result->swap_bytes = str8(swap_bytes, trap_inst.size);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
internal Rng1U64
|
internal Rng1U64
|
||||||
lnx_dmn_compute_image_vrange(int memory_fd, ELF_Class elf_class, U64 rebase, U64 e_phaddr, U64 e_phentsize, U64 e_phnum)
|
lnx_dmn_compute_image_vrange(int memory_fd, ELF_Class elf_class, U64 rebase, U64 e_phaddr, U64 e_phentsize, U64 e_phnum)
|
||||||
{
|
{
|
||||||
@@ -976,7 +998,7 @@ lnx_dmn_process_ctx_clone(LNX_DMN_Process *new_owner, LNX_DMN_ProcessCtx *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// clone probe traps
|
// clone probe traps
|
||||||
for EachNode(src, DMN_ActiveTrap, ctx->first_probe_trap)
|
for EachNode(src, LNX_DMN_ActiveTrap, ctx->first_probe_trap)
|
||||||
{
|
{
|
||||||
DMN_Trap *src_trap = src->trap;
|
DMN_Trap *src_trap = src->trap;
|
||||||
DMN_Trap *dst_trap = push_array(result->arena, DMN_Trap, 1);
|
DMN_Trap *dst_trap = push_array(result->arena, DMN_Trap, 1);
|
||||||
@@ -986,7 +1008,7 @@ lnx_dmn_process_ctx_clone(LNX_DMN_Process *new_owner, LNX_DMN_ProcessCtx *ctx)
|
|||||||
dst_trap->flags = src_trap->flags;
|
dst_trap->flags = src_trap->flags;
|
||||||
dst_trap->size = src_trap->size;
|
dst_trap->size = src_trap->size;
|
||||||
|
|
||||||
DMN_ActiveTrap *dst = push_array(result->arena, DMN_ActiveTrap, 1);
|
LNX_DMN_ActiveTrap *dst = push_array(result->arena, LNX_DMN_ActiveTrap, 1);
|
||||||
dst->trap = dst_trap;
|
dst->trap = dst_trap;
|
||||||
dst->swap_bytes = str8_copy(result->arena, src->swap_bytes);
|
dst->swap_bytes = str8_copy(result->arena, src->swap_bytes);
|
||||||
|
|
||||||
@@ -1112,7 +1134,7 @@ lnx_dmn_process_trap_probes(LNX_DMN_Process *process)
|
|||||||
trap->vaddr = process->ctx->probes[i]->pc;
|
trap->vaddr = process->ctx->probes[i]->pc;
|
||||||
trap->id = i;
|
trap->id = i;
|
||||||
|
|
||||||
DMN_ActiveTrap *active_trap = dmn_set_trap(process->ctx->arena, trap);
|
LNX_DMN_ActiveTrap *active_trap = lnx_dmn_set_trap(process->ctx->arena, trap);
|
||||||
SLLQueuePush(process->ctx->first_probe_trap, process->ctx->last_probe_trap, active_trap);
|
SLLQueuePush(process->ctx->first_probe_trap, process->ctx->last_probe_trap, active_trap);
|
||||||
|
|
||||||
if(BUILD_DEBUG && process->ctx->arch == Arch_x64)
|
if(BUILD_DEBUG && process->ctx->arch == Arch_x64)
|
||||||
@@ -1966,17 +1988,17 @@ lnx_dmn_event_unload_module(Arena *arena, DMN_EventList *events, LNX_DMN_Process
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
lnx_dmn_event_breakpoint(Arena *arena, DMN_EventList *events, DMN_ActiveTrap *user_traps, pid_t tid)
|
lnx_dmn_event_breakpoint(Arena *arena, DMN_EventList *events, LNX_DMN_ActiveTrap *user_traps, pid_t tid)
|
||||||
{
|
{
|
||||||
LNX_DMN_Thread *thread = lnx_dmn_thread_from_pid(tid);
|
LNX_DMN_Thread *thread = lnx_dmn_thread_from_pid(tid);
|
||||||
LNX_DMN_Process *process = thread->process;
|
LNX_DMN_Process *process = thread->process;
|
||||||
U64 ip = lnx_dmn_thread_read_ip(thread);
|
U64 ip = lnx_dmn_thread_read_ip(thread);
|
||||||
|
|
||||||
// is this user trap?
|
// is this user trap?
|
||||||
DMN_ActiveTrap *hit_user_trap = 0;
|
LNX_DMN_ActiveTrap *hit_user_trap = 0;
|
||||||
{
|
{
|
||||||
DMN_Handle process_handle = lnx_dmn_handle_from_process(process);
|
DMN_Handle process_handle = lnx_dmn_handle_from_process(process);
|
||||||
for EachNode(active_trap, DMN_ActiveTrap, user_traps)
|
for EachNode(active_trap, LNX_DMN_ActiveTrap, user_traps)
|
||||||
{
|
{
|
||||||
if(MemoryCompare(&active_trap->trap->process, &process_handle, sizeof(DMN_Handle)) == 0)
|
if(MemoryCompare(&active_trap->trap->process, &process_handle, sizeof(DMN_Handle)) == 0)
|
||||||
{
|
{
|
||||||
@@ -1993,7 +2015,7 @@ lnx_dmn_event_breakpoint(Arena *arena, DMN_EventList *events, DMN_ActiveTrap *us
|
|||||||
LNX_DMN_ProbeType probe_type = LNX_DMN_ProbeType_Null;
|
LNX_DMN_ProbeType probe_type = LNX_DMN_ProbeType_Null;
|
||||||
if(hit_user_trap == 0)
|
if(hit_user_trap == 0)
|
||||||
{
|
{
|
||||||
for EachNode(active_trap, DMN_ActiveTrap, process->ctx->first_probe_trap)
|
for EachNode(active_trap, LNX_DMN_ActiveTrap, process->ctx->first_probe_trap)
|
||||||
{
|
{
|
||||||
if(active_trap->trap->vaddr == ip-1)
|
if(active_trap->trap->vaddr == ip-1)
|
||||||
{
|
{
|
||||||
@@ -2397,7 +2419,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
if(lnx_dmn_state->process_count > 0)
|
if(lnx_dmn_state->process_count > 0)
|
||||||
{
|
{
|
||||||
// write traps to memory
|
// write traps to memory
|
||||||
DMN_ActiveTrap *active_trap_first = 0, *active_trap_last = 0;
|
LNX_DMN_ActiveTrap *active_trap_first = 0, *active_trap_last = 0;
|
||||||
{
|
{
|
||||||
HashTable *process_ht = hash_table_init(scratch.arena, lnx_dmn_state->process_count);
|
HashTable *process_ht = hash_table_init(scratch.arena, lnx_dmn_state->process_count);
|
||||||
for EachNode(n, DMN_TrapChunkNode, ctrls->traps.first)
|
for EachNode(n, DMN_TrapChunkNode, ctrls->traps.first)
|
||||||
@@ -2416,7 +2438,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: ctrl sends down duplicate traps
|
// TODO: ctrl sends down duplicate traps
|
||||||
DMN_ActiveTrap *is_set = hash_table_search_u64_raw(active_trap_ht, trap->vaddr);
|
LNX_DMN_ActiveTrap *is_set = hash_table_search_u64_raw(active_trap_ht, trap->vaddr);
|
||||||
if(is_set) { continue; }
|
if(is_set) { continue; }
|
||||||
|
|
||||||
// TODO: ctrl sends down traps for exited process
|
// TODO: ctrl sends down traps for exited process
|
||||||
@@ -2424,7 +2446,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
if(!process) { continue; }
|
if(!process) { continue; }
|
||||||
|
|
||||||
// trap instruction
|
// trap instruction
|
||||||
DMN_ActiveTrap *active_trap = dmn_set_trap(scratch.arena, trap);
|
LNX_DMN_ActiveTrap *active_trap = lnx_dmn_set_trap(scratch.arena, trap);
|
||||||
|
|
||||||
// add trap to the active list
|
// add trap to the active list
|
||||||
SLLQueuePush(active_trap_first, active_trap_last, active_trap);
|
SLLQueuePush(active_trap_first, active_trap_last, active_trap);
|
||||||
@@ -2854,7 +2876,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// restore original instruction bytes
|
// restore original instruction bytes
|
||||||
for EachNode(active_trap, DMN_ActiveTrap, active_trap_first)
|
for EachNode(active_trap, LNX_DMN_ActiveTrap, active_trap_first)
|
||||||
{
|
{
|
||||||
// skip process that exited during the wait
|
// skip process that exited during the wait
|
||||||
LNX_DMN_Process *process = lnx_dmn_process_from_handle(active_trap->trap->process);
|
LNX_DMN_Process *process = lnx_dmn_process_from_handle(active_trap->trap->process);
|
||||||
|
|||||||
@@ -285,8 +285,8 @@ typedef struct LNX_DMN_ProcessCtx
|
|||||||
ELF_Class dl_class;
|
ELF_Class dl_class;
|
||||||
HashTable *loaded_modules_ht;
|
HashTable *loaded_modules_ht;
|
||||||
LNX_DMN_Probe **probes;
|
LNX_DMN_Probe **probes;
|
||||||
DMN_ActiveTrap *first_probe_trap;
|
LNX_DMN_ActiveTrap *first_probe_trap;
|
||||||
DMN_ActiveTrap *last_probe_trap;
|
LNX_DMN_ActiveTrap *last_probe_trap;
|
||||||
LNX_DMN_Module *first_module;
|
LNX_DMN_Module *first_module;
|
||||||
LNX_DMN_Module *last_module;
|
LNX_DMN_Module *last_module;
|
||||||
U64 module_count;
|
U64 module_count;
|
||||||
@@ -331,6 +331,18 @@ typedef struct LNX_DMN_EntityList
|
|||||||
LNX_DMN_EntityNode *last;
|
LNX_DMN_EntityNode *last;
|
||||||
} LNX_DMN_EntityList;
|
} LNX_DMN_EntityList;
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Active Trap Data Structure
|
||||||
|
|
||||||
|
typedef struct LNX_DMN_ActiveTrap LNX_DMN_ActiveTrap;
|
||||||
|
struct LNX_DMN_ActiveTrap
|
||||||
|
{
|
||||||
|
LNX_DMN_ActiveTrap *next;
|
||||||
|
B32 good;
|
||||||
|
DMN_Trap *trap;
|
||||||
|
String8 swap_bytes;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Global State
|
//~ Global State
|
||||||
|
|
||||||
@@ -389,6 +401,11 @@ internal String8 lnx_dmn_read_string(Arena *arena, int memory_fd, U64 base_vaddr
|
|||||||
#define lnx_dmn_read_struct(fd, vaddr, ptr) lnx_dmn_read((fd), r1u64((vaddr), (vaddr)+sizeof(*(ptr))), (ptr))
|
#define lnx_dmn_read_struct(fd, vaddr, ptr) lnx_dmn_read((fd), r1u64((vaddr), (vaddr)+sizeof(*(ptr))), (ptr))
|
||||||
#define lnx_dmn_write_struct(fd, vaddr, ptr) lnx_dmn_write((fd), r1u64((vaddr), (vaddr)+sizeof(*(ptr))), (ptr))
|
#define lnx_dmn_write_struct(fd, vaddr, ptr) lnx_dmn_write((fd), r1u64((vaddr), (vaddr)+sizeof(*(ptr))), (ptr))
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Trap Setting
|
||||||
|
|
||||||
|
internal LNX_DMN_ActiveTrap *lnx_dmn_set_trap(Arena *arena, DMN_Trap *trap);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ ELF/GNU info
|
//~ ELF/GNU info
|
||||||
|
|
||||||
@@ -491,7 +508,7 @@ internal LNX_DMN_Process * lnx_dmn_event_create_process(Arena *arena, DMN_EventL
|
|||||||
internal void lnx_dmn_event_exit_process(Arena *arena, DMN_EventList *events, pid_t pid);
|
internal void lnx_dmn_event_exit_process(Arena *arena, DMN_EventList *events, pid_t pid);
|
||||||
internal void lnx_dmn_event_load_module(Arena *arena, DMN_EventList *events, LNX_DMN_Thread *thread, U64 name_space_id, U64 new_link_map_vaddr);
|
internal void lnx_dmn_event_load_module(Arena *arena, DMN_EventList *events, LNX_DMN_Thread *thread, U64 name_space_id, U64 new_link_map_vaddr);
|
||||||
internal void lnx_dmn_event_unload_module(Arena *arena, DMN_EventList *events, LNX_DMN_Process *process, U64 rdebug_vaddr);
|
internal void lnx_dmn_event_unload_module(Arena *arena, DMN_EventList *events, LNX_DMN_Process *process, U64 rdebug_vaddr);
|
||||||
internal void lnx_dmn_event_breakpoint(Arena *arena, DMN_EventList *events, DMN_ActiveTrap *user_traps, pid_t tid);
|
internal void lnx_dmn_event_breakpoint(Arena *arena, DMN_EventList *events, LNX_DMN_ActiveTrap *user_traps, pid_t tid);
|
||||||
internal void lnx_dmn_event_data_breakpoint(Arena *arena, DMN_EventList *events, pid_t tid);
|
internal void lnx_dmn_event_data_breakpoint(Arena *arena, DMN_EventList *events, pid_t tid);
|
||||||
internal void lnx_dmn_event_halt(Arena *arena, DMN_EventList *events);
|
internal void lnx_dmn_event_halt(Arena *arena, DMN_EventList *events);
|
||||||
internal void lnx_dmn_event_single_step(Arena *arena, DMN_EventList *events, pid_t tid);
|
internal void lnx_dmn_event_single_step(Arena *arena, DMN_EventList *events, pid_t tid);
|
||||||
|
|||||||
@@ -797,7 +797,7 @@ rd_eval_space_read(E_Space space, void *out, E_SpaceRangeInfo *out_range_info, R
|
|||||||
void *regs_block = 0;
|
void *regs_block = 0;
|
||||||
if(e_interpret_ctx->reg_unwind_count == 0)
|
if(e_interpret_ctx->reg_unwind_count == 0)
|
||||||
{
|
{
|
||||||
regs_block = d_reg_block_from_thread(scratch.arena, entity->handle);
|
regs_block = d_cached_reg_block_from_thread(scratch.arena, entity->handle);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1037,6 +1037,26 @@ rd_eval_space_write(E_Space space, void *in, Rng1U64 range)
|
|||||||
case D_EntityKind_Process:
|
case D_EntityKind_Process:
|
||||||
{
|
{
|
||||||
result = d_process_write(entity->handle, range, in);
|
result = d_process_write(entity->handle, range, in);
|
||||||
|
|
||||||
|
//- rjf: success -> wait for cache updates, for small regions - prefer relatively seamless
|
||||||
|
// writes within calling frame's "view" of the memory, at the expense of a small amount of
|
||||||
|
// time.
|
||||||
|
if(result)
|
||||||
|
{
|
||||||
|
U64 endt_us = now_time_us()+10000;
|
||||||
|
U64 page_size = get_system_info()->page_size; // TODO(rjf): @page_size_from_process
|
||||||
|
Rng1U64 page_range = r1u64(range.min/page_size, (range.max+page_size-1)/page_size);
|
||||||
|
for EachInRange(page_idx, page_range)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
D_ProcessMemorySlice slice = d_process_memory_slice_from_vaddr_range(scratch.arena, entity->handle, r1u64(page_idx*page_size, (page_idx+1)*page_size), 1, endt_us);
|
||||||
|
scratch_end(scratch);
|
||||||
|
if(!slice.stale || now_time_us() >= endt_us)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}break;
|
}break;
|
||||||
case D_EntityKind_Thread:
|
case D_EntityKind_Thread:
|
||||||
{
|
{
|
||||||
@@ -1046,7 +1066,7 @@ rd_eval_space_write(E_Space space, void *in, Rng1U64 range)
|
|||||||
Rng1U64 legal_range = r1u64(0, regs_size);
|
Rng1U64 legal_range = r1u64(0, regs_size);
|
||||||
Rng1U64 write_range = intersect_1u64(legal_range, range);
|
Rng1U64 write_range = intersect_1u64(legal_range, range);
|
||||||
U64 write_size = dim_1u64(write_range);
|
U64 write_size = dim_1u64(write_range);
|
||||||
void *new_regs = d_reg_block_from_thread(scratch.arena, entity->handle);
|
void *new_regs = d_cached_reg_block_from_thread(scratch.arena, entity->handle);
|
||||||
MemoryCopy((U8 *)new_regs + write_range.min, in, write_size);
|
MemoryCopy((U8 *)new_regs + write_range.min, in, write_size);
|
||||||
result = d_thread_write_reg_block(entity->handle, new_regs);
|
result = d_thread_write_reg_block(entity->handle, new_regs);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
@@ -9847,7 +9867,7 @@ rd_gather_auto_exprs(Arena *arena)
|
|||||||
//- rjf: unpack thread / module / debug info / lines
|
//- rjf: unpack thread / module / debug info / lines
|
||||||
ARCH_Info *arch_info = arch_info_from_arch(thread->arch);
|
ARCH_Info *arch_info = arch_info_from_arch(thread->arch);
|
||||||
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||||
U64 thread_ip_vaddr = d_rip_from_thread(thread_handle);
|
U64 thread_ip_vaddr = d_cached_ip_from_thread(thread_handle);
|
||||||
D_Entity *module = d_module_from_process_vaddr(process, thread_ip_vaddr);
|
D_Entity *module = d_module_from_process_vaddr(process, thread_ip_vaddr);
|
||||||
DI_Key dbgi_key = d_dbgi_key_from_module(module);
|
DI_Key dbgi_key = d_dbgi_key_from_module(module);
|
||||||
RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0);
|
RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0);
|
||||||
@@ -11360,7 +11380,7 @@ rd_frame(void)
|
|||||||
U64 rip_vaddr = d_query_cached_rip_from_thread_unwind(thread, unwind_count);
|
U64 rip_vaddr = d_query_cached_rip_from_thread_unwind(thread, unwind_count);
|
||||||
D_Entity *module = d_module_from_process_vaddr(process, rip_vaddr);
|
D_Entity *module = d_module_from_process_vaddr(process, rip_vaddr);
|
||||||
U64 rip_voff = d_voff_from_vaddr(module, rip_vaddr);
|
U64 rip_voff = d_voff_from_vaddr(module, rip_vaddr);
|
||||||
U64 tls_root_vaddr = d_tls_root_vaddr_from_thread(thread->handle);
|
U64 tls_root_vaddr = d_cached_tls_root_vaddr_from_thread(thread->handle);
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
@@ -15821,7 +15841,7 @@ rd_frame(void)
|
|||||||
{
|
{
|
||||||
D_Entity *thread = d_entity_from_handle(rd_regs()->thread);
|
D_Entity *thread = d_entity_from_handle(rd_regs()->thread);
|
||||||
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||||
D_Entity *module = d_module_from_process_vaddr(process, d_rip_from_thread(thread->handle));
|
D_Entity *module = d_module_from_process_vaddr(process, d_cached_ip_from_thread(thread->handle));
|
||||||
D_Entity *machine = d_entity_ancestor_from_kind(process, D_EntityKind_Machine);
|
D_Entity *machine = d_entity_ancestor_from_kind(process, D_EntityKind_Machine);
|
||||||
rd_state->base_regs.v.unwind_count = 0;
|
rd_state->base_regs.v.unwind_count = 0;
|
||||||
rd_state->base_regs.v.inline_depth = 0;
|
rd_state->base_regs.v.inline_depth = 0;
|
||||||
@@ -16664,7 +16684,7 @@ rd_frame(void)
|
|||||||
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||||
D_Entity *module = d_module_from_process_vaddr(process, vaddr);
|
D_Entity *module = d_module_from_process_vaddr(process, vaddr);
|
||||||
U64 voff = d_voff_from_vaddr(module, vaddr);
|
U64 voff = d_voff_from_vaddr(module, vaddr);
|
||||||
U64 test_cached_vaddr = d_rip_from_thread(thread->handle);
|
U64 test_cached_vaddr = d_cached_ip_from_thread(thread->handle);
|
||||||
|
|
||||||
// rjf: valid stop thread? -> select & snap
|
// rjf: valid stop thread? -> select & snap
|
||||||
if(need_refocus && thread->kind == D_EntityKind_Thread && evt->cause != D_EventCause_InterruptedByHalt)
|
if(need_refocus && thread->kind == D_EntityKind_Thread && evt->cause != D_EventCause_InterruptedByHalt)
|
||||||
@@ -16734,7 +16754,7 @@ rd_frame(void)
|
|||||||
// rjf: update the autos-determining code range
|
// rjf: update the autos-determining code range
|
||||||
{
|
{
|
||||||
D_Handle new_thread_handle = thread->handle;
|
D_Handle new_thread_handle = thread->handle;
|
||||||
U64 new_sp = d_rsp_from_thread(new_thread_handle);
|
U64 new_sp = d_cached_sp_from_thread(new_thread_handle);
|
||||||
if(thread == &d_entity_nil)
|
if(thread == &d_entity_nil)
|
||||||
{
|
{
|
||||||
new_thread_handle = selected_thread->handle;
|
new_thread_handle = selected_thread->handle;
|
||||||
|
|||||||
Reference in New Issue
Block a user