V9/cmd/adb/vax/mchframe.c

Compare this file to the similar file:
Show the results in this format:

/*
 * machine-dependent code for
 * looking in stack frames
 * vax version
 */

#include "defs.h"
#include <sys/param.h>
#include "regs.h"
#include "sym.h"
#include "space.h"

int maxargs = 20;

/*
 * VAX stack frame
 */

#define	F_PSW	4
#define	F_FLAGS	6
#define	F_AP	8	/* saved ap */
#define	F_FP	12	/* saved fp */
#define	F_PC	16	/* return pc */
#define	F_REGS	20	/* saved regs, if any */

/*
 * flags
 */

#define	FFREGS	0x1fff	/* saved register flags; 01 is r0 */
#define	FFCALLS	0x2000	/* called by calls, not callg */
#define	FFOFF	0xc000	/* offset added to align stack */
#define	SALIGN(f)	(((f)>>14) & 03)

/*
 * is the saved psw reasonable?
 * really just a last resort to find the end of the stack
 */

#define	BADPSW(p)	(((p)&0xff00) != 0)

/*
 * is the pc probably in signal trampoline code?
 * == it's in the user block
 */

#define	sigtramp(pc)	(0x80000000 > (pc) && (pc) > 0x80000000 - ctob(UPAGES))

#define	F_HACK	64	/* where to find the saved pc in a trampoline frame */
/*
 * return an address for a local variable
 * no register vars, unfortunately, as we can't provide an address
 * gn is the procedure; ln the local name
 *
 * this is vax dependent because symbol tables vary
 */

localaddr(gn, ln)
char *gn, *ln;
{
	WORD fp, ap;
	extern WORD expv;
	extern int expsp;
	ADDR laddr();

	if (gn) {
		if (findrtn(gn) == 0)
			error("function not found");
	}
	else {
		findsym((WORD)atow(rget(PC)), INSTSP);
		if (cursym == NULL)
			error("function not found");
	}
	if (findframe(&fp, &ap) == 0)
		error("stack frame not found");
	if (ln == NULL) {
		expsp = 0;
		expv = fp;
		return;
	}
	while (localsym()) {
		if (strcmp(ln, cursym->y_name) != 0)
			continue;
		expv = laddr(cursym, fp, ap);
		if (cursym->y_ltype == S_RSYM)
			expsp = REGSP;
		else
			expsp = NOSP;
		return;
	}
	error("bad local variable");
	/* NOTREACHED */
}

/*
 * print a stack traceback
 * give locals if possible
 */

ctrace(modif)
char modif;
{
	register ADDR fp, ap, callpc;
	register int narg;
	ADDR oap;
	register int fl;
	int tramp;

	if (adrflg) {
		fp = adrval;
		fl = stow(sget(fp + F_FLAGS, CORF|DATASP));
		if ((fl & FFCALLS) == 0)
			ap = fp;	/* callg, can't figure out ap */
		else {
			ap = adrval + F_REGS + SALIGN(fl);
			fl &= FFREGS;
			while (fl) {
				if (fl & 1)
					ap += SZREG;
				fl >>= 1;
			}
		}
		callpc = atow(aget(fp + F_PC, CORF|DATASP));
	} else {
		ap = (ADDR)rtow(rget(AP));
		fp = (ADDR)rtow(rget(FP));
		callpc = (ADDR)rtow(rget(PC));
	}
	clrraddr();
	while (cntval--) {
		chkerr();
		tramp = 0;
		if (sigtramp(callpc)) {
			printf("sigtramp(");
			tramp++;
		} else {
			findsym(callpc, INSTSP);
			if (cursym == NULL)
				printf("?(");
			else if (strcmp("start", cursym->y_name) == 0)
				break;
			else
				printf("%s(", cursym->y_name);
		}
		fl = ctow(cget(ap, CORF|DATASP));
		if ((narg = fl) > maxargs)
			narg = maxargs;
		oap = ap;
		while (--fl, --narg >= 0) {
			printf("%R", ltow(lget(ap += SZREG, CORF|DATASP)));
			if (narg != 0)
				printc(',');
		}
		if (fl >= 0)
			printf(",...");
		printf(") from %R\n", callpc);
		if (modif == 'C')
			locals(fp, oap);
		if (tramp)	/* hack */
			callpc = atow(aget(fp + F_HACK, CORF|DATASP));
		else
			callpc = atow(aget(fp + F_PC, CORF|DATASP));
		fl = stow(sget(fp + F_FLAGS, CORF|DATASP));
		setraddr(fl, fp);
		ap = atow(aget(fp + F_AP, CORF|DATASP));
		fp = atow(aget(fp + F_FP + SALIGN(fl), CORF|DATASP));
		if (fp == 0)
			break;
		fl = stow(sget(fp + F_PSW, CORF|DATASP));
		if (BADPSW(fl))
			break;
	}
	clrraddr();
}

static
locals(fp, ap)
ADDR fp, ap;
{
	WORD val;
	register int sp;
	ADDR laddr();

	while (localsym()) {
		sp = CORF | DATASP;
		if (cursym->y_ltype == S_RSYM)
			sp = CORF | REGSP;
		val = ltow(lget(laddr(cursym, fp, ap), sp));
		if (errflg == 0)
			printf("%8t%s/%10t%R\n", cursym->y_name, val);
		else {
			printf("%8t%s/%10t?\n", cursym->y_name);
			errflg = 0;
		}
	}
}

static ADDR
laddr(sp, fp, ap)
struct sym *sp;
ADDR fp, ap;
{

	switch (sp->y_ltype) {
	case S_STSYM:
		return (sp->y_value);

	case S_LSYM:
		return (fp - sp->y_value);

	case S_PSYM:
		return (ap + sp->y_value);

	case S_RSYM:
		return (sp->y_value * SZREG);
	}
	error("bad local symbol");
	/* NOTREACHED */
}

static int
findframe(fpp, app)
ADDR *fpp, *app;
{
	register ADDR fp, ap, pc;
	register int fl;
	struct sym *svcur;

	svcur = cursym;
	fp = rtow(rget(FP));
	ap = rtow(rget(AP));
	pc = rtow(rget(PC));
	if (errflg)
		return (0);
	clrraddr();
	for (;;) {
		findsym(pc, INSTSP);
		if (cursym == svcur)
			break;
		if (cursym && strcmp(cursym->y_name, "start") == 0) {
			clrraddr();
			return (0);
		}
		fl = stow(sget((ADDR)fp + F_FLAGS, CORF|DATASP));
		setraddr(fl, fp);
		pc = atow(aget(fp + F_PC, CORF|DATASP));
		ap = atow(aget(fp + F_AP, CORF|DATASP));
		fp = atow(aget(fp + F_FP + SALIGN(fl), CORF|DATASP));
		/* sigtramp? */
		if (errflg) {
			clrraddr();
			return (0);
		}
	}
	*fpp = fp;
	*app = ap;
	return (1);
}

/*
 * set addresses for saved registers for this frame
 */

static
setraddr(mask, fp)
register int mask;
register ADDR fp;
{
	register int r;
	register int i;
	extern ADDR raddr[];

	mask &= FFREGS;
	for (r = 0, i = 0; mask; r++)
		if (mask & (1 << r)) {
			if (MINREG <= r && r <= MAXREG)
				raddr[r - MINREG] = fp + F_REGS +
					i * SZREG;
			i++;
			mask &=~ (1 << r);
		}
}

static
clrraddr()
{
	register int i;
	extern ADDR raddr[];

	for (i = 0; i <= MAXREG - MINREG; i++)
		raddr[i] = 0;
}