xref: /csrg-svn/old/adb/adb.vax/machdep.c (revision 39222)
136565Sbostic #ifndef lint
2*39222Storek static char sccsid[] = "@(#)machdep.c	5.3 (Berkeley) 09/26/89";
336565Sbostic #endif
436565Sbostic 
536565Sbostic /*
636565Sbostic  * adb - miscellaneous machine dependent routines.
736565Sbostic  */
836565Sbostic 
936565Sbostic #define	RLOCALS			/* enable alternate $C stack trace */
1036565Sbostic 
1136565Sbostic #include "defs.h"
1236565Sbostic #include "bkpt.h"
1336565Sbostic #include <machine/pte.h>
1436565Sbostic #include <machine/frame.h>
1536565Sbostic #include <machine/reg.h>
1636565Sbostic #include <machine/vmparam.h>
1736565Sbostic #include <sys/ptrace.h>
1836565Sbostic #include <sys/vmmac.h>
1936565Sbostic #include <stab.h>
2036565Sbostic 
2136565Sbostic struct	pte *sbr;
2236565Sbostic int	slr;
2336565Sbostic struct	pcb pcb;
2436565Sbostic int	masterpcbb;
2536565Sbostic 
2636565Sbostic /*
2736565Sbostic  * Activation records.
2836565Sbostic  */
2936565Sbostic 
3036565Sbostic /*
3136565Sbostic  * Set up a stack frame based on the registers in the core image
3236565Sbostic  * (or in the kernel core file ... not yet!).
3336565Sbostic  */
3436565Sbostic a_init(ap)
3536565Sbostic 	register struct activation *ap;
3636565Sbostic {
3736565Sbostic 
3836565Sbostic 	ap->a_valid = 1;
3936565Sbostic 	if (kcore) {
4036565Sbostic 		ap->a_ap = pcb.pcb_ap;
4136565Sbostic 		ap->a_fp = pcb.pcb_fp;
4236565Sbostic 		ap->a_pc = pcb.pcb_pc;
4336565Sbostic 	} else {
4436565Sbostic 		ap->a_ap = u.u_ar0[AP];
4536565Sbostic 		ap->a_fp = u.u_ar0[FP];
4636565Sbostic 		ap->a_pc = u.u_ar0[PC];
4736565Sbostic 	}
4836565Sbostic }
4936565Sbostic 
5036565Sbostic /*
5136565Sbostic  * Back up one stack frame in the call stack.
5236565Sbostic  * ap points to the activation record from the previous frame.
5336565Sbostic  * Clear a_valid field if we ran out of frames.
5436565Sbostic  */
5536565Sbostic a_back(ap)
5636565Sbostic 	register struct activation *ap;
5736565Sbostic {
5836565Sbostic 	struct frame fr;
5936565Sbostic 
6036565Sbostic 	/*
6136565Sbostic 	 * The magic constants below allow us to read just the part of
6236565Sbostic 	 * the frame that we need.
6336565Sbostic 	 */
6436565Sbostic 	if (adbread(SP_DATA, ap->a_fp + 8, &fr.fr_savap, 12) != 12)
6536565Sbostic 		ap->a_valid = 0;
6636565Sbostic 	else {
6736565Sbostic 		ap->a_ap = fr.fr_savap;
6836565Sbostic 		ap->a_fp = fr.fr_savfp;
6936565Sbostic 		ap->a_pc = fr.fr_savpc;
7036565Sbostic 		if (ap->a_fp == 0)
7136565Sbostic 			ap->a_valid = 0;
7236565Sbostic 	}
7336565Sbostic }
7436565Sbostic 
7536565Sbostic /*
7636565Sbostic  * Evaluate a local symbol (N_LSYM or N_PSYM) using the activation
7736565Sbostic  * record pointed to by ap.
7836565Sbostic  */
7936565Sbostic addr_t
8036565Sbostic eval_localsym(sp, ap)
8136565Sbostic 	register struct nlist *sp;
8236565Sbostic 	struct activation *ap;
8336565Sbostic {
8436565Sbostic 	switch (sp->n_type) {
8536565Sbostic 
8636565Sbostic 	case N_LSYM:
8736565Sbostic 		return (ap->a_fp - sp->n_value);	/* ??? */
8836565Sbostic 
8936565Sbostic 	case N_PSYM:
9036565Sbostic 		return (ap->a_ap + sp->n_value);	/* ??? */
9136565Sbostic 	}
9236565Sbostic 	panic("eval_localsym");
9336565Sbostic 	/* NOTREACHED */
9436565Sbostic }
9536565Sbostic 
9636565Sbostic 
9736565Sbostic /* true iff address a is in instruction space */
9836565Sbostic #define	ispace(a) ((a) < txtmap.m1.e)
9936565Sbostic 
10036565Sbostic /*
10136565Sbostic  * Delete a (single) breakpoint.  Return 0 on success.
10236565Sbostic  */
10336565Sbostic int
10436565Sbostic clr_bpt(b)
10536565Sbostic 	struct bkpt *b;
10636565Sbostic {
10736565Sbostic 	addr_t a = b->loc;
10836565Sbostic 
10936565Sbostic 	return (adbwrite(ispace(a) ? SP_INSTR : SP_DATA, a, &b->ins, 1) != 1);
11036565Sbostic }
11136565Sbostic 
11236565Sbostic /*
11336565Sbostic  * Set a (single) breakpoint.  Return 0 on success.
11436565Sbostic  */
11536565Sbostic set_bpt(b)
11636565Sbostic 	struct bkpt *b;
11736565Sbostic {
11836565Sbostic 	addr_t a = b->loc;
11936565Sbostic 	int space;
12036565Sbostic 	char bpt = 0x03;		/* breakpoint instruction */
12136565Sbostic 
12236565Sbostic 	space = ispace(a) ? SP_INSTR : SP_DATA;
12336565Sbostic 	return (adbread(space, a, &b->ins, 1) != 1 ||
12436565Sbostic 		adbwrite(space, a, &bpt, 1) != 1);
12536565Sbostic }
12636565Sbostic 
12736565Sbostic /*
12836565Sbostic  * Check a float for `correctness' (reserved patterns, etc).  Return
12936565Sbostic  * a pointer to a character string to be printed instead of the float,
13036565Sbostic  * or NULL to print the float as-is.
13136565Sbostic  *
13236565Sbostic  * The string returned, if any, should be no longer than 16 characters.
13336565Sbostic  *
13436565Sbostic  * On the VAX, we can simply check the first two bytes.  Byte zero
13536565Sbostic  * contains one bit of the exponent, and byte 1 has the remaining 7
13636565Sbostic  * exponent bits and the sign bit.  If the sign bit is set and the
13736565Sbostic  * exponent is zero, the value is reserved.
13836565Sbostic  */
13936565Sbostic /* ARGSUSED */
14036565Sbostic char *
14136565Sbostic checkfloat(fp, isdouble)
14236565Sbostic 	caddr_t fp;
14336565Sbostic 	int isdouble;
14436565Sbostic {
14536565Sbostic 
14636565Sbostic 	return ((*(short *)fp & 0xff80) == 0x8000 ? "(reserved oprnd)" : NULL);
14736565Sbostic }
14836565Sbostic 
14936565Sbostic /*
15036565Sbostic  * Convert a value in `expr_t' format to float or double.
15136565Sbostic  */
15236565Sbostic etofloat(e, fp, isdouble)
15336565Sbostic 	expr_t e;
15436565Sbostic 	caddr_t fp;
15536565Sbostic 	int isdouble;
15636565Sbostic {
15736565Sbostic 
15836565Sbostic 	if (isdouble)
15936565Sbostic 		((int *)fp)[1] = 0;
16036565Sbostic 	*(int *)fp = e;
16136565Sbostic }
16236565Sbostic 
16336565Sbostic mch_init()
16436565Sbostic {
16536565Sbostic 
16636565Sbostic 	mkioptab();
16736565Sbostic }
16836565Sbostic 
16936565Sbostic /* quietly read object obj from address addr */
17036565Sbostic #define	GET(obj, addr)	(void) adbread(SP_DATA, addr, &(obj), sizeof(obj))
17136565Sbostic 
17236565Sbostic /* set `current process' pcb */
17336565Sbostic setpcb(addr)
17436565Sbostic 	addr_t addr;
17536565Sbostic {
17636565Sbostic 	int pte;
17736565Sbostic 
17836565Sbostic 	GET(pte, addr);
17936565Sbostic 	masterpcbb = (pte & PG_PFNUM) * NBPG;
18036565Sbostic }
18136565Sbostic 
18236565Sbostic getpcb()
18336565Sbostic {
18436565Sbostic 
18536565Sbostic 	/* maybe use adbread() here ... */
18636565Sbostic 	(void) readcore((off_t)masterpcbb & ~KERNBASE,
18736565Sbostic 		(char *)&pcb, sizeof(struct pcb));
18836565Sbostic 	pcb.pcb_p0lr &= ~AST_CLR;
18936565Sbostic 	adbprintf("p0br %R p0lr %R p1br %R p1lr %R\n",
19036565Sbostic 	    pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr);
19136565Sbostic }
19236565Sbostic 
19336565Sbostic /*
19436565Sbostic  * Convert a kernel virtual address to a physical address,
19536565Sbostic  * a la the VAX hardware.  Set *err if the resulting address
19636565Sbostic  * is invalid.
19736565Sbostic  */
19836565Sbostic addr_t
19936565Sbostic vtophys(addr, err)
20036565Sbostic 	addr_t addr;
20136565Sbostic 	char **err;
20236565Sbostic {
20336565Sbostic 	register unsigned v = btop(addr & ~0xc0000000);
20436565Sbostic 	register addr_t pteaddr;
20536565Sbostic 	struct pte pte;
20636565Sbostic #define issys(a) ((a) & 0x80000000)
20736565Sbostic #define isp1(a) ((a) & 0x40000000)
20836565Sbostic 
20936565Sbostic 	if (issys(addr)) {
21036565Sbostic 		/* system space: get system pte */
21136565Sbostic 		if (isp1(addr) || v >= slr) {
21236565Sbostic 	oor:
21336565Sbostic 			*err = "address out of segment";
21436565Sbostic 			return (0);
21536565Sbostic 		}
21636565Sbostic 		pteaddr = (addr_t)(sbr + v) & ~0x80000000;
21736565Sbostic 	} else {
21836565Sbostic 		if (isp1(addr)) {
21936565Sbostic 			/* P1 space: must not be in shadow region */
22036565Sbostic 			if (v < pcb.pcb_p1lr)
22136565Sbostic 				goto oor;
22236565Sbostic 			pteaddr = (addr_t)(pcb.pcb_p1br + v);
22336565Sbostic 		} else {
22436565Sbostic 			/* P0 space: must not be off end of region */
22536565Sbostic 			if (v >= pcb.pcb_p0lr)
22636565Sbostic 				goto oor;
22736565Sbostic 			pteaddr = (addr_t)(pcb.pcb_p0br + v);
22836565Sbostic 		}
22936565Sbostic 		if (!issys(pteaddr) || isp1(pteaddr)) {
23036565Sbostic 			*err = "bad p0br or p1br in pcb";
23136565Sbostic 			return (0);
23236565Sbostic 		}
23336565Sbostic 		/* in either case, find system pte by recursing */
23436565Sbostic 		pteaddr = vtophys(pteaddr, err);
23536565Sbostic 		if (*err)
23636565Sbostic 			return (0);
23736565Sbostic 	}
23836565Sbostic 
23936565Sbostic 	/*
24036565Sbostic 	 * Read system pte.  If valid or reclaimable,
24136565Sbostic 	 * physical address is combination of its page number and
24236565Sbostic 	 * the page offset of the original address.
24336565Sbostic 	 */
24436565Sbostic 	if (readcore((off_t)pteaddr, (caddr_t)&pte, 4) != 4) {
24536565Sbostic 		*err = "page table botch";
24636565Sbostic 		return (0);
24736565Sbostic 	}
24836565Sbostic 	/* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */
24936565Sbostic 	if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) {
25036565Sbostic 		*err = "page not valid/reclaimable";
25136565Sbostic 		return (0);
25236565Sbostic 	}
25336565Sbostic 	return ((addr_t)(ptob(pte.pg_pfnum) + (addr & PGOFSET)));
25436565Sbostic }
25536565Sbostic 
25636565Sbostic /*
25736565Sbostic  * Print a stack trace ($c, $C).  Trace backwards through nback
25836565Sbostic  * frames; if locals is set, print local variables.
25936565Sbostic  */
26036565Sbostic printstack(locals, nback)
26136565Sbostic 	int locals, nback;
26236565Sbostic {
26336565Sbostic 	register int i;
26436565Sbostic 	register addr_t a;
26536565Sbostic 	struct nlist *sym;
26636565Sbostic 	char *s;
26736565Sbostic /*	addr_t callpc;		/* pc that called this frame */
26836565Sbostic 	struct activation cur;	/* this frame itself */
26936565Sbostic 	struct frame fr;	/* the frame above this frame */
27036565Sbostic 	u_char narg;		/* number of int-args to this frame */
27136565Sbostic 	addr_t dummy;		/* a variable to scribble on */
27236565Sbostic #define	UNKNOWN	-1
27336565Sbostic 
27436565Sbostic #ifdef RLOCALS
27536565Sbostic 	/* if locals variables are broken, use an alternate strategy */
27636565Sbostic 	register int r;
27736565Sbostic 	addr_t sp, prev_sp;
27836565Sbostic 	int regs[12];
27936565Sbostic 	static char unknown[] = "<unknown>";
28036565Sbostic #endif
28136565Sbostic 
28236565Sbostic 	/* fr_savpc==UNKNOWN implies fr is invalid */
28336565Sbostic 	fr.fr_savpc = UNKNOWN;
28436565Sbostic 
28536565Sbostic #ifdef RLOCALS
28636565Sbostic 	/* grab registers */
28736565Sbostic 	bcopy((caddr_t)(kcore ? &pcb.pcb_r0 : &u.u_ar0[R0]), (caddr_t)regs,
28836565Sbostic 		sizeof(regs));
28936565Sbostic #endif
29036565Sbostic 
29136565Sbostic 	/* set up the current stack frame */
29236565Sbostic 	if (gavedot) {
29336565Sbostic 		GET(fr, cur.a_fp = dot);
29436565Sbostic 		checkerr();
29536565Sbostic 		if (fr.fr_s) {	/* was a `calls'; can figure out ap */
29636565Sbostic 			cur.a_ap = cur.a_fp + sizeof(fr) + fr.fr_spa;
29736565Sbostic 			for (i = fr.fr_mask; i != 0; i >>= 1)
29836565Sbostic 				if (i & 1)
29936565Sbostic 					cur.a_ap += 4;
30036565Sbostic 		} else		/* `callg': cannot find ap */
30136565Sbostic 			cur.a_ap = UNKNOWN;
30236565Sbostic 		cur.a_pc = UNKNOWN;
30336565Sbostic #ifdef RLOCALS
30436565Sbostic 		sp = UNKNOWN;
30536565Sbostic #endif
30636565Sbostic 	} else if (kcore) {
30736565Sbostic 		cur.a_ap = pcb.pcb_ap;
30836565Sbostic 		cur.a_fp = pcb.pcb_fp;
30936565Sbostic 		cur.a_pc = pcb.pcb_pc;
31036565Sbostic #ifdef RLOCALS
31136565Sbostic 		sp = pcb.pcb_ksp;
31236565Sbostic #endif
31336565Sbostic 	} else {
31436565Sbostic 		cur.a_ap = u.u_ar0[AP];
31536565Sbostic 		cur.a_fp = u.u_ar0[FP];
31636565Sbostic 		cur.a_pc = u.u_ar0[PC];
31736565Sbostic #ifdef RLOCALS
31836565Sbostic 		sp = u.u_ar0[SP];
31936565Sbostic #endif
32036565Sbostic 	}
32136565Sbostic 
32236565Sbostic 	/* now back up through the stack */
32336565Sbostic 	while (nback--) {
32436565Sbostic 		if (fr.fr_savpc == UNKNOWN)
32536565Sbostic 			GET(fr, cur.a_fp);
32636565Sbostic 
32736565Sbostic 		/* where are we? ... if u. area, signal trampoline code */
32836565Sbostic 		if ((int)cur.a_pc >= USRSTACK) {
32936565Sbostic /*			GET(callpc, cur.a_fp + 92);	/* XXX magic 92 */
33036565Sbostic 			s = "sigtramp";
33136565Sbostic 		} else {
33236565Sbostic /*			callpc = fr.fr_savpc; */
33336565Sbostic 			if (cur.a_pc != UNKNOWN &&
33436565Sbostic 			    (sym = findsym(cur.a_pc, SP_INSTR, &dummy)) != 0) {
33536565Sbostic 				s = sym->n_un.n_name;
33636565Sbostic 				if (eqstr(s, "start")) {
33736565Sbostic 					errflag = NULL;
33836565Sbostic 					break;
33936565Sbostic 				}
34036565Sbostic 			} else
34136565Sbostic 				s = "?";
34236565Sbostic 		}
34336565Sbostic 		adbprintf("%s(", s);
34436565Sbostic 		if ((a = cur.a_ap) != UNKNOWN) {
34536565Sbostic 			GET(narg, a);
346*39222Storek 			for (i = narg > 20 ? 20 : narg; i;)
34736565Sbostic 				prfrom(a += 4, --i ? ',' : 0);
34836565Sbostic 		}
34936565Sbostic 		printc(')');
35036565Sbostic 		if (cur.a_pc != UNKNOWN) {
35136565Sbostic 			prints(" at ");
35236565Sbostic 			psymoff("%R", cur.a_pc, SP_INSTR, -(addr_t)1, "");
35336565Sbostic 		}
35436565Sbostic 		printc('\n');
35536565Sbostic 
35636565Sbostic 		/* local variables */
35736565Sbostic 		if (locals) {
35836565Sbostic #ifdef busted
35936565Sbostic 			if (cur.a_pc != UNKNOWN) {
36036565Sbostic 				sym = findsym(cur.a_pc, SP_INSTR, &dummy);
36136565Sbostic 				while ((sym = nextlocal(sym)) != NULL) {
36236565Sbostic 					adbprintf("%8t");
36336565Sbostic 					printlsym(sym->n_un.n_name);
36436565Sbostic 					adbprintf(":%12t");
36536565Sbostic 					prfrom(eval_localsym(sym, &cur), '\n');
36636565Sbostic 				}
36736565Sbostic 			}
36836565Sbostic #endif
36936565Sbostic #ifdef RLOCALS
37036565Sbostic 			adbprintf("\
37136575Storek fp: %R\%16tap: %?s%?R%32tsp:  %?s%?R%48tpc:  %?s%?R\n\
37236575Storek r0: %R\%16tr1: %R\%32tr2:  %R\%48tr3:  %R\n\
37336575Storek r4: %R\%16tr5: %R\%32tr6:  %R\%48tr7:  %R\n\
37436575Storek r8: %R\%16tr9: %R\%32tr10: %R\%48tr11: %R\n",
37536565Sbostic #define q(s) s == UNKNOWN, unknown, s != UNKNOWN, s
37636565Sbostic 			    cur.a_fp, q(cur.a_ap), q(sp), q(cur.a_pc),
37736565Sbostic #undef q
37836565Sbostic 			    regs[0], regs[1], regs[2], regs[3],
37936565Sbostic 			    regs[4], regs[5], regs[6], regs[7],
38036565Sbostic 			    regs[8], regs[9], regs[10], regs[11]);
38136565Sbostic 
38236565Sbostic 			/* update registers, and find previous frame's sp */
38336565Sbostic 			a = cur.a_fp + 16;
38436565Sbostic 			for (r = 0, i = fr.fr_mask; i != 0; r++, i >>= 1)
38536565Sbostic 				if (i & 1)
38636565Sbostic 					GET(regs[r], a += 4);
38736565Sbostic 			a += fr.fr_spa;
38836565Sbostic 			if (fr.fr_s)
38936565Sbostic 				a += narg * 4;
39036565Sbostic 			prev_sp = a;
39136565Sbostic 
39236565Sbostic 			/* now print automatics */
39336565Sbostic 			if (sp != UNKNOWN) {
39436565Sbostic #define	MAXPRINT 30		/* max # words to print */
39536565Sbostic 				/* XXX should be settable */
39636565Sbostic 				i = (cur.a_fp - sp) >> 2;
39736565Sbostic 				if (i > MAXPRINT)
39836565Sbostic 					i = MAXPRINT;
39936565Sbostic 				for (a = cur.a_fp; --i >= 0;) {
40036565Sbostic 					a -= 4;
40136565Sbostic 					adbprintf("%R: %V(fp):%24t",
40236565Sbostic 						a, a - cur.a_fp);
40336565Sbostic 					prfrom(a, '\n');
40436565Sbostic 				}
40536565Sbostic 				if (a > sp)
40636565Sbostic 					adbprintf("\
40736565Sbostic %R: %V(fp) .. %R: %V(fp) not displayed\n",
40836565Sbostic 						a, a - cur.a_fp,
40936565Sbostic 						sp, sp - cur.a_fp);
41036565Sbostic 			}
41136565Sbostic #endif /* RLOCALS */
41236565Sbostic 		}
41336565Sbostic 
41436565Sbostic 		errflag = NULL;		/* clobber any read errors */
41536565Sbostic 
41636565Sbostic 		/* back up one frame */
41736565Sbostic 		if (fr.fr_savfp == 0)
41836565Sbostic 			break;
41936565Sbostic 		cur.a_ap = fr.fr_savap;
42036565Sbostic 		cur.a_fp = fr.fr_savfp;
42136565Sbostic #ifdef RLOCALS
42236565Sbostic 		sp = prev_sp;
42336565Sbostic #endif
42436565Sbostic 		cur.a_pc = fr.fr_savpc;
42536565Sbostic 		fr.fr_savpc = UNKNOWN;	/* until we read it again */
42636565Sbostic 
42736565Sbostic 		if (!gavedot && !INSTACK(cur.a_fp) && !kcore)
42836565Sbostic 			break;
42936565Sbostic 
43036565Sbostic 		/* make sure we returned somewhere... */
43136565Sbostic 		(void) adbread(kcore ? SP_DATA : SP_INSTR, cur.a_pc, &dummy, 1);
43236565Sbostic 		checkerr();
43336565Sbostic 	}
43436565Sbostic }
43536565Sbostic 
43636565Sbostic /*
43736565Sbostic  * Register offset to u. pointer, and register offset to ptrace value
43836565Sbostic  */
43936565Sbostic #define	otoua(o) \
44036565Sbostic 	((int *)(((o) < 0 ? (int)u.u_ar0 : (int)&u.u_pcb) + (o)))
44136565Sbostic #define	otopt(o) \
44236565Sbostic 	((int *)((o) < 0 ? (o) + ctob(UPAGES) : (o)))
44336565Sbostic 
44436565Sbostic /*
44536565Sbostic  * Return the value of some register.
44636565Sbostic  */
44736565Sbostic expr_t
44836565Sbostic getreg(reg)
44936565Sbostic 	register struct reglist *reg;
45036565Sbostic {
45136565Sbostic 
45236565Sbostic 	return (kcore ? *reg->r_pcbaddr : *otoua(reg->r_offset));
45336565Sbostic }
45436565Sbostic 
45536565Sbostic 
45636565Sbostic /*
45736565Sbostic  * Set the value of some register.  Return 0 if all goes well.
45836565Sbostic  */
45936565Sbostic setreg(reg, val)
46036565Sbostic 	register struct reglist *reg;
46136565Sbostic 	expr_t val;
46236565Sbostic {
46336565Sbostic 
46436565Sbostic 	if (kcore)
46536565Sbostic 		*reg->r_pcbaddr = val;
46636565Sbostic 	else {
46736565Sbostic 		*otoua(reg->r_offset) = val;
46836565Sbostic 		if (pid) {
46936565Sbostic 			errno = 0;
47036565Sbostic 			if (ptrace(PT_WRITE_U, pid, otopt(reg->r_offset),
47136565Sbostic 					(int)val) == -1 && errno)
47236565Sbostic 				return (-1);
47336565Sbostic 		}
47436565Sbostic 	}
47536565Sbostic 	return (0);
47636565Sbostic }
47736565Sbostic 
47836565Sbostic /*
47936565Sbostic  * Read registers from current process.
48036565Sbostic  */
48136565Sbostic readregs()
48236565Sbostic {
48336565Sbostic 	register struct reglist *reg;
48436565Sbostic 	extern struct reglist reglist[];
48536565Sbostic 
48636565Sbostic 	for (reg = reglist; reg->r_name != NULL; reg++)
48736565Sbostic 		*otoua(reg->r_offset) =
48836565Sbostic 			ptrace(PT_READ_U, pid, otopt(reg->r_offset), 0);
48936565Sbostic }
49036565Sbostic 
49136565Sbostic addr_t
49236565Sbostic getpc()
49336565Sbostic {
49436565Sbostic 
49536565Sbostic 	return (u.u_ar0[PC]);
49636565Sbostic }
49736565Sbostic 
49836565Sbostic setpc(where)
49936565Sbostic 	addr_t where;
50036565Sbostic {
50136565Sbostic 
50236565Sbostic 	u.u_ar0[PC] = where;
50336565Sbostic }
50436565Sbostic 
50536565Sbostic /*
50636565Sbostic  * udot returns true if u.u_pcb appears correct.  More extensive
50736565Sbostic  * checking is possible....
50836565Sbostic  */
50936565Sbostic udot()
51036565Sbostic {
51136565Sbostic 
51236565Sbostic 	/* user stack should be in stack segment */
51336565Sbostic 	if (!INSTACK(u.u_pcb.pcb_usp))
51436565Sbostic 		return (0);
51536565Sbostic 	/* kernel stack should be in u. area */
51636565Sbostic 	if (u.u_pcb.pcb_ksp < USRSTACK)
51736565Sbostic 		return (0);
51836565Sbostic 	/* looks good to us... */
51936565Sbostic 	return (1);
52036565Sbostic }
52136565Sbostic 
52236565Sbostic sigprint()
52336565Sbostic {
52436565Sbostic 	extern char *sys_siglist[];
52536565Sbostic 	extern char *illinames[], *fpenames[];
52636565Sbostic 	extern int nillinames, nfpenames;
52736565Sbostic 
52836565Sbostic 	if ((u_int)signo - 1 < NSIG - 1)
52936565Sbostic 		prints(sys_siglist[signo]);
53036565Sbostic 	switch (signo) {
53136565Sbostic 
53236565Sbostic 	case SIGFPE:
53336565Sbostic 		if ((u_int)sigcode < nfpenames)
53436565Sbostic 			prints(fpenames[sigcode]);
53536565Sbostic 		break;
53636565Sbostic 
53736565Sbostic 	case SIGILL:
53836565Sbostic 		if ((u_int)sigcode < nillinames)
53936565Sbostic 			prints(illinames[sigcode]);
54036565Sbostic 		break;
54136565Sbostic 	}
54236565Sbostic }
543