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