WIP improved signal handling in multi-threaded programs

This commit is contained in:
Nikita Smith
2025-11-19 11:38:22 -08:00
parent 597ea44337
commit b7fb4fe04d
4 changed files with 1472 additions and 1393 deletions
+12
View File
@@ -206,3 +206,15 @@ dmn_process_read_raw(Arena *arena, DMN_Handle process, Rng1U64 vrange)
} }
return buffer; return buffer;
} }
internal String8
dmn_get_trap_inst(void)
{
#if ARCH_X64
local_persist U8 inst[] = { 0xcc };
#else
# error "trap instruction is not defined for this arch"
#endif
return str8_array_fixed(inst);
}
+4 -1
View File
@@ -142,7 +142,7 @@ typedef struct DMN_ActiveTrap DMN_ActiveTrap;
struct DMN_ActiveTrap struct DMN_ActiveTrap
{ {
DMN_Trap *trap; DMN_Trap *trap;
U8 swap_byte; String8 swap_bytes;
DMN_ActiveTrap *next; DMN_ActiveTrap *next;
}; };
@@ -262,4 +262,7 @@ internal void dmn_process_iter_begin(DMN_ProcessIter *iter);
internal B32 dmn_process_iter_next(Arena *arena, DMN_ProcessIter *iter, DMN_ProcessInfo *info_out); internal B32 dmn_process_iter_next(Arena *arena, DMN_ProcessIter *iter, DMN_ProcessInfo *info_out);
internal void dmn_process_iter_end(DMN_ProcessIter *iter); internal void dmn_process_iter_end(DMN_ProcessIter *iter);
//- arch trap
internal String8 dmn_get_trap_inst(void);
#endif // DEMON_CORE_H #endif // DEMON_CORE_H
File diff suppressed because it is too large Load Diff
+100 -59
View File
@@ -11,19 +11,6 @@
#include <sys/uio.h> #include <sys/uio.h>
#include <elf.h> #include <elf.h>
////////////////////////////////
//~ SIGTRAP codes
enum
{
DMN_LNX_SigTrapCode_Brkpt = 1,
DMN_LNX_SigTrapCode_Trace = 2,
DMN_LNX_SigTrapCode_Branch = 3,
DMN_LNX_SigTrapCode_HwBkpt = 4,
DMN_LNX_SigTrapCode_Unk = 5,
DMN_LNX_SigTrapCode_Perf = 6
} DMN_LNX_SigTrapCode;
//////////////////////////////// ////////////////////////////////
//~ rjf: Register Layouts //~ rjf: Register Layouts
// //
@@ -143,7 +130,7 @@ typedef struct DMN_LNX_PhdrInfo DMN_LNX_PhdrInfo;
struct DMN_LNX_PhdrInfo struct DMN_LNX_PhdrInfo
{ {
Rng1U64 range; Rng1U64 range;
U64 dynamic; U64 dynamic;
}; };
typedef struct DMN_LNX_DynamicInfo DMN_LNX_DynamicInfo; typedef struct DMN_LNX_DynamicInfo DMN_LNX_DynamicInfo;
@@ -171,39 +158,60 @@ typedef enum DMN_LNX_EntityKind
} }
DMN_LNX_EntityKind; DMN_LNX_EntityKind;
typedef enum DMN_LNX_ThreadState
{
DMN_LNX_ThreadState_Null,
DMN_LNX_ThreadState_Running,
DMN_LNX_ThreadState_Stopped,
DMN_LNX_ThreadState_Exited,
DMN_LNX_ThreadState_WaitForVFrok,
} DMN_LNX_ThreadState;
typedef struct DMN_LNX_Entity DMN_LNX_Entity; typedef struct DMN_LNX_Entity DMN_LNX_Entity;
struct DMN_LNX_Entity struct DMN_LNX_Entity
{ {
// entity hierarchy
DMN_LNX_Entity *first; DMN_LNX_Entity *first;
DMN_LNX_Entity *last; DMN_LNX_Entity *last;
DMN_LNX_Entity *next; DMN_LNX_Entity *next;
DMN_LNX_Entity *prev; DMN_LNX_Entity *prev;
DMN_LNX_Entity *parent; DMN_LNX_Entity *parent;
// common
DMN_LNX_EntityKind kind; DMN_LNX_EntityKind kind;
U32 gen; U32 gen;
Arch arch; Arch arch;
U64 id; U64 id;
// process // process
Arena *arena; Arena *arena;
int fd; int fd;
pid_t tracer_tid; pid_t tracer_tid;
B32 expect_rdebug_data_breakpoint; B32 debug_subprocesses;
U64 rdebug_vaddr; B32 expect_user_interrupt;
U64 rdebug_brk_vaddr; B32 expect_rdebug_data_breakpoint;
ELF_Class dl_class; U64 rdebug_vaddr;
HashTable *loaded_modules_ht; U64 rdebug_brk_vaddr;
ELF_Class dl_class;
HashTable *loaded_modules_ht;
DMN_LNX_Probe **probes; DMN_LNX_Probe **probes;
U64 probe_vaddrs[DMN_LNX_ProbeType_Count]; U64 probe_vaddrs[DMN_LNX_ProbeType_Count];
U64 main_thread_exit_code;
U64 thread_count;
// process x64 // process x64
U64 xcr0; U64 xcr0;
U64 xsave_size; U64 xsave_size;
X64_XSaveLayout xsave_layout; X64_XSaveLayout xsave_layout;
// thread // thread
B32 expecting_dummy_sigstop; void *reg_block;
void *reg_block; B32 expecting_dummy_sigstop;
B32 is_main_thread;
B32 is_reg_block_dirty;
B32 pass_through_signal;
U64 pass_through_signo;
DMN_LNX_ThreadState thread_state;
// module // module
U64 base_vaddr; U64 base_vaddr;
@@ -217,13 +225,13 @@ typedef struct DMN_LNX_EntityNode DMN_LNX_EntityNode;
struct DMN_LNX_EntityNode struct DMN_LNX_EntityNode
{ {
DMN_LNX_EntityNode *next; DMN_LNX_EntityNode *next;
DMN_LNX_Entity *v; DMN_LNX_Entity *v;
}; };
typedef struct DMN_LNX_EntityList DMN_LNX_EntityList; typedef struct DMN_LNX_EntityList DMN_LNX_EntityList;
struct DMN_LNX_EntityList struct DMN_LNX_EntityList
{ {
U64 count; U64 count;
DMN_LNX_EntityNode *first; DMN_LNX_EntityNode *first;
DMN_LNX_EntityNode *last; DMN_LNX_EntityNode *last;
}; };
@@ -231,38 +239,69 @@ struct DMN_LNX_EntityList
//////////////////////////////// ////////////////////////////////
//~ rjf: Main State Bundle //~ rjf: Main State Bundle
typedef struct DMN_LNX_ProcessLaunch DMN_LNX_ProcessLaunch;
struct DMN_LNX_ProcessLaunch
{
B32 debug_subprocesses;
pid_t pid;
DMN_LNX_ProcessLaunch *next;
DMN_LNX_ProcessLaunch *prev;
};
typedef struct DMN_LNX_ProcessLaunchList DMN_LNX_ProcessLaunchList;
struct DMN_LNX_ProcessLaunchList
{
U64 count;
DMN_LNX_ProcessLaunch *first;
DMN_LNX_ProcessLaunch *last;
};
typedef struct DMN_LNX_Halt
{
pid_t halter_pid;
} DMN_LNX_Halt;
typedef struct DMN_LNX_State DMN_LNX_State; typedef struct DMN_LNX_State DMN_LNX_State;
struct DMN_LNX_State struct DMN_LNX_State
{ {
Arena *arena; Arena *arena;
pid_t tracer_tid;
// rjf: access locking mechanism // rjf: access locking mechanism
Mutex access_mutex; Mutex access_mutex;
B32 access_run_state; B32 access_run_state;
// rjf: deferred events
Arena *deferred_events_arena;
DMN_EventList deferred_events;
// rjf: entity storage
Arena *entities_arena;
DMN_LNX_Entity *entities_base;
U64 entities_count;
DMN_LNX_Entity *free_entity;
// rjf: halting mechanism
B32 has_halt_injection;
U64 halt_code;
U64 halt_user_data;
DMN_EventKind last_event_kind; // rjf: entity storage
pid_t last_stop_pid; Arena *entities_arena;
int last_sig_code; DMN_LNX_Entity *entities_base;
DMN_LNX_Entity *free_entity;
U64 entities_count;
HashTable *tid_ht; // thread id -> thread entity
HashTable *pid_ht; // process id -> process entity
// pid tracking
U64 active_process_count;
DMN_LNX_ProcessLaunchList pending_stopsig;
DMN_LNX_ProcessLaunchList pending_creation;
DMN_LNX_ProcessLaunchList active_pids;
DMN_LNX_ProcessLaunchList free_pids;
// halter
pid_t halter_tid;
U64 halt_code;
U64 halt_user_data;
B32 is_halting;
}; };
read_only global DMN_LNX_Entity dmn_lnx_nil_entity = {&dmn_lnx_nil_entity, &dmn_lnx_nil_entity, &dmn_lnx_nil_entity, &dmn_lnx_nil_entity, &dmn_lnx_nil_entity}; ////////////////////////////////
global DMN_LNX_State *dmn_lnx_state = 0; //~ Globals
thread_static B32 dmn_lnx_ctrl_thread = 0;
global DMN_LNX_State *dmn_lnx_state = 0;
thread_static B32 dmn_lnx_ctrl_thread = 0;
read_only global DMN_LNX_Entity dmn_lnx_nil_entity_ = {&dmn_lnx_nil_entity_, &dmn_lnx_nil_entity_, &dmn_lnx_nil_entity_, &dmn_lnx_nil_entity_, &dmn_lnx_nil_entity_};
read_only global DMN_LNX_Entity *dmn_lnx_nil_entity = &dmn_lnx_nil_entity_;
//////////////////////////////// ////////////////////////////////
//~ rjf: Helpers //~ rjf: Helpers
@@ -298,6 +337,8 @@ internal DMN_LNX_PhdrInfo dmn_lnx_phdr_info_from_memory(int memory_fd, ELF
internal DMN_LNX_DynamicInfo dmn_lnx_dynamic_info_from_memory(int memory_fd, ELF_Class elf_Class, U64 rebase, U64 dynamic_vaddr); internal DMN_LNX_DynamicInfo dmn_lnx_dynamic_info_from_memory(int memory_fd, ELF_Class elf_Class, U64 rebase, U64 dynamic_vaddr);
internal U64 dmn_lnx_rdebug_vaddr_from_memory(int memory_fd, U64 loader_vaddr); internal U64 dmn_lnx_rdebug_vaddr_from_memory(int memory_fd, U64 loader_vaddr);
internal String8 dmn_lnx_dl_path_from_pid(Arena *arena, pid_t pid, U64 auxv_base);
//////////////////////////////// ////////////////////////////////
//~ rjf: Entity Functions //~ rjf: Entity Functions
@@ -309,10 +350,10 @@ internal DMN_LNX_Entity *dmn_lnx_thread_from_pid(pid_t pid);
internal U64 dmn_lnx_thread_read_ip(DMN_LNX_Entity *thread); internal U64 dmn_lnx_thread_read_ip(DMN_LNX_Entity *thread);
internal U64 dmn_lnx_thread_read_sp(DMN_LNX_Entity *thread); internal U64 dmn_lnx_thread_read_sp(DMN_LNX_Entity *thread);
internal B32 dmn_lnx_thread_write_ip(DMN_LNX_Entity *thread, U64 ip); internal void dmn_lnx_thread_write_ip(DMN_LNX_Entity *thread, U64 ip);
internal B32 dmn_lnx_thread_write_sp(DMN_LNX_Entity *thread, U64 sp); internal void dmn_lnx_thread_write_sp(DMN_LNX_Entity *thread, U64 sp);
internal B32 dmn_lnx_thread_read_reg_block(DMN_LNX_Entity *thread, void *reg_block); internal B32 dmn_lnx_thread_read_reg_block(DMN_LNX_Entity *thread);
internal B32 dmn_lnx_thread_write_reg_block(DMN_LNX_Entity *thread, void *reg_block); internal B32 dmn_lnx_thread_write_reg_block(DMN_LNX_Entity *thread);
//////////////////////////////// ////////////////////////////////