summaryrefslogtreecommitdiffstats
path: root/debugger.c
diff options
context:
space:
mode:
Diffstat (limited to 'debugger.c')
-rw-r--r--debugger.c50
1 files changed, 43 insertions, 7 deletions
diff --git a/debugger.c b/debugger.c
index 2bbf866..06447c3 100644
--- a/debugger.c
+++ b/debugger.c
@@ -10,6 +10,7 @@
#include <capstone/capstone.h>
+#include "arch/arm-singlestep.h"
#include "debugger.h"
#include "helpers.h"
@@ -67,14 +68,14 @@ static void free_breakpoints(struct process *proc) {
}
}
-static void install_breakpoints(struct thread *th) {
+static void install_breakpoints(struct thread *th, int step) {
struct archinfo archinfo;
struct iovec regs = { &th->state->regs, th->state->regsize };
architecture_info(&archinfo, &regs);
struct list *breaks = &th->proc->breakpoints;
for (struct breakpoint *b = breaks->head; b != breaks->end; b = b->next) {
- if (!b->installed) {
+ if (!b->installed && (b->step == step)) {
unsigned long word;
word = ptrace(PTRACE_PEEKTEXT, th->id, b->address, NULL);
b->text = word;
@@ -272,13 +273,34 @@ static void continue_all_threads(struct process *proc) {
}
}
+static void compute_step_breakpoints(struct thread *th) {
+#ifdef ARCH_AARCH64
+ if (th->state->regsize == sizeof(struct user_regs_32)) {
+ arm_singlestep(th);
+ }
+#endif
+}
+
+static void do_singlestep(struct thread *th) {
+#ifdef ARCH_AARCH64
+ if (th->state->regsize == sizeof(struct user_regs_32)) {
+ ptrace(PTRACE_CONT, th->id, NULL, th->signal);
+ return;
+ }
+#endif
+
+ ptrace(PTRACE_SINGLESTEP, th->id, NULL, th->signal);
+}
+
static void resume_threads(struct process *proc) {
struct list *threads = &proc->threads;
int once = 0;
for (struct thread *th = threads->head; th != threads->end; th = th->next) {
if (th->stopped && th->doing == PTRACE_SINGLESTEP) {
- ptrace(PTRACE_SINGLESTEP, th->id, NULL, th->signal);
+ compute_step_breakpoints(th);
+ install_breakpoints(th, 1);
+ do_singlestep(th);
th->stopped = 0;
th->signal = 0;
strcpy(th->status, "RUNNING");
@@ -291,7 +313,7 @@ static void resume_threads(struct process *proc) {
usleep(SCHEDULER_DELAY);
once = 1;
}
- install_breakpoints(th);
+ install_breakpoints(th, 0);
ptrace(th->doing, th->id, NULL, th->signal);
th->stopped = 0;
th->signal = 0;
@@ -446,7 +468,7 @@ static int wait_thread(struct thread *th) {
return -1;
}
-struct breakpoint *add_breakpoint(struct process *proc, unsigned long address) {
+struct breakpoint *add_breakpoint(struct process *proc, unsigned long address, int step) {
struct breakpoint *b = xmalloc(sizeof(*b));
b->address = address;
b->text = 0;
@@ -454,10 +476,24 @@ struct breakpoint *add_breakpoint(struct process *proc, unsigned long address) {
b->previously_installed = 0;
b->hits = 0;
b->user = 1;
+ b->step = step;
b->stack = 0;
b->tid = 0;
b->enabled = 1;
- list_insert(proc->breakpoints.end, b);
+
+ if (step) {
+ struct breakpoint *p;
+ struct list *breaks = &proc->breakpoints;
+ for (p = breaks->head; p != breaks->end; p = p->next) {
+ if (p->step == 0) {
+ break;
+ }
+ }
+ list_insert(p, b);
+ } else {
+ list_insert(proc->breakpoints.end, b);
+ }
+
return b;
}
@@ -656,7 +692,7 @@ int dbg_stepover(struct thread *th) {
cs_disasm_iter(handle, &code, &size, &address, insn);
if (insn->id == archinfo.cs_call) {
- struct breakpoint *b = add_breakpoint(th->proc, address);
+ struct breakpoint *b = add_breakpoint(th->proc, address, 0);
b->user = 0;
b->stack = archinfo.stackptr;
b->tid = th->id;