1 /*- 2 * Copyright (c) 1980 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)stab.c 5.4 (Berkeley) 04/16/91"; 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*/ 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*/ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 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 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 */ 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 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 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 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 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 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