summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2002-03-12 11:58:15 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2002-03-12 11:58:15 +0000
commit5b79aab6eebe0f7a472f6dca68a6d5c34c8e48e3 (patch)
tree12f5d15fda057fdb207e251ce9ff7d0ac977db05
parent1f81b3a4471284b779fdf18bad08ed80babb2cd9 (diff)
Emulate ptrace(PT_STEP in software.
More or less directly from FreeBSD.
-rw-r--r--sys/arch/alpha/alpha/process_machdep.c232
-rw-r--r--sys/arch/alpha/alpha/trap.c7
-rw-r--r--sys/arch/alpha/include/proc.h14
-rw-r--r--sys/arch/alpha/include/ptrace.h11
4 files changed, 245 insertions, 19 deletions
diff --git a/sys/arch/alpha/alpha/process_machdep.c b/sys/arch/alpha/alpha/process_machdep.c
index 2427271486e..4e15522218f 100644
--- a/sys/arch/alpha/alpha/process_machdep.c
+++ b/sys/arch/alpha/alpha/process_machdep.c
@@ -1,6 +1,31 @@
-/* $OpenBSD: process_machdep.c,v 1.5 2000/11/08 16:01:03 art Exp $ */
+/* $OpenBSD: process_machdep.c,v 1.6 2002/03/12 11:58:14 art Exp $ */
/* $NetBSD: process_machdep.c,v 1.7 1996/07/11 20:14:21 cgd Exp $ */
+/*-
+ * Copyright (c) 1998 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
/*
* Copyright (c) 1994 Christopher G. Demetriou
* All rights reserved.
@@ -63,6 +88,9 @@
#include <machine/reg.h>
#include <machine/frame.h>
+#include <alpha/alpha/db_instruction.h>
+#include <miscfs/procfs/procfs.h>
+
#define process_frame(p) ((p)->p_md.md_tf)
#define process_pcb(p) (&(p)->p_addr->u_pcb)
#define process_fpframe(p) (&(process_pcb(p)->pcb_fp))
@@ -92,18 +120,6 @@ process_write_regs(p, regs)
}
int
-process_sstep(p, sstep)
- struct proc *p;
- int sstep;
-{
-
- if (sstep)
- return (EINVAL);
-
- return (0);
-}
-
-int
process_set_pc(p, addr)
struct proc *p;
caddr_t addr;
@@ -142,3 +158,193 @@ process_write_fpregs(p, regs)
bcopy(regs, process_fpframe(p), sizeof(struct fpreg));
return (0);
}
+
+/*
+ * Single stepping infrastructure.
+ */
+int ptrace_set_bpt(struct proc *p, struct mdbpt *bpt);
+int ptrace_clear_bpt(struct proc *p, struct mdbpt *bpt);
+int ptrace_read_int(struct proc *, vaddr_t, u_int32_t *);
+int ptrace_write_int(struct proc *, vaddr_t, u_int32_t);
+u_int64_t ptrace_read_register(struct proc *p, int regno);
+
+int
+ptrace_read_int(struct proc *p, vaddr_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_procp = p;
+ return procfs_domem(curproc, p, NULL, &uio);
+}
+
+int
+ptrace_write_int(struct proc *p, vaddr_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_procp = p;
+ return procfs_domem(curproc, p, NULL, &uio);
+}
+
+u_int64_t
+ptrace_read_register(struct proc *p, int regno)
+{
+ static int reg_to_frame[32] = {
+ FRAME_V0,
+ FRAME_T0,
+ FRAME_T1,
+ FRAME_T2,
+ FRAME_T3,
+ FRAME_T4,
+ FRAME_T5,
+ FRAME_T6,
+ FRAME_T7,
+
+ FRAME_S0,
+ FRAME_S1,
+ FRAME_S2,
+ FRAME_S3,
+ FRAME_S4,
+ FRAME_S5,
+ FRAME_S6,
+
+ FRAME_A0,
+ FRAME_A1,
+ FRAME_A2,
+ FRAME_A3,
+ FRAME_A4,
+ FRAME_A5,
+
+ FRAME_T8,
+ FRAME_T9,
+ FRAME_T10,
+ FRAME_T11,
+ FRAME_RA,
+ FRAME_T12,
+ FRAME_AT,
+ FRAME_GP,
+ FRAME_SP,
+ -1, /* zero */
+ };
+
+ if (regno == R_ZERO)
+ return 0;
+
+ return p->p_md.md_tf->tf_regs[reg_to_frame[regno]];
+}
+
+int
+ptrace_clear_bpt(struct proc *p, struct mdbpt *bpt)
+{
+ return ptrace_write_int(p, bpt->addr, bpt->contents);
+}
+
+int
+ptrace_set_bpt(struct proc *p, struct mdbpt *bpt)
+{
+ int error;
+ u_int32_t bpins = 0x00000080;
+ error = ptrace_read_int(p, bpt->addr, &bpt->contents);
+ if (error)
+ return error;
+ return ptrace_write_int(p, bpt->addr, bpins);
+}
+
+int
+process_sstep(struct proc *p, int sstep)
+{
+ int error;
+ vaddr_t pc = p->p_md.md_tf->tf_regs[FRAME_PC];
+ alpha_instruction ins;
+ vaddr_t addr[2];
+ int count = 0;
+
+ if (sstep == 0) {
+ /* clearing the breakpoint */
+ if (p->p_md.md_flags & MDP_STEP2) {
+ ptrace_clear_bpt(p, &p->p_md.md_sstep[1]);
+ ptrace_clear_bpt(p, &p->p_md.md_sstep[0]);
+ p->p_md.md_flags &= ~MDP_STEP2;
+ } else if (p->p_md.md_flags & MDP_STEP1) {
+ ptrace_clear_bpt(p, &p->p_md.md_sstep[0]);
+ p->p_md.md_flags &= ~MDP_STEP1;
+ }
+ return (0);
+ }
+#ifdef DIAGNOSTIC
+ if (p->p_md.md_flags & (MDP_STEP1|MDP_STEP2))
+ panic("process_sstep: step breakpoints not removed");
+#endif
+ error = ptrace_read_int(p, pc, &ins.bits);
+ if (error)
+ return (error);
+
+ switch (ins.branch_format.opcode) {
+ case op_j:
+ /* Jump: target is register value */
+ addr[0] = ptrace_read_register(p, ins.jump_format.rb) & ~3;
+ count = 1;
+ break;
+
+ case op_br:
+ case op_fbeq:
+ case op_fblt:
+ case op_fble:
+ case op_bsr:
+ case op_fbne:
+ case op_fbge:
+ case op_fbgt:
+ case op_blbc:
+ case op_beq:
+ case op_blt:
+ case op_ble:
+ case op_blbs:
+ case op_bne:
+ case op_bge:
+ case op_bgt:
+ /* Branch: target is pc+4+4*displacement */
+ addr[0] = pc + 4;
+ addr[1] = pc + 4 + 4 * ins.branch_format.displacement;
+ count = 2;
+ break;
+
+ default:
+ addr[0] = pc + 4;
+ count = 1;
+ }
+
+ p->p_md.md_sstep[0].addr = addr[0];
+ error = ptrace_set_bpt(p, &p->p_md.md_sstep[0]);
+ if (error)
+ return (error);
+ if (count == 2) {
+ p->p_md.md_sstep[1].addr = addr[1];
+ error = ptrace_set_bpt(p, &p->p_md.md_sstep[1]);
+ if (error) {
+ ptrace_clear_bpt(p, &p->p_md.md_sstep[0]);
+ return (error);
+ }
+ p->p_md.md_flags |= MDP_STEP2;
+ } else
+ p->p_md.md_flags |= MDP_STEP1;
+
+ return (0);
+}
diff --git a/sys/arch/alpha/alpha/trap.c b/sys/arch/alpha/alpha/trap.c
index 1adc97860b9..fdc15020ce5 100644
--- a/sys/arch/alpha/alpha/trap.c
+++ b/sys/arch/alpha/alpha/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.29 2001/11/28 16:13:27 art Exp $ */
+/* $OpenBSD: trap.c,v 1.30 2002/03/12 11:58:14 art Exp $ */
/* $NetBSD: trap.c,v 1.52 2000/05/24 16:48:33 thorpej Exp $ */
/*-
@@ -105,6 +105,7 @@
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
+#include <sys/ptrace.h>
#include <uvm/uvm_extern.h>
@@ -384,6 +385,10 @@ trap(a0, a1, a2, entry, framep)
/* FALLTHROUTH */
case ALPHA_IF_CODE_BPT:
case ALPHA_IF_CODE_BUGCHK:
+ if (p->p_md.md_flags & (MDP_STEP1|MDP_STEP2)) {
+ process_sstep(p, 0);
+ p->p_md.md_tf->tf_regs[FRAME_PC] -= 4;
+ }
ucode = a0; /* trap type */
i = SIGTRAP;
break;
diff --git a/sys/arch/alpha/include/proc.h b/sys/arch/alpha/include/proc.h
index 22ceefe5803..8caaad0c739 100644
--- a/sys/arch/alpha/include/proc.h
+++ b/sys/arch/alpha/include/proc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.h,v 1.5 2000/11/08 16:01:13 art Exp $ */
+/* $OpenBSD: proc.h,v 1.6 2002/03/12 11:58:14 art Exp $ */
/* $NetBSD: proc.h,v 1.2 1995/03/24 15:01:36 cgd Exp $ */
/*
@@ -33,13 +33,21 @@
* Machine-dependent part of the proc struct for the Alpha.
*/
+struct mdbpt {
+ vaddr_t addr;
+ u_int32_t contents;
+};
+
struct mdproc {
- u_long md_flags;
- struct trapframe *md_tf; /* trap/syscall registers */
+ u_long md_flags;
+ struct trapframe *md_tf; /* trap/syscall registers */
struct pcb *md_pcbpaddr; /* phys addr of the pcb */
+ struct mdbpt md_sstep[2]; /* two breakpoints for sstep */
};
#define MDP_FPUSED 0x0001 /* Process used the FPU */
+#define MDP_STEP1 0x0002 /* Single step normal */
+#define MDP_STEP2 0x0003 /* Single step branch */
#ifdef _KERNEL
void switch_exit __P((struct proc *));
diff --git a/sys/arch/alpha/include/ptrace.h b/sys/arch/alpha/include/ptrace.h
index a38169df9d0..81040c1cbf1 100644
--- a/sys/arch/alpha/include/ptrace.h
+++ b/sys/arch/alpha/include/ptrace.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ptrace.h,v 1.3 1996/10/30 22:39:24 niklas Exp $ */
+/* $OpenBSD: ptrace.h,v 1.4 2002/03/12 11:58:14 art Exp $ */
/* $NetBSD: ptrace.h,v 1.1 1995/02/13 23:07:51 cgd Exp $ */
/*
@@ -31,11 +31,18 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef __MACHINE_PTRACE_H__
+#define __MACHINE_PTRACE_H__
+
/*
* Alpha-dependent ptrace definitions.
- * Note that PT_STEP is _not_ supported.
*/
#define PT_GETREGS (PT_FIRSTMACH + 0)
#define PT_SETREGS (PT_FIRSTMACH + 1)
#define PT_GETFPREGS (PT_FIRSTMACH + 2)
#define PT_SETFPREGS (PT_FIRSTMACH + 3)
+#define PT_STEP (PT_FIRSTMACH + 4)
+
+#define FIX_SSTEP(p) process_sstep(p, 0)
+
+#endif