mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-13 07:32:23 -07:00
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:
+50
-42
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user