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 867