|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)stab.c 5.2 (Berkeley) 10/23/85";
9: #endif not lint
10:
11: /*
12: * Procedures to put out symbol table information
13: * and stabs for separate compilation type checking.
14: * These use the .stabs, .stabn, and .stabd directives.
15: */
16:
17: #include "whoami.h"
18: #ifdef PC
19: /* and the rest of the file */
20: # include "0.h"
21: # include "objfmt.h"
22: # include "yy.h"
23: # include <stab.h>
24:
25: /*
26: * additional symbol definition for <stab.h>
27: * that is used by the separate compilation facility --
28: * eventually, <stab.h> should be updated to include this
29: */
30:
31: # include "pstab.h"
32: # include "pc.h"
33:
34:
35: #define private static
36:
37: int oldway = 0;
38:
39: /*
40: * absolute value: line numbers are negative if error recovery.
41: */
42: #define ABS( x ) ( x < 0 ? -x : x )
43: long checksum();
44:
45: /*
46: * Generate information about variables.
47: */
48:
49: stabgvar (p, length, line)
50: struct nl *p;
51: int length, line;
52: {
53: putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x",
54: 0, p->symbol, N_PC, N_PGVAR, ABS(line)
55: );
56: if (oldway != 0) {
57: oldstabgvar(p->symbol, p2type(p->type), 0, length, line);
58: } else if (opt('g')) {
59: putprintf("\t.stabs\t\"%s:G", 1, p->symbol);
60: gentype(p->type);
61: putprintf("\",0x%x,0,0x%x,0", 0, N_GSYM, length);
62: }
63: }
64:
65: stablvar (p, offset, length)
66: struct nl *p;
67: int offset, length;
68: {
69: int level;
70:
71: level = (p->nl_block & 037);
72: if (oldway != 0) {
73: oldstablvar(p->symbol, p2type(p->type), level, offset, length);
74: } else if (opt('g')) {
75: putprintf("\t.stabs\t\"%s:", 1, p->symbol);
76: gentype(p->type);
77: putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, length, offset);
78: }
79: }
80:
81: /*
82: * global variables
83: */
84: /*ARGSUSED*/
85: oldstabgvar( name , type , offset , length , line )
86: char *name;
87: int type;
88: int offset;
89: int length;
90: int line;
91: {
92: if ( ! opt('g') ) {
93: return;
94: }
95: putprintf( " .stabs \"" , 1 );
96: putprintf( NAMEFORMAT , 1 , (int) name );
97: putprintf( "\",0x%x,0,0x%x,0" , 0 , N_GSYM , type );
98: putprintf( " .stabs \"" , 1 );
99: putprintf( NAMEFORMAT , 1 , (int) name );
100: putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
101: }
102:
103: /*
104: * local variables
105: */
106: /*ARGSUSED*/
107: oldstablvar( name , type , level , offset , length )
108: char *name;
109: int type;
110: int level;
111: int offset;
112: int length;
113: {
114:
115: if ( ! opt('g') ) {
116: return;
117: }
118: putprintf( " .stabs \"" , 1 );
119: putprintf( NAMEFORMAT , 1 , (int) name );
120: putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_LSYM , type , -offset );
121: putprintf( " .stabs \"" , 1 );
122: putprintf( NAMEFORMAT , 1 , (int) name );
123: putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
124: }
125:
126:
127: stabparam (p, offset, length)
128: struct nl *p;
129: int offset, length;
130: {
131: if (oldway != 0) {
132: oldstabparam(p->symbol, p2type(p->type), offset, length);
133: } else if (opt('g')) {
134: putprintf("\t.stabs\t\"%s:", 1, p->symbol);
135: if (p->class == REF) {
136: putprintf("v", 1);
137: } else {
138: putprintf("p", 1);
139: }
140: gentype((p->class == FPROC || p->class ==FFUNC) ? p : p->type);
141: putprintf("\",0x%x,0,0x%x,0x%x", 0, N_PSYM, length, offset);
142: }
143: }
144:
145: /*
146: * parameters
147: */
148: oldstabparam( name , type , offset , length )
149: char *name;
150: int type;
151: int offset;
152: int length;
153: {
154:
155: if ( ! opt('g') ) {
156: return;
157: }
158: putprintf( " .stabs \"" , 1 );
159: putprintf( NAMEFORMAT , 1 , (int) name );
160: putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_PSYM , type , offset );
161: putprintf( " .stabs \"" , 1 );
162: putprintf( NAMEFORMAT , 1 , (int) name );
163: putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length );
164: }
165:
166: /*
167: * fields
168: */
169:
170: /*
171: * left brackets
172: * (dbx handles module-2 without these, so we won't use them either)
173: */
174: stablbrac( level )
175: int level;
176: {
177:
178: if ( ! opt('g') || oldway == 0 ) {
179: return;
180: }
181: putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_LBRAC , level );
182: }
183:
184: /*
185: * right brackets
186: */
187: stabrbrac( level )
188: int level;
189: {
190:
191: if ( ! opt('g') || oldway == 0 ) {
192: return;
193: }
194: putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_RBRAC , level );
195: }
196:
197: stabfunc (p, name, line, level)
198: struct nl *p;
199: char *name;
200: int line, level;
201: {
202: char extname[BUFSIZ],nestspec[BUFSIZ];
203:
204: if ( level == 1 ) {
205: if (p->class == FUNC) {
206: putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" ,
207: 0 , name , N_PC , N_PGFUNC , ABS( line )
208: );
209: } else if (p->class == PROC) {
210: putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" ,
211: 0 , name , N_PC , N_PGPROC , ABS( line )
212: );
213: }
214: }
215: if (oldway != 0) {
216: oldstabfunc(name, p->class, line, level);
217: } else if (opt('g')) {
218: putprintf("\t.stabs\t\"%s:", 1, name);
219: if (p->class == FUNC) {
220: putprintf("F", 1);
221: gentype(p->type);
222: putprintf(",", 1);
223: } else {
224: putprintf("P,", 1);
225: }
226: sextname(extname, name, level); /* set extname to entry label */
227: putprintf("%s,", 1, &(extname[1])); /* remove initial underbar */
228: snestspec(nestspec, level);
229: putprintf("%s\",0x%x,0,0,%s", 0, nestspec, N_FUN, extname);
230: }
231: }
232:
233: /*
234: * construct the colon-separated static nesting string into a
235: * caller-supplied buffer
236: */
237: private snestspec(buffer, level)
238: char buffer[];
239: int level;
240: {
241: char *starthere;
242: int i;
243:
244: if (level <= 1) {
245: buffer[0] = '\0';
246: } else {
247: starthere = &buffer[0];
248: for ( i = 1 ; i < level ; i++ ) {
249: sprintf(starthere, "%s:", enclosing[i]);
250: starthere += strlen(enclosing[i]) + 1;
251: }
252: *--starthere = '\0'; /* remove last colon */
253: if (starthere >= &buffer[BUFSIZ-1]) {
254: panic("snestspec");
255: }
256: }
257: }
258:
259: /*
260: * functions
261: */
262: oldstabfunc( name , typeclass , line , level )
263: char *name;
264: int typeclass;
265: int line;
266: long level;
267: {
268: char extname[ BUFSIZ ];
269:
270: /*
271: * for sdb
272: */
273: if ( ! opt('g') ) {
274: return;
275: }
276: putprintf( " .stabs \"" , 1 );
277: putprintf( NAMEFORMAT , 1 , (int) name );
278: sextname( extname , name , (int) level );
279: putprintf( "\",0x%x,0,0x%x,%s" , 0 , N_FUN , line , (int) extname );
280: }
281:
282: /*
283: * source line numbers
284: */
285: stabline( line )
286: int line;
287: {
288: if ( ! opt('g') ) {
289: return;
290: }
291: putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_SLINE , ABS( line ) );
292: }
293:
294: /*
295: * source files get none or more of these:
296: * one as they are entered,
297: * and one every time they are returned to from nested #includes
298: */
299: stabsource(filename, firsttime)
300: char *filename;
301: bool firsttime;
302: {
303: int label;
304:
305: /*
306: * for separate compilation
307: */
308: putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0,
309: (int) filename, N_PC, N_PSO, N_FLAGCHECKSUM);
310: /*
311: * for debugger
312: */
313: if ( ! opt('g') ) {
314: return;
315: }
316: if (oldway != 0) {
317: label = (int) getlab();
318: putprintf( " .stabs \"" , 1 );
319: putprintf( NAMEFORMAT , 1 , filename );
320: putprintf( "\",0x%x,0,0," , 1 , N_SO );
321: putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label );
322: putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label );
323: putprintf( ":" , 0 );
324: } else {
325: if (firsttime) {
326: putprintf( " .stabs \"" , 1 );
327: putprintf( NAMEFORMAT , 1 , filename );
328: putprintf( "\",0x%x,0,0,0" , 0 , N_SO );
329: }
330: }
331: }
332:
333: /*
334: * included files get one or more of these:
335: * one as they are entered by a #include,
336: * and one every time they are returned to from nested #includes.
337: */
338: stabinclude(filename, firsttime)
339: char *filename;
340: bool firsttime;
341: {
342: int label;
343: long check;
344:
345: /*
346: * for separate compilation
347: */
348: if (firsttime) {
349: check = checksum(filename);
350: } else {
351: check = N_FLAGCHECKSUM;
352: }
353: putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0,
354: (int) filename, N_PC, N_PSOL, check);
355: /*
356: * for sdb
357: */
358: if ( ! opt('g') ) {
359: return;
360: }
361: if (oldway != 0) {
362: label = (int) getlab();
363: putprintf( " .stabs \"" , 1 );
364: putprintf( NAMEFORMAT , 1 , filename );
365: putprintf( "\",0x%x,0,0," , 1 , N_SOL );
366: putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label );
367: putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label );
368: putprintf( ":" , 0 );
369: }
370: }
371:
372: /*
373: * anyone know a good checksum for ascii files?
374: * this does a rotate-left and then exclusive-or's in the character.
375: * also, it avoids returning checksums of 0.
376: * The rotate is implemented by shifting and adding back the
377: * sign bit when negative.
378: */
379: long
380: checksum(filename)
381: char *filename;
382: {
383: FILE *filep;
384: register int input;
385: register long check;
386:
387: filep = fopen(filename, "r");
388: if (filep == NULL) {
389: perror(filename);
390: pexit(DIED);
391: }
392: check = 0;
393: while ((input = getc(filep)) != EOF) {
394: if (check < 0) {
395: check <<= 1;
396: check += 1;
397: } else {
398: check <<= 1;
399: }
400: check ^= input;
401: }
402: (void) fclose(filep);
403: if ((unsigned) check <= N_FLAGCHECKSUM) {
404: return N_FLAGCHECKSUM + 1;
405: } else {
406: return check;
407: }
408: }
409:
410: /*
411: * global Pascal symbols :
412: * labels, types, constants, and external procedure and function names:
413: * These are used by the separate compilation facility
414: * to be able to check for disjoint header files.
415: */
416:
417: /*
418: * global labels
419: */
420: stabglabel( label , line )
421: char *label;
422: int line;
423: {
424:
425: putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0
426: , (int) label , N_PC , N_PGLABEL , ABS( line ) );
427: }
428:
429: /*
430: * global constants
431: */
432: stabgconst( const , line )
433: char *const;
434: int line;
435: {
436:
437: putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0
438: , (int) const , N_PC , N_PGCONST , ABS( line ) );
439: }
440:
441: /*
442: * Generate symbolic information about a constant.
443: */
444:
445: stabconst (c)
446: struct nl *c;
447: {
448: if (opt('g') && oldway == 0) {
449: putprintf("\t.stabs\t\"%s:c=", 1, c->symbol);
450: if (c->type == nl + TSTR) {
451: putprintf("s'%s'", 1, c->ptr[0]);
452: } else if (c->type == nl + T1CHAR) {
453: putprintf("c%d", 1, c->range[0]);
454: } else if (isa(c->type, "i")) {
455: putprintf("i%d", 1, c->range[0]);
456: } else if (isa(c->type, "d")) {
457: putprintf("r%g", 1, c->real);
458: } else {
459: putprintf("e", 1);
460: gentype(c->type);
461: putprintf(",%d", 1, c->range[0]);
462: }
463: putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, 0, 0);
464: }
465: }
466:
467: stabgtype (name, type, line)
468: char *name;
469: struct nl *type;
470: int line;
471: {
472: putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" ,
473: 0, name, N_PC , N_PGTYPE, ABS(line)
474: );
475: if (oldway == 0) {
476: stabltype(name, type);
477: }
478: }
479:
480: stabltype (name, type)
481: char *name;
482: struct nl *type;
483: {
484: if (opt('g')) {
485: putprintf("\t.stabs\t\"%s:t", 1, name);
486: gentype(type);
487: putprintf("\",0x%x,0,0,0", 0, N_LSYM);
488: }
489: }
490:
491: /*
492: * external functions and procedures
493: */
494: stabefunc( name , typeclass , line )
495: char *name;
496: int typeclass;
497: int line;
498: {
499: int type;
500:
501: if ( typeclass == FUNC ) {
502: type = N_PEFUNC;
503: } else if ( typeclass == PROC ) {
504: type = N_PEPROC;
505: } else {
506: return;
507: }
508: putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0
509: , (int) name , N_PC , type , ABS( line ) );
510: }
511:
512: /*
513: * Generate type information encoded as a string for dbx.
514: * The fwdptrnum field is used only when the type is a pointer
515: * to a type that isn't known when it was entered. When the
516: * type field is filled for some such tptr, fixfwdtype should
517: * be called to output an equivalencing type definition.
518: */
519:
520: typedef struct TypeDesc *TypeDesc;
521:
522: struct TypeDesc {
523: struct nl *tptr;
524: int tnum;
525: int fwdptrnum;
526: TypeDesc chain;
527: };
528:
529: #define TABLESIZE 2003
530:
531: #define typehash(t) ( ( ((int) t) >> 2 ) % TABLESIZE )
532:
533: private int tcount = 1;
534: private TypeDesc typetable[TABLESIZE];
535:
536: private TypeDesc tdlookup (t)
537: struct nl *t;
538: {
539: register TypeDesc td;
540:
541: td = typetable[typehash(t)];
542: while (td != NIL && td->tptr != t) {
543: td = td->chain;
544: }
545: return td;
546: }
547:
548: private int typelookup (t)
549: struct nl *t;
550: {
551: register TypeDesc td;
552: int r;
553:
554: td = tdlookup(t);
555: if (td == NIL) {
556: r = 0;
557: } else {
558: r = td->tnum;
559: }
560: return r;
561: }
562:
563: private int entertype (type)
564: struct nl *type;
565: {
566: register TypeDesc td;
567: register int i;
568:
569: td = (TypeDesc) malloc(sizeof(struct TypeDesc));
570: td->tptr = type;
571: td->tnum = tcount;
572: td->fwdptrnum = 0;
573: ++tcount;
574: i = typehash(type);
575: td->chain = typetable[i];
576: typetable[i] = td;
577: return td->tnum;
578: }
579:
580: /*
581: * The in_types table currently contains "boolean", "char", "integer",
582: * "real" and "_nil". (See nl.c for definition.)
583: * The lookup call below will give the TYPE class nl entry for these
584: * types. In each case except _nil, the type field of that entry is a RANGE
585: * class nl entry for the type. Sometimes other symbol table entries
586: * point to the TYPE entry (e.g., when there is a range over the base type),
587: * and other entries point to the RANGE entry (e.g., for a variable of the
588: * given type). We don't really want to distinguish between these uses
589: * in dbx, and since it appears that the RANGE entries are not reused if
590: * a range happens to coincide, we will give the two the same identifying
591: * dbx type number.
592: */
593:
594: private inittypes()
595: {
596: int i;
597: extern char *in_types[];
598: struct nl *p;
599:
600: for (i = 0; in_types[i] != NIL; i++) {
601: p = lookup(in_types[i]);
602: if (p != NIL) {
603: entertype(p);
604: if (p->type != NIL) {
605: --tcount; /* see comment above */
606: entertype(p->type);
607: }
608: }
609: }
610: }
611:
612: static genarray (t)
613: struct nl *t;
614: {
615: register struct nl *p;
616:
617: for (p = t->chain; p != NIL; p = p->chain) {
618: putprintf("a", 1);
619: gentype(p);
620: putprintf(";", 1);
621: }
622: gentype(t->type);
623: }
624:
625: /*
626: * Really we should walk through ptr[NL_FIELDLIST] for the fields,
627: * and then do the variant tag and fields separately, but dbx
628: * doesn't support this yet.
629: * So, since all the fields of all the variants are on the chain,
630: * we walk through that. Except that this gives the fields in the
631: * reverse order, so we want to print in reverse order.
632: */
633:
634: static genrecord (t)
635: struct nl *t;
636: {
637: putprintf("s%d", 1, t->value[NL_OFFS]);
638: if (t->chain != NIL) {
639: genrecfield(t->chain, 1);
640: }
641: putprintf(";", 1);
642: }
643:
644: static genrecfield (t, n)
645: struct nl *t;
646: int n;
647: {
648: if (t->chain != NULL) {
649: genrecfield(t->chain, n + 1);
650: if (n % 2 == 0) {
651: gencontinue();
652: }
653: }
654: putprintf("%s:", 1, t->symbol);
655: gentype(t->type);
656: putprintf(",%d,%d;", 1, 8*t->value[NL_OFFS], 8*lwidth(t->type));
657: }
658:
659: static genvarnt (t)
660: struct nl *t;
661: {
662: genrecord(t);
663: }
664:
665: static genptr (t)
666: struct nl *t;
667: {
668: register TypeDesc td;
669:
670: putprintf("*", 1);
671: if (t->type != NIL) {
672: gentype(t->type);
673: } else {
674: /*
675: * unresolved forward pointer: use tcount to represent what is
676: * begin pointed to, to be defined later
677: */
678: td = tdlookup(t);
679: if (td == NIL) {
680: panic("nil ptr in stab.genptr");
681: }
682: td->fwdptrnum = tcount;
683: putprintf("%d", 1, tcount);
684: ++tcount;
685: }
686: }
687:
688: /*
689: * The type t is a pointer which has just had its type field filled.
690: * We need to generate a type stab saying that the number saved
691: * in t's fwdptrnum is the same as the t->type's number
692: */
693:
694: fixfwdtype (t)
695: struct nl *t;
696: {
697: register TypeDesc td;
698:
699: if (opt('g') && oldway == 0) {
700: td = tdlookup(t);
701: if (td != NIL) {
702: putprintf("\t.stabs\t\":t%d=", 1, td->fwdptrnum);
703: gentype(t->type);
704: putprintf("\",0x%x,0,0,0", 0, N_LSYM);
705: }
706: }
707: }
708:
709: static genenum (t)
710: struct nl *t;
711: {
712: register struct nl *e;
713: register int i;
714:
715: putprintf("e", 1);
716: i = 1;
717: e = t->chain;
718: while (e != NULL) {
719: if (i > 2) {
720: gencontinue();
721: i = 0;
722: }
723: putprintf("%s:%d,", 1, e->symbol, e->range[0]);
724: e = e->chain;
725: ++i;
726: }
727: putprintf(";", 1);
728: }
729:
730: static genset (t)
731: struct nl *t;
732: {
733: putprintf("S", 1);
734: gentype(t->type);
735: }
736:
737: static genrange (t)
738: struct nl *t;
739: {
740: putprintf("r", 1);
741: gentype(t->type);
742: putprintf(";%d;%d", 1, t->range[0], t->range[1]);
743: }
744:
745: static genfparam (t)
746: struct nl *t;
747: {
748: struct nl *p;
749: int count;
750:
751: if (t->type != NULL) {
752: putprintf("f", 1);
753: gentype(t->type);
754: putprintf(",", 1);
755: } else {
756: putprintf("p", 1);
757: }
758: count = 0;
759: for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) {
760: ++count;
761: }
762: putprintf("%d;", 1, count);
763: for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) {
764: gentype(p->type);
765: putprintf(",%d;", 1, p->class);
766: }
767: }
768:
769: static genfile (t)
770: struct nl *t;
771: {
772: putprintf("d", 1);
773: gentype(t->type);
774: }
775:
776: static gentype (t)
777: struct nl *t;
778: {
779: int id;
780:
781: if (tcount == 1) {
782: inittypes();
783: }
784: id = typelookup(t);
785: if (id != 0) {
786: putprintf("%d", 1, id);
787: } else if (t->class == SCAL && t->chain == NULL) {
788: id = typelookup(t->type);
789: if (id != 0) {
790: putprintf("%d", 1, id);
791: } else {
792: genenum(t->type);
793: }
794: } else {
795: id = entertype(t);
796: putprintf("%d=", 1, id);
797: switch (t->class) {
798: case TYPE:
799: gentype(t->type);
800: break;
801:
802: case ARRAY:
803: genarray(t);
804: break;
805:
806: case RECORD:
807: genrecord(t);
808: break;
809:
810: case VARNT:
811: genvarnt(t);
812: break;
813:
814: case REF:
815: gentype(t->type);
816: break;
817:
818: case PTR:
819: genptr(t);
820: break;
821:
822: case SET:
823: genset(t);
824: break;
825:
826: case RANGE:
827: genrange(t);
828: break;
829:
830: case SCAL:
831: genenum(t);
832: break;
833:
834: case FPROC:
835: case FFUNC:
836: genfparam(t);
837: break;
838:
839: case FILET:
840: case PTRFILE:
841: genfile(t);
842: break;
843:
844: default:
845: /* This shouldn't happen */
846: /* Rather than bomb outright, let debugging go on */
847: warning();
848: error("Bad type class found in stab");
849: putprintf("1", 1, t->class);
850: break;
851: }
852: }
853: }
854:
855: /*
856: * Continue stab information in a namelist new entry. This is necessary
857: * to avoid overflowing putprintf's buffer.
858: */
859:
860: static gencontinue ()
861: {
862: putprintf("?\",0x%x,0,0,0", 0, N_LSYM);
863: putprintf("\t.stabs\t\"", 1);
864: }
865:
866: #endif PC
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.