15828Srrh /* 25828Srrh * Copyright (c) 1982 Regents of the University of California 35828Srrh */ 45828Srrh #ifndef lint 5*13514Srrh static char sccsid[] = "@(#)assyms.c 4.11 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 72*13514Srrh for (ip = (Iptr)instab; FETCHNAME(ip)[0]; ip++) { 73*13514Srrh p1 = FETCHNAME(ip); 74600Sbill p2 = yytext; 75600Sbill while (*p2++ = *p1++); 76600Sbill hp = lookup(0); /* 0 => don't install this*/ 77600Sbill if (*hp==NULL) { 78600Sbill *hp = (struct symtab *)ip; 79634Shenry if ( (ip->s_tag!=INSTn) 80634Shenry && (ip->s_tag!=INST0) 81634Shenry && (ip->s_tag!=0)) 82600Sbill continue; /* was pseudo-op */ 835828Srrh if (itab[ip->i_eopcode] == (Iptr*)BADPOINT){ 845828Srrh itab[ip->i_eopcode] = 855828Srrh (Iptr*)ClearCalloc(256, sizeof(Iptr)); 865828Srrh for (i = 0; i < 256; i++) 875828Srrh itab[ip->i_eopcode][i] = 885828Srrh (Iptr)BADPOINT; 895828Srrh } 905828Srrh itab[ip->i_eopcode][ip->i_popcode] = ip; 91600Sbill } 92600Sbill } 93600Sbill } /*end of syminstall*/ 94600Sbill 95600Sbill 96600Sbill /* 97600Sbill * Assign final values to symbols, 98600Sbill * and overwrite the index field with its relative position in 99600Sbill * the symbol table we give to the loader. 100600Sbill */ 101600Sbill extern struct exec hdr; 102600Sbill 103600Sbill freezesymtab() 104600Sbill { 105600Sbill register struct symtab *sp; 106600Sbill long bs; 107600Sbill register int relpos = 0; 108600Sbill register struct symtab *ubsp; 109600Sbill register struct allocbox *allocwalk; 110600Sbill 111600Sbill DECLITERATE(allocwalk, sp, ubsp) 112600Sbill { 113634Shenry if (sp->s_tag >= IGNOREBOUND) 114600Sbill continue; /*totally ignore jxxx entries */ 115600Sbill /* 116600Sbill * Ignore stabs, but give them a symbol table index 117600Sbill */ 118634Shenry if (sp->s_type & STABFLAG) 119600Sbill goto assignindex; 120634Shenry if ((sp->s_type&XTYPE)==XUNDEF) 121634Shenry sp->s_type = XXTRN+XUNDEF; 122634Shenry else if ((sp->s_type&XTYPE)==XDATA) 123634Shenry sp->s_value += usedot[sp->s_index].e_xvalue; 124634Shenry else if ((sp->s_type&XTYPE)==XTEXT) 125634Shenry sp->s_value += usedot[sp->s_index].e_xvalue; 126634Shenry else if ((sp->s_type&XTYPE)==XBSS) { 127634Shenry bs = sp->s_value; 128634Shenry sp->s_value = hdr.a_bss + datbase; 129600Sbill hdr.a_bss += bs; 130600Sbill } 131600Sbill assignindex: 132*13514Srrh if ( (FETCHNAME(sp)[0] != 'L') 133634Shenry || (sp->s_tag != LABELID) 134600Sbill || savelabels 135600Sbill ) /*then, we will write it later on*/ 136634Shenry sp->s_index = relpos++; 137600Sbill } 138600Sbill } 139600Sbill 140600Sbill 141600Sbill 142600Sbill /* 143600Sbill * For all of the stabs that had their final value undefined during pass 1 144600Sbill * and during pass 2 assign a final value. 145600Sbill * We have already given stab entrys a initial approximation 146600Sbill * when we constsructed the sorted symbol table. 147600Sbill * Iteration order doesn't matter. 148600Sbill */ 14912592Scsvaf 15012592Scsvaf stabfix() 15112592Scsvaf { 152600Sbill register struct symtab *sp, **cosp; 153600Sbill register struct symtab *p; 154600Sbill 155600Sbill SYMITERATE(cosp, sp){ 156634Shenry if(sp->s_ptype && (sp->s_type & STABFLAG)) { 157634Shenry p = sp->s_dest; 15812592Scsvaf /* 15912592Scsvaf * STABFLOATING indicates that the offset has been saved in s_desc, s_other 16012592Scsvaf */ 16112592Scsvaf if(sp->s_tag == STABFLOATING) { 16212592Scsvaf sp->s_value = ( ( ((unsigned char) sp->s_other) << 16) | ( (unsigned short) sp->s_desc ) ); 16312592Scsvaf sp->s_value = sp->s_value + p->s_value; 16412592Scsvaf } 16512592Scsvaf else sp->s_value = p->s_value; 166634Shenry sp->s_index = p->s_index; 167634Shenry sp->s_type = p->s_type; 16812592Scsvaf 16912592Scsvaf 170600Sbill } 171600Sbill } 172600Sbill } 173600Sbill 174600Sbill char *Calloc(number, size) 175600Sbill int number, size; 176600Sbill { 177600Sbill register char *newstuff; 1785828Srrh char *sbrk(); 1795828Srrh newstuff = sbrk(number*size); 180600Sbill if ((int)newstuff == -1){ 181600Sbill yyerror("Ran out of Memory"); 182600Sbill delexit(); 183600Sbill } 184600Sbill return(newstuff); 185600Sbill } 186600Sbill 187600Sbill char *ClearCalloc(number, size) 188600Sbill int number, size; 189600Sbill { 190600Sbill register char *newstuff; /* r11 */ 191600Sbill register int length = number * size; /* r10 */ 1925828Srrh #ifdef lint 1935828Srrh length = length; 1945828Srrh #endif length 195600Sbill newstuff = Calloc(number, size); 196600Sbill asm("movc5 $0, (r0), $0, r10, (r11)"); 197600Sbill return(newstuff); 198600Sbill } 199600Sbill 200600Sbill struct symtab *symalloc() 201600Sbill { 202600Sbill if (symsleft == 0){ 203600Sbill newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY); 204600Sbill symsleft = SYMDALLOP; 205600Sbill nextsym = &newbox->symslots[0]; 206600Sbill if (alloctail == 0){ 207600Sbill allochead = alloctail = newbox; 208600Sbill } else { 209600Sbill alloctail->nextalloc = newbox; 210600Sbill alloctail = newbox; 211600Sbill } 212600Sbill } 213600Sbill --symsleft; 214600Sbill ++nsyms; 215600Sbill return(nextsym++); 216600Sbill } 217600Sbill 218600Sbill strpoolalloc() 219600Sbill { 220600Sbill register struct strpool *new; 221600Sbill 222600Sbill new = (struct strpool *)Calloc(1, sizeof (struct strpool)); 223600Sbill new->str_nalloc = 0; 224600Sbill new->str_next = strplhead; 225600Sbill strplhead = new; 226600Sbill } 227600Sbill 228600Sbill symcmp(Pptr, Qptr) 229600Sbill struct symtab **Pptr, **Qptr; 230600Sbill { 231600Sbill register struct symtab *p = *Pptr; 232600Sbill register struct symtab *q = *Qptr; 233634Shenry if (p->s_index < q->s_index) 234600Sbill return(-1); 235634Shenry if (p->s_index > q->s_index) 236600Sbill return(1); 237634Shenry if (p->s_value < q->s_value) 238600Sbill return(-1); 239634Shenry if (p->s_value > q->s_value) 240600Sbill return(1); 241600Sbill /* 242600Sbill * Force jxxx entries to virtually preceed labels defined 243600Sbill * to follow the jxxxx instruction, so that bumping the 244600Sbill * jxxx instruction correctly fixes up the following labels 245600Sbill */ 246634Shenry if (p->s_tag >= IGNOREBOUND) /*p points to a jxxx*/ 247600Sbill return(-1); 248634Shenry if (q->s_tag >= IGNOREBOUND) 249600Sbill return(1); 250600Sbill /* 251600Sbill * both are now just plain labels; the relative order doesn't 252600Sbill * matter. Both can't be jxxxes, as they would have different 253600Sbill * values. 254600Sbill */ 255600Sbill return(0); 256600Sbill } /*end of symcmp*/ 257600Sbill 258600Sbill /* 259600Sbill * We construct the auxiliary table of pointers, symptrs and 260600Sbill * symdelim 261600Sbill * We also assign preliminary values to stab entries that did not yet 262600Sbill * have an absolute value (because they initially referred to 263600Sbill * forward references). We don't worry about .stabds, as they 264600Sbill * already have an estimated final value 265600Sbill */ 266600Sbill 267600Sbill sortsymtab() 268600Sbill { 269600Sbill register struct symtab *sp; 270600Sbill register struct symtab **cowalk; 271600Sbill register struct allocbox *allocwalk; 272600Sbill struct symtab *ubsp; 273600Sbill int segno; 274600Sbill int slotno; 275600Sbill int symsin; /*number put into symptrs*/ 276600Sbill 277600Sbill symptrs = (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs); 278600Sbill /* 279600Sbill * Allocate one word at the beginning of the symptr array 280600Sbill * so that backwards scans through the symptr array will 281600Sbill * work correctly while scanning through the zeroth segment 282600Sbill */ 283600Sbill *symptrs++ = 0; 284600Sbill cowalk = symptrs; 285600Sbill symsin = 0; 286600Sbill DECLITERATE(allocwalk, sp, ubsp) { 287634Shenry if (sp->s_ptype && (sp->s_type &STABFLAG)){ 288634Shenry sp->s_value = sp->s_dest->s_value; 289634Shenry sp->s_index = sp->s_dest->s_index; 290600Sbill } 291600Sbill if (symsin >= nsyms) 292600Sbill yyerror("INTERNAL ERROR: overfilled symbol table indirection table"); 293600Sbill *cowalk++ = sp; 294600Sbill symsin++; 295600Sbill } 296600Sbill if (symsin != nsyms) 297600Sbill yyerror("INTERNAL ERROR: installed %d syms, should have installed %d", 298600Sbill symsin, nsyms); 299600Sbill symptrub = &symptrs[nsyms ]; 300600Sbill qsort(symptrs, nsyms, sizeof *symptrs, symcmp); 301600Sbill symdelim[0] = symptrs; 302600Sbill for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1; 303600Sbill segno < NLOC + NLOC; 304600Sbill segno++, slotno++){ 305634Shenry for (; sp && sp->s_index == segno; sp = *++cowalk); 306600Sbill symdelim[slotno] = cowalk; /*forms the ub delimeter*/ 307600Sbill } 308600Sbill } /*end of sortsymtab*/ 309600Sbill 310600Sbill #ifdef DEBUG 311600Sbill dumpsymtab() 312600Sbill { 313600Sbill register int segno; 314600Sbill register struct symtab *sp, **cosp, *ub; 315600Sbill char *tagstring(); 316600Sbill 317600Sbill printf("Symbol Table dump:\n"); 318600Sbill for (segno = 0; segno < NLOC + NLOC; segno++){ 319600Sbill printf("Segment number: %d\n", segno); 320600Sbill SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){ 321600Sbill #ifdef FLEXNAMES 322600Sbill printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n", 323*13514Srrh segno, FETCHNAME(sp), 324634Shenry sp->s_value, sp->s_index, 325634Shenry tagstring(sp->s_tag)); 326600Sbill #else not FLEXNAMES 327600Sbill printf("\tSeg: %d \"%*.*s\" value: %d index: %d tag %s\n", 328*13514Srrh segno, NCPName, NCPName, FETCHNAME(sp), 329634Shenry sp->s_value, sp->s_index, 330634Shenry tagstring(sp->s_tag)); 331600Sbill #endif not FLEXNAMES 332600Sbill printf("\t\ttype: %d jxbump %d jxfear: %d\n", 333634Shenry sp->s_type, sp->s_jxbump, sp->s_jxfear); 334600Sbill } 335600Sbill printf("\n\n"); 336600Sbill } 337600Sbill } 338600Sbill 339600Sbill static char tagbuff[4]; 340600Sbill 341600Sbill char *tagstring(tag) 342600Sbill unsigned char tag; 343600Sbill { 344600Sbill switch(tag){ 345600Sbill case JXACTIVE: return("active"); 346600Sbill case JXNOTYET: return("notyet"); 347600Sbill case JXALIGN: return("align"); 348600Sbill case JXQUESTIONABLE: return("jxquestionable"); 349600Sbill case JXINACTIVE: return("inactive"); 350600Sbill case JXTUNNEL: return("tunnel"); 351600Sbill case OBSOLETE: return("obsolete"); 352600Sbill case IGNOREBOUND: return("ignorebound"); 353600Sbill case STABFLOATING: return("stabfloating"); 354600Sbill case STABFIXED: return("stabfixed"); 355600Sbill case LABELID: return("labelid"); 356600Sbill case OKTOBUMP: return("oktobump"); 357600Sbill case ISET: return("iset"); 358600Sbill case ILSYM: return("ilsym"); 359600Sbill default: sprintf(tagbuff,"%d", tag); 360600Sbill return(tagbuff); 361600Sbill } 362600Sbill } 363600Sbill #endif DEBUG 364600Sbill 365600Sbill htaballoc() 366600Sbill { 367600Sbill register struct hashdallop *new; 368600Sbill new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop)); 369600Sbill if (htab == 0) 370600Sbill htab = new; 371600Sbill else { /* add AFTER the 1st slot */ 372600Sbill new->h_next = htab->h_next; 373600Sbill htab->h_next = new; 374600Sbill } 375600Sbill } 376600Sbill 377600Sbill #define HASHCLOGGED (NHASH / 2) 378600Sbill 379600Sbill /* 380600Sbill * Lookup a symbol stored in extern yytext. 381600Sbill * All strings passed in via extern yytext had better have 382600Sbill * a trailing null. Strings are placed in yytext for hashing by 383600Sbill * syminstall() and by yylex(); 384600Sbill * 385600Sbill * We take pains to avoid function calls; this functdion 386600Sbill * is called quite frequently, and the calls overhead 387600Sbill * in the vax contributes significantly to the overall 388600Sbill * execution speed of as. 389600Sbill */ 390600Sbill struct symtab **lookup(instflg) 391600Sbill int instflg; /* 0: don't install */ 392600Sbill { 393600Sbill static int initialprobe; 394600Sbill register struct symtab **hp; 395600Sbill register char *from; 396600Sbill register char *to; 397600Sbill register int len; 398600Sbill register int nprobes; 399*13514Srrh static struct hashdallop *hdallop; 400*13514Srrh static struct symtab **emptyslot; 401*13514Srrh static struct hashdallop *emptyhd; 402*13514Srrh static struct symtab **hp_ub; 403*13514Srrh static struct strdesc strdp; 404600Sbill 405600Sbill emptyslot = 0; 406600Sbill for (nprobes = 0, from = yytext; 407600Sbill *from; 408600Sbill nprobes <<= 2, nprobes += *from++) 409600Sbill continue; 410600Sbill nprobes += from[-1] << 5; 411600Sbill nprobes %= NHASH; 412600Sbill if (nprobes < 0) 413600Sbill nprobes += NHASH; 414600Sbill 415600Sbill initialprobe = nprobes; 416600Sbill for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){ 417600Sbill for (hp = &(hdallop->h_htab[initialprobe]), 418600Sbill nprobes = 1, 419600Sbill hp_ub = &(hdallop->h_htab[NHASH]); 420600Sbill (*hp) && (nprobes < NHASH); 421600Sbill hp += nprobes, 422600Sbill hp -= (hp >= hp_ub) ? NHASH:0, 423600Sbill nprobes += 2) 424600Sbill { 425600Sbill from = yytext; 426*13514Srrh to = FETCHNAME(*hp); 427600Sbill #ifndef FLEXNAMES 42813460Srrh for (len = 0; (len<NCPName) && *from; len++) 429600Sbill if (*from++ != *to++) 430600Sbill goto nextprobe; 43113460Srrh if (len >= NCPName) /*both are maximal length*/ 432600Sbill return(hp); 433600Sbill if (*to == 0) /*assert *from == 0*/ 434600Sbill return(hp); 435600Sbill #else FLEXNAMES 436600Sbill while (*from && *to) 437600Sbill if (*from++ != *to++) 438600Sbill goto nextprobe; 439600Sbill if (*to == *from) /*assert both are == 0*/ 440600Sbill return(hp); 441600Sbill #endif FLEXNAMES 442600Sbill 443600Sbill nextprobe: ; 444600Sbill } 445600Sbill if (*hp == 0 && emptyslot == 0 && 446600Sbill hdallop->h_nused < HASHCLOGGED) { 447600Sbill emptyslot = hp; 448600Sbill emptyhd = hdallop; 449600Sbill } 450600Sbill } 451600Sbill if (emptyslot == 0) { 452600Sbill htaballoc(); 453600Sbill hdallop = htab->h_next; /* aren't we smart! */ 454600Sbill hp = &hdallop->h_htab[initialprobe]; 455600Sbill } else { 456600Sbill hdallop = emptyhd; 457600Sbill hp = emptyslot; 458600Sbill } 459600Sbill if (instflg) { 460600Sbill *hp = symalloc(); 461600Sbill hdallop->h_nused++; 462600Sbill #ifndef FLEXNAMES 463*13514Srrh strncpy(FETCHNAME(*hp), yytext, NCPName); 464600Sbill #else FLEXNAMES 46513447Srrh for (from = yytext, len = 0; *from++; len++) 466600Sbill continue; 46713447Srrh /* 468*13514Srrh * save string and trailing null, both 469*13514Srrh * internally, and in the string temporary file 47013447Srrh */ 471*13514Srrh strdp.sd_stroff = strfilepos; 472*13514Srrh strdp.sd_place = STR_BOTH; 473*13514Srrh strdp.sd_strlen = len + 1; /* length and null */ 474*13514Srrh fputs(yytext, strfile); /* string */ 475*13514Srrh putc(0, strfile); /* null */ 476*13514Srrh strfilepos += strdp.sd_strlen; 477*13514Srrh (*hp)->s_name = (char *)savestr(yytext, &strdp); 478600Sbill #endif FLEXNAMES 479600Sbill } 480600Sbill return(hp); 481600Sbill } /*end of lookup*/ 48213447Srrh /* 483*13514Srrh * save a string str, descriptor strdp, in the string pool 48413447Srrh */ 485*13514Srrh struct strdesc *savestr(str, strdp) 48613447Srrh char *str; 487*13514Srrh struct strdesc *strdp; 488600Sbill { 489*13514Srrh reg struct strdesc *res; 490*13514Srrh int tlen; 491600Sbill 492*13514Srrh tlen = sizeof(struct strdesc) - sizeof(res->sd_string); 493*13514Srrh if (strdp->sd_place & STR_FILE) 494*13514Srrh tlen += strdp->sd_strlen; 495*13514Srrh 496*13514Srrh if (tlen >= (STRPOOLDALLOP - strplhead->str_nalloc)) 497600Sbill strpoolalloc(); 498*13514Srrh res = (struct strdesc *)(strplhead->str_names + strplhead->str_nalloc); 499*13514Srrh res[0] = *strdp; 500*13514Srrh if (strdp->sd_place & STR_FILE) 501*13514Srrh movestr(res[0].sd_string, str, strdp->sd_strlen); 502*13514Srrh strplhead->str_nalloc += tlen; 50313447Srrh return(res); 504600Sbill } 505600Sbill 506600Sbill /* 507600Sbill * The relocation information is saved internally in an array of 508600Sbill * lists of relocation buffers. The relocation buffers are 509600Sbill * exactly the same size as a token buffer; if we use VM for the 510600Sbill * temporary file we reclaim this storage, otherwise we create 511600Sbill * them by mallocing. 512600Sbill */ 513600Sbill #define RELBUFLG TOKBUFLG 514600Sbill #define NRELOC ((TOKBUFLG - \ 515600Sbill (sizeof (int) + sizeof (struct relbufdesc *)) \ 516600Sbill ) / (sizeof (struct relocation_info))) 517600Sbill 518600Sbill struct relbufdesc{ 519600Sbill int rel_count; 520600Sbill struct relbufdesc *rel_next; 521600Sbill struct relocation_info rel_reloc[NRELOC]; 522600Sbill }; 523600Sbill extern struct relbufdesc *tok_free; 524600Sbill #define rel_free tok_free 525600Sbill static struct relbufdesc *rel_temp; 526634Shenry struct relocation_info r_can_1PC; 527634Shenry struct relocation_info r_can_0PC; 528600Sbill 529600Sbill initoutrel() 530600Sbill { 531634Shenry r_can_0PC.r_address = 0; 532634Shenry r_can_0PC.r_symbolnum = 0; 533634Shenry r_can_0PC.r_pcrel = 0; 534634Shenry r_can_0PC.r_length = 0; 535634Shenry r_can_0PC.r_extern = 0; 536634Shenry 537634Shenry r_can_1PC = r_can_0PC; 538600Sbill r_can_1PC.r_pcrel = 1; 539600Sbill } 540600Sbill 541675Shenry outrel(xp, reloc_how) 542675Shenry register struct exp *xp; 5435828Srrh int reloc_how; /* TYPB..TYPH + (possibly)RELOC_PCREL */ 544600Sbill { 545675Shenry struct relocation_info reloc; 546675Shenry register int x_type_mask; 54713447Srrh int pcrel; 548600Sbill 549675Shenry x_type_mask = xp->e_xtype & ~XFORW; 550675Shenry pcrel = reloc_how & RELOC_PCREL; 551675Shenry reloc_how &= ~RELOC_PCREL; 552675Shenry 553600Sbill if (bitoff&07) 554600Sbill yyerror("Padding error"); 555675Shenry if (x_type_mask == XUNDEF) 556600Sbill yyerror("Undefined reference"); 557600Sbill 558675Shenry if ( (x_type_mask != XABS) || pcrel ) { 559675Shenry if (ty_NORELOC[reloc_how]) 5605828Srrh yyerror("Illegal Relocation of floating or large int number."); 561675Shenry reloc = pcrel ? r_can_1PC : r_can_0PC; 562634Shenry reloc.r_address = dotp->e_xvalue - 563640Sbill ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase ); 564675Shenry reloc.r_length = ty_nlg[reloc_how]; 565675Shenry switch(x_type_mask){ 566600Sbill case XXTRN | XUNDEF: 567675Shenry reloc.r_symbolnum = xp->e_xname->s_index; 568600Sbill reloc.r_extern = 1; 569600Sbill break; 570600Sbill default: 571675Shenry if (readonlydata && (x_type_mask&~XXTRN) == XDATA) 572675Shenry x_type_mask = XTEXT | (x_type_mask&XXTRN); 573675Shenry reloc.r_symbolnum = x_type_mask; 574600Sbill break; 575600Sbill } 576600Sbill if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){ 577600Sbill if (rel_free){ 578600Sbill rel_temp = rel_free; 579600Sbill rel_free = rel_temp->rel_next; 580600Sbill } else { 581600Sbill rel_temp = (struct relbufdesc *) 582600Sbill Calloc(1,sizeof (struct relbufdesc)); 583600Sbill } 584600Sbill rel_temp->rel_count = 0; 585600Sbill rel_temp->rel_next = relfil; 586600Sbill relfil = rusefile[dotp - &usedot[0]] = rel_temp; 587600Sbill } 588600Sbill relfil->rel_reloc[relfil->rel_count++] = reloc; 589600Sbill } 590600Sbill /* 591600Sbill * write the unrelocated value to the text file 592600Sbill */ 593675Shenry dotp->e_xvalue += ty_nbyte[reloc_how]; 594675Shenry if (pcrel) 595675Shenry xp->e_xvalue -= dotp->e_xvalue; 5965828Srrh switch(reloc_how){ 5975828Srrh case TYPO: 5985828Srrh case TYPQ: 5995828Srrh 6005828Srrh case TYPF: 6015828Srrh case TYPD: 6025828Srrh case TYPG: 6035828Srrh case TYPH: 6045828Srrh bignumwrite(xp->e_number, reloc_how); 6055828Srrh break; 6065828Srrh 6075828Srrh default: 6085828Srrh bwrite((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil); 6095828Srrh break; 6105828Srrh } 611600Sbill } 612600Sbill /* 613600Sbill * Flush out all of the relocation information. 614600Sbill * Note that the individual lists of buffers are in 615600Sbill * reverse order, so we must reverse them 616600Sbill */ 617600Sbill off_t closeoutrel(relocfile) 618600Sbill BFILE *relocfile; 619600Sbill { 620600Sbill int locindex; 621600Sbill u_long Closeoutrel(); 622600Sbill 623600Sbill trsize = 0; 624600Sbill for (locindex = 0; locindex < NLOC; locindex++){ 625600Sbill trsize += Closeoutrel(rusefile[locindex], relocfile); 626600Sbill } 627600Sbill drsize = 0; 628600Sbill for (locindex = 0; locindex < NLOC; locindex++){ 629600Sbill drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile); 630600Sbill } 631600Sbill return(trsize + drsize); 632600Sbill } 633600Sbill 634600Sbill u_long Closeoutrel(relfil, relocfile) 635600Sbill struct relbufdesc *relfil; 636600Sbill BFILE *relocfile; 637600Sbill { 638600Sbill u_long tail; 639600Sbill if (relfil == 0) 640600Sbill return(0L); 641600Sbill tail = Closeoutrel(relfil->rel_next, relocfile); 642600Sbill bwrite((char *)&relfil->rel_reloc[0], 643600Sbill relfil->rel_count * sizeof (struct relocation_info), 644600Sbill relocfile); 645600Sbill return(tail + relfil->rel_count * sizeof (struct relocation_info)); 646600Sbill } 647600Sbill 648634Shenry #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels)) 649600Sbill int sizesymtab() 650600Sbill { 651634Shenry return (sizeof (struct nlist) * NOUTSYMS); 652600Sbill } 653600Sbill 654600Sbill #ifdef FLEXNAMES 655600Sbill /* 656600Sbill * We write out the flexible length character strings for names 657600Sbill * in two stages. 65813447Srrh * 1) We always! maintain a fixed sized name list entry; 659600Sbill * the string is indexed by a four byte quantity from the beginning 660600Sbill * of the string pool area. Index 0 is reserved, and indicates 661600Sbill * that there is no associated string. The first valid index is 4. 662600Sbill * 2) We concatenate together and write all of the strings 663600Sbill * in the string pool at the end of the name list. The first 664600Sbill * four bytes in the string pool are indexed only by 0 (see above); 665600Sbill * they contain the total number of bytes in the string pool. 666600Sbill */ 667600Sbill #endif FLEXNAMES 668600Sbill 669600Sbill /* 670600Sbill * Write out n symbols to file f, beginning at p 671600Sbill * ignoring symbols that are obsolete, jxxx instructions, and 672600Sbill * possibly, labels 673600Sbill */ 674600Sbill 675600Sbill int symwrite(symfile) 676600Sbill BFILE *symfile; 677600Sbill { 678*13514Srrh int symsout; /*those actually written*/ 679*13514Srrh int symsdesired = NOUTSYMS; 680*13514Srrh reg struct symtab *sp, *ub; 681600Sbill #ifdef FLEXNAMES 682*13514Srrh char *name; /* temp to save the name */ 683*13514Srrh int nread; 684*13514Srrh char rbuf[2048]; 685*13514Srrh int i; 686634Shenry /* 687634Shenry * We use sp->s_index to hold the length of the 688634Shenry * name; it isn't used for anything else 689634Shenry */ 690600Sbill #endif FLEXNAMES 691600Sbill 692600Sbill register struct allocbox *allocwalk; 693600Sbill 694600Sbill symsout = 0; 695600Sbill DECLITERATE(allocwalk, sp, ub) 696600Sbill { 697634Shenry if (sp->s_tag >= IGNOREBOUND) 698600Sbill continue; 699*13514Srrh if ((FETCHNAME(sp)[0] == 'L') && (sp->s_tag == LABELID) && !savelabels) 700600Sbill continue; 701600Sbill symsout++; 702634Shenry 703634Shenry #ifdef FLEXNAMES 704634Shenry name = sp->s_name; /* save pointer */ 70513447Srrh /* 70613447Srrh * the length of the symbol table string 70713447Srrh * always includes the trailing null 70813447Srrh */ 709*13514Srrh if (sp->s_name && (sp->s_index = STRLEN(sp))){ 710*13514Srrh sp->s_nmx = STROFF(sp); /* clobber */ 711634Shenry } else { 71213447Srrh sp->s_nmx = 0; 713634Shenry } 714*13514Srrh #ifdef DEBUG 715*13514Srrh printf("symbol %d: nmx == %d\n", symsout, sp->s_nmx); 716*13514Srrh #endif DEBUG 717*13514Srrh #endif FLEXNAMES 718634Shenry sp->s_type = (sp->s_ptype != 0) ? sp->s_ptype : (sp->s_type & (~XFORW)); 719640Sbill if (readonlydata && (sp->s_type&~N_EXT) == N_DATA) 720640Sbill sp->s_type = N_TEXT | (sp->s_type & N_EXT); 7215828Srrh bwrite((char *)&sp->s_nm, sizeof (struct nlist), symfile); 722634Shenry #ifdef FLEXNAMES 723634Shenry sp->s_name = name; /* restore pointer */ 724600Sbill #endif FLEXNAMES 725600Sbill } 726600Sbill if (symsout != symsdesired) 727600Sbill yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n", 728600Sbill symsout, symsdesired); 729600Sbill #ifdef FLEXNAMES 730600Sbill /* 731*13514Srrh * Copy the string temporary file to the symbol file, 732*13514Srrh * copying all the strings and symbols we ever saw, 733*13514Srrh * including labels, stabs strings, ascii strings, etc. 734*13514Srrh * This is slightly wasteful. 735600Sbill */ 736*13514Srrh i = 0; 737*13514Srrh while((nread = read(strfile->_file, rbuf, sizeof(rbuf))) > 0){ 738*13514Srrh if (i == 0){ 739*13514Srrh #ifdef DEBUG 740*13514Srrh printf("%d bytes of strings\n", strfilepos); 741*13514Srrh #endif DEBUG 742*13514Srrh ((int *)rbuf)[0] = strfilepos; 74313447Srrh } 744*13514Srrh bwrite(rbuf, nread, symfile); 745*13514Srrh i++; 746600Sbill } 747600Sbill #endif FLEXNAMES 748600Sbill } 749