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