From 4a412739872dc999ca98f85e4a7c2502c7a2eea8 Mon Sep 17 00:00:00 2001 From: hellerve Date: Fri, 15 Sep 2017 13:57:21 +0200 Subject: [PATCH] debugger: added breakpoints --- Info.plist | 11 ++++++++ Makefile | 5 ++-- src/debugger.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++--- src/debugger.h | 22 ++++++++++++--- src/util.c | 37 +++++++++++++++++++++++++ src/util.h | 4 +++ 6 files changed, 144 insertions(+), 10 deletions(-) create mode 100644 Info.plist create mode 100644 src/util.c create mode 100644 src/util.h diff --git a/Info.plist b/Info.plist new file mode 100644 index 0000000..2e4cc8f --- /dev/null +++ b/Info.plist @@ -0,0 +1,11 @@ + + + + + SecTaskAccess + + allowed + debug + + + diff --git a/Makefile b/Makefile index eabc434..509d36f 100644 --- a/Makefile +++ b/Makefile @@ -3,12 +3,13 @@ BUILDDIR=bin/ PREFIX=/usr/local/bin/ SOURCES=$(wildcard src/*.c) MAIN=main.c -override CFLAGS+=-Werror -Wall -g -fPIC -O2 -DNDEBUG -ftrapv -Wfloat-equal -Wundef -Wwrite-strings -Wuninitialized -pedantic -std=c11 +OSX_BS=-sectcreate __TEXT __info_plist Info.plist +override CFLAGS+=-Werror -Wall -g -fPIC -O2 -DNDEBUG -ftrapv -Wfloat-equal -Wundef -Wwrite-strings -Wuninitialized -pedantic -std=gnu11 override LDFLAGS+=-ledit all: main.c mkdir -p $(BUILDDIR) - $(CC) $(MAIN) $(SOURCES) -o $(BUILDDIR)$(TARGET) $(CFLAGS) $(LDFLAGS) + $(CC) $(MAIN) $(SOURCES) -o $(BUILDDIR)$(TARGET) $(CFLAGS) $(LDFLAGS) $(OSX_BS) install: all install $(BUILDDIR)$(TARGET) $(PREFIX)$(TARGET) diff --git a/src/debugger.c b/src/debugger.c index 025bc98..ec7dabb 100644 --- a/src/debugger.c +++ b/src/debugger.c @@ -1,5 +1,55 @@ #include "debugger.h" +debugger* new_debugger(pid_t pid) { + debugger* d = malloc(sizeof(debugger)); + d->breakpoints = NULL; + d->n_breakpoints = 0; + d->pid = pid; + return d; +} + +breakpoint* new_breakpoint(pid_t pid, void* addr) { + breakpoint* b = malloc(sizeof(breakpoint)); + b->pid = pid; + b->addr = addr; + b->enabled = 0; + b->data = 0; + return b; +} + +void free_debugger(debugger* d) { + int i; + for (i = 0; i < d->n_breakpoints; i++) free(d->breakpoints[i]); + free(d); +} + +void enable(breakpoint* b) { + long data = ptrace(PTRACE_PEEKDATA, b->pid, b->addr, 0); + b->data = data & 0xff; + uint64_t int3 = 0xcc; + uint64_t data_with_int3 = ((data & ~0xff) | int3); + ptrace(PTRACE_POKEDATA, b->pid, b->addr, data_with_int3); + + b->enabled = 1; +} + +void disable(breakpoint* b) { + long data = ptrace(PTRACE_PEEKDATA, b->pid, b->addr, 0); + long restored = ((data & ~0xff) | b->data); + ptrace(PTRACE_POKEDATA, b->pid, b->addr, restored); + + b->enabled = 0; +} + +void set_breakpoint(debugger* d, void* addr) { + printf("Setting breakpoint at addres %p\n", addr); + breakpoint* b = new_breakpoint(d->pid, addr); + enable(b); + d->breakpoints = realloc(d->breakpoints, + (++d->n_breakpoints)*sizeof(breakpoint*)); + d->breakpoints[d->n_breakpoints-1] = 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); @@ -12,25 +62,42 @@ void debug_continue(pid_t pid) { waitpid(pid, &status, 0); } -void debug_loop(char* command, pid_t pid) { +short debug_loop(char* command, debugger* d) { + int quit = 0; + int i = 0; + char** args = split(command, ' '); + command = args[0]; + if (!strcmp(command, "c")) { - debug_continue(pid); + debug_continue(d->pid); + } else if (!strcmp(command, "b")) { + if (!args[1]) puts("'b' needs an argument"); + else set_breakpoint(d, (void*)strtol(args[1], NULL, 16)); + } else if ((!strcmp(command, "e")) || (!strcmp(command, "q"))) { + puts("Moriturus te saluto."); + quit = 1; } else { printf("%s: Unknown command\n", command); } + while(args[i]) free(args[i++]); + free(args); + return quit; } void run_debugger(pid_t pid) { int status; char* line = NULL; + debugger* d = new_debugger(pid); + short quit = 0; waitpid(pid, &status, 0); - while((line = readline("minidbg> ")) != NULL) { - debug_loop(line, pid); + while(!quit && (line = readline("minidbg> "))) { + quit = debug_loop(line, d); add_history(line); free(line); } + free_debugger(d); } void debug(char* program) { diff --git a/src/debugger.h b/src/debugger.h index 23fecea..8f3fa7e 100644 --- a/src/debugger.h +++ b/src/debugger.h @@ -1,17 +1,31 @@ -#include -#include +#include #include #include #include #include +#include "util.h" + #ifdef __APPLE__ #define PTRACE_TRACEME PT_TRACE_ME #define PTRACE_CONT PT_CONTINUE -#define DATA 0 +#define PTRACE_PEEKDATA PT_READ_D +#define PTRACE_POKEDATA PT_WRITE_D #else -#define DATA NULL #endif +typedef struct { + short enabled; + uint8_t data; + pid_t pid; + void* addr; +} breakpoint; + +typedef struct { + breakpoint** breakpoints; + int n_breakpoints; + pid_t pid; +} debugger; + void debug(char*); diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..b80eeda --- /dev/null +++ b/src/util.c @@ -0,0 +1,37 @@ +#include "util.h" + +char** split(char* inpt, char d) { + char** res = NULL; + size_t count = 0; + char* tmp = inpt; + char* last_comma = NULL; + size_t idx = 0; + char delim[2]; + delim[0] = d; + delim[1] = '\0'; + char* tok; + + while (*tmp) { + if (d == *tmp) { + count++; + last_comma = tmp; + } + tmp++; + } + + count += last_comma < (inpt+strlen(inpt)-1); + + res = malloc((++count)*sizeof(char*)); + + if (res) { + tok = strsep(&inpt, delim); + + while (tok) { + res[idx++] = strdup(tok); + tok = strsep(&inpt, delim); + } + res[idx] = NULL; + } + + return res; +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..72d5032 --- /dev/null +++ b/src/util.h @@ -0,0 +1,4 @@ +#include +#include + +char** split(char*, char);