15828Srrh /* 25828Srrh * Copyright (c) 1982 Regents of the University of California 35828Srrh */ 45828Srrh #ifndef lint 5*13460Srrh static char sccsid[] = "@(#)assyms.c 4.10 06/30/83"; 65828Srrh #endif not lint 75828Srrh 8600Sbill #include <stdio.h> 9600Sbill #include <ctype.h> 10600Sbill #include "as.h" 11600Sbill #include "asscan.h" 12600Sbill #include "assyms.h" 13600Sbill 14600Sbill /* 15600Sbill * Managers for chunks of symbols allocated from calloc() 16600Sbill * We maintain a linked list of such chunks. 17600Sbill * 18600Sbill */ 19600Sbill struct allocbox *allochead; /*head of chunk list*/ 20600Sbill struct allocbox *alloctail; /*tail*/ 21600Sbill struct allocbox *newbox; /*for creating a new chunk*/ 22600Sbill struct symtab *nextsym; /*next symbol free*/ 23600Sbill int symsleft; /*slots left in current chunk*/ 24600Sbill 25600Sbill struct symtab **symptrs; 26600Sbill struct symtab **symdelim[NLOC + NLOC +1]; 27600Sbill struct symtab **symptrub; 28600Sbill /* 29600Sbill * Managers for the dynamically extendable hash table 30600Sbill */ 31600Sbill struct hashdallop *htab; 32600Sbill 335828Srrh Iptr *itab[NINST]; /*maps opcodes to instructions*/ 34600Sbill /* 35600Sbill * Counts what went into the symbol table, so that the 36600Sbill * size of the symbol table can be computed. 37600Sbill */ 38600Sbill int nsyms; /* total number in the symbol table */ 39600Sbill int njxxx; /* number of jxxx entrys */ 40600Sbill int nforgotten; /* number of symbols erroneously entered */ 41600Sbill int nlabels; /* number of label entries */ 42600Sbill 43600Sbill /* 44600Sbill * Managers of the symbol literal storage. 45600Sbill */ 46600Sbill struct strpool *strplhead = 0; 47600Sbill 48600Sbill symtabinit() 49600Sbill { 50600Sbill allochead = 0; 51600Sbill alloctail = 0; 52600Sbill nextsym = 0; 53600Sbill symsleft = 0; 54600Sbill strpoolalloc(); /* get the first strpool storage area */ 55600Sbill htab = 0; 56600Sbill htaballoc(); /* get the first part of the hash table */ 57600Sbill } 58600Sbill 59600Sbill /* 60600Sbill * Install all known instructions in the symbol table 61600Sbill */ 62600Sbill syminstall() 63600Sbill { 645828Srrh register Iptr ip; 65600Sbill register struct symtab **hp; 66600Sbill register char *p1, *p2; 675828Srrh register int i; 68600Sbill 695828Srrh for (i = 0; i < NINST; i++) 705828Srrh itab[i] = (Iptr*)BADPOINT; 715828Srrh 72634Shenry #ifdef FLEXNAMES 735828Srrh for (ip = (Iptr)instab; ip->s_name != 0; ip++) { 74634Shenry #else not FLEXNAMES 755828Srrh for (ip = (Iptr)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 */ 875828Srrh if (itab[ip->i_eopcode] == (Iptr*)BADPOINT){ 885828Srrh itab[ip->i_eopcode] = 895828Srrh (Iptr*)ClearCalloc(256, sizeof(Iptr)); 905828Srrh for (i = 0; i < 256; i++) 915828Srrh itab[ip->i_eopcode][i] = 925828Srrh (Iptr)BADPOINT; 935828Srrh } 945828Srrh itab[ip->i_eopcode][ip->i_popcode] = ip; 95600Sbill } 96600Sbill } 97600Sbill } /*end of syminstall*/ 98600Sbill 99600Sbill 100600Sbill /* 101600Sbill * Assign final values to symbols, 102600Sbill * and overwrite the index field with its relative position in 103600Sbill * the symbol table we give to the loader. 104600Sbill */ 105600Sbill extern struct exec hdr; 106600Sbill 107600Sbill freezesymtab() 108600Sbill { 109600Sbill register struct symtab *sp; 110600Sbill long bs; 111600Sbill register int relpos = 0; 112600Sbill register struct symtab *ubsp; 113600Sbill register struct allocbox *allocwalk; 114600Sbill 115600Sbill DECLITERATE(allocwalk, sp, ubsp) 116600Sbill { 117634Shenry if (sp->s_tag >= IGNOREBOUND) 118600Sbill continue; /*totally ignore jxxx entries */ 119600Sbill /* 120600Sbill * Ignore stabs, but give them a symbol table index 121600Sbill */ 122634Shenry if (sp->s_type & STABFLAG) 123600Sbill goto assignindex; 124634Shenry if ((sp->s_type&XTYPE)==XUNDEF) 125634Shenry sp->s_type = XXTRN+XUNDEF; 126634Shenry else if ((sp->s_type&XTYPE)==XDATA) 127634Shenry sp->s_value += usedot[sp->s_index].e_xvalue; 128634Shenry else if ((sp->s_type&XTYPE)==XTEXT) 129634Shenry sp->s_value += usedot[sp->s_index].e_xvalue; 130634Shenry else if ((sp->s_type&XTYPE)==XBSS) { 131634Shenry bs = sp->s_value; 132634Shenry sp->s_value = hdr.a_bss + datbase; 133600Sbill hdr.a_bss += bs; 134600Sbill } 135600Sbill assignindex: 136634Shenry if ( (sp->s_name[0] != 'L') 137634Shenry || (sp->s_tag != LABELID) 138600Sbill || savelabels 139600Sbill ) /*then, we will write it later on*/ 140634Shenry sp->s_index = relpos++; 141600Sbill } 142600Sbill } 143600Sbill 144600Sbill 145600Sbill 146600Sbill /* 147600Sbill * For all of the stabs that had their final value undefined during pass 1 148600Sbill * and during pass 2 assign a final value. 149600Sbill * We have already given stab entrys a initial approximation 150600Sbill * when we constsructed the sorted symbol table. 151600Sbill * Iteration order doesn't matter. 152600Sbill */ 15312592Scsvaf 15412592Scsvaf stabfix() 15512592Scsvaf { 156600Sbill register struct symtab *sp, **cosp; 157600Sbill register struct symtab *p; 158600Sbill 159600Sbill SYMITERATE(cosp, sp){ 160634Shenry if(sp->s_ptype && (sp->s_type & STABFLAG)) { 161634Shenry p = sp->s_dest; 16212592Scsvaf /* 16312592Scsvaf * STABFLOATING indicates that the offset has been saved in s_desc, s_other 16412592Scsvaf */ 16512592Scsvaf if(sp->s_tag == STABFLOATING) { 16612592Scsvaf sp->s_value = ( ( ((unsigned char) sp->s_other) << 16) | ( (unsigned short) sp->s_desc ) ); 16712592Scsvaf sp->s_value = sp->s_value + p->s_value; 16812592Scsvaf } 16912592Scsvaf else sp->s_value = p->s_value; 170634Shenry sp->s_index = p->s_index; 171634Shenry sp->s_type = p->s_type; 17212592Scsvaf 17312592Scsvaf 174600Sbill } 175600Sbill } 176600Sbill } 177600Sbill 178600Sbill char *Calloc(number, size) 179600Sbill int number, size; 180600Sbill { 181600Sbill register char *newstuff; 1825828Srrh char *sbrk(); 1835828Srrh newstuff = sbrk(number*size); 184600Sbill if ((int)newstuff == -1){ 185600Sbill yyerror("Ran out of Memory"); 186600Sbill delexit(); 187600Sbill } 188600Sbill return(newstuff); 189600Sbill } 190600Sbill 191600Sbill char *ClearCalloc(number, size) 192600Sbill int number, size; 193600Sbill { 194600Sbill register char *newstuff; /* r11 */ 195600Sbill register int length = number * size; /* r10 */ 1965828Srrh #ifdef lint 1975828Srrh length = length; 1985828Srrh #endif length 199600Sbill newstuff = Calloc(number, size); 200600Sbill asm("movc5 $0, (r0), $0, r10, (r11)"); 201600Sbill return(newstuff); 202600Sbill } 203600Sbill 204600Sbill struct symtab *symalloc() 205600Sbill { 206600Sbill if (symsleft == 0){ 207600Sbill newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY); 208600Sbill symsleft = SYMDALLOP; 209600Sbill nextsym = &newbox->symslots[0]; 210600Sbill if (alloctail == 0){ 211600Sbill allochead = alloctail = newbox; 212600Sbill } else { 213600Sbill alloctail->nextalloc = newbox; 214600Sbill alloctail = newbox; 215600Sbill } 216600Sbill } 217600Sbill --symsleft; 218600Sbill ++nsyms; 219600Sbill return(nextsym++); 220600Sbill } 221600Sbill 222600Sbill strpoolalloc() 223600Sbill { 224600Sbill register struct strpool *new; 225600Sbill 226600Sbill new = (struct strpool *)Calloc(1, sizeof (struct strpool)); 227600Sbill new->str_nalloc = 0; 228600Sbill new->str_next = strplhead; 229600Sbill strplhead = new; 230600Sbill } 231600Sbill 232600Sbill symcmp(Pptr, Qptr) 233600Sbill struct symtab **Pptr, **Qptr; 234600Sbill { 235600Sbill register struct symtab *p = *Pptr; 236600Sbill register struct symtab *q = *Qptr; 237634Shenry if (p->s_index < q->s_index) 238600Sbill return(-1); 239634Shenry if (p->s_index > q->s_index) 240600Sbill return(1); 241634Shenry if (p->s_value < q->s_value) 242600Sbill return(-1); 243634Shenry if (p->s_value > q->s_value) 244600Sbill return(1); 245600Sbill /* 246600Sbill * Force jxxx entries to virtually preceed labels defined 247600Sbill * to follow the jxxxx instruction, so that bumping the 248600Sbill * jxxx instruction correctly fixes up the following labels 249600Sbill */ 250634Shenry if (p->s_tag >= IGNOREBOUND) /*p points to a jxxx*/ 251600Sbill return(-1); 252634Shenry if (q->s_tag >= IGNOREBOUND) 253600Sbill return(1); 254600Sbill /* 255600Sbill * both are now just plain labels; the relative order doesn't 256600Sbill * matter. Both can't be jxxxes, as they would have different 257600Sbill * values. 258600Sbill */ 259600Sbill return(0); 260600Sbill } /*end of symcmp*/ 261600Sbill 262600Sbill /* 263600Sbill * We construct the auxiliary table of pointers, symptrs and 264600Sbill * symdelim 265600Sbill * We also assign preliminary values to stab entries that did not yet 266600Sbill * have an absolute value (because they initially referred to 267600Sbill * forward references). We don't worry about .stabds, as they 268600Sbill * already have an estimated final value 269600Sbill */ 270600Sbill 271600Sbill sortsymtab() 272600Sbill { 273600Sbill register struct symtab *sp; 274600Sbill register struct symtab **cowalk; 275600Sbill register struct allocbox *allocwalk; 276600Sbill struct symtab *ubsp; 277600Sbill int segno; 278600Sbill int slotno; 279600Sbill int symsin; /*number put into symptrs*/ 280600Sbill 281600Sbill symptrs = (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs); 282600Sbill /* 283600Sbill * Allocate one word at the beginning of the symptr array 284600Sbill * so that backwards scans through the symptr array will 285600Sbill * work correctly while scanning through the zeroth segment 286600Sbill */ 287600Sbill *symptrs++ = 0; 288600Sbill cowalk = symptrs; 289600Sbill symsin = 0; 290600Sbill DECLITERATE(allocwalk, sp, ubsp) { 291634Shenry if (sp->s_ptype && (sp->s_type &STABFLAG)){ 292634Shenry sp->s_value = sp->s_dest->s_value; 293634Shenry sp->s_index = sp->s_dest->s_index; 294600Sbill } 295600Sbill if (symsin >= nsyms) 296600Sbill yyerror("INTERNAL ERROR: overfilled symbol table indirection table"); 297600Sbill *cowalk++ = sp; 298600Sbill symsin++; 299600Sbill } 300600Sbill if (symsin != nsyms) 301600Sbill yyerror("INTERNAL ERROR: installed %d syms, should have installed %d", 302600Sbill symsin, nsyms); 303600Sbill symptrub = &symptrs[nsyms ]; 304600Sbill qsort(symptrs, nsyms, sizeof *symptrs, symcmp); 305600Sbill symdelim[0] = symptrs; 306600Sbill for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1; 307600Sbill segno < NLOC + NLOC; 308600Sbill segno++, slotno++){ 309634Shenry for (; sp && sp->s_index == segno; sp = *++cowalk); 310600Sbill symdelim[slotno] = cowalk; /*forms the ub delimeter*/ 311600Sbill } 312600Sbill } /*end of sortsymtab*/ 313600Sbill 314600Sbill #ifdef DEBUG 315600Sbill dumpsymtab() 316600Sbill { 317600Sbill register int segno; 318600Sbill register struct symtab *sp, **cosp, *ub; 319600Sbill char *tagstring(); 320600Sbill 321600Sbill printf("Symbol Table dump:\n"); 322600Sbill for (segno = 0; segno < NLOC + NLOC; segno++){ 323600Sbill printf("Segment number: %d\n", segno); 324600Sbill SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){ 325600Sbill #ifdef FLEXNAMES 326600Sbill printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n", 327634Shenry segno, sp->s_name, 328634Shenry sp->s_value, sp->s_index, 329634Shenry tagstring(sp->s_tag)); 330600Sbill #else not FLEXNAMES 331600Sbill printf("\tSeg: %d \"%*.*s\" value: %d index: %d tag %s\n", 332*13460Srrh segno, NCPName, NCPName, sp->s_name, 333634Shenry sp->s_value, sp->s_index, 334634Shenry tagstring(sp->s_tag)); 335600Sbill #endif not FLEXNAMES 336600Sbill printf("\t\ttype: %d jxbump %d jxfear: %d\n", 337634Shenry sp->s_type, sp->s_jxbump, sp->s_jxfear); 338600Sbill } 339600Sbill printf("\n\n"); 340600Sbill } 341600Sbill } 342600Sbill 343600Sbill static char tagbuff[4]; 344600Sbill 345600Sbill char *tagstring(tag) 346600Sbill unsigned char tag; 347600Sbill { 348600Sbill switch(tag){ 349600Sbill case JXACTIVE: return("active"); 350600Sbill case JXNOTYET: return("notyet"); 351600Sbill case JXALIGN: return("align"); 352600Sbill case JXQUESTIONABLE: return("jxquestionable"); 353600Sbill case JXINACTIVE: return("inactive"); 354600Sbill case JXTUNNEL: return("tunnel"); 355600Sbill case OBSOLETE: return("obsolete"); 356600Sbill case IGNOREBOUND: return("ignorebound"); 357600Sbill case STABFLOATING: return("stabfloating"); 358600Sbill case STABFIXED: return("stabfixed"); 359600Sbill case LABELID: return("labelid"); 360600Sbill case OKTOBUMP: return("oktobump"); 361600Sbill case ISET: return("iset"); 362600Sbill case ILSYM: return("ilsym"); 363600Sbill default: sprintf(tagbuff,"%d", tag); 364600Sbill return(tagbuff); 365600Sbill } 366600Sbill } 367600Sbill #endif DEBUG 368600Sbill 369600Sbill htaballoc() 370600Sbill { 371600Sbill register struct hashdallop *new; 372600Sbill new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop)); 373600Sbill if (htab == 0) 374600Sbill htab = new; 375600Sbill else { /* add AFTER the 1st slot */ 376600Sbill new->h_next = htab->h_next; 377600Sbill htab->h_next = new; 378600Sbill } 379600Sbill } 380600Sbill 381600Sbill #define HASHCLOGGED (NHASH / 2) 382600Sbill 383600Sbill /* 384600Sbill * Lookup a symbol stored in extern yytext. 385600Sbill * All strings passed in via extern yytext had better have 386600Sbill * a trailing null. Strings are placed in yytext for hashing by 387600Sbill * syminstall() and by yylex(); 388600Sbill * 389600Sbill * We take pains to avoid function calls; this functdion 390600Sbill * is called quite frequently, and the calls overhead 391600Sbill * in the vax contributes significantly to the overall 392600Sbill * execution speed of as. 393600Sbill */ 394600Sbill struct symtab **lookup(instflg) 395600Sbill int instflg; /* 0: don't install */ 396600Sbill { 397600Sbill static int initialprobe; 398600Sbill register struct symtab **hp; 399600Sbill register char *from; 400600Sbill register char *to; 401600Sbill register int len; 402600Sbill register int nprobes; 403600Sbill static struct hashdallop *hdallop; 404600Sbill static struct symtab **emptyslot; 405600Sbill static struct hashdallop *emptyhd; 406600Sbill static struct symtab **hp_ub; 407600Sbill 408600Sbill emptyslot = 0; 409600Sbill for (nprobes = 0, from = yytext; 410600Sbill *from; 411600Sbill nprobes <<= 2, nprobes += *from++) 412600Sbill continue; 413600Sbill nprobes += from[-1] << 5; 414600Sbill nprobes %= NHASH; 415600Sbill if (nprobes < 0) 416600Sbill nprobes += NHASH; 417600Sbill 418600Sbill initialprobe = nprobes; 419600Sbill for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){ 420600Sbill for (hp = &(hdallop->h_htab[initialprobe]), 421600Sbill nprobes = 1, 422600Sbill hp_ub = &(hdallop->h_htab[NHASH]); 423600Sbill (*hp) && (nprobes < NHASH); 424600Sbill hp += nprobes, 425600Sbill hp -= (hp >= hp_ub) ? NHASH:0, 426600Sbill nprobes += 2) 427600Sbill { 428600Sbill from = yytext; 429634Shenry to = (*hp)->s_name; 430600Sbill #ifndef FLEXNAMES 431*13460Srrh for (len = 0; (len<NCPName) && *from; len++) 432600Sbill if (*from++ != *to++) 433600Sbill goto nextprobe; 434*13460Srrh if (len >= NCPName) /*both are maximal length*/ 435600Sbill return(hp); 436600Sbill if (*to == 0) /*assert *from == 0*/ 437600Sbill return(hp); 438600Sbill #else FLEXNAMES 439600Sbill while (*from && *to) 440600Sbill if (*from++ != *to++) 441600Sbill goto nextprobe; 442600Sbill if (*to == *from) /*assert both are == 0*/ 443600Sbill return(hp); 444600Sbill #endif FLEXNAMES 445600Sbill 446600Sbill nextprobe: ; 447600Sbill } 448600Sbill if (*hp == 0 && emptyslot == 0 && 449600Sbill hdallop->h_nused < HASHCLOGGED) { 450600Sbill emptyslot = hp; 451600Sbill emptyhd = hdallop; 452600Sbill } 453600Sbill } 454600Sbill if (emptyslot == 0) { 455600Sbill htaballoc(); 456600Sbill hdallop = htab->h_next; /* aren't we smart! */ 457600Sbill hp = &hdallop->h_htab[initialprobe]; 458600Sbill } else { 459600Sbill hdallop = emptyhd; 460600Sbill hp = emptyslot; 461600Sbill } 462600Sbill if (instflg) { 463600Sbill *hp = symalloc(); 464600Sbill hdallop->h_nused++; 465600Sbill #ifndef FLEXNAMES 466*13460Srrh strncpy((*hp)->s_name, yytext, NCPName); 467600Sbill #else FLEXNAMES 46813447Srrh for (from = yytext, len = 0; *from++; len++) 469600Sbill continue; 47013447Srrh /* 47113447Srrh * save string and trailing null 47213447Srrh */ 47313447Srrh (*hp)->s_name = savestr(yytext, len + 1); 474600Sbill #endif FLEXNAMES 475600Sbill } 476600Sbill return(hp); 477600Sbill } /*end of lookup*/ 47813447Srrh /* 47913447Srrh * save a string str, length len in the string pool. 48013447Srrh * string known just by its length; can have or not have trailing nulls. 48113447Srrh * 48213447Srrh * The length of the string occurs as a short just before 48313447Srrh * the character pointer returned. 48413447Srrh */ 48513447Srrh char *savestr(str, len) 48613447Srrh char *str; 48713447Srrh int len; 488600Sbill { 48913447Srrh char *res; 490600Sbill 49113447Srrh if (len + sizeof(lgtype) >= (STRPOOLDALLOP - strplhead->str_nalloc)) 492600Sbill strpoolalloc(); 49313447Srrh res = strplhead->str_names + strplhead->str_nalloc; 49413447Srrh plgtype(res, len); 49513447Srrh movestr(res, str, len); 49613447Srrh strplhead->str_nalloc += sizeof(lgtype) + len; 49713447Srrh return(res); 498600Sbill } 499600Sbill 500600Sbill /* 501600Sbill * The relocation information is saved internally in an array of 502600Sbill * lists of relocation buffers. The relocation buffers are 503600Sbill * exactly the same size as a token buffer; if we use VM for the 504600Sbill * temporary file we reclaim this storage, otherwise we create 505600Sbill * them by mallocing. 506600Sbill */ 507600Sbill #define RELBUFLG TOKBUFLG 508600Sbill #define NRELOC ((TOKBUFLG - \ 509600Sbill (sizeof (int) + sizeof (struct relbufdesc *)) \ 510600Sbill ) / (sizeof (struct relocation_info))) 511600Sbill 512600Sbill struct relbufdesc{ 513600Sbill int rel_count; 514600Sbill struct relbufdesc *rel_next; 515600Sbill struct relocation_info rel_reloc[NRELOC]; 516600Sbill }; 517600Sbill extern struct relbufdesc *tok_free; 518600Sbill #define rel_free tok_free 519600Sbill static struct relbufdesc *rel_temp; 520634Shenry struct relocation_info r_can_1PC; 521634Shenry struct relocation_info r_can_0PC; 522600Sbill 523600Sbill initoutrel() 524600Sbill { 525634Shenry r_can_0PC.r_address = 0; 526634Shenry r_can_0PC.r_symbolnum = 0; 527634Shenry r_can_0PC.r_pcrel = 0; 528634Shenry r_can_0PC.r_length = 0; 529634Shenry r_can_0PC.r_extern = 0; 530634Shenry 531634Shenry r_can_1PC = r_can_0PC; 532600Sbill r_can_1PC.r_pcrel = 1; 533600Sbill } 534600Sbill 535675Shenry outrel(xp, reloc_how) 536675Shenry register struct exp *xp; 5375828Srrh int reloc_how; /* TYPB..TYPH + (possibly)RELOC_PCREL */ 538600Sbill { 539675Shenry struct relocation_info reloc; 540675Shenry register int x_type_mask; 54113447Srrh int pcrel; 542600Sbill 543675Shenry x_type_mask = xp->e_xtype & ~XFORW; 544675Shenry pcrel = reloc_how & RELOC_PCREL; 545675Shenry reloc_how &= ~RELOC_PCREL; 546675Shenry 547600Sbill if (bitoff&07) 548600Sbill yyerror("Padding error"); 549675Shenry if (x_type_mask == XUNDEF) 550600Sbill yyerror("Undefined reference"); 551600Sbill 552675Shenry if ( (x_type_mask != XABS) || pcrel ) { 553675Shenry if (ty_NORELOC[reloc_how]) 5545828Srrh yyerror("Illegal Relocation of floating or large int number."); 555675Shenry reloc = pcrel ? r_can_1PC : r_can_0PC; 556634Shenry reloc.r_address = dotp->e_xvalue - 557640Sbill ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase ); 558675Shenry reloc.r_length = ty_nlg[reloc_how]; 559675Shenry switch(x_type_mask){ 560600Sbill case XXTRN | XUNDEF: 561675Shenry reloc.r_symbolnum = xp->e_xname->s_index; 562600Sbill reloc.r_extern = 1; 563600Sbill break; 564600Sbill default: 565675Shenry if (readonlydata && (x_type_mask&~XXTRN) == XDATA) 566675Shenry x_type_mask = XTEXT | (x_type_mask&XXTRN); 567675Shenry reloc.r_symbolnum = x_type_mask; 568600Sbill break; 569600Sbill } 570600Sbill if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){ 571600Sbill if (rel_free){ 572600Sbill rel_temp = rel_free; 573600Sbill rel_free = rel_temp->rel_next; 574600Sbill } else { 575600Sbill rel_temp = (struct relbufdesc *) 576600Sbill Calloc(1,sizeof (struct relbufdesc)); 577600Sbill } 578600Sbill rel_temp->rel_count = 0; 579600Sbill rel_temp->rel_next = relfil; 580600Sbill relfil = rusefile[dotp - &usedot[0]] = rel_temp; 581600Sbill } 582600Sbill relfil->rel_reloc[relfil->rel_count++] = reloc; 583600Sbill } 584600Sbill /* 585600Sbill * write the unrelocated value to the text file 586600Sbill */ 587675Shenry dotp->e_xvalue += ty_nbyte[reloc_how]; 588675Shenry if (pcrel) 589675Shenry xp->e_xvalue -= dotp->e_xvalue; 5905828Srrh switch(reloc_how){ 5915828Srrh case TYPO: 5925828Srrh case TYPQ: 5935828Srrh 5945828Srrh case TYPF: 5955828Srrh case TYPD: 5965828Srrh case TYPG: 5975828Srrh case TYPH: 5985828Srrh bignumwrite(xp->e_number, reloc_how); 5995828Srrh break; 6005828Srrh 6015828Srrh default: 6025828Srrh bwrite((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil); 6035828Srrh break; 6045828Srrh } 605600Sbill } 606600Sbill /* 607600Sbill * Flush out all of the relocation information. 608600Sbill * Note that the individual lists of buffers are in 609600Sbill * reverse order, so we must reverse them 610600Sbill */ 611600Sbill off_t closeoutrel(relocfile) 612600Sbill BFILE *relocfile; 613600Sbill { 614600Sbill int locindex; 615600Sbill u_long Closeoutrel(); 616600Sbill 617600Sbill trsize = 0; 618600Sbill for (locindex = 0; locindex < NLOC; locindex++){ 619600Sbill trsize += Closeoutrel(rusefile[locindex], relocfile); 620600Sbill } 621600Sbill drsize = 0; 622600Sbill for (locindex = 0; locindex < NLOC; locindex++){ 623600Sbill drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile); 624600Sbill } 625600Sbill return(trsize + drsize); 626600Sbill } 627600Sbill 628600Sbill u_long Closeoutrel(relfil, relocfile) 629600Sbill struct relbufdesc *relfil; 630600Sbill BFILE *relocfile; 631600Sbill { 632600Sbill u_long tail; 633600Sbill if (relfil == 0) 634600Sbill return(0L); 635600Sbill tail = Closeoutrel(relfil->rel_next, relocfile); 636600Sbill bwrite((char *)&relfil->rel_reloc[0], 637600Sbill relfil->rel_count * sizeof (struct relocation_info), 638600Sbill relocfile); 639600Sbill return(tail + relfil->rel_count * sizeof (struct relocation_info)); 640600Sbill } 641600Sbill 642634Shenry #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels)) 643600Sbill int sizesymtab() 644600Sbill { 645634Shenry return (sizeof (struct nlist) * NOUTSYMS); 646600Sbill } 647600Sbill 648600Sbill #ifdef FLEXNAMES 649600Sbill /* 650600Sbill * We write out the flexible length character strings for names 651600Sbill * in two stages. 65213447Srrh * 1) We always! maintain a fixed sized name list entry; 653600Sbill * the string is indexed by a four byte quantity from the beginning 654600Sbill * of the string pool area. Index 0 is reserved, and indicates 655600Sbill * that there is no associated string. The first valid index is 4. 656600Sbill * 2) We concatenate together and write all of the strings 657600Sbill * in the string pool at the end of the name list. The first 658600Sbill * four bytes in the string pool are indexed only by 0 (see above); 659600Sbill * they contain the total number of bytes in the string pool. 660600Sbill */ 661600Sbill #endif FLEXNAMES 662600Sbill 663600Sbill /* 664600Sbill * Write out n symbols to file f, beginning at p 665600Sbill * ignoring symbols that are obsolete, jxxx instructions, and 666600Sbill * possibly, labels 667600Sbill */ 668600Sbill 669600Sbill int symwrite(symfile) 670600Sbill BFILE *symfile; 671600Sbill { 672600Sbill int symsout; /*those actually written*/ 673600Sbill int symsdesired = NOUTSYMS; 674600Sbill register struct symtab *sp, *ub; 675600Sbill #ifdef FLEXNAMES 676634Shenry char *name; /* temp to save the name */ 677600Sbill long stroff = sizeof (stroff); 678634Shenry /* 679634Shenry * We use sp->s_index to hold the length of the 680634Shenry * name; it isn't used for anything else 681634Shenry */ 682600Sbill #endif FLEXNAMES 683600Sbill 684600Sbill register struct allocbox *allocwalk; 685600Sbill 686600Sbill symsout = 0; 687600Sbill DECLITERATE(allocwalk, sp, ub) 688600Sbill { 689634Shenry if (sp->s_tag >= IGNOREBOUND) 690600Sbill continue; 691634Shenry if ((sp->s_name[0] == 'L') && (sp->s_tag == LABELID) && !savelabels) 692600Sbill continue; 693600Sbill symsout++; 694634Shenry 695634Shenry #ifdef FLEXNAMES 696634Shenry name = sp->s_name; /* save pointer */ 69713447Srrh /* 69813447Srrh * the length of the symbol table string 69913447Srrh * always includes the trailing null 70013447Srrh */ 70113447Srrh if (sp->s_name && (sp->s_index = STRLEN(sp->s_name))){ 702634Shenry sp->s_nmx = stroff; /* clobber pointer */ 70313447Srrh stroff += sp->s_index; 704634Shenry } else { 70513447Srrh sp->s_nmx = 0; 706634Shenry } 707634Shenry #endif 708634Shenry sp->s_type = (sp->s_ptype != 0) ? sp->s_ptype : (sp->s_type & (~XFORW)); 709640Sbill if (readonlydata && (sp->s_type&~N_EXT) == N_DATA) 710640Sbill sp->s_type = N_TEXT | (sp->s_type & N_EXT); 7115828Srrh bwrite((char *)&sp->s_nm, sizeof (struct nlist), symfile); 712634Shenry #ifdef FLEXNAMES 713634Shenry sp->s_name = name; /* restore pointer */ 714600Sbill #endif FLEXNAMES 715600Sbill } 716600Sbill if (symsout != symsdesired) 717600Sbill yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n", 718600Sbill symsout, symsdesired); 719600Sbill #ifdef FLEXNAMES 720600Sbill /* 721600Sbill * Pass 2 through the string pool 722600Sbill */ 723600Sbill symsout = 0; 7245828Srrh bwrite((char *)&stroff, sizeof (stroff), symfile); 725600Sbill stroff = sizeof (stroff); 726600Sbill symsout = 0; 727600Sbill DECLITERATE(allocwalk, sp, ub) 728600Sbill { 729634Shenry if (sp->s_tag >= IGNOREBOUND) 730600Sbill continue; 731634Shenry if ((sp->s_name[0] == 'L') && (sp->s_tag == LABELID) && !savelabels) 732600Sbill continue; 73313447Srrh if (sp->s_name && (sp->s_index = STRLEN(sp->s_name))){ 73413447Srrh bwrite(sp->s_name, sp->s_index, symfile); 73513447Srrh } 736600Sbill } 737600Sbill #endif FLEXNAMES 738600Sbill } 739