diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2005-05-26 04:34:53 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2005-05-26 04:34:53 +0000 |
commit | e926c786ee7effb5dbbcb62123460110959befa5 (patch) | |
tree | 46cd2338c04725ece07418d861a1121cb4aba7b0 | |
parent | fe222533e855920691266112478951bfa255abdc (diff) |
Implement PT_STEP for hppa.
ok mickey@
-rw-r--r-- | sys/arch/hppa/hppa/process_machdep.c | 13 | ||||
-rw-r--r-- | sys/arch/hppa/hppa/trap.c | 122 | ||||
-rw-r--r-- | sys/arch/hppa/include/proc.h | 5 | ||||
-rw-r--r-- | sys/arch/hppa/include/trap.h | 3 |
4 files changed, 127 insertions, 16 deletions
diff --git a/sys/arch/hppa/hppa/process_machdep.c b/sys/arch/hppa/hppa/process_machdep.c index 52b6c826984..b3bf29c9bb6 100644 --- a/sys/arch/hppa/hppa/process_machdep.c +++ b/sys/arch/hppa/hppa/process_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: process_machdep.c,v 1.12 2005/05/10 11:32:51 mickey Exp $ */ +/* $OpenBSD: process_machdep.c,v 1.13 2005/05/26 04:34:51 kettenis Exp $ */ /* * Copyright (c) 1999-2004 Michael Shalayeff @@ -164,16 +164,7 @@ process_write_fpregs(p, fpregs) return (0); } -int -process_sstep(p, sstep) - struct proc *p; - int sstep; -{ - if (sstep) - return (EINVAL); - - return (0); -} +/* process_sstep() is in trap.c */ int process_set_pc(p, addr) diff --git a/sys/arch/hppa/hppa/trap.c b/sys/arch/hppa/hppa/trap.c index 7dfd2065336..63b6043e42f 100644 --- a/sys/arch/hppa/hppa/trap.c +++ b/sys/arch/hppa/hppa/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.85 2005/04/07 00:23:51 mickey Exp $ */ +/* $OpenBSD: trap.c,v 1.86 2005/05/26 04:34:52 kettenis Exp $ */ /* * Copyright (c) 1998-2004 Michael Shalayeff @@ -52,6 +52,14 @@ #endif #endif +#ifdef PTRACE +#include <miscfs/procfs/procfs.h> +void ss_clear_breakpoints(struct proc *p); +#endif + +/* single-step breakpoint */ +#define SSBREAKPOINT (HPPA_BREAK_KERNEL | (HPPA_BREAK_SS << 13)) + const char *trap_type[] = { "invalid", "HPMC", @@ -277,10 +285,26 @@ trap(type, frame) break; case T_IBREAK | T_USER: - case T_DBREAK | T_USER: + case T_DBREAK | T_USER: { + int code = TRAP_BRKPT; +#ifdef PTRACE + ss_clear_breakpoints(p); + if (opcode == SSBREAKPOINT) + code = TRAP_TRACE; +#endif + /* pass to user debugger */ + trapsignal(p, SIGTRAP, type &~ T_USER, code, sv); + } + break; + +#ifdef PTRACE + case T_TAKENBR | T_USER: + ss_clear_breakpoints(p); + /* pass to user debugger */ - trapsignal(p, SIGTRAP, type &~ T_USER, TRAP_BRKPT, sv); + trapsignal(p, SIGTRAP, type &~ T_USER, TRAP_TRACE, sv); break; +#endif case T_EXCEPTION | T_USER: { u_int64_t *fpp = (u_int64_t *)frame->tf_cr30; @@ -571,6 +595,98 @@ child_return(arg) #endif } +#ifdef PTRACE + +#include <sys/ptrace.h> + +int +ss_get_value(struct proc *p, vaddr_t addr, u_int *value) +{ + struct uio uio; + struct iovec iov; + + iov.iov_base = (caddr_t)value; + iov.iov_len = sizeof(u_int); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = (off_t)addr; + uio.uio_resid = sizeof(u_int); + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_rw = UIO_READ; + uio.uio_procp = curproc; + return (procfs_domem(curproc, p, NULL, &uio)); +} + +int +ss_put_value(struct proc *p, vaddr_t addr, u_int value) +{ + struct uio uio; + struct iovec iov; + + iov.iov_base = (caddr_t)&value; + iov.iov_len = sizeof(u_int); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = (off_t)addr; + uio.uio_resid = sizeof(u_int); + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_rw = UIO_WRITE; + uio.uio_procp = curproc; + return (procfs_domem(curproc, p, NULL, &uio)); +} + +void +ss_clear_breakpoints(struct proc *p) +{ + /* Restore origional instructions. */ + if (p->p_md.md_bpva != 0) { + ss_put_value(p, p->p_md.md_bpva, p->p_md.md_bpsave[0]); + ss_put_value(p, p->p_md.md_bpva + 4, p->p_md.md_bpsave[1]); + p->p_md.md_bpva = 0; + } +} + +int +process_sstep(struct proc *p, int sstep) +{ + int error; + + ss_clear_breakpoints(p); + + /* Don't touch the syscall gateway page. */ + if (sstep == 0 || + (p->p_md.md_regs->tf_iioq_tail & ~PAGE_MASK) == SYSCALLGATE) { + p->p_md.md_regs->tf_ipsw &= ~PSL_T; + return (0); + } + + p->p_md.md_bpva = p->p_md.md_regs->tf_iioq_tail & ~HPPA_PC_PRIV_MASK; + + /* + * Insert two breakpoint instructions; the first one might be + * nullified. Of course we need to save two instruction + * first. + */ + + error = ss_get_value(p, p->p_md.md_bpva, &p->p_md.md_bpsave[0]); + if (error) + return (error); + error = ss_get_value(p, p->p_md.md_bpva + 4, &p->p_md.md_bpsave[1]); + if (error) + return (error); + + error = ss_put_value(p, p->p_md.md_bpva, SSBREAKPOINT); + if (error) + return (error); + error = ss_put_value(p, p->p_md.md_bpva + 4, SSBREAKPOINT); + if (error) + return (error); + + p->p_md.md_regs->tf_ipsw |= PSL_T; + return (0); +} + +#endif /* PTRACE */ /* * call actual syscall routine diff --git a/sys/arch/hppa/include/proc.h b/sys/arch/hppa/include/proc.h index d05eb94fa6d..41df3eb8a3a 100644 --- a/sys/arch/hppa/include/proc.h +++ b/sys/arch/hppa/include/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.2 2003/06/02 23:27:46 millert Exp $ */ +/* $OpenBSD: proc.h,v 1.3 2005/05/26 04:34:52 kettenis Exp $ */ /* * Copyright (c) 1992, 1993 @@ -37,6 +37,9 @@ struct mdproc { struct trapframe *md_regs; /* registers on current frame */ int md_flags; /* machine-dependent flags */ + + vaddr_t md_bpva; + u_int md_bpsave[2]; }; /* md_flags */ diff --git a/sys/arch/hppa/include/trap.h b/sys/arch/hppa/include/trap.h index 774dcbf7ad0..7c21380f4fc 100644 --- a/sys/arch/hppa/include/trap.h +++ b/sys/arch/hppa/include/trap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.h,v 1.11 2005/01/17 20:47:40 mickey Exp $ */ +/* $OpenBSD: trap.h,v 1.12 2005/05/26 04:34:52 kettenis Exp $ */ /* * Copyright (c) 1999-2004 Michael Shalayeff @@ -95,6 +95,7 @@ /* im5 */ #define HPPA_BREAK_KERNEL 0 /* im13 */ +#define HPPA_BREAK_SS 4 #define HPPA_BREAK_KGDB 5 #define HPPA_BREAK_GET_PSW 9 #define HPPA_BREAK_SET_PSW 10 |