debugger: added breakpoints

This commit is contained in:
2017-09-15 13:57:21 +02:00
parent 6f6b5b934e
commit 4a41273987
6 changed files with 144 additions and 10 deletions

11
Info.plist Normal file
View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SecTaskAccess</key>
<array>
<string>allowed</string>
<string>debug</string>
</array>
</dict>
</plist>

View File

@@ -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)

View File

@@ -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) {

View File

@@ -1,17 +1,31 @@
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <editline/readline.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#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*);

37
src/util.c Normal file
View File

@@ -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;
}

4
src/util.h Normal file
View File

@@ -0,0 +1,4 @@
#include <string.h>
#include <stdlib.h>
char** split(char*, char);