diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arm/arm/machdep.c | 59 | ||||
-rw-r--r-- | sys/arm/arm/trap.c | 6 | ||||
-rw-r--r-- | sys/arm/arm/undefined.c | 23 | ||||
-rw-r--r-- | sys/arm/include/proc.h | 2 | ||||
-rw-r--r-- | sys/arm/include/trap.h | 6 |
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_ */ |