diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index cc06e979..bee2f0fb 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -3562,9 +3562,15 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, // rjf: run for new events ProfScope("run for new events") { - log_infof("{dmn_ctrl_run ..."); - DMN_EventList events = dmn_ctrl_run(scratch.arena, ctrl_ctx, run_ctrls); + log_infof("dmn_ctrl_run:\n{\n"); + log_infof(" single_step_thread: [0x%I64x]\n", run_ctrls->single_step_thread); + log_infof(" ignore_previous_exception: %i\n", !!run_ctrls->ignore_previous_exception); + log_infof(" run_entities_are_unfrozen: %i\n", !!run_ctrls->run_entities_are_unfrozen); + log_infof(" run_entities_are_processes: %i\n", !!run_ctrls->run_entities_are_processes); + log_infof(" run_entity_count: %I64u\n", run_ctrls->run_entity_count); + log_infof(" trap_count: %I64u\n", run_ctrls->traps.trap_count); log_infof("}\n"); + DMN_EventList events = dmn_ctrl_run(scratch.arena, ctrl_ctx, run_ctrls); for(DMN_EventNode *src_n = events.first; src_n != 0; src_n = src_n->next) { DMN_EventNode *dst_n = ctrl_state->free_dmn_event_node; @@ -4105,11 +4111,21 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) node != 0; node = node->next) { - DMN_RunCtrls run_ctrls = {0}; - run_ctrls.single_step_thread = node->v; - for(B32 done = 0; done == 0;) + DMN_Handle thread = node->v; + U64 thread_pre_rip = dmn_rip_from_thread(thread); + U64 thread_post_rip = thread_pre_rip; + for(B32 done = 0; !done;) { + DMN_RunCtrls run_ctrls = {0}; + run_ctrls.run_entities_are_unfrozen = 1; + run_ctrls.run_entities = &thread; + run_ctrls.run_entity_count = 1; + if(thread_post_rip == thread_pre_rip) + { + run_ctrls.single_step_thread = thread; + } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0); + thread_post_rip = dmn_rip_from_thread(thread); switch(event->kind) { default:{}break; @@ -4124,7 +4140,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) }break; case DMN_EventKind_SingleStep: { - done = 1; + done = dmn_handle_match(node->v, event->thread); }break; } } @@ -4212,6 +4228,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) ////////////////////////// //- rjf: get next run-related event // + log_infof(">>> stepping >>> getting next event\n"); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, run_spoof); ////////////////////////// @@ -4680,11 +4697,21 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) CTRL_EventCause cond_bp_single_step_stop_cause = CTRL_EventCause_Null; if(hit_conditional_bp_but_filtered) { - DMN_RunCtrls single_step_ctrls = {0}; - single_step_ctrls.single_step_thread = event->thread; - for(B32 single_step_done = 0; single_step_done == 0;) + DMN_Handle thread = event->thread; + U64 thread_pre_rip = dmn_rip_from_thread(thread); + U64 thread_post_rip = thread_pre_rip; + for(B32 single_step_done = 0; !single_step_done;) { + DMN_RunCtrls single_step_ctrls = {0}; + single_step_ctrls.run_entities_are_unfrozen = 1; + single_step_ctrls.run_entities = &thread; + single_step_ctrls.run_entity_count = 1; + if(thread_post_rip == thread_pre_rip) + { + single_step_ctrls.single_step_thread = thread; + } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0); + thread_post_rip = dmn_rip_from_thread(thread); switch(event->kind) { default:{}break; @@ -4700,7 +4727,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) }break; case DMN_EventKind_SingleStep: { - single_step_done = 1; + single_step_done = dmn_handle_match(event->thread, thread); cond_bp_single_step_stop_cause = ctrl_event_cause_from_dmn_event_kind(event->kind); }break; } @@ -4759,11 +4786,21 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { if(hit_trap_flags & CTRL_TrapFlag_SingleStepAfterHit) { - DMN_RunCtrls single_step_ctrls = {0}; - single_step_ctrls.single_step_thread = target_thread; + log_infof(">>> stepping >>> trap net logic: single step after hit\n"); + U64 thread_pre_rip = dmn_rip_from_thread(target_thread); + U64 thread_post_rip = thread_pre_rip; for(B32 single_step_done = 0; single_step_done == 0;) { + DMN_RunCtrls single_step_ctrls = {0}; + single_step_ctrls.run_entities_are_unfrozen = 1; + single_step_ctrls.run_entities = &target_thread; + single_step_ctrls.run_entity_count = 1; + if(thread_post_rip == thread_pre_rip) + { + single_step_ctrls.single_step_thread = target_thread; + } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0); + thread_post_rip = dmn_rip_from_thread(target_thread); switch(event->kind) { default:{}break; @@ -4780,7 +4817,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) }break; case DMN_EventKind_SingleStep: { - single_step_done = 1; + single_step_done = dmn_handle_match(event->thread, target_thread);; single_step_stop_cause = ctrl_event_cause_from_dmn_event_kind(event->kind); }break; } @@ -4795,6 +4832,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) if(hit_trap_flags & CTRL_TrapFlag_BeginSpoofMode) { // rjf: setup spoof mode + log_infof(">>> stepping >>> trap net logic: begin spoof mode\n"); begin_spoof_mode = 1; U64 spoof_sp = dmn_rsp_from_thread(target_thread); spoof_mode = 1; @@ -4815,6 +4853,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { save_stack_pointer = 1; sp_check_value = dmn_rsp_from_thread(target_thread); + log_infof(">>> stepping >>> trap net logic: save stack pointer (0x%I64x)\n", sp_check_value); } } } @@ -4828,6 +4867,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) if((hit_trap_flags & CTRL_TrapFlag_IgnoreStackPointerCheck) || stack_pointer_matches) { + log_infof(">>> stepping >>> trap net logic: end stepping\n"); trap_net_stop = 1; use_trap_net_logic = 0; } @@ -4844,11 +4884,22 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) CTRL_EventCause step_past_trap_net_stop_cause = CTRL_EventCause_Null; if(step_past_trap_net) { - DMN_RunCtrls single_step_ctrls = {0}; - single_step_ctrls.single_step_thread = event->thread; + log_infof(">>> stepping >>> trap net logic: single-step non-target-thread (%I64x) past trap net\n", event->thread.u64[0]); + DMN_Handle thread = event->thread; + U64 thread_pre_rip = dmn_rip_from_thread(thread); + U64 thread_post_rip = thread_pre_rip; for(B32 single_step_done = 0; single_step_done == 0;) { + DMN_RunCtrls single_step_ctrls = {0}; + single_step_ctrls.run_entities_are_unfrozen = 1; + single_step_ctrls.run_entities = &thread; + single_step_ctrls.run_entity_count = 1; + if(thread_post_rip == thread_pre_rip) + { + single_step_ctrls.single_step_thread = thread; + } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0); + thread_post_rip = dmn_rip_from_thread(thread); switch(event->kind) { default:{}break; @@ -4863,7 +4914,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) }break; case DMN_EventKind_SingleStep: { - single_step_done = 1; + single_step_done = dmn_handle_match(event->thread, thread); step_past_trap_net_stop_cause = ctrl_event_cause_from_dmn_event_kind(event->kind); }break; } @@ -4955,11 +5006,21 @@ ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) DMN_Event *stop_event = 0; CTRL_EventCause stop_cause = CTRL_EventCause_Null; { - DMN_RunCtrls run_ctrls = {0}; - run_ctrls.single_step_thread = msg->entity; + DMN_Handle thread = msg->entity; + U64 thread_pre_rip = dmn_rip_from_thread(thread); + U64 thread_post_rip = thread_pre_rip; for(B32 done = 0; done == 0;) { + DMN_RunCtrls run_ctrls = {0}; + run_ctrls.run_entities_are_unfrozen = 1; + run_ctrls.run_entities = &thread; + run_ctrls.run_entity_count = 1; + if(thread_post_rip == thread_pre_rip) + { + run_ctrls.single_step_thread = msg->entity; + } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0); + thread_post_rip = dmn_rip_from_thread(msg->entity); switch(event->kind) { default:{}break; @@ -4967,8 +5028,8 @@ ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) case DMN_EventKind_Exception: {stop_cause = CTRL_EventCause_InterruptedByException;}goto end_single_step; case DMN_EventKind_Halt: {stop_cause = CTRL_EventCause_InterruptedByHalt;}goto end_single_step; case DMN_EventKind_Trap: {stop_cause = CTRL_EventCause_InterruptedByTrap;}goto end_single_step; - case DMN_EventKind_SingleStep: {stop_cause = CTRL_EventCause_Finished;}goto end_single_step; case DMN_EventKind_Breakpoint: {stop_cause = CTRL_EventCause_UserBreakpoint;}goto end_single_step; + case DMN_EventKind_SingleStep: {stop_cause = CTRL_EventCause_Finished;}goto end_single_step; end_single_step: { stop_event = event; diff --git a/src/demon/win32/demon_core_win32.c b/src/demon/win32/demon_core_win32.c index 1d865093..71679442 100644 --- a/src/demon/win32/demon_core_win32.c +++ b/src/demon/win32/demon_core_win32.c @@ -1449,7 +1449,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) if(single_step_thread_ctx != 0) { U64 rflags = single_step_thread_ctx->EFlags|0x2; - U64 new_rflags = rflags |= 0x100; + U64 new_rflags = rflags | 0x100; single_step_thread_ctx->EFlags = new_rflags; SetThreadContext(thread->handle, single_step_thread_ctx); ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen); @@ -1517,10 +1517,9 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) B32 is_frozen = 0; { // rjf: single-step? freeze if not the single-step thread. - if(!dmn_handle_match(dmn_handle_zero(), ctrls->single_step_thread) && - !dmn_handle_match(dmn_w32_handle_from_entity(thread), ctrls->single_step_thread)) + if(!dmn_handle_match(dmn_handle_zero(), ctrls->single_step_thread)) { - is_frozen = 1; + is_frozen = !dmn_handle_match(dmn_w32_handle_from_entity(thread), ctrls->single_step_thread); } // rjf: not single-stepping? determine based on run controls freezing info @@ -2430,7 +2429,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) if(ctx != 0) { U64 rflags = single_step_thread_ctx->EFlags|0x2; - U64 new_rflags = rflags &= ~0x100; + U64 new_rflags = rflags & ~0x100; single_step_thread_ctx->EFlags = new_rflags; SetThreadContext(thread->handle, single_step_thread_ctx); ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen); diff --git a/src/demon/win32/demon_core_win32.h b/src/demon/win32/demon_core_win32.h index 04c955c8..f3cbb398 100644 --- a/src/demon/win32/demon_core_win32.h +++ b/src/demon/win32/demon_core_win32.h @@ -54,6 +54,8 @@ #define DMN_W32_EXCEPTION_NO_MEMORY 0xC0000017u #define DMN_W32_EXCEPTION_THROW 0xE06D7363u #define DMN_W32_EXCEPTION_SET_THREAD_NAME 0x406d1388u +#define DMN_w32_EXCEPTION_CLRDBG_NOTIFICATION 0x04242420u +#define DMN_w32_EXCEPTION_CLR 0xE0434352u //////////////////////////////// //~ rjf: Win32 Register Codes