summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/arm/arm/machdep.c59
-rw-r--r--sys/arm/arm/trap.c6
-rw-r--r--sys/arm/arm/undefined.c23
-rw-r--r--sys/arm/include/proc.h2
-rw-r--r--sys/arm/include/trap.h6
5 files changed, 80 insertions, 16 deletions
diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index c9d78e7..9a9f615 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -64,8 +64,10 @@ __FBSDID("$FreeBSD$");
#include <sys/buf.h>
#include <sys/exec.h>
#include <sys/sysent.h>
+#include <sys/uio.h>
#include <machine/reg.h>
#include <machine/cpu.h>
+#include <machine/trap.h>
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -289,17 +291,68 @@ set_dbregs(struct thread *td, struct dbreg *regs)
return (0);
}
+
+static int
+ptrace_read_int(struct thread *td, vm_offset_t addr, u_int32_t *v)
+{
+ struct iovec iov;
+ struct uio uio;
+ iov.iov_base = (caddr_t) v;
+ iov.iov_len = sizeof(u_int32_t);
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = (off_t)addr;
+ uio.uio_resid = sizeof(u_int32_t);
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_READ;
+ uio.uio_td = td;
+ return proc_rwmem(td->td_proc, &uio);
+}
+
+static int
+ptrace_write_int(struct thread *td, vm_offset_t addr, u_int32_t v)
+{
+ struct iovec iov;
+ struct uio uio;
+ iov.iov_base = (caddr_t) &v;
+ iov.iov_len = sizeof(u_int32_t);
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = (off_t)addr;
+ uio.uio_resid = sizeof(u_int32_t);
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_WRITE;
+ uio.uio_td = td;
+ return proc_rwmem(td->td_proc, &uio);
+}
+
int
ptrace_single_step(struct thread *td)
{
- /* XXX */
- return (0);
+ int error;
+
+ KASSERT(td->td_md.md_ptrace_instr == 0,
+ ("Didn't clear single step"));
+ error = ptrace_read_int(td, td->td_frame->tf_pc + 4,
+ &td->td_md.md_ptrace_instr);
+ if (error)
+ return (error);
+ error = ptrace_write_int(td, td->td_frame->tf_pc + 4,
+ PTRACE_BREAKPOINT);
+ if (error)
+ td->td_md.md_ptrace_instr = 0;
+ td->td_md.md_ptrace_addr = td->td_frame->tf_pc + 4;
+ return (error);
}
int
ptrace_clear_single_step(struct thread *td)
{
- /* XXX */
+ if (td->td_md.md_ptrace_instr) {
+ ptrace_write_int(td, td->td_md.md_ptrace_addr,
+ td->td_md.md_ptrace_instr);
+ td->td_md.md_ptrace_instr = 0;
+ }
return (0);
}
diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c
index 344a4a6..46595f1 100644
--- a/sys/arm/arm/trap.c
+++ b/sys/arm/arm/trap.c
@@ -100,6 +100,8 @@ __FBSDID("$FreeBSD$");
#include <sys/uio.h>
#include <sys/ktrace.h>
#endif
+#include <sys/ptrace.h>
+#include <sys/pioctl.h>
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -919,6 +921,8 @@ syscall(struct thread *td, trapframe_t *frame, u_int32_t insn)
if (error == 0) {
td->td_retval[0] = 0;
td->td_retval[1] = 0;
+ STOPEVENT(p, S_SCE, (callp->sy_narg & SYF_ARGMASK));
+ PTRACESTOP_SC(p, td, S_PT_SCE);
error = (*callp->sy_call)(td, args);
}
switch (error) {
@@ -952,6 +956,8 @@ bad:
CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
td->td_proc->p_pid, td->td_proc->p_comm, code);
+ STOPEVENT(p, S_SCX, code);
+ PTRACESTOP_SC(p, td, S_PT_SCX);
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSRET))
ktrsysret(code, error, td->td_retval[0]);
diff --git a/sys/arm/arm/undefined.c b/sys/arm/arm/undefined.c
index 6b99baf..257e612 100644
--- a/sys/arm/arm/undefined.c
+++ b/sys/arm/arm/undefined.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/signalvar.h>
+#include <sys/ptrace.h>
#ifdef KDB
#include <sys/kdb.h>
#endif
@@ -135,26 +136,17 @@ gdb_trapper(u_int addr, u_int insn, struct trapframe *frame, int code)
struct thread *td;
td = (curthread == NULL) ? &thread0 : curthread;
-#if 0
if (insn == GDB_BREAKPOINT || insn == GDB5_BREAKPOINT) {
if (code == FAULT_USER) {
- ksiginfo_t ksi;
-
- KSI_INIT_TRAP(&ksi);
- ksi.ksi_signo = SIGTRAP;
- ksi.ksi_code = TRAP_BRKPT;
- ksi.ksi_addr = (u_int32_t *)addr;
- ksi.ksi_trap = 0;
- PROC_LOCK(td->td_proc);
- trapsignal(td, &ksi);
- PROC_UNLOCK(td->td_proc);
+ trapsignal(td, SIGTRAP, 0);
return 0;
}
+#if 0
#ifdef KGDB
return !kgdb_trap(T_BREAKPOINT, frame);
#endif
- }
#endif
+ }
return 1;
}
@@ -257,6 +249,11 @@ undefinedinstruction(trapframe_t *frame)
fault_code) == 0)
break;
+ if (fault_code & FAULT_USER && fault_instruction == PTRACE_BREAKPOINT) {
+ ptrace_clear_single_step(td);
+ return;
+ }
+
if (uh == NULL && (fault_code & FAULT_USER)) {
/* Fault has not been handled */
trapsignal(td, SIGILL, 0);
@@ -272,7 +269,7 @@ undefinedinstruction(trapframe_t *frame)
return;
} else
panic("Undefined instruction in kernel.\n");
- }
+ }
#ifdef FAST_FPE
/* Optimised exit code */
diff --git a/sys/arm/include/proc.h b/sys/arm/include/proc.h
index f7e78ae..e14f38d 100644
--- a/sys/arm/include/proc.h
+++ b/sys/arm/include/proc.h
@@ -47,6 +47,8 @@ struct md_utrap {
struct mdthread {
register_t md_savecrit;
+ int md_ptrace_instr;
+ int md_ptrace_addr;
};
struct mdproc {
diff --git a/sys/arm/include/trap.h b/sys/arm/include/trap.h
index f8b28fa..a9f42e3 100644
--- a/sys/arm/include/trap.h
+++ b/sys/arm/include/trap.h
@@ -1,4 +1,10 @@
/* $NetBSD: trap.h,v 1.1 2001/02/23 03:48:19 ichiro Exp $ */
/* $FreeBSD$ */
+#ifndef _MACHINE_TRAP_H_
+#define _MACHINE_TRAP_H_
+#define GDB_BREAKPOINT 0xe6000011
+#define GDB5_BREAKPOINT 0xe7ffdefe
+#define PTRACE_BREAKPOINT 0xe7fffff0
#define KERNEL_BREAKPOINT 0xe7ffffff
+#endif /* _MACHINE_TRAP_H_ */
OpenPOWER on IntegriCloud