extend demon2 with explicit separation between blocking ctrl mechanisms & passive access/introspection/writing mechanisms; extend demon2 api with access mechanism

This commit is contained in:
Ryan Fleury
2024-03-22 15:53:04 -07:00
parent 07bbf1b43c
commit c636e1ad2e
6 changed files with 293 additions and 195 deletions
+35 -34
View File
@@ -1717,6 +1717,7 @@ ctrl_thread__entry_point(void *p)
{ {
ThreadNameF("[ctrl] thread"); ThreadNameF("[ctrl] thread");
ProfBeginFunction(); ProfBeginFunction();
DMN_CtrlCtx *ctrl_ctx = dmn_ctrl_begin();
//- rjf: loop //- rjf: loop
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
@@ -1746,13 +1747,13 @@ ctrl_thread__entry_point(void *p)
case CTRL_MsgKind_COUNT:{}break; case CTRL_MsgKind_COUNT:{}break;
//- rjf: target operations //- rjf: target operations
case CTRL_MsgKind_LaunchAndHandshake:{ctrl_thread__launch_and_handshake(msg);}break; case CTRL_MsgKind_LaunchAndHandshake:{ctrl_thread__launch_and_handshake(ctrl_ctx, msg);}break;
case CTRL_MsgKind_LaunchAndInit: {ctrl_thread__launch_and_init (msg);}break; case CTRL_MsgKind_LaunchAndInit: {ctrl_thread__launch_and_init (ctrl_ctx, msg);}break;
case CTRL_MsgKind_Attach: {ctrl_thread__attach (msg);}break; case CTRL_MsgKind_Attach: {ctrl_thread__attach (ctrl_ctx, msg);}break;
case CTRL_MsgKind_Kill: {ctrl_thread__kill (msg);}break; case CTRL_MsgKind_Kill: {ctrl_thread__kill (ctrl_ctx, msg);}break;
case CTRL_MsgKind_Detach: {ctrl_thread__detach (msg);}break; case CTRL_MsgKind_Detach: {ctrl_thread__detach (ctrl_ctx, msg);}break;
case CTRL_MsgKind_Run: {ctrl_thread__run (msg); done = 1;}break; case CTRL_MsgKind_Run: {ctrl_thread__run (ctrl_ctx, msg); done = 1;}break;
case CTRL_MsgKind_SingleStep: {ctrl_thread__single_step (msg); done = 1;}break; case CTRL_MsgKind_SingleStep: {ctrl_thread__single_step (ctrl_ctx, msg); done = 1;}break;
//- rjf: configuration //- rjf: configuration
case CTRL_MsgKind_SetUserEntryPoints: case CTRL_MsgKind_SetUserEntryPoints:
@@ -1899,7 +1900,7 @@ ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_MachineID
//- rjf: attached process running/event gathering //- rjf: attached process running/event gathering
internal DMN_Event * internal DMN_Event *
ctrl_thread__next_dmn_event(Arena *arena, CTRL_Msg *msg, DMN_RunCtrls *run_ctrls, CTRL_Spoof *spoof) ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, DMN_RunCtrls *run_ctrls, CTRL_Spoof *spoof)
{ {
ProfBeginFunction(); ProfBeginFunction();
DMN_Event *event = push_array(arena, DMN_Event, 1); DMN_Event *event = push_array(arena, DMN_Event, 1);
@@ -2042,8 +2043,8 @@ ctrl_thread__next_dmn_event(Arena *arena, CTRL_Msg *msg, DMN_RunCtrls *run_ctrls
} }
} }
//- rjf: no event -> dmn_run for a new one //- rjf: no event -> dmn_ctrl_run for a new one
if(got_event == 0) ProfScope("no event -> dmn_run for a new one") if(got_event == 0) ProfScope("no event -> dmn_ctrl_run for a new one")
{ {
// rjf: prep spoof // rjf: prep spoof
B32 do_spoof = (spoof != 0 && dmn_handle_match(run_ctrls->single_step_thread, dmn_handle_zero())); B32 do_spoof = (spoof != 0 && dmn_handle_match(run_ctrls->single_step_thread, dmn_handle_zero()));
@@ -2065,7 +2066,7 @@ ctrl_thread__next_dmn_event(Arena *arena, CTRL_Msg *msg, DMN_RunCtrls *run_ctrls
// rjf: run for new events // rjf: run for new events
ProfScope("run for new events") ProfScope("run for new events")
{ {
DMN_EventList events = dmn_run(scratch.arena, run_ctrls); 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) 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; DMN_EventNode *dst_n = ctrl_state->free_dmn_event_node;
@@ -2255,7 +2256,7 @@ ctrl_eval_memory_read(void *u, void *out, U64 addr, U64 size)
//- rjf: msg kind implementations //- rjf: msg kind implementations
internal void internal void
ctrl_thread__launch_and_handshake(CTRL_Msg *msg) ctrl_thread__launch_and_handshake(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
{ {
ProfBeginFunction(); ProfBeginFunction();
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
@@ -2269,7 +2270,7 @@ ctrl_thread__launch_and_handshake(CTRL_Msg *msg)
opts.env = msg->env_string_list; opts.env = msg->env_string_list;
opts.inherit_env = msg->env_inherit; opts.inherit_env = msg->env_inherit;
} }
U32 id = dmn_launch_process(&opts); U32 id = dmn_ctrl_launch(ctrl_ctx, &opts);
//- rjf: record start //- rjf: record start
{ {
@@ -2296,7 +2297,7 @@ ctrl_thread__launch_and_handshake(CTRL_Msg *msg)
// rjf: run until handshake-signifying events // rjf: run until handshake-signifying events
for(B32 done = 0; done == 0;) for(B32 done = 0; done == 0;)
{ {
DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, msg, &run_ctrls, 0); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0);
switch(event->kind) switch(event->kind)
{ {
default:{}break; default:{}break;
@@ -2363,7 +2364,7 @@ ctrl_thread__launch_and_handshake(CTRL_Msg *msg)
} }
internal void internal void
ctrl_thread__launch_and_init(CTRL_Msg *msg) ctrl_thread__launch_and_init(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
{ {
ProfBeginFunction(); ProfBeginFunction();
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
@@ -2378,7 +2379,7 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
opts.env = msg->env_string_list; opts.env = msg->env_string_list;
opts.inherit_env = msg->env_inherit; opts.inherit_env = msg->env_inherit;
} }
U32 id = dmn_launch_process(&opts); U32 id = dmn_ctrl_launch(ctrl_ctx, &opts);
////////////////////////////// //////////////////////////////
//- rjf: record start //- rjf: record start
@@ -2402,7 +2403,7 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
run_ctrls.run_entities_are_processes = 1; run_ctrls.run_entities_are_processes = 1;
for(B32 done = 0; done == 0;) for(B32 done = 0; done == 0;)
{ {
DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, msg, &run_ctrls, 0); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0);
switch(event->kind) switch(event->kind)
{ {
default:{}break; default:{}break;
@@ -2686,14 +2687,14 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
} }
internal void internal void
ctrl_thread__attach(CTRL_Msg *msg) ctrl_thread__attach(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
{ {
ProfBeginFunction(); ProfBeginFunction();
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
DBGI_Scope *scope = dbgi_scope_open(); DBGI_Scope *scope = dbgi_scope_open();
//- rjf: attach //- rjf: attach
B32 attach_successful = dmn_attach_process(msg->entity_id); B32 attach_successful = dmn_ctrl_attach(ctrl_ctx, msg->entity_id);
//- rjf: run to handshake //- rjf: run to handshake
if(attach_successful) if(attach_successful)
@@ -2704,7 +2705,7 @@ ctrl_thread__attach(CTRL_Msg *msg)
run_ctrls.run_entities_are_processes = 1; run_ctrls.run_entities_are_processes = 1;
for(B32 done = 0; done == 0;) for(B32 done = 0; done == 0;)
{ {
DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, msg, &run_ctrls, 0); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0);
switch(event->kind) switch(event->kind)
{ {
default:{}break; default:{}break;
@@ -2739,7 +2740,7 @@ ctrl_thread__attach(CTRL_Msg *msg)
} }
internal void internal void
ctrl_thread__kill(CTRL_Msg *msg) ctrl_thread__kill(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
{ {
ProfBeginFunction(); ProfBeginFunction();
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
@@ -2748,7 +2749,7 @@ ctrl_thread__kill(CTRL_Msg *msg)
U32 exit_code = msg->exit_code; U32 exit_code = msg->exit_code;
//- rjf: send kill //- rjf: send kill
B32 kill_worked = dmn_kill_process(process, exit_code); B32 kill_worked = dmn_ctrl_kill(ctrl_ctx, process, exit_code);
//- rjf: wait for process to be dead //- rjf: wait for process to be dead
if(kill_worked) if(kill_worked)
@@ -2760,7 +2761,7 @@ ctrl_thread__kill(CTRL_Msg *msg)
run_ctrls.run_entity_count = 1; run_ctrls.run_entity_count = 1;
for(B32 done = 0; done == 0;) for(B32 done = 0; done == 0;)
{ {
DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, msg, &run_ctrls, 0); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0);
if(event->kind == DMN_EventKind_ExitProcess && dmn_handle_match(event->process, process)) if(event->kind == DMN_EventKind_ExitProcess && dmn_handle_match(event->process, process))
{ {
done = 1; done = 1;
@@ -2788,7 +2789,7 @@ ctrl_thread__kill(CTRL_Msg *msg)
} }
internal void internal void
ctrl_thread__detach(CTRL_Msg *msg) ctrl_thread__detach(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
{ {
ProfBeginFunction(); ProfBeginFunction();
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
@@ -2796,7 +2797,7 @@ ctrl_thread__detach(CTRL_Msg *msg)
DMN_Handle process = msg->entity; DMN_Handle process = msg->entity;
//- rjf: detach //- rjf: detach
B32 detach_worked = dmn_detach_process(process); B32 detach_worked = dmn_ctrl_detach(ctrl_ctx, process);
//- rjf: wait for process to be dead //- rjf: wait for process to be dead
if(detach_worked) if(detach_worked)
@@ -2808,7 +2809,7 @@ ctrl_thread__detach(CTRL_Msg *msg)
run_ctrls.run_entity_count = 1; run_ctrls.run_entity_count = 1;
for(B32 done = 0; done == 0;) for(B32 done = 0; done == 0;)
{ {
DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, msg, &run_ctrls, 0); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0);
if(event->kind == DMN_EventKind_ExitProcess && dmn_handle_match(event->process, process)) if(event->kind == DMN_EventKind_ExitProcess && dmn_handle_match(event->process, process))
{ {
done = 1; done = 1;
@@ -2836,7 +2837,7 @@ ctrl_thread__detach(CTRL_Msg *msg)
} }
internal void internal void
ctrl_thread__run(CTRL_Msg *msg) ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
{ {
ProfBeginFunction(); ProfBeginFunction();
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
@@ -2959,7 +2960,7 @@ ctrl_thread__run(CTRL_Msg *msg)
run_ctrls.single_step_thread = node->v; run_ctrls.single_step_thread = node->v;
for(B32 done = 0; done == 0;) for(B32 done = 0; done == 0;)
{ {
DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, msg, &run_ctrls, 0); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0);
switch(event->kind) switch(event->kind)
{ {
default:{}break; default:{}break;
@@ -3062,7 +3063,7 @@ ctrl_thread__run(CTRL_Msg *msg)
////////////////////////// //////////////////////////
//- rjf: get next event //- rjf: get next event
// //
DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, msg, &run_ctrls, run_spoof); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, run_spoof);
////////////////////////// //////////////////////////
//- rjf: determine event handling //- rjf: determine event handling
@@ -3298,7 +3299,7 @@ ctrl_thread__run(CTRL_Msg *msg)
single_step_ctrls.single_step_thread = event->thread; single_step_ctrls.single_step_thread = event->thread;
for(B32 single_step_done = 0; single_step_done == 0;) for(B32 single_step_done = 0; single_step_done == 0;)
{ {
DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, msg, &single_step_ctrls, 0); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0);
switch(event->kind) switch(event->kind)
{ {
default:{}break; default:{}break;
@@ -3369,7 +3370,7 @@ ctrl_thread__run(CTRL_Msg *msg)
single_step_ctrls.single_step_thread = target_thread; single_step_ctrls.single_step_thread = target_thread;
for(B32 single_step_done = 0; single_step_done == 0;) for(B32 single_step_done = 0; single_step_done == 0;)
{ {
DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, msg, &single_step_ctrls, 0); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0);
switch(event->kind) switch(event->kind)
{ {
default:{}break; default:{}break;
@@ -3454,7 +3455,7 @@ ctrl_thread__run(CTRL_Msg *msg)
single_step_ctrls.single_step_thread = event->thread; single_step_ctrls.single_step_thread = event->thread;
for(B32 single_step_done = 0; single_step_done == 0;) for(B32 single_step_done = 0; single_step_done == 0;)
{ {
DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, msg, &single_step_ctrls, 0); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0);
switch(event->kind) switch(event->kind)
{ {
default:{}break; default:{}break;
@@ -3539,7 +3540,7 @@ ctrl_thread__run(CTRL_Msg *msg)
} }
internal void internal void
ctrl_thread__single_step(CTRL_Msg *msg) ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
{ {
ProfBeginFunction(); ProfBeginFunction();
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
@@ -3561,7 +3562,7 @@ ctrl_thread__single_step(CTRL_Msg *msg)
run_ctrls.single_step_thread = msg->entity; run_ctrls.single_step_thread = msg->entity;
for(B32 done = 0; done == 0;) for(B32 done = 0; done == 0;)
{ {
DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, msg, &run_ctrls, 0); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0);
switch(event->kind) switch(event->kind)
{ {
default:{}break; default:{}break;
+10 -10
View File
@@ -699,23 +699,23 @@ internal CTRL_EventList ctrl_c2u_pop_events(Arena *arena);
internal void ctrl_thread__entry_point(void *p); internal void ctrl_thread__entry_point(void *p);
//- rjf: breakpoint resolution //- rjf: breakpoint resolution
internal void ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_MachineID machine_id, DMN_Handle process, DMN_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out); internal void ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_MachineID machine_id, DMN_Handle process, DMN_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_MachineID machine_id, DMN_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out); internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_MachineID machine_id, DMN_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
//- rjf: attached process running/event gathering //- rjf: attached process running/event gathering
internal DMN_Event *ctrl_thread__next_dmn_event(Arena *arena, CTRL_Msg *msg, DMN_RunCtrls *run_ctrls, CTRL_Spoof *spoof); internal DMN_Event *ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, DMN_RunCtrls *run_ctrls, CTRL_Spoof *spoof);
//- rjf: eval helpers //- rjf: eval helpers
internal B32 ctrl_eval_memory_read(void *u, void *out, U64 addr, U64 size); internal B32 ctrl_eval_memory_read(void *u, void *out, U64 addr, U64 size);
//- rjf: msg kind implementations //- rjf: msg kind implementations
internal void ctrl_thread__launch_and_handshake(CTRL_Msg *msg); internal void ctrl_thread__launch_and_handshake(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
internal void ctrl_thread__launch_and_init(CTRL_Msg *msg); internal void ctrl_thread__launch_and_init(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
internal void ctrl_thread__attach(CTRL_Msg *msg); internal void ctrl_thread__attach(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
internal void ctrl_thread__kill(CTRL_Msg *msg); internal void ctrl_thread__kill(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
internal void ctrl_thread__detach(CTRL_Msg *msg); internal void ctrl_thread__detach(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
internal void ctrl_thread__run(CTRL_Msg *msg); internal void ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
internal void ctrl_thread__single_step(CTRL_Msg *msg); internal void ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
//////////////////////////////// ////////////////////////////////
//~ rjf: Memory-Stream Thread Functions //~ rjf: Memory-Stream Thread Functions
+25 -5
View File
@@ -4,6 +4,20 @@
#ifndef DEMON2_CORE_H #ifndef DEMON2_CORE_H
#define DEMON2_CORE_H #define DEMON2_CORE_H
////////////////////////////////
//~ rjf: Control-Thread-Only Context
//
// An instance of this struct must ONLY be returned by dmn_ctrl_begin, and only
// used by the thread which called it. All APIs which can ONLY run on the
// control thread, which blocks to control & receive events, will take this
// parameter. All other APIs can be called from any thread.
typedef struct DMN_CtrlCtx DMN_CtrlCtx;
struct DMN_CtrlCtx
{
U64 u64 [1];
};
//////////////////////////////// ////////////////////////////////
//~ rjf: Handle Types //~ rjf: Handle Types
@@ -174,11 +188,12 @@ internal void dmn_init(void);
//////////////////////////////// ////////////////////////////////
//~ rjf: @dmn_os_hooks Blocking Control Thread Operations (Implemented Per-OS) //~ rjf: @dmn_os_hooks Blocking Control Thread Operations (Implemented Per-OS)
internal U32 dmn_launch_process(OS_LaunchOptions *options); internal DMN_CtrlCtx *dmn_ctrl_begin(void);
internal B32 dmn_attach_process(U32 pid); internal U32 dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_LaunchOptions *options);
internal B32 dmn_kill_process(DMN_Handle process, U32 exit_code); internal B32 dmn_ctrl_attach(DMN_CtrlCtx *ctx, U32 pid);
internal B32 dmn_detach_process(DMN_Handle process); internal B32 dmn_ctrl_kill(DMN_CtrlCtx *ctx, DMN_Handle process, U32 exit_code);
internal DMN_EventList dmn_run(Arena *arena, DMN_RunCtrls *ctrls); internal B32 dmn_ctrl_detach(DMN_CtrlCtx *ctx, DMN_Handle process);
internal DMN_EventList dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls);
//////////////////////////////// ////////////////////////////////
//~ rjf: @dmn_os_hooks Halting (Implemented Per-OS) //~ rjf: @dmn_os_hooks Halting (Implemented Per-OS)
@@ -193,6 +208,11 @@ internal U64 dmn_run_gen(void);
internal U64 dmn_mem_gen(void); internal U64 dmn_mem_gen(void);
internal U64 dmn_reg_gen(void); internal U64 dmn_reg_gen(void);
//- rjf: non-blocking-control-thread access barriers
internal B32 dmn_access_open(void);
internal void dmn_access_close(void);
#define DMN_AccessScope DeferLoopChecked(dmn_access_open(), dmn_access_close())
//- rjf: processes //- rjf: processes
internal U64 dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst); internal U64 dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst);
internal B32 dmn_process_write(DMN_Handle process, Rng1U64 range, void *src); internal B32 dmn_process_write(DMN_Handle process, Rng1U64 range, void *src);
+207 -136
View File
@@ -1073,6 +1073,7 @@ dmn_init(void)
Arena *arena = arena_alloc(); Arena *arena = arena_alloc();
dmn_w32_shared = push_array(arena, DMN_W32_Shared, 1); dmn_w32_shared = push_array(arena, DMN_W32_Shared, 1);
dmn_w32_shared->arena = arena; dmn_w32_shared->arena = arena;
dmn_w32_shared->access_mutex = os_mutex_alloc();
dmn_w32_shared->detach_arena = arena_alloc(); dmn_w32_shared->detach_arena = arena_alloc();
dmn_w32_shared->entities_arena = arena_alloc__sized(GB(8), KB(64)); dmn_w32_shared->entities_arena = arena_alloc__sized(GB(8), KB(64));
dmn_w32_shared->entities_base = dmn_w32_entity_alloc(&dmn_w32_entity_nil, DMN_W32_EntityKind_Root, 0); dmn_w32_shared->entities_base = dmn_w32_entity_alloc(&dmn_w32_entity_nil, DMN_W32_EntityKind_Root, 0);
@@ -1110,102 +1111,111 @@ dmn_init(void)
//////////////////////////////// ////////////////////////////////
//~ rjf: @dmn_os_hooks Blocking Control Thread Operations (Implemented Per-OS) //~ rjf: @dmn_os_hooks Blocking Control Thread Operations (Implemented Per-OS)
internal DMN_CtrlCtx *
dmn_ctrl_begin(void)
{
DMN_CtrlCtx *ctx = (DMN_CtrlCtx *)1;
dmn_w32_ctrl_thread = 1;
return ctx;
}
internal U32 internal U32
dmn_launch_process(OS_LaunchOptions *options) dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_LaunchOptions *options)
{ {
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
U32 result = 0; U32 result = 0;
DMN_AccessScope
//- rjf: produce exe / arguments string
String8 cmd = {0};
if(options->cmd_line.first != 0)
{ {
String8List args = {0}; //- rjf: produce exe / arguments string
String8 exe_path = options->cmd_line.first->string; String8 cmd = {0};
str8_list_pushf(scratch.arena, &args, "\"%S\"", exe_path); if(options->cmd_line.first != 0)
for(String8Node *n = options->cmd_line.first->next; n != 0; n = n->next)
{ {
str8_list_push(scratch.arena, &args, n->string); String8List args = {0};
} String8 exe_path = options->cmd_line.first->string;
StringJoin join_params = {0}; str8_list_pushf(scratch.arena, &args, "\"%S\"", exe_path);
join_params.sep = str8_lit(" "); for(String8Node *n = options->cmd_line.first->next; n != 0; n = n->next)
cmd = str8_list_join(scratch.arena, &args, &join_params);
}
//- rjf: produce environment strings
String8 env = {0};
{
String8List all_opts = options->env;
if(options->inherit_env != 0)
{
MemoryZeroStruct(&all_opts);
str8_list_push(scratch.arena, &all_opts, str8_lit("_NO_DEBUG_HEAP=1"));
for(String8Node *n = options->env.first; n != 0; n = n->next)
{ {
str8_list_push(scratch.arena, &all_opts, n->string); str8_list_push(scratch.arena, &args, n->string);
}
for(String8Node *n = dmn_w32_shared->env_strings.first; n != 0; n = n->next)
{
str8_list_push(scratch.arena, &all_opts, n->string);
} }
StringJoin join_params = {0};
join_params.sep = str8_lit(" ");
cmd = str8_list_join(scratch.arena, &args, &join_params);
} }
StringJoin join_params2 = {0};
join_params2.sep = str8_lit("\0");
join_params2.post = str8_lit("\0");
env = str8_list_join(scratch.arena, &all_opts, &join_params2);
}
//- rjf: produce utf-16 strings //- rjf: produce environment strings
String16 cmd16 = str16_from_8(scratch.arena, cmd); String8 env = {0};
String16 dir16 = str16_from_8(scratch.arena, options->path);
String16 env16 = str16_from_8(scratch.arena, env);
//- rjf: launch
DWORD access_flags = CREATE_UNICODE_ENVIRONMENT|DEBUG_PROCESS;
STARTUPINFOW startup_info = {sizeof(startup_info)};
PROCESS_INFORMATION process_info = {0};
AllocConsole();
if(CreateProcessW(0, (WCHAR*)cmd16.str, 0, 0, 1, access_flags, (WCHAR*)env16.str, (WCHAR*)dir16.str, &startup_info, &process_info))
{
// check if we are 32-bit app, and just close it immediately
BOOL is_wow = 0;
IsWow64Process(process_info.hProcess, &is_wow);
if(is_wow)
{ {
MessageBox(0, "Sorry, The RAD Debugger only debugs 64-bit applications currently.", "Process error", MB_OK|MB_ICONSTOP); String8List all_opts = options->env;
DebugActiveProcessStop(process_info.dwProcessId); if(options->inherit_env != 0)
TerminateProcess(process_info.hProcess,0xffffffff); {
MemoryZeroStruct(&all_opts);
str8_list_push(scratch.arena, &all_opts, str8_lit("_NO_DEBUG_HEAP=1"));
for(String8Node *n = options->env.first; n != 0; n = n->next)
{
str8_list_push(scratch.arena, &all_opts, n->string);
}
for(String8Node *n = dmn_w32_shared->env_strings.first; n != 0; n = n->next)
{
str8_list_push(scratch.arena, &all_opts, n->string);
}
}
StringJoin join_params2 = {0};
join_params2.sep = str8_lit("\0");
join_params2.post = str8_lit("\0");
env = str8_list_join(scratch.arena, &all_opts, &join_params2);
}
//- rjf: produce utf-16 strings
String16 cmd16 = str16_from_8(scratch.arena, cmd);
String16 dir16 = str16_from_8(scratch.arena, options->path);
String16 env16 = str16_from_8(scratch.arena, env);
//- rjf: launch
DWORD access_flags = CREATE_UNICODE_ENVIRONMENT|DEBUG_PROCESS;
STARTUPINFOW startup_info = {sizeof(startup_info)};
PROCESS_INFORMATION process_info = {0};
AllocConsole();
if(CreateProcessW(0, (WCHAR*)cmd16.str, 0, 0, 1, access_flags, (WCHAR*)env16.str, (WCHAR*)dir16.str, &startup_info, &process_info))
{
// check if we are 32-bit app, and just close it immediately
BOOL is_wow = 0;
IsWow64Process(process_info.hProcess, &is_wow);
if(is_wow)
{
MessageBox(0, "Sorry, The RAD Debugger only debugs 64-bit applications currently.", "Process error", MB_OK|MB_ICONSTOP);
DebugActiveProcessStop(process_info.dwProcessId);
TerminateProcess(process_info.hProcess,0xffffffff);
}
else
{
result = process_info.dwProcessId;
dmn_w32_shared->new_process_pending = 1;
}
CloseHandle(process_info.hProcess);
CloseHandle(process_info.hThread);
} }
else else
{ {
result = process_info.dwProcessId; MessageBox(0, "Error starting process.", "Process error", MB_OK|MB_ICONSTOP);
dmn_w32_shared->new_process_pending = 1;
} }
CloseHandle(process_info.hProcess); FreeConsole();
CloseHandle(process_info.hThread);
}
else
{
MessageBox(0, "Error starting process.", "Process error", MB_OK|MB_ICONSTOP);
}
FreeConsole();
//- rjf: eliminate all handles which have stuck around from the AllocConsole //- rjf: eliminate all handles which have stuck around from the AllocConsole
{ {
SetStdHandle(STD_INPUT_HANDLE, 0); SetStdHandle(STD_INPUT_HANDLE, 0);
SetStdHandle(STD_OUTPUT_HANDLE, 0); SetStdHandle(STD_OUTPUT_HANDLE, 0);
SetStdHandle(STD_ERROR_HANDLE, 0); SetStdHandle(STD_ERROR_HANDLE, 0);
}
} }
scratch_end(scratch); scratch_end(scratch);
return result; return result;
} }
internal B32 internal B32
dmn_attach_process(U32 pid) dmn_ctrl_attach(DMN_CtrlCtx *ctx, U32 pid)
{ {
B32 result = 0; B32 result = 0;
if(DebugActiveProcess((DWORD)pid)) DMN_AccessScope if(DebugActiveProcess((DWORD)pid))
{ {
result = 1; result = 1;
dmn_w32_shared->new_process_pending = 1; dmn_w32_shared->new_process_pending = 1;
@@ -1214,57 +1224,63 @@ dmn_attach_process(U32 pid)
} }
internal B32 internal B32
dmn_kill_process(DMN_Handle process, U32 exit_code) dmn_ctrl_kill(DMN_CtrlCtx *ctx, DMN_Handle process, U32 exit_code)
{ {
B32 result = 0; B32 result = 0;
DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); DMN_AccessScope
if(TerminateProcess(process_entity->handle, exit_code))
{ {
result = 1; DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process);
if(TerminateProcess(process_entity->handle, exit_code))
{
result = 1;
}
} }
return result; return result;
} }
internal B32 internal B32
dmn_detach_process(DMN_Handle process) dmn_ctrl_detach(DMN_CtrlCtx *ctx, DMN_Handle process)
{ {
B32 result = 0; B32 result = 0;
DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); DMN_AccessScope
// rjf: resume threads
for(DMN_W32_Entity *child = process_entity->first;
child != &dmn_w32_entity_nil;
child = child->next)
{ {
if(child->kind == DMN_W32_EntityKind_Thread) DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process);
// rjf: resume threads
for(DMN_W32_Entity *child = process_entity->first;
child != &dmn_w32_entity_nil;
child = child->next)
{ {
DWORD resume_result = ResumeThread(child->handle); if(child->kind == DMN_W32_EntityKind_Thread)
(void)resume_result; {
DWORD resume_result = ResumeThread(child->handle);
(void)resume_result;
}
}
// rjf: detach
{
DWORD pid = (DWORD)process_entity->id;
if(DebugActiveProcessStop(pid))
{
result = 1;
}
}
// rjf: push into list of processes to generate events for later
if(result != 0)
{
dmn_handle_list_push(dmn_w32_shared->detach_arena, &dmn_w32_shared->detach_processes, process);
} }
} }
// rjf: detach
{
DWORD pid = (DWORD)process_entity->id;
if(DebugActiveProcessStop(pid))
{
result = 1;
}
}
// rjf: push into list of processes to generate events for later
if(result != 0)
{
dmn_handle_list_push(dmn_w32_shared->detach_arena, &dmn_w32_shared->detach_processes, process);
}
return result; return result;
} }
internal DMN_EventList internal DMN_EventList
dmn_run(Arena *arena, DMN_RunCtrls *ctrls) dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
{ {
DMN_EventList events = {0}; DMN_EventList events = {0};
dmn_access_open();
////////////////////////////// //////////////////////////////
//- rjf: determine event generation path //- rjf: determine event generation path
@@ -2319,6 +2335,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
}break; }break;
} }
dmn_access_close();
return events; return events;
} }
@@ -2378,21 +2395,56 @@ dmn_reg_gen(void)
return result; return result;
} }
//- rjf: non-blocking-control-thread access barriers
internal B32
dmn_access_open(void)
{
B32 result = 0;
if(dmn_w32_ctrl_thread)
{
result = 1;
}
else
{
os_mutex_take(dmn_w32_shared->access_mutex);
result = !dmn_w32_shared->access_run_state;
}
return result;
}
internal void
dmn_access_close(void)
{
if(!dmn_w32_ctrl_thread)
{
os_mutex_drop(dmn_w32_shared->access_mutex);
}
}
//- rjf: processes //- rjf: processes
internal U64 internal U64
dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst) dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst)
{ {
DMN_W32_Entity *entity = dmn_w32_entity_from_handle(process); U64 result = 0;
U64 result = dmn_w32_process_read(entity->handle, range, dst); DMN_AccessScope
{
DMN_W32_Entity *entity = dmn_w32_entity_from_handle(process);
result = dmn_w32_process_read(entity->handle, range, dst);
}
return result; return result;
} }
internal B32 internal B32
dmn_process_write(DMN_Handle process, Rng1U64 range, void *src) dmn_process_write(DMN_Handle process, Rng1U64 range, void *src)
{ {
DMN_W32_Entity *entity = dmn_w32_entity_from_handle(process); B32 result = 0;
B32 result = dmn_w32_process_write(entity->handle, range, src); DMN_AccessScope
{
DMN_W32_Entity *entity = dmn_w32_entity_from_handle(process);
result = dmn_w32_process_write(entity->handle, range, src);
}
return result; return result;
} }
@@ -2401,37 +2453,45 @@ dmn_process_write(DMN_Handle process, Rng1U64 range, void *src)
internal Architecture internal Architecture
dmn_arch_from_thread(DMN_Handle handle) dmn_arch_from_thread(DMN_Handle handle)
{ {
DMN_W32_Entity *entity = dmn_w32_entity_from_handle(handle); Architecture arch = Architecture_Null;
return entity->arch; DMN_AccessScope
{
DMN_W32_Entity *entity = dmn_w32_entity_from_handle(handle);
arch = entity->arch;
}
return arch;
} }
internal U64 internal U64
dmn_stack_base_vaddr_from_thread(DMN_Handle handle) dmn_stack_base_vaddr_from_thread(DMN_Handle handle)
{ {
U64 result = 0; U64 result = 0;
DMN_W32_Entity *thread = dmn_w32_entity_from_handle(handle); DMN_AccessScope
if(thread->kind == DMN_W32_EntityKind_Thread)
{ {
DMN_W32_Entity *process = thread->parent; DMN_W32_Entity *thread = dmn_w32_entity_from_handle(handle);
U64 tlb = thread->thread.thread_local_base; if(thread->kind == DMN_W32_EntityKind_Thread)
switch(thread->arch)
{ {
case Architecture_Null: DMN_W32_Entity *process = thread->parent;
case Architecture_COUNT: U64 tlb = thread->thread.thread_local_base;
{}break; switch(thread->arch)
case Architecture_arm64:
case Architecture_arm32:
{NotImplemented;}break;
case Architecture_x64:
{ {
U64 stack_base_addr = tlb + 0x8; case Architecture_Null:
dmn_w32_process_read(process->handle, r1u64(stack_base_addr, stack_base_addr+8), &result); case Architecture_COUNT:
}break; {}break;
case Architecture_x86: case Architecture_arm64:
{ case Architecture_arm32:
U64 stack_base_addr = tlb + 0x4; {NotImplemented;}break;
dmn_w32_process_read(process->handle, r1u64(stack_base_addr, stack_base_addr+4), &result); case Architecture_x64:
}break; {
U64 stack_base_addr = tlb + 0x8;
dmn_w32_process_read(process->handle, r1u64(stack_base_addr, stack_base_addr+8), &result);
}break;
case Architecture_x86:
{
U64 stack_base_addr = tlb + 0x4;
dmn_w32_process_read(process->handle, r1u64(stack_base_addr, stack_base_addr+4), &result);
}break;
}
} }
} }
return result; return result;
@@ -2441,10 +2501,13 @@ internal U64
dmn_tls_root_vaddr_from_thread(DMN_Handle handle) dmn_tls_root_vaddr_from_thread(DMN_Handle handle)
{ {
U64 result = 0; U64 result = 0;
DMN_W32_Entity *entity = dmn_w32_entity_from_handle(handle); DMN_AccessScope
if(entity->kind == DMN_W32_EntityKind_Thread)
{ {
result = entity->thread.thread_local_base; DMN_W32_Entity *entity = dmn_w32_entity_from_handle(handle);
if(entity->kind == DMN_W32_EntityKind_Thread)
{
result = entity->thread.thread_local_base;
}
} }
return result; return result;
} }
@@ -2452,16 +2515,24 @@ dmn_tls_root_vaddr_from_thread(DMN_Handle handle)
internal B32 internal B32
dmn_thread_read_reg_block(DMN_Handle handle, void *reg_block) dmn_thread_read_reg_block(DMN_Handle handle, void *reg_block)
{ {
DMN_W32_Entity *thread = dmn_w32_entity_from_handle(handle); B32 result = 0;
B32 result = dmn_w32_thread_read_reg_block(thread->arch, thread->handle, reg_block); DMN_AccessScope
{
DMN_W32_Entity *thread = dmn_w32_entity_from_handle(handle);
result = dmn_w32_thread_read_reg_block(thread->arch, thread->handle, reg_block);
}
return result; return result;
} }
internal B32 internal B32
dmn_thread_write_reg_block(DMN_Handle handle, void *reg_block) dmn_thread_write_reg_block(DMN_Handle handle, void *reg_block)
{ {
DMN_W32_Entity *thread = dmn_w32_entity_from_handle(handle); B32 result = 0;
B32 result = dmn_w32_thread_write_reg_block(thread->arch, thread->handle, reg_block); DMN_AccessScope
{
DMN_W32_Entity *thread = dmn_w32_entity_from_handle(handle);
result = dmn_w32_thread_write_reg_block(thread->arch, thread->handle, reg_block);
}
return result; return result;
} }
+5
View File
@@ -194,6 +194,10 @@ struct DMN_W32_Shared
Arena *arena; Arena *arena;
String8List env_strings; String8List env_strings;
// rjf: access locking mechanism
OS_Handle access_mutex;
B32 access_run_state;
// rjf: run/mem/reg gens // rjf: run/mem/reg gens
U64 run_gen; U64 run_gen;
U64 mem_gen; U64 mem_gen;
@@ -232,6 +236,7 @@ struct DMN_W32_Shared
global DMN_W32_Shared *dmn_w32_shared = 0; global DMN_W32_Shared *dmn_w32_shared = 0;
global DMN_W32_Entity dmn_w32_entity_nil = {&dmn_w32_entity_nil, &dmn_w32_entity_nil, &dmn_w32_entity_nil, &dmn_w32_entity_nil, &dmn_w32_entity_nil}; global DMN_W32_Entity dmn_w32_entity_nil = {&dmn_w32_entity_nil, &dmn_w32_entity_nil, &dmn_w32_entity_nil, &dmn_w32_entity_nil, &dmn_w32_entity_nil};
global DMN_W32_GetThreadDescriptionFunctionType *dmn_w32_GetThreadDescription = 0; global DMN_W32_GetThreadDescriptionFunctionType *dmn_w32_GetThreadDescription = 0;
thread_static B32 dmn_w32_ctrl_thread = 0;
//////////////////////////////// ////////////////////////////////
//~ rjf: Basic Helpers //~ rjf: Basic Helpers
+9 -8
View File
@@ -1,18 +1,21 @@
// Copyright (c) 2024 Epic Games Tools // Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Demon2 Pass Tasks
//
// [ ] solidify synchronization mechanisms for usage of demon2 layer
// [ ] TLS eval correctness
// [ ] TLS eval -> in-process-memory EXE info
// [ ] unwinding -> in-process-memory EXE info
// [ ] freezing thread while running -> soft-halt
//////////////////////////////// ////////////////////////////////
//~ rjf: Frontend/UI Pass Tasks //~ rjf: Frontend/UI Pass Tasks
// //
// [x] hover-eval when window is not focused - maybe just start directly
// using mouse-move events here
// [x] CRT asserts - stepping over int 29 should work just like stepping over
// an int3
// [ ] check new callstack caching rules very strongly
// [ ] committing needs to happen when navigating focus away for any reason // [ ] committing needs to happen when navigating focus away for any reason
// [ ] better discoverability for view rules - have better help hover tooltip, // [ ] better discoverability for view rules - have better help hover tooltip,
// info on arguments, and better autocomplete lister // info on arguments, and better autocomplete lister
// [ ] freezing thread while running -> soft-halt
// //
// [ ] source view -> floating margin/line-nums // [ ] source view -> floating margin/line-nums
// [ ] theme colors -> more explicit about e.g. opaque backgrounds vs. floating // [ ] theme colors -> more explicit about e.g. opaque backgrounds vs. floating
@@ -81,8 +84,6 @@
// [ ] disasm animation & go-to-address // [ ] disasm animation & go-to-address
// //
// [ ] visualize remapped files (via path map) // [ ] visualize remapped files (via path map)
//
// [x] DBGI layer is case-sensitive even on case-insensitive systems
//////////////////////////////// ////////////////////////////////
//~ rjf: Hot, Medium Priority Tasks (Low-Hanging-Fruit Features, UI Jank, Cleanup) //~ rjf: Hot, Medium Priority Tasks (Low-Hanging-Fruit Features, UI Jank, Cleanup)