debugger: added breakpoints
This commit is contained in:
11
Info.plist
Normal file
11
Info.plist
Normal 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>
|
5
Makefile
5
Makefile
@@ -3,12 +3,13 @@ BUILDDIR=bin/
|
|||||||
PREFIX=/usr/local/bin/
|
PREFIX=/usr/local/bin/
|
||||||
SOURCES=$(wildcard src/*.c)
|
SOURCES=$(wildcard src/*.c)
|
||||||
MAIN=main.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
|
override LDFLAGS+=-ledit
|
||||||
|
|
||||||
all: main.c
|
all: main.c
|
||||||
mkdir -p $(BUILDDIR)
|
mkdir -p $(BUILDDIR)
|
||||||
$(CC) $(MAIN) $(SOURCES) -o $(BUILDDIR)$(TARGET) $(CFLAGS) $(LDFLAGS)
|
$(CC) $(MAIN) $(SOURCES) -o $(BUILDDIR)$(TARGET) $(CFLAGS) $(LDFLAGS) $(OSX_BS)
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
install $(BUILDDIR)$(TARGET) $(PREFIX)$(TARGET)
|
install $(BUILDDIR)$(TARGET) $(PREFIX)$(TARGET)
|
||||||
|
@@ -1,5 +1,55 @@
|
|||||||
#include "debugger.h"
|
#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) {
|
void run_target(char* program) {
|
||||||
if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) perror("Error while creating child: ptrace failed");
|
if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) perror("Error while creating child: ptrace failed");
|
||||||
else execl(program, program, NULL);
|
else execl(program, program, NULL);
|
||||||
@@ -12,25 +62,42 @@ void debug_continue(pid_t pid) {
|
|||||||
waitpid(pid, &status, 0);
|
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")) {
|
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 {
|
} else {
|
||||||
printf("%s: Unknown command\n", command);
|
printf("%s: Unknown command\n", command);
|
||||||
}
|
}
|
||||||
|
while(args[i]) free(args[i++]);
|
||||||
|
free(args);
|
||||||
|
return quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_debugger(pid_t pid) {
|
void run_debugger(pid_t pid) {
|
||||||
int status;
|
int status;
|
||||||
char* line = NULL;
|
char* line = NULL;
|
||||||
|
debugger* d = new_debugger(pid);
|
||||||
|
short quit = 0;
|
||||||
|
|
||||||
waitpid(pid, &status, 0);
|
waitpid(pid, &status, 0);
|
||||||
|
|
||||||
while((line = readline("minidbg> ")) != NULL) {
|
while(!quit && (line = readline("minidbg> "))) {
|
||||||
debug_loop(line, pid);
|
quit = debug_loop(line, d);
|
||||||
add_history(line);
|
add_history(line);
|
||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
|
free_debugger(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void debug(char* program) {
|
void debug(char* program) {
|
||||||
|
@@ -1,17 +1,31 @@
|
|||||||
#include <stdlib.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <editline/readline.h>
|
#include <editline/readline.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#define PTRACE_TRACEME PT_TRACE_ME
|
#define PTRACE_TRACEME PT_TRACE_ME
|
||||||
#define PTRACE_CONT PT_CONTINUE
|
#define PTRACE_CONT PT_CONTINUE
|
||||||
#define DATA 0
|
#define PTRACE_PEEKDATA PT_READ_D
|
||||||
|
#define PTRACE_POKEDATA PT_WRITE_D
|
||||||
#else
|
#else
|
||||||
#define DATA NULL
|
|
||||||
#endif
|
#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*);
|
void debug(char*);
|
||||||
|
37
src/util.c
Normal file
37
src/util.c
Normal 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
4
src/util.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
char** split(char*, char);
|
Reference in New Issue
Block a user