Ausam/sys/sysd/source/proc4.c

Find at most related files.
including files from this version of Unix.

/* file for cdb etc */

#include "proc.h"

#define	DSP	0
#define	ISP	1
#define	TRACEWARN	30
#define	TRACETERM	50
int	symoff;
int	errflg;
int	symlen;
int	symcnt;
struct symbol	*symbuf;
int	*alpha;
int	*numeric;

#ifndef	BIG_UNIX
stackdecode(r5, r6, ka6)
#endif
#ifdef	BIG_UNIX
stackdecode(r5, r6, aka5, ka6)
#endif
int	r5, r6;
#ifdef	BIG_UNIX
int	aka5;
#endif
int	ka6;
{
	unsigned int	i, j;
	unsigned int	rr5, rr6;
	int	nxtrr5;
	int	intrpt;
	int	callev, narg, argp;
	int	lcls;
	int	inst, adr, callpt;
	struct symbol	*ss;
	struct sybmol	*indss;
	int	callmode;
	int	oldpc;
#ifdef	BIG_UNIX
	int	ka5, nxtka5;
	int	knarg;
	int	paged;
#endif

	printf(S_PTAB, "Stack trace - last called routines appear first\n\n");
	printf(S_PTAB, "Calling routine ( arguments )\n");
	printf(SS_PTAB, "local variables - if any\n\n");

	DEBUG
		printf("stackdecode called with r5=%u (%o), r6=%u (%o), ka6=%u (%o)\n",
			r5, r5, r6, r6, ka6, ka6);

	rr5 = r5;
	rr6 = r6;
#ifdef	BIG_UNIX
	ka5 = aka5;
#endif
	callev = 0;
	errflg = 0;
	oldpc = 0;

	do {
		if (u.u_qsav[1] == rr5)
			printf(S_PTAB, "  <------ u.u_qsav\n");
		if (u.u_ssav[1] == rr5)
			printf(S_PTAB, "  <------ u.u_ssav\n");

		nxtrr5 = get(rr5, DSP, ka6);
		callpt = get(rr5+2, DSP, ka6);
#ifdef	BIG_UNIX
		inst = get(callpt-4, ISP, ka5);
		adr = get(callpt-2, ISP, ka5);
#endif	BIG_UNIX
#ifndef	BIG_UNIX
		inst = get(callpt-4, ISP, txtoff);
		adr = get(callpt-2, ISP, txtoff);
#endif	BIG_UNIX

#ifdef	BIG_UNIX
		paged = 0;
		nxtka5 = ka5;
		if (adr==04730 && inst==KISA5) {
			/* paged kernel transfer */
			paged++;
			printf(S_PTAB, "\t     V\b+--- paged transfer\n");
			inst = get(callpt, ISP, ka5);
			if (inst == 012637)		/* mov (sp)+,*$... */
				knarg = 0;
			else if (inst == 05726)		/* tst (sp)+ */
				knarg = 1;
			else if (inst == 022626) {
				/* cmp (sp)+,(sp)+ */
				inst = get(callpt+8, ISP, ka5);
				if (inst == 011607)	/* mov (sp),pc */
					knarg = 2;
				else
					knarg = (get(callpt+10, ISP, ka5) + 4)/2;
			} else {
				errflg++;
				break;
			}
			callpt = get(rr5+4+(knarg==0 ? 2 : knarg*2), DSP, ka6);
			nxtka5 = get(rr5+4+(knarg==0 ? 0 : (knarg+1)*2), DSP, ka6);
			inst = get(callpt-4, ISP, nxtka5);
			adr = get(callpt-2, ISP, nxtka5);
		}
#endif
		intrpt = 0;
		DEBUG
			printf("stackdecode first test ins=%u (%o), adr=%u (%o), callpt=%u (%o), txtoff=%u (%o)\n",
				inst, inst, adr, adr, callpt, callpt, txtoff, txtoff);
		if (adr == 04730) {
			/* jsr pc,*(r0)+ */
			intrpt++;
#ifdef	BIG_UNIX
			narg = paged ? knarg : 7;
#endif	BIG_UNIX
#ifndef	BIG_UNIX
			narg = 7;
#endif	BIG_UNIX
			adr = oldpc;
		} else {
			if (inst == 04737)			/* jsr pc,*$... */
				narg = 1;
			else if ((inst & ~077) == 04700)	/* jsr pc,... */
				narg = 0;
			else {
				errflg++;
				break;
			}

			callmode = 0;
			if (inst == 04767)		/* jsr pc,... */
				adr =+ callpt;
			else if (inst == 04777) {
				/* jsr pc,*... */
				callmode = 1;
				adr =+ callpt;
#ifdef	BIG_UNIX
				indss = vallook(adr, nxtka5);
#endif	BIG_UNIX
#ifndef	BIG_UNIX
				indss = vallook(adr);
#endif	BIG_UNIX
				adr = get(adr, DSP, ka6);
			} else if (inst == 04775) {
				/* jsr pc,*...(r5) */
				callmode = 2;
				adr = get(adr+nxtrr5, DSP, ka6);
			} else if ((inst & ~07) == 04770) {
				/* jsr pc,*...(?) */
				callmode = 3;
				adr = oldpc;
			}
#ifdef	BIG_UNIX
			if (paged && callmode<3) {
				i = get(adr+4, ISP, ka5);
				if (i != ka5)
					printf(S_PTAB, "-->ka5 discrepancy; vector=%o; stack=%o\n", i, ka5);
				adr = get(adr+6, ISP, ka5);
			}
			inst = get(callpt, ISP, nxtka5);
#endif	BIG_UNIX
#ifndef	BIG_UNIX
			inst = get(callpt, ISP, txtoff);
#endif	BIG_UNIX
			if (inst == 05726)		/* tst (sp)+ */
				narg++;
			else if (inst == 022626)	/* cmp (sp)+,(sp)+ */
				narg =+ 2;
			else if (inst == 062706)	/* add $n,sp */
#ifndef	BIG_UNIX
				narg =+ get(callpt+2, ISP, txtoff)/2;
#endif	BIG_UNIX
#ifdef	BIG_UNIX
				narg =+ get(callpt+2, ISP, nxtka5)/2;
			if (paged && knarg!=narg) {
				printf(S_PTAB, " difference in paged argument count and real argument count\n");
				printf(S_PTAB, "  real = %d.; paged = %d.\n", narg, knarg);
				printf(S_PTAB, " paged count shall be used\n");
				narg = knarg;
			}
#endif	BIG_UNIX
		}

		DEBUG
			printf("narg=%u (%o), rr5=%u (%o)\n", narg, narg, rr5, rr5);


		/*
		 * print call and arguments
		 */
#ifdef	BIG_UNIX
		ss = vallook(adr, ka5);
#endif	BIG_UNIX
#ifndef	BIG_UNIX
		ss = vallook(adr);
#endif	BIG_UNIX
		printf(S_PTAB, "%2d: %8.8s (", callev, ss->s_symbol);
		for (i = 0; i < narg; i++) {
			if (i > 0)
				printf(", ");
			printf("%.1o", get(rr5+4 + 2*i, DSP, ka6));
		}
		switch (callmode) {

		case 0:
			printf(")\n");
			break;

		case 1:
			printf(") indirect call via %8.8s\n", indss->s_symbol);
			break;

		case 2:
			printf(") called via higher arg list\n");
			break;

		case 3:
			printf(") called via array\n");
			adr = ss->s_symval;
			break;
		}

		/*
		 * list locals to called routine
		 */
		lcls = 0;
#ifdef	BIG_UNIX
		if (get(adr, ISP, ka5) == 04567) {
			/* jsr r5,csv */
			inst = get(adr+4, ISP, ka5);
			if (inst == 05746)		/* tst -(sp) */
				lcls = 1;
			else if (inst == 0162706)	/* sub $n,sp */
				lcls = get(adr+6, ISP, ka5) / 2;
		}
#endif	BIG=UNIX
#ifndef	BIG_UNIX
		if (get(adr, ISP, txtoff) == 04567) {
			/* jsr r5,csv */
			inst = get(adr+4, ISP, txtoff);
			if (inst == 05746)		/* tst -(sp) */
				lcls = 1;
			else if (inst == 0162706)	/* sub $n,sp */
				lcls = get(adr+6, ISP, txtoff) / 2;
		}
#endif	BIG_UNIX
		if (lcls > 0) {
			printf(SS_PTAB, "{");
			for (i = 0; i < lcls; i++) {
				if (i > 0)
					printf(", ");
				printf("%.1o", get(rr5-6 - 2*i, DSP, ka6));
			}
			printf("}\n");
		}
		printf(SS_PTAB, "%60tsaved registers:");
		for (i = 2; i <= 5; i++) {
			j = get(rr5 + (i - 5)*2, DSP, ka6);
			if (!(i & 1))
				printf("%78t");
			printf(" r%d = %u (%o);", i, j, j);
			if (i & 1)
				printf("\n");
		}

		if (callev == TRACEWARN)
			WARNING
				warn("stack trace level rather large!");
		if (callev++ == TRACETERM) {
			WARNING
				warn("stack trace looping - terminated!");
			errflg++;
		}

#ifdef	BIG_UNIX
		if (paged)
			ka5 = nxtka5;
#endif	BIG_UNIX
		if (intrpt) {
			i = rr5 + 14 + 4;
#ifdef	BIG_UNIX
			if (paged)
				i =+ 4;
#endif	BIG_UNIX
			if (i >= USERADR+04000)
				break;
		} else {
			if (rr5+4 >= USERADR+04000)
				break;
		}
		rr5 = nxtrr5;
		if (rr5 >= USERADR+04000)
			break;
		oldpc = callpt;

		if (rr5 >= USERADR+04000)
			break;
		DEBUG
			printf("at end of loop new rr5=%u (%o)\n", rr5, rr5);
	} while (!errflg);

	printf("\n\n");
}

