Ausam/sys/sysd/source/proc4.c
/* 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));
}