Annotation of sys/arch/alpha/alpha/process_machdep.c, Revision 1.1.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