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