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