ctrl: eliminate possibility of threads getting stuck at spoof address at the event-pump layer - if we report other events first, the step is already cancelled anyways

This commit is contained in:
Ryan Fleury
2024-01-17 20:58:55 -08:00
parent 268ca9ab53
commit d2d72bd7ab
2 changed files with 51 additions and 42 deletions
+50 -42
View File
@@ -1366,6 +1366,7 @@ ctrl_thread__next_demon_event(Arena *arena, CTRL_Msg *msg, DEMON_RunCtrls *run_c
Temp scratch = scratch_begin(&arena, 1);
//- rjf: loop -> try to get event, run, repeat
U64 spoof_old_ip_value = 0;
ProfScope("loop -> try to get event, run, repeat") for(B32 got_event = 0; got_event == 0;)
{
//- rjf: get next event
@@ -1437,7 +1438,6 @@ ctrl_thread__next_demon_event(Arena *arena, CTRL_Msg *msg, DEMON_RunCtrls *run_c
{
// rjf: prep spoof
B32 do_spoof = (spoof != 0 && run_ctrls->single_step_thread == 0);
U64 spoof_old_ip_value = 0;
U64 size_of_spoof = 0;
if(do_spoof) ProfScope("prep spoof")
{
@@ -1487,6 +1487,18 @@ ctrl_thread__next_demon_event(Arena *arena, CTRL_Msg *msg, DEMON_RunCtrls *run_c
}
}
//- rjf: irrespective of what event came back, we should ALWAYS check the
// spoof's thread and see if it hit the spoof address, because we may have
// simply been sent other debug events first
if(spoof != 0)
{
U64 spoof_thread_rip = demon_read_ip(ctrl_demon_handle_from_ctrl(spoof->thread));
if(spoof_thread_rip == spoof->new_ip_value)
{
demon_write_ip(ctrl_demon_handle_from_ctrl(spoof->thread), spoof_old_ip_value);
}
}
//- rjf: push ctrl events associated with this demon event
CTRL_EventList evts = {0};
ProfScope("push ctrl events associated with this demon event") switch(event->kind)
@@ -2124,10 +2136,14 @@ ctrl_thread__run(CTRL_Msg *msg)
DEMON_Handle target_process = ctrl_demon_handle_from_ctrl(msg->parent);
U64 spoof_ip_vaddr = 911;
//////////////////////////////
//- rjf: gather processes
//
DEMON_HandleArray processes = demon_all_processes(scratch.arena);
//////////////////////////////
//- rjf: gather all initial breakpoints
//
DEMON_TrapChunkList user_traps = {0};
{
// rjf: resolve module-dependent user bps
@@ -2149,6 +2165,7 @@ ctrl_thread__run(CTRL_Msg *msg)
}
}
//////////////////////////////
//- rjf: single step "stuck threads"
//
// "Stuck threads" are threads that are already on a User BP and would hit
@@ -2253,7 +2270,9 @@ ctrl_thread__run(CTRL_Msg *msg)
}
}
//////////////////////////////
//- rjf: resolve trap net
//
DEMON_TrapChunkList trap_net_traps = {0};
for(CTRL_TrapNode *node = msg->traps.first;
node != 0;
@@ -2263,14 +2282,18 @@ ctrl_thread__run(CTRL_Msg *msg)
demon_trap_chunk_list_push(scratch.arena, &trap_net_traps, 256, &trap);
}
//////////////////////////////
//- rjf: join user breakpoints and trap net traps
//
DEMON_TrapChunkList joined_traps = {0};
{
demon_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &user_traps);
demon_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &trap_net_traps);
}
//////////////////////////////
//- rjf: record start
//
if(stop_event == 0)
{
CTRL_EventList evts = {0};
@@ -2279,31 +2302,37 @@ ctrl_thread__run(CTRL_Msg *msg)
ctrl_c2u_push_events(&evts);
}
//////////////////////////////
//- rjf: run loop
//
if(stop_event == 0)
{
U64 sp_check_value = demon_read_sp(target_thread);
B32 spoof_mode = 0;
CTRL_Spoof spoof = {0};
U64 spoof_1_return_ip = 0;
for(;;)
{
//////////////////////////
//- rjf: choose low level traps
//
DEMON_TrapChunkList *trap_list = &joined_traps;
if(spoof_mode)
{
trap_list = &user_traps;
}
//////////////////////////
//- rjf: choose spoof
//
CTRL_Spoof *run_spoof = 0;
if(spoof_mode)
{
run_spoof = &spoof;
}
//////////////////////////
//- rjf: setup run controls
//
DEMON_RunCtrls run_ctrls = {0};
run_ctrls.ignore_previous_exception = 1;
run_ctrls.run_entity_count = msg->freeze_state_threads.count;
@@ -2317,12 +2346,16 @@ ctrl_thread__run(CTRL_Msg *msg)
idx += 1;
}
}
run_ctrls.traps = *trap_list;
run_ctrls.traps = *trap_list;
//- rjf: get an event
//////////////////////////
//- rjf: get next event
//
DEMON_Event *event = ctrl_thread__next_demon_event(scratch.arena, msg, &run_ctrls, run_spoof);
//////////////////////////
//- rjf: determine event handling
//
B32 hard_stop = 0;
CTRL_EventCause hard_stop_cause = ctrl_event_cause_from_demon_event_kind(event->kind);
B32 use_stepping_logic = 0;
@@ -2356,7 +2389,9 @@ ctrl_thread__run(CTRL_Msg *msg)
}break;
}
//////////////////////////
//- rjf: unpack info about thread attached to event
//
Architecture arch = demon_arch_from_object(event->thread);
U64 reg_size = regs_block_size_from_architecture(arch);
void *thread_regs_block = demon_read_regs(event->thread);
@@ -2382,11 +2417,14 @@ ctrl_thread__run(CTRL_Msg *msg)
temp_end(temp);
}
////////////////////////////////
//- rjf: stepping logic -//
//////////////////////////
//- rjf: stepping logic
//
//{
//////////////////////////
//- rjf: handle if hitting a spoof or baked in trap
//
B32 hit_spoof = 0;
B32 exception_stop = 0;
if(use_stepping_logic)
@@ -2411,28 +2449,9 @@ ctrl_thread__run(CTRL_Msg *msg)
}
}
//- TODO(rjf): Jeff is hitting a bug where a spoof IP (911) has been
// hit by a thread, !!!BUT!!! we seemingly don't catch that until a
// subsequent run of this loop, probably because there are other
// events in the queue that we report first, losing all state about
// spoof mode.
//
// I'm throwing in some detection for this case, so that we can diagnose
// it further from there.
//
if(event->kind == DEMON_EventKind_Exception &&
event->instruction_pointer == 911 &&
(hit_spoof == 0 || spoof_mode == 0))
{
os_graphical_message(1, str8_lit("RADDBG INTERNAL DEVELOPMENT MESSAGE"), str8_lit("a bad, rare bug that Jeff found has been detected to occur - attach with debugger now"));
}
//- rjf: handle spoof hit
if(hit_spoof)
{
// rjf: restore 1 ip
demon_write_ip(target_thread, spoof_1_return_ip);
// rjf: clear spoof mode
spoof_mode = 0;
MemoryZeroStruct(&spoof);
@@ -2675,15 +2694,12 @@ ctrl_thread__run(CTRL_Msg *msg)
{
// rjf: setup spoof mode
begin_spoof_mode = 1;
U64 spoof_sp = demon_read_sp(target_thread);
spoof_mode = 1;
spoof.process = ctrl_handle_from_demon(target_process);
spoof.thread = ctrl_handle_from_demon(target_thread);
spoof.vaddr = spoof_sp;
spoof.new_ip_value = spoof_ip_vaddr;
// rjf: remember 1 return ip
demon_read_memory(target_process, &spoof_1_return_ip, spoof_sp, sizeof(spoof_1_return_ip));
}
}
@@ -2717,7 +2733,8 @@ ctrl_thread__run(CTRL_Msg *msg)
}
//}
//- rjf: stepping logic -//
//
//- rjf: stepping logic
////////////////////////////////
//- rjf: handle step past trap net
@@ -2788,20 +2805,11 @@ ctrl_thread__run(CTRL_Msg *msg)
break;
}
}
//- rjf: unstick silently-hit spoofs
if(stop_event != 0 && stop_event->thread != target_thread && spoof_mode != 0)
{
U64 target_thread_rip = demon_read_ip(target_thread);
if(target_thread_rip == spoof.new_ip_value)
{
// rjf: restore 1 ip
demon_write_ip(target_thread, spoof_1_return_ip);
}
}
}
//////////////////////////////
//- rjf: record stop
//
if(stop_event != 0)
{
CTRL_EventList evts = {0};
+1
View File
@@ -85,6 +85,7 @@ typedef struct CTRL_Spoof CTRL_Spoof;
struct CTRL_Spoof
{
CTRL_Handle process;
CTRL_Handle thread;
U64 vaddr;
U64 new_ip_value;
};