/***********************/

get(adr, space, ka56)
unsigned adr;
int	space;
int	ka56;
{
	long	bign;
	int	word;

	DEBUG
		printf("get passed adr=%u (%o), space=%u (%o), ka56=%u (%o)\n", adr, adr, space, space, ka56, ka56);

	bign = ka56.unsign;
	bign =<< 6;	/* 64 bytes/block */
	if (space == DSP) {
		lseek(corefd, bign, 0);
		seek(corefd, adr - USERADR, 1);
	} else {
#ifdef	BIG_UNIX
		if (adr >= PAGEADR) {
			lseek(corefd, bign, 0);
			seek(corefd, adr - PAGEADR, 1);
		} else
#endif	BIG_UNIX
#ifdef	_1170
		if(adr >= FULLPAGE)
			{
			lseek(corefd, bign, 0);
			seek(corefd, adr - FULLPAGE, 1);
			}
		  else
			seek(corefd, adr, 0);
#endif	_1170
#ifdef	BIG_UNIX | _1140
			seek(corefd, adr, 0);
#endif	BIG_UNIX | _1140
	}

	if (read(corefd, &word, 2) != 2)
		errflg++;
	return(word);
}

/****************************/

#ifdef	BIG_UNIX
vallook(value, ka5)
#endif	BIG_UNIX
#ifndef	BIG_UNIX
vallook(value)
#endif	BIG_UNIX
unsigned value;
#ifdef	BIG_UNIX
int	ka5;
#endif	BIG_UNIX
{
#ifdef	BIG_UNIX
	return(getnum(value, ka5));
#endif	BIG_UNIX
#ifndef	BIG_UNIX
	return(getnum(value));
#endif	BIG_UNIX
}

