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