summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2005-05-26 04:34:53 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2005-05-26 04:34:53 +0000
commite926c786ee7effb5dbbcb62123460110959befa5 (patch)
tree46cd2338c04725ece07418d861a1121cb4aba7b0
parentfe222533e855920691266112478951bfa255abdc (diff)
Implement PT_STEP for hppa.
ok mickey@
-rw-r--r--sys/arch/hppa/hppa/process_machdep.c13
-rw-r--r--sys/arch/hppa/hppa/trap.c122
-rw-r--r--sys/arch/hppa/include/proc.h5
-rw-r--r--sys/arch/hppa/include/trap.h3
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