debugger: can read and write memory

This commit is contained in:
2017-09-15 18:42:54 +02:00
parent 3542a43078
commit 24302179eb
2 changed files with 63 additions and 11 deletions

View File

@@ -1,7 +1,8 @@
#include "debugger.h"
debugger* new_debugger(pid_t pid) {
debugger* new_debugger(char* pname, pid_t pid) {
debugger* d = malloc(sizeof(debugger));
d->pname = pname;
d->breakpoints = NULL;
d->n_breakpoints = 0;
d->pid = pid;
@@ -289,7 +290,7 @@ const reg_descriptor* get_register_from_name(const char* name) {
}
void dump_register(debugger* d, reg_descriptor r) {
printf("%s: 0x%" PRIx64 "\n", r.name, get_register_value(d, r.r));
printf("%s: 0x%"PRIx64"\n", r.name, get_register_value(d, r.r));
}
void dump_registers(debugger* d) {
@@ -298,16 +299,56 @@ void dump_registers(debugger* d) {
for (i = 0; i < n_registers; i++) dump_register(d, reg_descriptors[i]);
}
inline uint64_t read_mem(debugger* d, uint64_t addr) {
return ptrace(PTRACE_PEEKDATA, d->pid, (void*)addr, 0);
}
inline void write_mem(debugger* d, uint64_t addr, uint64_t val) {
ptrace(PTRACE_POKEDATA, d->pid, (void*)addr, val);
}
inline uint64_t get_pc(debugger* d) {
return get_register_value(d, rip);
}
inline void set_pc(debugger* d, uint64_t pc) {
set_register_value(d, rip, pc);
}
void wait_for_signal(debugger* d) {
int status;
waitpid(d->pid, &status, 0);
}
void step_over_breakpoint(debugger* d) {
int i;
uint64_t loc = get_pc(d) - 1;
for (i = 0; i < d->n_breakpoints; i++) {
if (d->breakpoints[i]->addr == (void*)loc) {
breakpoint* b = d->breakpoints[i];
if (b->enabled) {
set_pc(d, loc);
disable(b);
ptrace(PTRACE_SINGLESTEP, d->pid, NULL, 0);
wait_for_signal(d);
enable(b);
}
}
}
}
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);
}
void debug_continue(pid_t pid) {
int status;
ptrace(PTRACE_CONT, pid, NULL, 0);
waitpid(pid, &status, 0);
void debug_continue(debugger* d) {
step_over_breakpoint(d);
ptrace(PTRACE_CONT, d->pid, NULL, 0);
wait_for_signal(d);
}
short debug_loop(char* command, debugger* d) {
@@ -317,7 +358,7 @@ short debug_loop(char* command, debugger* d) {
command = args[0];
if (!strcmp(command, "c")) {
debug_continue(d->pid);
debug_continue(d);
} else if (!strcmp(command, "b")) {
if (!args[1]) puts("'b' needs an argument");
else set_breakpoint(d, (void*)strtol(args[1], NULL, 16));
@@ -328,6 +369,14 @@ short debug_loop(char* command, debugger* d) {
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 if(!strcmp(command, "m")) {
uint64_t addr = strtol(args[2], NULL, 16);
if (!args[3]) {
printf("%"PRIx64"\n", read_mem(d, addr));
} else {
uint64_t val = strtol(args[3], NULL, 16);
write_mem(d, addr, val);
}
} else {
printf("%s: Unknown command\n", command);
}
@@ -336,10 +385,10 @@ short debug_loop(char* command, debugger* d) {
return quit;
}
void run_debugger(pid_t pid) {
void run_debugger(char* pname, pid_t pid) {
int status;
char* line = NULL;
debugger* d = new_debugger(pid);
debugger* d = new_debugger(pname, pid);
short quit = 0;
waitpid(pid, &status, 0);
@@ -356,6 +405,6 @@ void debug(char* program) {
pid_t pid = fork();
if (!pid) run_target(program);
else if (pid > 0) run_debugger(pid);
else if (pid > 0) run_debugger(program, pid);
else perror("Error while creating debugger: unable to fork.");
}

View File

@@ -7,6 +7,8 @@
#ifdef __APPLE__
#include <mach/mach.h>
#define PTRACE_SINGLESTEP PT_STEP
#else
#include <sys/user.h>
@@ -14,6 +16,7 @@ typedef short task_t;
#endif
typedef struct {
char* pname;
breakpoint** breakpoints;
int n_breakpoints;
pid_t pid;