/************************/

numcomp(a, b)
int *a, *b;
{
	register struct symbol	*sa, *sb;

	sa = &symbuf[*a];
	sb = &symbuf[*b];
	if (sa->s_symval < sb->s_symval)
		return(-1);
	if (sa->s_symval > sb->s_symval)
		return(1);
#ifdef	BIG_UNIX
	if (sa->s_symseg < sb->s_symseg)
		return(-1);
	if (sa->s_symseg > sb->s_symseg)
		return(1);
#endif	BIG_UNIX
	return(0);
}

/****************************/

alcomp(a, b)
int	*a, *b;
{
	return(alcom(symbuf[*a].s_symbol, symbuf[*b].s_symbol));
}

/************************/

symsort()
{
	/*
	 *	this procedure verifys the validity of the file
	 *	and having done this creates:
	 *
	 *	symbuf[] - an array of symbol table entry structures
	 *		   read from the namelist file.
	 *	alpha[] -  alpha ordered index into symbuf
	 *	numeric[] - numerically ordered index into symbuf
	 *
	 *	and for 70s notes where the text REALLY is
	 *
	 */

	/* declarations */

	register unsigned	i;

	seek(namefd, 0, 0);
	read(namefd, regbuf, 16);

	if (regbuf[0]!=0407 && regbuf[0]!=0410 && regbuf[0]!=0411)
		crash("namelist file - bad format!");

	symoff = regbuf[1] + regbuf[2];
	symlen = regbuf[4];
	if (symlen == 0)
		crash("namelist stripped!");
	if (regbuf[7] != 1)
		symoff =<< 1;
	symoff =+ 16;
	seek(namefd, symoff, 0);

	/* get core for it */

	symcnt = symlen / 6;

	if ((alpha = alloc(symcnt)) < 0)
		crash("no core for alpha!");
	if ((numeric = alloc(symcnt)) < 0)
		crash("no core for numeric!");

	symcnt = symlen / 12;

	/* get core for symbol buffer */

	if ((symbuf = alloc(symlen)) < 0)
		crash("no core for symbuf!");

	/* now initialise vectors and symbol table */

	for (i = 0; i < symcnt; i++) {
		alpha[i] = i;
		numeric[i] = i;
	}

	if (read(namefd, symbuf, symlen) < symlen)
		crash("cannot read whole symbuf!");

	/* now for a quicksort or two */

	qsort(alpha, symcnt, 2, alcomp);
	qsort(numeric, symcnt, 2, numcomp);
#ifdef	_1170
	if((i = albin("_end\0\0\0\0")) == 0)
		{
		crash("cant find \"_end\"!");
		}
	  else
		{
		txtoff = ((i->s_symval+63) >> 6) & 077777;
		}
	DEBUG
		printf("symsort 70 text offset=%u (%o)\n",
			txtoff, txtoff);
#endif	_1170
#ifdef	BIG_UNIX
	segsort();
#endif

	/* assuming they both worked, that is all */

}

