linux/demon flattening / clean-up checkpoint - eliminate redundant helpers, single-use functions, obsolete code

This commit is contained in:
Ryan Fleury committed 2026-08-07 13:23:42 -06:00
1 parent 7388b757d1
commit 8c2efc5adf
9 files changed
+1220 -1254

No files matched your search

@@ -0,0 +1,54 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal LNX_DMN_Process *
lnx_dmn_event_attach(Arena *arena, DMN_EventList *events, pid_t pid)
{
Temp scratch = scratch_begin(&arena, 1);
// create process
LNX_DMN_Process *process = lnx_dmn_event_create_process(arena, events, pid, 0, LNX_DMN_CreateProcessFlag_DebugSubprocesses|LNX_DMN_CreateProcessFlag_Rebased);
// extract threads from /proc/pid/task
{
String8 task_path = str8f(scratch.arena, "/proc/%d/task", pid);
DIR *task_dirp = opendir((char *)task_path.str);
if(task_dirp)
{
for(;;)
{
struct dirent *dirent = readdir(task_dirp);
if(dirent == 0) { break; }
String8 tid_str = str8_cstring_capped(dirent->d_name, dirent->d_name + NAME_MAX);
if(str8_match(tid_str, str8_lit(".."), 0) || str8_match(tid_str, str8_lit("."), 0)) { continue; }
U64 tid_64 = u64_from_str8(tid_str, 10);
pid_t tid = (pid_t)tid_64;
AssertAlways(tid == tid_64);
if(tid == pid) { continue; } // main thread was created during create process sequence
lnx_dmn_event_create_thread(arena, events, process, tid);
}
LNX_RETRY_ON_EINTR(closedir(task_dirp));
}
}
// extract modules from r_debug
{
B32 is_64bit = process->ctx->dl_class == ELF_Class_64;
GNU_RDebugInfoList rdebug_list = gnu_parse_rdebug(scratch.arena, is_64bit, process->ctx->rdebug_vaddr, lnx_dmn_machine_op_mem_read, &process->fd);
U64 name_space_id = 0;
for EachNode(rdebug_n, GNU_RDebugInfoNode, rdebug_list.first)
{
lnx_dmn_event_load_module(arena, events, process->first_thread, name_space_id, rdebug_n->v.r_map);
name_space_id += 1;
}
}
// handshake complete
lnx_dmn_push_event_handshake_complete(arena, events, process);
scratch_end(scratch);
return process;
}
@@ -0,0 +1,40 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
//- GENERATED CODE
C_LINKAGE_BEGIN
U8 lnx_dmn_probe_kind_args_count_table[12] =
{
0,
2,
2,
2,
3,
2,
3,
2,
2,
3,
3,
3,
};
String8 lnx_dmn_probe_kind_string_table[12] =
{
{0},
str8_lit_comp("init_start"),
str8_lit_comp("init_complete"),
str8_lit_comp("reloc_start"),
str8_lit_comp("reloc_complete"),
str8_lit_comp("map_start"),
str8_lit_comp("map_complete"),
str8_lit_comp("unmap_start"),
str8_lit_comp("unmap_complete"),
str8_lit_comp("longjmp"),
str8_lit_comp("longjmp_target"),
str8_lit_comp("setjmp"),
};
C_LINKAGE_END
@@ -0,0 +1,32 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
//- GENERATED CODE
#ifndef LINUX_DEMON_META_H
#define LINUX_DEMON_META_H
typedef enum LNX_DMN_ProbeKind
{
LNX_DMN_ProbeKind_Null,
LNX_DMN_ProbeKind_InitStart,
LNX_DMN_ProbeKind_InitComplete,
LNX_DMN_ProbeKind_RelocStart,
LNX_DMN_ProbeKind_RelocComplete,
LNX_DMN_ProbeKind_MapStart,
LNX_DMN_ProbeKind_MapComplete,
LNX_DMN_ProbeKind_UnmapStart,
LNX_DMN_ProbeKind_UnmapComplete,
LNX_DMN_ProbeKind_LongJmp,
LNX_DMN_ProbeKind_LongJmpTarget,
LNX_DMN_ProbeKind_SetJmp,
LNX_DMN_ProbeKind_COUNT,
} LNX_DMN_ProbeKind;
C_LINKAGE_BEGIN
extern U8 lnx_dmn_probe_kind_args_count_table[12];
extern String8 lnx_dmn_probe_kind_string_table[12];
C_LINKAGE_END
#endif // LINUX_DEMON_META_H
File diff suppressed because it is too large. Load diff
+169 -193
View File
@@ -4,6 +4,18 @@
#ifndef LINUX_DEMON_H #ifndef LINUX_DEMON_H
#define LINUX_DEMON_H #define LINUX_DEMON_H
////////////////////////////////
//~ rjf: Linux Includes
#include <sys/ptrace.h>
#include <sys/uio.h>
#include <elf.h>
////////////////////////////////
//~ rjf: Generated Code
#include "generated/linux_demon.meta.h"
//////////////////////////////// ////////////////////////////////
//~ rjf: Register Layouts //~ rjf: Register Layouts
// //
@@ -62,70 +74,54 @@ struct LNX_DMN_UserX64
U8 u_comm[32]; U8 u_comm[32];
U64 u_debugreg[8]; U64 u_debugreg[8];
}; };
StaticAssert(sizeof(LNX_DMN_UserX64) == 912, lnx_user_x64_size_check); StaticAssert(sizeof(LNX_DMN_UserX64) == 912, lnx_user_x64_size_check);
//////////////////////////////// ////////////////////////////////
//~ TLS //~ rjf: TLS Descriptions
typedef struct LNX_DMN_DbDesc typedef struct LNX_DMN_DbDesc LNX_DMN_DbDesc;
struct LNX_DMN_DbDesc
{ {
U32 bit_size; U32 bit_size;
U32 count; U32 count;
U32 offset; U32 offset;
} LNX_DMN_DbDesc; };
//////////////////////////////// ////////////////////////////////
//~ SDT Probes //~ rjf: SDT (Statically-Defined Tracing) Probes
typedef struct LNX_DMN_Probe typedef struct LNX_DMN_Probe LNX_DMN_Probe;
struct LNX_DMN_Probe
{ {
String8 provider; String8 provider;
String8 name; String8 name;
String8 args_string; String8 args_string;
STAP_ArgArray args; STAP_ArgArray args;
U64 pc; U64 pc;
U64 semaphore; U64 semaphore;
} LNX_DMN_Probe; };
typedef struct LNX_DMN_ProbeNode typedef struct LNX_DMN_ProbeNode LNX_DMN_ProbeNode;
struct LNX_DMN_ProbeNode
{ {
LNX_DMN_ProbeNode *next;
LNX_DMN_Probe v; LNX_DMN_Probe v;
struct LNX_DMN_ProbeNode *next; };
} LNX_DMN_ProbeNode;
typedef struct LNX_DMN_ProbeList typedef struct LNX_DMN_ProbeList LNX_DMN_ProbeList;
struct LNX_DMN_ProbeList
{ {
U64 count;
LNX_DMN_ProbeNode *first; LNX_DMN_ProbeNode *first;
LNX_DMN_ProbeNode *last; LNX_DMN_ProbeNode *last;
} LNX_DMN_ProbeList; U64 count;
};
#define LNX_DMN_Probe_XList \
X(InitStart, 2, "init_start") \
X(InitComplete, 2, "init_complete") \
X(RelocStart, 2, "reloc_start") \
X(RelocComplete, 3, "reloc_complete") \
X(MapStart, 2, "map_start") \
X(MapComplete, 3, "map_complete") \
X(UnmapStart, 2, "unmap_start") \
X(UnmapComplete, 2, "unmap_complete") \
X(LongJmp, 3, "longjmp") \
X(LongJmpTarget, 3, "longjmp_target") \
X(SetJmp, 3, "setjmp")
typedef enum
{
LNX_DMN_ProbeType_Null,
#define X(_N,...) LNX_DMN_ProbeType_##_N,
LNX_DMN_Probe_XList
#undef X
LNX_DMN_ProbeType_Count,
} LNX_DMN_ProbeType;
//////////////////////////////// ////////////////////////////////
//~ Process Info //~ rjf: Process Info
typedef struct LNX_DMN_Auxv typedef struct LNX_DMN_Auxv LNX_DMN_Auxv;
struct LNX_DMN_Auxv
{ {
U64 base; U64 base;
U64 phnum; U64 phnum;
@@ -133,9 +129,10 @@ typedef struct LNX_DMN_Auxv
U64 phdr; U64 phdr;
U64 execfn; U64 execfn;
U64 pagesz; U64 pagesz;
} LNX_DMN_Auxv; };
typedef struct LNX_DMN_DynamicInfo typedef struct LNX_DMN_DynamicInfo LNX_DMN_DynamicInfo;
struct LNX_DMN_DynamicInfo
{ {
U64 hash_vaddr; U64 hash_vaddr;
U64 gnu_hash_vaddr; U64 gnu_hash_vaddr;
@@ -143,10 +140,10 @@ typedef struct LNX_DMN_DynamicInfo
U64 strtab_size; U64 strtab_size;
U64 symtab_vaddr; U64 symtab_vaddr;
U64 symtab_entry_size; U64 symtab_entry_size;
} LNX_DMN_DynamicInfo; };
//////////////////////////////// ////////////////////////////////
//~ Entities //~ rjf: Entities
typedef enum LNX_DMN_EntityKind typedef enum LNX_DMN_EntityKind
{ {
@@ -155,7 +152,8 @@ typedef enum LNX_DMN_EntityKind
LNX_DMN_EntityKind_ProcessCtx, LNX_DMN_EntityKind_ProcessCtx,
LNX_DMN_EntityKind_Thread, LNX_DMN_EntityKind_Thread,
LNX_DMN_EntityKind_Module, LNX_DMN_EntityKind_Module,
} LNX_DMN_EntityKind; }
LNX_DMN_EntityKind;
typedef enum LNX_DMN_ThreadState typedef enum LNX_DMN_ThreadState
{ {
@@ -164,40 +162,46 @@ typedef enum LNX_DMN_ThreadState
LNX_DMN_ThreadState_Stopped, LNX_DMN_ThreadState_Stopped,
LNX_DMN_ThreadState_Exited, LNX_DMN_ThreadState_Exited,
LNX_DMN_ThreadState_PendingCreation, LNX_DMN_ThreadState_PendingCreation,
} LNX_DMN_ThreadState; }
LNX_DMN_ThreadState;
typedef struct LNX_DMN_Thread typedef struct LNX_DMN_Thread LNX_DMN_Thread;
struct LNX_DMN_Thread
{ {
pid_t tid; LNX_DMN_Thread *next;
LNX_DMN_ThreadState state; LNX_DMN_Thread *prev;
pid_t tid;
LNX_DMN_ThreadState state;
struct LNX_DMN_Process *process; struct LNX_DMN_Process *process;
void *reg_block; void *reg_block;
B32 is_reg_block_dirty; B32 is_reg_block_dirty;
B32 pass_through_signal; B32 pass_through_signal;
U64 pass_through_signo; U64 pass_through_signo;
U64 orig_rax; U64 orig_rax;
U64 dtv_base_vaddr; U64 dtv_base_vaddr;
};
struct LNX_DMN_Thread *next;
struct LNX_DMN_Thread *prev;
} LNX_DMN_Thread;
typedef struct LNX_DMN_ThreadPtrNode typedef struct LNX_DMN_ThreadPtrNode LNX_DMN_ThreadPtrNode;
struct LNX_DMN_ThreadPtrNode
{ {
LNX_DMN_ThreadPtrNode *next;
LNX_DMN_ThreadPtrNode *prev;
LNX_DMN_Thread *v; LNX_DMN_Thread *v;
struct LNX_DMN_ThreadPtrNode *next; };
struct LNX_DMN_ThreadPtrNode *prev;
} LNX_DMN_ThreadPtrNode;
typedef struct LNX_DMN_ThreadPtrList typedef struct LNX_DMN_ThreadPtrList LNX_DMN_ThreadPtrList;
struct LNX_DMN_ThreadPtrList
{ {
U64 count;
LNX_DMN_ThreadPtrNode *first; LNX_DMN_ThreadPtrNode *first;
LNX_DMN_ThreadPtrNode *last; LNX_DMN_ThreadPtrNode *last;
} LNX_DMN_ThreadPtrList; U64 count;
};
typedef struct LNX_DMN_Module typedef struct LNX_DMN_Module LNX_DMN_Module;
struct LNX_DMN_Module
{ {
LNX_DMN_Module *next;
LNX_DMN_Module *prev;
U64 name_vaddr; U64 name_vaddr;
U64 base_vaddr; U64 base_vaddr;
U64 name_space_id; U64 name_space_id;
@@ -207,27 +211,26 @@ typedef struct LNX_DMN_Module
U64 phcount; U64 phcount;
U64 tls_index; U64 tls_index;
U64 tls_offset; U64 tls_offset;
B8 is_live; B8 is_live;
B8 is_main; B8 is_main;
};
struct LNX_DMN_Module *next;
struct LNX_DMN_Module *prev;
} LNX_DMN_Module;
typedef struct LNX_DMN_ModulePtrNode typedef struct LNX_DMN_ModulePtrNode LNX_DMN_ModulePtrNode;
struct LNX_DMN_ModulePtrNode
{ {
LNX_DMN_ModulePtrNode *next;
LNX_DMN_Module *v; LNX_DMN_Module *v;
struct LNX_DMN_ModulePtrNode *next; };
} LNX_DMN_ModulePtrNode;
typedef struct LNX_DMN_ModulePtrList typedef struct LNX_DMN_ModulePtrList LNX_DMN_ModulePtrList;
struct LNX_DMN_ModulePtrList
{ {
U64 count;
LNX_DMN_ModulePtrNode *first; LNX_DMN_ModulePtrNode *first;
LNX_DMN_ModulePtrNode *last; LNX_DMN_ModulePtrNode *last;
} LNX_DMN_ModulePtrList; U64 count;
};
typedef enum typedef enum LNX_DMN_ProcessState
{ {
LNX_DMN_ProcessState_Null, LNX_DMN_ProcessState_Null,
LNX_DMN_ProcessState_Launch, LNX_DMN_ProcessState_Launch,
@@ -235,48 +238,51 @@ typedef enum
LNX_DMN_ProcessState_WaitForExec, LNX_DMN_ProcessState_WaitForExec,
LNX_DMN_ProcessState_ExecFailedDoExit, LNX_DMN_ProcessState_ExecFailedDoExit,
LNX_DMN_ProcessState_Normal, LNX_DMN_ProcessState_Normal,
} LNX_DMN_ProcessState; }
LNX_DMN_ProcessState;
typedef enum typedef enum LNX_DMN_CreateProcessFlags
{ {
LNX_DMN_CreateProcessFlag_DebugSubprocesses = (1 << 0), LNX_DMN_CreateProcessFlag_DebugSubprocesses = (1 << 0),
LNX_DMN_CreateProcessFlag_Rebased = (1 << 1), LNX_DMN_CreateProcessFlag_Rebased = (1 << 1),
LNX_DMN_CreateProcessFlag_Cow = (1 << 2), LNX_DMN_CreateProcessFlag_Cow = (1 << 2),
LNX_DMN_CreateProcessFlag_ClonedMemory = (1 << 3), LNX_DMN_CreateProcessFlag_ClonedMemory = (1 << 3),
} LNX_DMN_CreateProcessFlags; }
LNX_DMN_CreateProcessFlags;
typedef struct LNX_DMN_Process typedef struct LNX_DMN_Process LNX_DMN_Process;
struct LNX_DMN_Process
{ {
pid_t pid; LNX_DMN_Process *parent_process;
int fd;
LNX_DMN_ProcessState state;
B32 debug_subprocesses;
B32 is_cow;
B32 vfork_with_spoof;
U64 thread_count;
LNX_DMN_Thread *first_thread;
LNX_DMN_Thread *last_thread;
U64 main_thread_exit_code;
struct LNX_DMN_Process *parent_process;
struct LNX_DMN_ProcessCtx *ctx; struct LNX_DMN_ProcessCtx *ctx;
LNX_DMN_Process *next;
LNX_DMN_Process *prev;
struct LNX_DMN_Process *next; pid_t pid;
struct LNX_DMN_Process *prev; int fd;
} LNX_DMN_Process; LNX_DMN_ProcessState state;
B32 debug_subprocesses;
B32 is_cow;
B32 vfork_with_spoof;
U64 thread_count;
LNX_DMN_Thread *first_thread;
LNX_DMN_Thread *last_thread;
U64 main_thread_exit_code;
};
typedef struct LNX_DMN_ProcessPtrNode typedef struct LNX_DMN_ProcessPtrNode LNX_DMN_ProcessPtrNode;
struct LNX_DMN_ProcessPtrNode
{ {
LNX_DMN_ProcessPtrNode *next;
LNX_DMN_Process *v; LNX_DMN_Process *v;
struct LNX_DMN_ProcessPtrNode *next; };
} LNX_DMN_ProcessPtrNode;
typedef struct LNX_DMN_ProcessPtrList typedef struct LNX_DMN_ProcessPtrList LNX_DMN_ProcessPtrList;
struct LNX_DMN_ProcessPtrList
{ {
U64 count;
LNX_DMN_ProcessPtrNode *first; LNX_DMN_ProcessPtrNode *first;
LNX_DMN_ProcessPtrNode *last; LNX_DMN_ProcessPtrNode *last;
} LNX_DMN_ProcessPtrList; U64 count;
};
typedef struct LNX_DMN_ActiveTrap LNX_DMN_ActiveTrap; typedef struct LNX_DMN_ActiveTrap LNX_DMN_ActiveTrap;
struct LNX_DMN_ActiveTrap struct LNX_DMN_ActiveTrap
@@ -287,64 +293,65 @@ struct LNX_DMN_ActiveTrap
String8 swap_bytes; String8 swap_bytes;
}; };
typedef struct LNX_DMN_ProcessCtx typedef struct LNX_DMN_ProcessCtx LNX_DMN_ProcessCtx;
struct LNX_DMN_ProcessCtx
{ {
Arena *arena; Arena *arena;
Arch arch; Arch arch;
U64 rdebug_vaddr; U64 rdebug_vaddr;
ELF_Class dl_class; ELF_Class dl_class;
HashTable *loaded_modules_ht; HashTable *loaded_modules_ht;
LNX_DMN_Probe **probes; LNX_DMN_Probe **probes;
LNX_DMN_ActiveTrap *first_probe_trap; LNX_DMN_ActiveTrap *first_probe_trap;
LNX_DMN_ActiveTrap *last_probe_trap; LNX_DMN_ActiveTrap *last_probe_trap;
LNX_DMN_Module *first_module; LNX_DMN_Module *first_module;
LNX_DMN_Module *last_module; LNX_DMN_Module *last_module;
U64 module_count; U64 module_count;
U64 ref_count; U64 ref_count;
String8List free_reg_blocks; String8List free_reg_blocks;
String8List free_reg_block_nodes; String8List free_reg_block_nodes;
// x64 // x64
U64 xcr0; U64 xcr0;
U64 xsave_size; U64 xsave_size;
X64_XSaveLayout xsave_layout; X64_XSaveLayout xsave_layout;
} LNX_DMN_ProcessCtx; };
typedef struct LNX_DMN_Entity typedef struct LNX_DMN_Entity LNX_DMN_Entity;
struct LNX_DMN_Entity
{ {
union union
{ {
LNX_DMN_Process process; LNX_DMN_Process process;
LNX_DMN_ProcessCtx process_ctx; LNX_DMN_ProcessCtx process_ctx;
LNX_DMN_Thread thread; LNX_DMN_Thread thread;
LNX_DMN_Module module; LNX_DMN_Module module;
struct LNX_DMN_Entity *next;
{
struct LNX_DMN_Entity *next;
};
}; };
U32 gen; U32 gen;
LNX_DMN_EntityKind kind; LNX_DMN_EntityKind kind;
} LNX_DMN_Entity; };
typedef struct LNX_DMN_EntityNode typedef struct LNX_DMN_EntityNode LNX_DMN_EntityNode;
struct LNX_DMN_EntityNode
{ {
LNX_DMN_EntityNode *next;
LNX_DMN_Entity *v; LNX_DMN_Entity *v;
struct LNX_DMN_EntityNode *next; };
} LNX_DMN_EntityNode;
typedef struct LNX_DMN_EntityList typedef struct LNX_DMN_EntityList LNX_DMN_EntityList;
struct LNX_DMN_EntityList
{ {
U64 count;
LNX_DMN_EntityNode *first; LNX_DMN_EntityNode *first;
LNX_DMN_EntityNode *last; LNX_DMN_EntityNode *last;
} LNX_DMN_EntityList; U64 count;
};
//////////////////////////////// ////////////////////////////////
//~ Global State //~ rjf: Top-Level State Bundle
typedef struct LNX_DMN_State typedef struct LNX_DMN_State LNX_DMN_State;
struct LNX_DMN_State
{ {
Arena *arena; Arena *arena;
@@ -353,16 +360,16 @@ typedef struct LNX_DMN_State
B32 access_run_state; B32 access_run_state;
// rjf: entity storage // rjf: entity storage
Arena *entities_arena; Arena *entities_arena;
LNX_DMN_Entity *entities_base; LNX_DMN_Entity *entities_base;
LNX_DMN_Entity *free_entity; LNX_DMN_Entity *free_entity;
U64 entities_count; U64 entities_count;
HashTable *tid_ht; // thread id -> thread entity HashTable *tid_ht; // thread id -> thread entity
HashTable *pid_ht; // process id -> process entity HashTable *pid_ht; // process id -> process entity
// process tracking // process tracking
U64 process_count; U64 process_count;
LNX_DMN_Process *first_process; LNX_DMN_Process *first_process;
LNX_DMN_Process *last_process; LNX_DMN_Process *last_process;
@@ -373,27 +380,28 @@ typedef struct LNX_DMN_State
// halter // halter
Mutex halter_mutex; Mutex halter_mutex;
pid_t halter_tid; pid_t halter_tid;
U64 halt_code; U64 halt_code;
U64 halt_user_data; U64 halt_user_data;
B32 is_halting; B32 is_halting;
// TLS // TLS
B32 is_tls_detected; B32 is_tls_detected;
LNX_DMN_DbDesc tls_modid_desc; LNX_DMN_DbDesc tls_modid_desc;
LNX_DMN_DbDesc tls_offset_desc; LNX_DMN_DbDesc tls_offset_desc;
} LNX_DMN_State; };
//////////////////////////////// ////////////////////////////////
//~ Globals //~ rjf: Globals
global B32 lnx_dmn_ctrl_thread; global LNX_DMN_State *lnx_dmn_state = 0;
global LNX_DMN_State *lnx_dmn_state; thread_static B32 lnx_dmn_ctrl_thread = 0;
//////////////////////////////// ////////////////////////////////
//~ Memory R/W //~ rjf: Memory R/W Helpers
internal U64 lnx_dmn_read(int memory_fd, Rng1U64 range, void *dst); internal U64 lnx_dmn_size_from_fd(int memory_fd, U64 cap);
internal B32 lnx_dmn_write(int memory_fd, Rng1U64 range, void *src); internal U64 lnx_dmn_read(int memory_fd, Rng1U64 range, void *dst);
internal B32 lnx_dmn_write(int memory_fd, Rng1U64 range, void *src);
internal String8 lnx_dmn_read_string_capped(Arena *arena, int memory_fd, U64 base_vaddr, U64 cap_size); internal String8 lnx_dmn_read_string_capped(Arena *arena, int memory_fd, U64 base_vaddr, U64 cap_size);
internal String8 lnx_dmn_read_string(Arena *arena, int memory_fd, U64 base_vaddr); internal String8 lnx_dmn_read_string(Arena *arena, int memory_fd, U64 base_vaddr);
#define lnx_dmn_read_struct(fd, vaddr, ptr) lnx_dmn_read((fd), r1u64((vaddr), (vaddr)+sizeof(*(ptr))), (ptr)) #define lnx_dmn_read_struct(fd, vaddr, ptr) lnx_dmn_read((fd), r1u64((vaddr), (vaddr)+sizeof(*(ptr))), (ptr))
@@ -407,17 +415,15 @@ internal LNX_DMN_ActiveTrap *lnx_dmn_set_trap(Arena *arena, DMN_Trap *trap);
//////////////////////////////// ////////////////////////////////
//~ ELF/GNU info //~ ELF/GNU info
internal Rng1U64 lnx_dmn_compute_image_vrange(int memory_fd, ELF_Class elf_class, U64 rebase, U64 e_phaddr, U64 e_phentsize, U64 e_phnum); internal Rng1U64 lnx_dmn_compute_image_vrange(int memory_fd, ELF_Class elf_class, U64 rebase, U64 e_phaddr, U64 e_phentsize, U64 e_phnum);
internal LNX_DMN_DynamicInfo lnx_dmn_dynamic_info_from_memory(int memory_fd, ELF_Class elf_Class, U64 rebase, U64 dynamic_vaddr);
internal U64 lnx_dmn_rdebug_vaddr_from_memory(int memory_fd, U64 loader_vaddr, B32 is_rebased);
//////////////////////////////// ////////////////////////////////
//~ Process Info //~ rjf: Process Info Parsing Functions
internal String8 lnx_dmn_exe_path_from_pid(Arena *arena, pid_t pid);
internal String8 lnx_dmn_dl_path_from_pid(Arena *arena, pid_t pid, U64 auxv_base); internal String8 lnx_dmn_dl_path_from_pid(Arena *arena, pid_t pid, U64 auxv_base);
internal ELF_Hdr64 lnx_dmn_ehdr_from_pid(pid_t pid); internal ELF_Hdr64 lnx_dmn_ehdr_from_pid(pid_t pid);
internal LNX_DMN_Auxv lnx_dmn_auxv_from_pid(pid_t pid, ELF_Class elf_class); internal LNX_DMN_Auxv lnx_dmn_auxv_from_pid(pid_t pid, ELF_Class elf_class);
internal LNX_DMN_Thread * lnx_dmn_thread_from_pid(pid_t pid); internal LNX_DMN_Thread * lnx_dmn_thread_from_pid(pid_t pid);
internal LNX_DMN_Process * lnx_dmn_process_from_pid(pid_t pid); internal LNX_DMN_Process * lnx_dmn_process_from_pid(pid_t pid);
@@ -427,19 +433,17 @@ internal LNX_DMN_Process * lnx_dmn_process_from_pid(pid_t pid);
internal DMN_ModuleInfo *lnx_dmn_module_info_from_process_module(Arena *arena, pid_t pid, int memory_fd, U64 base_vaddr, U64 link_map_vaddr, B32 is_main); internal DMN_ModuleInfo *lnx_dmn_module_info_from_process_module(Arena *arena, pid_t pid, int memory_fd, U64 base_vaddr, U64 link_map_vaddr, B32 is_main);
//////////////////////////////// ////////////////////////////////
//~ Entity //~ rjf: Entity Functions
// alloc // alloc
internal LNX_DMN_Entity * lnx_dmn_entity_alloc(LNX_DMN_EntityKind kind); internal LNX_DMN_Entity * lnx_dmn_entity_alloc(LNX_DMN_EntityKind kind);
internal LNX_DMN_Process * lnx_dmn_process_alloc(pid_t pid, LNX_DMN_ProcessState state, LNX_DMN_Process *parent_process, B32 debug_subprocess, B32 is_cow); internal LNX_DMN_Process * lnx_dmn_process_alloc(pid_t pid, LNX_DMN_ProcessState state, LNX_DMN_Process *parent_process, B32 debug_subprocess, B32 is_cow);
internal LNX_DMN_ProcessCtx * lnx_dmn_process_ctx_alloc(LNX_DMN_Process *process, B32 is_rebased);
internal LNX_DMN_Thread * lnx_dmn_thread_alloc(LNX_DMN_Process *process, LNX_DMN_ThreadState thread_state, pid_t tid); internal LNX_DMN_Thread * lnx_dmn_thread_alloc(LNX_DMN_Process *process, LNX_DMN_ThreadState thread_state, pid_t tid);
internal LNX_DMN_Module * lnx_dmn_module_alloc(LNX_DMN_ProcessCtx *ctx, int memory_fd, U64 base_vaddr, U64 name_vaddr, U64 name_space_id, B32 is_main); internal LNX_DMN_Module * lnx_dmn_module_alloc(LNX_DMN_ProcessCtx *ctx, int memory_fd, U64 base_vaddr, U64 name_vaddr, U64 name_space_id, B32 is_main);
// release // release
internal void lnx_dmn_entity_release(LNX_DMN_Entity *entity); internal void lnx_dmn_entity_release(LNX_DMN_Entity *entity);
internal void lnx_dmn_process_release(LNX_DMN_Process *process); internal void lnx_dmn_process_release(LNX_DMN_Process *process);
internal void lnx_dmn_process_ctx_release(LNX_DMN_ProcessCtx *process_ctx);
internal void lnx_dmn_thread_release(LNX_DMN_Thread *thread); internal void lnx_dmn_thread_release(LNX_DMN_Thread *thread);
internal void lnx_dmn_module_release(LNX_DMN_ProcessCtx *ctx, LNX_DMN_Module *module); internal void lnx_dmn_module_release(LNX_DMN_ProcessCtx *ctx, LNX_DMN_Module *module);
@@ -450,30 +454,20 @@ internal LNX_DMN_Module * lnx_dmn_module_clone(LNX_DMN_ProcessCtx *process_c
// entity -> handle // entity -> handle
internal DMN_Handle lnx_dmn_handle_from_entity(LNX_DMN_Entity *entity); internal DMN_Handle lnx_dmn_handle_from_entity(LNX_DMN_Entity *entity);
internal DMN_Handle lnx_dmn_handle_from_process(LNX_DMN_Process *process); internal DMN_Handle lnx_dmn_handle_from_process(LNX_DMN_Process *process);
internal DMN_Handle lnx_dmn_handle_from_process_ctx(LNX_DMN_ProcessCtx *process_ctx);
internal DMN_Handle lnx_dmn_handle_from_thread(LNX_DMN_Thread *thread); internal DMN_Handle lnx_dmn_handle_from_thread(LNX_DMN_Thread *thread);
internal DMN_Handle lnx_dmn_handle_from_module(LNX_DMN_Module *module); internal DMN_Handle lnx_dmn_handle_from_module(LNX_DMN_Module *module);
// handle -> entity // handle -> entity
internal LNX_DMN_Entity * lnx_dmn_entity_from_handle(DMN_Handle handle, LNX_DMN_EntityKind expected_kind); internal LNX_DMN_Entity * lnx_dmn_entity_from_handle(DMN_Handle handle, LNX_DMN_EntityKind expected_kind);
internal LNX_DMN_Process * lnx_dmn_process_from_handle(DMN_Handle process_handle); internal LNX_DMN_Process * lnx_dmn_process_from_handle(DMN_Handle process_handle);
internal LNX_DMN_ProcessCtx * lnx_dmn_process_ctx_from_handle(DMN_Handle process_ctx_handle);
internal LNX_DMN_Thread * lnx_dmn_thread_from_handle(DMN_Handle thread_handle); internal LNX_DMN_Thread * lnx_dmn_thread_from_handle(DMN_Handle thread_handle);
internal LNX_DMN_Module * lnx_dmn_module_from_handle(DMN_Handle module_handle); internal LNX_DMN_Module * lnx_dmn_module_from_handle(DMN_Handle module_handle);
////////////////////////////////
//~ Process Helpers
internal void lnx_dmn_process_trap_probes(LNX_DMN_Process *process);
internal void lnx_dmn_process_untrap_probes(LNX_DMN_Process *process);
//////////////////////////////// ////////////////////////////////
//~ Thread Helpers //~ Thread Helpers
internal U64 lnx_dmn_thread_read_ip(LNX_DMN_Thread *thread); internal U64 lnx_dmn_thread_read_ip(LNX_DMN_Thread *thread);
internal U64 lnx_dmn_thread_read_sp(LNX_DMN_Thread *thread);
internal void lnx_dmn_thread_write_ip(LNX_DMN_Thread *thread, U64 ip); internal void lnx_dmn_thread_write_ip(LNX_DMN_Thread *thread, U64 ip);
internal void lnx_dmn_thread_write_sp(LNX_DMN_Thread *thread, U64 sp);
internal B32 lnx_dmn_thread_read_reg_block(LNX_DMN_Thread *thread); internal B32 lnx_dmn_thread_read_reg_block(LNX_DMN_Thread *thread);
internal B32 lnx_dmn_thread_write_reg_block(LNX_DMN_Thread *thread); internal B32 lnx_dmn_thread_write_reg_block(LNX_DMN_Thread *thread);
internal B32 lnx_dmn_set_single_step_flag(LNX_DMN_Thread *thread, B32 is_on); internal B32 lnx_dmn_set_single_step_flag(LNX_DMN_Thread *thread, B32 is_on);
@@ -484,39 +478,21 @@ internal U64 lnx_dmn_tls_root_vaddr_from_reg_block(int fd, Arch arch, void *reg
internal void lnx_dmn_thread_ptr_list_push_node(LNX_DMN_ThreadPtrList *list, LNX_DMN_ThreadPtrNode *n); internal void lnx_dmn_thread_ptr_list_push_node(LNX_DMN_ThreadPtrList *list, LNX_DMN_ThreadPtrNode *n);
internal LNX_DMN_ThreadPtrNode * lnx_dmn_thread_ptr_list_push(Arena *arena, LNX_DMN_ThreadPtrList *list, LNX_DMN_Thread *v); internal LNX_DMN_ThreadPtrNode * lnx_dmn_thread_ptr_list_push(Arena *arena, LNX_DMN_ThreadPtrList *list, LNX_DMN_Thread *v);
internal void lnx_dmn_thread_ptr_list_remove(LNX_DMN_ThreadPtrList *list, LNX_DMN_ThreadPtrNode *n);
internal LNX_DMN_ModulePtrNode * lnx_dmn_module_ptr_list_push(Arena *arena, LNX_DMN_ModulePtrList *list, LNX_DMN_Module *v); internal LNX_DMN_ModulePtrNode * lnx_dmn_module_ptr_list_push(Arena *arena, LNX_DMN_ModulePtrList *list, LNX_DMN_Module *v);
internal LNX_DMN_ProcessPtrNode * lnx_dmn_process_ptr_list_push(Arena *arena, LNX_DMN_ProcessPtrList *list, LNX_DMN_Process *v);
//////////////////////////////// ////////////////////////////////
//~ Debug Event Pushers //~ Debug Event Pushers
internal void lnx_dmn_push_event_create_process(Arena *arena, DMN_EventList *events, LNX_DMN_Process *process);
internal void lnx_dmn_push_event_exit_process(Arena *arena, DMN_EventList *events, LNX_DMN_Process *process);
internal void lnx_dmn_push_event_create_thread(Arena *arena, DMN_EventList *events, LNX_DMN_Thread *thread); internal void lnx_dmn_push_event_create_thread(Arena *arena, DMN_EventList *events, LNX_DMN_Thread *thread);
internal void lnx_dmn_push_event_exit_thread(Arena *arena, DMN_EventList *events, LNX_DMN_Thread *thread, U64 exit_code);
internal void lnx_dmn_push_event_load_module(Arena *arena, DMN_EventList *events, LNX_DMN_Thread *thread, LNX_DMN_Module *module); internal void lnx_dmn_push_event_load_module(Arena *arena, DMN_EventList *events, LNX_DMN_Thread *thread, LNX_DMN_Module *module);
internal void lnx_dmn_push_event_unload_module(Arena *arena, DMN_EventList *events, LNX_DMN_Process *process, LNX_DMN_Module *module); internal void lnx_dmn_push_event_unload_module(Arena *arena, DMN_EventList *events, LNX_DMN_Process *process, LNX_DMN_Module *module);
internal void lnx_dmn_push_event_handshake_complete(Arena *arena, DMN_EventList *events, LNX_DMN_Process *process);
internal void lnx_dmn_push_event_breakpoint(Arena *arena, DMN_EventList *events, LNX_DMN_Thread *thread, U64 address);
internal void lnx_dmn_push_event_single_step(Arena *arena, DMN_EventList *events, LNX_DMN_Thread *thread);
internal void lnx_dmn_push_event_exception(Arena *arena, DMN_EventList *events, LNX_DMN_Thread *thread, U64 signo);
internal void lnx_dmn_push_event_halt(Arena *arena, DMN_EventList *events);
internal void lnx_dmn_push_event_not_attached(Arena *arena, DMN_EventList *events);
//////////////////////////////// ////////////////////////////////
//~ Debug Event //~ Debug Event
internal LNX_DMN_Thread * lnx_dmn_event_create_thread(Arena *arena, DMN_EventList *events, LNX_DMN_Process *process, pid_t tid);
internal void lnx_dmn_event_exit_thread(Arena *arena, DMN_EventList *events, pid_t tid, U64 exit_code); internal void lnx_dmn_event_exit_thread(Arena *arena, DMN_EventList *events, pid_t tid, U64 exit_code);
internal LNX_DMN_Process * lnx_dmn_event_create_process(Arena *arena, DMN_EventList *events, pid_t pid, LNX_DMN_Process *parent_process, LNX_DMN_CreateProcessFlags flags); internal LNX_DMN_Process * lnx_dmn_event_create_process(Arena *arena, DMN_EventList *events, pid_t pid, LNX_DMN_Process *parent_process, LNX_DMN_CreateProcessFlags flags);
internal void lnx_dmn_event_exit_process(Arena *arena, DMN_EventList *events, pid_t pid);
internal void lnx_dmn_event_load_module(Arena *arena, DMN_EventList *events, LNX_DMN_Thread *thread, U64 name_space_id, U64 new_link_map_vaddr); internal void lnx_dmn_event_load_module(Arena *arena, DMN_EventList *events, LNX_DMN_Thread *thread, U64 name_space_id, U64 new_link_map_vaddr);
internal void lnx_dmn_event_unload_module(Arena *arena, DMN_EventList *events, LNX_DMN_Process *process, U64 rdebug_vaddr);
internal void lnx_dmn_event_breakpoint(Arena *arena, DMN_EventList *events, LNX_DMN_ActiveTrap *user_traps, pid_t tid);
internal void lnx_dmn_event_data_breakpoint(Arena *arena, DMN_EventList *events, pid_t tid);
internal void lnx_dmn_event_halt(Arena *arena, DMN_EventList *events);
internal void lnx_dmn_event_single_step(Arena *arena, DMN_EventList *events, pid_t tid);
internal void lnx_dmn_event_exception(Arena *arena, DMN_EventList *events, pid_t tid, U64 signo);
internal LNX_DMN_Process * lnx_dmn_event_attach(Arena *arena, DMN_EventList *events, pid_t pid);
#endif // LINUX_DEMON_H #endif // LINUX_DEMON_H
+37
View File
@@ -0,0 +1,37 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
@table(name args_count string}
LNX_DMN_ProbeTable:
{
{InitStart 2 "init_start"}
{InitComplete 2 "init_complete"}
{RelocStart 2 "reloc_start"}
{RelocComplete 3 "reloc_complete"}
{MapStart 2 "map_start"}
{MapComplete 3 "map_complete"}
{UnmapStart 2 "unmap_start"}
{UnmapComplete 2 "unmap_complete"}
{LongJmp 3 "longjmp"}
{LongJmpTarget 3 "longjmp_target"}
{SetJmp 3 "setjmp"}
}
@enum LNX_DMN_ProbeKind:
{
Null
@expand(LNX_DMN_ProbeTable row) `$(row.name)`
COUNT
}
@data(U8) lnx_dmn_probe_kind_args_count_table:
{
0,
@expand(LNX_DMN_ProbeTable row) `$(row.args_count)`
}
@data(String8) lnx_dmn_probe_kind_string_table:
{
`{0}`,
@expand(LNX_DMN_ProbeTable row) `str8_lit_comp("$(row.string)")`
}
+8 -8
View File
@@ -235,7 +235,7 @@ stap_parse_args_x64(String8 string, STAP_Arg *arg_out)
} }
// fill out memory ref portion // fill out memory ref portion
arg.type = STAP_ArgType_MemoryRef; arg.kind = STAP_ArgKind_MemoryRef;
arg.memory_ref.disp = disp; arg.memory_ref.disp = disp;
arg.memory_ref.base.reg_code = base_reg_code; arg.memory_ref.base.reg_code = base_reg_code;
arg.memory_ref.index.reg_code = index_reg_code; arg.memory_ref.index.reg_code = index_reg_code;
@@ -274,7 +274,7 @@ stap_parse_args_x64(String8 string, STAP_Arg *arg_out)
goto operand_parse_exit; goto operand_parse_exit;
} }
arg.type = STAP_ArgType_Imm; arg.kind = STAP_ArgKind_Imm;
arg.imm = imm; arg.imm = imm;
} }
// %reg // %reg
@@ -291,7 +291,7 @@ stap_parse_args_x64(String8 string, STAP_Arg *arg_out)
goto operand_parse_exit; goto operand_parse_exit;
} }
arg.type = STAP_ArgType_Reg; arg.kind = STAP_ArgKind_Reg;
arg.reg.reg_code = reg_code; arg.reg.reg_code = reg_code;
} else { } else {
goto operand_parse_exit; goto operand_parse_exit;
@@ -353,21 +353,21 @@ stap_read_arg(STAP_Arg arg,
AssertAlways(arg.value_size <= 8); AssertAlways(arg.value_size <= 8);
ARCH_Info *arch_info = arch_info_from_arch(arch); ARCH_Info *arch_info = arch_info_from_arch(arch);
B32 is_value_read = 0; B32 is_value_read = 0;
switch(arg.type) switch(arg.kind)
{ {
default:{}break; default:{}break;
case STAP_ArgType_Null:{}break; case STAP_ArgKind_Null:{}break;
case STAP_ArgType_Imm: case STAP_ArgKind_Imm:
{ {
MemoryCopy(raw_value, &arg.imm, arg.value_size); MemoryCopy(raw_value, &arg.imm, arg.value_size);
is_value_read = 1; is_value_read = 1;
}break; }break;
case STAP_ArgType_Reg: case STAP_ArgKind_Reg:
if(0 < arg.reg.reg_code && arg.reg.reg_code < arch_info->reg_code_count) if(0 < arg.reg.reg_code && arg.reg.reg_code < arch_info->reg_code_count)
{ {
is_value_read = arch_reg_block_read_range(arch_info, reg_block, arch_info->reg_code_rng_table[arg.reg.reg_code], raw_value); is_value_read = arch_reg_block_read_range(arch_info, reg_block, arch_info->reg_code_rng_table[arg.reg.reg_code], raw_value);
}break; }break;
case STAP_ArgType_MemoryRef: case STAP_ArgKind_MemoryRef:
{ {
U64 base = 0; U64 base = 0;
if(0 < arg.memory_ref.base.reg_code && arg.memory_ref.base.reg_code < arch_info->reg_code_count) if(0 < arg.memory_ref.base.reg_code && arg.memory_ref.base.reg_code < arch_info->reg_code_count)
+7 -7
View File
@@ -4,13 +4,13 @@
#ifndef STAP_PARSE_H #ifndef STAP_PARSE_H
#define STAP_PARSE_H #define STAP_PARSE_H
typedef enum STAP_ArgType typedef enum STAP_ArgKind
{ {
STAP_ArgType_Null, STAP_ArgKind_Null,
STAP_ArgType_Imm, STAP_ArgKind_Imm,
STAP_ArgType_Reg, STAP_ArgKind_Reg,
STAP_ArgType_MemoryRef, STAP_ArgKind_MemoryRef,
} STAP_ArgType; } STAP_ArgKind;
typedef enum STAP_ArgValueType typedef enum STAP_ArgValueType
{ {
@@ -24,7 +24,7 @@ typedef struct STAP_Arg
{ {
STAP_ArgValueType value_type; STAP_ArgValueType value_type;
U64 value_size; U64 value_size;
STAP_ArgType type; STAP_ArgKind kind;
union { union {
U64 imm; U64 imm;
struct { struct {
+5 -5
View File
@@ -25,7 +25,7 @@ entry_point(CmdLine *cmd_line)
if (error.size != 0) { goto exit; } if (error.size != 0) { goto exit; }
AssertAlways(arg.value_type == STAP_ArgValueType_S); AssertAlways(arg.value_type == STAP_ArgValueType_S);
AssertAlways(arg.value_size == 2); AssertAlways(arg.value_size == 2);
AssertAlways(arg.type == STAP_ArgType_Imm); AssertAlways(arg.type == STAP_ArgKind_Imm);
AssertAlways((S64)arg.imm == -123); AssertAlways((S64)arg.imm == -123);
string = str8_lit("1@$43"); string = str8_lit("1@$43");
@@ -33,7 +33,7 @@ entry_point(CmdLine *cmd_line)
if (error.size != 0) { goto exit; } if (error.size != 0) { goto exit; }
AssertAlways(arg.value_type == STAP_ArgValueType_U); AssertAlways(arg.value_type == STAP_ArgValueType_U);
AssertAlways(arg.value_size == 1); AssertAlways(arg.value_size == 1);
AssertAlways(arg.type == STAP_ArgType_Imm); AssertAlways(arg.type == STAP_ArgKind_Imm);
AssertAlways((S64)arg.imm == 43); AssertAlways((S64)arg.imm == 43);
string = str8_lit("4f@%eax"); string = str8_lit("4f@%eax");
@@ -41,7 +41,7 @@ entry_point(CmdLine *cmd_line)
if (error.size != 0) { goto exit; } if (error.size != 0) { goto exit; }
AssertAlways(arg.value_type == STAP_ArgValueType_F); AssertAlways(arg.value_type == STAP_ArgValueType_F);
AssertAlways(arg.value_size == 4); AssertAlways(arg.value_size == 4);
AssertAlways(arg.type == STAP_ArgType_Reg); AssertAlways(arg.type == STAP_ArgKind_Reg);
AssertAlways(arg.reg.is_alias == 1); AssertAlways(arg.reg.is_alias == 1);
AssertAlways(arg.reg.reg_code == REGS_AliasCodeX64_eax); AssertAlways(arg.reg.reg_code == REGS_AliasCodeX64_eax);
@@ -50,7 +50,7 @@ entry_point(CmdLine *cmd_line)
if (error.size != 0) { goto exit; } if (error.size != 0) { goto exit; }
AssertAlways(arg.value_size == 4); AssertAlways(arg.value_size == 4);
AssertAlways(arg.value_type == STAP_ArgValueType_U); AssertAlways(arg.value_type == STAP_ArgValueType_U);
AssertAlways(arg.type == STAP_ArgType_MemoryRef); AssertAlways(arg.type == STAP_ArgKind_MemoryRef);
AssertAlways(arg.memory_ref.disp == 0); AssertAlways(arg.memory_ref.disp == 0);
AssertAlways(arg.memory_ref.base.reg_code == REGS_RegCodeX64_rdi); AssertAlways(arg.memory_ref.base.reg_code == REGS_RegCodeX64_rdi);
AssertAlways(!arg.memory_ref.base.is_alias); AssertAlways(!arg.memory_ref.base.is_alias);
@@ -63,7 +63,7 @@ entry_point(CmdLine *cmd_line)
if (error.size != 0) { goto exit; } if (error.size != 0) { goto exit; }
AssertAlways(arg.value_size == 4); AssertAlways(arg.value_size == 4);
AssertAlways(arg.value_type == STAP_ArgValueType_U); AssertAlways(arg.value_type == STAP_ArgValueType_U);
AssertAlways(arg.type == STAP_ArgType_MemoryRef); AssertAlways(arg.type == STAP_ArgKind_MemoryRef);
AssertAlways(arg.memory_ref.disp == -22); AssertAlways(arg.memory_ref.disp == -22);
AssertAlways(arg.memory_ref.base.reg_code == REGS_RegCodeX64_rdi); AssertAlways(arg.memory_ref.base.reg_code == REGS_RegCodeX64_rdi);
AssertAlways(!arg.memory_ref.base.is_alias); AssertAlways(!arg.memory_ref.base.is_alias);