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