1600Sbill /* Copyright (c) 1980 Regents of the University of California */ 2*640Sbill static char sccsid[] = "@(#)assyms.c 4.2 8/15/80"; 3600Sbill #include <stdio.h> 4600Sbill #include <ctype.h> 5600Sbill #include "as.h" 6600Sbill #include "asscan.h" 7600Sbill #include "assyms.h" 8600Sbill 9600Sbill /* 10600Sbill * Managers for chunks of symbols allocated from calloc() 11600Sbill * We maintain a linked list of such chunks. 12600Sbill * 13600Sbill */ 14600Sbill struct allocbox *allochead; /*head of chunk list*/ 15600Sbill struct allocbox *alloctail; /*tail*/ 16600Sbill struct allocbox *newbox; /*for creating a new chunk*/ 17600Sbill struct symtab *nextsym; /*next symbol free*/ 18600Sbill int symsleft; /*slots left in current chunk*/ 19600Sbill 20600Sbill struct symtab **symptrs; 21600Sbill struct symtab **symdelim[NLOC + NLOC +1]; 22600Sbill struct symtab **symptrub; 23600Sbill /* 24600Sbill * Managers for the dynamically extendable hash table 25600Sbill */ 26600Sbill struct hashdallop *htab; 27600Sbill 28600Sbill struct instab *itab[NINST]; /*maps opcodes to instructions*/ 29600Sbill /* 30600Sbill * Counts what went into the symbol table, so that the 31600Sbill * size of the symbol table can be computed. 32600Sbill */ 33600Sbill int nsyms; /* total number in the symbol table */ 34600Sbill int njxxx; /* number of jxxx entrys */ 35600Sbill int nforgotten; /* number of symbols erroneously entered */ 36600Sbill int nlabels; /* number of label entries */ 37600Sbill int hshused; /* number of hash slots used */ 38600Sbill 39600Sbill /* 40600Sbill * Managers of the symbol literal storage. 41600Sbill * If we have flexible names, then we allocate BUFSIZ long 42600Sbill * string, and pack strings into that. Otherwise, we allocate 43600Sbill * symbol storage in fixed hunks NCPS long when we allocate space 44600Sbill * for other symbol attributes. 45600Sbill */ 46600Sbill #ifdef FLEXNAMES 47600Sbill struct strpool *strplhead = 0; 48634Shenry #endif FLEXNAMES 49600Sbill 50600Sbill symtabinit() 51600Sbill { 52600Sbill allochead = 0; 53600Sbill alloctail = 0; 54600Sbill nextsym = 0; 55600Sbill symsleft = 0; 56600Sbill #ifdef FLEXNAMES 57600Sbill strpoolalloc(); /* get the first strpool storage area */ 58600Sbill #endif FLEXNAMES 59600Sbill htab = 0; 60600Sbill htaballoc(); /* get the first part of the hash table */ 61600Sbill } 62600Sbill 63600Sbill /* 64600Sbill * Install all known instructions in the symbol table 65600Sbill */ 66600Sbill syminstall() 67600Sbill { 68600Sbill register struct instab *ip; 69600Sbill register struct symtab **hp; 70600Sbill register char *p1, *p2; 71600Sbill 72634Shenry #ifdef FLEXNAMES 73634Shenry for (ip = (struct instab *)instab; ip->s_name != 0; ip++) { 74634Shenry #else not FLEXNAMES 75634Shenry for (ip = (struct instab *)instab; ip->s_name[0] != '\0'; ip++){ 76634Shenry #endif not FLEXNAMES 77634Shenry p1 = ip->s_name; 78600Sbill p2 = yytext; 79600Sbill while (*p2++ = *p1++); 80600Sbill hp = lookup(0); /* 0 => don't install this*/ 81600Sbill if (*hp==NULL) { 82600Sbill *hp = (struct symtab *)ip; 83634Shenry if ( (ip->s_tag!=INSTn) 84634Shenry && (ip->s_tag!=INST0) 85634Shenry && (ip->s_tag!=0)) 86600Sbill continue; /* was pseudo-op */ 87634Shenry itab[ip->i_opcode & 0xFF] = ip; 88600Sbill } 89600Sbill } 90600Sbill } /*end of syminstall*/ 91600Sbill 92600Sbill 93600Sbill /* 94600Sbill * Assign final values to symbols, 95600Sbill * and overwrite the index field with its relative position in 96600Sbill * the symbol table we give to the loader. 97600Sbill */ 98600Sbill extern struct exec hdr; 99600Sbill 100600Sbill freezesymtab() 101600Sbill { 102600Sbill register struct symtab *sp; 103600Sbill long bs; 104600Sbill register int relpos = 0; 105600Sbill register struct symtab *ubsp; 106600Sbill register struct allocbox *allocwalk; 107600Sbill 108600Sbill DECLITERATE(allocwalk, sp, ubsp) 109600Sbill { 110634Shenry if (sp->s_tag >= IGNOREBOUND) 111600Sbill continue; /*totally ignore jxxx entries */ 112600Sbill /* 113600Sbill * Ignore stabs, but give them a symbol table index 114600Sbill */ 115634Shenry if (sp->s_type & STABFLAG) 116600Sbill goto assignindex; 117634Shenry if ((sp->s_type&XTYPE)==XUNDEF) 118634Shenry sp->s_type = XXTRN+XUNDEF; 119634Shenry else if ((sp->s_type&XTYPE)==XDATA) 120634Shenry sp->s_value += usedot[sp->s_index].e_xvalue; 121634Shenry else if ((sp->s_type&XTYPE)==XTEXT) 122634Shenry sp->s_value += usedot[sp->s_index].e_xvalue; 123634Shenry else if ((sp->s_type&XTYPE)==XBSS) { 124634Shenry bs = sp->s_value; 125634Shenry sp->s_value = hdr.a_bss + datbase; 126600Sbill hdr.a_bss += bs; 127600Sbill } 128600Sbill assignindex: 129634Shenry if ( (sp->s_name[0] != 'L') 130634Shenry || (sp->s_tag != LABELID) 131600Sbill || savelabels 132600Sbill ) /*then, we will write it later on*/ 133634Shenry sp->s_index = relpos++; 134600Sbill } 135600Sbill } 136600Sbill 137600Sbill 138600Sbill 139600Sbill /* 140600Sbill * For all of the stabs that had their final value undefined during pass 1 141600Sbill * and during pass 2 assign a final value. 142600Sbill * We have already given stab entrys a initial approximation 143600Sbill * when we constsructed the sorted symbol table. 144600Sbill * Iteration order doesn't matter. 145600Sbill */ 146600Sbill stabfix() { 147600Sbill register struct symtab *sp, **cosp; 148600Sbill register struct symtab *p; 149600Sbill 150600Sbill SYMITERATE(cosp, sp){ 151634Shenry if(sp->s_ptype && (sp->s_type & STABFLAG)) { 152634Shenry p = sp->s_dest; 153634Shenry sp->s_value = p->s_value; 154634Shenry sp->s_index = p->s_index; 155634Shenry sp->s_type = p->s_type; 156600Sbill } 157600Sbill } 158600Sbill } 159600Sbill 160600Sbill char *Calloc(number, size) 161600Sbill int number, size; 162600Sbill { 163600Sbill register char *newstuff; 164600Sbill newstuff = (char *)sbrk(number*size); 165600Sbill if ((int)newstuff == -1){ 166600Sbill yyerror("Ran out of Memory"); 167600Sbill delexit(); 168600Sbill } 169600Sbill return(newstuff); 170600Sbill } 171600Sbill 172600Sbill char *ClearCalloc(number, size) 173600Sbill int number, size; 174600Sbill { 175600Sbill register char *newstuff; /* r11 */ 176600Sbill register int length = number * size; /* r10 */ 177600Sbill newstuff = Calloc(number, size); 178600Sbill asm("movc5 $0, (r0), $0, r10, (r11)"); 179600Sbill return(newstuff); 180600Sbill } 181600Sbill 182600Sbill struct symtab *symalloc() 183600Sbill { 184600Sbill if (symsleft == 0){ 185600Sbill newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY); 186600Sbill symsleft = SYMDALLOP; 187600Sbill nextsym = &newbox->symslots[0]; 188600Sbill if (alloctail == 0){ 189600Sbill allochead = alloctail = newbox; 190600Sbill } else { 191600Sbill alloctail->nextalloc = newbox; 192600Sbill alloctail = newbox; 193600Sbill } 194600Sbill } 195600Sbill --symsleft; 196600Sbill ++nsyms; 197600Sbill return(nextsym++); 198600Sbill } 199600Sbill 200600Sbill #ifdef FLEXNAMES 201600Sbill strpoolalloc() 202600Sbill { 203600Sbill register struct strpool *new; 204600Sbill 205600Sbill new = (struct strpool *)Calloc(1, sizeof (struct strpool)); 206600Sbill new->str_nalloc = 0; 207600Sbill new->str_next = strplhead; 208600Sbill strplhead = new; 209600Sbill } 210600Sbill #endif FLEXNAMES 211600Sbill 212600Sbill symcmp(Pptr, Qptr) 213600Sbill struct symtab **Pptr, **Qptr; 214600Sbill { 215600Sbill register struct symtab *p = *Pptr; 216600Sbill register struct symtab *q = *Qptr; 217634Shenry if (p->s_index < q->s_index) 218600Sbill return(-1); 219634Shenry if (p->s_index > q->s_index) 220600Sbill return(1); 221634Shenry if (p->s_value < q->s_value) 222600Sbill return(-1); 223634Shenry if (p->s_value > q->s_value) 224600Sbill return(1); 225600Sbill /* 226600Sbill * Force jxxx entries to virtually preceed labels defined 227600Sbill * to follow the jxxxx instruction, so that bumping the 228600Sbill * jxxx instruction correctly fixes up the following labels 229600Sbill */ 230634Shenry if (p->s_tag >= IGNOREBOUND) /*p points to a jxxx*/ 231600Sbill return(-1); 232634Shenry if (q->s_tag >= IGNOREBOUND) 233600Sbill return(1); 234600Sbill /* 235600Sbill * both are now just plain labels; the relative order doesn't 236600Sbill * matter. Both can't be jxxxes, as they would have different 237600Sbill * values. 238600Sbill */ 239600Sbill return(0); 240600Sbill } /*end of symcmp*/ 241600Sbill 242600Sbill /* 243600Sbill * We construct the auxiliary table of pointers, symptrs and 244600Sbill * symdelim 245600Sbill * We also assign preliminary values to stab entries that did not yet 246600Sbill * have an absolute value (because they initially referred to 247600Sbill * forward references). We don't worry about .stabds, as they 248600Sbill * already have an estimated final value 249600Sbill */ 250600Sbill 251600Sbill sortsymtab() 252600Sbill { 253600Sbill register struct symtab *sp; 254600Sbill register struct symtab **cowalk; 255600Sbill register struct allocbox *allocwalk; 256600Sbill struct symtab *ubsp; 257600Sbill int segno; 258600Sbill int slotno; 259600Sbill int symsin; /*number put into symptrs*/ 260600Sbill 261600Sbill symptrs = (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs); 262600Sbill /* 263600Sbill * Allocate one word at the beginning of the symptr array 264600Sbill * so that backwards scans through the symptr array will 265600Sbill * work correctly while scanning through the zeroth segment 266600Sbill */ 267600Sbill *symptrs++ = 0; 268600Sbill cowalk = symptrs; 269600Sbill symsin = 0; 270600Sbill DECLITERATE(allocwalk, sp, ubsp) { 271634Shenry if (sp->s_ptype && (sp->s_type &STABFLAG)){ 272634Shenry sp->s_value = sp->s_dest->s_value; 273634Shenry sp->s_index = sp->s_dest->s_index; 274600Sbill } 275600Sbill if (symsin >= nsyms) 276600Sbill yyerror("INTERNAL ERROR: overfilled symbol table indirection table"); 277600Sbill *cowalk++ = sp; 278600Sbill symsin++; 279600Sbill } 280600Sbill if (symsin != nsyms) 281600Sbill yyerror("INTERNAL ERROR: installed %d syms, should have installed %d", 282600Sbill symsin, nsyms); 283600Sbill symptrub = &symptrs[nsyms ]; 284600Sbill qsort(symptrs, nsyms, sizeof *symptrs, symcmp); 285600Sbill symdelim[0] = symptrs; 286600Sbill for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1; 287600Sbill segno < NLOC + NLOC; 288600Sbill segno++, slotno++){ 289634Shenry for (; sp && sp->s_index == segno; sp = *++cowalk); 290600Sbill symdelim[slotno] = cowalk; /*forms the ub delimeter*/ 291600Sbill } 292600Sbill } /*end of sortsymtab*/ 293600Sbill 294600Sbill #ifdef DEBUG 295600Sbill dumpsymtab() 296600Sbill { 297600Sbill register int segno; 298600Sbill register struct symtab *sp, **cosp, *ub; 299600Sbill char *tagstring(); 300600Sbill 301600Sbill printf("Symbol Table dump:\n"); 302600Sbill for (segno = 0; segno < NLOC + NLOC; segno++){ 303600Sbill printf("Segment number: %d\n", segno); 304600Sbill SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){ 305600Sbill #ifdef FLEXNAMES 306600Sbill printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n", 307634Shenry segno, sp->s_name, 308634Shenry sp->s_value, sp->s_index, 309634Shenry tagstring(sp->s_tag)); 310600Sbill #else not FLEXNAMES 311600Sbill printf("\tSeg: %d \"%*.*s\" value: %d index: %d tag %s\n", 312634Shenry segno, NCPS, NCPS, sp->s_name, 313634Shenry sp->s_value, sp->s_index, 314634Shenry tagstring(sp->s_tag)); 315600Sbill #endif not FLEXNAMES 316600Sbill printf("\t\ttype: %d jxbump %d jxfear: %d\n", 317634Shenry sp->s_type, sp->s_jxbump, sp->s_jxfear); 318600Sbill } 319600Sbill printf("\n\n"); 320600Sbill } 321600Sbill } 322600Sbill 323600Sbill static char tagbuff[4]; 324600Sbill 325600Sbill char *tagstring(tag) 326600Sbill unsigned char tag; 327600Sbill { 328600Sbill switch(tag){ 329600Sbill case JXACTIVE: return("active"); 330600Sbill case JXNOTYET: return("notyet"); 331600Sbill case JXALIGN: return("align"); 332600Sbill case JXQUESTIONABLE: return("jxquestionable"); 333600Sbill case JXINACTIVE: return("inactive"); 334600Sbill case JXTUNNEL: return("tunnel"); 335600Sbill case OBSOLETE: return("obsolete"); 336600Sbill case IGNOREBOUND: return("ignorebound"); 337600Sbill case STABFLOATING: return("stabfloating"); 338600Sbill case STABFIXED: return("stabfixed"); 339600Sbill case LABELID: return("labelid"); 340600Sbill case OKTOBUMP: return("oktobump"); 341600Sbill case ISET: return("iset"); 342600Sbill case ILSYM: return("ilsym"); 343600Sbill default: sprintf(tagbuff,"%d", tag); 344600Sbill return(tagbuff); 345600Sbill } 346600Sbill } 347600Sbill #endif DEBUG 348600Sbill 349600Sbill htaballoc() 350600Sbill { 351600Sbill register struct hashdallop *new; 352600Sbill new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop)); 353600Sbill if (htab == 0) 354600Sbill htab = new; 355600Sbill else { /* add AFTER the 1st slot */ 356600Sbill new->h_next = htab->h_next; 357600Sbill htab->h_next = new; 358600Sbill } 359600Sbill } 360600Sbill 361600Sbill #define HASHCLOGGED (NHASH / 2) 362600Sbill 363600Sbill /* 364600Sbill * Lookup a symbol stored in extern yytext. 365600Sbill * All strings passed in via extern yytext had better have 366600Sbill * a trailing null. Strings are placed in yytext for hashing by 367600Sbill * syminstall() and by yylex(); 368600Sbill * 369600Sbill * We take pains to avoid function calls; this functdion 370600Sbill * is called quite frequently, and the calls overhead 371600Sbill * in the vax contributes significantly to the overall 372600Sbill * execution speed of as. 373600Sbill */ 374600Sbill struct symtab **lookup(instflg) 375600Sbill int instflg; /* 0: don't install */ 376600Sbill { 377600Sbill static int initialprobe; 378600Sbill register struct symtab **hp; 379600Sbill register char *from; 380600Sbill register char *to; 381600Sbill register int len; 382600Sbill register int nprobes; 383600Sbill static struct hashdallop *hdallop; 384600Sbill static struct symtab **emptyslot; 385600Sbill static struct hashdallop *emptyhd; 386600Sbill static struct symtab **hp_ub; 387600Sbill 388600Sbill emptyslot = 0; 389600Sbill for (nprobes = 0, from = yytext; 390600Sbill *from; 391600Sbill nprobes <<= 2, nprobes += *from++) 392600Sbill continue; 393600Sbill nprobes += from[-1] << 5; 394600Sbill nprobes %= NHASH; 395600Sbill if (nprobes < 0) 396600Sbill nprobes += NHASH; 397600Sbill 398600Sbill initialprobe = nprobes; 399600Sbill for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){ 400600Sbill for (hp = &(hdallop->h_htab[initialprobe]), 401600Sbill nprobes = 1, 402600Sbill hp_ub = &(hdallop->h_htab[NHASH]); 403600Sbill (*hp) && (nprobes < NHASH); 404600Sbill hp += nprobes, 405600Sbill hp -= (hp >= hp_ub) ? NHASH:0, 406600Sbill nprobes += 2) 407600Sbill { 408600Sbill from = yytext; 409634Shenry to = (*hp)->s_name; 410600Sbill #ifndef FLEXNAMES 411600Sbill for (len = 0; (len<NCPS) && *from; len++) 412600Sbill if (*from++ != *to++) 413600Sbill goto nextprobe; 414600Sbill if (len >= NCPS) /*both are maximal length*/ 415600Sbill return(hp); 416600Sbill if (*to == 0) /*assert *from == 0*/ 417600Sbill return(hp); 418600Sbill #else FLEXNAMES 419600Sbill while (*from && *to) 420600Sbill if (*from++ != *to++) 421600Sbill goto nextprobe; 422600Sbill if (*to == *from) /*assert both are == 0*/ 423600Sbill return(hp); 424600Sbill #endif FLEXNAMES 425600Sbill 426600Sbill nextprobe: ; 427600Sbill } 428600Sbill if (*hp == 0 && emptyslot == 0 && 429600Sbill hdallop->h_nused < HASHCLOGGED) { 430600Sbill emptyslot = hp; 431600Sbill emptyhd = hdallop; 432600Sbill } 433600Sbill } 434600Sbill if (emptyslot == 0) { 435600Sbill htaballoc(); 436600Sbill hdallop = htab->h_next; /* aren't we smart! */ 437600Sbill hp = &hdallop->h_htab[initialprobe]; 438600Sbill } else { 439600Sbill hdallop = emptyhd; 440600Sbill hp = emptyslot; 441600Sbill } 442600Sbill if (instflg) { 443600Sbill *hp = symalloc(); 444600Sbill hdallop->h_nused++; 445600Sbill #ifndef FLEXNAMES 446634Shenry for(len = 0, from = yytext, to = (*hp)->s_name; (len<NCPS); len++) 447600Sbill if ((*to++ = *from++) == '\0') 448600Sbill break; 449600Sbill #else FLEXNAMES 450600Sbill for (from = yytext, len = 1; *from++; len++) 451600Sbill continue; 452600Sbill if (len >= (STRPOOLDALLOP - strplhead->str_nalloc)) 453600Sbill strpoolalloc(); 454634Shenry for ( (*hp)->s_name = to = strplhead->str_names + strplhead->str_nalloc, from = yytext; 455600Sbill ( (*to++ = *from++) != '\0'); ) 456600Sbill continue; 457600Sbill strplhead->str_nalloc += len; 458600Sbill #endif FLEXNAMES 459600Sbill } 460600Sbill return(hp); 461600Sbill } /*end of lookup*/ 462600Sbill 463600Sbill char *savestr(str) 464600Sbill char *str; 465600Sbill { 466600Sbill register int len; 467600Sbill register char *from, *to; 468600Sbill char *res; 469600Sbill 470600Sbill for (from = str, len = 1; *from++; len++) 471600Sbill continue; 472600Sbill if (len >= (STRPOOLDALLOP - strplhead->str_nalloc)) 473600Sbill strpoolalloc(); 474600Sbill for ( res = to = strplhead->str_names + strplhead->str_nalloc, from = str; 475600Sbill ( (*to++ = *from++) != '\0'); ) 476600Sbill continue; 477600Sbill strplhead->str_nalloc += len; 478600Sbill return (res); 479600Sbill } 480600Sbill 481600Sbill /* 482600Sbill * The following two tables are indexed by 483600Sbill * {LEN1,LEN2,LEN4,LEN8} | {PCREL,0} 484600Sbill * Note that PCREL = 1 485600Sbill */ 486600Sbill int reflen[] = {0, 0, 1, 1, 2, 2, 4, 4, 8, 8}; 487600Sbill int lgreflen[] = {-1, -1, 0, 0, 1, 1, 2, 2, 3, 3}; 488600Sbill 489600Sbill /* 490600Sbill * The relocation information is saved internally in an array of 491600Sbill * lists of relocation buffers. The relocation buffers are 492600Sbill * exactly the same size as a token buffer; if we use VM for the 493600Sbill * temporary file we reclaim this storage, otherwise we create 494600Sbill * them by mallocing. 495600Sbill */ 496600Sbill #define RELBUFLG TOKBUFLG 497600Sbill #define NRELOC ((TOKBUFLG - \ 498600Sbill (sizeof (int) + sizeof (struct relbufdesc *)) \ 499600Sbill ) / (sizeof (struct relocation_info))) 500600Sbill 501600Sbill struct relbufdesc{ 502600Sbill int rel_count; 503600Sbill struct relbufdesc *rel_next; 504600Sbill struct relocation_info rel_reloc[NRELOC]; 505600Sbill }; 506600Sbill extern struct relbufdesc *tok_free; 507600Sbill #define rel_free tok_free 508600Sbill static struct relbufdesc *rel_temp; 509634Shenry struct relocation_info r_can_1PC; 510634Shenry struct relocation_info r_can_0PC; 511600Sbill 512600Sbill initoutrel() 513600Sbill { 514634Shenry r_can_0PC.r_address = 0; 515634Shenry r_can_0PC.r_symbolnum = 0; 516634Shenry r_can_0PC.r_pcrel = 0; 517634Shenry r_can_0PC.r_length = 0; 518634Shenry r_can_0PC.r_extern = 0; 519634Shenry 520634Shenry r_can_1PC = r_can_0PC; 521600Sbill r_can_1PC.r_pcrel = 1; 522600Sbill } 523600Sbill 524600Sbill outrel(pval,reftype,reltype,xsym) 525600Sbill long *pval; 526600Sbill register int reftype,reltype; 527600Sbill struct symtab *xsym; 528600Sbill { 529600Sbill /* 530600Sbill * reftype: PCREL or not, plus length LEN1, LEN2, LEN4, LEN8 531600Sbill * reltype: csect ("segment") number (XTEXT, XDATA, ...) associated with 'val' 532600Sbill * xsym: symbol table pointer 533600Sbill */ 534600Sbill short this_reflen; 535600Sbill struct relocation_info reloc; 536600Sbill 537600Sbill this_reflen = reflen[reftype]; 538600Sbill if (bitoff&07) 539600Sbill yyerror("Padding error"); 540600Sbill reltype &= ~XFORW; 541600Sbill if (reltype == XUNDEF) 542600Sbill yyerror("Undefined reference"); 543600Sbill 544600Sbill if (reltype != XABS || reftype & PCREL) { 545600Sbill reloc = (reftype & PCREL)? r_can_1PC : r_can_0PC; 546634Shenry reloc.r_address = dotp->e_xvalue - 547*640Sbill ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase ); 548600Sbill reloc.r_length = lgreflen[reftype]; 549600Sbill switch(reltype){ 550600Sbill case XXTRN | XUNDEF: 551634Shenry reloc.r_symbolnum = xsym->s_index; 552600Sbill reloc.r_extern = 1; 553600Sbill break; 554600Sbill default: 555*640Sbill if (readonlydata && (reltype&~XXTRN) == XDATA) 556*640Sbill reltype = XTEXT | (reltype&XXTRN); 557600Sbill reloc.r_symbolnum = reltype; 558600Sbill break; 559600Sbill } 560600Sbill if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){ 561600Sbill if (rel_free){ 562600Sbill rel_temp = rel_free; 563600Sbill rel_free = rel_temp->rel_next; 564600Sbill } else { 565600Sbill rel_temp = (struct relbufdesc *) 566600Sbill Calloc(1,sizeof (struct relbufdesc)); 567600Sbill } 568600Sbill rel_temp->rel_count = 0; 569600Sbill rel_temp->rel_next = relfil; 570600Sbill relfil = rusefile[dotp - &usedot[0]] = rel_temp; 571600Sbill } 572600Sbill relfil->rel_reloc[relfil->rel_count++] = reloc; 573600Sbill } 574600Sbill /* 575600Sbill * write the unrelocated value to the text file 576600Sbill */ 577634Shenry dotp->e_xvalue += this_reflen; 578600Sbill if (reftype & PCREL) 579634Shenry *pval -= dotp->e_xvalue; 580600Sbill bwrite((char *)pval, this_reflen, txtfil); 581600Sbill } 582600Sbill /* 583600Sbill * Flush out all of the relocation information. 584600Sbill * Note that the individual lists of buffers are in 585600Sbill * reverse order, so we must reverse them 586600Sbill */ 587600Sbill off_t closeoutrel(relocfile) 588600Sbill BFILE *relocfile; 589600Sbill { 590600Sbill int locindex; 591600Sbill u_long Closeoutrel(); 592600Sbill 593600Sbill trsize = 0; 594600Sbill for (locindex = 0; locindex < NLOC; locindex++){ 595600Sbill trsize += Closeoutrel(rusefile[locindex], relocfile); 596600Sbill } 597600Sbill drsize = 0; 598600Sbill for (locindex = 0; locindex < NLOC; locindex++){ 599600Sbill drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile); 600600Sbill } 601600Sbill return(trsize + drsize); 602600Sbill } 603600Sbill 604600Sbill u_long Closeoutrel(relfil, relocfile) 605600Sbill struct relbufdesc *relfil; 606600Sbill BFILE *relocfile; 607600Sbill { 608600Sbill u_long tail; 609600Sbill if (relfil == 0) 610600Sbill return(0L); 611600Sbill tail = Closeoutrel(relfil->rel_next, relocfile); 612600Sbill bwrite((char *)&relfil->rel_reloc[0], 613600Sbill relfil->rel_count * sizeof (struct relocation_info), 614600Sbill relocfile); 615600Sbill return(tail + relfil->rel_count * sizeof (struct relocation_info)); 616600Sbill } 617600Sbill 618634Shenry #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels)) 619600Sbill int sizesymtab() 620600Sbill { 621634Shenry return (sizeof (struct nlist) * NOUTSYMS); 622600Sbill } 623600Sbill 624600Sbill #ifdef FLEXNAMES 625600Sbill /* 626600Sbill * We write out the flexible length character strings for names 627600Sbill * in two stages. 628600Sbill * 1) We have always! maintain a fixed sized name list entry; 629600Sbill * the string is indexed by a four byte quantity from the beginning 630600Sbill * of the string pool area. Index 0 is reserved, and indicates 631600Sbill * that there is no associated string. The first valid index is 4. 632600Sbill * 2) We concatenate together and write all of the strings 633600Sbill * in the string pool at the end of the name list. The first 634600Sbill * four bytes in the string pool are indexed only by 0 (see above); 635600Sbill * they contain the total number of bytes in the string pool. 636600Sbill */ 637600Sbill #endif FLEXNAMES 638600Sbill 639600Sbill /* 640600Sbill * Write out n symbols to file f, beginning at p 641600Sbill * ignoring symbols that are obsolete, jxxx instructions, and 642600Sbill * possibly, labels 643600Sbill */ 644600Sbill 645600Sbill int symwrite(symfile) 646600Sbill BFILE *symfile; 647600Sbill { 648600Sbill int symsout; /*those actually written*/ 649600Sbill int symsdesired = NOUTSYMS; 650600Sbill register struct symtab *sp, *ub; 651600Sbill #ifdef FLEXNAMES 652634Shenry char *name; /* temp to save the name */ 653600Sbill long stroff = sizeof (stroff); 654634Shenry /* 655634Shenry * We use sp->s_index to hold the length of the 656634Shenry * name; it isn't used for anything else 657634Shenry */ 658600Sbill #endif FLEXNAMES 659600Sbill 660600Sbill register struct allocbox *allocwalk; 661600Sbill 662600Sbill symsout = 0; 663600Sbill DECLITERATE(allocwalk, sp, ub) 664600Sbill { 665634Shenry if (sp->s_tag >= IGNOREBOUND) 666600Sbill continue; 667634Shenry if ((sp->s_name[0] == 'L') && (sp->s_tag == LABELID) && !savelabels) 668600Sbill continue; 669600Sbill symsout++; 670634Shenry 671634Shenry #ifdef FLEXNAMES 672634Shenry name = sp->s_name; /* save pointer */ 673634Shenry if ( (sp->s_index = strlen(sp->s_name)) != 0){ 674634Shenry sp->s_nmx = stroff; /* clobber pointer */ 675634Shenry stroff += sp->s_index + 1; 676634Shenry } else { 677634Shenry sp->s_nmx = 0; /* clobber pointer */ 678634Shenry } 679634Shenry #endif 680634Shenry sp->s_type = (sp->s_ptype != 0) ? sp->s_ptype : (sp->s_type & (~XFORW)); 681*640Sbill if (readonlydata && (sp->s_type&~N_EXT) == N_DATA) 682*640Sbill sp->s_type = N_TEXT | (sp->s_type & N_EXT); 683634Shenry bwrite(&sp->s_nm, sizeof (struct nlist), symfile); 684634Shenry #ifdef FLEXNAMES 685634Shenry sp->s_name = name; /* restore pointer */ 686600Sbill #endif FLEXNAMES 687600Sbill } 688600Sbill if (symsout != symsdesired) 689600Sbill yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n", 690600Sbill symsout, symsdesired); 691600Sbill #ifdef FLEXNAMES 692600Sbill /* 693600Sbill * Pass 2 through the string pool 694600Sbill */ 695600Sbill symsout = 0; 696600Sbill bwrite(&stroff, sizeof (stroff), symfile); 697600Sbill stroff = sizeof (stroff); 698600Sbill symsout = 0; 699600Sbill DECLITERATE(allocwalk, sp, ub) 700600Sbill { 701634Shenry if (sp->s_tag >= IGNOREBOUND) 702600Sbill continue; 703634Shenry if ((sp->s_name[0] == 'L') && (sp->s_tag == LABELID) && !savelabels) 704600Sbill continue; 705634Shenry sp->s_index = strlen(sp->s_name); 706634Shenry if (sp->s_index) 707634Shenry bwrite(sp->s_name, sp->s_index + 1, symfile); 708600Sbill } 709600Sbill #endif FLEXNAMES 710600Sbill } 711