debugger: can read and write memory
This commit is contained in:
@@ -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.");
|
||||
}
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user