mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-11-14 02:03:27 -08:00
linux/demon flattening / clean-up checkpoint - eliminate redundant helpers, single-use functions, obsolete code
This commit is contained in:
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
|
||||||
+868
-1041
File diff suppressed because it is too large.
Load diff
+169
-193
@@ -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
|
||||||
@@ -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)")`
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in new issue
Block a user