/****************************/

#ifdef	BIG_UNIX
char	segsymbol[] "..seg000";

segsort()
{
	register int	i;
	register struct symbol	*sp;
	
	for (i = 0; i < MAXSEG; i++) {
		segsymbol[7] = (i+1) % 10 + '0';
		segsymbol[6] = (i+1)/10%10 + '0';
		segsymbol[5] = (i+1)/100%10 + '0';
		sp = albin(segsymbol);
		if (sp == 0)
			break;
		segbase[i] = sp->s_symval;
	}
	maxseg = i;
}
#endif

/****************************/

albin(string)
char	*string;
{
	/*
	 *	given a "string" (8-chars, null padded) this routine
	 *	will return a pointer to a structure of type "symbol"
	 *	whose symbol field matches the passed "string".
	 *	Otherwise will return null (0);
	 */

	register	i, j, k;
	int	r;

	i = 0;
	j = symcnt;

	while (i != j-1) {
		k = (i+j) / 2;
		DEBUG
			printf("albin loop: i=%u, j=%u, k=%u\n", i, j, k);
		DEBUG
			printf("alcom(%8.8s, %8.8s) ", string, symbuf[alpha[k]].s_symbol);
		r = alcom(string, symbuf[alpha[k]].s_symbol);
		if (r < 0)
			j = k;
		else
			i = k;
		DEBUG
			printf("=> %d\n", r);
	}
	if (alcom(string, symbuf[alpha[i]].s_symbol) == 0)
		return(&symbuf[alpha[i]]);

	return(0);
}

