Annotation of sys/arch/alpha/alpha/process_machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: process_machdep.c,v 1.11 2005/12/12 19:44:30 miod Exp $ */
! 2: /* $NetBSD: process_machdep.c,v 1.7 1996/07/11 20:14:21 cgd Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1998 Doug Rabson
! 6: * All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: *
! 17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 27: * SUCH DAMAGE.
! 28: */
! 29: /*
! 30: * Copyright (c) 1994 Christopher G. Demetriou
! 31: * All rights reserved.
! 32: *
! 33: * Redistribution and use in source and binary forms, with or without
! 34: * modification, are permitted provided that the following conditions
! 35: * are met:
! 36: * 1. Redistributions of source code must retain the above copyright
! 37: * notice, this list of conditions and the following disclaimer.
! 38: * 2. Redistributions in binary form must reproduce the above copyright
! 39: * notice, this list of conditions and the following disclaimer in the
! 40: * documentation and/or other materials provided with the distribution.
! 41: * 3. All advertising materials mentioning features or use of this software
! 42: * must display the following acknowledgement:
! 43: * This product includes software developed by Christopher G. Demetriou.
! 44: * 4. The name of the author may not be used to endorse or promote products
! 45: * derived from this software without specific prior written permission
! 46: *
! 47: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 48: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 49: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 50: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 51: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 52: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 53: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 54: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 55: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 56: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 57: */
! 58:
! 59: /*
! 60: * This file may seem a bit stylized, but that so that it's easier to port.
! 61: * Functions to be implemented here are:
! 62: *
! 63: * process_read_regs(proc, regs)
! 64: * Get the current user-visible register set from the process
! 65: * and copy it into the regs structure (<machine/reg.h>).
! 66: * The process is stopped at the time read_regs is called.
! 67: *
! 68: * process_write_regs(proc, regs)
! 69: * Update the current register set from the passed in regs
! 70: * structure. Take care to avoid clobbering special CPU
! 71: * registers or privileged bits in the PSL.
! 72: * The process is stopped at the time write_regs is called.
! 73: *
! 74: * process_sstep(proc)
! 75: * Arrange for the process to trap after executing a single instruction.
! 76: *
! 77: * process_set_pc(proc)
! 78: * Set the process's program counter.
! 79: */
! 80:
! 81: #include <sys/param.h>
! 82: #include <sys/systm.h>
! 83: #include <sys/kernel.h>
! 84: #include <sys/proc.h>
! 85: #include <sys/user.h>
! 86: #include <sys/vnode.h>
! 87: #include <sys/ptrace.h>
! 88: #include <machine/reg.h>
! 89: #include <machine/frame.h>
! 90:
! 91: #include <alpha/alpha/db_instruction.h>
! 92:
! 93: #define process_frame(p) ((p)->p_md.md_tf)
! 94: #define process_pcb(p) (&(p)->p_addr->u_pcb)
! 95: #define process_fpframe(p) (&(process_pcb(p)->pcb_fp))
! 96:
! 97: int
! 98: process_read_regs(p, regs)
! 99: struct proc *p;
! 100: struct reg *regs;
! 101: {
! 102:
! 103: frametoreg(process_frame(p), regs);
! 104: regs->r_regs[R_ZERO] = process_frame(p)->tf_regs[FRAME_PC];
! 105: regs->r_regs[R_SP] = process_pcb(p)->pcb_hw.apcb_usp;
! 106: return (0);
! 107: }
! 108:
! 109: int
! 110: process_read_fpregs(p, regs)
! 111: struct proc *p;
! 112: struct fpreg *regs;
! 113: {
! 114:
! 115: if (p == fpcurproc) {
! 116: alpha_pal_wrfen(1);
! 117: savefpstate(process_fpframe(p));
! 118: alpha_pal_wrfen(0);
! 119: }
! 120:
! 121: bcopy(process_fpframe(p), regs, sizeof(struct fpreg));
! 122: return (0);
! 123: }
! 124:
! 125: #ifdef PTRACE
! 126:
! 127: int
! 128: process_write_regs(p, regs)
! 129: struct proc *p;
! 130: struct reg *regs;
! 131: {
! 132:
! 133: regtoframe(regs, process_frame(p));
! 134: process_frame(p)->tf_regs[FRAME_PC] = regs->r_regs[R_ZERO];
! 135: process_pcb(p)->pcb_hw.apcb_usp = regs->r_regs[R_SP];
! 136: return (0);
! 137: }
! 138:
! 139: int
! 140: process_set_pc(p, addr)
! 141: struct proc *p;
! 142: caddr_t addr;
! 143: {
! 144: struct trapframe *frame = process_frame(p);
! 145:
! 146: frame->tf_regs[FRAME_PC] = (u_int64_t)addr;
! 147: return (0);
! 148: }
! 149:
! 150: int
! 151: process_write_fpregs(p, regs)
! 152: struct proc *p;
! 153: struct fpreg *regs;
! 154: {
! 155:
! 156: if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
! 157: fpusave_proc(p, 1);
! 158:
! 159: bcopy(regs, process_fpframe(p), sizeof(struct fpreg));
! 160: return (0);
! 161: }
! 162:
! 163: /*
! 164: * Single stepping infrastructure.
! 165: */
! 166: int ptrace_set_bpt(struct proc *p, struct mdbpt *bpt);
! 167: int ptrace_clear_bpt(struct proc *p, struct mdbpt *bpt);
! 168: int ptrace_read_int(struct proc *, vaddr_t, u_int32_t *);
! 169: int ptrace_write_int(struct proc *, vaddr_t, u_int32_t);
! 170: u_int64_t ptrace_read_register(struct proc *p, int regno);
! 171:
! 172: int
! 173: ptrace_read_int(struct proc *p, vaddr_t addr, u_int32_t *v)
! 174: {
! 175: struct iovec iov;
! 176: struct uio uio;
! 177:
! 178: iov.iov_base = (caddr_t) v;
! 179: iov.iov_len = sizeof(u_int32_t);
! 180: uio.uio_iov = &iov;
! 181: uio.uio_iovcnt = 1;
! 182: uio.uio_offset = (off_t)addr;
! 183: uio.uio_resid = sizeof(u_int32_t);
! 184: uio.uio_segflg = UIO_SYSSPACE;
! 185: uio.uio_rw = UIO_READ;
! 186: uio.uio_procp = p;
! 187: return process_domem(curproc, p, &uio, PT_READ_I);
! 188: }
! 189:
! 190: int
! 191: ptrace_write_int(struct proc *p, vaddr_t addr, u_int32_t v)
! 192: {
! 193: struct iovec iov;
! 194: struct uio uio;
! 195:
! 196: iov.iov_base = (caddr_t) &v;
! 197: iov.iov_len = sizeof(u_int32_t);
! 198: uio.uio_iov = &iov;
! 199: uio.uio_iovcnt = 1;
! 200: uio.uio_offset = (off_t)addr;
! 201: uio.uio_resid = sizeof(u_int32_t);
! 202: uio.uio_segflg = UIO_SYSSPACE;
! 203: uio.uio_rw = UIO_WRITE;
! 204: uio.uio_procp = p;
! 205: return process_domem(curproc, p, &uio, PT_WRITE_I);
! 206: }
! 207:
! 208: u_int64_t
! 209: ptrace_read_register(struct proc *p, int regno)
! 210: {
! 211: static int reg_to_frame[32] = {
! 212: FRAME_V0,
! 213: FRAME_T0,
! 214: FRAME_T1,
! 215: FRAME_T2,
! 216: FRAME_T3,
! 217: FRAME_T4,
! 218: FRAME_T5,
! 219: FRAME_T6,
! 220: FRAME_T7,
! 221:
! 222: FRAME_S0,
! 223: FRAME_S1,
! 224: FRAME_S2,
! 225: FRAME_S3,
! 226: FRAME_S4,
! 227: FRAME_S5,
! 228: FRAME_S6,
! 229:
! 230: FRAME_A0,
! 231: FRAME_A1,
! 232: FRAME_A2,
! 233: FRAME_A3,
! 234: FRAME_A4,
! 235: FRAME_A5,
! 236:
! 237: FRAME_T8,
! 238: FRAME_T9,
! 239: FRAME_T10,
! 240: FRAME_T11,
! 241: FRAME_RA,
! 242: FRAME_T12,
! 243: FRAME_AT,
! 244: FRAME_GP,
! 245: FRAME_SP,
! 246: -1, /* zero */
! 247: };
! 248:
! 249: if (regno == R_ZERO)
! 250: return 0;
! 251:
! 252: return p->p_md.md_tf->tf_regs[reg_to_frame[regno]];
! 253: }
! 254:
! 255: int
! 256: ptrace_clear_bpt(struct proc *p, struct mdbpt *bpt)
! 257: {
! 258: return ptrace_write_int(p, bpt->addr, bpt->contents);
! 259: }
! 260:
! 261: int
! 262: ptrace_set_bpt(struct proc *p, struct mdbpt *bpt)
! 263: {
! 264: int error;
! 265: u_int32_t bpins = 0x00000080;
! 266: error = ptrace_read_int(p, bpt->addr, &bpt->contents);
! 267: if (error)
! 268: return error;
! 269: return ptrace_write_int(p, bpt->addr, bpins);
! 270: }
! 271:
! 272: int
! 273: process_sstep(struct proc *p, int sstep)
! 274: {
! 275: int error;
! 276: vaddr_t pc = p->p_md.md_tf->tf_regs[FRAME_PC];
! 277: alpha_instruction ins;
! 278: vaddr_t addr[2];
! 279: int count = 0;
! 280:
! 281: if (sstep == 0) {
! 282: /* clearing the breakpoint */
! 283: if (p->p_md.md_flags & MDP_STEP2) {
! 284: ptrace_clear_bpt(p, &p->p_md.md_sstep[1]);
! 285: ptrace_clear_bpt(p, &p->p_md.md_sstep[0]);
! 286: p->p_md.md_flags &= ~MDP_STEP2;
! 287: } else if (p->p_md.md_flags & MDP_STEP1) {
! 288: ptrace_clear_bpt(p, &p->p_md.md_sstep[0]);
! 289: p->p_md.md_flags &= ~MDP_STEP1;
! 290: }
! 291: return (0);
! 292: }
! 293: #ifdef DIAGNOSTIC
! 294: if (p->p_md.md_flags & (MDP_STEP1|MDP_STEP2))
! 295: panic("process_sstep: step breakpoints not removed");
! 296: #endif
! 297: error = ptrace_read_int(p, pc, &ins.bits);
! 298: if (error)
! 299: return (error);
! 300:
! 301: switch (ins.branch_format.opcode) {
! 302: case op_j:
! 303: /* Jump: target is register value */
! 304: addr[0] = ptrace_read_register(p, ins.jump_format.rb) & ~3;
! 305: count = 1;
! 306: break;
! 307:
! 308: case op_br:
! 309: case op_fbeq:
! 310: case op_fblt:
! 311: case op_fble:
! 312: case op_bsr:
! 313: case op_fbne:
! 314: case op_fbge:
! 315: case op_fbgt:
! 316: case op_blbc:
! 317: case op_beq:
! 318: case op_blt:
! 319: case op_ble:
! 320: case op_blbs:
! 321: case op_bne:
! 322: case op_bge:
! 323: case op_bgt:
! 324: /* Branch: target is pc+4+4*displacement */
! 325: addr[0] = pc + 4;
! 326: addr[1] = pc + 4 + 4 * ins.branch_format.displacement;
! 327: count = 2;
! 328: break;
! 329:
! 330: default:
! 331: addr[0] = pc + 4;
! 332: count = 1;
! 333: }
! 334:
! 335: if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
! 336: fpusave_proc(p, 0);
! 337: p->p_md.md_sstep[0].addr = addr[0];
! 338: error = ptrace_set_bpt(p, &p->p_md.md_sstep[0]);
! 339: if (error)
! 340: return (error);
! 341: if (count == 2) {
! 342: p->p_md.md_sstep[1].addr = addr[1];
! 343: error = ptrace_set_bpt(p, &p->p_md.md_sstep[1]);
! 344: if (error) {
! 345: ptrace_clear_bpt(p, &p->p_md.md_sstep[0]);
! 346: return (error);
! 347: }
! 348: p->p_md.md_flags |= MDP_STEP2;
! 349: } else
! 350: p->p_md.md_flags |= MDP_STEP1;
! 351:
! 352: return (0);
! 353: }
! 354:
! 355: #endif /* PTRACE */
CVSweb