mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
WIP: got Linux to the point where single stepping and breakpoint
events are being reported correctly to the debugger
This commit is contained in:
committed by
Ryan Fleury
parent
0d5df8f38d
commit
c4c9ef5182
@@ -138,6 +138,14 @@ struct DMN_TrapChunkList
|
||||
U64 trap_count;
|
||||
};
|
||||
|
||||
typedef struct DMN_ActiveTrap DMN_ActiveTrap;
|
||||
struct DMN_ActiveTrap
|
||||
{
|
||||
DMN_Trap *trap;
|
||||
U8 swap_byte;
|
||||
DMN_ActiveTrap *next;
|
||||
};
|
||||
|
||||
typedef struct DMN_RunCtrls DMN_RunCtrls;
|
||||
struct DMN_RunCtrls
|
||||
{
|
||||
|
||||
+1385
-554
File diff suppressed because it is too large
Load Diff
+130
-146
@@ -25,16 +25,26 @@ PTRACE_O_TRACEFORK|\
|
||||
PTRACE_O_TRACEVFORK|\
|
||||
PTRACE_O_TRACECLONE)
|
||||
|
||||
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
|
||||
//
|
||||
// These are defined in <sys/user.h>, but only for one architecture at a time
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct DMN_LNX_UserRegsX64 DMN_LNX_UserRegsX64;
|
||||
struct DMN_LNX_UserRegsX64
|
||||
typedef struct DMN_LNX_UserX64 DMN_LNX_UserX64;
|
||||
struct DMN_LNX_UserX64
|
||||
{
|
||||
struct
|
||||
{
|
||||
U64 r15;
|
||||
U64 r14;
|
||||
U64 r13;
|
||||
@@ -62,65 +72,9 @@ struct DMN_LNX_UserRegsX64
|
||||
U64 es;
|
||||
U64 fs;
|
||||
U64 gs;
|
||||
};
|
||||
|
||||
typedef struct DMN_LNX_XSaveLegacy DMN_LNX_XSaveLegacy;
|
||||
struct DMN_LNX_XSaveLegacy
|
||||
{
|
||||
U16 fcw;
|
||||
U16 fsw;
|
||||
U16 ftw;
|
||||
U16 fop;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
U64 fip;
|
||||
U64 fdp;
|
||||
} b64;
|
||||
struct
|
||||
{
|
||||
U32 fip;
|
||||
U16 fcs, _pad0;
|
||||
U32 fdp;
|
||||
U16 fds, _pad1;
|
||||
} b32;
|
||||
};
|
||||
U32 mxcsr;
|
||||
U32 mxcsr_mask;
|
||||
U128 st_space;
|
||||
U256 xmm_space;
|
||||
U8 padding[96];
|
||||
};
|
||||
|
||||
typedef struct DMN_LNX_XSaveHeader DMN_LNX_XSaveHeader;
|
||||
struct DMN_LNX_XSaveHeader
|
||||
{
|
||||
U64 xstate_bv;
|
||||
U64 xcomp_bv;
|
||||
U8 reserved[48];
|
||||
};
|
||||
|
||||
// TODO(rjf):
|
||||
//
|
||||
// this one is hacked; ymmh is not gauranteed to be at a fixed location
|
||||
// and there can be more after that. Requires CPUID to be totally compliant to the standard.
|
||||
// See intel's manual on the xsave format for more info.
|
||||
//
|
||||
typedef struct DMN_LNX_XSave DMN_LNX_XSave;
|
||||
struct DMN_LNX_XSave
|
||||
{
|
||||
DMN_LNX_XSaveLegacy legacy;
|
||||
DMN_LNX_XSaveHeader header;
|
||||
U8 ymmh[256];
|
||||
};
|
||||
|
||||
typedef struct DMN_LNX_UserX64 DMN_LNX_UserX64;
|
||||
struct DMN_LNX_UserX64
|
||||
{
|
||||
DMN_LNX_UserRegsX64 regs;
|
||||
} regs;
|
||||
S32 u_fpvalid, _pad0;
|
||||
DMN_LNX_XSaveLegacy i387;
|
||||
X64_FXSave i387;
|
||||
U64 u_tsize, u_dsize, u_ssize, start_code, start_stack;
|
||||
U64 signal;
|
||||
S32 reserved, _pad1;
|
||||
@@ -129,74 +83,66 @@ struct DMN_LNX_UserX64
|
||||
U8 u_comm[32];
|
||||
U64 u_debugreg[8];
|
||||
};
|
||||
StaticAssert(sizeof(DMN_LNX_UserX64) == 912, g_dmn_lnx_user_x64_size_check);
|
||||
|
||||
typedef struct DMN_LNX_UserRegsX86 DMN_LNX_UserRegsX86;
|
||||
struct DMN_LNX_UserRegsX86
|
||||
////////////////////////////////
|
||||
//~ Probes
|
||||
|
||||
typedef struct DMN_LNX_Probe DMN_LNX_Probe;
|
||||
struct DMN_LNX_Probe
|
||||
{
|
||||
U32 ebx;
|
||||
U32 ecx;
|
||||
U32 edx;
|
||||
U32 esi;
|
||||
U32 edi;
|
||||
U32 ebp;
|
||||
U32 eax;
|
||||
U32 ds;
|
||||
U32 es;
|
||||
U32 fs;
|
||||
U32 gs;
|
||||
U32 orig_eax;
|
||||
U32 eip;
|
||||
U32 cs;
|
||||
U32 eflags;
|
||||
U32 sp;
|
||||
U32 ss;
|
||||
String8 provider;
|
||||
String8 name;
|
||||
String8 args;
|
||||
U64 pc;
|
||||
U64 semaphore;
|
||||
};
|
||||
|
||||
// NOTE(rjf): (32-Bit Protected Mode Format)
|
||||
typedef struct DMN_LNX_FSave DMN_LNX_FSave;
|
||||
struct DMN_LNX_FSave
|
||||
typedef struct DMN_LNX_ProbeNode DMN_LNX_ProbeNode;
|
||||
struct DMN_LNX_ProbeNode
|
||||
{
|
||||
// control registers
|
||||
U16 fcw;
|
||||
U16 _pad0;
|
||||
U16 fsw;
|
||||
U16 _pad1;
|
||||
U16 ftw;
|
||||
U16 _pad2;
|
||||
U32 fip;
|
||||
U16 fips;
|
||||
U16 fop;
|
||||
U32 fdp;
|
||||
U16 fds;
|
||||
U16 _pad3;
|
||||
|
||||
// data registers
|
||||
U8 st[80];
|
||||
DMN_LNX_Probe v;
|
||||
DMN_LNX_ProbeNode *next;
|
||||
};
|
||||
|
||||
typedef struct DMN_LNX_UserX86 DMN_LNX_UserX86;
|
||||
struct DMN_LNX_UserX86
|
||||
typedef struct DMN_LNX_ProbeList DMN_LNX_ProbeList;
|
||||
struct DMN_LNX_ProbeList
|
||||
{
|
||||
DMN_LNX_UserRegsX86 regs;
|
||||
S32 u_fpvalid;
|
||||
DMN_LNX_FSave i387;
|
||||
U32 u_tsize, u_dsize, u_ssize, start_code, start_stack;
|
||||
S32 signal, reserved;
|
||||
U32 u_ar0, u_fpstate;
|
||||
U32 magic;
|
||||
U8 u_comm[32];
|
||||
U32 u_debugreg[8];
|
||||
U64 count;
|
||||
DMN_LNX_ProbeNode *first;
|
||||
DMN_LNX_ProbeNode *last;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
#define DMN_LNX_Probe_XList \
|
||||
X(InitStart, "init_start") \
|
||||
X(InitComplete, "init_complete") \
|
||||
X(RelocStart, "reloc_start") \
|
||||
X(RelocComplete, "reloc_complete") \
|
||||
X(MapStart, "map_start") \
|
||||
X(MapComplete, "map_complete") \
|
||||
X(UnmapStart, "unmap_start") \
|
||||
X(UnmapComplete, "unmap_complete") \
|
||||
X(LongJmp, "longjmp") \
|
||||
X(LongJmpTarget, "longjmp_target") \
|
||||
X(SetJmp, "setjmp")
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMN_LNX_ProbeType_Null,
|
||||
|
||||
#define X(_N,...) DMN_LNX_ProbeType_##_N,
|
||||
DMN_LNX_Probe_XList
|
||||
#undef X
|
||||
DMN_LNX_ProbeType_Count,
|
||||
} DMN_LNX_ProbeType;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Process Info Extraction Types
|
||||
|
||||
typedef struct DMN_LNX_ProcessAux DMN_LNX_ProcessAux;
|
||||
struct DMN_LNX_ProcessAux
|
||||
typedef struct DMN_LNX_ProcessAuxv DMN_LNX_ProcessAuxv;
|
||||
struct DMN_LNX_ProcessAuxv
|
||||
{
|
||||
B32 filled;
|
||||
U64 base;
|
||||
U64 phnum;
|
||||
U64 phent;
|
||||
U64 phdr;
|
||||
@@ -211,29 +157,15 @@ struct DMN_LNX_PhdrInfo
|
||||
U64 dynamic;
|
||||
};
|
||||
|
||||
typedef struct DMN_LNX_ModuleInfo DMN_LNX_ModuleInfo;
|
||||
struct DMN_LNX_ModuleInfo
|
||||
typedef struct DMN_LNX_DynamicInfo DMN_LNX_DynamicInfo;
|
||||
struct DMN_LNX_DynamicInfo
|
||||
{
|
||||
Rng1U64 vaddr_range;
|
||||
U64 name;
|
||||
U64 phvaddr;
|
||||
U64 phentsize;
|
||||
U64 phcount;
|
||||
};
|
||||
|
||||
typedef struct DMN_LNX_ModuleInfoNode DMN_LNX_ModuleInfoNode;
|
||||
struct DMN_LNX_ModuleInfoNode
|
||||
{
|
||||
DMN_LNX_ModuleInfoNode *next;
|
||||
DMN_LNX_ModuleInfo v;
|
||||
};
|
||||
|
||||
typedef struct DMN_LNX_ModuleInfoList DMN_LNX_ModuleInfoList;
|
||||
struct DMN_LNX_ModuleInfoList
|
||||
{
|
||||
DMN_LNX_ModuleInfoNode *first;
|
||||
DMN_LNX_ModuleInfoNode *last;
|
||||
U64 count;
|
||||
U64 hash_vaddr;
|
||||
U64 gnu_hash_vaddr;
|
||||
U64 strtab_vaddr;
|
||||
U64 strtab_size;
|
||||
U64 symtab_vaddr;
|
||||
U64 symtab_entry_size;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
@@ -262,11 +194,33 @@ struct DMN_LNX_Entity
|
||||
U32 gen;
|
||||
Arch arch;
|
||||
U64 id;
|
||||
|
||||
// process
|
||||
Arena *arena;
|
||||
int fd;
|
||||
pid_t tracer_tid;
|
||||
B32 expect_rdebug_data_breakpoint;
|
||||
U64 rdebug_vaddr;
|
||||
U64 rdebug_brk_vaddr;
|
||||
ELF_Class dl_class;
|
||||
HashTable *loaded_modules_ht;
|
||||
U64 probe_vaddrs[DMN_LNX_ProbeType_Count];
|
||||
|
||||
// process x64
|
||||
U64 xcr0;
|
||||
U64 xsave_size;
|
||||
X64_XSaveLayout xsave_layout;
|
||||
|
||||
// thread
|
||||
B32 expecting_dummy_sigstop;
|
||||
void *reg_block;
|
||||
|
||||
// module
|
||||
U64 base_vaddr;
|
||||
U64 phvaddr;
|
||||
U64 phentsize;
|
||||
U64 phcount;
|
||||
B8 is_active;
|
||||
};
|
||||
|
||||
typedef struct DMN_LNX_EntityNode DMN_LNX_EntityNode;
|
||||
@@ -276,6 +230,14 @@ struct DMN_LNX_EntityNode
|
||||
DMN_LNX_Entity *v;
|
||||
};
|
||||
|
||||
typedef struct DMN_LNX_EntityList DMN_LNX_EntityList;
|
||||
struct DMN_LNX_EntityList
|
||||
{
|
||||
U64 count;
|
||||
DMN_LNX_EntityNode *first;
|
||||
DMN_LNX_EntityNode *last;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Main State Bundle
|
||||
|
||||
@@ -302,6 +264,10 @@ struct DMN_LNX_State
|
||||
B32 has_halt_injection;
|
||||
U64 halt_code;
|
||||
U64 halt_user_data;
|
||||
|
||||
DMN_EventKind last_event_kind;
|
||||
pid_t last_stop_pid;
|
||||
int last_sig_code;
|
||||
};
|
||||
|
||||
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};
|
||||
@@ -311,25 +277,36 @@ thread_static B32 dmn_lnx_ctrl_thread = 0;
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
|
||||
internal DMN_LNX_EntityNode * dmn_lnx_entity_list_push(Arena *arena, DMN_LNX_EntityList *list, DMN_LNX_Entity *v);
|
||||
|
||||
//- rjf: file descriptor memory reading/writing helpers
|
||||
internal U64 dmn_lnx_read(int memory_fd, Rng1U64 range, void *dst);
|
||||
internal B32 dmn_lnx_write(int memory_fd, Rng1U64 range, void *src);
|
||||
#define dmn_lnx_read_struct(fd, vaddr, ptr) dmn_lnx_read((fd), r1u64((vaddr), (vaddr)+sizeof(*(ptr))), (ptr))
|
||||
#define dmn_lnx_write_struct(fd, vaddr, ptr) dmn_lnx_write((fd), r1u64((vaddr), (vaddr)+sizeof(*(ptr))), (ptr))
|
||||
internal String8 dmn_lnx_read_string_capped(Arena *arena, int memory_fd, U64 base_vaddr, U64 cap_size);
|
||||
internal String8 dmn_lnx_read_string(Arena *arena, int memory_fd, U64 base_vaddr);
|
||||
internal void * dmn_lnx_read_raw(Arena *arena, int memory_fd, Rng1U64 vrange);
|
||||
internal String8 dmn_lnx_read_block(Arena *arena, int memory_fd, Rng1U64 vrange);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Runtime Struct Helpers
|
||||
|
||||
internal B32 dmn_lnx_read_ehdr(int memory_fd, U64 addr, ELF_Hdr64 *ehdr_out);
|
||||
internal B32 dmn_lnx_read_phdr(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Phdr64 *phdr_out);
|
||||
internal B32 dmn_lnx_read_shdr(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Shdr64 *shdr_out);
|
||||
internal B32 dmn_lnx_read_linkmap(int memory_fd, U64 addr, ELF_Class elf_class, GNU_LinkMap64 *link_map_out);
|
||||
internal B32 dmn_lnx_read_dynamic(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Dyn64 *dyn_out);
|
||||
internal B32 dmn_lnx_read_symbol(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Sym64 *symbol_out);
|
||||
internal B32 dmn_lnx_read_r_debug(int memory_fd, U64 addr, Arch arch, GNU_RDebugInfo64 *rdebug_out);
|
||||
|
||||
//- rjf: pid => info extraction
|
||||
internal String8 dmn_lnx_exe_path_from_pid(Arena *arena, pid_t pid);
|
||||
internal Arch dmn_lnx_arch_from_pid(pid_t pid);
|
||||
internal DMN_LNX_ProcessAux dmn_lnx_aux_from_pid(pid_t pid, Arch arch);
|
||||
internal ELF_Hdr64 dmn_lnx_ehdr_from_pid(pid_t pid);
|
||||
internal DMN_LNX_ProcessAuxv dmn_lnx_auxv_from_pid(pid_t pid, ELF_Class elf_class);
|
||||
|
||||
//- rjf: phdr info extraction
|
||||
internal DMN_LNX_PhdrInfo dmn_lnx_phdr_info_from_memory(int memory_fd, B32 is_32bit, U64 phvaddr, U64 phsize, U64 phcount);
|
||||
|
||||
//- rjf: process entity => info extraction
|
||||
internal DMN_LNX_ModuleInfoList dmn_lnx_module_info_list_from_process(Arena *arena, DMN_LNX_Entity *process);
|
||||
//- ELF/GNU info from memory
|
||||
internal DMN_LNX_PhdrInfo dmn_lnx_phdr_info_from_memory(int memory_fd, ELF_Class elf_class, U64 rebase, U64 e_phaddr, U64 e_phentsize, U64 e_phnum);
|
||||
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);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entity Functions
|
||||
@@ -339,7 +316,14 @@ internal void dmn_lnx_entity_release(DMN_LNX_Entity *entity);
|
||||
internal DMN_Handle dmn_lnx_handle_from_entity(DMN_LNX_Entity *entity);
|
||||
internal DMN_LNX_Entity *dmn_lnx_entity_from_handle(DMN_Handle handle);
|
||||
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_sp(DMN_LNX_Entity *thread);
|
||||
internal B32 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 B32 dmn_lnx_thread_read_reg_block(DMN_LNX_Entity *thread, void *reg_block);
|
||||
internal B32 dmn_lnx_thread_write_reg_block(DMN_LNX_Entity *thread, void *reg_block);
|
||||
|
||||
internal B32 dmn_lnx_set_single_step_flag(DMN_LNX_Entity *thread, B32 is_on);
|
||||
|
||||
#endif // DEMON_CORE_LINUX_H
|
||||
|
||||
Reference in New Issue
Block a user