/***************************/

#ifndef	BIG_UNIX
numbin(a)
#endif
#ifdef	BIG_UNIX
numbin(a, ka5)
#endif
unsigned a;
#ifdef	BIG_UNIX
int	ka5;
#endif
{
	/*
	 *	given a value "a" will return a pointer to a structure
	 *	of type "symbol" whose "value" field is
	 *	exactly equal to the value passed.
	 *	otherwise a pointer to the structure
	 *	with the next lowest value is returned.
	 *	if no lower structure exists, null is returned (0).
	 *
	 *	A non-zero value of ka5 will cause us to look
	 *	in the appropriate page for symbols.
	 */

	register	i, j;
	int	k;
#ifdef	BIG_UNIX
	int	seg;
#endif
	int	r;
	register struct symbol	*sp;

#ifdef	BIG_UNIX
	seg = 0;
	if (a<PAGEADR || a>=PAGEADR+020000)
		ka5 = 0;
	if (ka5 != 0) {
		for (i = 0; i < maxseg; i++)
			if (ka5 == segbase[i]) {
				seg = i+1;
				break;
			}
	}

	DEBUG
		printf("numbin: a=%u, seg=%u, ka5=%u\n", a, seg, ka5);
#endif

	i = 0;
	j = symcnt;

	while (i != j-1) {
		k = (i+j) / 2;
		sp = &symbuf[numeric[k]];
		DEBUG {
			printf("numbin loop: i=%u, j=%u, k=%u\n", i, j, k);
#ifndef	BIG_UNIX
			printf("\t\ts_symval=%u\n", sp->s_symval);
#endif
#ifdef	BIG_UNIX
			printf("\t\ts_symval=%u, s_symseg=%u\n", sp->s_symval, sp->s_symseg);
#endif
		}
		if (a < sp->s_symval)
			j = k;
#ifdef	BIG_UNIX
		else if (a > sp->s_symval)
			i = k;
		else if (seg == 0)
			i = k;
		else if (seg < sp->s_symseg)
			j = k;
#endif
		else
			i = k;
	}

	sp = &symbuf[numeric[i]];
	if (a == sp->s_symval)
#ifdef	BIG_UNIX
		if (seg==0 || seg==sp->s_symseg)
#endif
			return(sp);

	if (i == 0)
		return(0);
	/* above should be checked by calling program */

#ifdef	BIG_UNIX
	if (seg != 0)
		/*
		 * It is a far better thing I do to find an even
		 * more distant symbol that is at least in the
		 * same page of memory.
		 */
		for (j = i; j != 0; j--) {
			DEBUG
				printf("numbin: segment test: s_symseg=%u, s_symval=%u\n",
					symbuf[numeric[j]].s_symseg,
					symbuf[numeric[j]].s_symval);
			if (seg == symbuf[numeric[j]].s_symseg) {
				sp = &symbuf[numeric[j]];
				break;
			}
		}
#endif

	return(sp);
}

/***************************/

alcom(a, b)
{
	register	r;
	register char	*p, *q;

	p = a;
	q = b;

	for (r = 0; r < 8; r++) {
		if (*p < *q)
			return(-1);
		if (*p++ > *q++)
			return(1);
	}
	return(0);
}

/*************************/

#ifdef	BIG_UNIX
getnum(adr, ka5)
#endif	BIG_UNIX
#ifndef	BIG_UNIX
getnum(adr)
#endif	BIG_UNIX
unsigned adr;
#ifdef	BIG_UNIX
int	ka5;
#endif	BIG_UNIX
{
	register struct symbol	*p;

#ifdef	BIG_UNIX
	p = numbin(adr, ka5);
#endif	BIG_UNIX
#ifndef	BIG_UNIX
	p = numbin(adr);
#endif	BIG_UNIX
	if (p == 0)
		p = &nullnum;

	return(p);
}

/*********************/

getname(string)
char	*string;
{
	return(albin(string));
}