|
|
1.1 root 1: #include <a.out.h>
2: #include "symtab.pri"
3: #include "dtype.pri"
4: #include "symbol.h"
5: #include "stab.h"
6: #include "core.pub"
7: SRCFILE("bsdsymtab.c")
8:
9: char *strchr(char *, int);
10: char *memset(char *, int, int);
11: char *memcpy(char *, char *, int);
12: int nccdemangle(char **, char *);
13: void SymbolStats();
14:
15: BsdSymTab::BsdSymTab(Core* c, int fd, SymTab *i, long r):(c, fd, i, r)
16: {
17: hdr = new exec;
18: bsdshare = 0;
19: }
20:
21: BsdSymTab::~BsdSymTab()
22: {
23: delete hdr;
24: if (bsdshare)
25: delete bsdshare;
26: }
27:
28: char *BsdSymTab::gethdr()
29: {
30: if( lseek( fd, 0L, 0 ) == -1 || !ReadOK(fd, (char*)hdr, sizeof *hdr) )
31: return SysErr( "symbol table: " );
32: _magic = hdr->a_magic;
33: // if( N_BADMAG(*hdr) || hdr->a_trsize || hdr->a_drsize )
34: if( N_BADMAG(*hdr) )
35: return "symbol table: not executable text";
36: entries = hdr->a_syms/sizeof(nlist);
37: return 0;
38: }
39:
40: int BsdSymTab::endtext()
41: {
42: exec h = *hdr;
43: return N_DATADDR(h);
44: }
45:
46: Block *BsdSymTab::gatherfunc(Func *func)
47: {
48: register struct nlist *f, *n;
49: register Block *ablk, *lblk;
50: Var *arg = 0, *lcl = 0;
51: register Stmt *stmt = 0;
52: long bfun = func->begin, size = func->size, i;
53: char *so = func->source()->_text;
54: BsdType *bsd = func->source()->bsdp;
55: char *subtype;
56:
57: ++FunctionGathered;
58: SymbolStats();
59: IF_LIVE( bfun < 0 || bfun+size > entries ) return 0;
60: if (size == 0)
61: return fakeblk();
62: if( !(n = f = nlistvector(bfun,size+1)) ) return 0;
63: IF_LIVE( n->n_type != N_FUN ) return 0;
64: ablk = new Block( this, 0, 0, sf("%s().arg_blk",n->n_un.n_name) );
65: lblk = new Block( this, ablk, 0, sf("%s().lcl_blk",n->n_un.n_name) );
66: ablk->child = lblk;
67: for( i = 0; i < size; ++i, ++n ){
68: switch( n->n_type ){
69: case N_PSYM:
70: gathervar( n, &arg, ablk, U_ARG, bsd );
71: break;
72: case N_LSYM:
73: subtype = strchr(n->n_un.n_name, ':');
74: if (!subtype || *++subtype != '(')
75: break;
76: gathervar( n, &lcl, lblk, U_AUT, bsd );
77: break;
78: case N_STSYM:
79: case N_LCSYM:
80: subtype = strchr(n->n_un.n_name, ':');
81: if (!subtype || *++subtype != 'V')
82: break;
83: n->n_value += relocation;
84: gathervar( n, &lcl, lblk, U_STA, bsd );
85: break;
86: case N_RSYM:
87: gathervar( n, &lcl, lblk, U_REG, bsd );
88: break;
89: case N_FUN:
90: case N_SLINE:
91: n->n_value += relocation;
92: if( stmt ) {
93: if ( n->n_desc > stmt->lineno )
94: func->lines.hi = n->n_desc;
95: stmt->range.hi = n->n_value;
96: }
97: stmt = new Stmt(this,lblk,stmt);
98: if( !ablk->stmt ) ablk->stmt = stmt;
99: stmt->lineno = n->n_desc;
100: stmt->range.lo = n->n_value;
101: if( !ablk->range.lo )
102: ablk->range.lo = n->n_value;
103: ablk->range.hi = n->n_value;
104: break;
105: }
106: }
107: if( stmt )
108: stmt->range.hi = n->n_value + relocation;
109: delete f;
110: uncfront( ablk->var, (char *)0 );
111: uncfront( lblk->var, (char *)0 );
112: return ablk;
113: }
114:
115: void BsdSymTab::gathervar( nlist *n, Var **v, Block *b, UDisc d, BsdType *bt )
116: {
117: IF_LIVE( !v ) return;
118: if( *n->n_un.n_name == ' ')
119: return;
120: char *marker = strchr( n->n_un.n_name, ':');
121: if (!marker)
122: marker = n->n_un.n_name + strlen(n->n_un.n_name);
123: else if (marker[1] == ':') { //Special Ncc symbol
124: marker = strchr( &marker[2], ':');
125: if (!marker) {
126: marker = n->n_un.n_name + strlen(n->n_un.n_name);
127: while (*++marker == 0)
128: ;
129: marker--;
130: }
131: }
132: *marker++ = 0;
133: *v = new Var( this, b, *v, d, n->n_un.n_name );
134: if( b && !b->var ) b->var = *v;
135: (*v)->range.lo = n->n_value;
136: (*v)->type = bt->gettype(marker);
137: }
138:
139: void BsdSymTab::gathervar( nlist *n, Var **v, Block *b, UDisc d)
140: {
141: DType dt;
142:
143: IF_LIVE( !v ) return;
144: *v = new Var( this, b, *v, d, n->n_un.n_name );
145: if( b && !b->var ) b->var = *v;
146: (*v)->range.lo = n->n_value;
147: (*v)->type = dt;
148: (*v)->type.pcc = n->n_desc;
149: }
150:
151: char *BsdSymTab::gettbl()
152: {
153: base = new nlist[entries];
154: symoff = (nlist*)N_SYMOFF(*hdr);
155: if( lseek(fd, (long)symoff, 0) == 1
156: || !ReadOK(fd, (char*)base, hdr->a_syms)
157: || !ReadOK(fd, (char*)&strsize, 4) ){
158: delete base; base = 0;
159: return SysErr( "symbol table: " );
160: }
161: strings = new char[strsize];
162: if( lseek( fd, -4, 1 ) == -1 || !ReadOK(fd, strings, strsize) ){
163: delete strings; strings = 0;
164: delete base; base = 0;
165: return SysErr( "strings table: " );
166: }
167: strcpy( strings, "???" ); /* zero string index */
168: return 0;
169: }
170:
171: Source *BsdSymTab::tree()
172: {
173: register nlist *n, *base_entries;
174: Source *src = 0;
175: Func *func = 0;
176: Block *fake = fakeblk();
177: Var *glb = 0, *fst = 0, *resolve;
178: // UType *u;
179: register long regstrings, inafunc = 0, inasrc = 0;
180: long lastline, funcstart = 0, lgfound = 0;
181: char *equal, *subtype;
182: BsdType *bsd = 0;
183: DType *t;
184:
185: if( _warn = gettbl() ) return 0;
186: base_entries = base+entries;
187: regstrings = (long) strings;
188: glb = globregs(_blk, _core->nregs() );
189: bsdshare = new BsdTShare;
190: for( n = base; n < base_entries; ++n ){
191: n->n_un.n_strx += (long) regstrings;
192: if( inasrc && n->n_un.n_name && (equal = strchr(n->n_un.n_name, '=')))
193: bsd->parsetype(equal, n->n_un.n_name);
194: switch( n->n_type ){
195: case N_ABS|N_EXT:
196: if( n->n_un.n_name[0] != '_' ) break; /* ? */
197: case N_BSS|N_EXT:
198: case N_DATA|N_EXT:
199: if( *n->n_un.n_name == '_' ) ++n->n_un.n_name;
200: nccdemangle(&n->n_un.n_name, (char *)0);
201: resolve = (Var*)idtosym(U_GLB, n->n_un.n_name, 0);
202: n->n_value += relocation;
203: if( resolve ){
204: if( !resolve->range.lo )
205: resolve->range.lo = n->n_value;
206: } else {
207: n->n_desc = LONG;
208: gathervar( n, &glb, _blk, U_GLB );
209: break;
210: }
211: break;
212: case N_GSYM:
213: if( !inasrc ) break;
214: subtype = strchr(n->n_un.n_name, ':');
215: if (!subtype)
216: break;
217: *subtype = 0;
218: nccdemangle(&n->n_un.n_name, (char *)0);
219: if( !idtosym(U_GLB, n->n_un.n_name, 0) )
220: gathervar( n, &glb, _blk, U_GLB, bsd );
221: break;
222: case N_LCSYM:
223: case N_STSYM:
224: if( !inasrc || !src || !src->blk ) break;
225: subtype = strchr(n->n_un.n_name, ':') + 1;
226: if (*subtype != 'S')
227: break;
228: n->n_value += relocation;
229: gathervar( n, &fst, src->blk, U_FST, bsd );
230: break;
231: case N_SLINE:
232: lastline = n->n_desc;
233: if (funcstart) {
234: funcstart = 0;
235: func->lines.lo = lastline;
236: }
237: break;
238: case N_BINCL: // Include files for type indexing
239: bsd->addinclude(n->n_un.n_name, 1);
240: break;
241: case N_EXCL:
242: bsd->addinclude(n->n_un.n_name, 0);
243: break;
244: case N_SO:
245: if (inafunc) {
246: inafunc = 0;
247: func->lines.hi = lastline;
248: func->size = n-base - func->begin;
249: }
250: // Directory entry in 4.0?
251: if (n->n_un.n_name[strlen(n->n_un.n_name)-1] == '/') {
252: inasrc = 0;
253: break;
254: }
255: if (!strcmp(n->n_un.n_name, "libg.s")) {
256: lgfound = 1;
257: inasrc = 0;
258: break;
259: }
260: inasrc = 1;
261: src = new Source(this,src,n->n_un.n_name,0);
262: bsd = src->bsdp = new BsdType(src, bsdshare);
263: func = 0;
264: inafunc = 0;
265: fst = 0;
266: n += 12; // Through away type info
267: break;
268: case N_TEXT|N_EXT:
269: if( *n->n_un.n_name == '_' ) ++n->n_un.n_name;
270: nccdemangle(&n->n_un.n_name, (char *)0);
271: if( idtosym(U_FUNC, n->n_un.n_name, 0) ) break;
272: func = new Func(this,0,0,0,n->n_un.n_name);
273: func->range.lo = n->n_value + relocation;
274: func->_blk = fake;
275: t = new DType;
276: t->pcc = LONG;
277: func->type = t->incref();
278: func->type.pcc = FTN;
279: break;
280: case N_FUN:
281: if (inafunc) {
282: inafunc = 0;
283: func->lines.hi = lastline;
284: func->size = n-base - func->begin;
285: }
286: if( !inasrc || !src ) break;
287: inafunc = 1;
288: ++FunctionStubs;
289: subtype = strchr(n->n_un.n_name, ':');
290: *subtype++ = 0;
291: nccdemangle(&n->n_un.n_name, (char *)0);
292: func = new Func(this,src,func,n-base,n->n_un.n_name);
293: if( !src->child ) src->child = src->linefunc = func;
294: funcstart = 1;
295: func->range.lo = n->n_value + relocation;
296: t = new DType;
297: *t = bsd->gettype(subtype);
298: func->type = t->incref();
299: func->type.pcc = FTN;
300: break;
301: }
302: }
303: while( src && src->lsib ) src = (Source*) src->lsib;
304: if( base ) { delete base; base = 0; }
305: if (!lgfound)
306: _warn = "should be linked with ld -g";
307: return src;
308: }
309:
310: Var *BsdSymTab::gatherutype(UType *u)
311: {
312: Var *first = 0, *v = 0;
313: char *memname, *cp;
314: int file, offset;
315: int bitsize, bitoffset;
316: int isenum = (u->type.pcc == ENUMTY);
317:
318: memname = u->encode;
319: if (!memname)
320: return first;
321: ++UTypeGathered;
322: SymbolStats();
323: while (*memname != ';') {
324: cp = strchr(memname, ':');
325: *cp++ = 0;
326: if (isenum) {
327: v = new Var( this, 0, v, U_MOT, memname );
328: v->range.lo = u->bsdp->toint(cp);
329: v->type.pcc = MOETY;
330: if( !first ) first = v;
331: memname = strchr(cp, ',') + 1;
332: continue;
333: }
334: u->bsdp->toindices(cp, file, offset);
335: cp = strchr(cp, ')') + 2;
336: bitoffset = u->bsdp->toint(cp);
337: cp = strchr(cp, ',') + 1;
338: bitsize = u->bsdp->toint(cp);
339: v = new Var( this, 0, v, U_MOT, memname );
340: v->type = u->bsdp->gettype(file, offset);
341: if ((bitsize & 0x7) || (bitoffset & 0x7)) {
342: v->range.lo = ((bitoffset >> 5) << 5) +
343: 32 - bitsize - (bitoffset & 0x1f);
344: v->type.pcc = UBITS;
345: v->type.dim = bitsize;
346: } else
347: v->range.lo = bitoffset >> 3;
348: if( !first ) first = v;
349: memname = strchr(cp, ';') + 1;
350: }
351: uncfront(first, u->_text);
352: return first;
353: }
354:
355: nlist *BsdSymTab::nlistvector(long start, long size )
356: {
357: struct nlist *n;
358: int i;
359:
360: lseek(fd, (long) (symoff + start), 0);
361: n = new nlist[size];
362: IF_LIVE( !ReadOK(fd, (char*) n, size * sizeof *n) ){
363: delete n;
364: return 0;
365: }
366: for( i = 0; i < size; ++i )
367: n[i].n_un.n_strx += (long) strings;
368: return n;
369: }
370:
371: BsdTShare::BsdTShare()
372: {
373: }
374:
375: BsdTShare::~BsdTShare()
376: {
377: for(BsdTFile *f = file; f < &file[used]; f++) {
378: for (int i = 0; i < f->ntypes; i++)
379: delete f->type[i];
380: delete f->type;
381: }
382: delete file;
383: }
384:
385: int BsdTShare::addfile(char *fname, int flag)
386: {
387: BsdTFile *f;
388: int i;
389:
390: if (used == nfiles) { // Grow the number of files
391: nfiles += 10;
392: f = new BsdTFile[nfiles];
393: for (i = 0; i < used; i++)
394: f[i] = file[i];
395: delete file;
396: file = f;
397: }
398: f = &file[used];
399: f->fname = fname; // Initialize
400: f->ntypes = 20;
401: f->type = new DTypep[20];
402: if (flag) { // add builtins
403: static int typeindex[] = {
404: 0, INT, CHAR, LONG, SHORT, UCHAR, USHORT,
405: ULONG, UNSIGNED, FLOAT, DOUBLE, INT, UNDEF
406: };
407: for(i = 1; i < sizeof(typeindex)/sizeof(int); i++) {
408: f->type[i] = new DType;
409: f->type[i]->pcc = typeindex[i];
410: }
411: }
412: return used++;
413: }
414:
415: int BsdTShare::findfile(char *fname)
416: {
417: for(BsdTFile *f = &file[used-1]; f >= file; f--)
418: if (!strcmp(f->fname, fname))
419: return f - file;
420: return -1;
421: }
422:
423: DType *BsdTShare::findtype(int fnum, int offset)
424: {
425: if (offset >= file[fnum].ntypes)
426: return 0;
427: return file[fnum].type[offset];
428: }
429:
430: char *BsdTShare::filename(int fnum)
431: {
432: return file[fnum].fname;
433: }
434:
435: void BsdTShare::entertype(int fnum, int offset, DTypep dp)
436: {
437: BsdTFile *f = &file[fnum];
438: if (offset >= f->ntypes) {
439: int n = offset + 5; // Room to spare
440: DTypepar nda = new DTypep[n];
441: for(int i = 0; i < f->ntypes; i++)
442: nda[i] = f->type[i];
443: delete f->type;
444: f->type = nda;
445: f->ntypes = n;
446: }
447: f->type[offset] = dp;
448: }
449:
450: BsdType::BsdType(Source *sp, BsdTShare *sh)
451: {
452: share = sh;
453: src = sp;
454: utypeindex = 0;
455: nfiles = 10;
456: filemap = new int[nfiles];
457: filemap[0] = share->addfile(src->text(), 1);
458: used = 1;
459: }
460:
461: BsdType::~BsdType()
462: {
463: delete filemap;
464: }
465:
466: void BsdType::addinclude(char *fname, int flg)
467: {
468: if (used == nfiles) { // More mapping space needed
469: nfiles += 10;
470: int *map = new int[nfiles];
471: for(int i = 0; i < used; i++)
472: map[i] = filemap[i];
473: delete filemap;
474: filemap = map;
475: }
476: if (flg)
477: filemap[used] = share->addfile(fname);
478: else
479: filemap[used] = share->findfile(fname);
480: used++;
481: }
482:
483: /*
484: * Parse the yucky '=' symbol table information
485: * Possiblities:
486: * (a,b)=(x,y) usually typedefs
487: * (a,b)=*(x,y) pointers
488: * (a,b)=f(x,y) functions
489: * (a,b)=ar(0,1);lo;hi;(x,y) arrays
490: * (a,b)=r(x,y);lo;hi; range - who cares!
491: * (a,b)=eN:size,...; enum encoding
492: * (a,b)=sSN:(x,y),off,size;...;; structure encoding
493: * (a,b)=uSN:(x,y),off,size;...;; union encoding
494: * (a,b)=x{esu}name: ptr to undefined utype
495: */
496: void BsdType::parsetype(char *equalptr, char *name)
497: {
498: int file, offset;
499: int pfile, poffset;
500: struct DType *dp, *dp1;
501: int ssize;
502: char stype;
503: char sname[100], *utypename;
504:
505: char *nextequal = strchr(equalptr+1, '=');
506: if (nextequal)
507: parsetype (nextequal, name);
508: register char *tp = equalptr;
509: while (*--tp != '(')
510: ;
511: toindices(tp, file, offset);
512: register char *cp = equalptr + 1;
513: switch ( *cp ) {
514: case '(':
515: toindices(cp, pfile, poffset);
516: dp1 = share->findtype(pfile,poffset);
517: dp = new DType;
518: dp->pcc = dp1->pcc;
519: dp->dim = dp1->dim;
520: dp->univ = dp1->univ;
521: share->entertype(file, offset, dp);
522: cp = strchr(cp, ')') + 1;
523: break;
524: case '*':
525: toindices(++cp, pfile, poffset);
526: cp = strchr(cp, ')') + 1;
527: dp = new DType;
528: dp->univ = share->findtype(pfile,poffset);
529: if (!dp->univ)
530: dp->over = (pfile << 16) | poffset;
531: dp->pcc = PTR;
532: share->entertype(file, offset, dp);
533: break;
534: case 'f':
535: toindices(++cp, pfile, poffset);
536: cp = strchr(cp, ')') + 1;
537: dp = new DType;
538: dp->univ = share->findtype(pfile,poffset);
539: if (!dp->univ)
540: dp->over = (pfile << 16) | poffset;
541: dp->pcc = FTN;
542: share->entertype(file, offset, dp);
543: break;
544: case 'a':
545: cp = strchr(cp, ';') + 1;
546: cp = strchr(cp, ';') + 1;
547: dp = new DType;
548: dp->dim = toint(cp) + 1;
549: dp->pcc = ARY;
550: cp = strchr(cp, ';') + 1;
551: toindices(cp, pfile, poffset);
552: cp = strchr(cp, ')') + 1;
553: dp->univ = share->findtype(pfile,poffset);
554: if (!dp->univ)
555: dp->over = (pfile << 16) | poffset;
556: share->entertype(file, offset, dp);
557: break;
558: case 'r':
559: cp = strchr(cp, ';') + 1;
560: cp = strchr(cp, ';') + 1;
561: cp = strchr(cp, ';') + 1;
562: break;
563: case 'x':
564: stype = *++cp;
565: ssize = 0;
566: cp++;
567: for(char *to = utypename = sname; *cp != ':'; )
568: *to++ = *cp++;
569: *to = 0;
570: cp++;
571: goto xentry;
572: case 's':
573: case 'u':
574: case 'e':
575: if (*--tp == 'T' || *tp == 't') {
576: *strchr(name, ':') = 0;
577: utypename = name;
578: } else {
579: sprintf(sname, "%s.%d",
580: basename(share->filename(file)),
581: offset);
582: utypename = sname;
583: }
584: stype = *cp++;
585: ssize = toint(cp);
586: if (stype == 'e')
587: ssize = 1;
588: xentry:
589: UType *u = (UType*) src->symtab->idtosym(
590: U_UTYPE, utypename, 0);
591: if( u ){
592: if( u->range.lo < ssize ){
593: if( u->encode )
594: delete u->encode;
595: u->encode = toutypestr(cp, stype);
596: u->range.lo = ssize;
597: u->bsdp = this;
598: } else if (ssize)
599: delete toutypestr(cp, stype);
600: } else {
601: ++UTypeStubs;
602: if (utypename == sname)
603: utypename = sf("%s", sname);
604: u = new UType(src->symtab,
605: ssize ? toutypestr(cp, stype) : (char *)0,
606: utypename, this);
607: u->range.lo = ssize;
608: switch(stype) {
609: case 'e':
610: u->type.pcc = ENUMTY;
611: break;
612: case 's':
613: u->type.pcc = STRTY;
614: break;
615: case 'u':
616: u->type.pcc = UNIONTY;
617: break;
618: }
619: u->type.univ = u;
620: u->rsib = src->symtab->utype;
621: src->symtab->utype = u;
622: }
623: if (!share->findtype(file, offset)) {
624: dp = new DType;
625: dp->univ = u;
626: dp->pcc = u->type.pcc;
627: share->entertype(file, offset, dp);
628: }
629: break;
630: default:
631: break;
632: }
633: memset(equalptr, ' ', cp - equalptr);
634: }
635:
636: DType BsdType::gettype(char *string)
637: {
638: int file, offset;
639: string = strchr(string, '(');
640: toindices(string, file, offset);
641: return gettype(file, offset);
642: }
643:
644: DType BsdType::gettype(int fnum, int offset)
645: {
646: return chain(share->findtype(fnum, offset));
647: }
648:
649: DType BsdType::chain(DType *dp)
650: {
651: DType d;
652:
653: if (!dp) { // Shouldn't happen - fix this if ever figure
654: d.pcc = INT; // out how the include file references are
655: return d; // shared. I give up ....
656: }
657: d.pcc = dp->pcc;
658: d.dim = dp->dim;
659: d.univ = dp->univ;
660: if( d.pcc & TMASK ){
661: if (!dp->univ)
662: dp->univ = share->findtype(dp->over>>16,
663: dp->over&0xffff);
664: d.univ = new DType;
665: *(d.ref()) = chain(dp->ref());
666: }
667: return d;
668: }
669:
670: void BsdType::toindices(char *cp, int &fnum, int &offset)
671: {
672: while (*cp++ != '(')
673: ;
674: fnum = filemap[toint(cp)];
675: while (*cp++ != ',')
676: ;
677: offset = toint(cp);
678: }
679:
680: int BsdType::toint(char *cp)
681: {
682: int cnt = 0;
683: int sign = 1;
684:
685: if (*cp == '-') {
686: sign = -1;
687: cp++;
688: }
689: while (*cp >= '0' && *cp <= '9')
690: cnt = cnt * 10 + *cp++ - '0';
691: return cnt * sign;
692: }
693:
694: char *BsdType::toutypestr(char *cp, int c)
695: {
696: char *bp;
697: int size;
698: char *cstart;
699: register char *to, *from;
700:
701: if (c == 'e') {
702: cstart = cp;
703: for(size = 0; ; cp++) {
704: if (*cp == '\\') {
705: *cp++ = ' ';
706: *cp = ' ';
707: }
708: if (*cp != ' ')
709: size++;
710: if (*cp == ';') /* Enum delimiter */
711: break;
712: }
713: } else {
714: while (*cp >= '0' && *cp <= '9')
715: *cp++ = ' ';
716: cstart = cp;
717: for(size = 0; ; cp++) {
718: if (*cp == '\\') {
719: *cp++ = ' ';
720: *cp = ' ';
721: char *nextequal = strchr(cp+1, '=');
722: if (nextequal)
723: parsetype (nextequal, nextequal);
724: }
725: if (*cp != ' ')
726: size++;
727: if (*cp == ';' && *(cp-1) == ';')
728: break;
729: }
730: }
731: to = bp = new char[size + 1];
732: from = cstart;
733: for (register i = size; size--; ) {
734: while (*from == ' ')
735: from++;
736: *to++ = *from;
737: *from++ = ' ';
738: }
739: *to = 0;
740: return bp;
741: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.