xref: /original-bsd/old/adb/adb.vax/machdep.c (revision 125ffe57)
1*125ffe57Sbostic /*-
2*125ffe57Sbostic  * Copyright (c) 1991 The Regents of the University of California.
3*125ffe57Sbostic  * All rights reserved.
4*125ffe57Sbostic  *
5*125ffe57Sbostic  * %sccs.include.proprietary.c%
6*125ffe57Sbostic  */
7*125ffe57Sbostic 
819544fcfSbostic #ifndef lint
9*125ffe57Sbostic static char sccsid[] = "@(#)machdep.c	5.4 (Berkeley) 04/04/91";
10*125ffe57Sbostic #endif /* not lint */
1119544fcfSbostic 
1219544fcfSbostic /*
1319544fcfSbostic  * adb - miscellaneous machine dependent routines.
1419544fcfSbostic  */
1519544fcfSbostic 
1619544fcfSbostic #define	RLOCALS			/* enable alternate $C stack trace */
1719544fcfSbostic 
1819544fcfSbostic #include "defs.h"
1919544fcfSbostic #include "bkpt.h"
2019544fcfSbostic #include <machine/pte.h>
2119544fcfSbostic #include <machine/frame.h>
2219544fcfSbostic #include <machine/reg.h>
2319544fcfSbostic #include <machine/vmparam.h>
2419544fcfSbostic #include <sys/ptrace.h>
2519544fcfSbostic #include <sys/vmmac.h>
2619544fcfSbostic #include <stab.h>
2719544fcfSbostic 
2819544fcfSbostic struct	pte *sbr;
2919544fcfSbostic int	slr;
3019544fcfSbostic struct	pcb pcb;
3119544fcfSbostic int	masterpcbb;
3219544fcfSbostic 
3319544fcfSbostic /*
3419544fcfSbostic  * Activation records.
3519544fcfSbostic  */
3619544fcfSbostic 
3719544fcfSbostic /*
3819544fcfSbostic  * Set up a stack frame based on the registers in the core image
3919544fcfSbostic  * (or in the kernel core file ... not yet!).
4019544fcfSbostic  */
a_init(ap)4119544fcfSbostic a_init(ap)
4219544fcfSbostic 	register struct activation *ap;
4319544fcfSbostic {
4419544fcfSbostic 
4519544fcfSbostic 	ap->a_valid = 1;
4619544fcfSbostic 	if (kcore) {
4719544fcfSbostic 		ap->a_ap = pcb.pcb_ap;
4819544fcfSbostic 		ap->a_fp = pcb.pcb_fp;
4919544fcfSbostic 		ap->a_pc = pcb.pcb_pc;
5019544fcfSbostic 	} else {
5119544fcfSbostic 		ap->a_ap = u.u_ar0[AP];
5219544fcfSbostic 		ap->a_fp = u.u_ar0[FP];
5319544fcfSbostic 		ap->a_pc = u.u_ar0[PC];
5419544fcfSbostic 	}
5519544fcfSbostic }
5619544fcfSbostic 
5719544fcfSbostic /*
5819544fcfSbostic  * Back up one stack frame in the call stack.
5919544fcfSbostic  * ap points to the activation record from the previous frame.
6019544fcfSbostic  * Clear a_valid field if we ran out of frames.
6119544fcfSbostic  */
a_back(ap)6219544fcfSbostic a_back(ap)
6319544fcfSbostic 	register struct activation *ap;
6419544fcfSbostic {
6519544fcfSbostic 	struct frame fr;
6619544fcfSbostic 
6719544fcfSbostic 	/*
6819544fcfSbostic 	 * The magic constants below allow us to read just the part of
6919544fcfSbostic 	 * the frame that we need.
7019544fcfSbostic 	 */
7119544fcfSbostic 	if (adbread(SP_DATA, ap->a_fp + 8, &fr.fr_savap, 12) != 12)
7219544fcfSbostic 		ap->a_valid = 0;
7319544fcfSbostic 	else {
7419544fcfSbostic 		ap->a_ap = fr.fr_savap;
7519544fcfSbostic 		ap->a_fp = fr.fr_savfp;
7619544fcfSbostic 		ap->a_pc = fr.fr_savpc;
7719544fcfSbostic 		if (ap->a_fp == 0)
7819544fcfSbostic 			ap->a_valid = 0;
7919544fcfSbostic 	}
8019544fcfSbostic }
8119544fcfSbostic 
8219544fcfSbostic /*
8319544fcfSbostic  * Evaluate a local symbol (N_LSYM or N_PSYM) using the activation
8419544fcfSbostic  * record pointed to by ap.
8519544fcfSbostic  */
8619544fcfSbostic addr_t
eval_localsym(sp,ap)8719544fcfSbostic eval_localsym(sp, ap)
8819544fcfSbostic 	register struct nlist *sp;
8919544fcfSbostic 	struct activation *ap;
9019544fcfSbostic {
9119544fcfSbostic 	switch (sp->n_type) {
9219544fcfSbostic 
9319544fcfSbostic 	case N_LSYM:
9419544fcfSbostic 		return (ap->a_fp - sp->n_value);	/* ??? */
9519544fcfSbostic 
9619544fcfSbostic 	case N_PSYM:
9719544fcfSbostic 		return (ap->a_ap + sp->n_value);	/* ??? */
9819544fcfSbostic 	}
9919544fcfSbostic 	panic("eval_localsym");
10019544fcfSbostic 	/* NOTREACHED */
10119544fcfSbostic }
10219544fcfSbostic 
10319544fcfSbostic 
10419544fcfSbostic /* true iff address a is in instruction space */
10519544fcfSbostic #define	ispace(a) ((a) < txtmap.m1.e)
10619544fcfSbostic 
10719544fcfSbostic /*
10819544fcfSbostic  * Delete a (single) breakpoint.  Return 0 on success.
10919544fcfSbostic  */
11019544fcfSbostic int
clr_bpt(b)11119544fcfSbostic clr_bpt(b)
11219544fcfSbostic 	struct bkpt *b;
11319544fcfSbostic {
11419544fcfSbostic 	addr_t a = b->loc;
11519544fcfSbostic 
11619544fcfSbostic 	return (adbwrite(ispace(a) ? SP_INSTR : SP_DATA, a, &b->ins, 1) != 1);
11719544fcfSbostic }
11819544fcfSbostic 
11919544fcfSbostic /*
12019544fcfSbostic  * Set a (single) breakpoint.  Return 0 on success.
12119544fcfSbostic  */
12219544fcfSbostic set_bpt(b)
12319544fcfSbostic 	struct bkpt *b;
12419544fcfSbostic {
12519544fcfSbostic 	addr_t a = b->loc;
12619544fcfSbostic 	int space;
12719544fcfSbostic 	char bpt = 0x03;		/* breakpoint instruction */
12819544fcfSbostic 
12919544fcfSbostic 	space = ispace(a) ? SP_INSTR : SP_DATA;
13019544fcfSbostic 	return (adbread(space, a, &b->ins, 1) != 1 ||
13119544fcfSbostic 		adbwrite(space, a, &bpt, 1) != 1);
13219544fcfSbostic }
13319544fcfSbostic 
13419544fcfSbostic /*
13519544fcfSbostic  * Check a float for `correctness' (reserved patterns, etc).  Return
13619544fcfSbostic  * a pointer to a character string to be printed instead of the float,
13719544fcfSbostic  * or NULL to print the float as-is.
13819544fcfSbostic  *
13919544fcfSbostic  * The string returned, if any, should be no longer than 16 characters.
14019544fcfSbostic  *
14119544fcfSbostic  * On the VAX, we can simply check the first two bytes.  Byte zero
14219544fcfSbostic  * contains one bit of the exponent, and byte 1 has the remaining 7
14319544fcfSbostic  * exponent bits and the sign bit.  If the sign bit is set and the
14419544fcfSbostic  * exponent is zero, the value is reserved.
14519544fcfSbostic  */
14619544fcfSbostic /* ARGSUSED */
14719544fcfSbostic char *
checkfloat(fp,isdouble)14819544fcfSbostic checkfloat(fp, isdouble)
14919544fcfSbostic 	caddr_t fp;
15019544fcfSbostic 	int isdouble;
15119544fcfSbostic {
15219544fcfSbostic 
15319544fcfSbostic 	return ((*(short *)fp & 0xff80) == 0x8000 ? "(reserved oprnd)" : NULL);
15419544fcfSbostic }
15519544fcfSbostic 
15619544fcfSbostic /*
15719544fcfSbostic  * Convert a value in `expr_t' format to float or double.
15819544fcfSbostic  */
etofloat(e,fp,isdouble)15919544fcfSbostic etofloat(e, fp, isdouble)
16019544fcfSbostic 	expr_t e;
16119544fcfSbostic 	caddr_t fp;
16219544fcfSbostic 	int isdouble;
16319544fcfSbostic {
16419544fcfSbostic 
16519544fcfSbostic 	if (isdouble)
16619544fcfSbostic 		((int *)fp)[1] = 0;
16719544fcfSbostic 	*(int *)fp = e;
16819544fcfSbostic }
16919544fcfSbostic 
mch_init()17019544fcfSbostic mch_init()
17119544fcfSbostic {
17219544fcfSbostic 
17319544fcfSbostic 	mkioptab();
17419544fcfSbostic }
17519544fcfSbostic 
17619544fcfSbostic /* quietly read object obj from address addr */
17719544fcfSbostic #define	GET(obj, addr)	(void) adbread(SP_DATA, addr, &(obj), sizeof(obj))
17819544fcfSbostic 
17919544fcfSbostic /* set `current process' pcb */
setpcb(addr)18019544fcfSbostic setpcb(addr)
18119544fcfSbostic 	addr_t addr;
18219544fcfSbostic {
18319544fcfSbostic 	int pte;
18419544fcfSbostic 
18519544fcfSbostic 	GET(pte, addr);
18619544fcfSbostic 	masterpcbb = (pte & PG_PFNUM) * NBPG;
18719544fcfSbostic }
18819544fcfSbostic 
getpcb()18919544fcfSbostic getpcb()
19019544fcfSbostic {
19119544fcfSbostic 
19219544fcfSbostic 	/* maybe use adbread() here ... */
19319544fcfSbostic 	(void) readcore((off_t)masterpcbb & ~KERNBASE,
19419544fcfSbostic 		(char *)&pcb, sizeof(struct pcb));
19519544fcfSbostic 	pcb.pcb_p0lr &= ~AST_CLR;
19619544fcfSbostic 	adbprintf("p0br %R p0lr %R p1br %R p1lr %R\n",
19719544fcfSbostic 	    pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr);
19819544fcfSbostic }
19919544fcfSbostic 
20019544fcfSbostic /*
20119544fcfSbostic  * Convert a kernel virtual address to a physical address,
20219544fcfSbostic  * a la the VAX hardware.  Set *err if the resulting address
20319544fcfSbostic  * is invalid.
20419544fcfSbostic  */
20519544fcfSbostic addr_t
vtophys(addr,err)20619544fcfSbostic vtophys(addr, err)
20719544fcfSbostic 	addr_t addr;
20819544fcfSbostic 	char **err;
20919544fcfSbostic {
21019544fcfSbostic 	register unsigned v = btop(addr & ~0xc0000000);
21119544fcfSbostic 	register addr_t pteaddr;
21219544fcfSbostic 	struct pte pte;
21319544fcfSbostic #define issys(a) ((a) & 0x80000000)
21419544fcfSbostic #define isp1(a) ((a) & 0x40000000)
21519544fcfSbostic 
21619544fcfSbostic 	if (issys(addr)) {
21719544fcfSbostic 		/* system space: get system pte */
21819544fcfSbostic 		if (isp1(addr) || v >= slr) {
21919544fcfSbostic 	oor:
22019544fcfSbostic 			*err = "address out of segment";
22119544fcfSbostic 			return (0);
22219544fcfSbostic 		}
22319544fcfSbostic 		pteaddr = (addr_t)(sbr + v) & ~0x80000000;
22419544fcfSbostic 	} else {
22519544fcfSbostic 		if (isp1(addr)) {
22619544fcfSbostic 			/* P1 space: must not be in shadow region */
22719544fcfSbostic 			if (v < pcb.pcb_p1lr)
22819544fcfSbostic 				goto oor;
22919544fcfSbostic 			pteaddr = (addr_t)(pcb.pcb_p1br + v);
23019544fcfSbostic 		} else {
23119544fcfSbostic 			/* P0 space: must not be off end of region */
23219544fcfSbostic 			if (v >= pcb.pcb_p0lr)
23319544fcfSbostic 				goto oor;
23419544fcfSbostic 			pteaddr = (addr_t)(pcb.pcb_p0br + v);
23519544fcfSbostic 		}
23619544fcfSbostic 		if (!issys(pteaddr) || isp1(pteaddr)) {
23719544fcfSbostic 			*err = "bad p0br or p1br in pcb";
23819544fcfSbostic 			return (0);
23919544fcfSbostic 		}
24019544fcfSbostic 		/* in either case, find system pte by recursing */
24119544fcfSbostic 		pteaddr = vtophys(pteaddr, err);
24219544fcfSbostic 		if (*err)
24319544fcfSbostic 			return (0);
24419544fcfSbostic 	}
24519544fcfSbostic 
24619544fcfSbostic 	/*
24719544fcfSbostic 	 * Read system pte.  If valid or reclaimable,
24819544fcfSbostic 	 * physical address is combination of its page number and
24919544fcfSbostic 	 * the page offset of the original address.
25019544fcfSbostic 	 */
25119544fcfSbostic 	if (readcore((off_t)pteaddr, (caddr_t)&pte, 4) != 4) {
25219544fcfSbostic 		*err = "page table botch";
25319544fcfSbostic 		return (0);
25419544fcfSbostic 	}
25519544fcfSbostic 	/* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */
25619544fcfSbostic 	if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) {
25719544fcfSbostic 		*err = "page not valid/reclaimable";
25819544fcfSbostic 		return (0);
25919544fcfSbostic 	}
26019544fcfSbostic 	return ((addr_t)(ptob(pte.pg_pfnum) + (addr & PGOFSET)));
26119544fcfSbostic }
26219544fcfSbostic 
26319544fcfSbostic /*
26419544fcfSbostic  * Print a stack trace ($c, $C).  Trace backwards through nback
26519544fcfSbostic  * frames; if locals is set, print local variables.
26619544fcfSbostic  */
printstack(locals,nback)26719544fcfSbostic printstack(locals, nback)
26819544fcfSbostic 	int locals, nback;
26919544fcfSbostic {
27019544fcfSbostic 	register int i;
27119544fcfSbostic 	register addr_t a;
27219544fcfSbostic 	struct nlist *sym;
27319544fcfSbostic 	char *s;
27419544fcfSbostic /*	addr_t callpc;		/* pc that called this frame */
27519544fcfSbostic 	struct activation cur;	/* this frame itself */
27619544fcfSbostic 	struct frame fr;	/* the frame above this frame */
27719544fcfSbostic 	u_char narg;		/* number of int-args to this frame */
27819544fcfSbostic 	addr_t dummy;		/* a variable to scribble on */
27919544fcfSbostic #define	UNKNOWN	-1
28019544fcfSbostic 
28119544fcfSbostic #ifdef RLOCALS
28219544fcfSbostic 	/* if locals variables are broken, use an alternate strategy */
28319544fcfSbostic 	register int r;
28419544fcfSbostic 	addr_t sp, prev_sp;
28519544fcfSbostic 	int regs[12];
28619544fcfSbostic 	static char unknown[] = "<unknown>";
28719544fcfSbostic #endif
28819544fcfSbostic 
28919544fcfSbostic 	/* fr_savpc==UNKNOWN implies fr is invalid */
29019544fcfSbostic 	fr.fr_savpc = UNKNOWN;
29119544fcfSbostic 
29219544fcfSbostic #ifdef RLOCALS
29319544fcfSbostic 	/* grab registers */
29419544fcfSbostic 	bcopy((caddr_t)(kcore ? &pcb.pcb_r0 : &u.u_ar0[R0]), (caddr_t)regs,
29519544fcfSbostic 		sizeof(regs));
29619544fcfSbostic #endif
29719544fcfSbostic 
29819544fcfSbostic 	/* set up the current stack frame */
29919544fcfSbostic 	if (gavedot) {
30019544fcfSbostic 		GET(fr, cur.a_fp = dot);
30119544fcfSbostic 		checkerr();
30219544fcfSbostic 		if (fr.fr_s) {	/* was a `calls'; can figure out ap */
30319544fcfSbostic 			cur.a_ap = cur.a_fp + sizeof(fr) + fr.fr_spa;
30419544fcfSbostic 			for (i = fr.fr_mask; i != 0; i >>= 1)
30519544fcfSbostic 				if (i & 1)
30619544fcfSbostic 					cur.a_ap += 4;
30719544fcfSbostic 		} else		/* `callg': cannot find ap */
30819544fcfSbostic 			cur.a_ap = UNKNOWN;
30919544fcfSbostic 		cur.a_pc = UNKNOWN;
31019544fcfSbostic #ifdef RLOCALS
31119544fcfSbostic 		sp = UNKNOWN;
31219544fcfSbostic #endif
31319544fcfSbostic 	} else if (kcore) {
31419544fcfSbostic 		cur.a_ap = pcb.pcb_ap;
31519544fcfSbostic 		cur.a_fp = pcb.pcb_fp;
31619544fcfSbostic 		cur.a_pc = pcb.pcb_pc;
31719544fcfSbostic #ifdef RLOCALS
31819544fcfSbostic 		sp = pcb.pcb_ksp;
31919544fcfSbostic #endif
32019544fcfSbostic 	} else {
32119544fcfSbostic 		cur.a_ap = u.u_ar0[AP];
32219544fcfSbostic 		cur.a_fp = u.u_ar0[FP];
32319544fcfSbostic 		cur.a_pc = u.u_ar0[PC];
32419544fcfSbostic #ifdef RLOCALS
32519544fcfSbostic 		sp = u.u_ar0[SP];
32619544fcfSbostic #endif
32719544fcfSbostic 	}
32819544fcfSbostic 
32919544fcfSbostic 	/* now back up through the stack */
33019544fcfSbostic 	while (nback--) {
33119544fcfSbostic 		if (fr.fr_savpc == UNKNOWN)
33219544fcfSbostic 			GET(fr, cur.a_fp);
33319544fcfSbostic 
33419544fcfSbostic 		/* where are we? ... if u. area, signal trampoline code */
33519544fcfSbostic 		if ((int)cur.a_pc >= USRSTACK) {
33619544fcfSbostic /*			GET(callpc, cur.a_fp + 92);	/* XXX magic 92 */
33719544fcfSbostic 			s = "sigtramp";
33819544fcfSbostic 		} else {
33919544fcfSbostic /*			callpc = fr.fr_savpc; */
34019544fcfSbostic 			if (cur.a_pc != UNKNOWN &&
34119544fcfSbostic 			    (sym = findsym(cur.a_pc, SP_INSTR, &dummy)) != 0) {
34219544fcfSbostic 				s = sym->n_un.n_name;
34319544fcfSbostic 				if (eqstr(s, "start")) {
34419544fcfSbostic 					errflag = NULL;
34519544fcfSbostic 					break;
34619544fcfSbostic 				}
34719544fcfSbostic 			} else
34819544fcfSbostic 				s = "?";
34919544fcfSbostic 		}
35019544fcfSbostic 		adbprintf("%s(", s);
35119544fcfSbostic 		if ((a = cur.a_ap) != UNKNOWN) {
35219544fcfSbostic 			GET(narg, a);
353dfcfdf84Storek 			for (i = narg > 20 ? 20 : narg; i;)
35419544fcfSbostic 				prfrom(a += 4, --i ? ',' : 0);
35519544fcfSbostic 		}
35619544fcfSbostic 		printc(')');
35719544fcfSbostic 		if (cur.a_pc != UNKNOWN) {
35819544fcfSbostic 			prints(" at ");
35919544fcfSbostic 			psymoff("%R", cur.a_pc, SP_INSTR, -(addr_t)1, "");
36019544fcfSbostic 		}
36119544fcfSbostic 		printc('\n');
36219544fcfSbostic 
36319544fcfSbostic 		/* local variables */
36419544fcfSbostic 		if (locals) {
36519544fcfSbostic #ifdef busted
36619544fcfSbostic 			if (cur.a_pc != UNKNOWN) {
36719544fcfSbostic 				sym = findsym(cur.a_pc, SP_INSTR, &dummy);
36819544fcfSbostic 				while ((sym = nextlocal(sym)) != NULL) {
36919544fcfSbostic 					adbprintf("%8t");
37019544fcfSbostic 					printlsym(sym->n_un.n_name);
37119544fcfSbostic 					adbprintf(":%12t");
37219544fcfSbostic 					prfrom(eval_localsym(sym, &cur), '\n');
37319544fcfSbostic 				}
37419544fcfSbostic 			}
37519544fcfSbostic #endif
37619544fcfSbostic #ifdef RLOCALS
37719544fcfSbostic 			adbprintf("\
37843ae9965Storek fp: %R\%16tap: %?s%?R%32tsp:  %?s%?R%48tpc:  %?s%?R\n\
37943ae9965Storek r0: %R\%16tr1: %R\%32tr2:  %R\%48tr3:  %R\n\
38043ae9965Storek r4: %R\%16tr5: %R\%32tr6:  %R\%48tr7:  %R\n\
38143ae9965Storek r8: %R\%16tr9: %R\%32tr10: %R\%48tr11: %R\n",
38219544fcfSbostic #define q(s) s == UNKNOWN, unknown, s != UNKNOWN, s
38319544fcfSbostic 			    cur.a_fp, q(cur.a_ap), q(sp), q(cur.a_pc),
38419544fcfSbostic #undef q
38519544fcfSbostic 			    regs[0], regs[1], regs[2], regs[3],
38619544fcfSbostic 			    regs[4], regs[5], regs[6], regs[7],
38719544fcfSbostic 			    regs[8], regs[9], regs[10], regs[11]);
38819544fcfSbostic 
38919544fcfSbostic 			/* update registers, and find previous frame's sp */
39019544fcfSbostic 			a = cur.a_fp + 16;
39119544fcfSbostic 			for (r = 0, i = fr.fr_mask; i != 0; r++, i >>= 1)
39219544fcfSbostic 				if (i & 1)
39319544fcfSbostic 					GET(regs[r], a += 4);
39419544fcfSbostic 			a += fr.fr_spa;
39519544fcfSbostic 			if (fr.fr_s)
39619544fcfSbostic 				a += narg * 4;
39719544fcfSbostic 			prev_sp = a;
39819544fcfSbostic 
39919544fcfSbostic 			/* now print automatics */
40019544fcfSbostic 			if (sp != UNKNOWN) {
40119544fcfSbostic #define	MAXPRINT 30		/* max # words to print */
40219544fcfSbostic 				/* XXX should be settable */
40319544fcfSbostic 				i = (cur.a_fp - sp) >> 2;
40419544fcfSbostic 				if (i > MAXPRINT)
40519544fcfSbostic 					i = MAXPRINT;
40619544fcfSbostic 				for (a = cur.a_fp; --i >= 0;) {
40719544fcfSbostic 					a -= 4;
40819544fcfSbostic 					adbprintf("%R: %V(fp):%24t",
40919544fcfSbostic 						a, a - cur.a_fp);
41019544fcfSbostic 					prfrom(a, '\n');
41119544fcfSbostic 				}
41219544fcfSbostic 				if (a > sp)
41319544fcfSbostic 					adbprintf("\
41419544fcfSbostic %R: %V(fp) .. %R: %V(fp) not displayed\n",
41519544fcfSbostic 						a, a - cur.a_fp,
41619544fcfSbostic 						sp, sp - cur.a_fp);
41719544fcfSbostic 			}
41819544fcfSbostic #endif /* RLOCALS */
41919544fcfSbostic 		}
42019544fcfSbostic 
42119544fcfSbostic 		errflag = NULL;		/* clobber any read errors */
42219544fcfSbostic 
42319544fcfSbostic 		/* back up one frame */
42419544fcfSbostic 		if (fr.fr_savfp == 0)
42519544fcfSbostic 			break;
42619544fcfSbostic 		cur.a_ap = fr.fr_savap;
42719544fcfSbostic 		cur.a_fp = fr.fr_savfp;
42819544fcfSbostic #ifdef RLOCALS
42919544fcfSbostic 		sp = prev_sp;
43019544fcfSbostic #endif
43119544fcfSbostic 		cur.a_pc = fr.fr_savpc;
43219544fcfSbostic 		fr.fr_savpc = UNKNOWN;	/* until we read it again */
43319544fcfSbostic 
43419544fcfSbostic 		if (!gavedot && !INSTACK(cur.a_fp) && !kcore)
43519544fcfSbostic 			break;
43619544fcfSbostic 
43719544fcfSbostic 		/* make sure we returned somewhere... */
43819544fcfSbostic 		(void) adbread(kcore ? SP_DATA : SP_INSTR, cur.a_pc, &dummy, 1);
43919544fcfSbostic 		checkerr();
44019544fcfSbostic 	}
44119544fcfSbostic }
44219544fcfSbostic 
44319544fcfSbostic /*
44419544fcfSbostic  * Register offset to u. pointer, and register offset to ptrace value
44519544fcfSbostic  */
44619544fcfSbostic #define	otoua(o) \
44719544fcfSbostic 	((int *)(((o) < 0 ? (int)u.u_ar0 : (int)&u.u_pcb) + (o)))
44819544fcfSbostic #define	otopt(o) \
44919544fcfSbostic 	((int *)((o) < 0 ? (o) + ctob(UPAGES) : (o)))
45019544fcfSbostic 
45119544fcfSbostic /*
45219544fcfSbostic  * Return the value of some register.
45319544fcfSbostic  */
45419544fcfSbostic expr_t
getreg(reg)45519544fcfSbostic getreg(reg)
45619544fcfSbostic 	register struct reglist *reg;
45719544fcfSbostic {
45819544fcfSbostic 
45919544fcfSbostic 	return (kcore ? *reg->r_pcbaddr : *otoua(reg->r_offset));
46019544fcfSbostic }
46119544fcfSbostic 
46219544fcfSbostic 
46319544fcfSbostic /*
46419544fcfSbostic  * Set the value of some register.  Return 0 if all goes well.
46519544fcfSbostic  */
setreg(reg,val)46619544fcfSbostic setreg(reg, val)
46719544fcfSbostic 	register struct reglist *reg;
46819544fcfSbostic 	expr_t val;
46919544fcfSbostic {
47019544fcfSbostic 
47119544fcfSbostic 	if (kcore)
47219544fcfSbostic 		*reg->r_pcbaddr = val;
47319544fcfSbostic 	else {
47419544fcfSbostic 		*otoua(reg->r_offset) = val;
47519544fcfSbostic 		if (pid) {
47619544fcfSbostic 			errno = 0;
47719544fcfSbostic 			if (ptrace(PT_WRITE_U, pid, otopt(reg->r_offset),
47819544fcfSbostic 					(int)val) == -1 && errno)
47919544fcfSbostic 				return (-1);
48019544fcfSbostic 		}
48119544fcfSbostic 	}
48219544fcfSbostic 	return (0);
48319544fcfSbostic }
48419544fcfSbostic 
48519544fcfSbostic /*
48619544fcfSbostic  * Read registers from current process.
48719544fcfSbostic  */
readregs()48819544fcfSbostic readregs()
48919544fcfSbostic {
49019544fcfSbostic 	register struct reglist *reg;
49119544fcfSbostic 	extern struct reglist reglist[];
49219544fcfSbostic 
49319544fcfSbostic 	for (reg = reglist; reg->r_name != NULL; reg++)
49419544fcfSbostic 		*otoua(reg->r_offset) =
49519544fcfSbostic 			ptrace(PT_READ_U, pid, otopt(reg->r_offset), 0);
49619544fcfSbostic }
49719544fcfSbostic 
49819544fcfSbostic addr_t
getpc()49919544fcfSbostic getpc()
50019544fcfSbostic {
50119544fcfSbostic 
50219544fcfSbostic 	return (u.u_ar0[PC]);
50319544fcfSbostic }
50419544fcfSbostic 
setpc(where)50519544fcfSbostic setpc(where)
50619544fcfSbostic 	addr_t where;
50719544fcfSbostic {
50819544fcfSbostic 
50919544fcfSbostic 	u.u_ar0[PC] = where;
51019544fcfSbostic }
51119544fcfSbostic 
51219544fcfSbostic /*
51319544fcfSbostic  * udot returns true if u.u_pcb appears correct.  More extensive
51419544fcfSbostic  * checking is possible....
51519544fcfSbostic  */
udot()51619544fcfSbostic udot()
51719544fcfSbostic {
51819544fcfSbostic 
51919544fcfSbostic 	/* user stack should be in stack segment */
52019544fcfSbostic 	if (!INSTACK(u.u_pcb.pcb_usp))
52119544fcfSbostic 		return (0);
52219544fcfSbostic 	/* kernel stack should be in u. area */
52319544fcfSbostic 	if (u.u_pcb.pcb_ksp < USRSTACK)
52419544fcfSbostic 		return (0);
52519544fcfSbostic 	/* looks good to us... */
52619544fcfSbostic 	return (1);
52719544fcfSbostic }
52819544fcfSbostic 
sigprint()52919544fcfSbostic sigprint()
53019544fcfSbostic {
53119544fcfSbostic 	extern char *sys_siglist[];
53219544fcfSbostic 	extern char *illinames[], *fpenames[];
53319544fcfSbostic 	extern int nillinames, nfpenames;
53419544fcfSbostic 
53519544fcfSbostic 	if ((u_int)signo - 1 < NSIG - 1)
53619544fcfSbostic 		prints(sys_siglist[signo]);
53719544fcfSbostic 	switch (signo) {
53819544fcfSbostic 
53919544fcfSbostic 	case SIGFPE:
54019544fcfSbostic 		if ((u_int)sigcode < nfpenames)
54119544fcfSbostic 			prints(fpenames[sigcode]);
54219544fcfSbostic 		break;
54319544fcfSbostic 
54419544fcfSbostic 	case SIGILL:
54519544fcfSbostic 		if ((u_int)sigcode < nillinames)
54619544fcfSbostic 			prints(illinames[sigcode]);
54719544fcfSbostic 		break;
54819544fcfSbostic 	}
54919544fcfSbostic }
550