xref: /csrg-svn/old/adb/adb.vax/machdep.c (revision 36565)
1*36565Sbostic #ifndef lint
2*36565Sbostic static char sccsid[] = "@(#)machdep.c	5.1 (Berkeley) 01/16/89";
3*36565Sbostic #endif
4*36565Sbostic 
5*36565Sbostic /*
6*36565Sbostic  * adb - miscellaneous machine dependent routines.
7*36565Sbostic  */
8*36565Sbostic 
9*36565Sbostic #define	RLOCALS			/* enable alternate $C stack trace */
10*36565Sbostic 
11*36565Sbostic #include "defs.h"
12*36565Sbostic #include "bkpt.h"
13*36565Sbostic #include <machine/pte.h>
14*36565Sbostic #include <machine/frame.h>
15*36565Sbostic #include <machine/reg.h>
16*36565Sbostic #include <machine/vmparam.h>
17*36565Sbostic #include <sys/ptrace.h>
18*36565Sbostic #include <sys/vmmac.h>
19*36565Sbostic #include <stab.h>
20*36565Sbostic 
21*36565Sbostic struct	pte *sbr;
22*36565Sbostic int	slr;
23*36565Sbostic struct	pcb pcb;
24*36565Sbostic int	masterpcbb;
25*36565Sbostic 
26*36565Sbostic /*
27*36565Sbostic  * Activation records.
28*36565Sbostic  */
29*36565Sbostic 
30*36565Sbostic /*
31*36565Sbostic  * Set up a stack frame based on the registers in the core image
32*36565Sbostic  * (or in the kernel core file ... not yet!).
33*36565Sbostic  */
34*36565Sbostic a_init(ap)
35*36565Sbostic 	register struct activation *ap;
36*36565Sbostic {
37*36565Sbostic 
38*36565Sbostic 	ap->a_valid = 1;
39*36565Sbostic 	if (kcore) {
40*36565Sbostic 		ap->a_ap = pcb.pcb_ap;
41*36565Sbostic 		ap->a_fp = pcb.pcb_fp;
42*36565Sbostic 		ap->a_pc = pcb.pcb_pc;
43*36565Sbostic 	} else {
44*36565Sbostic 		ap->a_ap = u.u_ar0[AP];
45*36565Sbostic 		ap->a_fp = u.u_ar0[FP];
46*36565Sbostic 		ap->a_pc = u.u_ar0[PC];
47*36565Sbostic 	}
48*36565Sbostic }
49*36565Sbostic 
50*36565Sbostic /*
51*36565Sbostic  * Back up one stack frame in the call stack.
52*36565Sbostic  * ap points to the activation record from the previous frame.
53*36565Sbostic  * Clear a_valid field if we ran out of frames.
54*36565Sbostic  */
55*36565Sbostic a_back(ap)
56*36565Sbostic 	register struct activation *ap;
57*36565Sbostic {
58*36565Sbostic 	struct frame fr;
59*36565Sbostic 
60*36565Sbostic 	/*
61*36565Sbostic 	 * The magic constants below allow us to read just the part of
62*36565Sbostic 	 * the frame that we need.
63*36565Sbostic 	 */
64*36565Sbostic 	if (adbread(SP_DATA, ap->a_fp + 8, &fr.fr_savap, 12) != 12)
65*36565Sbostic 		ap->a_valid = 0;
66*36565Sbostic 	else {
67*36565Sbostic 		ap->a_ap = fr.fr_savap;
68*36565Sbostic 		ap->a_fp = fr.fr_savfp;
69*36565Sbostic 		ap->a_pc = fr.fr_savpc;
70*36565Sbostic 		if (ap->a_fp == 0)
71*36565Sbostic 			ap->a_valid = 0;
72*36565Sbostic 	}
73*36565Sbostic }
74*36565Sbostic 
75*36565Sbostic /*
76*36565Sbostic  * Evaluate a local symbol (N_LSYM or N_PSYM) using the activation
77*36565Sbostic  * record pointed to by ap.
78*36565Sbostic  */
79*36565Sbostic addr_t
80*36565Sbostic eval_localsym(sp, ap)
81*36565Sbostic 	register struct nlist *sp;
82*36565Sbostic 	struct activation *ap;
83*36565Sbostic {
84*36565Sbostic 	switch (sp->n_type) {
85*36565Sbostic 
86*36565Sbostic 	case N_LSYM:
87*36565Sbostic 		return (ap->a_fp - sp->n_value);	/* ??? */
88*36565Sbostic 
89*36565Sbostic 	case N_PSYM:
90*36565Sbostic 		return (ap->a_ap + sp->n_value);	/* ??? */
91*36565Sbostic 	}
92*36565Sbostic 	panic("eval_localsym");
93*36565Sbostic 	/* NOTREACHED */
94*36565Sbostic }
95*36565Sbostic 
96*36565Sbostic 
97*36565Sbostic /* true iff address a is in instruction space */
98*36565Sbostic #define	ispace(a) ((a) < txtmap.m1.e)
99*36565Sbostic 
100*36565Sbostic /*
101*36565Sbostic  * Delete a (single) breakpoint.  Return 0 on success.
102*36565Sbostic  */
103*36565Sbostic int
104*36565Sbostic clr_bpt(b)
105*36565Sbostic 	struct bkpt *b;
106*36565Sbostic {
107*36565Sbostic 	addr_t a = b->loc;
108*36565Sbostic 
109*36565Sbostic 	return (adbwrite(ispace(a) ? SP_INSTR : SP_DATA, a, &b->ins, 1) != 1);
110*36565Sbostic }
111*36565Sbostic 
112*36565Sbostic /*
113*36565Sbostic  * Set a (single) breakpoint.  Return 0 on success.
114*36565Sbostic  */
115*36565Sbostic set_bpt(b)
116*36565Sbostic 	struct bkpt *b;
117*36565Sbostic {
118*36565Sbostic 	addr_t a = b->loc;
119*36565Sbostic 	int space;
120*36565Sbostic 	char bpt = 0x03;		/* breakpoint instruction */
121*36565Sbostic 
122*36565Sbostic 	space = ispace(a) ? SP_INSTR : SP_DATA;
123*36565Sbostic 	return (adbread(space, a, &b->ins, 1) != 1 ||
124*36565Sbostic 		adbwrite(space, a, &bpt, 1) != 1);
125*36565Sbostic }
126*36565Sbostic 
127*36565Sbostic /*
128*36565Sbostic  * Check a float for `correctness' (reserved patterns, etc).  Return
129*36565Sbostic  * a pointer to a character string to be printed instead of the float,
130*36565Sbostic  * or NULL to print the float as-is.
131*36565Sbostic  *
132*36565Sbostic  * The string returned, if any, should be no longer than 16 characters.
133*36565Sbostic  *
134*36565Sbostic  * On the VAX, we can simply check the first two bytes.  Byte zero
135*36565Sbostic  * contains one bit of the exponent, and byte 1 has the remaining 7
136*36565Sbostic  * exponent bits and the sign bit.  If the sign bit is set and the
137*36565Sbostic  * exponent is zero, the value is reserved.
138*36565Sbostic  */
139*36565Sbostic /* ARGSUSED */
140*36565Sbostic char *
141*36565Sbostic checkfloat(fp, isdouble)
142*36565Sbostic 	caddr_t fp;
143*36565Sbostic 	int isdouble;
144*36565Sbostic {
145*36565Sbostic 
146*36565Sbostic 	return ((*(short *)fp & 0xff80) == 0x8000 ? "(reserved oprnd)" : NULL);
147*36565Sbostic }
148*36565Sbostic 
149*36565Sbostic /*
150*36565Sbostic  * Convert a value in `expr_t' format to float or double.
151*36565Sbostic  */
152*36565Sbostic etofloat(e, fp, isdouble)
153*36565Sbostic 	expr_t e;
154*36565Sbostic 	caddr_t fp;
155*36565Sbostic 	int isdouble;
156*36565Sbostic {
157*36565Sbostic 
158*36565Sbostic 	if (isdouble)
159*36565Sbostic 		((int *)fp)[1] = 0;
160*36565Sbostic 	*(int *)fp = e;
161*36565Sbostic }
162*36565Sbostic 
163*36565Sbostic mch_init()
164*36565Sbostic {
165*36565Sbostic 
166*36565Sbostic 	mkioptab();
167*36565Sbostic }
168*36565Sbostic 
169*36565Sbostic /* quietly read object obj from address addr */
170*36565Sbostic #define	GET(obj, addr)	(void) adbread(SP_DATA, addr, &(obj), sizeof(obj))
171*36565Sbostic 
172*36565Sbostic /* set `current process' pcb */
173*36565Sbostic setpcb(addr)
174*36565Sbostic 	addr_t addr;
175*36565Sbostic {
176*36565Sbostic 	int pte;
177*36565Sbostic 
178*36565Sbostic 	GET(pte, addr);
179*36565Sbostic 	masterpcbb = (pte & PG_PFNUM) * NBPG;
180*36565Sbostic }
181*36565Sbostic 
182*36565Sbostic getpcb()
183*36565Sbostic {
184*36565Sbostic 
185*36565Sbostic 	/* maybe use adbread() here ... */
186*36565Sbostic 	(void) readcore((off_t)masterpcbb & ~KERNBASE,
187*36565Sbostic 		(char *)&pcb, sizeof(struct pcb));
188*36565Sbostic 	pcb.pcb_p0lr &= ~AST_CLR;
189*36565Sbostic 	adbprintf("p0br %R p0lr %R p1br %R p1lr %R\n",
190*36565Sbostic 	    pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr);
191*36565Sbostic }
192*36565Sbostic 
193*36565Sbostic /*
194*36565Sbostic  * Convert a kernel virtual address to a physical address,
195*36565Sbostic  * a la the VAX hardware.  Set *err if the resulting address
196*36565Sbostic  * is invalid.
197*36565Sbostic  */
198*36565Sbostic addr_t
199*36565Sbostic vtophys(addr, err)
200*36565Sbostic 	addr_t addr;
201*36565Sbostic 	char **err;
202*36565Sbostic {
203*36565Sbostic 	register unsigned v = btop(addr & ~0xc0000000);
204*36565Sbostic 	register addr_t pteaddr;
205*36565Sbostic 	struct pte pte;
206*36565Sbostic #define issys(a) ((a) & 0x80000000)
207*36565Sbostic #define isp1(a) ((a) & 0x40000000)
208*36565Sbostic 
209*36565Sbostic 	if (issys(addr)) {
210*36565Sbostic 		/* system space: get system pte */
211*36565Sbostic 		if (isp1(addr) || v >= slr) {
212*36565Sbostic 	oor:
213*36565Sbostic 			*err = "address out of segment";
214*36565Sbostic 			return (0);
215*36565Sbostic 		}
216*36565Sbostic 		pteaddr = (addr_t)(sbr + v) & ~0x80000000;
217*36565Sbostic 	} else {
218*36565Sbostic 		if (isp1(addr)) {
219*36565Sbostic 			/* P1 space: must not be in shadow region */
220*36565Sbostic 			if (v < pcb.pcb_p1lr)
221*36565Sbostic 				goto oor;
222*36565Sbostic 			pteaddr = (addr_t)(pcb.pcb_p1br + v);
223*36565Sbostic 		} else {
224*36565Sbostic 			/* P0 space: must not be off end of region */
225*36565Sbostic 			if (v >= pcb.pcb_p0lr)
226*36565Sbostic 				goto oor;
227*36565Sbostic 			pteaddr = (addr_t)(pcb.pcb_p0br + v);
228*36565Sbostic 		}
229*36565Sbostic 		if (!issys(pteaddr) || isp1(pteaddr)) {
230*36565Sbostic 			*err = "bad p0br or p1br in pcb";
231*36565Sbostic 			return (0);
232*36565Sbostic 		}
233*36565Sbostic 		/* in either case, find system pte by recursing */
234*36565Sbostic 		pteaddr = vtophys(pteaddr, err);
235*36565Sbostic 		if (*err)
236*36565Sbostic 			return (0);
237*36565Sbostic 	}
238*36565Sbostic 
239*36565Sbostic 	/*
240*36565Sbostic 	 * Read system pte.  If valid or reclaimable,
241*36565Sbostic 	 * physical address is combination of its page number and
242*36565Sbostic 	 * the page offset of the original address.
243*36565Sbostic 	 */
244*36565Sbostic 	if (readcore((off_t)pteaddr, (caddr_t)&pte, 4) != 4) {
245*36565Sbostic 		*err = "page table botch";
246*36565Sbostic 		return (0);
247*36565Sbostic 	}
248*36565Sbostic 	/* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */
249*36565Sbostic 	if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) {
250*36565Sbostic 		*err = "page not valid/reclaimable";
251*36565Sbostic 		return (0);
252*36565Sbostic 	}
253*36565Sbostic 	return ((addr_t)(ptob(pte.pg_pfnum) + (addr & PGOFSET)));
254*36565Sbostic }
255*36565Sbostic 
256*36565Sbostic /*
257*36565Sbostic  * Print a stack trace ($c, $C).  Trace backwards through nback
258*36565Sbostic  * frames; if locals is set, print local variables.
259*36565Sbostic  */
260*36565Sbostic printstack(locals, nback)
261*36565Sbostic 	int locals, nback;
262*36565Sbostic {
263*36565Sbostic 	register int i;
264*36565Sbostic 	register addr_t a;
265*36565Sbostic 	struct nlist *sym;
266*36565Sbostic 	char *s;
267*36565Sbostic /*	addr_t callpc;		/* pc that called this frame */
268*36565Sbostic 	struct activation cur;	/* this frame itself */
269*36565Sbostic 	struct frame fr;	/* the frame above this frame */
270*36565Sbostic 	u_char narg;		/* number of int-args to this frame */
271*36565Sbostic 	addr_t dummy;		/* a variable to scribble on */
272*36565Sbostic #define	UNKNOWN	-1
273*36565Sbostic 
274*36565Sbostic #ifdef RLOCALS
275*36565Sbostic 	/* if locals variables are broken, use an alternate strategy */
276*36565Sbostic 	register int r;
277*36565Sbostic 	addr_t sp, prev_sp;
278*36565Sbostic 	int regs[12];
279*36565Sbostic 	static char unknown[] = "<unknown>";
280*36565Sbostic #endif
281*36565Sbostic 
282*36565Sbostic 	/* fr_savpc==UNKNOWN implies fr is invalid */
283*36565Sbostic 	fr.fr_savpc = UNKNOWN;
284*36565Sbostic 
285*36565Sbostic #ifdef RLOCALS
286*36565Sbostic 	/* grab registers */
287*36565Sbostic 	bcopy((caddr_t)(kcore ? &pcb.pcb_r0 : &u.u_ar0[R0]), (caddr_t)regs,
288*36565Sbostic 		sizeof(regs));
289*36565Sbostic #endif
290*36565Sbostic 
291*36565Sbostic 	/* set up the current stack frame */
292*36565Sbostic 	if (gavedot) {
293*36565Sbostic 		GET(fr, cur.a_fp = dot);
294*36565Sbostic 		checkerr();
295*36565Sbostic 		if (fr.fr_s) {	/* was a `calls'; can figure out ap */
296*36565Sbostic 			cur.a_ap = cur.a_fp + sizeof(fr) + fr.fr_spa;
297*36565Sbostic 			for (i = fr.fr_mask; i != 0; i >>= 1)
298*36565Sbostic 				if (i & 1)
299*36565Sbostic 					cur.a_ap += 4;
300*36565Sbostic 		} else		/* `callg': cannot find ap */
301*36565Sbostic 			cur.a_ap = UNKNOWN;
302*36565Sbostic 		cur.a_pc = UNKNOWN;
303*36565Sbostic #ifdef RLOCALS
304*36565Sbostic 		sp = UNKNOWN;
305*36565Sbostic #endif
306*36565Sbostic 	} else if (kcore) {
307*36565Sbostic 		cur.a_ap = pcb.pcb_ap;
308*36565Sbostic 		cur.a_fp = pcb.pcb_fp;
309*36565Sbostic 		cur.a_pc = pcb.pcb_pc;
310*36565Sbostic #ifdef RLOCALS
311*36565Sbostic 		sp = pcb.pcb_ksp;
312*36565Sbostic #endif
313*36565Sbostic 	} else {
314*36565Sbostic 		cur.a_ap = u.u_ar0[AP];
315*36565Sbostic 		cur.a_fp = u.u_ar0[FP];
316*36565Sbostic 		cur.a_pc = u.u_ar0[PC];
317*36565Sbostic #ifdef RLOCALS
318*36565Sbostic 		sp = u.u_ar0[SP];
319*36565Sbostic #endif
320*36565Sbostic 	}
321*36565Sbostic 
322*36565Sbostic 	/* now back up through the stack */
323*36565Sbostic 	while (nback--) {
324*36565Sbostic 		if (fr.fr_savpc == UNKNOWN)
325*36565Sbostic 			GET(fr, cur.a_fp);
326*36565Sbostic 
327*36565Sbostic 		/* where are we? ... if u. area, signal trampoline code */
328*36565Sbostic 		if ((int)cur.a_pc >= USRSTACK) {
329*36565Sbostic /*			GET(callpc, cur.a_fp + 92);	/* XXX magic 92 */
330*36565Sbostic 			s = "sigtramp";
331*36565Sbostic 		} else {
332*36565Sbostic /*			callpc = fr.fr_savpc; */
333*36565Sbostic 			if (cur.a_pc != UNKNOWN &&
334*36565Sbostic 			    (sym = findsym(cur.a_pc, SP_INSTR, &dummy)) != 0) {
335*36565Sbostic 				s = sym->n_un.n_name;
336*36565Sbostic 				if (eqstr(s, "start")) {
337*36565Sbostic 					errflag = NULL;
338*36565Sbostic 					break;
339*36565Sbostic 				}
340*36565Sbostic 			} else
341*36565Sbostic 				s = "?";
342*36565Sbostic 		}
343*36565Sbostic 		adbprintf("%s(", s);
344*36565Sbostic 		if ((a = cur.a_ap) != UNKNOWN) {
345*36565Sbostic 			GET(narg, a);
346*36565Sbostic 			for (i = narg; i;)
347*36565Sbostic 				prfrom(a += 4, --i ? ',' : 0);
348*36565Sbostic 		}
349*36565Sbostic 		printc(')');
350*36565Sbostic 		if (cur.a_pc != UNKNOWN) {
351*36565Sbostic 			prints(" at ");
352*36565Sbostic 			psymoff("%R", cur.a_pc, SP_INSTR, -(addr_t)1, "");
353*36565Sbostic 		}
354*36565Sbostic 		printc('\n');
355*36565Sbostic 
356*36565Sbostic 		/* local variables */
357*36565Sbostic 		if (locals) {
358*36565Sbostic #ifdef busted
359*36565Sbostic 			if (cur.a_pc != UNKNOWN) {
360*36565Sbostic 				sym = findsym(cur.a_pc, SP_INSTR, &dummy);
361*36565Sbostic 				while ((sym = nextlocal(sym)) != NULL) {
362*36565Sbostic 					adbprintf("%8t");
363*36565Sbostic 					printlsym(sym->n_un.n_name);
364*36565Sbostic 					adbprintf(":%12t");
365*36565Sbostic 					prfrom(eval_localsym(sym, &cur), '\n');
366*36565Sbostic 				}
367*36565Sbostic 			}
368*36565Sbostic #endif
369*36565Sbostic #ifdef RLOCALS
370*36565Sbostic 			adbprintf("\
371*36565Sbostic fp: 516tap: %?s%?R%32tsp:  %?s%?R%48tpc:  %?s%?R\n\
372*36565Sbostic r0: 516tr1: 532tr2:  548tr3:  %R\n\
373*36565Sbostic r4: 516tr5: 532tr6:  548tr7:  %R\n\
374*36565Sbostic r8: 516tr9: 532tr10: 548tr11: %R\n",
375*36565Sbostic #define q(s) s == UNKNOWN, unknown, s != UNKNOWN, s
376*36565Sbostic 			    cur.a_fp, q(cur.a_ap), q(sp), q(cur.a_pc),
377*36565Sbostic #undef q
378*36565Sbostic 			    regs[0], regs[1], regs[2], regs[3],
379*36565Sbostic 			    regs[4], regs[5], regs[6], regs[7],
380*36565Sbostic 			    regs[8], regs[9], regs[10], regs[11]);
381*36565Sbostic 
382*36565Sbostic 			/* update registers, and find previous frame's sp */
383*36565Sbostic 			a = cur.a_fp + 16;
384*36565Sbostic 			for (r = 0, i = fr.fr_mask; i != 0; r++, i >>= 1)
385*36565Sbostic 				if (i & 1)
386*36565Sbostic 					GET(regs[r], a += 4);
387*36565Sbostic 			a += fr.fr_spa;
388*36565Sbostic 			if (fr.fr_s)
389*36565Sbostic 				a += narg * 4;
390*36565Sbostic 			prev_sp = a;
391*36565Sbostic 
392*36565Sbostic 			/* now print automatics */
393*36565Sbostic 			if (sp != UNKNOWN) {
394*36565Sbostic #define	MAXPRINT 30		/* max # words to print */
395*36565Sbostic 				/* XXX should be settable */
396*36565Sbostic 				i = (cur.a_fp - sp) >> 2;
397*36565Sbostic 				if (i > MAXPRINT)
398*36565Sbostic 					i = MAXPRINT;
399*36565Sbostic 				for (a = cur.a_fp; --i >= 0;) {
400*36565Sbostic 					a -= 4;
401*36565Sbostic 					adbprintf("%R: %V(fp):%24t",
402*36565Sbostic 						a, a - cur.a_fp);
403*36565Sbostic 					prfrom(a, '\n');
404*36565Sbostic 				}
405*36565Sbostic 				if (a > sp)
406*36565Sbostic 					adbprintf("\
407*36565Sbostic %R: %V(fp) .. %R: %V(fp) not displayed\n",
408*36565Sbostic 						a, a - cur.a_fp,
409*36565Sbostic 						sp, sp - cur.a_fp);
410*36565Sbostic 			}
411*36565Sbostic #endif /* RLOCALS */
412*36565Sbostic 		}
413*36565Sbostic 
414*36565Sbostic 		errflag = NULL;		/* clobber any read errors */
415*36565Sbostic 
416*36565Sbostic 		/* back up one frame */
417*36565Sbostic 		if (fr.fr_savfp == 0)
418*36565Sbostic 			break;
419*36565Sbostic 		cur.a_ap = fr.fr_savap;
420*36565Sbostic 		cur.a_fp = fr.fr_savfp;
421*36565Sbostic #ifdef RLOCALS
422*36565Sbostic 		sp = prev_sp;
423*36565Sbostic #endif
424*36565Sbostic 		cur.a_pc = fr.fr_savpc;
425*36565Sbostic 		fr.fr_savpc = UNKNOWN;	/* until we read it again */
426*36565Sbostic 
427*36565Sbostic 		if (!gavedot && !INSTACK(cur.a_fp) && !kcore)
428*36565Sbostic 			break;
429*36565Sbostic 
430*36565Sbostic 		/* make sure we returned somewhere... */
431*36565Sbostic 		(void) adbread(kcore ? SP_DATA : SP_INSTR, cur.a_pc, &dummy, 1);
432*36565Sbostic 		checkerr();
433*36565Sbostic 	}
434*36565Sbostic }
435*36565Sbostic 
436*36565Sbostic /*
437*36565Sbostic  * Register offset to u. pointer, and register offset to ptrace value
438*36565Sbostic  */
439*36565Sbostic #define	otoua(o) \
440*36565Sbostic 	((int *)(((o) < 0 ? (int)u.u_ar0 : (int)&u.u_pcb) + (o)))
441*36565Sbostic #define	otopt(o) \
442*36565Sbostic 	((int *)((o) < 0 ? (o) + ctob(UPAGES) : (o)))
443*36565Sbostic 
444*36565Sbostic /*
445*36565Sbostic  * Return the value of some register.
446*36565Sbostic  */
447*36565Sbostic expr_t
448*36565Sbostic getreg(reg)
449*36565Sbostic 	register struct reglist *reg;
450*36565Sbostic {
451*36565Sbostic 
452*36565Sbostic 	return (kcore ? *reg->r_pcbaddr : *otoua(reg->r_offset));
453*36565Sbostic }
454*36565Sbostic 
455*36565Sbostic 
456*36565Sbostic /*
457*36565Sbostic  * Set the value of some register.  Return 0 if all goes well.
458*36565Sbostic  */
459*36565Sbostic setreg(reg, val)
460*36565Sbostic 	register struct reglist *reg;
461*36565Sbostic 	expr_t val;
462*36565Sbostic {
463*36565Sbostic 
464*36565Sbostic 	if (kcore)
465*36565Sbostic 		*reg->r_pcbaddr = val;
466*36565Sbostic 	else {
467*36565Sbostic 		*otoua(reg->r_offset) = val;
468*36565Sbostic 		if (pid) {
469*36565Sbostic 			errno = 0;
470*36565Sbostic 			if (ptrace(PT_WRITE_U, pid, otopt(reg->r_offset),
471*36565Sbostic 					(int)val) == -1 && errno)
472*36565Sbostic 				return (-1);
473*36565Sbostic 		}
474*36565Sbostic 	}
475*36565Sbostic 	return (0);
476*36565Sbostic }
477*36565Sbostic 
478*36565Sbostic /*
479*36565Sbostic  * Read registers from current process.
480*36565Sbostic  */
481*36565Sbostic readregs()
482*36565Sbostic {
483*36565Sbostic 	register struct reglist *reg;
484*36565Sbostic 	extern struct reglist reglist[];
485*36565Sbostic 
486*36565Sbostic 	for (reg = reglist; reg->r_name != NULL; reg++)
487*36565Sbostic 		*otoua(reg->r_offset) =
488*36565Sbostic 			ptrace(PT_READ_U, pid, otopt(reg->r_offset), 0);
489*36565Sbostic }
490*36565Sbostic 
491*36565Sbostic addr_t
492*36565Sbostic getpc()
493*36565Sbostic {
494*36565Sbostic 
495*36565Sbostic 	return (u.u_ar0[PC]);
496*36565Sbostic }
497*36565Sbostic 
498*36565Sbostic setpc(where)
499*36565Sbostic 	addr_t where;
500*36565Sbostic {
501*36565Sbostic 
502*36565Sbostic 	u.u_ar0[PC] = where;
503*36565Sbostic }
504*36565Sbostic 
505*36565Sbostic /*
506*36565Sbostic  * udot returns true if u.u_pcb appears correct.  More extensive
507*36565Sbostic  * checking is possible....
508*36565Sbostic  */
509*36565Sbostic udot()
510*36565Sbostic {
511*36565Sbostic 
512*36565Sbostic 	/* user stack should be in stack segment */
513*36565Sbostic 	if (!INSTACK(u.u_pcb.pcb_usp))
514*36565Sbostic 		return (0);
515*36565Sbostic 	/* kernel stack should be in u. area */
516*36565Sbostic 	if (u.u_pcb.pcb_ksp < USRSTACK)
517*36565Sbostic 		return (0);
518*36565Sbostic 	/* looks good to us... */
519*36565Sbostic 	return (1);
520*36565Sbostic }
521*36565Sbostic 
522*36565Sbostic sigprint()
523*36565Sbostic {
524*36565Sbostic 	extern char *sys_siglist[];
525*36565Sbostic 	extern char *illinames[], *fpenames[];
526*36565Sbostic 	extern int nillinames, nfpenames;
527*36565Sbostic 
528*36565Sbostic 	if ((u_int)signo - 1 < NSIG - 1)
529*36565Sbostic 		prints(sys_siglist[signo]);
530*36565Sbostic 	switch (signo) {
531*36565Sbostic 
532*36565Sbostic 	case SIGFPE:
533*36565Sbostic 		if ((u_int)sigcode < nfpenames)
534*36565Sbostic 			prints(fpenames[sigcode]);
535*36565Sbostic 		break;
536*36565Sbostic 
537*36565Sbostic 	case SIGILL:
538*36565Sbostic 		if ((u_int)sigcode < nillinames)
539*36565Sbostic 			prints(illinames[sigcode]);
540*36565Sbostic 		break;
541*36565Sbostic 	}
542*36565Sbostic }
543