diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2002-03-12 11:58:15 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2002-03-12 11:58:15 +0000 |
commit | 5b79aab6eebe0f7a472f6dca68a6d5c34c8e48e3 (patch) | |
tree | 12f5d15fda057fdb207e251ce9ff7d0ac977db05 | |
parent | 1f81b3a4471284b779fdf18bad08ed80babb2cd9 (diff) |
Emulate ptrace(PT_STEP in software.
More or less directly from FreeBSD.
-rw-r--r-- | sys/arch/alpha/alpha/process_machdep.c | 232 | ||||
-rw-r--r-- | sys/arch/alpha/alpha/trap.c | 7 | ||||
-rw-r--r-- | sys/arch/alpha/include/proc.h | 14 | ||||
-rw-r--r-- | sys/arch/alpha/include/ptrace.h | 11 |
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 |