|
|
Power 6/32 Unix version 1.2b
static char sccsid[] = "@(#)sym.c 2.11";
#include "cdb.h"
#ifdef BSD41
/* these are used for caching string space info */
export int vcbSbCache;
char *vsbCache;
char *vsbSs;
export int vcbSbFirst, vissLo, vissLim, vissMax;
#define cbProcMax 20
#define iCacheMax 1000 /* number of symbols in cache */
#else
export char *vsbProcHdr;
export char *vsbLHdr;
export char *vsbLnHdr;
export char *vsbLeHdr;
#define cbProcMax 7
#define iCacheMax 256 /* number of symbols in cache */
#endif
export int vcbVarHdr, vcbProcHdr, vcbLHdr, vcbLeHdr, vcbLnHdr;
#ifdef SYSIII
#define cbVarHdr 1
#define cbProcHdr 2
#define cbLHdr 3
#define cbLnHdr 4
#define cbLeHdr 4
#endif
#ifdef BSD41
#define cbVarHdr 0
#define cbProcHdr 0
#define cbLHdr 0
#define cbLnHdr 0
#define cbLeHdr 0
#endif
export long visym; /* last symbol index used */
export long visymGlobal; /* isym of first global */
export pSYMR vsymCur; /* the `current' symbol */
export char *vsbCorefile, *vsbSymfile;
export int vcaseMod; /* has 0 or 040 for case sensitive search */
export int vfnSym, vfnCore; /* the symbol file and core file numbers */
export long visymMax; /* number of symbols */
export long vcbSymFirst; /* byte offset to first symbol */
static SYMR vsymCache[iCacheMax]; /* symbol cache */
#define cbSymCache sizeof(vsymCache)
export long visymLo, visymLim; /* min/max values for what is in cache */
/* F S B C M P */
export FLAGT FSbCmp(sb1, sb2)
char *sb1, *sb2;
{
while ((*sb1|vcaseMod) == (*sb2|vcaseMod)) {
if (*sb1 == chNull)
return(true);
sb1++;
sb2++;
} /* while */
#ifdef BSD42
if ((*sb1 == chNull AND *sb2 == ':')
OR (*sb2 == chNull AND *sb1 == ':'))
return(true);
#endif
return(false);
} /* FSbCmp */
/* F H D R C M P */
export FLAGT FHdrCmp(sbHdr, sb2)
char *sbHdr, *sb2;
{
for ( ; (*sbHdr|vcaseMod) == (*sb2|vcaseMod) ; sbHdr++, sb2++)
if (*sbHdr == chNull)
return(true);
return(*sbHdr == chNull);
} /* FHdrCmp */
/* F P R O C C M P */
export FLAGT FProcCmp(sbProc, sbCheck)
char *sbProc, *sbCheck;
{
char *sbSave;
/* this is ALMOST like FHdrCmp. If sbProc <= cbProcMax chars in length,
* an exact match is required, else it is like FHdrCmp.
* This allows us to have '1234567' match '1234567*'
* BUT '1234' does NOT match '12345' (or 6 or 7 or *)
*/
sbSave = sbProc;
for ( ; (*sbProc|vcaseMod)==(*sbCheck|vcaseMod); sbProc++, sbCheck++) {
if (*sbProc == chNull)
return(true); /* exact match */
} /* for */
#ifdef BSD42
if ( ((*sbProc == ':') AND (*sbCheck == chNull))
OR ((*sbProc == chNull) AND (*sbCheck == ':')) )
return(true);
#else
if ( (*sbProc == chNull)
AND (sbProc-sbSave == cbProcMax) )
return(true);
#endif
return(false);
} /* FProcCmp */
/* S E T C A C H E */
local void SetCache(isym)
long isym;
{
int cRead;
long offset;
if (isym >= visymLo AND isym < visymLim)
return; /* it is already in there, somewhere */
offset = vcbSymFirst + (isym * cbSYMR);
if (lseek(vfnSym, offset, 0) < 0L)
Panic("Bad seek in SetCache");
cRead = read(vfnSym, vsymCache, cbSymCache);
if (cRead < 0)
Panic("Bad read in SetCache (cRead: %d)", cRead);
visymLo = isym;
visymLim = isym + (cRead/cbSYMR);
if (visymLim > visymMax)
visymLim = visymMax;
} /* SetCache */
/* S E T S Y M */
export void SetSym(isym)
long isym;
{
if (isym < 0 OR isym >= visymMax)
Panic("isym out of bounds in SetSym - %d", isym);
visym = isym;
SetCache(isym);
vsymCur = &(vsymCache[isym-visymLo]);
} /* SetSym */
/* S E T N E X T */
export void SetNext(isym)
long isym;
{
if (isym < 0 OR isym >= visymMax)
Panic("isym out of bounds in SetNext - %d", isym);
visym = isym - 1;
if (visym < 0)
vsymCur = symNil;
else SetSym(visym);
} /* SetNext */
/* F N E X T S Y M */
export FLAGT FNextSym(typHit1, typHit2, typStop, sbHit, Cmp)
int typHit1, typHit2, typStop;
char *sbHit;
FLAGT (* Cmp)();
{
int typ, i;
long isym;
isym = visym + 1;
while (isym < visymMax) {
SetCache(isym);
for (i=(isym-visymLo); isym<visymLim; i++, isym++) {
vsymCur = &(vsymCache[i]);
#ifdef REGULUS
typ = vsymCur->type & N_TYPE;
#else
typ = vsymCur->type & ~N_EXT;
#endif
if ( ((typ == typHit1)
OR (typ == typHit2))
AND ((sbHit == sbNil)
OR ((*Cmp)(sbHit, SbInCore(vsymCur->sbSym)))) ) {
visym = isym;
return(true);
}
else if (typ == typStop) {
return(false);
} /* if */
} /* for */
} /* while */
return(false); /* off the end of the symbol table */
} /* FNextSym */
/* I L N F I S Y M */
export int IlnFIsym(isym)
long isym;
{
ADRT adr;
SetNext(isym);
#ifdef SYSIII
if (FNextSym(N_TEXT, N_ABS, N_FN, vsbLnHdr, FHdrCmp))
return(atoi(vsymCur->sbSym+vcbLnHdr));
#endif
#ifdef BSD41
if (FNextSym(stLine, 0, stProc, sbNil, nil)) {
adr = vsymCur->value;
isym = visym;
/* see if there are any more lines w/ same address, take highest */
while (FNextSym(stLine, 0, stProc, sbNil, nil)) {
if (vsymCur->value > adr)
break;
isym = visym;
} /* while */
SetSym(isym);
return(vsymCur->desc);
} /* if */
#endif
return(ilnNil);
} /* IlnFIsym */
/* F N E X T L O C A L */
export FLAGT FNextLocal(fLocal, fParam, sbVar)
FLAGT fLocal, fParam;
char *sbVar;
{
int value;
long isymSave;
char *sbSym;
/* set vsymCur to point to next local (or param) and return true,
* return false if no more, leaving symbol advanced by one.
*/
isymSave = visym;
#ifdef SYSIII
while (FNextSym(N_ABS, N_TEXT, 0, "~", FHdrCmp)) {
sbSym = SbInCore(vsymCur->sbSym);
if (sbSym[1] == '~')
break; /* it's the strart of another procedure, bail out */
value = vsymCur->value;
if ( ((value < 0) AND (!fLocal))
OR ((value > 0) AND (!fParam)) )
continue; /* wrong value */
if (sbVar != sbNil) {
if (!FProcCmp(sbSym+vcbVarHdr, sbVar))
continue; /* wrong name */
}
else {
/* a non-specific request */
if (FHdrCmp(vsbLHdr, sbSym))
continue; /* we aren't interested in line numbers */
} /* if */
return(true);
} /* while */
#endif
#ifdef BSD41
while (FNextSym(stLocal, stParam, stProc, sbNil, nil)) {
/* we have a param OR a local */
if ( ((vsymCur->type == stParam) AND (!fParam))
OR ((vsymCur->type == stLocal) AND (!fLocal)) ) {
if (fParam AND !fLocal) {
SetSym(isymSave+1);
return(false); /* NEVER any params after locals */
} /* if */
continue;
} /* if */
sbSym = SbInCore(vsymCur->sbSym);
if ( (sbVar != sbNil)
AND (!FProcCmp(sbSym, sbVar)) )
continue; /* wrong name */
#ifdef BSD42
if (FSbCmp(sbSym, "int"))
return(false); /* we ran into the next file */
#endif
return(true);
} /* while */
#endif
SetSym(isymSave+1); /* we failed, sigh..... */
return(false);
} /* FNextLocal */
/* A D R F E N D O F P R O C */
export ADRT AdrFEndOfProc(ipd)
int ipd;
{
long isym;
SetNext(vrgPd[ipd].isym);
#ifdef SYSIII
if (FNextSym(N_TEXT, N_ABS, N_FN, vsbLeHdr, FHdrCmp))
return(vsymCur->value);
UError("Can't find end of '%s'", vrgPd[ipd].sbProc);
#endif
#ifdef BSD41
SetNext(vrgPd[ipd].isym+1);
FNextSym(stProc, 0, stSource, sbNil, nil); /* don't care about true/false */
isym = visym;
/* now we back up to first stLine we can find - that should be it! */
while (true) {
SetSym(--isym);
if (vsymCur->type == stLine)
return(vsymCur->value);
} /* while */
#endif
} /* AdrFEndOfProc */
/* A D R F I F D L N */
export ADRT AdrFIfdLn(ifd, iln)
int ifd, iln;
{
long isym, isymLast, ilnCur;
ADRT adr;
SetNext(vrgFd[ifd].isym+1); /* start just AFTER the file symbol */
isym = isymLast = isymNil;
#ifdef SYSIII
while (FNextSym(N_TEXT, N_ABS, N_FN, vsbLnHdr, FHdrCmp)) {
if ((ilnCur=atoi(vsymCur->sbSym+vcbLnHdr)) >= iln) {
#endif
#ifdef BSD41
while (FNextSym(stLine, 0, 0, sbNil, nil)) {
if ((ilnCur=vsymCur->desc) >= iln) {
#endif
isym = (ilnCur == iln) ? visym : isymLast;
break;
} /* if */
isymLast = visym;
} /* while */
if (isym != isymNil) {
SetSym(isym);
adr = vsymCur->value;
}
else {
adr = adrNil;
} /* if */
return(adr);
} /* AdrFIfdLn */
/* I F D L N F A D R */
export void IfdLnFAdr(adr, isym, pifd, piln, pslop)
ADRT adr;
long isym;
int *pifd, *piln, *pslop;
{
int ifd;
long isymLast;
*pifd = ifd = IfdFAdr(adr);
if (ifd == vifdNil)
return;
/* we now have the file, try to get the line number */
if (isym == 0)
isym = vrgFd[ifd].isym+1; /* start just AFTER the file symbol */
SetNext(isym);
isym = isymNil;
isymLast = isymNil;
#ifndef BSD41
while (FNextSym(N_TEXT, N_ABS, N_FN, vsbLnHdr, FHdrCmp)) {
if ((vsymCur->value) >= adr) {
isym = (vsymCur->value == adr) ? visym : isymLast;
break;
} /* if */
isymLast = visym;
} /* while */
#else
/* we want the HIGHEST line number that applies to a given address */
while (FNextSym(stLine, 0, stSource, sbNil, nil)) {
if ((vsymCur->value) >= adr) {
if ((vsymCur->value > adr)
AND (isym != isymNil))
break;
isym = (vsymCur->value == adr) ? visym : isymLast;
} /* if */
isymLast = visym;
} /* while */
#endif
*pslop = -1;
if (isym != isymNil) {
SetSym(isym);
#ifdef BSD41
*piln = vsymCur->desc;
#else
*piln = atoi(vsymCur->sbSym+vcbLnHdr);
#endif
*pslop = adr - vsymCur->value;
}
else {
*piln = ilnNil;
} /* if */
} /* IfdLnFAdr */
#ifdef BSD41
/* I N I T S S */
export void InitSs()
{
if (vcbSbCache == 0) {
/* we will read the whole thing in. This means that we
* aren't really using the cacheing mechanism, but we
* leave it for compatibility with systems where we can't
* get away with this.
*/
vcbSbCache = vissMax;
} /* if */
vsbCache = malloc(vcbSbCache);
SetIss(0); /* force read first section */
} /* InitSs */
/* S B I N C O R E */
/* neither export NOR local - it is a macro for NON-BSD systems */
char * SbInCore(sb)
char *sb;
{
long iss;
iss = (long) sb;
if (iss == -1)
return(sbNil);
if (iss & bitHigh)
return((char *)(iss & ~bitHigh)); /* a cdb string */
/* an a.out string */
SetIss(iss);
return(vsbSs);
} /* SbInCore */
/* S E T I S S */
export void SetIss(iss)
int iss;
{
long ret, offset, cRead, issSave;
char *sbTest;
/* printf("SetIss entered with iss=%d\n",iss); */
if (iss < 0 OR iss >= vissMax)
Panic("Iss out of bounds");
if (iss >= vissLo AND iss < vissLim) {
/* make sure the WHOLE string is in the cache */
issSave = iss;
sbTest = vsbCache + (iss - vissLo);
while ((iss < vissLim) AND (*sbTest != chNull)) {
sbTest++;
iss++;
} /* while */
iss = issSave;
if (*sbTest == chNull) {
vsbSs = vsbCache + (iss - vissLo);
return;
}
} /* if */
/* not in (or not ALL in) the cache - make it the first thing */
offset = vcbSbFirst + iss;
/* printf("Seeking in symbols file at offset %d\n", offset); */
if ((ret=lseek(vfnSym, offset, 0)) < 0L)
Panic("Bad seek in SetIss");
cRead = read(vfnSym, vsbCache, vcbSbCache);
if (cRead < 0)
Panic("Bad read in SetIss (cRead: %d)", cRead);
vissLo = iss;
vissLim = iss + cRead;
vsbSs = vsbCache + (iss - vissLo);
} /* SetIss */
#endif
/* I N I T F D P D */
export void InitFdPd()
{
short ipd, i;
FLAGT fGotit, fStop;
ADRT adr;
char *sbTemp, *sbDot;
char sbWorking[cbVarMax+5]; /* used for non-bsd41 stuff */
pFDR fd;
pPDR pd;
#ifdef SYSIII
/* set up line number names */
vsbLHdr = "~_l";
vsbLnHdr = "~_lN";
vsbLeHdr = "~_lE";
vsbProcHdr = "~~";
vityMac = 0;
#endif
vcbVarHdr = cbVarHdr;
vcbProcHdr = cbProcHdr;
vcbLHdr = cbLHdr;
vcbLeHdr = cbLeHdr;
vcbLnHdr = cbLnHdr;
visymLo = 0;
visymLim = -1;
/* first we have to see how big file and proc arrays should be */
vifdMac = 0;
vipdMac = 0;
SetNext(isym0);
fStop = false; /* goes true when we are processing 'end.o' */
#ifdef SYSIII
while (FNextSym(N_FN, N_TEXT, 0, sbNil, nil)) {
if (vsymCur->type == N_FN) {
if (fStop)
break;
++vifdMac;
}
else if (FHdrCmp(vsbProcHdr, SbInCore(vsymCur->sbSym))) {
++vipdMac;
if (FSbCmp(SbInCore(vsymCur->sbSym+vcbProcHdr), "_end_"))
fStop = true; /* will stop on next file symbol */
} /* if */
} /* while */
#ifndef REGULUS
vifdMac -= 1; /* ignore crt0.o */
#endif
#endif
#ifdef BSD41
while (FNextSym(stSource, stProc, 0, sbNil, nil)) {
if (vsymCur->type == stSource) {
/* a file {ning */
if (fStop)
break;
++vifdMac;
}
else {
/* a procedure */
++vipdMac;
if (FSbCmp(SbInCore(vsymCur->sbSym), "_end_"))
fStop = true; /* will stop on next file symbol */
} /* if */
} /* while */
#endif
if (vipdMac == 0)
UError("It appears that NO files have debugging information");
if (!fStop)
printf("WARNING! 'end.o' was not loaded with this program\n");
vifdTemp = vifdMac++;
vifd = vifdNil = vifdMac++;
vrgFd = (pFDR) malloc(vifdMac * cbFDR); /* allocate the arrays */
vcbTot += vifdMac * cbFDR;
vrgPd = (pPDR) malloc(vipdMac * cbPDR);
vcbTot += vipdMac * cbPDR;
/* we scan through again, filling the arrays */
fd = vrgFd;
pd = vrgPd;
ipd = 0;
SetNext(isym0);
fStop = false;
#ifdef SYSIII
while (FNextSym(N_FN, N_TEXT, 0, sbNil, nil)) {
if (vsymCur->type == N_FN) {
#ifndef REGULUS
if (FSbCmp(vsymCur->sbSym, "crt0.o"))
continue;
#endif
#endif
#ifdef BSD41
while (FNextSym(stSource, stProc, 0, sbNil, nil)) {
if (vsymCur->type == stSource) {
#endif
if (fStop)
break; /* we have finished processing end.c */
fd->adrStart = vsymCur->value;
fd->isym = visym;
fd->ipd = ipd;
fd->ilnMac = ilnNil;
fd->rgLn = (uint *) 0;
fd->fHasDecl = true; /* will go false if none - IfdFOpen */
fd->fWarned = false;
#ifdef SYSIII
sbTemp = sbWorking;
strncpy(sbTemp, vsymCur->sbSym, cbVarMax);
sbTemp[cbVarMax] = chNull; /* make sure we have a clean buffer */
sbDot = strrchr(sbTemp, '.'); /* find last period */
if (sbDot != nil) {
sbDot[1] = 'c'; /* somewhat presumptuous, but I write in C */
sbDot[2] = 0;
}
else {
/* this will help if name is `01234567' and lost the `.c' */
sbTemp[cbVarMax] = '.';
sbTemp[cbVarMax+1] = 'c';
sbTemp[cbVarMax+2] = 0;
} /* if */
fd->sbFile = malloc(cbVarMax+5);
vcbTot += cbVarMax + 5;
#endif
#ifdef BSD41
#ifdef BSD42
sbTemp = SbInCore(SbSafe(SbInCore(vsymCur->sbSym)));
#else
sbTemp = SbInCore(vsymCur->sbSym);
#endif
fd->sbFile = malloc(strlen(sbTemp)+2);
#endif
strcpy(fd->sbFile, sbTemp);
fd++;
#ifdef SYSIII
}
else if (FHdrCmp(vsbProcHdr, vsymCur->sbSym)) {
#endif
#ifdef BSD41
}
else {
#endif
adr = vsymCur->value;
pd->adrStart = adr;
pd->isym = visym;
#ifdef SYSIII
sbTemp = sbWorking;
/* given ~~foo, copy ~foo */
strncpy(sbTemp, vsymCur->sbSym+1, cbVarMax-1);
/* make it _foo */
sbTemp[0] = '_';
sbTemp[7] = chNull;
pd->sbProc = malloc(cbVarMax+2);
vcbTot += cbVarMax + 2;
#endif
#ifdef BSD41
#ifdef BSD42
sbTemp = SbInCore(SbSafe(SbInCore(vsymCur->sbSym)));
#else
sbTemp = SbInCore(vsymCur->sbSym);
#endif
pd->sbProc = malloc(strlen(sbTemp)+2);
#endif
strcpy(pd->sbProc, sbTemp);
pd++;
ipd++;
#ifdef BSD41
if (FSbCmp(sbTemp, "_end_")) {
fStop = true; /* causes us to stop on next file symbol */
}
#else
if (FSbCmp(sbTemp, "__end_"))
fStop = true; /* causes us to stop on next file symbol */
#endif
} /* if */
} /* while */
visymGlobal = visym;
vipd = ipdNil;
printf("%d source files, %d procedures\n", vifdMac-2, vipdMac);
fd = vrgFd + vifdTemp;
fd->adrStart = 0; /* we use vifdTemp for `other' files */
fd->sbFile = sbNil;
fd->fHasDecl = false;
fd->fWarned = true; /* we assume warning here isn't important */
fd->isym = isym0;
fd->ipd = ipdNil;
fd->ilnMac = ilnNil;
fd->rgLn = (uint *) 0;
fd = vrgFd + vifdNil; /* we use vifdNil as a `catchall' */
fd->adrStart = 0;
fd->sbFile = "no src file";
fd->fHasDecl = false;
fd->fWarned = true;
fd->isym = isym0;
fd->ipd = ipdNil;
fd->ilnMac = ilnNil;
fd->rgLn = (uint *) 0;
#ifdef SYSIII
/* the following gives us one more char in procedure name, if it's there */
SetNext(visymGlobal);
for (i=0; i<vipdMac; i++) {
fGotit = false;
while (FNextSym(N_TEXT, 0, 0, vrgPd[i].sbProc, FProcCmp)) {
if (vsymCur->value == vrgPd[i].adrStart) {
fGotit = true;
break;
} /* if */
} /* while */
if (!fGotit) {
/* try it from the top of globals again */
SetNext(visymGlobal);
while (FNextSym(N_TEXT, 0, 0, vrgPd[i].sbProc, FProcCmp)) {
if (vsymCur->value == vrgPd[i].adrStart) {
fGotit = true;
break;
} /* if */
} /* while */
} /* if */
if (!fGotit) {
/* Can't find it, I hope it is a static, else oooops! */
strncpy(vrgPd[i].sbProc, vrgPd[i].sbProc+1, 6);
vrgPd[i].sbProc[6] = 0;
}
else {
/* we found _foo, copy foo into name area */
strncpy(vrgPd[i].sbProc, vsymCur->sbSym+1, 7);
vrgPd[i].sbProc[7] = 0;
} /* if */
} /* for */
#endif
} /* InitFdPd */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.