mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-13 07:32:23 -07:00
merge
This commit is contained in:
+1
-1
@@ -47,7 +47,7 @@ commands =
|
||||
{
|
||||
.rjf_f1 =
|
||||
{
|
||||
.win = "build ryan_scratch",
|
||||
.win = "build raddbg telemetry",
|
||||
.linux = "",
|
||||
.out = "*compilation*",
|
||||
.footer_panel = true,
|
||||
|
||||
+1269
-909
File diff suppressed because it is too large
Load Diff
+218
-101
@@ -10,16 +10,7 @@
|
||||
typedef U64 CTRL_MsgID;
|
||||
typedef U64 CTRL_MachineID;
|
||||
|
||||
#define CTRL_MachineID_Client (1)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type
|
||||
|
||||
typedef struct CTRL_Handle CTRL_Handle;
|
||||
struct CTRL_Handle
|
||||
{
|
||||
U64 u64[1];
|
||||
};
|
||||
#define CTRL_MachineID_Local (1)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Machine/Handle Pair Types
|
||||
@@ -28,7 +19,7 @@ typedef struct CTRL_MachineIDHandlePair CTRL_MachineIDHandlePair;
|
||||
struct CTRL_MachineIDHandlePair
|
||||
{
|
||||
CTRL_MachineID machine_id;
|
||||
CTRL_Handle handle;
|
||||
DMN_Handle handle;
|
||||
};
|
||||
|
||||
typedef struct CTRL_MachineIDHandlePairNode CTRL_MachineIDHandlePairNode;
|
||||
@@ -46,6 +37,71 @@ struct CTRL_MachineIDHandlePairList
|
||||
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
|
||||
|
||||
@@ -105,8 +161,8 @@ struct CTRL_TrapList
|
||||
typedef struct CTRL_Spoof CTRL_Spoof;
|
||||
struct CTRL_Spoof
|
||||
{
|
||||
CTRL_Handle process;
|
||||
CTRL_Handle thread;
|
||||
DMN_Handle process;
|
||||
DMN_Handle thread;
|
||||
U64 vaddr;
|
||||
U64 new_ip_value;
|
||||
};
|
||||
@@ -177,8 +233,8 @@ struct CTRL_Msg
|
||||
CTRL_MsgKind kind;
|
||||
CTRL_MsgID msg_id;
|
||||
CTRL_MachineID machine_id;
|
||||
CTRL_Handle entity;
|
||||
CTRL_Handle parent;
|
||||
DMN_Handle entity;
|
||||
DMN_Handle parent;
|
||||
U32 entity_id;
|
||||
U32 exit_code;
|
||||
B32 env_inherit;
|
||||
@@ -281,8 +337,8 @@ struct CTRL_Event
|
||||
CTRL_ExceptionKind exception_kind;
|
||||
CTRL_MsgID msg_id;
|
||||
CTRL_MachineID machine_id;
|
||||
CTRL_Handle entity;
|
||||
CTRL_Handle parent;
|
||||
DMN_Handle entity;
|
||||
DMN_Handle parent;
|
||||
Architecture arch;
|
||||
U64 u64_code;
|
||||
U32 entity_id;
|
||||
@@ -320,7 +376,8 @@ struct CTRL_ProcessMemoryRangeHashNode
|
||||
B32 zero_terminated;
|
||||
Rng1U64 vaddr_range_clamped;
|
||||
U128 hash;
|
||||
U64 memgen_idx;
|
||||
U64 mem_gen;
|
||||
U64 last_time_requested_us;
|
||||
B32 is_taken;
|
||||
};
|
||||
|
||||
@@ -338,7 +395,7 @@ struct CTRL_ProcessMemoryCacheNode
|
||||
CTRL_ProcessMemoryCacheNode *prev;
|
||||
Arena *arena;
|
||||
CTRL_MachineID machine_id;
|
||||
CTRL_Handle process;
|
||||
DMN_Handle process;
|
||||
U64 range_hash_slots_count;
|
||||
CTRL_ProcessMemoryRangeHashSlot *range_hash_slots;
|
||||
};
|
||||
@@ -372,6 +429,47 @@ struct CTRL_ProcessMemorySlice
|
||||
String8 data;
|
||||
U64 *byte_bad_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;
|
||||
CTRL_WakeupFunctionType *wakeup_hook;
|
||||
U64 run_idx;
|
||||
U64 memgen_idx;
|
||||
U64 reggen_idx;
|
||||
|
||||
// rjf: name -> register/alias hash tables for eval
|
||||
EVAL_String2NumMap arch_string2reg_tables[Architecture_COUNT];
|
||||
EVAL_String2NumMap arch_string2alias_tables[Architecture_COUNT];
|
||||
|
||||
// rjf: process memory cache
|
||||
// rjf: caches
|
||||
CTRL_ProcessMemoryCache process_memory_cache;
|
||||
CTRL_ThreadRegCache thread_reg_cache;
|
||||
|
||||
// rjf: user -> ctrl msg ring buffer
|
||||
U64 u2c_ring_size;
|
||||
@@ -417,10 +513,11 @@ struct CTRL_State
|
||||
|
||||
// rjf: ctrl thread state
|
||||
OS_Handle ctrl_thread;
|
||||
Arena *demon_event_arena;
|
||||
DEMON_EventNode *first_demon_event_node;
|
||||
DEMON_EventNode *last_demon_event_node;
|
||||
DEMON_EventNode *free_demon_event_node;
|
||||
CTRL_EntityStore *ctrl_thread_entity_store;
|
||||
Arena *dmn_event_arena;
|
||||
DMN_EventNode *first_dmn_event_node;
|
||||
DMN_EventNode *last_dmn_event_node;
|
||||
DMN_EventNode *free_dmn_event_node;
|
||||
Arena *user_entry_point_arena;
|
||||
String8List user_entry_points;
|
||||
U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64];
|
||||
@@ -443,29 +540,21 @@ struct CTRL_State
|
||||
//~ rjf: Globals
|
||||
|
||||
global CTRL_State *ctrl_state = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Main Layer Initialization
|
||||
|
||||
internal void ctrl_init(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Wakeup Callback Registration
|
||||
|
||||
internal void ctrl_set_wakeup_hook(CTRL_WakeupFunctionType *wakeup_hook);
|
||||
read_only global CTRL_Entity ctrl_entity_nil =
|
||||
{
|
||||
&ctrl_entity_nil,
|
||||
&ctrl_entity_nil,
|
||||
&ctrl_entity_nil,
|
||||
&ctrl_entity_nil,
|
||||
&ctrl_entity_nil,
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Type Functions
|
||||
|
||||
internal U64 ctrl_hash_from_string(String8 string);
|
||||
internal CTRL_EventCause ctrl_event_cause_from_demon_event_kind(DEMON_EventKind event_kind);
|
||||
internal B32 ctrl_handle_match(CTRL_Handle a, CTRL_Handle b);
|
||||
|
||||
////////////////////////////////
|
||||
//~ 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);
|
||||
internal U64 ctrl_hash_from_machine_id_handle(CTRL_MachineID machine_id, DMN_Handle handle);
|
||||
internal CTRL_EventCause ctrl_event_cause_from_dmn_event_kind(DMN_EventKind event_kind);
|
||||
|
||||
////////////////////////////////
|
||||
//~ 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 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
|
||||
@@ -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);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Shared Functions
|
||||
//~ rjf: Entity Type Functions
|
||||
|
||||
//- rjf: run index
|
||||
internal U64 ctrl_run_idx(void);
|
||||
internal U64 ctrl_memgen_idx(void);
|
||||
internal U64 ctrl_reggen_idx(void);
|
||||
//- rjf: cache creation/destruction
|
||||
internal CTRL_EntityStore *ctrl_entity_store_alloc(void);
|
||||
internal void ctrl_entity_store_release(CTRL_EntityStore *store);
|
||||
|
||||
//- rjf: halt everything
|
||||
internal void ctrl_halt(void);
|
||||
//- rjf: string allocation/deletion
|
||||
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
|
||||
internal String8 ctrl_inferred_og_dbg_path_from_exe_path(Arena *arena, String8 exe_path);
|
||||
internal String8 ctrl_forced_og_dbg_path_from_exe_path(Arena *arena, String8 exe_path);
|
||||
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: entity construction/deletion
|
||||
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 void ctrl_entity_release(CTRL_EntityStore *store, CTRL_Entity *entity);
|
||||
|
||||
//- rjf: handle -> arch
|
||||
internal Architecture ctrl_arch_from_handle(CTRL_MachineID machine, CTRL_Handle handle);
|
||||
//- rjf: entity equipment
|
||||
internal void ctrl_entity_equip_string(CTRL_EntityStore *store, CTRL_Entity *entity, String8 string);
|
||||
|
||||
//- rjf: process memory reading/writing
|
||||
internal U64 ctrl_process_read(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, void *dst);
|
||||
internal B32 ctrl_process_write(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, void *src);
|
||||
//- rjf: entity store lookups
|
||||
internal CTRL_Entity *ctrl_entity_from_machine_id_handle(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle handle);
|
||||
|
||||
//- 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
|
||||
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_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, B32 zero_terminated, U64 endt_us);
|
||||
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, DMN_Handle process, Rng1U64 range, B32 zero_terminated, B32 *out_is_stale, U64 endt_us);
|
||||
|
||||
//- 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_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_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, DMN_Handle process, U64 vaddr, U64 limit, U64 endt_us);
|
||||
|
||||
//- rjf: register reading/writing
|
||||
internal void *ctrl_reg_block_from_thread(CTRL_MachineID machine_id, CTRL_Handle thread);
|
||||
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 memory writing
|
||||
internal B32 ctrl_process_write(CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 range, void *src);
|
||||
|
||||
//- 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
|
||||
internal CTRL_Unwind ctrl_unwind_from_process_thread(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, CTRL_Handle thread);
|
||||
//- rjf: thread register cache reading
|
||||
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
|
||||
internal EVAL_String2NumMap *ctrl_string2reg_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 CTRL_MsgList ctrl_u2c_pop_msgs(Arena *arena);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Ctrl -> User Communication
|
||||
|
||||
//- rjf: control -> user thread communication
|
||||
internal void ctrl_c2u_push_events(CTRL_EventList *events);
|
||||
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
|
||||
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
|
||||
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
|
||||
internal B32 ctrl_eval_memory_read(void *u, void *out, U64 addr, U64 size);
|
||||
|
||||
//- rjf: msg kind implementations
|
||||
internal void ctrl_thread__launch_and_handshake(CTRL_Msg *msg);
|
||||
internal void ctrl_thread__launch_and_init(CTRL_Msg *msg);
|
||||
internal void ctrl_thread__attach(CTRL_Msg *msg);
|
||||
internal void ctrl_thread__kill(CTRL_Msg *msg);
|
||||
internal void ctrl_thread__detach(CTRL_Msg *msg);
|
||||
internal void ctrl_thread__run(CTRL_Msg *msg);
|
||||
internal void ctrl_thread__single_step(CTRL_Msg *msg);
|
||||
internal void ctrl_thread__launch_and_handshake(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
|
||||
internal void ctrl_thread__launch_and_init(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
|
||||
internal void ctrl_thread__attach(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
|
||||
internal void ctrl_thread__kill(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
|
||||
internal void ctrl_thread__detach(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
|
||||
internal void ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, 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
|
||||
internal void ctrl_mem_stream_thread__entry_point(void *p);
|
||||
|
||||
#endif //CTRL_CORE_H
|
||||
#endif // CTRL_CORE_H
|
||||
|
||||
+1
-1
@@ -74,4 +74,4 @@
|
||||
|
||||
#include "ctrl_core.h"
|
||||
|
||||
#endif //CTRL_INC_H
|
||||
#endif // CTRL_INC_H
|
||||
|
||||
+8
-6
@@ -179,7 +179,7 @@ dasm_inst_chunk_list_from_arch_addr_data(Arena *arena, U64 *bytes_processed_coun
|
||||
//- rjf: opening handles & correllation with module
|
||||
|
||||
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};
|
||||
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)
|
||||
{
|
||||
if(e->machine_id == machine &&
|
||||
ctrl_handle_match(e->process, process) &&
|
||||
MemoryMatchStruct(&e->vaddr_range, &vaddr_range))
|
||||
dmn_handle_match(e->process, process) &&
|
||||
MemoryMatchStruct(&e->vaddr_range, &vaddr_range) &&
|
||||
e->arch == arch)
|
||||
{
|
||||
entity = e;
|
||||
break;
|
||||
@@ -209,6 +210,7 @@ dasm_handle_from_ctrl_process_range(CTRL_MachineID machine, CTRL_Handle process,
|
||||
entity->machine_id = machine;
|
||||
entity->process = process;
|
||||
entity->vaddr_range= vaddr_range;
|
||||
entity->arch = arch;
|
||||
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_string_arena = arena_alloc__sized(GB(1), KB(64));
|
||||
@@ -389,7 +391,7 @@ dasm_decode_thread_entry_point(void *p)
|
||||
//- rjf: request -> ctrl info
|
||||
B32 is_first_to_task = 0;
|
||||
CTRL_MachineID ctrl_machine_id = 0;
|
||||
CTRL_Handle ctrl_process = {0};
|
||||
DMN_Handle ctrl_process = {0};
|
||||
Rng1U64 vaddr_range = {0};
|
||||
Architecture arch = Architecture_Null;
|
||||
U64 *bytes_processed_counter = 0;
|
||||
@@ -413,7 +415,7 @@ dasm_decode_thread_entry_point(void *p)
|
||||
ctrl_machine_id = entity->machine_id;
|
||||
ctrl_process = entity->process;
|
||||
vaddr_range = entity->vaddr_range;
|
||||
arch = ctrl_arch_from_handle(ctrl_machine_id, ctrl_process);
|
||||
arch = entity->arch;
|
||||
bytes_processed_counter = &entity->bytes_processed;
|
||||
U64 bytes_to_process = dim_1u64(vaddr_range);
|
||||
ins_atomic_u64_eval_assign(&entity->bytes_processed, 0);
|
||||
@@ -465,7 +467,7 @@ dasm_decode_thread_entry_point(void *p)
|
||||
if(good_task)
|
||||
{
|
||||
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)
|
||||
{
|
||||
inst_list = dasm_inst_chunk_list_from_arch_addr_data(scratch.arena, bytes_processed_counter, arch, chunk_vaddr_range.min, data);
|
||||
|
||||
+4
-3
@@ -77,8 +77,9 @@ struct DASM_Entity
|
||||
|
||||
// rjf: key info
|
||||
CTRL_MachineID machine_id;
|
||||
CTRL_Handle process;
|
||||
DMN_Handle process;
|
||||
Rng1U64 vaddr_range;
|
||||
Architecture arch;
|
||||
U64 id;
|
||||
|
||||
// rjf: top-level info
|
||||
@@ -114,7 +115,7 @@ typedef struct DASM_BinaryInfo DASM_BinaryInfo;
|
||||
struct DASM_BinaryInfo
|
||||
{
|
||||
CTRL_MachineID machine_id;
|
||||
CTRL_Handle process;
|
||||
DMN_Handle process;
|
||||
Rng1U64 vaddr_range;
|
||||
U64 bytes_processed;
|
||||
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: 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
|
||||
internal DASM_BinaryInfo dasm_binary_info_from_handle(Arena *arena, DASM_Handle handle);
|
||||
|
||||
@@ -116,3 +116,38 @@ dmn_event_list_push(Arena *arena, DMN_EventList *list)
|
||||
DMN_Event *result = &n->v;
|
||||
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
@@ -4,6 +4,20 @@
|
||||
#ifndef 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
|
||||
|
||||
@@ -54,6 +68,7 @@ struct DMN_Event
|
||||
DMN_Handle process;
|
||||
DMN_Handle thread;
|
||||
DMN_Handle module;
|
||||
Architecture arch;
|
||||
U64 address;
|
||||
U64 size;
|
||||
String8 string;
|
||||
@@ -159,43 +174,62 @@ internal DMN_HandleArray dmn_handle_array_copy(Arena *arena, DMN_HandleArray *sr
|
||||
//- rjf: event list building
|
||||
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)
|
||||
|
||||
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);
|
||||
|
||||
////////////////////////////////
|
||||
//~ 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);
|
||||
internal B32 dmn_attach_process(U32 pid);
|
||||
internal B32 dmn_kill_process(DMN_Handle process, U32 exit_code);
|
||||
internal B32 dmn_detach_process(DMN_Handle process);
|
||||
//- rjf: run/memory/register counters
|
||||
internal U64 dmn_run_gen(void);
|
||||
internal U64 dmn_mem_gen(void);
|
||||
internal U64 dmn_reg_gen(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @dmn_os_hooks Process/Thread Reads/Writes (Implemented Per-OS)
|
||||
//- rjf: non-blocking-control-thread access barriers
|
||||
internal B32 dmn_access_open(void);
|
||||
internal void dmn_access_close(void);
|
||||
#define DMN_AccessScope DeferLoopChecked(dmn_access_open(), dmn_access_close())
|
||||
|
||||
//- rjf: processes
|
||||
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 U64 dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst);
|
||||
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_write_struct(process, vaddr, ptr) dmn_process_write((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr)
|
||||
|
||||
//- rjf: threads
|
||||
internal U64 dmn_stack_base_vaddr_from_thread(DMN_Handle handle);
|
||||
internal U64 dmn_tls_root_vaddr_from_thread(DMN_Handle handle);
|
||||
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)
|
||||
internal Architecture dmn_arch_from_thread(DMN_Handle handle);
|
||||
internal U64 dmn_stack_base_vaddr_from_thread(DMN_Handle handle);
|
||||
internal U64 dmn_tls_root_vaddr_from_thread(DMN_Handle handle);
|
||||
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: system process listing
|
||||
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 void dmn_process_iter_end(DMN_ProcessIter *iter);
|
||||
|
||||
@@ -40,7 +40,7 @@ dmn_w32_entity_from_handle(DMN_Handle handle)
|
||||
{
|
||||
U32 idx = handle.u32[0];
|
||||
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)
|
||||
{
|
||||
entity = &dmn_w32_entity_nil;
|
||||
@@ -141,7 +141,7 @@ dmn_w32_entity_release(DMN_W32_Entity *entity)
|
||||
Task *last_task = &start_task;
|
||||
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);
|
||||
t->e = child;
|
||||
@@ -343,6 +343,7 @@ dmn_w32_process_write(HANDLE process, Rng1U64 range, void *src)
|
||||
ptr += actual_write;
|
||||
cursor += actual_write;
|
||||
}
|
||||
ins_atomic_u64_inc_eval(&dmn_w32_shared->mem_gen);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -581,9 +582,10 @@ dmn_w32_thread_read_reg_block(Architecture arch, HANDLE thread, void *reg_block)
|
||||
//- rjf: unimplemented win32/arch combos
|
||||
//
|
||||
case Architecture_Null:
|
||||
case Architecture_COUNT:
|
||||
{}break;
|
||||
case Architecture_arm64:
|
||||
case Architecture_arm32:
|
||||
case Architecture_COUNT:
|
||||
{NotImplemented;}break;
|
||||
|
||||
////////////////////////////
|
||||
@@ -824,9 +826,10 @@ dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block
|
||||
//- rjf: unimplemented win32/arch combos
|
||||
//
|
||||
case Architecture_Null:
|
||||
case Architecture_COUNT:
|
||||
{}break;
|
||||
case Architecture_arm64:
|
||||
case Architecture_arm32:
|
||||
case Architecture_COUNT:
|
||||
{NotImplemented;}break;
|
||||
|
||||
////////////////////////////
|
||||
@@ -951,6 +954,7 @@ dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block
|
||||
//- rjf: bad context -> abort
|
||||
if(ctx == 0)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1041,6 +1045,7 @@ dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
}
|
||||
ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1068,6 +1073,7 @@ dmn_init(void)
|
||||
Arena *arena = arena_alloc();
|
||||
dmn_w32_shared = push_array(arena, DMN_W32_Shared, 1);
|
||||
dmn_w32_shared->arena = arena;
|
||||
dmn_w32_shared->access_mutex = os_mutex_alloc();
|
||||
dmn_w32_shared->detach_arena = arena_alloc();
|
||||
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);
|
||||
@@ -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
|
||||
dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
|
||||
dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
{
|
||||
DMN_EventList events = {0};
|
||||
dmn_access_open();
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: determine event generation path
|
||||
//
|
||||
typedef enum DMN_W32_EventGenPath
|
||||
{
|
||||
DMN_W32_EventGenPath_NotAttached,
|
||||
DMN_W32_EventGenPath_Run,
|
||||
DMN_W32_EventGenPath_DetachProcesses,
|
||||
}
|
||||
@@ -1124,12 +1315,41 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
|
||||
{
|
||||
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
|
||||
//
|
||||
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
|
||||
//
|
||||
@@ -1148,9 +1368,10 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
|
||||
{
|
||||
//- rjf: unimplemented win32/arch combos
|
||||
case Architecture_Null:
|
||||
case Architecture_COUNT:
|
||||
{}break;
|
||||
case Architecture_arm64:
|
||||
case Architecture_arm32:
|
||||
case Architecture_COUNT:
|
||||
{NotImplemented;}break;
|
||||
|
||||
//- rjf: x86/64
|
||||
@@ -1198,7 +1419,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
|
||||
{
|
||||
//- rjf: scan all processes
|
||||
for(DMN_W32_Entity *process = dmn_w32_shared->entities_base->first;
|
||||
process != 0;
|
||||
process != &dmn_w32_entity_nil;
|
||||
process = process->next)
|
||||
{
|
||||
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
|
||||
for(DMN_W32_Entity *thread = process->first;
|
||||
thread != 0;
|
||||
thread != &dmn_w32_entity_nil;
|
||||
thread = thread->next)
|
||||
{
|
||||
if(thread->kind != DMN_W32_EntityKind_Thread) {continue;}
|
||||
@@ -1345,7 +1566,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
|
||||
DEBUG_EVENT evt = {0};
|
||||
B32 evt_good = 0;
|
||||
{
|
||||
B32 resume_good = 0;
|
||||
B32 resume_good = 1;
|
||||
if(dmn_w32_shared->resume_needed)
|
||||
{
|
||||
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_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->arch = image_info.arch;
|
||||
thread->handle = thread_handle;
|
||||
thread->arch = image_info.arch;
|
||||
thread->thread.thread_local_base = tls_base;
|
||||
module->handle = module_handle;
|
||||
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);
|
||||
e->kind = DMN_EventKind_CreateProcess;
|
||||
e->process = dmn_w32_handle_from_entity(process);
|
||||
e->arch = image_info.arch;
|
||||
e->code = evt.dwProcessId;
|
||||
}
|
||||
|
||||
@@ -1471,6 +1697,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
|
||||
e->kind = DMN_EventKind_CreateThread;
|
||||
e->process = dmn_w32_handle_from_entity(process);
|
||||
e->thread = dmn_w32_handle_from_entity(thread);
|
||||
e->arch = image_info.arch;
|
||||
e->code = evt.dwThreadId;
|
||||
}
|
||||
|
||||
@@ -1480,6 +1707,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
|
||||
e->kind = DMN_EventKind_LoadModule;
|
||||
e->process = dmn_w32_handle_from_entity(process);
|
||||
e->module = dmn_w32_handle_from_entity(module);
|
||||
e->arch = image_info.arch;
|
||||
e->address = module_base;
|
||||
e->size = image_info.size;
|
||||
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);
|
||||
{
|
||||
thread->handle = evt.u.CreateThread.hThread;
|
||||
thread->arch = process->arch;
|
||||
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->process = dmn_w32_handle_from_entity(process);
|
||||
e->thread = dmn_w32_handle_from_entity(thread);
|
||||
e->arch = thread->arch;
|
||||
e->code = evt.dwThreadId;
|
||||
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);
|
||||
{
|
||||
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.address_of_name_pointer = (U64)evt.u.LoadDll.lpImageName;
|
||||
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->process = dmn_w32_handle_from_entity(process);
|
||||
e->module = dmn_w32_handle_from_entity(module);
|
||||
e->arch = module->arch;
|
||||
e->address = module_base;
|
||||
e->size = image_info.size;
|
||||
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);
|
||||
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);
|
||||
}
|
||||
@@ -1980,7 +2212,7 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
|
||||
{
|
||||
if(process->kind != DMN_W32_EntityKind_Process) { continue; }
|
||||
for(DMN_W32_Entity *thread = process->first;
|
||||
thread != 0;
|
||||
thread != &dmn_w32_entity_nil;
|
||||
thread = thread->next)
|
||||
{
|
||||
if(thread->kind != DMN_W32_EntityKind_Thread) { continue; }
|
||||
@@ -2043,9 +2275,10 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
|
||||
{
|
||||
//- rjf: unimplemented win32/arch combos
|
||||
case Architecture_Null:
|
||||
case Architecture_COUNT:
|
||||
{}break;
|
||||
case Architecture_arm64:
|
||||
case Architecture_arm32:
|
||||
case Architecture_COUNT:
|
||||
{NotImplemented;}break;
|
||||
|
||||
//- rjf: x86/64
|
||||
@@ -2120,13 +2353,17 @@ dmn_run(Arena *arena, DMN_RunCtrls *ctrls)
|
||||
}break;
|
||||
}
|
||||
|
||||
dmn_access_close();
|
||||
return events;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @dmn_os_hooks Halting (Implemented Per-OS)
|
||||
|
||||
internal void
|
||||
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;
|
||||
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
|
||||
dmn_launch_process(OS_LaunchOptions *options)
|
||||
//- rjf: run/memory/register counters
|
||||
|
||||
internal U64
|
||||
dmn_run_gen(void)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
U32 result = 0;
|
||||
|
||||
//- rjf: produce exe / arguments string
|
||||
String8 cmd = {0};
|
||||
if(options->cmd_line.first != 0)
|
||||
U64 result = ins_atomic_u64_eval(&dmn_w32_shared->run_gen);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
dmn_mem_gen(void)
|
||||
{
|
||||
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};
|
||||
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);
|
||||
result = 1;
|
||||
}
|
||||
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_attach_process(U32 pid)
|
||||
{
|
||||
B32 result = 0;
|
||||
if(DebugActiveProcess((DWORD)pid))
|
||||
{
|
||||
result = 1;
|
||||
dmn_w32_shared->new_process_pending = 1;
|
||||
os_mutex_take(dmn_w32_shared->access_mutex);
|
||||
result = !dmn_w32_shared->access_run_state;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
dmn_kill_process(DMN_Handle process, U32 exit_code)
|
||||
internal void
|
||||
dmn_access_close(void)
|
||||
{
|
||||
B32 result = 0;
|
||||
DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process);
|
||||
if(TerminateProcess(process_entity->handle, exit_code))
|
||||
if(!dmn_w32_ctrl_thread)
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
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);
|
||||
os_mutex_drop(dmn_w32_shared->access_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @dmn_os_hooks Process/Thread Reads/Writes (Implemented Per-OS)
|
||||
|
||||
//- rjf: processes
|
||||
|
||||
internal U64
|
||||
dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst)
|
||||
{
|
||||
DMN_W32_Entity *entity = dmn_w32_entity_from_handle(process);
|
||||
U64 result = dmn_w32_process_read(entity->handle, range, dst);
|
||||
U64 result = 0;
|
||||
DMN_AccessScope
|
||||
{
|
||||
DMN_W32_Entity *entity = dmn_w32_entity_from_handle(process);
|
||||
result = dmn_w32_process_read(entity->handle, range, dst);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
dmn_process_write(DMN_Handle process, Rng1U64 range, void *src)
|
||||
{
|
||||
DMN_W32_Entity *entity = dmn_w32_entity_from_handle(process);
|
||||
B32 result = dmn_w32_process_write(entity->handle, range, src);
|
||||
B32 result = 0;
|
||||
DMN_AccessScope
|
||||
{
|
||||
DMN_W32_Entity *entity = dmn_w32_entity_from_handle(process);
|
||||
result = dmn_w32_process_write(entity->handle, range, src);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//- 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
|
||||
dmn_stack_base_vaddr_from_thread(DMN_Handle handle)
|
||||
{
|
||||
U64 result = 0;
|
||||
DMN_W32_Entity *thread = dmn_w32_entity_from_handle(handle);
|
||||
if(thread->kind == DMN_W32_EntityKind_Thread)
|
||||
DMN_AccessScope
|
||||
{
|
||||
DMN_W32_Entity *process = thread->parent;
|
||||
U64 tlb = thread->thread.thread_local_base;
|
||||
U64 result = 0;
|
||||
switch(thread->arch)
|
||||
DMN_W32_Entity *thread = dmn_w32_entity_from_handle(handle);
|
||||
if(thread->kind == DMN_W32_EntityKind_Thread)
|
||||
{
|
||||
case Architecture_Null:
|
||||
case Architecture_arm64:
|
||||
case Architecture_arm32:
|
||||
case Architecture_COUNT:
|
||||
{NotImplemented;}break;
|
||||
case Architecture_x64:
|
||||
DMN_W32_Entity *process = thread->parent;
|
||||
U64 tlb = thread->thread.thread_local_base;
|
||||
switch(thread->arch)
|
||||
{
|
||||
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;
|
||||
case Architecture_Null:
|
||||
case Architecture_COUNT:
|
||||
{}break;
|
||||
case Architecture_arm64:
|
||||
case Architecture_arm32:
|
||||
{NotImplemented;}break;
|
||||
case Architecture_x64:
|
||||
{
|
||||
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;
|
||||
@@ -2360,10 +2519,30 @@ internal U64
|
||||
dmn_tls_root_vaddr_from_thread(DMN_Handle handle)
|
||||
{
|
||||
U64 result = 0;
|
||||
DMN_W32_Entity *entity = dmn_w32_entity_from_handle(handle);
|
||||
if(entity->kind == DMN_W32_EntityKind_Thread)
|
||||
DMN_AccessScope
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -2371,21 +2550,28 @@ dmn_tls_root_vaddr_from_thread(DMN_Handle handle)
|
||||
internal B32
|
||||
dmn_thread_read_reg_block(DMN_Handle handle, void *reg_block)
|
||||
{
|
||||
DMN_W32_Entity *thread = dmn_w32_entity_from_handle(handle);
|
||||
B32 result = dmn_w32_thread_read_reg_block(thread->arch, thread->handle, reg_block);
|
||||
B32 result = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
internal B32
|
||||
dmn_thread_write_reg_block(DMN_Handle handle, void *reg_block)
|
||||
{
|
||||
DMN_W32_Entity *thread = dmn_w32_entity_from_handle(handle);
|
||||
B32 result = dmn_w32_thread_write_reg_block(thread->arch, thread->handle, reg_block);
|
||||
B32 result = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @dmn_os_hooks System Process Listing (Implemented Per-OS)
|
||||
//- rjf: system process listing
|
||||
|
||||
internal void
|
||||
dmn_process_iter_begin(DMN_ProcessIter *iter)
|
||||
|
||||
@@ -194,6 +194,15 @@ struct DMN_W32_Shared
|
||||
Arena *arena;
|
||||
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
|
||||
Arena *detach_arena;
|
||||
DMN_HandleList detach_processes;
|
||||
@@ -227,6 +236,7 @@ struct DMN_W32_Shared
|
||||
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_GetThreadDescriptionFunctionType *dmn_w32_GetThreadDescription = 0;
|
||||
thread_static B32 dmn_w32_ctrl_thread = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Helpers
|
||||
|
||||
+247
-248
@@ -1404,7 +1404,7 @@ internal DASM_Handle
|
||||
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));
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -2025,7 +2025,7 @@ 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)
|
||||
df_entity_equip_ctrl_handle(DF_Entity *entity, DMN_Handle handle)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->ctrl_handle = handle;
|
||||
@@ -2419,7 +2419,7 @@ 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)
|
||||
df_entity_from_ctrl_handle(CTRL_MachineID machine_id, DMN_Handle handle)
|
||||
{
|
||||
DF_Entity *result = &df_g_nil_entity;
|
||||
if(handle.u64[0] != 0)
|
||||
@@ -2520,11 +2520,13 @@ df_set_thread_freeze_state(DF_Entity *thread, B32 frozen)
|
||||
}
|
||||
node->handle = thread_handle;
|
||||
df_handle_list_push_node(&df_state->frozen_threads, node);
|
||||
df_state->entities_mut_soft_halt = 1;
|
||||
}
|
||||
|
||||
// rjf: frozen => not 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);
|
||||
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
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
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;
|
||||
scratch_end(scratch);
|
||||
}
|
||||
ProfEnd();
|
||||
return result;
|
||||
@@ -2824,14 +2824,14 @@ df_trap_net_from_thread__step_over_inst(Arena *arena, DF_Entity *thread)
|
||||
// rjf: thread => unpacked info
|
||||
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
|
||||
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
|
||||
String8 machine_code = {0};
|
||||
{
|
||||
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));
|
||||
machine_code.size = ctrl_process_read(process->ctrl_machine_id, process->ctrl_handle, rng, machine_code.str);
|
||||
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 = machine_code_slice.data;
|
||||
}
|
||||
|
||||
// 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 *binary = df_binary_file_from_module(module);
|
||||
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
|
||||
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};
|
||||
if(good_line_info)
|
||||
{
|
||||
machine_code.str = push_array_no_zero(scratch.arena, U8, dim_1u64(line_vaddr_rng));
|
||||
machine_code.size = ctrl_process_read(process->ctrl_machine_id, process->ctrl_handle, line_vaddr_rng, machine_code.str);
|
||||
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 = machine_code_slice.data;
|
||||
}
|
||||
|
||||
// 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 *binary = df_binary_file_from_module(module);
|
||||
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
|
||||
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};
|
||||
if(good_line_info)
|
||||
{
|
||||
machine_code.str = push_array_no_zero(scratch.arena, U8, dim_1u64(line_vaddr_rng));
|
||||
machine_code.size = ctrl_process_read(process->ctrl_machine_id, process->ctrl_handle, line_vaddr_rng, machine_code.str);
|
||||
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 = machine_code_slice.data;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
DBGI_Scope *scope = dbgi_scope_open();
|
||||
|
||||
//- 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;
|
||||
if(!df_ctrl_targets_running())
|
||||
{
|
||||
U64 bytes_read = ctrl_process_read(process->ctrl_machine_id, process->ctrl_handle, tls_vaddr_range, &tls_index);
|
||||
if(bytes_read < sizeof(U64))
|
||||
{
|
||||
tls_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//- 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.
|
||||
//- 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;
|
||||
|
||||
U64 dtv_addr = UINT64_MAX;
|
||||
demon_read_memory(process->demon_handle, &dtv_addr, thread_info_addr, addr_size);
|
||||
//- rjf: grab tls range
|
||||
Rng1U64 tls_vaddr_range = pe_tls_rng_from_bin_base_vaddr(bin_data, bin, df_base_vaddr_from_module(module));
|
||||
|
||||
/*
|
||||
union delta_thread_vector
|
||||
//- rjf: read module's TLS index
|
||||
U64 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)
|
||||
{
|
||||
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);
|
||||
tls_index = *(U64 *)tls_index_slice.data.str;
|
||||
}
|
||||
}
|
||||
|
||||
//- 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);
|
||||
scratch_end(scratch);
|
||||
ProfEnd();
|
||||
@@ -3654,43 +3634,6 @@ df_architecture_from_entity(DF_Entity *entity)
|
||||
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 *
|
||||
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
|
||||
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
|
||||
if(result)
|
||||
{
|
||||
DF_RunUnwindCache *unwind_cache = &df_state->unwind_cache;
|
||||
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->table_size;
|
||||
DF_RunUnwindCacheSlot *slot = &unwind_cache->table[slot_idx];
|
||||
for(DF_RunUnwindCacheNode *n = slot->first; n != 0; n = n->hash_next)
|
||||
DF_RunUnwindCache *unwind_cache = &df_state->unwind_caches[df_state->unwind_cache_gen%ArrayCount(df_state->unwind_caches)];
|
||||
if(unwind_cache->slots_count != 0)
|
||||
{
|
||||
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;
|
||||
break;
|
||||
if(df_handle_match(n->thread, thread_handle) && n->unwind.first != 0)
|
||||
{
|
||||
n->unwind.first->rip = vaddr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -4134,7 +4084,7 @@ df_eval_from_string(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_
|
||||
|
||||
//- rjf: unpack arguments
|
||||
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;
|
||||
U64 unwind_count = ctrl_ctx->unwind_count;
|
||||
CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread);
|
||||
@@ -6188,37 +6138,57 @@ df_push_active_target_list(Arena *arena)
|
||||
internal CTRL_Unwind
|
||||
df_query_cached_unwind_from_thread(DF_Entity *thread)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
CTRL_Unwind result = {0};
|
||||
DF_RunUnwindCache *cache = &df_state->unwind_cache;
|
||||
if(cache->table_size != 0)
|
||||
DF_Handle handle = df_handle_from_entity(thread);
|
||||
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);
|
||||
U64 hash = df_hash_from_string(str8_struct(&handle));
|
||||
U64 slot_idx = hash % cache->table_size;
|
||||
DF_RunUnwindCacheSlot *slot = &cache->table[slot_idx];
|
||||
DF_RunUnwindCache *cache = &df_state->unwind_caches[(df_state->unwind_cache_gen+cache_idx)%ArrayCount(df_state->unwind_caches)];
|
||||
if(cache_idx == 0 && cache->slots_count == 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
ProfEnd();
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
df_query_cached_rip_from_thread(DF_Entity *thread)
|
||||
{
|
||||
U64 result = 0;
|
||||
CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread);
|
||||
if(unwind.first != 0)
|
||||
{
|
||||
result = unwind.first->rip;
|
||||
}
|
||||
U64 result = df_query_cached_rip_from_thread_unwind(thread, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -6226,14 +6196,21 @@ internal U64
|
||||
df_query_cached_rip_from_thread_unwind(DF_Entity *thread, U64 unwind_count)
|
||||
{
|
||||
U64 result = 0;
|
||||
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)
|
||||
if(unwind_count == 0)
|
||||
{
|
||||
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;
|
||||
break;
|
||||
if(unwind_idx == unwind_count)
|
||||
{
|
||||
result = frame->rip;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
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;
|
||||
if(cache->slots_count == 0)
|
||||
DF_RunTLSBaseCache *cache = &df_state->tls_base_caches[(df_state->tls_base_cache_gen+cache_idx)%ArrayCount(df_state->tls_base_caches)];
|
||||
if(cache_idx == 0 && cache->slots_count == 0)
|
||||
{
|
||||
cache->slots_count = 256;
|
||||
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);
|
||||
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;
|
||||
@@ -6265,14 +6247,22 @@ df_query_cached_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 roo
|
||||
}
|
||||
if(node == 0)
|
||||
{
|
||||
node = push_array(cache->arena, DF_RunTLSBaseCacheNode, 1);
|
||||
SLLQueuePush_N(slot->first, slot->last, node, hash_next);
|
||||
node->process = handle;
|
||||
node->root_vaddr = root_vaddr;
|
||||
node->rip_vaddr = rip_vaddr;
|
||||
node->tls_base_vaddr = df_tls_base_vaddr_from_process_root_rip(process, root_vaddr, rip_vaddr);
|
||||
U64 tls_base_vaddr = df_tls_base_vaddr_from_process_root_rip(process, root_vaddr, rip_vaddr);
|
||||
if(tls_base_vaddr != 0)
|
||||
{
|
||||
node = push_array(cache->arena, DF_RunTLSBaseCacheNode, 1);
|
||||
SLLQueuePush_N(slot->first, slot->last, node, hash_next);
|
||||
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;
|
||||
}
|
||||
@@ -6282,13 +6272,18 @@ df_query_cached_locals_map_from_binary_voff(DF_Entity *binary, U64 voff)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
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;
|
||||
if(cache->table_size == 0)
|
||||
DF_RunLocalsCache *cache = &df_state->locals_caches[(df_state->locals_cache_gen+cache_idx)%ArrayCount(df_state->locals_caches)];
|
||||
if(cache_idx == 0 && cache->table_size == 0)
|
||||
{
|
||||
cache->table_size = 256;
|
||||
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);
|
||||
U64 hash = df_hash_from_string(str8_struct(&handle));
|
||||
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);
|
||||
}
|
||||
if(node != 0)
|
||||
if(node != 0 && node->locals_map->slots_count != 0)
|
||||
{
|
||||
map = node->locals_map;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ProfEnd();
|
||||
@@ -6330,13 +6326,18 @@ df_query_cached_member_map_from_binary_voff(DF_Entity *binary, U64 voff)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
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;
|
||||
if(cache->table_size == 0)
|
||||
DF_RunLocalsCache *cache = &df_state->member_caches[(df_state->member_cache_gen+cache_idx)%ArrayCount(df_state->member_caches)];
|
||||
if(cache_idx == 0 && cache->table_size == 0)
|
||||
{
|
||||
cache->table_size = 256;
|
||||
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);
|
||||
U64 hash = df_hash_from_string(str8_struct(&handle));
|
||||
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);
|
||||
}
|
||||
if(node != 0)
|
||||
if(node != 0 && node->locals_map->slots_count != 0)
|
||||
{
|
||||
map = node->locals_map;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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_count = 0;
|
||||
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->entities_root = df_entity_alloc(0, &df_g_nil_entity, DF_EntityKind_Root);
|
||||
df_state->cmd_spec_table_size = 1024;
|
||||
@@ -6417,7 +6420,7 @@ df_core_init(CmdLine *cmdln, DF_StateDeltaHistory *hist)
|
||||
// rjf: set up initial entities
|
||||
{
|
||||
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"));
|
||||
}
|
||||
|
||||
@@ -6434,10 +6437,22 @@ df_core_init(CmdLine *cmdln, DF_StateDeltaHistory *hist)
|
||||
}
|
||||
|
||||
// rjf: set up per-run caches
|
||||
df_state->unwind_cache.arena = arena_alloc();
|
||||
df_state->tls_base_cache.arena = arena_alloc();
|
||||
df_state->locals_cache.arena = arena_alloc();
|
||||
df_state->member_cache.arena = arena_alloc();
|
||||
for(U64 idx = 0; idx < ArrayCount(df_state->unwind_caches); idx += 1)
|
||||
{
|
||||
df_state->unwind_caches[idx].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
|
||||
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);
|
||||
|
||||
//- rjf: grab next reggen/memgen
|
||||
U64 new_memgen_idx = ctrl_memgen_idx();
|
||||
U64 new_reggen_idx = ctrl_reggen_idx();
|
||||
U64 new_mem_gen = ctrl_mem_gen();
|
||||
U64 new_reg_gen = ctrl_reg_gen();
|
||||
|
||||
//- rjf: consume & process events
|
||||
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)
|
||||
{
|
||||
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
|
||||
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 *module = df_module_from_process_vaddr(process, stop_thread_vaddr);
|
||||
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);
|
||||
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);
|
||||
@@ -6903,72 +6919,55 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: refresh unwind cache
|
||||
if((df_state->unwind_cache_memgen_idx != new_memgen_idx ||
|
||||
df_state->unwind_cache_reggen_idx != new_reggen_idx) &&
|
||||
//- rjf: clear unwind cache
|
||||
if((df_state->unwind_cache_memgen_idx != new_mem_gen ||
|
||||
df_state->unwind_cache_reggen_idx != new_reg_gen) &&
|
||||
!df_ctrl_targets_running()) ProfScope("per-thread unwind gather")
|
||||
{
|
||||
B32 good = 1;
|
||||
DF_EntityList all_threads = df_query_cached_entity_list_with_kind(DF_EntityKind_Thread);
|
||||
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;
|
||||
df_state->unwind_cache_gen += 1;
|
||||
DF_RunUnwindCache *cache = &df_state->unwind_caches[df_state->unwind_cache_gen%ArrayCount(df_state->unwind_caches)];
|
||||
arena_clear(cache->arena);
|
||||
cache->slots_count = 0;
|
||||
cache->slots = 0;
|
||||
df_state->tls_base_cache_reggen_idx = new_reggen_idx;
|
||||
df_state->tls_base_cache_memgen_idx = new_memgen_idx;
|
||||
df_state->unwind_cache_memgen_idx = new_mem_gen;
|
||||
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
|
||||
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);
|
||||
cache->table_size = 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
|
||||
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);
|
||||
cache->table_size = 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);
|
||||
@@ -7515,7 +7514,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
|
||||
}break;
|
||||
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();
|
||||
params.entity = df_handle_from_entity(df_machine_entity_from_machine_id(machine_id));
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity);
|
||||
@@ -7523,7 +7522,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
|
||||
}break;
|
||||
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();
|
||||
params.entity = df_handle_from_entity(df_machine_entity_from_machine_id(machine_id));
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity);
|
||||
|
||||
+14
-14
@@ -447,7 +447,7 @@ struct DF_Entity
|
||||
|
||||
// rjf: ctrl entity equipment
|
||||
CTRL_MachineID ctrl_machine_id;
|
||||
CTRL_Handle ctrl_handle;
|
||||
DMN_Handle ctrl_handle;
|
||||
Architecture arch;
|
||||
U32 ctrl_id;
|
||||
U64 stack_base;
|
||||
@@ -940,7 +940,6 @@ struct DF_RunUnwindCacheNode
|
||||
DF_RunUnwindCacheNode *hash_next;
|
||||
DF_Handle thread;
|
||||
CTRL_Unwind unwind;
|
||||
U64 tls_base_vaddr;
|
||||
};
|
||||
|
||||
typedef struct DF_RunUnwindCacheSlot DF_RunUnwindCacheSlot;
|
||||
@@ -954,8 +953,8 @@ typedef struct DF_RunUnwindCache DF_RunUnwindCache;
|
||||
struct DF_RunUnwindCache
|
||||
{
|
||||
Arena *arena;
|
||||
U64 table_size;
|
||||
DF_RunUnwindCacheSlot *table;
|
||||
U64 slots_count;
|
||||
DF_RunUnwindCacheSlot *slots;
|
||||
};
|
||||
|
||||
//- rjf: per-run tls-base-vaddr cache
|
||||
@@ -1136,14 +1135,18 @@ struct DF_State
|
||||
// rjf: per-run caches
|
||||
U64 unwind_cache_reggen_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_memgen_idx;
|
||||
DF_RunTLSBaseCache tls_base_cache;
|
||||
DF_RunTLSBaseCache tls_base_caches[2];
|
||||
U64 tls_base_cache_gen;
|
||||
U64 locals_cache_reggen_idx;
|
||||
DF_RunLocalsCache locals_cache;
|
||||
DF_RunLocalsCache locals_caches[2];
|
||||
U64 locals_cache_gen;
|
||||
U64 member_cache_reggen_idx;
|
||||
DF_RunLocalsCache member_cache;
|
||||
DF_RunLocalsCache member_caches[2];
|
||||
U64 member_cache_gen;
|
||||
|
||||
// rjf: eval view cache
|
||||
DF_EvalViewCache eval_view_cache;
|
||||
@@ -1179,6 +1182,7 @@ struct DF_State
|
||||
B32 ctrl_solo_stepping_mode;
|
||||
|
||||
// rjf: control thread ctrl -> user reading state
|
||||
CTRL_EntityStore *ctrl_entity_store;
|
||||
Arena *ctrl_stop_arena;
|
||||
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
|
||||
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_ctrl_id(DF_Entity *entity, U32 id);
|
||||
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_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_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_name_and_kind(String8 string, 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
|
||||
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
|
||||
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 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 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_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);
|
||||
|
||||
+3
-3
@@ -2131,7 +2131,7 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D
|
||||
if(thread->kind == DF_EntityKind_Thread)
|
||||
{
|
||||
// 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
|
||||
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;
|
||||
}
|
||||
ui_labelf("Target Hz: %.2f", 1.f/df_dt());
|
||||
ui_labelf("Ctrl Run Index: %I64u", ctrl_run_idx());
|
||||
ui_labelf("Ctrl Mem Gen Index: %I64u", ctrl_memgen_idx());
|
||||
ui_labelf("Ctrl Run Index: %I64u", ctrl_run_gen());
|
||||
ui_labelf("Ctrl Mem Gen Index: %I64u", ctrl_mem_gen());
|
||||
ui_labelf("Window %p", window);
|
||||
ui_set_next_pref_width(ui_children_sum(1));
|
||||
ui_set_next_pref_height(ui_children_sum(1));
|
||||
|
||||
@@ -565,7 +565,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(rgba)
|
||||
Vec4F32 rgba = {0};
|
||||
Vec4F32 hsva = {0};
|
||||
{
|
||||
if(state->memgen_idx >= ctrl_memgen_idx())
|
||||
if(state->memgen_idx >= ctrl_mem_gen())
|
||||
{
|
||||
hsva = state->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);
|
||||
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->memgen_idx = ctrl_memgen_idx();
|
||||
state->memgen_idx = ctrl_mem_gen();
|
||||
}
|
||||
}
|
||||
Vec4F32 initial_hsva = hsva;
|
||||
@@ -624,7 +624,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(rgba)
|
||||
{
|
||||
Vec4F32 rgba = rgba_from_hsva(hsva);
|
||||
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
|
||||
@@ -700,7 +700,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text)
|
||||
}
|
||||
|
||||
//- 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
|
||||
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
|
||||
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
|
||||
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
|
||||
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 vertex_buffer_hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vertex_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, 0);
|
||||
|
||||
//- rjf: get gpu buffers
|
||||
R_Handle index_buffer = geo_buffer_from_key_hash(geo_scope, index_buffer_key, index_buffer_hash);
|
||||
|
||||
+13
-8
@@ -240,9 +240,9 @@ df_process_info_list_from_query(Arena *arena, String8 query)
|
||||
//- rjf: build list
|
||||
DF_ProcessInfoList list = {0};
|
||||
{
|
||||
DEMON_ProcessIter iter = {0};
|
||||
demon_proc_iter_begin(&iter);
|
||||
for(DEMON_ProcessInfo info = {0}; demon_proc_iter_next(scratch.arena, &iter, &info);)
|
||||
DMN_ProcessIter iter = {0};
|
||||
dmn_process_iter_begin(&iter);
|
||||
for(DMN_ProcessInfo info = {0}; dmn_process_iter_next(scratch.arena, &iter, &info);)
|
||||
{
|
||||
// rjf: skip root-level or otherwise 0-pid processes
|
||||
if(info.pid == 0)
|
||||
@@ -290,7 +290,7 @@ df_process_info_list_from_query(Arena *arena, String8 query)
|
||||
list.count += 1;
|
||||
}
|
||||
}
|
||||
demon_proc_iter_end(&iter);
|
||||
dmn_process_iter_end(&iter);
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
@@ -6235,6 +6235,7 @@ DF_VIEW_UI_FUNCTION_DEF(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_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
|
||||
ProfScope("find breakpoints mapping to this disassembly")
|
||||
{
|
||||
DF_EntityList bps = df_query_cached_entity_list_with_kind(DF_EntityKind_Breakpoint);
|
||||
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
|
||||
ProfScope("find watch pins mapping to this disassembly")
|
||||
{
|
||||
DF_EntityList pins = df_query_cached_entity_list_with_kind(DF_EntityKind_WatchPin);
|
||||
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)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
HS_Scope *hs_scope = hs_scope_open();
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: unpack state
|
||||
@@ -7755,7 +7759,7 @@ DF_VIEW_UI_FUNCTION_DEF(Memory)
|
||||
U8 *visible_memory = 0;
|
||||
{
|
||||
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 ||
|
||||
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);
|
||||
@@ -7766,8 +7770,8 @@ DF_VIEW_UI_FUNCTION_DEF(Memory)
|
||||
// rjf: try to read new memory for this range
|
||||
U64 bytes_to_read = dim_1u64(chunk_aligned_range_bytes);
|
||||
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 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 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 = 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
|
||||
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);
|
||||
ProfEnd();
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ struct DF_EntityListerItemArray
|
||||
typedef struct DF_ProcessInfo DF_ProcessInfo;
|
||||
struct DF_ProcessInfo
|
||||
{
|
||||
DEMON_ProcessInfo info;
|
||||
DMN_ProcessInfo info;
|
||||
B32 is_attached;
|
||||
FuzzyMatchRangeList attached_match_ranges;
|
||||
FuzzyMatchRangeList name_match_ranges;
|
||||
|
||||
@@ -372,7 +372,7 @@ mg_str_expr_parse_from_first_opl__min_prec(Arena *arena, MD_Node *first, MD_Node
|
||||
|
||||
//- rjf: consume prefix operators
|
||||
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;
|
||||
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
|
||||
for(;it < opl && !md_node_is_nil(it);)
|
||||
for(;it != opl && !md_node_is_nil(it);)
|
||||
{
|
||||
// rjf: find binary op kind of `it`
|
||||
MG_StrExprOp found_op = MG_StrExprOp_Null;
|
||||
|
||||
+9
-6
@@ -1,13 +1,18 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// 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
|
||||
//
|
||||
// [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
|
||||
// [ ] better discoverability for view rules - have better help hover tooltip,
|
||||
// info on arguments, and better autocomplete lister
|
||||
@@ -79,8 +84,6 @@
|
||||
// [ ] disasm animation & go-to-address
|
||||
//
|
||||
// [ ] 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)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#define BUILD_VERSION_MAJOR 0
|
||||
#define BUILD_VERSION_MINOR 9
|
||||
#define BUILD_VERSION_PATCH 8
|
||||
#define BUILD_VERSION_PATCH 9
|
||||
#define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA"
|
||||
#define BUILD_TITLE "The RAD Debugger"
|
||||
#define OS_FEATURE_GRAPHICAL 1
|
||||
@@ -43,7 +43,7 @@
|
||||
#include "regs/raddbgi/regs_raddbgi.h"
|
||||
#include "type_graph/type_graph.h"
|
||||
#include "dbgi/dbgi.h"
|
||||
#include "demon/demon_inc.h"
|
||||
#include "demon2/demon2_inc.h"
|
||||
#include "eval/eval_inc.h"
|
||||
#include "unwind/unwind.h"
|
||||
#include "ctrl/ctrl_inc.h"
|
||||
@@ -81,7 +81,7 @@
|
||||
#include "regs/raddbgi/regs_raddbgi.c"
|
||||
#include "type_graph/type_graph.c"
|
||||
#include "dbgi/dbgi.c"
|
||||
#include "demon/demon_inc.c"
|
||||
#include "demon2/demon2_inc.c"
|
||||
#include "eval/eval_inc.c"
|
||||
#include "unwind/unwind.c"
|
||||
#include "ctrl/ctrl_inc.c"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
internal U64 regs_block_size_from_architecture(Architecture arch)
|
||||
{
|
||||
U64 result = 0;
|
||||
U64 result = 8;
|
||||
switch(arch)
|
||||
{
|
||||
default:{}break;
|
||||
|
||||
+1
-1
@@ -421,7 +421,7 @@ regs_g_reg_code_x86_usage_kind_table:
|
||||
{
|
||||
`internal U64 regs_block_size_from_architecture(Architecture arch)`;
|
||||
`{`;
|
||||
`U64 result = 0;`;
|
||||
`U64 result = 8;`;
|
||||
`switch(arch)`;
|
||||
`{`;
|
||||
`default:{}break;`;
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
#include "demon2/demon2_inc.h"
|
||||
#include "eval/eval_inc.h"
|
||||
#include "unwind/unwind.h"
|
||||
#include "ctrl2/ctrl2_inc.h"
|
||||
#include "ctrl/ctrl_inc.h"
|
||||
|
||||
//- rjf: [c]
|
||||
#include "base/base_inc.c"
|
||||
@@ -74,7 +74,7 @@
|
||||
#include "demon2/demon2_inc.c"
|
||||
#include "eval/eval_inc.c"
|
||||
#include "unwind/unwind.c"
|
||||
#include "ctrl2/ctrl2_inc.c"
|
||||
#include "ctrl/ctrl_inc.c"
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entry Point
|
||||
|
||||
+2
-1
@@ -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
|
||||
//
|
||||
{
|
||||
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) &&
|
||||
(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)) &&
|
||||
|
||||
Reference in New Issue
Block a user