1 /* Copyright (c) 1980 Regents of the University of California */ 2 static char sccsid[] = "@(#)assyms.c 4.1 08/13/80"; 3 #include <stdio.h> 4 #include <ctype.h> 5 #include <sys/types.h> 6 #include <a.out.h> 7 #include "as.h" 8 #include "asscan.h" 9 #include "assyms.h" 10 11 /* 12 * Managers for chunks of symbols allocated from calloc() 13 * We maintain a linked list of such chunks. 14 * 15 */ 16 struct allocbox *allochead; /*head of chunk list*/ 17 struct allocbox *alloctail; /*tail*/ 18 struct allocbox *newbox; /*for creating a new chunk*/ 19 struct symtab *nextsym; /*next symbol free*/ 20 int symsleft; /*slots left in current chunk*/ 21 22 struct symtab **symptrs; 23 struct symtab **symdelim[NLOC + NLOC +1]; 24 struct symtab **symptrub; 25 /* 26 * Managers for the dynamically extendable hash table 27 */ 28 struct hashdallop *htab; 29 30 struct instab *itab[NINST]; /*maps opcodes to instructions*/ 31 /* 32 * Counts what went into the symbol table, so that the 33 * size of the symbol table can be computed. 34 */ 35 int nsyms; /* total number in the symbol table */ 36 int njxxx; /* number of jxxx entrys */ 37 int nforgotten; /* number of symbols erroneously entered */ 38 int nlabels; /* number of label entries */ 39 int hshused; /* number of hash slots used */ 40 41 /* 42 * Managers of the symbol literal storage. 43 * If we have flexible names, then we allocate BUFSIZ long 44 * string, and pack strings into that. Otherwise, we allocate 45 * symbol storage in fixed hunks NCPS long when we allocate space 46 * for other symbol attributes. 47 */ 48 #ifdef FLEXNAMES 49 struct strpool *strplhead = 0; 50 #else 51 char *namebuffer; 52 #endif 53 54 symtabinit() 55 { 56 allochead = 0; 57 alloctail = 0; 58 nextsym = 0; 59 symsleft = 0; 60 #ifdef FLEXNAMES 61 strpoolalloc(); /* get the first strpool storage area */ 62 #endif FLEXNAMES 63 htab = 0; 64 htaballoc(); /* get the first part of the hash table */ 65 } 66 67 /* 68 * Install all known instructions in the symbol table 69 */ 70 syminstall() 71 { 72 register struct instab *ip; 73 register struct symtab **hp; 74 register char *p1, *p2; 75 76 for (ip=instab; ip->name!=0; ip++) { 77 p1 = ip->name; 78 p2 = yytext; 79 while (*p2++ = *p1++); 80 hp = lookup(0); /* 0 => don't install this*/ 81 if (*hp==NULL) { 82 *hp = (struct symtab *)ip; 83 if ( (ip->tag!=INSTn) 84 && (ip->tag!=INST0) 85 && (ip->tag!=0)) 86 continue; /* was pseudo-op */ 87 itab[ip->opcode & 0xFF] = ip; 88 } 89 } 90 } /*end of syminstall*/ 91 92 93 /* 94 * Assign final values to symbols, 95 * and overwrite the index field with its relative position in 96 * the symbol table we give to the loader. 97 */ 98 extern struct exec hdr; 99 100 freezesymtab() 101 { 102 register struct symtab *sp; 103 long bs; 104 register int relpos = 0; 105 register struct symtab *ubsp; 106 register struct allocbox *allocwalk; 107 108 DECLITERATE(allocwalk, sp, ubsp) 109 { 110 if (sp->tag >= IGNOREBOUND) 111 continue; /*totally ignore jxxx entries */ 112 /* 113 * Ignore stabs, but give them a symbol table index 114 */ 115 if (sp->type & STABFLAG) 116 goto assignindex; 117 if ((sp->type&XTYPE)==XUNDEF) 118 sp->type = XXTRN+XUNDEF; 119 else if ((sp->type&XTYPE)==XDATA) 120 sp->value += usedot[sp->index].xvalue; 121 else if ((sp->type&XTYPE)==XTEXT) 122 sp->value += usedot[sp->index].xvalue; 123 else if ((sp->type&XTYPE)==XBSS) { 124 bs = sp->value; 125 sp->value = hdr.a_bss + datbase; 126 hdr.a_bss += bs; 127 } 128 assignindex: 129 if ( (sp->name[0] != 'L') 130 || (sp->tag != LABELID) 131 || savelabels 132 ) /*then, we will write it later on*/ 133 sp->index = relpos++; 134 } 135 } 136 137 138 139 /* 140 * For all of the stabs that had their final value undefined during pass 1 141 * and during pass 2 assign a final value. 142 * We have already given stab entrys a initial approximation 143 * when we constsructed the sorted symbol table. 144 * Iteration order doesn't matter. 145 */ 146 stabfix() { 147 register struct symtab *sp, **cosp; 148 register struct symtab *p; 149 150 SYMITERATE(cosp, sp){ 151 if(sp->ptype && (sp->type & STABFLAG)) { 152 p = sp->dest; 153 sp->value = p->value; 154 sp->index = p->index; 155 sp->type = p->type; 156 } 157 } 158 } 159 160 char *Calloc(number, size) 161 int number, size; 162 { 163 register char *newstuff; 164 newstuff = (char *)sbrk(number*size); 165 if ((int)newstuff == -1){ 166 yyerror("Ran out of Memory"); 167 delexit(); 168 } 169 return(newstuff); 170 } 171 172 char *ClearCalloc(number, size) 173 int number, size; 174 { 175 register char *newstuff; /* r11 */ 176 register int length = number * size; /* r10 */ 177 newstuff = Calloc(number, size); 178 asm("movc5 $0, (r0), $0, r10, (r11)"); 179 return(newstuff); 180 } 181 182 struct symtab *symalloc() 183 { 184 if (symsleft == 0){ 185 newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY); 186 symsleft = SYMDALLOP; 187 nextsym = &newbox->symslots[0]; 188 #ifndef FLEXNAMES 189 namebuffer = &newbox->symnames[0]; 190 #endif not FLEXNAMES 191 if (alloctail == 0){ 192 allochead = alloctail = newbox; 193 } else { 194 alloctail->nextalloc = newbox; 195 alloctail = newbox; 196 } 197 } 198 --symsleft; 199 ++nsyms; 200 #ifndef FLEXNAMES 201 nextsym->name = namebuffer; 202 namebuffer += NCPS; 203 #endif not FLEXNAMES 204 return(nextsym++); 205 } 206 207 #ifdef FLEXNAMES 208 strpoolalloc() 209 { 210 register struct strpool *new; 211 212 new = (struct strpool *)Calloc(1, sizeof (struct strpool)); 213 new->str_nalloc = 0; 214 new->str_next = strplhead; 215 strplhead = new; 216 } 217 #endif FLEXNAMES 218 219 symcmp(Pptr, Qptr) 220 struct symtab **Pptr, **Qptr; 221 { 222 register struct symtab *p = *Pptr; 223 register struct symtab *q = *Qptr; 224 if (p->index < q->index) 225 return(-1); 226 if (p->index > q->index) 227 return(1); 228 if (p->value < q->value) 229 return(-1); 230 if (p->value > q->value) 231 return(1); 232 /* 233 * Force jxxx entries to virtually preceed labels defined 234 * to follow the jxxxx instruction, so that bumping the 235 * jxxx instruction correctly fixes up the following labels 236 */ 237 if (p->tag >= IGNOREBOUND) /*p points to a jxxx*/ 238 return(-1); 239 if (q->tag >= IGNOREBOUND) 240 return(1); 241 /* 242 * both are now just plain labels; the relative order doesn't 243 * matter. Both can't be jxxxes, as they would have different 244 * values. 245 */ 246 return(0); 247 } /*end of symcmp*/ 248 249 /* 250 * We construct the auxiliary table of pointers, symptrs and 251 * symdelim 252 * We also assign preliminary values to stab entries that did not yet 253 * have an absolute value (because they initially referred to 254 * forward references). We don't worry about .stabds, as they 255 * already have an estimated final value 256 */ 257 258 sortsymtab() 259 { 260 register struct symtab *sp; 261 register struct symtab **cowalk; 262 register struct allocbox *allocwalk; 263 struct symtab *ubsp; 264 int segno; 265 int slotno; 266 int symsin; /*number put into symptrs*/ 267 268 symptrs = (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs); 269 /* 270 * Allocate one word at the beginning of the symptr array 271 * so that backwards scans through the symptr array will 272 * work correctly while scanning through the zeroth segment 273 */ 274 *symptrs++ = 0; 275 cowalk = symptrs; 276 symsin = 0; 277 DECLITERATE(allocwalk, sp, ubsp) { 278 if (sp->ptype && (sp->type &STABFLAG)){ 279 sp->value = sp->dest->value; 280 sp->index = sp->dest->index; 281 } 282 if (symsin >= nsyms) 283 yyerror("INTERNAL ERROR: overfilled symbol table indirection table"); 284 *cowalk++ = sp; 285 symsin++; 286 } 287 if (symsin != nsyms) 288 yyerror("INTERNAL ERROR: installed %d syms, should have installed %d", 289 symsin, nsyms); 290 symptrub = &symptrs[nsyms ]; 291 qsort(symptrs, nsyms, sizeof *symptrs, symcmp); 292 symdelim[0] = symptrs; 293 for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1; 294 segno < NLOC + NLOC; 295 segno++, slotno++){ 296 for (; sp && sp->index == segno; sp = *++cowalk); 297 symdelim[slotno] = cowalk; /*forms the ub delimeter*/ 298 } 299 } /*end of sortsymtab*/ 300 301 #ifdef DEBUG 302 dumpsymtab() 303 { 304 register int segno; 305 register struct symtab *sp, **cosp, *ub; 306 char *tagstring(); 307 308 printf("Symbol Table dump:\n"); 309 for (segno = 0; segno < NLOC + NLOC; segno++){ 310 printf("Segment number: %d\n", segno); 311 SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){ 312 #ifdef FLEXNAMES 313 printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n", 314 segno, sp->name, 315 sp->value, sp->index, 316 tagstring(sp->tag)); 317 #else not FLEXNAMES 318 printf("\tSeg: %d \"%*.*s\" value: %d index: %d tag %s\n", 319 segno, NCPS, NCPS, sp->name, 320 sp->value, sp->index, 321 tagstring(sp->tag)); 322 #endif not FLEXNAMES 323 printf("\t\ttype: %d jxbump %d jxfear: %d\n", 324 sp->type, sp->jxbump, sp->jxfear); 325 } 326 printf("\n\n"); 327 } 328 } 329 330 static char tagbuff[4]; 331 332 char *tagstring(tag) 333 unsigned char tag; 334 { 335 switch(tag){ 336 case JXACTIVE: return("active"); 337 case JXNOTYET: return("notyet"); 338 case JXALIGN: return("align"); 339 case JXQUESTIONABLE: return("jxquestionable"); 340 case JXINACTIVE: return("inactive"); 341 case JXTUNNEL: return("tunnel"); 342 case OBSOLETE: return("obsolete"); 343 case IGNOREBOUND: return("ignorebound"); 344 case STABFLOATING: return("stabfloating"); 345 case STABFIXED: return("stabfixed"); 346 case LABELID: return("labelid"); 347 case OKTOBUMP: return("oktobump"); 348 case ISET: return("iset"); 349 case ILSYM: return("ilsym"); 350 default: sprintf(tagbuff,"%d", tag); 351 return(tagbuff); 352 } 353 } 354 #endif DEBUG 355 356 htaballoc() 357 { 358 register struct hashdallop *new; 359 new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop)); 360 if (htab == 0) 361 htab = new; 362 else { /* add AFTER the 1st slot */ 363 new->h_next = htab->h_next; 364 htab->h_next = new; 365 } 366 } 367 368 #define HASHCLOGGED (NHASH / 2) 369 370 /* 371 * Lookup a symbol stored in extern yytext. 372 * All strings passed in via extern yytext had better have 373 * a trailing null. Strings are placed in yytext for hashing by 374 * syminstall() and by yylex(); 375 * 376 * We take pains to avoid function calls; this functdion 377 * is called quite frequently, and the calls overhead 378 * in the vax contributes significantly to the overall 379 * execution speed of as. 380 */ 381 struct symtab **lookup(instflg) 382 int instflg; /* 0: don't install */ 383 { 384 static int initialprobe; 385 register struct symtab **hp; 386 register char *from; 387 register char *to; 388 register int len; 389 register int nprobes; 390 static struct hashdallop *hdallop; 391 static struct symtab **emptyslot; 392 static struct hashdallop *emptyhd; 393 static struct symtab **hp_ub; 394 395 emptyslot = 0; 396 for (nprobes = 0, from = yytext; 397 *from; 398 nprobes <<= 2, nprobes += *from++) 399 continue; 400 nprobes += from[-1] << 5; 401 nprobes %= NHASH; 402 if (nprobes < 0) 403 nprobes += NHASH; 404 405 initialprobe = nprobes; 406 for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){ 407 for (hp = &(hdallop->h_htab[initialprobe]), 408 nprobes = 1, 409 hp_ub = &(hdallop->h_htab[NHASH]); 410 (*hp) && (nprobes < NHASH); 411 hp += nprobes, 412 hp -= (hp >= hp_ub) ? NHASH:0, 413 nprobes += 2) 414 { 415 from = yytext; 416 to = (*hp)->name; 417 #ifndef FLEXNAMES 418 for (len = 0; (len<NCPS) && *from; len++) 419 if (*from++ != *to++) 420 goto nextprobe; 421 if (len >= NCPS) /*both are maximal length*/ 422 return(hp); 423 if (*to == 0) /*assert *from == 0*/ 424 return(hp); 425 #else FLEXNAMES 426 while (*from && *to) 427 if (*from++ != *to++) 428 goto nextprobe; 429 if (*to == *from) /*assert both are == 0*/ 430 return(hp); 431 #endif FLEXNAMES 432 433 nextprobe: ; 434 } 435 if (*hp == 0 && emptyslot == 0 && 436 hdallop->h_nused < HASHCLOGGED) { 437 emptyslot = hp; 438 emptyhd = hdallop; 439 } 440 } 441 if (emptyslot == 0) { 442 htaballoc(); 443 hdallop = htab->h_next; /* aren't we smart! */ 444 hp = &hdallop->h_htab[initialprobe]; 445 } else { 446 hdallop = emptyhd; 447 hp = emptyslot; 448 } 449 if (instflg) { 450 *hp = symalloc(); 451 hdallop->h_nused++; 452 #ifndef FLEXNAMES 453 for(len = 0, from = yytext, to = (*hp)->name; (len<NCPS); len++) 454 if ((*to++ = *from++) == '\0') 455 break; 456 #else FLEXNAMES 457 for (from = yytext, len = 1; *from++; len++) 458 continue; 459 if (len >= (STRPOOLDALLOP - strplhead->str_nalloc)) 460 strpoolalloc(); 461 for ( (*hp)->name = to = strplhead->str_names + strplhead->str_nalloc, from = yytext; 462 ( (*to++ = *from++) != '\0'); ) 463 continue; 464 strplhead->str_nalloc += len; 465 #endif FLEXNAMES 466 } 467 return(hp); 468 } /*end of lookup*/ 469 470 char *savestr(str) 471 char *str; 472 { 473 register int len; 474 register char *from, *to; 475 char *res; 476 477 for (from = str, len = 1; *from++; len++) 478 continue; 479 if (len >= (STRPOOLDALLOP - strplhead->str_nalloc)) 480 strpoolalloc(); 481 for ( res = to = strplhead->str_names + strplhead->str_nalloc, from = str; 482 ( (*to++ = *from++) != '\0'); ) 483 continue; 484 strplhead->str_nalloc += len; 485 return (res); 486 } 487 488 /* 489 * The following two tables are indexed by 490 * {LEN1,LEN2,LEN4,LEN8} | {PCREL,0} 491 * Note that PCREL = 1 492 */ 493 int reflen[] = {0, 0, 1, 1, 2, 2, 4, 4, 8, 8}; 494 int lgreflen[] = {-1, -1, 0, 0, 1, 1, 2, 2, 3, 3}; 495 496 /* 497 * The relocation information is saved internally in an array of 498 * lists of relocation buffers. The relocation buffers are 499 * exactly the same size as a token buffer; if we use VM for the 500 * temporary file we reclaim this storage, otherwise we create 501 * them by mallocing. 502 */ 503 #define RELBUFLG TOKBUFLG 504 #define NRELOC ((TOKBUFLG - \ 505 (sizeof (int) + sizeof (struct relbufdesc *)) \ 506 ) / (sizeof (struct relocation_info))) 507 508 struct relbufdesc{ 509 int rel_count; 510 struct relbufdesc *rel_next; 511 struct relocation_info rel_reloc[NRELOC]; 512 }; 513 extern struct relbufdesc *tok_free; 514 #define rel_free tok_free 515 static struct relbufdesc *rel_temp; 516 struct relocation_info r_can_1PC = {0,0,0,0,0,0}; 517 struct relocation_info r_can_0PC = {0,0,0,0,0,0}; 518 519 initoutrel() 520 { 521 r_can_1PC.r_pcrel = 1; 522 } 523 524 outrel(pval,reftype,reltype,xsym) 525 long *pval; 526 register int reftype,reltype; 527 struct symtab *xsym; 528 { 529 /* 530 * reftype: PCREL or not, plus length LEN1, LEN2, LEN4, LEN8 531 * reltype: csect ("segment") number (XTEXT, XDATA, ...) associated with 'val' 532 * xsym: symbol table pointer 533 */ 534 short this_reflen; 535 struct relocation_info reloc; 536 537 this_reflen = reflen[reftype]; 538 if (bitoff&07) 539 yyerror("Padding error"); 540 reltype &= ~XFORW; 541 if (reltype == XUNDEF) 542 yyerror("Undefined reference"); 543 544 if (reltype != XABS || reftype & PCREL) { 545 reloc = (reftype & PCREL)? r_can_1PC : r_can_0PC; 546 reloc.r_address = dotp->xvalue - 547 ( (dotp < &usedot[NLOC]) ? 0 : datbase ); 548 reloc.r_length = lgreflen[reftype]; 549 switch(reltype){ 550 case XXTRN | XUNDEF: 551 reloc.r_symbolnum = xsym->index; 552 reloc.r_extern = 1; 553 break; 554 default: 555 reloc.r_symbolnum = reltype; 556 break; 557 } 558 if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){ 559 if (rel_free){ 560 rel_temp = rel_free; 561 rel_free = rel_temp->rel_next; 562 } else { 563 rel_temp = (struct relbufdesc *) 564 Calloc(1,sizeof (struct relbufdesc)); 565 } 566 rel_temp->rel_count = 0; 567 rel_temp->rel_next = relfil; 568 relfil = rusefile[dotp - &usedot[0]] = rel_temp; 569 } 570 relfil->rel_reloc[relfil->rel_count++] = reloc; 571 } 572 /* 573 * write the unrelocated value to the text file 574 */ 575 dotp->xvalue += this_reflen; 576 if (reftype & PCREL) 577 *pval -= dotp->xvalue; 578 bwrite((char *)pval, this_reflen, txtfil); 579 } 580 /* 581 * Flush out all of the relocation information. 582 * Note that the individual lists of buffers are in 583 * reverse order, so we must reverse them 584 */ 585 off_t closeoutrel(relocfile) 586 BFILE *relocfile; 587 { 588 int locindex; 589 u_long Closeoutrel(); 590 591 trsize = 0; 592 for (locindex = 0; locindex < NLOC; locindex++){ 593 trsize += Closeoutrel(rusefile[locindex], relocfile); 594 } 595 drsize = 0; 596 for (locindex = 0; locindex < NLOC; locindex++){ 597 drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile); 598 } 599 return(trsize + drsize); 600 } 601 602 u_long Closeoutrel(relfil, relocfile) 603 struct relbufdesc *relfil; 604 BFILE *relocfile; 605 { 606 u_long tail; 607 if (relfil == 0) 608 return(0L); 609 tail = Closeoutrel(relfil->rel_next, relocfile); 610 bwrite((char *)&relfil->rel_reloc[0], 611 relfil->rel_count * sizeof (struct relocation_info), 612 relocfile); 613 return(tail + relfil->rel_count * sizeof (struct relocation_info)); 614 } 615 616 int sizesymtab() 617 { 618 struct symtab *sp; 619 620 #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels)) 621 622 return ( 623 ( 624 #ifndef FLEXNAMES 625 NCPS 626 #else FLEXNAMES 627 sizeof (long) 628 #endif FLEXNAMES 629 + sizeof (sp->ptype) 630 + sizeof (sp->other) 631 + sizeof (sp->desc) 632 + sizeof (sp->value) 633 ) 634 * NOUTSYMS 635 ); 636 } 637 638 #ifdef FLEXNAMES 639 /* 640 * We write out the flexible length character strings for names 641 * in two stages. 642 * 1) We have always! maintain a fixed sized name list entry; 643 * the string is indexed by a four byte quantity from the beginning 644 * of the string pool area. Index 0 is reserved, and indicates 645 * that there is no associated string. The first valid index is 4. 646 * 2) We concatenate together and write all of the strings 647 * in the string pool at the end of the name list. The first 648 * four bytes in the string pool are indexed only by 0 (see above); 649 * they contain the total number of bytes in the string pool. 650 */ 651 #endif FLEXNAMES 652 653 /* 654 * Write out n symbols to file f, beginning at p 655 * ignoring symbols that are obsolete, jxxx instructions, and 656 * possibly, labels 657 */ 658 659 int symwrite(symfile) 660 BFILE *symfile; 661 { 662 int symsout; /*those actually written*/ 663 int symsdesired = NOUTSYMS; 664 register struct symtab *sp, *ub; 665 #ifdef FLEXNAMES 666 register int len; 667 long stroff = sizeof (stroff); 668 #endif FLEXNAMES 669 670 register struct allocbox *allocwalk; 671 672 symsout = 0; 673 DECLITERATE(allocwalk, sp, ub) 674 { 675 if (sp->tag >= IGNOREBOUND) 676 continue; 677 if ((sp->name[0] == 'L') && (sp->tag == LABELID) && !savelabels) 678 continue; 679 symsout++; 680 #ifndef FLEXNAMES 681 bwrite(sp->name, NCPS, symfile); 682 #else FLEXNAMES 683 len = strlen(sp->name); 684 if (len != 0) { 685 bwrite(&stroff, sizeof (stroff), symfile); 686 stroff += len + 1; 687 } else 688 bwrite("\0\0\0\0", sizeof (stroff), symfile); 689 #endif FLEXNAMES 690 sp->type &= ~XFORW; 691 bputc( ( (sp->ptype != 0) ? sp->ptype : sp->type ), 692 symfile); 693 /* 694 * WATCH OUT. THIS DEPENDS THAT THE ALLOCATION OF 695 * the four fields ptype, other, desc and value are 696 * contiguous, which is compiler dependent. 697 */ 698 bwrite((char *)&(sp->other), 699 sizeof (sp->other) 700 + sizeof (sp->desc) 701 + sizeof (sp->value), 702 symfile 703 ); 704 } 705 if (symsout != symsdesired) 706 yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n", 707 symsout, symsdesired); 708 #ifdef FLEXNAMES 709 /* 710 * Pass 2 through the string pool 711 */ 712 symsout = 0; 713 bwrite(&stroff, sizeof (stroff), symfile); 714 stroff = sizeof (stroff); 715 symsout = 0; 716 DECLITERATE(allocwalk, sp, ub) 717 { 718 if (sp->tag >= IGNOREBOUND) 719 continue; 720 if ((sp->name[0] == 'L') && (sp->tag == LABELID) && !savelabels) 721 continue; 722 len = strlen(sp->name); 723 if (len) 724 bwrite(sp->name, len + 1, symfile); 725 } 726 #endif FLEXNAMES 727 } 728