This commit is contained in:
Ryan Fleury
2024-03-22 16:31:05 -07:00
23 changed files with 2274 additions and 1521 deletions
+1 -1
View File
@@ -47,7 +47,7 @@ commands =
{ {
.rjf_f1 = .rjf_f1 =
{ {
.win = "build ryan_scratch", .win = "build raddbg telemetry",
.linux = "", .linux = "",
.out = "*compilation*", .out = "*compilation*",
.footer_panel = true, .footer_panel = true,
+1265 -905
View File
File diff suppressed because it is too large Load Diff
+218 -101
View File
@@ -10,16 +10,7 @@
typedef U64 CTRL_MsgID; typedef U64 CTRL_MsgID;
typedef U64 CTRL_MachineID; typedef U64 CTRL_MachineID;
#define CTRL_MachineID_Client (1) #define CTRL_MachineID_Local (1)
////////////////////////////////
//~ rjf: Handle Type
typedef struct CTRL_Handle CTRL_Handle;
struct CTRL_Handle
{
U64 u64[1];
};
//////////////////////////////// ////////////////////////////////
//~ rjf: Machine/Handle Pair Types //~ rjf: Machine/Handle Pair Types
@@ -28,7 +19,7 @@ typedef struct CTRL_MachineIDHandlePair CTRL_MachineIDHandlePair;
struct CTRL_MachineIDHandlePair struct CTRL_MachineIDHandlePair
{ {
CTRL_MachineID machine_id; CTRL_MachineID machine_id;
CTRL_Handle handle; DMN_Handle handle;
}; };
typedef struct CTRL_MachineIDHandlePairNode CTRL_MachineIDHandlePairNode; typedef struct CTRL_MachineIDHandlePairNode CTRL_MachineIDHandlePairNode;
@@ -46,6 +37,71 @@ struct CTRL_MachineIDHandlePairList
U64 count; U64 count;
}; };
////////////////////////////////
//~ rjf: Entity Types
typedef enum CTRL_EntityKind
{
CTRL_EntityKind_Null,
CTRL_EntityKind_Root,
CTRL_EntityKind_Machine,
CTRL_EntityKind_Process,
CTRL_EntityKind_Thread,
CTRL_EntityKind_Module,
CTRL_EntityKind_COUNT
}
CTRL_EntityKind;
typedef struct CTRL_Entity CTRL_Entity;
struct CTRL_Entity
{
CTRL_Entity *first;
CTRL_Entity *last;
CTRL_Entity *next;
CTRL_Entity *prev;
CTRL_Entity *parent;
CTRL_EntityKind kind;
Architecture arch;
CTRL_MachineID machine_id;
DMN_Handle handle;
Rng1U64 vaddr_range;
String8 string;
};
typedef struct CTRL_EntityHashNode CTRL_EntityHashNode;
struct CTRL_EntityHashNode
{
CTRL_EntityHashNode *next;
CTRL_EntityHashNode *prev;
CTRL_Entity *entity;
};
typedef struct CTRL_EntityHashSlot CTRL_EntityHashSlot;
struct CTRL_EntityHashSlot
{
CTRL_EntityHashNode *first;
CTRL_EntityHashNode *last;
};
typedef struct CTRL_EntityStringChunkNode CTRL_EntityStringChunkNode;
struct CTRL_EntityStringChunkNode
{
CTRL_EntityStringChunkNode *next;
U64 size;
};
typedef struct CTRL_EntityStore CTRL_EntityStore;
struct CTRL_EntityStore
{
Arena *arena;
CTRL_Entity *root;
CTRL_Entity *free;
CTRL_EntityHashSlot *hash_slots;
CTRL_EntityHashNode *hash_node_free;
U64 hash_slots_count;
CTRL_EntityStringChunkNode *free_string_chunks[8];
};
//////////////////////////////// ////////////////////////////////
//~ rjf: Unwind Types //~ rjf: Unwind Types
@@ -105,8 +161,8 @@ struct CTRL_TrapList
typedef struct CTRL_Spoof CTRL_Spoof; typedef struct CTRL_Spoof CTRL_Spoof;
struct CTRL_Spoof struct CTRL_Spoof
{ {
CTRL_Handle process; DMN_Handle process;
CTRL_Handle thread; DMN_Handle thread;
U64 vaddr; U64 vaddr;
U64 new_ip_value; U64 new_ip_value;
}; };
@@ -177,8 +233,8 @@ struct CTRL_Msg
CTRL_MsgKind kind; CTRL_MsgKind kind;
CTRL_MsgID msg_id; CTRL_MsgID msg_id;
CTRL_MachineID machine_id; CTRL_MachineID machine_id;
CTRL_Handle entity; DMN_Handle entity;
CTRL_Handle parent; DMN_Handle parent;
U32 entity_id; U32 entity_id;
U32 exit_code; U32 exit_code;
B32 env_inherit; B32 env_inherit;
@@ -281,8 +337,8 @@ struct CTRL_Event
CTRL_ExceptionKind exception_kind; CTRL_ExceptionKind exception_kind;
CTRL_MsgID msg_id; CTRL_MsgID msg_id;
CTRL_MachineID machine_id; CTRL_MachineID machine_id;
CTRL_Handle entity; DMN_Handle entity;
CTRL_Handle parent; DMN_Handle parent;
Architecture arch; Architecture arch;
U64 u64_code; U64 u64_code;
U32 entity_id; U32 entity_id;
@@ -320,7 +376,8 @@ struct CTRL_ProcessMemoryRangeHashNode
B32 zero_terminated; B32 zero_terminated;
Rng1U64 vaddr_range_clamped; Rng1U64 vaddr_range_clamped;
U128 hash; U128 hash;
U64 memgen_idx; U64 mem_gen;
U64 last_time_requested_us;
B32 is_taken; B32 is_taken;
}; };
@@ -338,7 +395,7 @@ struct CTRL_ProcessMemoryCacheNode
CTRL_ProcessMemoryCacheNode *prev; CTRL_ProcessMemoryCacheNode *prev;
Arena *arena; Arena *arena;
CTRL_MachineID machine_id; CTRL_MachineID machine_id;
CTRL_Handle process; DMN_Handle process;
U64 range_hash_slots_count; U64 range_hash_slots_count;
CTRL_ProcessMemoryRangeHashSlot *range_hash_slots; CTRL_ProcessMemoryRangeHashSlot *range_hash_slots;
}; };
@@ -372,6 +429,47 @@ struct CTRL_ProcessMemorySlice
String8 data; String8 data;
U64 *byte_bad_flags; U64 *byte_bad_flags;
U64 *byte_changed_flags; U64 *byte_changed_flags;
B32 stale;
B32 any_byte_bad;
B32 any_byte_changed;
};
////////////////////////////////
//~ rjf: Thread Register Cache Types
typedef struct CTRL_ThreadRegCacheNode CTRL_ThreadRegCacheNode;
struct CTRL_ThreadRegCacheNode
{
CTRL_ThreadRegCacheNode *next;
CTRL_ThreadRegCacheNode *prev;
CTRL_MachineID machine_id;
DMN_Handle thread;
U64 block_size;
void *block;
U64 reg_gen;
};
typedef struct CTRL_ThreadRegCacheSlot CTRL_ThreadRegCacheSlot;
struct CTRL_ThreadRegCacheSlot
{
CTRL_ThreadRegCacheNode *first;
CTRL_ThreadRegCacheNode *last;
};
typedef struct CTRL_ThreadRegCacheStripe CTRL_ThreadRegCacheStripe;
struct CTRL_ThreadRegCacheStripe
{
Arena *arena;
OS_Handle rw_mutex;
};
typedef struct CTRL_ThreadRegCache CTRL_ThreadRegCache;
struct CTRL_ThreadRegCache
{
U64 slots_count;
CTRL_ThreadRegCacheSlot *slots;
U64 stripes_count;
CTRL_ThreadRegCacheStripe *stripes;
}; };
//////////////////////////////// ////////////////////////////////
@@ -388,16 +486,14 @@ struct CTRL_State
{ {
Arena *arena; Arena *arena;
CTRL_WakeupFunctionType *wakeup_hook; CTRL_WakeupFunctionType *wakeup_hook;
U64 run_idx;
U64 memgen_idx;
U64 reggen_idx;
// rjf: name -> register/alias hash tables for eval // rjf: name -> register/alias hash tables for eval
EVAL_String2NumMap arch_string2reg_tables[Architecture_COUNT]; EVAL_String2NumMap arch_string2reg_tables[Architecture_COUNT];
EVAL_String2NumMap arch_string2alias_tables[Architecture_COUNT]; EVAL_String2NumMap arch_string2alias_tables[Architecture_COUNT];
// rjf: process memory cache // rjf: caches
CTRL_ProcessMemoryCache process_memory_cache; CTRL_ProcessMemoryCache process_memory_cache;
CTRL_ThreadRegCache thread_reg_cache;
// rjf: user -> ctrl msg ring buffer // rjf: user -> ctrl msg ring buffer
U64 u2c_ring_size; U64 u2c_ring_size;
@@ -417,10 +513,11 @@ struct CTRL_State
// rjf: ctrl thread state // rjf: ctrl thread state
OS_Handle ctrl_thread; OS_Handle ctrl_thread;
Arena *demon_event_arena; CTRL_EntityStore *ctrl_thread_entity_store;
DEMON_EventNode *first_demon_event_node; Arena *dmn_event_arena;
DEMON_EventNode *last_demon_event_node; DMN_EventNode *first_dmn_event_node;
DEMON_EventNode *free_demon_event_node; DMN_EventNode *last_dmn_event_node;
DMN_EventNode *free_dmn_event_node;
Arena *user_entry_point_arena; Arena *user_entry_point_arena;
String8List user_entry_points; String8List user_entry_points;
U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64]; U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64];
@@ -443,29 +540,21 @@ struct CTRL_State
//~ rjf: Globals //~ rjf: Globals
global CTRL_State *ctrl_state = 0; global CTRL_State *ctrl_state = 0;
read_only global CTRL_Entity ctrl_entity_nil =
//////////////////////////////// {
//~ rjf: Main Layer Initialization &ctrl_entity_nil,
&ctrl_entity_nil,
internal void ctrl_init(void); &ctrl_entity_nil,
&ctrl_entity_nil,
//////////////////////////////// &ctrl_entity_nil,
//~ rjf: Wakeup Callback Registration };
internal void ctrl_set_wakeup_hook(CTRL_WakeupFunctionType *wakeup_hook);
//////////////////////////////// ////////////////////////////////
//~ rjf: Basic Type Functions //~ rjf: Basic Type Functions
internal U64 ctrl_hash_from_string(String8 string); internal U64 ctrl_hash_from_string(String8 string);
internal CTRL_EventCause ctrl_event_cause_from_demon_event_kind(DEMON_EventKind event_kind); internal U64 ctrl_hash_from_machine_id_handle(CTRL_MachineID machine_id, DMN_Handle handle);
internal B32 ctrl_handle_match(CTRL_Handle a, CTRL_Handle b); internal CTRL_EventCause ctrl_event_cause_from_dmn_event_kind(DMN_EventKind event_kind);
////////////////////////////////
//~ rjf: Ctrl <-> Demon Handle Translation Functions
internal DEMON_Handle ctrl_demon_handle_from_ctrl(CTRL_Handle h);
internal CTRL_Handle ctrl_handle_from_demon(DEMON_Handle h);
//////////////////////////////// ////////////////////////////////
//~ rjf: Machine/Handle Pair Type Functions //~ rjf: Machine/Handle Pair Type Functions
@@ -484,8 +573,6 @@ internal CTRL_TrapList ctrl_trap_list_copy(Arena *arena, CTRL_TrapList *src);
internal void ctrl_user_breakpoint_list_push(Arena *arena, CTRL_UserBreakpointList *list, CTRL_UserBreakpoint *bp); internal void ctrl_user_breakpoint_list_push(Arena *arena, CTRL_UserBreakpointList *list, CTRL_UserBreakpoint *bp);
internal CTRL_UserBreakpointList ctrl_user_breakpoint_list_copy(Arena *arena, CTRL_UserBreakpointList *src); internal CTRL_UserBreakpointList ctrl_user_breakpoint_list_copy(Arena *arena, CTRL_UserBreakpointList *src);
internal void ctrl_append_resolved_module_user_bp_traps(Arena *arena, DEMON_Handle process, DEMON_Handle module, CTRL_UserBreakpointList *user_bps, DEMON_TrapChunkList *traps_out);
internal void ctrl_append_resolved_process_user_bp_traps(Arena *arena, DEMON_Handle process, CTRL_UserBreakpointList *user_bps, DEMON_TrapChunkList *traps_out);
//////////////////////////////// ////////////////////////////////
//~ rjf: Message Type Functions //~ rjf: Message Type Functions
@@ -512,97 +599,127 @@ internal String8 ctrl_serialized_string_from_event(Arena *arena, CTRL_Event *eve
internal CTRL_Event ctrl_event_from_serialized_string(Arena *arena, String8 string); internal CTRL_Event ctrl_event_from_serialized_string(Arena *arena, String8 string);
//////////////////////////////// ////////////////////////////////
//~ rjf: Shared Functions //~ rjf: Entity Type Functions
//- rjf: run index //- rjf: cache creation/destruction
internal U64 ctrl_run_idx(void); internal CTRL_EntityStore *ctrl_entity_store_alloc(void);
internal U64 ctrl_memgen_idx(void); internal void ctrl_entity_store_release(CTRL_EntityStore *store);
internal U64 ctrl_reggen_idx(void);
//- rjf: halt everything //- rjf: string allocation/deletion
internal void ctrl_halt(void); internal String8 ctrl_entity_string_alloc(CTRL_EntityStore *store, String8 string);
internal void ctrl_entity_string_release(CTRL_EntityStore *store, String8 string);
//- rjf: exe -> dbg path mapping //- rjf: entity construction/deletion
internal String8 ctrl_inferred_og_dbg_path_from_exe_path(Arena *arena, String8 exe_path); internal CTRL_Entity *ctrl_entity_alloc(CTRL_EntityStore *store, CTRL_Entity *parent, CTRL_EntityKind kind, Architecture arch, CTRL_MachineID machine_id, DMN_Handle handle);
internal String8 ctrl_forced_og_dbg_path_from_exe_path(Arena *arena, String8 exe_path); internal void ctrl_entity_release(CTRL_EntityStore *store, CTRL_Entity *entity);
internal String8 ctrl_natural_og_dbg_path_from_exe_path(Arena *arena, String8 exe_path);
internal String8 ctrl_og_dbg_path_from_exe_path(Arena *arena, String8 exe_path);
//- rjf: handle -> arch //- rjf: entity equipment
internal Architecture ctrl_arch_from_handle(CTRL_MachineID machine, CTRL_Handle handle); internal void ctrl_entity_equip_string(CTRL_EntityStore *store, CTRL_Entity *entity, String8 string);
//- rjf: process memory reading/writing //- rjf: entity store lookups
internal U64 ctrl_process_read(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, void *dst); internal CTRL_Entity *ctrl_entity_from_machine_id_handle(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle handle);
internal B32 ctrl_process_write(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, void *src);
//- rjf: applying events to entity caches
internal void ctrl_entity_store_apply_events(CTRL_EntityStore *store, CTRL_EventList *list);
////////////////////////////////
//~ rjf: Main Layer Initialization
internal void ctrl_init(void);
////////////////////////////////
//~ rjf: Wakeup Callback Registration
internal void ctrl_set_wakeup_hook(CTRL_WakeupFunctionType *wakeup_hook);
////////////////////////////////
//~ rjf: Process Memory Functions
//- rjf: process memory cache interaction //- rjf: process memory cache interaction
internal U128 ctrl_hash_store_key_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, B32 zero_terminated); internal U128 ctrl_hash_store_key_from_process_vaddr_range(CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 range, B32 zero_terminated);
internal U128 ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, B32 zero_terminated, U64 endt_us); internal U128 ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 range, B32 zero_terminated, B32 *out_is_stale, U64 endt_us);
//- rjf: process memory cache reading helpers //- rjf: process memory cache reading helpers
internal CTRL_ProcessMemorySlice ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, U64 endt_us); internal CTRL_ProcessMemorySlice ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 range, U64 endt_us);
internal CTRL_ProcessMemorySlice ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr, U64 limit, U64 endt_us); internal CTRL_ProcessMemorySlice ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_MachineID machine_id, DMN_Handle process, U64 vaddr, U64 limit, U64 endt_us);
//- rjf: register reading/writing //- rjf: process memory writing
internal void *ctrl_reg_block_from_thread(CTRL_MachineID machine_id, CTRL_Handle thread); internal B32 ctrl_process_write(CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 range, void *src);
internal B32 ctrl_thread_write_reg_block(CTRL_MachineID machine_id, CTRL_Handle thread, void *block);
internal U64 ctrl_rip_from_thread(CTRL_MachineID machine_id, CTRL_Handle thread);
internal B32 ctrl_thread_write_rip(CTRL_MachineID machine_id, CTRL_Handle thread, U64 rip);
internal U64 ctrl_tls_root_vaddr_from_thread(CTRL_MachineID machine_id, CTRL_Handle thread);
//- rjf: process * vaddr -> module ////////////////////////////////
internal CTRL_Handle ctrl_module_from_process_vaddr(CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr); //~ rjf: Thread Register Functions
//- rjf: unwinding //- rjf: thread register cache reading
internal CTRL_Unwind ctrl_unwind_from_process_thread(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, CTRL_Handle thread); internal void *ctrl_query_cached_reg_block_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread);
internal U64 ctrl_query_cached_tls_root_vaddr_from_thread(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread);
internal U64 ctrl_query_cached_rip_from_thread(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread);
//- rjf: thread register writing
internal B32 ctrl_thread_write_reg_block(CTRL_MachineID machine_id, DMN_Handle thread, void *block);
////////////////////////////////
//~ rjf: Unwinding Functions
internal CTRL_Unwind ctrl_unwind_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread, U64 endt_us);
////////////////////////////////
//~ rjf: Halting All Attached Processes
internal void ctrl_halt(void);
////////////////////////////////
//~ rjf: Shared Accessor Functions
//- rjf: generation counters
internal U64 ctrl_run_gen(void);
internal U64 ctrl_mem_gen(void);
internal U64 ctrl_reg_gen(void);
//- rjf: name -> register/alias hash tables, for eval //- rjf: name -> register/alias hash tables, for eval
internal EVAL_String2NumMap *ctrl_string2reg_from_arch(Architecture arch); internal EVAL_String2NumMap *ctrl_string2reg_from_arch(Architecture arch);
internal EVAL_String2NumMap *ctrl_string2alias_from_arch(Architecture arch); internal EVAL_String2NumMap *ctrl_string2alias_from_arch(Architecture arch);
//////////////////////////////// ////////////////////////////////
//~ rjf: User -> Ctrl Communication //~ rjf: Control-Thread Functions
//- rjf: user -> control thread communication
internal B32 ctrl_u2c_push_msgs(CTRL_MsgList *msgs, U64 endt_us); internal B32 ctrl_u2c_push_msgs(CTRL_MsgList *msgs, U64 endt_us);
internal CTRL_MsgList ctrl_u2c_pop_msgs(Arena *arena); internal CTRL_MsgList ctrl_u2c_pop_msgs(Arena *arena);
//////////////////////////////// //- rjf: control -> user thread communication
//~ rjf: Ctrl -> User Communication
internal void ctrl_c2u_push_events(CTRL_EventList *events); internal void ctrl_c2u_push_events(CTRL_EventList *events);
internal CTRL_EventList ctrl_c2u_pop_events(Arena *arena); internal CTRL_EventList ctrl_c2u_pop_events(Arena *arena);
////////////////////////////////
//~ rjf: User -> Memory Stream Communication
internal B32 ctrl_u2ms_enqueue_req(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, U64 endt_us);
internal void ctrl_u2ms_dequeue_req(CTRL_MachineID *out_machine_id, CTRL_Handle *out_process, Rng1U64 *out_vaddr_range, B32 *out_zero_terminated);
////////////////////////////////
//~ rjf: Control-Thread-Only Functions
//- rjf: entry point //- rjf: entry point
internal void ctrl_thread__entry_point(void *p); internal void ctrl_thread__entry_point(void *p);
//- rjf: breakpoint resolution
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, 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 DEMON_Event *ctrl_thread__next_demon_event(Arena *arena, CTRL_Msg *msg, DEMON_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-Only Functions //~ rjf: Memory-Stream Thread Functions
//- rjf: user -> memory stream communication
internal B32 ctrl_u2ms_enqueue_req(CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, U64 endt_us);
internal void ctrl_u2ms_dequeue_req(CTRL_MachineID *out_machine_id, DMN_Handle *out_process, Rng1U64 *out_vaddr_range, B32 *out_zero_terminated);
//- rjf: entry point //- rjf: entry point
internal void ctrl_mem_stream_thread__entry_point(void *p); internal void ctrl_mem_stream_thread__entry_point(void *p);
#endif //CTRL_CORE_H #endif // CTRL_CORE_H
+1 -1
View File
@@ -74,4 +74,4 @@
#include "ctrl_core.h" #include "ctrl_core.h"
#endif //CTRL_INC_H #endif // CTRL_INC_H
+8 -6
View File
@@ -179,7 +179,7 @@ dasm_inst_chunk_list_from_arch_addr_data(Arena *arena, U64 *bytes_processed_coun
//- rjf: opening handles & correllation with module //- rjf: opening handles & correllation with module
internal DASM_Handle internal DASM_Handle
dasm_handle_from_ctrl_process_range(CTRL_MachineID machine, CTRL_Handle process, Rng1U64 vaddr_range) dasm_handle_from_ctrl_process_range_arch(CTRL_MachineID machine, DMN_Handle process, Rng1U64 vaddr_range, Architecture arch)
{ {
DASM_Handle result = {0}; DASM_Handle result = {0};
if(machine != 0 && process.u64[0] != 0) if(machine != 0 && process.u64[0] != 0)
@@ -195,8 +195,9 @@ dasm_handle_from_ctrl_process_range(CTRL_MachineID machine, CTRL_Handle process,
for(DASM_Entity *e = slot->first; e != 0; e = e->next) for(DASM_Entity *e = slot->first; e != 0; e = e->next)
{ {
if(e->machine_id == machine && if(e->machine_id == machine &&
ctrl_handle_match(e->process, process) && dmn_handle_match(e->process, process) &&
MemoryMatchStruct(&e->vaddr_range, &vaddr_range)) MemoryMatchStruct(&e->vaddr_range, &vaddr_range) &&
e->arch == arch)
{ {
entity = e; entity = e;
break; break;
@@ -209,6 +210,7 @@ dasm_handle_from_ctrl_process_range(CTRL_MachineID machine, CTRL_Handle process,
entity->machine_id = machine; entity->machine_id = machine;
entity->process = process; entity->process = process;
entity->vaddr_range= vaddr_range; entity->vaddr_range= vaddr_range;
entity->arch = arch;
entity->id = ins_atomic_u64_inc_eval(&dasm_shared->entity_id_gen); entity->id = ins_atomic_u64_inc_eval(&dasm_shared->entity_id_gen);
entity->decode_inst_arena = arena_alloc__sized(MB(256), KB(64)); entity->decode_inst_arena = arena_alloc__sized(MB(256), KB(64));
entity->decode_string_arena = arena_alloc__sized(GB(1), KB(64)); entity->decode_string_arena = arena_alloc__sized(GB(1), KB(64));
@@ -389,7 +391,7 @@ dasm_decode_thread_entry_point(void *p)
//- rjf: request -> ctrl info //- rjf: request -> ctrl info
B32 is_first_to_task = 0; B32 is_first_to_task = 0;
CTRL_MachineID ctrl_machine_id = 0; CTRL_MachineID ctrl_machine_id = 0;
CTRL_Handle ctrl_process = {0}; DMN_Handle ctrl_process = {0};
Rng1U64 vaddr_range = {0}; Rng1U64 vaddr_range = {0};
Architecture arch = Architecture_Null; Architecture arch = Architecture_Null;
U64 *bytes_processed_counter = 0; U64 *bytes_processed_counter = 0;
@@ -413,7 +415,7 @@ dasm_decode_thread_entry_point(void *p)
ctrl_machine_id = entity->machine_id; ctrl_machine_id = entity->machine_id;
ctrl_process = entity->process; ctrl_process = entity->process;
vaddr_range = entity->vaddr_range; vaddr_range = entity->vaddr_range;
arch = ctrl_arch_from_handle(ctrl_machine_id, ctrl_process); arch = entity->arch;
bytes_processed_counter = &entity->bytes_processed; bytes_processed_counter = &entity->bytes_processed;
U64 bytes_to_process = dim_1u64(vaddr_range); U64 bytes_to_process = dim_1u64(vaddr_range);
ins_atomic_u64_eval_assign(&entity->bytes_processed, 0); ins_atomic_u64_eval_assign(&entity->bytes_processed, 0);
@@ -465,7 +467,7 @@ dasm_decode_thread_entry_point(void *p)
if(good_task) if(good_task)
{ {
data.str = push_array_no_zero(scratch.arena, U8, dim_1u64(chunk_vaddr_range)); data.str = push_array_no_zero(scratch.arena, U8, dim_1u64(chunk_vaddr_range));
data.size = ctrl_process_read(ctrl_machine_id, ctrl_process, chunk_vaddr_range, data.str); data.size = dmn_process_read(ctrl_process, chunk_vaddr_range, data.str);
if(data.size != 0) if(data.size != 0)
{ {
inst_list = dasm_inst_chunk_list_from_arch_addr_data(scratch.arena, bytes_processed_counter, arch, chunk_vaddr_range.min, data); inst_list = dasm_inst_chunk_list_from_arch_addr_data(scratch.arena, bytes_processed_counter, arch, chunk_vaddr_range.min, data);
+4 -3
View File
@@ -77,8 +77,9 @@ struct DASM_Entity
// rjf: key info // rjf: key info
CTRL_MachineID machine_id; CTRL_MachineID machine_id;
CTRL_Handle process; DMN_Handle process;
Rng1U64 vaddr_range; Rng1U64 vaddr_range;
Architecture arch;
U64 id; U64 id;
// rjf: top-level info // rjf: top-level info
@@ -114,7 +115,7 @@ typedef struct DASM_BinaryInfo DASM_BinaryInfo;
struct DASM_BinaryInfo struct DASM_BinaryInfo
{ {
CTRL_MachineID machine_id; CTRL_MachineID machine_id;
CTRL_Handle process; DMN_Handle process;
Rng1U64 vaddr_range; Rng1U64 vaddr_range;
U64 bytes_processed; U64 bytes_processed;
U64 bytes_to_process; U64 bytes_to_process;
@@ -187,7 +188,7 @@ internal DASM_InstChunkList dasm_inst_chunk_list_from_arch_addr_data(Arena *aren
//~ rjf: Cache Lookups //~ rjf: Cache Lookups
//- rjf: opening handles & correllation with module //- rjf: opening handles & correllation with module
internal DASM_Handle dasm_handle_from_ctrl_process_range(CTRL_MachineID machine, CTRL_Handle process, Rng1U64 vaddr_range); internal DASM_Handle dasm_handle_from_ctrl_process_range_arch(CTRL_MachineID machine, DMN_Handle process, Rng1U64 vaddr_range, Architecture arch);
//- rjf: asking for top-level info of a handle //- rjf: asking for top-level info of a handle
internal DASM_BinaryInfo dasm_binary_info_from_handle(Arena *arena, DASM_Handle handle); internal DASM_BinaryInfo dasm_binary_info_from_handle(Arena *arena, DASM_Handle handle);
+35
View File
@@ -116,3 +116,38 @@ 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);
{
Architecture arch = dmn_arch_from_thread(thread);
U64 reg_block_size = regs_block_size_from_architecture(arch);
void *reg_block = push_array(scratch.arena, U8, reg_block_size);
dmn_thread_read_reg_block(thread, reg_block);
result = regs_rip_from_arch_block(arch, 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);
{
Architecture arch = dmn_arch_from_thread(thread);
U64 reg_block_size = regs_block_size_from_architecture(arch);
void *reg_block = push_array(scratch.arena, U8, reg_block_size);
dmn_thread_read_reg_block(thread, reg_block);
result = regs_rsp_from_arch_block(arch, reg_block);
}
scratch_end(scratch);
return result;
}
+52 -18
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
@@ -54,6 +68,7 @@ struct DMN_Event
DMN_Handle process; DMN_Handle process;
DMN_Handle thread; DMN_Handle thread;
DMN_Handle module; DMN_Handle module;
Architecture arch;
U64 address; U64 address;
U64 size; U64 size;
String8 string; String8 string;
@@ -159,43 +174,62 @@ 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: @dmn_os_hooks Main Layer Initialization (Implemented Per-OS) //~ rjf: @dmn_os_hooks Main Layer Initialization (Implemented Per-OS)
internal void dmn_init(void); internal void dmn_init(void);
//////////////////////////////// ////////////////////////////////
//~ rjf: @dmn_os_hooks Running/Halting (Implemented Per-OS) //~ rjf: @dmn_os_hooks Blocking Control Thread Operations (Implemented Per-OS)
internal DMN_CtrlCtx *dmn_ctrl_begin(void);
internal void dmn_ctrl_exclusive_access_begin(void);
internal void dmn_ctrl_exclusive_access_end(void);
#define DMN_CtrlExclusiveAccessScope DeferLoop(dmn_ctrl_exclusive_access_begin(), dmn_ctrl_exclusive_access_end())
internal U32 dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_LaunchOptions *options);
internal B32 dmn_ctrl_attach(DMN_CtrlCtx *ctx, U32 pid);
internal B32 dmn_ctrl_kill(DMN_CtrlCtx *ctx, DMN_Handle process, U32 exit_code);
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)
internal DMN_EventList dmn_run(Arena *arena, DMN_RunCtrls *ctrls);
internal void dmn_halt(U64 code, U64 user_data); internal void dmn_halt(U64 code, U64 user_data);
//////////////////////////////// ////////////////////////////////
//~ rjf: @dmn_os_hooks Process Launching/Attaching/Killing/Detaching (Implemented Per-OS) //~ rjf: @dmn_os_hooks Introspection Functions (Implemented Per-OS)
internal U32 dmn_launch_process(OS_LaunchOptions *options); //- rjf: run/memory/register counters
internal B32 dmn_attach_process(U32 pid); internal U64 dmn_run_gen(void);
internal B32 dmn_kill_process(DMN_Handle process, U32 exit_code); internal U64 dmn_mem_gen(void);
internal B32 dmn_detach_process(DMN_Handle process); internal U64 dmn_reg_gen(void);
//////////////////////////////// //- rjf: non-blocking-control-thread access barriers
//~ rjf: @dmn_os_hooks Process/Thread Reads/Writes (Implemented Per-OS) 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);
#define dmn_process_read_struct(process, vaddr, ptr) dmn_process_read((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr) #define dmn_process_read_struct(process, vaddr, ptr) dmn_process_read((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr)
#define dmn_process_write_struct(process, vaddr, ptr) dmn_process_write((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr) #define dmn_process_write_struct(process, vaddr, ptr) dmn_process_write((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr)
//- rjf: threads //- rjf: threads
internal U64 dmn_stack_base_vaddr_from_thread(DMN_Handle handle); internal Architecture dmn_arch_from_thread(DMN_Handle handle);
internal U64 dmn_tls_root_vaddr_from_thread(DMN_Handle handle); internal U64 dmn_stack_base_vaddr_from_thread(DMN_Handle handle);
internal B32 dmn_thread_read_reg_block(DMN_Handle handle, void *reg_block); internal U64 dmn_tls_root_vaddr_from_thread(DMN_Handle handle);
internal B32 dmn_thread_write_reg_block(DMN_Handle handle, void *reg_block); internal B32 dmn_thread_read_reg_block(DMN_Handle handle, void *reg_block);
internal B32 dmn_thread_write_reg_block(DMN_Handle handle, void *reg_block);
////////////////////////////////
//~ rjf: @dmn_os_hooks System Process Listing (Implemented Per-OS)
//- rjf: system process listing
internal void dmn_process_iter_begin(DMN_ProcessIter *iter); 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);
+370 -184
View File
@@ -40,7 +40,7 @@ dmn_w32_entity_from_handle(DMN_Handle handle)
{ {
U32 idx = handle.u32[0]; U32 idx = handle.u32[0];
U32 gen = handle.u32[1]; U32 gen = handle.u32[1];
DMN_W32_Entity *entity = dmn_w32_shared->entities_base; DMN_W32_Entity *entity = dmn_w32_shared->entities_base + idx;
if(entity->gen != gen) if(entity->gen != gen)
{ {
entity = &dmn_w32_entity_nil; entity = &dmn_w32_entity_nil;
@@ -141,7 +141,7 @@ dmn_w32_entity_release(DMN_W32_Entity *entity)
Task *last_task = &start_task; Task *last_task = &start_task;
for(Task *t = first_task; t != 0; t = t->next) for(Task *t = first_task; t != 0; t = t->next)
{ {
for(DMN_W32_Entity *child = entity->first; child != &dmn_w32_entity_nil; child = child->next) for(DMN_W32_Entity *child = t->e->first; child != &dmn_w32_entity_nil; child = child->next)
{ {
Task *t = push_array(scratch.arena, Task, 1); Task *t = push_array(scratch.arena, Task, 1);
t->e = child; t->e = child;
@@ -343,6 +343,7 @@ dmn_w32_process_write(HANDLE process, Rng1U64 range, void *src)
ptr += actual_write; ptr += actual_write;
cursor += actual_write; cursor += actual_write;
} }
ins_atomic_u64_inc_eval(&dmn_w32_shared->mem_gen);
return result; return result;
} }
@@ -581,9 +582,10 @@ dmn_w32_thread_read_reg_block(Architecture arch, HANDLE thread, void *reg_block)
//- rjf: unimplemented win32/arch combos //- rjf: unimplemented win32/arch combos
// //
case Architecture_Null: case Architecture_Null:
case Architecture_COUNT:
{}break;
case Architecture_arm64: case Architecture_arm64:
case Architecture_arm32: case Architecture_arm32:
case Architecture_COUNT:
{NotImplemented;}break; {NotImplemented;}break;
//////////////////////////// ////////////////////////////
@@ -824,9 +826,10 @@ dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block
//- rjf: unimplemented win32/arch combos //- rjf: unimplemented win32/arch combos
// //
case Architecture_Null: case Architecture_Null:
case Architecture_COUNT:
{}break;
case Architecture_arm64: case Architecture_arm64:
case Architecture_arm32: case Architecture_arm32:
case Architecture_COUNT:
{NotImplemented;}break; {NotImplemented;}break;
//////////////////////////// ////////////////////////////
@@ -951,6 +954,7 @@ dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block
//- rjf: bad context -> abort //- rjf: bad context -> abort
if(ctx == 0) if(ctx == 0)
{ {
DWORD error = GetLastError();
break; break;
} }
@@ -1041,6 +1045,7 @@ dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block
scratch_end(scratch); scratch_end(scratch);
}break; }break;
} }
ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen);
return result; return result;
} }
@@ -1068,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);
@@ -1103,18 +1109,203 @@ dmn_init(void)
} }
//////////////////////////////// ////////////////////////////////
//~ rjf: @dmn_os_hooks Running/Halting (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 void
dmn_ctrl_exclusive_access_begin(void)
{
OS_MutexScope(dmn_w32_shared->access_mutex)
{
dmn_w32_shared->access_run_state = 1;
}
}
internal void
dmn_ctrl_exclusive_access_end(void)
{
OS_MutexScope(dmn_w32_shared->access_mutex)
{
dmn_w32_shared->access_run_state = 0;
}
}
internal U32
dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_LaunchOptions *options)
{
Temp scratch = scratch_begin(0, 0);
U32 result = 0;
DMN_AccessScope
{
//- rjf: produce exe / arguments string
String8 cmd = {0};
if(options->cmd_line.first != 0)
{
String8List args = {0};
String8 exe_path = options->cmd_line.first->string;
str8_list_pushf(scratch.arena, &args, "\"%S\"", exe_path);
for(String8Node *n = options->cmd_line.first->next; n != 0; n = n->next)
{
str8_list_push(scratch.arena, &args, n->string);
}
StringJoin join_params = {0};
join_params.sep = str8_lit(" ");
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);
}
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
{
MessageBox(0, "Error starting process.", "Process error", MB_OK|MB_ICONSTOP);
}
FreeConsole();
//- rjf: eliminate all handles which have stuck around from the AllocConsole
{
SetStdHandle(STD_INPUT_HANDLE, 0);
SetStdHandle(STD_OUTPUT_HANDLE, 0);
SetStdHandle(STD_ERROR_HANDLE, 0);
}
}
scratch_end(scratch);
return result;
}
internal B32
dmn_ctrl_attach(DMN_CtrlCtx *ctx, U32 pid)
{
B32 result = 0;
DMN_AccessScope if(DebugActiveProcess((DWORD)pid))
{
result = 1;
dmn_w32_shared->new_process_pending = 1;
}
return result;
}
internal B32
dmn_ctrl_kill(DMN_CtrlCtx *ctx, DMN_Handle process, U32 exit_code)
{
B32 result = 0;
DMN_AccessScope
{
DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process);
if(TerminateProcess(process_entity->handle, exit_code))
{
result = 1;
}
}
return result;
}
internal B32
dmn_ctrl_detach(DMN_CtrlCtx *ctx, DMN_Handle process)
{
B32 result = 0;
DMN_AccessScope
{
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)
{
if(child->kind == DMN_W32_EntityKind_Thread)
{
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);
}
}
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
// //
typedef enum DMN_W32_EventGenPath typedef enum DMN_W32_EventGenPath
{ {
DMN_W32_EventGenPath_NotAttached,
DMN_W32_EventGenPath_Run, DMN_W32_EventGenPath_Run,
DMN_W32_EventGenPath_DetachProcesses, DMN_W32_EventGenPath_DetachProcesses,
} }
@@ -1124,12 +1315,41 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
{ {
event_gen_path = DMN_W32_EventGenPath_DetachProcesses; event_gen_path = DMN_W32_EventGenPath_DetachProcesses;
} }
else
{
B32 any_processes_live = dmn_w32_shared->new_process_pending;
if(!any_processes_live)
{
for(DMN_W32_Entity *process = dmn_w32_shared->entities_base->first; process != &dmn_w32_entity_nil; process = process->next)
{
if(process->kind == DMN_W32_EntityKind_Process)
{
any_processes_live = 1;
break;
}
}
}
if(!any_processes_live)
{
event_gen_path = DMN_W32_EventGenPath_NotAttached;
}
}
////////////////////////////// //////////////////////////////
//- rjf: produce debug events //- rjf: produce debug events
// //
switch(event_gen_path) switch(event_gen_path)
{ {
////////////////////////////
//- rjf: produce not-attached error events
//
case DMN_W32_EventGenPath_NotAttached:
{
DMN_Event *e = dmn_event_list_push(arena, &events);
e->kind = DMN_EventKind_Error;
e->error_kind = DMN_ErrorKind_NotAttached;
}break;
//////////////////////////// ////////////////////////////
//- rjf: produce debug events from regular running //- rjf: produce debug events from regular running
// //
@@ -1148,9 +1368,10 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
{ {
//- rjf: unimplemented win32/arch combos //- rjf: unimplemented win32/arch combos
case Architecture_Null: case Architecture_Null:
case Architecture_COUNT:
{}break;
case Architecture_arm64: case Architecture_arm64:
case Architecture_arm32: case Architecture_arm32:
case Architecture_COUNT:
{NotImplemented;}break; {NotImplemented;}break;
//- rjf: x86/64 //- rjf: x86/64
@@ -1198,7 +1419,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
{ {
//- rjf: scan all processes //- rjf: scan all processes
for(DMN_W32_Entity *process = dmn_w32_shared->entities_base->first; for(DMN_W32_Entity *process = dmn_w32_shared->entities_base->first;
process != 0; process != &dmn_w32_entity_nil;
process = process->next) process = process->next)
{ {
if(process->kind != DMN_W32_EntityKind_Process) {continue;} if(process->kind != DMN_W32_EntityKind_Process) {continue;}
@@ -1219,7 +1440,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
//- rjf: scan all threads in this process //- rjf: scan all threads in this process
for(DMN_W32_Entity *thread = process->first; for(DMN_W32_Entity *thread = process->first;
thread != 0; thread != &dmn_w32_entity_nil;
thread = thread->next) thread = thread->next)
{ {
if(thread->kind != DMN_W32_EntityKind_Thread) {continue;} if(thread->kind != DMN_W32_EntityKind_Thread) {continue;}
@@ -1345,7 +1566,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
DEBUG_EVENT evt = {0}; DEBUG_EVENT evt = {0};
B32 evt_good = 0; B32 evt_good = 0;
{ {
B32 resume_good = 0; B32 resume_good = 1;
if(dmn_w32_shared->resume_needed) if(dmn_w32_shared->resume_needed)
{ {
dmn_w32_shared->resume_needed = 0; dmn_w32_shared->resume_needed = 0;
@@ -1363,6 +1584,9 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
dmn_w32_shared->resume_pid = evt.dwProcessId; dmn_w32_shared->resume_pid = evt.dwProcessId;
dmn_w32_shared->resume_tid = evt.dwThreadId; dmn_w32_shared->resume_tid = evt.dwThreadId;
} }
ins_atomic_u64_inc_eval(&dmn_w32_shared->run_gen);
ins_atomic_u64_inc_eval(&dmn_w32_shared->mem_gen);
ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen);
} }
} }
@@ -1432,6 +1656,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
process->handle = process_handle; process->handle = process_handle;
process->arch = image_info.arch; process->arch = image_info.arch;
thread->handle = thread_handle; thread->handle = thread_handle;
thread->arch = image_info.arch;
thread->thread.thread_local_base = tls_base; thread->thread.thread_local_base = tls_base;
module->handle = module_handle; module->handle = module_handle;
module->module.vaddr_range = r1u64(module_base, image_info.size); module->module.vaddr_range = r1u64(module_base, image_info.size);
@@ -1462,6 +1687,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
DMN_Event *e = dmn_event_list_push(arena, &events); DMN_Event *e = dmn_event_list_push(arena, &events);
e->kind = DMN_EventKind_CreateProcess; e->kind = DMN_EventKind_CreateProcess;
e->process = dmn_w32_handle_from_entity(process); e->process = dmn_w32_handle_from_entity(process);
e->arch = image_info.arch;
e->code = evt.dwProcessId; e->code = evt.dwProcessId;
} }
@@ -1471,6 +1697,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
e->kind = DMN_EventKind_CreateThread; e->kind = DMN_EventKind_CreateThread;
e->process = dmn_w32_handle_from_entity(process); e->process = dmn_w32_handle_from_entity(process);
e->thread = dmn_w32_handle_from_entity(thread); e->thread = dmn_w32_handle_from_entity(thread);
e->arch = image_info.arch;
e->code = evt.dwThreadId; e->code = evt.dwThreadId;
} }
@@ -1480,6 +1707,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
e->kind = DMN_EventKind_LoadModule; e->kind = DMN_EventKind_LoadModule;
e->process = dmn_w32_handle_from_entity(process); e->process = dmn_w32_handle_from_entity(process);
e->module = dmn_w32_handle_from_entity(module); e->module = dmn_w32_handle_from_entity(module);
e->arch = image_info.arch;
e->address = module_base; e->address = module_base;
e->size = image_info.size; e->size = image_info.size;
e->string = dmn_w32_full_path_from_module(arena, module); e->string = dmn_w32_full_path_from_module(arena, module);
@@ -1543,6 +1771,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
DMN_W32_Entity *thread = dmn_w32_entity_alloc(process, DMN_W32_EntityKind_Thread, evt.dwThreadId); DMN_W32_Entity *thread = dmn_w32_entity_alloc(process, DMN_W32_EntityKind_Thread, evt.dwThreadId);
{ {
thread->handle = evt.u.CreateThread.hThread; thread->handle = evt.u.CreateThread.hThread;
thread->arch = process->arch;
thread->thread.thread_local_base = (U64)evt.u.CreateThread.lpThreadLocalBase; thread->thread.thread_local_base = (U64)evt.u.CreateThread.lpThreadLocalBase;
} }
@@ -1573,6 +1802,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
e->kind = DMN_EventKind_CreateThread; e->kind = DMN_EventKind_CreateThread;
e->process = dmn_w32_handle_from_entity(process); e->process = dmn_w32_handle_from_entity(process);
e->thread = dmn_w32_handle_from_entity(thread); e->thread = dmn_w32_handle_from_entity(thread);
e->arch = thread->arch;
e->code = evt.dwThreadId; e->code = evt.dwThreadId;
e->string = thread_name; e->string = thread_name;
} }
@@ -1627,6 +1857,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
DMN_W32_Entity *module = dmn_w32_entity_alloc(process, DMN_W32_EntityKind_Module, module_base); DMN_W32_Entity *module = dmn_w32_entity_alloc(process, DMN_W32_EntityKind_Module, module_base);
{ {
module->handle = evt.u.LoadDll.hFile; module->handle = evt.u.LoadDll.hFile;
module->arch = image_info.arch;
module->module.vaddr_range = r1u64(module_base, module_base+image_info.size); module->module.vaddr_range = r1u64(module_base, module_base+image_info.size);
module->module.address_of_name_pointer = (U64)evt.u.LoadDll.lpImageName; module->module.address_of_name_pointer = (U64)evt.u.LoadDll.lpImageName;
module->module.name_is_unicode = (evt.u.LoadDll.fUnicode != 0); module->module.name_is_unicode = (evt.u.LoadDll.fUnicode != 0);
@@ -1638,6 +1869,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
e->kind = DMN_EventKind_LoadModule; e->kind = DMN_EventKind_LoadModule;
e->process = dmn_w32_handle_from_entity(process); e->process = dmn_w32_handle_from_entity(process);
e->module = dmn_w32_handle_from_entity(module); e->module = dmn_w32_handle_from_entity(module);
e->arch = module->arch;
e->address = module_base; e->address = module_base;
e->size = image_info.size; e->size = image_info.size;
e->string = dmn_w32_full_path_from_module(arena, module); e->string = dmn_w32_full_path_from_module(arena, module);
@@ -1765,7 +1997,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
{ {
post_trap_rip = regs_rip_from_arch_block(thread->arch, regs_block); post_trap_rip = regs_rip_from_arch_block(thread->arch, regs_block);
regs_arch_block_write_rip(thread->arch, regs_block, instruction_pointer); regs_arch_block_write_rip(thread->arch, regs_block, instruction_pointer);
dmn_w32_thread_write_reg_block(thread->arch, thread, regs_block); dmn_w32_thread_write_reg_block(thread->arch, thread->handle, regs_block);
} }
temp_end(temp); temp_end(temp);
} }
@@ -1980,7 +2212,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
{ {
if(process->kind != DMN_W32_EntityKind_Process) { continue; } if(process->kind != DMN_W32_EntityKind_Process) { continue; }
for(DMN_W32_Entity *thread = process->first; for(DMN_W32_Entity *thread = process->first;
thread != 0; thread != &dmn_w32_entity_nil;
thread = thread->next) thread = thread->next)
{ {
if(thread->kind != DMN_W32_EntityKind_Thread) { continue; } if(thread->kind != DMN_W32_EntityKind_Thread) { continue; }
@@ -2043,9 +2275,10 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
{ {
//- rjf: unimplemented win32/arch combos //- rjf: unimplemented win32/arch combos
case Architecture_Null: case Architecture_Null:
case Architecture_COUNT:
{}break;
case Architecture_arm64: case Architecture_arm64:
case Architecture_arm32: case Architecture_arm32:
case Architecture_COUNT:
{NotImplemented;}break; {NotImplemented;}break;
//- rjf: x86/64 //- rjf: x86/64
@@ -2120,13 +2353,17 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
}break; }break;
} }
dmn_access_close();
return events; return events;
} }
////////////////////////////////
//~ rjf: @dmn_os_hooks Halting (Implemented Per-OS)
internal void internal void
dmn_halt(U64 code, U64 user_data) dmn_halt(U64 code, U64 user_data)
{ {
if(!dmn_handle_match(dmn_handle_zero(), dmn_w32_shared->halter_process)) if(dmn_handle_match(dmn_handle_zero(), dmn_w32_shared->halter_process))
{ {
DMN_W32_Entity *process = &dmn_w32_entity_nil; DMN_W32_Entity *process = &dmn_w32_entity_nil;
for(DMN_W32_Entity *entity = dmn_w32_shared->entities_base->first; for(DMN_W32_Entity *entity = dmn_w32_shared->entities_base->first;
@@ -2151,206 +2388,128 @@ dmn_halt(U64 code, U64 user_data)
} }
//////////////////////////////// ////////////////////////////////
//~ rjf: @dmn_os_hooks Process Launching/Attaching/Killing/Detaching (Implemented Per-OS) //~ rjf: @dmn_os_hooks Introspection Functions (Implemented Per-OS)
internal U32 //- rjf: run/memory/register counters
dmn_launch_process(OS_LaunchOptions *options)
internal U64
dmn_run_gen(void)
{ {
Temp scratch = scratch_begin(0, 0); U64 result = ins_atomic_u64_eval(&dmn_w32_shared->run_gen);
U32 result = 0; return result;
}
//- rjf: produce exe / arguments string internal U64
String8 cmd = {0}; dmn_mem_gen(void)
if(options->cmd_line.first != 0) {
U64 result = ins_atomic_u64_eval(&dmn_w32_shared->mem_gen);
return result;
}
internal U64
dmn_reg_gen(void)
{
U64 result = ins_atomic_u64_eval(&dmn_w32_shared->reg_gen);
return result;
}
//- rjf: non-blocking-control-thread access barriers
internal B32
dmn_access_open(void)
{
B32 result = 0;
if(dmn_w32_ctrl_thread)
{ {
String8List args = {0}; result = 1;
String8 exe_path = options->cmd_line.first->string;
str8_list_pushf(scratch.arena, &args, "\"%S\"", exe_path);
for(String8Node *n = options->cmd_line.first->next; n != 0; n = n->next)
{
str8_list_push(scratch.arena, &args, n->string);
}
StringJoin join_params = {0};
join_params.sep = str8_lit(" ");
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);
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
{ {
MessageBox(0, "Error starting process.", "Process error", MB_OK|MB_ICONSTOP); os_mutex_take(dmn_w32_shared->access_mutex);
} result = !dmn_w32_shared->access_run_state;
FreeConsole();
//- rjf: eliminate all handles which have stuck around from the AllocConsole
{
SetStdHandle(STD_INPUT_HANDLE, 0);
SetStdHandle(STD_OUTPUT_HANDLE, 0);
SetStdHandle(STD_ERROR_HANDLE, 0);
}
scratch_end(scratch);
return result;
}
internal B32
dmn_attach_process(U32 pid)
{
B32 result = 0;
if(DebugActiveProcess((DWORD)pid))
{
result = 1;
dmn_w32_shared->new_process_pending = 1;
} }
return result; return result;
} }
internal B32 internal void
dmn_kill_process(DMN_Handle process, U32 exit_code) dmn_access_close(void)
{ {
B32 result = 0; if(!dmn_w32_ctrl_thread)
DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process);
if(TerminateProcess(process_entity->handle, exit_code))
{ {
result = 1; os_mutex_drop(dmn_w32_shared->access_mutex);
}
return result;
}
internal B32
dmn_detach_process(DMN_Handle process)
{
B32 result = 0;
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)
{
if(child->kind == DMN_W32_EntityKind_Thread)
{
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: @dmn_os_hooks Process/Thread Reads/Writes (Implemented Per-OS)
//- 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;
} }
//- rjf: threads //- rjf: threads
internal Architecture
dmn_arch_from_thread(DMN_Handle handle)
{
Architecture arch = Architecture_Null;
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)
U64 result = 0;
switch(thread->arch)
{ {
case Architecture_Null: DMN_W32_Entity *process = thread->parent;
case Architecture_arm64: U64 tlb = thread->thread.thread_local_base;
case Architecture_arm32: switch(thread->arch)
case Architecture_COUNT:
{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;
@@ -2360,10 +2519,30 @@ 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;
switch(entity->arch)
{
case Architecture_Null:
case Architecture_COUNT:
{}break;
case Architecture_arm64:
case Architecture_arm32:
{NotImplemented;}break;
case Architecture_x64:
{
result += 88;
}break;
case Architecture_x86:
{
result += 44;
}break;
}
}
} }
return result; return result;
} }
@@ -2371,21 +2550,28 @@ 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;
} }
//////////////////////////////// //- rjf: system process listing
//~ rjf: @dmn_os_hooks System Process Listing (Implemented Per-OS)
internal void internal void
dmn_process_iter_begin(DMN_ProcessIter *iter) dmn_process_iter_begin(DMN_ProcessIter *iter)
+10
View File
@@ -194,6 +194,15 @@ 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
U64 run_gen;
U64 mem_gen;
U64 reg_gen;
// rjf: detaching info // rjf: detaching info
Arena *detach_arena; Arena *detach_arena;
DMN_HandleList detach_processes; DMN_HandleList detach_processes;
@@ -227,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
+249 -250
View File
@@ -1404,7 +1404,7 @@ internal DASM_Handle
df_dasm_handle_from_process_vaddr(DF_Entity *process, U64 vaddr) df_dasm_handle_from_process_vaddr(DF_Entity *process, U64 vaddr)
{ {
Rng1U64 disasm_vaddr_rng = r1u64(AlignDownPow2(vaddr, KB(4)), AlignDownPow2(vaddr, KB(4)) + KB(16)); Rng1U64 disasm_vaddr_rng = r1u64(AlignDownPow2(vaddr, KB(4)), AlignDownPow2(vaddr, KB(4)) + KB(16));
DASM_Handle dasm_handle = dasm_handle_from_ctrl_process_range(process->ctrl_machine_id, process->ctrl_handle, disasm_vaddr_rng); DASM_Handle dasm_handle = dasm_handle_from_ctrl_process_range_arch(process->ctrl_machine_id, process->ctrl_handle, disasm_vaddr_rng, process->arch);
return dasm_handle; return dasm_handle;
} }
@@ -2025,7 +2025,7 @@ df_entity_equip_ctrl_machine_id(DF_Entity *entity, CTRL_MachineID machine_id)
} }
internal void internal void
df_entity_equip_ctrl_handle(DF_Entity *entity, CTRL_Handle handle) df_entity_equip_ctrl_handle(DF_Entity *entity, DMN_Handle handle)
{ {
df_require_entity_nonnil(entity, return); df_require_entity_nonnil(entity, return);
entity->ctrl_handle = handle; entity->ctrl_handle = handle;
@@ -2419,7 +2419,7 @@ df_machine_entity_from_machine_id(CTRL_MachineID machine_id)
} }
internal DF_Entity * internal DF_Entity *
df_entity_from_ctrl_handle(CTRL_MachineID machine_id, CTRL_Handle handle) df_entity_from_ctrl_handle(CTRL_MachineID machine_id, DMN_Handle handle)
{ {
DF_Entity *result = &df_g_nil_entity; DF_Entity *result = &df_g_nil_entity;
if(handle.u64[0] != 0) if(handle.u64[0] != 0)
@@ -2520,11 +2520,13 @@ df_set_thread_freeze_state(DF_Entity *thread, B32 frozen)
} }
node->handle = thread_handle; node->handle = thread_handle;
df_handle_list_push_node(&df_state->frozen_threads, node); df_handle_list_push_node(&df_state->frozen_threads, node);
df_state->entities_mut_soft_halt = 1;
} }
// rjf: frozen => not frozen // rjf: frozen => not frozen
if(is_frozen && !should_be_frozen) if(is_frozen && !should_be_frozen)
{ {
df_state->entities_mut_soft_halt = 1;
df_handle_list_remove(&df_state->frozen_threads, already_frozen_node); df_handle_list_remove(&df_state->frozen_threads, already_frozen_node);
SLLStackPush(df_state->free_handle_node, already_frozen_node); SLLStackPush(df_state->free_handle_node, already_frozen_node);
} }
@@ -2710,11 +2712,9 @@ df_debug_info_path_from_module(Arena *arena, DF_Entity *module)
} }
else else
{ {
Temp scratch = scratch_begin(&arena, 1);
String8 exe_path = module->name; String8 exe_path = module->name;
String8 dbg_path = ctrl_og_dbg_path_from_exe_path(arena, exe_path); String8 dbg_path = push_str8f(arena, "%S.pdb", str8_chop_last_dot(exe_path));
result = dbg_path; result = dbg_path;
scratch_end(scratch);
} }
ProfEnd(); ProfEnd();
return result; return result;
@@ -2824,14 +2824,14 @@ df_trap_net_from_thread__step_over_inst(Arena *arena, DF_Entity *thread)
// rjf: thread => unpacked info // rjf: thread => unpacked info
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
Architecture arch = df_architecture_from_entity(thread); Architecture arch = df_architecture_from_entity(thread);
U64 ip_vaddr = df_rip_from_thread(thread); U64 ip_vaddr = ctrl_query_cached_rip_from_thread(df_state->ctrl_entity_store, thread->ctrl_machine_id, thread->ctrl_handle);
// rjf: ip => machine code // rjf: ip => machine code
String8 machine_code = {0}; String8 machine_code = {0};
{ {
Rng1U64 rng = r1u64(ip_vaddr, ip_vaddr+max_instruction_size_from_arch(arch)); Rng1U64 rng = r1u64(ip_vaddr, ip_vaddr+max_instruction_size_from_arch(arch));
machine_code.str = push_array_no_zero(scratch.arena, U8, max_instruction_size_from_arch(arch)); CTRL_ProcessMemorySlice machine_code_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, rng, os_now_microseconds()+5000);
machine_code.size = ctrl_process_read(process->ctrl_machine_id, process->ctrl_handle, rng, machine_code.str); machine_code = machine_code_slice.data;
} }
// rjf: build traps if machine code was read successfully // rjf: build traps if machine code was read successfully
@@ -2863,7 +2863,7 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread)
DF_Entity *module = df_module_from_thread(thread); DF_Entity *module = df_module_from_thread(thread);
DF_Entity *binary = df_binary_file_from_module(module); DF_Entity *binary = df_binary_file_from_module(module);
Architecture arch = df_architecture_from_entity(thread); Architecture arch = df_architecture_from_entity(thread);
U64 ip_vaddr = df_rip_from_thread(thread); U64 ip_vaddr = ctrl_query_cached_rip_from_thread(df_state->ctrl_entity_store, thread->ctrl_machine_id, thread->ctrl_handle);
// rjf: ip => line vaddr range // rjf: ip => line vaddr range
Rng1U64 line_vaddr_rng = {0}; Rng1U64 line_vaddr_rng = {0};
@@ -2897,8 +2897,8 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread)
String8 machine_code = {0}; String8 machine_code = {0};
if(good_line_info) if(good_line_info)
{ {
machine_code.str = push_array_no_zero(scratch.arena, U8, dim_1u64(line_vaddr_rng)); CTRL_ProcessMemorySlice machine_code_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, line_vaddr_rng, os_now_microseconds()+50000);
machine_code.size = ctrl_process_read(process->ctrl_machine_id, process->ctrl_handle, line_vaddr_rng, machine_code.str); machine_code = machine_code_slice.data;
} }
// rjf: machine code => ctrl flow analysis // rjf: machine code => ctrl flow analysis
@@ -2988,7 +2988,7 @@ df_trap_net_from_thread__step_into_line(Arena *arena, DF_Entity *thread)
DF_Entity *module = df_module_from_thread(thread); DF_Entity *module = df_module_from_thread(thread);
DF_Entity *binary = df_binary_file_from_module(module); DF_Entity *binary = df_binary_file_from_module(module);
Architecture arch = df_architecture_from_entity(thread); Architecture arch = df_architecture_from_entity(thread);
U64 ip_vaddr = df_rip_from_thread(thread); U64 ip_vaddr = ctrl_query_cached_rip_from_thread(df_state->ctrl_entity_store, thread->ctrl_machine_id, thread->ctrl_handle);
// rjf: ip => line vaddr range // rjf: ip => line vaddr range
Rng1U64 line_vaddr_rng = {0}; Rng1U64 line_vaddr_rng = {0};
@@ -3022,8 +3022,8 @@ df_trap_net_from_thread__step_into_line(Arena *arena, DF_Entity *thread)
String8 machine_code = {0}; String8 machine_code = {0};
if(good_line_info) if(good_line_info)
{ {
machine_code.str = push_array_no_zero(scratch.arena, U8, dim_1u64(line_vaddr_rng)); CTRL_ProcessMemorySlice machine_code_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, line_vaddr_rng, os_now_microseconds()+5000);
machine_code.size = ctrl_process_read(process->ctrl_machine_id, process->ctrl_handle, line_vaddr_rng, machine_code.str); machine_code = machine_code_slice.data;
} }
// rjf: machine code => ctrl flow analysis // rjf: machine code => ctrl flow analysis
@@ -3379,27 +3379,6 @@ df_text_line_dasm2src_info_from_binary_voff(DF_Entity *binary, U64 voff)
return result; return result;
} }
internal DF_TextLineDasm2SrcInfoList
df_text_line_dasm2src_info_from_voff(Arena *arena, U64 voff)
{
Temp scratch = scratch_begin(&arena, 1);
DF_TextLineDasm2SrcInfoList result = {0};
DF_EntityList binaries = df_push_active_binary_list(scratch.arena);
for(DF_EntityNode *n = binaries.first; n != 0; n = n->next)
{
DF_TextLineDasm2SrcInfo info = df_text_line_dasm2src_info_from_binary_voff(n->entity, voff);
if(!df_entity_is_nil(info.file))
{
DF_TextLineDasm2SrcInfoNode *dst_n = push_array(arena, DF_TextLineDasm2SrcInfoNode, 1);
dst_n->v = info;
SLLQueuePush(result.first, result.last, dst_n);
result.count += 1;
}
}
scratch_end(scratch);
return result;
}
//- rjf: symbol -> voff lookups //- rjf: symbol -> voff lookups
internal U64 internal U64
@@ -3565,83 +3544,84 @@ df_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64
U64 base_vaddr = 0; U64 base_vaddr = 0;
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
DBGI_Scope *scope = dbgi_scope_open(); DBGI_Scope *scope = dbgi_scope_open();
if(!df_ctrl_targets_running())
//- rjf: unpack thread info
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
DF_Entity *binary = df_binary_file_from_module(module);
DBGI_Parse *dbgi = df_dbgi_parse_from_binary_file(scope, binary);
String8 bin_data = str8((U8 *)dbgi->exe_base, dbgi->exe_props.size);
PE_BinInfo *bin = &dbgi->pe;
B32 bin_is_pe = 1; // TODO(rjf): this path needs to change for ELF
U64 addr_size = bit_size_from_arch(bin->arch)/8;
//- rjf: grab tls range
Rng1U64 tls_vaddr_range = pe_tls_rng_from_bin_base_vaddr(bin_data, bin, df_base_vaddr_from_module(module));
//- rjf: read module's TLS index
U64 tls_index = 0;
{ {
U64 bytes_read = ctrl_process_read(process->ctrl_machine_id, process->ctrl_handle, tls_vaddr_range, &tls_index); //- rjf: unpack thread info
if(bytes_read < sizeof(U64)) DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
DF_Entity *binary = df_binary_file_from_module(module);
DBGI_Parse *dbgi = df_dbgi_parse_from_binary_file(scope, binary);
String8 bin_data = str8((U8 *)dbgi->exe_base, dbgi->exe_props.size);
PE_BinInfo *bin = &dbgi->pe;
B32 bin_is_pe = 1; // TODO(rjf): this path needs to change for ELF
U64 addr_size = bit_size_from_arch(bin->arch)/8;
//- rjf: grab tls range
Rng1U64 tls_vaddr_range = pe_tls_rng_from_bin_base_vaddr(bin_data, bin, df_base_vaddr_from_module(module));
//- rjf: read module's TLS index
U64 tls_index = 0;
{ {
tls_index = 0; CTRL_ProcessMemorySlice tls_index_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, tls_vaddr_range, 0);
} if(tls_index_slice.data.size >= addr_size)
}
//- rjf: PE path
if(bin_is_pe)
{
U64 thread_info_addr = root_vaddr;
U64 tls_addr_off = tls_index*addr_size;
U64 tls_addr_array = 0;
CTRL_ProcessMemorySlice tls_addr_array_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(thread_info_addr, thread_info_addr+addr_size), 0);
String8 tls_addr_array_data = tls_addr_array_slice.data;
if(tls_addr_array_data.size >= 8)
{
MemoryCopy(&tls_addr_array, tls_addr_array_data.str, sizeof(U64));
}
CTRL_ProcessMemorySlice result_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(tls_addr_array + tls_addr_off, tls_addr_array + tls_addr_off + addr_size), 0);
String8 result_data = result_slice.data;
if(result_data.size >= 8)
{
MemoryCopy(&base_vaddr, result_data.str, sizeof(U64));
}
}
//- rjf: non-PE path (not implemented)
if(!bin_is_pe)
{
// TODO(rjf): not supported. old code from the prototype that Nick had sketched out:
#if 0
// TODO(nick): This code works only if the linked c runtime library is glibc.
// Implement CRT detection here.
U64 dtv_addr = UINT64_MAX;
demon_read_memory(process->demon_handle, &dtv_addr, thread_info_addr, addr_size);
/*
union delta_thread_vector
{ {
size_t counter; tls_index = *(U64 *)tls_index_slice.data.str;
struct }
{
void *value;
void *to_free;
} pointer;
};
*/
U64 dtv_size = 16;
U64 dtv_count = 0;
demon_read_memory(process->demon_handle, &dtv_count, dtv_addr - dtv_size, addr_size);
if (tls_index > 0 && tls_index < dtv_count)
{
demon_read_memory(process->demon_handle, &result, dtv_addr + dtv_size*tls_index, addr_size);
} }
#endif
}
//- rjf: PE path
if(bin_is_pe)
{
U64 thread_info_addr = root_vaddr;
U64 tls_addr_off = tls_index*addr_size;
U64 tls_addr_array = 0;
CTRL_ProcessMemorySlice tls_addr_array_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(thread_info_addr, thread_info_addr+addr_size), 0);
String8 tls_addr_array_data = tls_addr_array_slice.data;
if(tls_addr_array_data.size >= 8)
{
MemoryCopy(&tls_addr_array, tls_addr_array_data.str, sizeof(U64));
}
CTRL_ProcessMemorySlice result_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(tls_addr_array + tls_addr_off, tls_addr_array + tls_addr_off + addr_size), 0);
String8 result_data = result_slice.data;
if(result_data.size >= 8)
{
MemoryCopy(&base_vaddr, result_data.str, sizeof(U64));
}
}
//- rjf: non-PE path (not implemented)
if(!bin_is_pe)
{
// TODO(rjf): not supported. old code from the prototype that Nick had sketched out:
#if 0
// TODO(nick): This code works only if the linked c runtime library is glibc.
// Implement CRT detection here.
U64 dtv_addr = UINT64_MAX;
demon_read_memory(process->demon_handle, &dtv_addr, thread_info_addr, addr_size);
/*
union delta_thread_vector
{
size_t counter;
struct
{
void *value;
void *to_free;
} pointer;
};
*/
U64 dtv_size = 16;
U64 dtv_count = 0;
demon_read_memory(process->demon_handle, &dtv_count, dtv_addr - dtv_size, addr_size);
if (tls_index > 0 && tls_index < dtv_count)
{
demon_read_memory(process->demon_handle, &result, dtv_addr + dtv_size*tls_index, addr_size);
}
#endif
}
}
dbgi_scope_close(scope); dbgi_scope_close(scope);
scratch_end(scratch); scratch_end(scratch);
ProfEnd(); ProfEnd();
@@ -3654,43 +3634,6 @@ df_architecture_from_entity(DF_Entity *entity)
return entity->arch; return entity->arch;
} }
internal CTRL_Unwind
df_push_unwind_from_thread(Arena *arena, DF_Entity *thread)
{
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
CTRL_Unwind unwind = ctrl_unwind_from_process_thread(arena, thread->ctrl_machine_id, process->ctrl_handle, thread->ctrl_handle);
return unwind;
}
internal U64
df_rip_from_thread(DF_Entity *thread)
{
U64 result = ctrl_rip_from_thread(thread->ctrl_machine_id, thread->ctrl_handle);
return result;
}
internal U64
df_rip_from_thread_unwind(DF_Entity *thread, U64 unwind_count)
{
Temp scratch = scratch_begin(0, 0);
U64 result = df_rip_from_thread(thread);
if(unwind_count != 0)
{
CTRL_Unwind unwind = df_push_unwind_from_thread(scratch.arena, thread);
U64 unwind_idx = 0;
for(CTRL_UnwindFrame *frame = unwind.first; frame != 0; frame = frame->next, unwind_idx += 1)
{
if(unwind_count == unwind_idx)
{
result = frame->rip;
break;
}
}
}
scratch_end(scratch);
return result;
}
internal EVAL_String2NumMap * internal EVAL_String2NumMap *
df_push_locals_map_from_binary_voff(Arena *arena, DBGI_Scope *scope, DF_Entity *binary, U64 voff) df_push_locals_map_from_binary_voff(Arena *arena, DBGI_Scope *scope, DF_Entity *binary, U64 voff)
{ {
@@ -3718,26 +3661,33 @@ df_push_member_map_from_binary_voff(Arena *arena, DBGI_Scope *scope, DF_Entity *
internal B32 internal B32
df_set_thread_rip(DF_Entity *thread, U64 vaddr) df_set_thread_rip(DF_Entity *thread, U64 vaddr)
{ {
B32 result = ctrl_thread_write_rip(thread->ctrl_machine_id, thread->ctrl_handle, vaddr); Temp scratch = scratch_begin(0, 0);
void *block = ctrl_query_cached_reg_block_from_thread(scratch.arena, df_state->ctrl_entity_store, thread->ctrl_machine_id, thread->ctrl_handle);
regs_arch_block_write_rip(thread->arch, block, vaddr);
B32 result = ctrl_thread_write_reg_block(thread->ctrl_machine_id, thread->ctrl_handle, block);
// rjf: early mutation of unwind cache for immediate frontend effect // rjf: early mutation of unwind cache for immediate frontend effect
if(result) if(result)
{ {
DF_RunUnwindCache *unwind_cache = &df_state->unwind_cache; DF_RunUnwindCache *unwind_cache = &df_state->unwind_caches[df_state->unwind_cache_gen%ArrayCount(df_state->unwind_caches)];
DF_Handle thread_handle = df_handle_from_entity(thread); if(unwind_cache->slots_count != 0)
U64 hash = df_hash_from_string(str8_struct(&thread_handle));
U64 slot_idx = hash % unwind_cache->table_size;
DF_RunUnwindCacheSlot *slot = &unwind_cache->table[slot_idx];
for(DF_RunUnwindCacheNode *n = slot->first; n != 0; n = n->hash_next)
{ {
if(df_handle_match(n->thread, thread_handle) && n->unwind.first != 0) DF_Handle thread_handle = df_handle_from_entity(thread);
U64 hash = df_hash_from_string(str8_struct(&thread_handle));
U64 slot_idx = hash % unwind_cache->slots_count;
DF_RunUnwindCacheSlot *slot = &unwind_cache->slots[slot_idx];
for(DF_RunUnwindCacheNode *n = slot->first; n != 0; n = n->hash_next)
{ {
n->unwind.first->rip = vaddr; if(df_handle_match(n->thread, thread_handle) && n->unwind.first != 0)
break; {
n->unwind.first->rip = vaddr;
break;
}
} }
} }
} }
scratch_end(scratch);
return result; return result;
} }
@@ -4134,7 +4084,7 @@ df_eval_from_string(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_
//- rjf: unpack arguments //- rjf: unpack arguments
DF_Entity *thread = df_entity_from_handle(ctrl_ctx->thread); DF_Entity *thread = df_entity_from_handle(ctrl_ctx->thread);
U64 tls_root_vaddr = ctrl_tls_root_vaddr_from_thread(thread->ctrl_machine_id, thread->ctrl_handle); U64 tls_root_vaddr = ctrl_query_cached_tls_root_vaddr_from_thread(df_state->ctrl_entity_store, thread->ctrl_machine_id, thread->ctrl_handle);
DF_Entity *process = thread->parent; DF_Entity *process = thread->parent;
U64 unwind_count = ctrl_ctx->unwind_count; U64 unwind_count = ctrl_ctx->unwind_count;
CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread); CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread);
@@ -6188,37 +6138,57 @@ df_push_active_target_list(Arena *arena)
internal CTRL_Unwind internal CTRL_Unwind
df_query_cached_unwind_from_thread(DF_Entity *thread) df_query_cached_unwind_from_thread(DF_Entity *thread)
{ {
ProfBeginFunction();
CTRL_Unwind result = {0}; CTRL_Unwind result = {0};
DF_RunUnwindCache *cache = &df_state->unwind_cache; DF_Handle handle = df_handle_from_entity(thread);
if(cache->table_size != 0) U64 hash = df_hash_from_string(str8_struct(&handle));
for(U64 cache_idx = 0; cache_idx < ArrayCount(df_state->unwind_caches); cache_idx += 1)
{ {
DF_Handle handle = df_handle_from_entity(thread); DF_RunUnwindCache *cache = &df_state->unwind_caches[(df_state->unwind_cache_gen+cache_idx)%ArrayCount(df_state->unwind_caches)];
U64 hash = df_hash_from_string(str8_struct(&handle)); if(cache_idx == 0 && cache->slots_count == 0)
U64 slot_idx = hash % cache->table_size; {
DF_RunUnwindCacheSlot *slot = &cache->table[slot_idx]; cache->slots_count = 1024;
cache->slots = push_array(cache->arena, DF_RunUnwindCacheSlot, cache->slots_count);
}
else if(cache->slots_count == 0)
{
break;
}
U64 slot_idx = hash%cache->slots_count;
DF_RunUnwindCacheSlot *slot = &cache->slots[slot_idx];
DF_RunUnwindCacheNode *node = 0;
for(DF_RunUnwindCacheNode *n = slot->first; n != 0; n = n->hash_next) for(DF_RunUnwindCacheNode *n = slot->first; n != 0; n = n->hash_next)
{ {
if(df_handle_match(n->thread, handle)) if(df_handle_match(n->thread, handle))
{ {
result = n->unwind; node = n;
break;
}
}
if(node != 0)
{
result = node->unwind;
break;
}
else
{
result = ctrl_unwind_from_thread(cache->arena, df_state->ctrl_entity_store, thread->ctrl_machine_id, thread->ctrl_handle, 0);
if(!result.error)
{
node = push_array(cache->arena, DF_RunUnwindCacheNode, 1);
SLLQueuePush_N(slot->first, slot->last, node, hash_next);
node->thread = handle;
node->unwind = result;
break; break;
} }
} }
} }
ProfEnd();
return result; return result;
} }
internal U64 internal U64
df_query_cached_rip_from_thread(DF_Entity *thread) df_query_cached_rip_from_thread(DF_Entity *thread)
{ {
U64 result = 0; U64 result = df_query_cached_rip_from_thread_unwind(thread, 0);
CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread);
if(unwind.first != 0)
{
result = unwind.first->rip;
}
return result; return result;
} }
@@ -6226,14 +6196,21 @@ internal U64
df_query_cached_rip_from_thread_unwind(DF_Entity *thread, U64 unwind_count) df_query_cached_rip_from_thread_unwind(DF_Entity *thread, U64 unwind_count)
{ {
U64 result = 0; U64 result = 0;
CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread); if(unwind_count == 0)
U64 unwind_idx = 0;
for(CTRL_UnwindFrame *frame = unwind.first; frame != 0; frame = frame->next, unwind_idx += 1)
{ {
if(unwind_idx == unwind_count) result = ctrl_query_cached_rip_from_thread(df_state->ctrl_entity_store, thread->ctrl_machine_id, thread->ctrl_handle);
}
else
{
CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread);
U64 unwind_idx = 0;
for(CTRL_UnwindFrame *frame = unwind.first; frame != 0; frame = frame->next, unwind_idx += 1)
{ {
result = frame->rip; if(unwind_idx == unwind_count)
break; {
result = frame->rip;
break;
}
} }
} }
return result; return result;
@@ -6243,13 +6220,18 @@ internal U64
df_query_cached_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64 rip_vaddr) df_query_cached_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64 rip_vaddr)
{ {
U64 result = 0; U64 result = 0;
for(U64 cache_idx = 0; cache_idx < ArrayCount(df_state->tls_base_caches); cache_idx += 1)
{ {
DF_RunTLSBaseCache *cache = &df_state->tls_base_cache; DF_RunTLSBaseCache *cache = &df_state->tls_base_caches[(df_state->tls_base_cache_gen+cache_idx)%ArrayCount(df_state->tls_base_caches)];
if(cache->slots_count == 0) if(cache_idx == 0 && cache->slots_count == 0)
{ {
cache->slots_count = 256; cache->slots_count = 256;
cache->slots = push_array(cache->arena, DF_RunTLSBaseCacheSlot, cache->slots_count); cache->slots = push_array(cache->arena, DF_RunTLSBaseCacheSlot, cache->slots_count);
} }
else if(cache->slots_count == 0)
{
break;
}
DF_Handle handle = df_handle_from_entity(process); DF_Handle handle = df_handle_from_entity(process);
U64 hash = df_hash_from_seed_string(df_hash_from_string(str8_struct(&handle)), str8_struct(&rip_vaddr)); U64 hash = df_hash_from_seed_string(df_hash_from_string(str8_struct(&handle)), str8_struct(&rip_vaddr));
U64 slot_idx = hash%cache->slots_count; U64 slot_idx = hash%cache->slots_count;
@@ -6265,14 +6247,22 @@ df_query_cached_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 roo
} }
if(node == 0) if(node == 0)
{ {
node = push_array(cache->arena, DF_RunTLSBaseCacheNode, 1); U64 tls_base_vaddr = df_tls_base_vaddr_from_process_root_rip(process, root_vaddr, rip_vaddr);
SLLQueuePush_N(slot->first, slot->last, node, hash_next); if(tls_base_vaddr != 0)
node->process = handle; {
node->root_vaddr = root_vaddr; node = push_array(cache->arena, DF_RunTLSBaseCacheNode, 1);
node->rip_vaddr = rip_vaddr; SLLQueuePush_N(slot->first, slot->last, node, hash_next);
node->tls_base_vaddr = df_tls_base_vaddr_from_process_root_rip(process, root_vaddr, rip_vaddr); node->process = handle;
node->root_vaddr = root_vaddr;
node->rip_vaddr = rip_vaddr;
node->tls_base_vaddr = tls_base_vaddr;
}
}
if(node != 0 && node->tls_base_vaddr != 0)
{
result = node->tls_base_vaddr;
break;
} }
result = node->tls_base_vaddr;
} }
return result; return result;
} }
@@ -6282,13 +6272,18 @@ df_query_cached_locals_map_from_binary_voff(DF_Entity *binary, U64 voff)
{ {
ProfBeginFunction(); ProfBeginFunction();
EVAL_String2NumMap *map = &eval_string2num_map_nil; EVAL_String2NumMap *map = &eval_string2num_map_nil;
for(U64 cache_idx = 0; cache_idx < ArrayCount(df_state->locals_caches); cache_idx += 1)
{ {
DF_RunLocalsCache *cache = &df_state->locals_cache; DF_RunLocalsCache *cache = &df_state->locals_caches[(df_state->locals_cache_gen+cache_idx)%ArrayCount(df_state->locals_caches)];
if(cache->table_size == 0) if(cache_idx == 0 && cache->table_size == 0)
{ {
cache->table_size = 256; cache->table_size = 256;
cache->table = push_array(cache->arena, DF_RunLocalsCacheSlot, cache->table_size); cache->table = push_array(cache->arena, DF_RunLocalsCacheSlot, cache->table_size);
} }
else if(cache->table_size == 0)
{
break;
}
DF_Handle handle = df_handle_from_entity(binary); DF_Handle handle = df_handle_from_entity(binary);
U64 hash = df_hash_from_string(str8_struct(&handle)); U64 hash = df_hash_from_string(str8_struct(&handle));
U64 slot_idx = hash % cache->table_size; U64 slot_idx = hash % cache->table_size;
@@ -6316,9 +6311,10 @@ df_query_cached_locals_map_from_binary_voff(DF_Entity *binary, U64 voff)
} }
dbgi_scope_close(scope); dbgi_scope_close(scope);
} }
if(node != 0) if(node != 0 && node->locals_map->slots_count != 0)
{ {
map = node->locals_map; map = node->locals_map;
break;
} }
} }
ProfEnd(); ProfEnd();
@@ -6330,13 +6326,18 @@ df_query_cached_member_map_from_binary_voff(DF_Entity *binary, U64 voff)
{ {
ProfBeginFunction(); ProfBeginFunction();
EVAL_String2NumMap *map = &eval_string2num_map_nil; EVAL_String2NumMap *map = &eval_string2num_map_nil;
for(U64 cache_idx = 0; cache_idx < ArrayCount(df_state->member_caches); cache_idx += 1)
{ {
DF_RunLocalsCache *cache = &df_state->member_cache; DF_RunLocalsCache *cache = &df_state->member_caches[(df_state->member_cache_gen+cache_idx)%ArrayCount(df_state->member_caches)];
if(cache->table_size == 0) if(cache_idx == 0 && cache->table_size == 0)
{ {
cache->table_size = 256; cache->table_size = 256;
cache->table = push_array(cache->arena, DF_RunLocalsCacheSlot, cache->table_size); cache->table = push_array(cache->arena, DF_RunLocalsCacheSlot, cache->table_size);
} }
else if(cache->table_size == 0)
{
break;
}
DF_Handle handle = df_handle_from_entity(binary); DF_Handle handle = df_handle_from_entity(binary);
U64 hash = df_hash_from_string(str8_struct(&handle)); U64 hash = df_hash_from_string(str8_struct(&handle));
U64 slot_idx = hash % cache->table_size; U64 slot_idx = hash % cache->table_size;
@@ -6364,9 +6365,10 @@ df_query_cached_member_map_from_binary_voff(DF_Entity *binary, U64 voff)
} }
dbgi_scope_close(scope); dbgi_scope_close(scope);
} }
if(node != 0) if(node != 0 && node->locals_map->slots_count != 0)
{ {
map = node->locals_map; map = node->locals_map;
break;
} }
} }
ProfEnd(); ProfEnd();
@@ -6396,6 +6398,7 @@ df_core_init(CmdLine *cmdln, DF_StateDeltaHistory *hist)
df_state->entities_base = push_array(df_state->entities_arena, DF_Entity, 0); df_state->entities_base = push_array(df_state->entities_arena, DF_Entity, 0);
df_state->entities_count = 0; df_state->entities_count = 0;
df_state->ctrl_msg_arena = arena_alloc(); df_state->ctrl_msg_arena = arena_alloc();
df_state->ctrl_entity_store = ctrl_entity_store_alloc();
df_state->ctrl_stop_arena = arena_alloc(); df_state->ctrl_stop_arena = arena_alloc();
df_state->entities_root = df_entity_alloc(0, &df_g_nil_entity, DF_EntityKind_Root); df_state->entities_root = df_entity_alloc(0, &df_g_nil_entity, DF_EntityKind_Root);
df_state->cmd_spec_table_size = 1024; df_state->cmd_spec_table_size = 1024;
@@ -6417,7 +6420,7 @@ df_core_init(CmdLine *cmdln, DF_StateDeltaHistory *hist)
// rjf: set up initial entities // rjf: set up initial entities
{ {
DF_Entity *local_machine = df_entity_alloc(0, df_state->entities_root, DF_EntityKind_Machine); DF_Entity *local_machine = df_entity_alloc(0, df_state->entities_root, DF_EntityKind_Machine);
df_entity_equip_ctrl_machine_id(local_machine, CTRL_MachineID_Client); df_entity_equip_ctrl_machine_id(local_machine, CTRL_MachineID_Local);
df_entity_equip_name(0, local_machine, str8_lit("This PC")); df_entity_equip_name(0, local_machine, str8_lit("This PC"));
} }
@@ -6434,10 +6437,22 @@ df_core_init(CmdLine *cmdln, DF_StateDeltaHistory *hist)
} }
// rjf: set up per-run caches // rjf: set up per-run caches
df_state->unwind_cache.arena = arena_alloc(); for(U64 idx = 0; idx < ArrayCount(df_state->unwind_caches); idx += 1)
df_state->tls_base_cache.arena = arena_alloc(); {
df_state->locals_cache.arena = arena_alloc(); df_state->unwind_caches[idx].arena = arena_alloc();
df_state->member_cache.arena = arena_alloc(); }
for(U64 idx = 0; idx < ArrayCount(df_state->tls_base_caches); idx += 1)
{
df_state->tls_base_caches[idx].arena = arena_alloc();
}
for(U64 idx = 0; idx < ArrayCount(df_state->locals_caches); idx += 1)
{
df_state->locals_caches[idx].arena = arena_alloc();
}
for(U64 idx = 0; idx < ArrayCount(df_state->member_caches); idx += 1)
{
df_state->member_caches[idx].arena = arena_alloc();
}
// rjf: set up eval view cache // rjf: set up eval view cache
df_state->eval_view_cache.slots_count = 4096; df_state->eval_view_cache.slots_count = 4096;
@@ -6542,11 +6557,12 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
Temp scratch = scratch_begin(&arena, 1); Temp scratch = scratch_begin(&arena, 1);
//- rjf: grab next reggen/memgen //- rjf: grab next reggen/memgen
U64 new_memgen_idx = ctrl_memgen_idx(); U64 new_mem_gen = ctrl_mem_gen();
U64 new_reggen_idx = ctrl_reggen_idx(); U64 new_reg_gen = ctrl_reg_gen();
//- rjf: consume & process events //- rjf: consume & process events
CTRL_EventList events = ctrl_c2u_pop_events(scratch.arena); CTRL_EventList events = ctrl_c2u_pop_events(scratch.arena);
ctrl_entity_store_apply_events(df_state->ctrl_entity_store, &events);
for(CTRL_EventNode *event_n = events.first; event_n != 0; event_n = event_n->next) for(CTRL_EventNode *event_n = events.first; event_n != 0; event_n = event_n->next)
{ {
CTRL_Event *event = &event_n->v; CTRL_Event *event = &event_n->v;
@@ -6586,7 +6602,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
// rjf: thread hit user breakpoint -> increment breakpoint hit count // rjf: thread hit user breakpoint -> increment breakpoint hit count
if(event->cause == CTRL_EventCause_UserBreakpoint) if(event->cause == CTRL_EventCause_UserBreakpoint)
{ {
U64 stop_thread_vaddr = df_rip_from_thread(stop_thread); U64 stop_thread_vaddr = ctrl_query_cached_rip_from_thread(df_state->ctrl_entity_store, stop_thread->ctrl_machine_id, stop_thread->ctrl_handle);
DF_Entity *process = df_entity_ancestor_from_kind(stop_thread, DF_EntityKind_Process); DF_Entity *process = df_entity_ancestor_from_kind(stop_thread, DF_EntityKind_Process);
DF_Entity *module = df_module_from_process_vaddr(process, stop_thread_vaddr); DF_Entity *module = df_module_from_process_vaddr(process, stop_thread_vaddr);
DF_Entity *binary = df_binary_file_from_module(module); DF_Entity *binary = df_binary_file_from_module(module);
@@ -6895,7 +6911,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
} }
} }
// rjf: collect s top info // rjf: collect stop info
arena_clear(df_state->ctrl_stop_arena); arena_clear(df_state->ctrl_stop_arena);
MemoryCopyStruct(&df_state->ctrl_last_stop_event, event); MemoryCopyStruct(&df_state->ctrl_last_stop_event, event);
df_state->ctrl_last_stop_event.string = push_str8_copy(df_state->ctrl_stop_arena, df_state->ctrl_last_stop_event.string); df_state->ctrl_last_stop_event.string = push_str8_copy(df_state->ctrl_stop_arena, df_state->ctrl_last_stop_event.string);
@@ -6903,72 +6919,55 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
} }
} }
//- rjf: refresh unwind cache //- rjf: clear unwind cache
if((df_state->unwind_cache_memgen_idx != new_memgen_idx || if((df_state->unwind_cache_memgen_idx != new_mem_gen ||
df_state->unwind_cache_reggen_idx != new_reggen_idx) && df_state->unwind_cache_reggen_idx != new_reg_gen) &&
!df_ctrl_targets_running()) ProfScope("per-thread unwind gather") !df_ctrl_targets_running()) ProfScope("per-thread unwind gather")
{ {
B32 good = 1; df_state->unwind_cache_gen += 1;
DF_EntityList all_threads = df_query_cached_entity_list_with_kind(DF_EntityKind_Thread); DF_RunUnwindCache *cache = &df_state->unwind_caches[df_state->unwind_cache_gen%ArrayCount(df_state->unwind_caches)];
DF_RunUnwindCache *cache = &df_state->unwind_cache;
arena_clear(cache->arena);
cache->table_size = 1024;
cache->table = push_array(cache->arena, DF_RunUnwindCacheSlot, cache->table_size);
for(DF_EntityNode *n = all_threads.first; n != 0; n = n->next)
{
DF_Entity *thread = n->entity;
DF_Handle thread_handle = df_handle_from_entity(thread);
U64 hash = df_hash_from_string(str8_struct(&thread_handle));
U64 slot_idx = hash % cache->table_size;
DF_RunUnwindCacheSlot *slot = &cache->table[slot_idx];
DF_RunUnwindCacheNode *cache_node = push_array(cache->arena, DF_RunUnwindCacheNode, 1);
cache_node->thread = thread_handle;
cache_node->unwind = df_push_unwind_from_thread(cache->arena, thread);
SLLQueuePush_NZ(0, slot->first, slot->last, cache_node, hash_next);
if(cache_node->unwind.error != 0)
{
good = 0;
break;
}
}
if(good)
{
df_state->unwind_cache_memgen_idx = new_memgen_idx;
df_state->unwind_cache_reggen_idx = new_reggen_idx;
}
}
//- rjf: clear tls base cache
if((df_state->tls_base_cache_reggen_idx != new_reggen_idx ||
df_state->tls_base_cache_memgen_idx != new_memgen_idx) &&
!df_ctrl_targets_running())
{
DF_RunTLSBaseCache *cache = &df_state->tls_base_cache;
arena_clear(cache->arena); arena_clear(cache->arena);
cache->slots_count = 0; cache->slots_count = 0;
cache->slots = 0; cache->slots = 0;
df_state->tls_base_cache_reggen_idx = new_reggen_idx; df_state->unwind_cache_memgen_idx = new_mem_gen;
df_state->tls_base_cache_memgen_idx = new_memgen_idx; df_state->unwind_cache_reggen_idx = new_reg_gen;
}
//- rjf: clear tls base cache
if((df_state->tls_base_cache_reggen_idx != new_reg_gen ||
df_state->tls_base_cache_memgen_idx != new_mem_gen) &&
!df_ctrl_targets_running())
{
df_state->tls_base_cache_gen += 1;
DF_RunTLSBaseCache *cache = &df_state->tls_base_caches[df_state->tls_base_cache_gen%ArrayCount(df_state->tls_base_caches)];
arena_clear(cache->arena);
cache->slots_count = 0;
cache->slots = 0;
df_state->tls_base_cache_reggen_idx = new_reg_gen;
df_state->tls_base_cache_memgen_idx = new_mem_gen;
} }
//- rjf: clear locals cache //- rjf: clear locals cache
if(df_state->locals_cache_reggen_idx != new_reggen_idx && !df_ctrl_targets_running()) if(df_state->locals_cache_reggen_idx != new_reg_gen &&
!df_ctrl_targets_running())
{ {
DF_RunLocalsCache *cache = &df_state->locals_cache; df_state->locals_cache_gen += 1;
DF_RunLocalsCache *cache = &df_state->locals_caches[df_state->locals_cache_gen%ArrayCount(df_state->locals_caches)];
arena_clear(cache->arena); arena_clear(cache->arena);
cache->table_size = 0; cache->table_size = 0;
cache->table = 0; cache->table = 0;
df_state->locals_cache_reggen_idx = new_reggen_idx; df_state->locals_cache_reggen_idx = new_reg_gen;
} }
//- rjf: clear members cache //- rjf: clear members cache
if(df_state->member_cache_reggen_idx != new_reggen_idx && !df_ctrl_targets_running()) if(df_state->member_cache_reggen_idx != new_reg_gen && !df_ctrl_targets_running())
{ {
DF_RunLocalsCache *cache = &df_state->member_cache; df_state->member_cache_gen += 1;
DF_RunLocalsCache *cache = &df_state->member_caches[df_state->member_cache_gen%ArrayCount(df_state->member_caches)];
arena_clear(cache->arena); arena_clear(cache->arena);
cache->table_size = 0; cache->table_size = 0;
cache->table = 0; cache->table = 0;
df_state->member_cache_reggen_idx = new_reggen_idx; df_state->member_cache_reggen_idx = new_reg_gen;
} }
scratch_end(scratch); scratch_end(scratch);
@@ -7515,7 +7514,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
}break; }break;
case DF_CoreCmdKind_FreezeLocalMachine: case DF_CoreCmdKind_FreezeLocalMachine:
{ {
CTRL_MachineID machine_id = CTRL_MachineID_Client; CTRL_MachineID machine_id = CTRL_MachineID_Local;
DF_CmdParams params = df_cmd_params_zero(); DF_CmdParams params = df_cmd_params_zero();
params.entity = df_handle_from_entity(df_machine_entity_from_machine_id(machine_id)); params.entity = df_handle_from_entity(df_machine_entity_from_machine_id(machine_id));
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_Entity); df_cmd_params_mark_slot(&params, DF_CmdParamSlot_Entity);
@@ -7523,7 +7522,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
}break; }break;
case DF_CoreCmdKind_ThawLocalMachine: case DF_CoreCmdKind_ThawLocalMachine:
{ {
CTRL_MachineID machine_id = CTRL_MachineID_Client; CTRL_MachineID machine_id = CTRL_MachineID_Local;
DF_CmdParams params = df_cmd_params_zero(); DF_CmdParams params = df_cmd_params_zero();
params.entity = df_handle_from_entity(df_machine_entity_from_machine_id(machine_id)); params.entity = df_handle_from_entity(df_machine_entity_from_machine_id(machine_id));
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_Entity); df_cmd_params_mark_slot(&params, DF_CmdParamSlot_Entity);
+14 -14
View File
@@ -447,7 +447,7 @@ struct DF_Entity
// rjf: ctrl entity equipment // rjf: ctrl entity equipment
CTRL_MachineID ctrl_machine_id; CTRL_MachineID ctrl_machine_id;
CTRL_Handle ctrl_handle; DMN_Handle ctrl_handle;
Architecture arch; Architecture arch;
U32 ctrl_id; U32 ctrl_id;
U64 stack_base; U64 stack_base;
@@ -940,7 +940,6 @@ struct DF_RunUnwindCacheNode
DF_RunUnwindCacheNode *hash_next; DF_RunUnwindCacheNode *hash_next;
DF_Handle thread; DF_Handle thread;
CTRL_Unwind unwind; CTRL_Unwind unwind;
U64 tls_base_vaddr;
}; };
typedef struct DF_RunUnwindCacheSlot DF_RunUnwindCacheSlot; typedef struct DF_RunUnwindCacheSlot DF_RunUnwindCacheSlot;
@@ -954,8 +953,8 @@ typedef struct DF_RunUnwindCache DF_RunUnwindCache;
struct DF_RunUnwindCache struct DF_RunUnwindCache
{ {
Arena *arena; Arena *arena;
U64 table_size; U64 slots_count;
DF_RunUnwindCacheSlot *table; DF_RunUnwindCacheSlot *slots;
}; };
//- rjf: per-run tls-base-vaddr cache //- rjf: per-run tls-base-vaddr cache
@@ -1136,14 +1135,18 @@ struct DF_State
// rjf: per-run caches // rjf: per-run caches
U64 unwind_cache_reggen_idx; U64 unwind_cache_reggen_idx;
U64 unwind_cache_memgen_idx; U64 unwind_cache_memgen_idx;
DF_RunUnwindCache unwind_cache; DF_RunUnwindCache unwind_caches[2];
U64 unwind_cache_gen;
U64 tls_base_cache_reggen_idx; U64 tls_base_cache_reggen_idx;
U64 tls_base_cache_memgen_idx; U64 tls_base_cache_memgen_idx;
DF_RunTLSBaseCache tls_base_cache; DF_RunTLSBaseCache tls_base_caches[2];
U64 tls_base_cache_gen;
U64 locals_cache_reggen_idx; U64 locals_cache_reggen_idx;
DF_RunLocalsCache locals_cache; DF_RunLocalsCache locals_caches[2];
U64 locals_cache_gen;
U64 member_cache_reggen_idx; U64 member_cache_reggen_idx;
DF_RunLocalsCache member_cache; DF_RunLocalsCache member_caches[2];
U64 member_cache_gen;
// rjf: eval view cache // rjf: eval view cache
DF_EvalViewCache eval_view_cache; DF_EvalViewCache eval_view_cache;
@@ -1179,6 +1182,7 @@ struct DF_State
B32 ctrl_solo_stepping_mode; B32 ctrl_solo_stepping_mode;
// rjf: control thread ctrl -> user reading state // rjf: control thread ctrl -> user reading state
CTRL_EntityStore *ctrl_entity_store;
Arena *ctrl_stop_arena; Arena *ctrl_stop_arena;
CTRL_Event ctrl_last_stop_event; CTRL_Event ctrl_last_stop_event;
@@ -1447,7 +1451,7 @@ internal void df_entity_equip_cfg_src(DF_Entity *entity, DF_CfgSrc cfg_src);
//- rjf: control layer correllation equipment //- rjf: control layer correllation equipment
internal void df_entity_equip_ctrl_machine_id(DF_Entity *entity, CTRL_MachineID machine_id); internal void df_entity_equip_ctrl_machine_id(DF_Entity *entity, CTRL_MachineID machine_id);
internal void df_entity_equip_ctrl_handle(DF_Entity *entity, CTRL_Handle handle); internal void df_entity_equip_ctrl_handle(DF_Entity *entity, DMN_Handle handle);
internal void df_entity_equip_arch(DF_Entity *entity, Architecture arch); internal void df_entity_equip_arch(DF_Entity *entity, Architecture arch);
internal void df_entity_equip_ctrl_id(DF_Entity *entity, U32 id); internal void df_entity_equip_ctrl_id(DF_Entity *entity, U32 id);
internal void df_entity_equip_stack_base(DF_Entity *entity, U64 stack_base); internal void df_entity_equip_stack_base(DF_Entity *entity, U64 stack_base);
@@ -1468,7 +1472,7 @@ internal DF_Entity *df_entity_root(void);
internal DF_EntityList df_push_entity_list_with_kind(Arena *arena, DF_EntityKind kind); internal DF_EntityList df_push_entity_list_with_kind(Arena *arena, DF_EntityKind kind);
internal DF_Entity *df_entity_from_id(DF_EntityID id); internal DF_Entity *df_entity_from_id(DF_EntityID id);
internal DF_Entity *df_machine_entity_from_machine_id(CTRL_MachineID machine_id); internal DF_Entity *df_machine_entity_from_machine_id(CTRL_MachineID machine_id);
internal DF_Entity *df_entity_from_ctrl_handle(CTRL_MachineID machine_id, CTRL_Handle handle); internal DF_Entity *df_entity_from_ctrl_handle(CTRL_MachineID machine_id, DMN_Handle handle);
internal DF_Entity *df_entity_from_ctrl_id(CTRL_MachineID machine_id, U32 id); internal DF_Entity *df_entity_from_ctrl_id(CTRL_MachineID machine_id, U32 id);
internal DF_Entity *df_entity_from_name_and_kind(String8 string, DF_EntityKind kind); internal DF_Entity *df_entity_from_name_and_kind(String8 string, DF_EntityKind kind);
internal DF_Entity *df_entity_from_u64_and_kind(U64 u64, DF_EntityKind kind); internal DF_Entity *df_entity_from_u64_and_kind(U64 u64, DF_EntityKind kind);
@@ -1533,7 +1537,6 @@ internal DF_TextLineSrc2DasmInfoListArray df_text_line_src2dasm_info_list_array_
//- rjf: voff -> src lookups //- rjf: voff -> src lookups
internal DF_TextLineDasm2SrcInfo df_text_line_dasm2src_info_from_binary_voff(DF_Entity *binary, U64 voff); internal DF_TextLineDasm2SrcInfo df_text_line_dasm2src_info_from_binary_voff(DF_Entity *binary, U64 voff);
internal DF_TextLineDasm2SrcInfoList df_text_line_dasm2src_info_from_voff(Arena *arena, U64 voff);
//- rjf: symbol -> voff lookups //- rjf: symbol -> voff lookups
internal U64 df_voff_from_binary_symbol_name(DF_Entity *binary, String8 symbol_name); internal U64 df_voff_from_binary_symbol_name(DF_Entity *binary, String8 symbol_name);
@@ -1547,9 +1550,6 @@ internal DF_Entity *df_module_from_process_vaddr(DF_Entity *process, U64 vaddr);
internal DF_Entity *df_module_from_thread(DF_Entity *thread); internal DF_Entity *df_module_from_thread(DF_Entity *thread);
internal U64 df_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64 rip_vaddr); internal U64 df_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64 rip_vaddr);
internal Architecture df_architecture_from_entity(DF_Entity *entity); internal Architecture df_architecture_from_entity(DF_Entity *entity);
internal CTRL_Unwind df_push_unwind_from_thread(Arena *arena, DF_Entity *thread);
internal U64 df_rip_from_thread(DF_Entity *thread);
internal U64 df_rip_from_thread_unwind(DF_Entity *thread, U64 unwind_count);
internal EVAL_String2NumMap *df_push_locals_map_from_binary_voff(Arena *arena, DBGI_Scope *scope, DF_Entity *binary, U64 voff); internal EVAL_String2NumMap *df_push_locals_map_from_binary_voff(Arena *arena, DBGI_Scope *scope, DF_Entity *binary, U64 voff);
internal EVAL_String2NumMap *df_push_member_map_from_binary_voff(Arena *arena, DBGI_Scope *scope, DF_Entity *binary, U64 voff); internal EVAL_String2NumMap *df_push_member_map_from_binary_voff(Arena *arena, DBGI_Scope *scope, DF_Entity *binary, U64 voff);
internal B32 df_set_thread_rip(DF_Entity *thread, U64 vaddr); internal B32 df_set_thread_rip(DF_Entity *thread, U64 vaddr);
+3 -3
View File
@@ -2131,7 +2131,7 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D
if(thread->kind == DF_EntityKind_Thread) if(thread->kind == DF_EntityKind_Thread)
{ {
// rjf: grab rip // rjf: grab rip
U64 rip_vaddr = (unwind_count == 0 ? df_rip_from_thread(thread) : df_query_cached_rip_from_thread_unwind(thread, unwind_count)); U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count);
// rjf: extract thread/rip info // rjf: extract thread/rip info
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
@@ -3111,8 +3111,8 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D
avg_ui_hash_chain_length = chain_length_sum / chain_count; avg_ui_hash_chain_length = chain_length_sum / chain_count;
} }
ui_labelf("Target Hz: %.2f", 1.f/df_dt()); ui_labelf("Target Hz: %.2f", 1.f/df_dt());
ui_labelf("Ctrl Run Index: %I64u", ctrl_run_idx()); ui_labelf("Ctrl Run Index: %I64u", ctrl_run_gen());
ui_labelf("Ctrl Mem Gen Index: %I64u", ctrl_memgen_idx()); ui_labelf("Ctrl Mem Gen Index: %I64u", ctrl_mem_gen());
ui_labelf("Window %p", window); ui_labelf("Window %p", window);
ui_set_next_pref_width(ui_children_sum(1)); ui_set_next_pref_width(ui_children_sum(1));
ui_set_next_pref_height(ui_children_sum(1)); ui_set_next_pref_height(ui_children_sum(1));
+7 -7
View File
@@ -565,7 +565,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(rgba)
Vec4F32 rgba = {0}; Vec4F32 rgba = {0};
Vec4F32 hsva = {0}; Vec4F32 hsva = {0};
{ {
if(state->memgen_idx >= ctrl_memgen_idx()) if(state->memgen_idx >= ctrl_mem_gen())
{ {
hsva = state->hsva; hsva = state->hsva;
rgba = rgba_from_hsva(hsva); rgba = rgba_from_hsva(hsva);
@@ -575,7 +575,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(rgba)
DF_Eval value_eval = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdi, ctrl_ctx, eval); DF_Eval value_eval = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdi, ctrl_ctx, eval);
rgba = df_view_rule_hooks__rgba_from_eval(value_eval, parse_ctx->type_graph, parse_ctx->rdi, process); rgba = df_view_rule_hooks__rgba_from_eval(value_eval, parse_ctx->type_graph, parse_ctx->rdi, process);
state->hsva = hsva = hsva_from_rgba(rgba); state->hsva = hsva = hsva_from_rgba(rgba);
state->memgen_idx = ctrl_memgen_idx(); state->memgen_idx = ctrl_mem_gen();
} }
} }
Vec4F32 initial_hsva = hsva; Vec4F32 initial_hsva = hsva;
@@ -624,7 +624,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(rgba)
{ {
Vec4F32 rgba = rgba_from_hsva(hsva); Vec4F32 rgba = rgba_from_hsva(hsva);
df_view_rule_hooks__eval_commit_rgba(eval, parse_ctx->type_graph, parse_ctx->rdi, ctrl_ctx, rgba); df_view_rule_hooks__eval_commit_rgba(eval, parse_ctx->type_graph, parse_ctx->rdi, ctrl_ctx, rgba);
state->memgen_idx = ctrl_memgen_idx(); state->memgen_idx = ctrl_mem_gen();
} }
//- rjf: commit possible edited value to state //- rjf: commit possible edited value to state
@@ -700,7 +700,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text)
} }
//- rjf: address range -> hash //- rjf: address range -> hash
U128 hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vaddr_range, 1, 0); U128 hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vaddr_range, 1, 0, 0);
//- rjf: hash -> data //- rjf: hash -> data
String8 data = hs_data_from_hash(hs_scope, hash); String8 data = hs_data_from_hash(hs_scope, hash);
@@ -891,7 +891,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(bitmap)
} }
//- rjf: address range -> hash //- rjf: address range -> hash
U128 hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vaddr_range, 0, 0); U128 hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vaddr_range, 0, 0, 0);
//- rjf: hash & topology -> texture //- rjf: hash & topology -> texture
TEX_Topology topology = tex_topology_make(v2s32((S32)topology_info.width, (S32)topology_info.height), topology_info.fmt); TEX_Topology topology = tex_topology_make(v2s32((S32)topology_info.width, (S32)topology_info.height), topology_info.fmt);
@@ -1151,8 +1151,8 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(geo)
} }
//- rjf: address range -> hash //- rjf: address range -> hash
U128 index_buffer_hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, index_buffer_vaddr_range, 0, 0); U128 index_buffer_hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, index_buffer_vaddr_range, 0, 0, 0);
U128 vertex_buffer_hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vertex_buffer_vaddr_range, 0, 0); U128 vertex_buffer_hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vertex_buffer_vaddr_range, 0, 0, 0);
//- rjf: get gpu buffers //- rjf: get gpu buffers
R_Handle index_buffer = geo_buffer_from_key_hash(geo_scope, index_buffer_key, index_buffer_hash); R_Handle index_buffer = geo_buffer_from_key_hash(geo_scope, index_buffer_key, index_buffer_hash);
+13 -8
View File
@@ -240,9 +240,9 @@ df_process_info_list_from_query(Arena *arena, String8 query)
//- rjf: build list //- rjf: build list
DF_ProcessInfoList list = {0}; DF_ProcessInfoList list = {0};
{ {
DEMON_ProcessIter iter = {0}; DMN_ProcessIter iter = {0};
demon_proc_iter_begin(&iter); dmn_process_iter_begin(&iter);
for(DEMON_ProcessInfo info = {0}; demon_proc_iter_next(scratch.arena, &iter, &info);) for(DMN_ProcessInfo info = {0}; dmn_process_iter_next(scratch.arena, &iter, &info);)
{ {
// rjf: skip root-level or otherwise 0-pid processes // rjf: skip root-level or otherwise 0-pid processes
if(info.pid == 0) if(info.pid == 0)
@@ -290,7 +290,7 @@ df_process_info_list_from_query(Arena *arena, String8 query)
list.count += 1; list.count += 1;
} }
} }
demon_proc_iter_end(&iter); dmn_process_iter_end(&iter);
} }
scratch_end(scratch); scratch_end(scratch);
@@ -6235,6 +6235,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
} }
// rjf: find live threads mapping to this disassembly // rjf: find live threads mapping to this disassembly
ProfScope("find live threads mapping to this disassembly")
{ {
DF_Entity *selected_thread = df_entity_from_handle(ctrl_ctx.thread); DF_Entity *selected_thread = df_entity_from_handle(ctrl_ctx.thread);
DF_EntityList threads = df_query_cached_entity_list_with_kind(DF_EntityKind_Thread); DF_EntityList threads = df_query_cached_entity_list_with_kind(DF_EntityKind_Thread);
@@ -6257,6 +6258,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
} }
// rjf: find breakpoints mapping to this disassembly // rjf: find breakpoints mapping to this disassembly
ProfScope("find breakpoints mapping to this disassembly")
{ {
DF_EntityList bps = df_query_cached_entity_list_with_kind(DF_EntityKind_Breakpoint); DF_EntityList bps = df_query_cached_entity_list_with_kind(DF_EntityKind_Breakpoint);
for(DF_EntityNode *n = bps.first; n != 0; n = n->next) for(DF_EntityNode *n = bps.first; n != 0; n = n->next)
@@ -6277,6 +6279,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
} }
// rjf: find watch pins mapping to this disassembly // rjf: find watch pins mapping to this disassembly
ProfScope("find watch pins mapping to this disassembly")
{ {
DF_EntityList pins = df_query_cached_entity_list_with_kind(DF_EntityKind_WatchPin); DF_EntityList pins = df_query_cached_entity_list_with_kind(DF_EntityKind_WatchPin);
for(DF_EntityNode *n = pins.first; n != 0; n = n->next) for(DF_EntityNode *n = pins.first; n != 0; n = n->next)
@@ -7552,8 +7555,9 @@ DF_VIEW_CMD_FUNCTION_DEF(Memory)
DF_VIEW_UI_FUNCTION_DEF(Memory) DF_VIEW_UI_FUNCTION_DEF(Memory)
{ {
Temp scratch = scratch_begin(0, 0);
ProfBeginFunction(); ProfBeginFunction();
Temp scratch = scratch_begin(0, 0);
HS_Scope *hs_scope = hs_scope_open();
////////////////////////////// //////////////////////////////
//- rjf: unpack state //- rjf: unpack state
@@ -7755,7 +7759,7 @@ DF_VIEW_UI_FUNCTION_DEF(Memory)
U8 *visible_memory = 0; U8 *visible_memory = 0;
{ {
Rng1U64 chunk_aligned_range_bytes = r1u64(AlignDownPow2(viz_range_bytes.min, KB(4)), AlignPow2(viz_range_bytes.max, KB(4))); Rng1U64 chunk_aligned_range_bytes = r1u64(AlignDownPow2(viz_range_bytes.min, KB(4)), AlignPow2(viz_range_bytes.max, KB(4)));
U64 current_memgen_idx = ctrl_memgen_idx(); U64 current_memgen_idx = ctrl_mem_gen();
B32 range_changed = (chunk_aligned_range_bytes.min != mv->last_viewed_memory_cache_range.min || B32 range_changed = (chunk_aligned_range_bytes.min != mv->last_viewed_memory_cache_range.min ||
chunk_aligned_range_bytes.max != mv->last_viewed_memory_cache_range.max); chunk_aligned_range_bytes.max != mv->last_viewed_memory_cache_range.max);
B32 mem_changed = (current_memgen_idx != mv->last_viewed_memory_cache_memgen_idx); B32 mem_changed = (current_memgen_idx != mv->last_viewed_memory_cache_memgen_idx);
@@ -7766,8 +7770,8 @@ DF_VIEW_UI_FUNCTION_DEF(Memory)
// rjf: try to read new memory for this range // rjf: try to read new memory for this range
U64 bytes_to_read = dim_1u64(chunk_aligned_range_bytes); U64 bytes_to_read = dim_1u64(chunk_aligned_range_bytes);
U8 *buffer = push_array_no_zero(scratch.arena, U8, bytes_to_read); U8 *buffer = push_array_no_zero(scratch.arena, U8, bytes_to_read);
U64 half1_bytes_read = ctrl_process_read(process->ctrl_machine_id, process->ctrl_handle, r1u64(chunk_aligned_range_bytes.min, chunk_aligned_range_bytes.min+bytes_to_read/2), buffer+0); U64 half1_bytes_read = dmn_process_read(process->ctrl_handle, r1u64(chunk_aligned_range_bytes.min, chunk_aligned_range_bytes.min+bytes_to_read/2), buffer+0);
U64 half2_bytes_read = ctrl_process_read(process->ctrl_machine_id, process->ctrl_handle, r1u64(chunk_aligned_range_bytes.min+bytes_to_read/2, chunk_aligned_range_bytes.max), buffer+bytes_to_read/2); U64 half2_bytes_read = dmn_process_read(process->ctrl_handle, r1u64(chunk_aligned_range_bytes.min+bytes_to_read/2, chunk_aligned_range_bytes.max), buffer+bytes_to_read/2);
// rjf: worked? -> clear cache & store // rjf: worked? -> clear cache & store
if(half1_bytes_read+half2_bytes_read >= bytes_to_read) if(half1_bytes_read+half2_bytes_read >= bytes_to_read)
@@ -8340,6 +8344,7 @@ DF_VIEW_UI_FUNCTION_DEF(Memory)
} }
} }
hs_scope_close(hs_scope);
scratch_end(scratch); scratch_end(scratch);
ProfEnd(); ProfEnd();
} }
+1 -1
View File
@@ -144,7 +144,7 @@ struct DF_EntityListerItemArray
typedef struct DF_ProcessInfo DF_ProcessInfo; typedef struct DF_ProcessInfo DF_ProcessInfo;
struct DF_ProcessInfo struct DF_ProcessInfo
{ {
DEMON_ProcessInfo info; DMN_ProcessInfo info;
B32 is_attached; B32 is_attached;
FuzzyMatchRangeList attached_match_ranges; FuzzyMatchRangeList attached_match_ranges;
FuzzyMatchRangeList name_match_ranges; FuzzyMatchRangeList name_match_ranges;
+2 -2
View File
@@ -372,7 +372,7 @@ mg_str_expr_parse_from_first_opl__min_prec(Arena *arena, MD_Node *first, MD_Node
//- rjf: consume prefix operators //- rjf: consume prefix operators
MG_StrExpr *leafmost_op = &mg_str_expr_nil; MG_StrExpr *leafmost_op = &mg_str_expr_nil;
for(;it < opl && !md_node_is_nil(it);) for(;it != opl && !md_node_is_nil(it);)
{ {
MG_StrExprOp found_op = MG_StrExprOp_Null; MG_StrExprOp found_op = MG_StrExprOp_Null;
for(MG_StrExprOp op = (MG_StrExprOp)(MG_StrExprOp_Null+1); for(MG_StrExprOp op = (MG_StrExprOp)(MG_StrExprOp_Null+1);
@@ -431,7 +431,7 @@ mg_str_expr_parse_from_first_opl__min_prec(Arena *arena, MD_Node *first, MD_Node
} }
//- rjf: parse binary operator extensions at this precedence level //- rjf: parse binary operator extensions at this precedence level
for(;it < opl && !md_node_is_nil(it);) for(;it != opl && !md_node_is_nil(it);)
{ {
// rjf: find binary op kind of `it` // rjf: find binary op kind of `it`
MG_StrExprOp found_op = MG_StrExprOp_Null; MG_StrExprOp found_op = MG_StrExprOp_Null;
+9 -6
View File
@@ -1,13 +1,18 @@
// 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
//
// [ ] TLS eval -> in-process-memory EXE info
// [ ] unwinding -> in-process-memory EXE info
// [x] solidify synchronization mechanisms for usage of demon2 layer
// [x] TLS eval correctness
// [x] 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
// [ ] 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
@@ -79,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)
+3 -3
View File
@@ -6,7 +6,7 @@
#define BUILD_VERSION_MAJOR 0 #define BUILD_VERSION_MAJOR 0
#define BUILD_VERSION_MINOR 9 #define BUILD_VERSION_MINOR 9
#define BUILD_VERSION_PATCH 8 #define BUILD_VERSION_PATCH 9
#define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA" #define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA"
#define BUILD_TITLE "The RAD Debugger" #define BUILD_TITLE "The RAD Debugger"
#define OS_FEATURE_GRAPHICAL 1 #define OS_FEATURE_GRAPHICAL 1
@@ -43,7 +43,7 @@
#include "regs/raddbgi/regs_raddbgi.h" #include "regs/raddbgi/regs_raddbgi.h"
#include "type_graph/type_graph.h" #include "type_graph/type_graph.h"
#include "dbgi/dbgi.h" #include "dbgi/dbgi.h"
#include "demon/demon_inc.h" #include "demon2/demon2_inc.h"
#include "eval/eval_inc.h" #include "eval/eval_inc.h"
#include "unwind/unwind.h" #include "unwind/unwind.h"
#include "ctrl/ctrl_inc.h" #include "ctrl/ctrl_inc.h"
@@ -81,7 +81,7 @@
#include "regs/raddbgi/regs_raddbgi.c" #include "regs/raddbgi/regs_raddbgi.c"
#include "type_graph/type_graph.c" #include "type_graph/type_graph.c"
#include "dbgi/dbgi.c" #include "dbgi/dbgi.c"
#include "demon/demon_inc.c" #include "demon2/demon2_inc.c"
#include "eval/eval_inc.c" #include "eval/eval_inc.c"
#include "unwind/unwind.c" #include "unwind/unwind.c"
#include "ctrl/ctrl_inc.c" #include "ctrl/ctrl_inc.c"
+1 -1
View File
@@ -5,7 +5,7 @@
internal U64 regs_block_size_from_architecture(Architecture arch) internal U64 regs_block_size_from_architecture(Architecture arch)
{ {
U64 result = 0; U64 result = 8;
switch(arch) switch(arch)
{ {
default:{}break; default:{}break;
+1 -1
View File
@@ -421,7 +421,7 @@ regs_g_reg_code_x86_usage_kind_table:
{ {
`internal U64 regs_block_size_from_architecture(Architecture arch)`; `internal U64 regs_block_size_from_architecture(Architecture arch)`;
`{`; `{`;
`U64 result = 0;`; `U64 result = 8;`;
`switch(arch)`; `switch(arch)`;
`{`; `{`;
`default:{}break;`; `default:{}break;`;
+2 -2
View File
@@ -46,7 +46,7 @@
#include "demon2/demon2_inc.h" #include "demon2/demon2_inc.h"
#include "eval/eval_inc.h" #include "eval/eval_inc.h"
#include "unwind/unwind.h" #include "unwind/unwind.h"
#include "ctrl2/ctrl2_inc.h" #include "ctrl/ctrl_inc.h"
//- rjf: [c] //- rjf: [c]
#include "base/base_inc.c" #include "base/base_inc.c"
@@ -74,7 +74,7 @@
#include "demon2/demon2_inc.c" #include "demon2/demon2_inc.c"
#include "eval/eval_inc.c" #include "eval/eval_inc.c"
#include "unwind/unwind.c" #include "unwind/unwind.c"
#include "ctrl2/ctrl2_inc.c" #include "ctrl/ctrl_inc.c"
//////////////////////////////// ////////////////////////////////
//~ rjf: Entry Point //~ rjf: Entry Point
+2 -1
View File
@@ -2635,7 +2635,8 @@ ui_signal_from_box(UI_Box *box)
//- rjf: mouse is over this box's rect, no other hot key? -> set hot key, mark hovering //- rjf: mouse is over this box's rect, no other hot key? -> set hot key, mark hovering
// //
{ {
if(contains_2f32(rect, ui_state->mouse) && if(box->flags & UI_BoxFlag_MouseClickable &&
contains_2f32(rect, ui_state->mouse) &&
!contains_2f32(blacklist_rect, ui_state->mouse) && !contains_2f32(blacklist_rect, ui_state->mouse) &&
(ui_key_match(ui_state->hot_box_key, ui_key_zero()) || ui_key_match(ui_state->hot_box_key, box->key)) && (ui_key_match(ui_state->hot_box_key, ui_key_zero()) || ui_key_match(ui_state->hot_box_key, box->key)) &&
(ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], ui_key_zero()) || ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], box->key)) && (ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], ui_key_zero()) || ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], box->key)) &&