debugger: can dump, set, and read registers

This commit is contained in:
2017-09-15 17:42:16 +02:00
parent 20aa78ef9f
commit 3542a43078
3 changed files with 290 additions and 0 deletions

View File

@@ -5,6 +5,11 @@ debugger* new_debugger(pid_t pid) {
d->breakpoints = NULL;
d->n_breakpoints = 0;
d->pid = pid;
#ifdef __APPLE__
task_for_pid(mach_task_self(), pid, &d->port);
#else
d->port = 0;
#endif
return d;
}
@@ -23,6 +28,276 @@ void set_breakpoint(debugger* d, void* addr) {
d->breakpoints[d->n_breakpoints-1] = b;
}
//y u do dis to me
#ifdef __APPLE__
uint64_t get_register_value(debugger* d, reg r) {
thread_act_port_array_t thread_list;
mach_msg_type_number_t thread_count;
task_threads(d->port, &thread_list, &thread_count);
x86_thread_state64_t thread_state;
mach_msg_type_number_t sc = x86_THREAD_STATE64_COUNT;
thread_get_state(thread_list[0], x86_THREAD_STATE64,
(thread_state_t)&thread_state, &sc);
switch (r) {
case rax: return thread_state.__rax;
case rbx: return thread_state.__rbx;
case rcx: return thread_state.__rcx;
case rdx: return thread_state.__rdx;
case rdi: return thread_state.__rdi;
case rsi: return thread_state.__rsi;
case rbp: return thread_state.__rbp;
case rsp: return thread_state.__rsp;
case r8: return thread_state.__r8;
case r9: return thread_state.__r9;
case r10: return thread_state.__r10;
case r11: return thread_state.__r11;
case r12: return thread_state.__r12;
case r13: return thread_state.__r13;
case r14: return thread_state.__r14;
case r15: return thread_state.__r15;
case rip: return thread_state.__rip;
case rflags: return thread_state.__rflags;
case cs: return thread_state.__cs;
case fs: return thread_state.__fs;
case gs: return thread_state.__gs;
default: return 0;
}
}
void set_register_value(debugger* d, reg r, uint64_t val) {
thread_act_port_array_t thread_list;
mach_msg_type_number_t thread_count;
task_threads(d->port, &thread_list, &thread_count);
x86_thread_state64_t thread_state;
mach_msg_type_number_t sc = x86_THREAD_STATE64_COUNT;
thread_get_state(thread_list[0], x86_THREAD_STATE64,
(thread_state_t)&thread_state, &sc);
switch (r) {
case rax:
thread_state.__rax = val;
break;
case rbx:
thread_state.__rbx = val;
break;
case rcx:
thread_state.__rcx = val;
break;
case rdx:
thread_state.__rdx = val;
break;
case rdi:
thread_state.__rdi = val;
break;
case rsi:
thread_state.__rsi = val;
break;
case rbp:
thread_state.__rbp = val;
break;
case rsp:
thread_state.__rsp = val;
break;
case r8:
thread_state.__r8 = val;
break;
case r9:
thread_state.__r9 = val;
break;
case r10:
thread_state.__r10 = val;
break;
case r11:
thread_state.__r11 = val;
break;
case r12:
thread_state.__r12 = val;
break;
case r13:
thread_state.__r13 = val;
break;
case r14:
thread_state.__r14 = val;
break;
case r15:
thread_state.__r15 = val;
break;
case rip:
thread_state.__rip = val;
break;
case rflags:
thread_state.__rflags = val;
break;
case cs:
thread_state.__cs = val;
break;
case fs:
thread_state.__fs = val;
break;
case gs:
thread_state.__gs = val;
break;
default: break;
}
thread_set_state(thread_list[0], x86_THREAD_STATE,
(thread_state_t)&thread_state, sc);
}
#else
uint64_t get_register_value(debugger* d, reg r) {
struct user_regs_struct regs;
ptrace(PTRACE_GETREGS, d->pid, NULL, &regs);
switch (r) {
case rax: return regs.rax;
case rbx: return regs.rbx;
case rcx: return regs.rcx;
case rdx: return regs.rdx;
case rdi: return regs.rdi;
case rsi: return regs.rsi;
case rbp: return regs.rbp;
case rsp: return regs.rsp;
case r8: return regs.r8;
case r9: return regs.r9;
case r10: return regs.r10;
case r11: return regs.r11;
case r12: return regs.r12;
case r13: return regs.r13;
case r14: return regs.r14;
case r15: return regs.r15;
case rip: return regs.rip;
case eflags: return regs.eflags;
case cs: return regs.cs;
case orig_rax: return regs.orig_rax;
case fs_base: return regs.fs_base;
case gs_base: return regs.gs_base;
case fs: return regs.fs;
case gs: return regs.gs;
case ss: return regs.ss;
case ds: return regs.ds;
case es: return regs.es;
default: return 0;
}
}
void set_register_value(debugger* d, reg r, uint64_t val) {
struct user_regs_struct regs;
ptrace(PTRACE_GETREGS, d->pid, NULL, &regs);
switch (r) {
case rax:
regs.rax = val;
break;
case rbx:
regs.rbx = val;
break;
case rcx:
regs.rcx = val;
break;
case rdx:
regs.rdx = val;
break;
case rdi:
regs.rdi = val;
break;
case rsi:
regs.rsi = val;
break;
case rbp:
regs.rbp = val;
break;
case rsp:
regs.rsp = val;
break;
case r8:
regs.r8 = val;
break;
case r9:
regs.r9 = val;
break;
case r10:
regs.r10 = val;
break;
case r11:
regs.r11 = val;
break;
case r12:
regs.r12 = val;
break;
case r13:
regs.r13 = val;
break;
case r14:
regs.r14 = val;
break;
case r15:
regs.r15 = val;
break;
case rip:
regs.rip = val;
break;
case eflags:
regs.eflags = val;
break;
case cs:
regs.cs = val;
break;
case orig_rax:
regs.orig_rax = val;
break;
case fs_base:
regs.fs_base = val;
break;
case gs_base:
regs.gs_base = val;
break;
case fs:
regs.fs = val;
break;
case gs:
regs.gs = val;
break;
case ss:
regs.ss = val;
break;
case ds:
regs.ds = val;
break;
case es:
regs.es = val;
break;
default: break;
}
ptrace(PTRACE_SETREGS, d->pid, NULL, &regs);
}
#endif
const reg_descriptor* get_register_from_name(const char* name) {
int i;
for (i = 0; i < n_registers; i++) {
if (!strcmp(name, reg_descriptors[i].name)) return &reg_descriptors[i];
}
return NULL;
}
void dump_register(debugger* d, reg_descriptor r) {
printf("%s: 0x%" PRIx64 "\n", r.name, get_register_value(d, r.r));
}
void dump_registers(debugger* d) {
int i;
for (i = 0; i < n_registers; i++) dump_register(d, reg_descriptors[i]);
}
void run_target(char* program) {
if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) perror("Error while creating child: ptrace failed");
else execl(program, program, NULL);
@@ -49,6 +324,10 @@ short debug_loop(char* command, debugger* d) {
} else if ((!strcmp(command, "e")) || (!strcmp(command, "q"))) {
puts("Moriturus te saluto.");
quit = 1;
} else if (!strcmp(command, "r")) {
if (!args[1]) dump_registers(d);
else if (!args[2]) dump_register(d, *get_register_from_name(args[1]));
else set_register_value(d, get_register_from_name(args[1])->r, atol(args[2]));
} else {
printf("%s: Unknown command\n", command);
}

View File

@@ -1,13 +1,23 @@
#include <inttypes.h>
#include <editline/readline.h>
#include "breakpoint.h"
#include "register.h"
#include "util.h"
#ifdef __APPLE__
#include <mach/mach.h>
#else
#include <sys/user.h>
typedef short task_t;
#endif
typedef struct {
breakpoint** breakpoints;
int n_breakpoints;
pid_t pid;
task_t port;
} debugger;
void debug(char*);

View File

@@ -28,6 +28,7 @@ typedef enum {
ss,
ds,
es,
eflags,
} reg;