15828Srrh /* 25828Srrh * Copyright (c) 1982 Regents of the University of California 35828Srrh */ 45828Srrh #ifndef lint 5*14450Srrh static char sccsid[] = "@(#)assyms.c 4.14 08/11/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 7213514Srrh for (ip = (Iptr)instab; FETCHNAME(ip)[0]; ip++) { 7313514Srrh 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 95*14450Srrh #define ISLABEL(sp) \ 96*14450Srrh ( (!savelabels) \ 97*14450Srrh && (sp->s_tag == LABELID) \ 98*14450Srrh && (STRPLACE(sp) & STR_CORE) \ 99*14450Srrh && (FETCHNAME(sp)[0] == 'L')) 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: 136*14450Srrh if (!ISLABEL(sp)) 137*14450Srrh sp->s_index = relpos++; 138600Sbill } 139600Sbill } 140600Sbill 141600Sbill /* 142600Sbill * For all of the stabs that had their final value undefined during pass 1 143600Sbill * and during pass 2 assign a final value. 144600Sbill * We have already given stab entrys a initial approximation 145600Sbill * when we constsructed the sorted symbol table. 146600Sbill * Iteration order doesn't matter. 147600Sbill */ 14812592Scsvaf 14912592Scsvaf stabfix() 15012592Scsvaf { 151600Sbill register struct symtab *sp, **cosp; 152600Sbill register struct symtab *p; 153600Sbill 154600Sbill SYMITERATE(cosp, sp){ 155634Shenry if(sp->s_ptype && (sp->s_type & STABFLAG)) { 156634Shenry p = sp->s_dest; 15712592Scsvaf /* 15812592Scsvaf * STABFLOATING indicates that the offset has been saved in s_desc, s_other 15912592Scsvaf */ 16012592Scsvaf if(sp->s_tag == STABFLOATING) { 16112592Scsvaf sp->s_value = ( ( ((unsigned char) sp->s_other) << 16) | ( (unsigned short) sp->s_desc ) ); 16212592Scsvaf sp->s_value = sp->s_value + p->s_value; 16312592Scsvaf } 16412592Scsvaf else sp->s_value = p->s_value; 165634Shenry sp->s_index = p->s_index; 166634Shenry sp->s_type = p->s_type; 16712592Scsvaf 16812592Scsvaf 169600Sbill } 170600Sbill } 171600Sbill } 172600Sbill 173600Sbill char *Calloc(number, size) 174600Sbill int number, size; 175600Sbill { 176600Sbill register char *newstuff; 1775828Srrh char *sbrk(); 1785828Srrh newstuff = sbrk(number*size); 179600Sbill if ((int)newstuff == -1){ 180600Sbill yyerror("Ran out of Memory"); 181600Sbill delexit(); 182600Sbill } 183600Sbill return(newstuff); 184600Sbill } 185600Sbill 186600Sbill char *ClearCalloc(number, size) 187600Sbill int number, size; 188600Sbill { 189600Sbill register char *newstuff; /* r11 */ 190600Sbill register int length = number * size; /* r10 */ 1915828Srrh #ifdef lint 1925828Srrh length = length; 1935828Srrh #endif length 194600Sbill newstuff = Calloc(number, size); 195600Sbill asm("movc5 $0, (r0), $0, r10, (r11)"); 196600Sbill return(newstuff); 197600Sbill } 198600Sbill 199600Sbill struct symtab *symalloc() 200600Sbill { 201600Sbill if (symsleft == 0){ 202600Sbill newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY); 203600Sbill symsleft = SYMDALLOP; 204600Sbill nextsym = &newbox->symslots[0]; 205600Sbill if (alloctail == 0){ 206600Sbill allochead = alloctail = newbox; 207600Sbill } else { 208600Sbill alloctail->nextalloc = newbox; 209600Sbill alloctail = newbox; 210600Sbill } 211600Sbill } 212600Sbill --symsleft; 213600Sbill ++nsyms; 214600Sbill return(nextsym++); 215600Sbill } 216600Sbill 217600Sbill strpoolalloc() 218600Sbill { 219600Sbill register struct strpool *new; 220600Sbill 221600Sbill new = (struct strpool *)Calloc(1, sizeof (struct strpool)); 222600Sbill new->str_nalloc = 0; 223600Sbill new->str_next = strplhead; 224600Sbill strplhead = new; 225600Sbill } 226600Sbill 227600Sbill symcmp(Pptr, Qptr) 228600Sbill struct symtab **Pptr, **Qptr; 229600Sbill { 230600Sbill register struct symtab *p = *Pptr; 231600Sbill register struct symtab *q = *Qptr; 232634Shenry if (p->s_index < q->s_index) 233600Sbill return(-1); 234634Shenry if (p->s_index > q->s_index) 235600Sbill return(1); 236634Shenry if (p->s_value < q->s_value) 237600Sbill return(-1); 238634Shenry if (p->s_value > q->s_value) 239600Sbill return(1); 240600Sbill /* 241600Sbill * Force jxxx entries to virtually preceed labels defined 242600Sbill * to follow the jxxxx instruction, so that bumping the 243600Sbill * jxxx instruction correctly fixes up the following labels 244600Sbill */ 245634Shenry if (p->s_tag >= IGNOREBOUND) /*p points to a jxxx*/ 246600Sbill return(-1); 247634Shenry if (q->s_tag >= IGNOREBOUND) 248600Sbill return(1); 249600Sbill /* 250600Sbill * both are now just plain labels; the relative order doesn't 251600Sbill * matter. Both can't be jxxxes, as they would have different 252600Sbill * values. 253600Sbill */ 254600Sbill return(0); 255600Sbill } /*end of symcmp*/ 256600Sbill 257600Sbill /* 258600Sbill * We construct the auxiliary table of pointers, symptrs and 259600Sbill * symdelim 260600Sbill * We also assign preliminary values to stab entries that did not yet 261600Sbill * have an absolute value (because they initially referred to 262600Sbill * forward references). We don't worry about .stabds, as they 263600Sbill * already have an estimated final value 264600Sbill */ 265600Sbill 266600Sbill sortsymtab() 267600Sbill { 268600Sbill register struct symtab *sp; 269600Sbill register struct symtab **cowalk; 270600Sbill register struct allocbox *allocwalk; 271600Sbill struct symtab *ubsp; 272600Sbill int segno; 273600Sbill int slotno; 274600Sbill int symsin; /*number put into symptrs*/ 275600Sbill 276600Sbill symptrs = (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs); 277600Sbill /* 278600Sbill * Allocate one word at the beginning of the symptr array 279600Sbill * so that backwards scans through the symptr array will 280600Sbill * work correctly while scanning through the zeroth segment 281600Sbill */ 282600Sbill *symptrs++ = 0; 283600Sbill cowalk = symptrs; 284600Sbill symsin = 0; 285600Sbill DECLITERATE(allocwalk, sp, ubsp) { 286634Shenry if (sp->s_ptype && (sp->s_type &STABFLAG)){ 287634Shenry sp->s_value = sp->s_dest->s_value; 288634Shenry sp->s_index = sp->s_dest->s_index; 289600Sbill } 290600Sbill if (symsin >= nsyms) 291600Sbill yyerror("INTERNAL ERROR: overfilled symbol table indirection table"); 292600Sbill *cowalk++ = sp; 293600Sbill symsin++; 294600Sbill } 295600Sbill if (symsin != nsyms) 296600Sbill yyerror("INTERNAL ERROR: installed %d syms, should have installed %d", 297600Sbill symsin, nsyms); 298600Sbill symptrub = &symptrs[nsyms ]; 299600Sbill qsort(symptrs, nsyms, sizeof *symptrs, symcmp); 300600Sbill symdelim[0] = symptrs; 301600Sbill for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1; 302600Sbill segno < NLOC + NLOC; 303600Sbill segno++, slotno++){ 304634Shenry for (; sp && sp->s_index == segno; sp = *++cowalk); 305600Sbill symdelim[slotno] = cowalk; /*forms the ub delimeter*/ 306600Sbill } 307600Sbill } /*end of sortsymtab*/ 308600Sbill 309600Sbill #ifdef DEBUG 310600Sbill dumpsymtab() 311600Sbill { 312600Sbill register int segno; 313600Sbill register struct symtab *sp, **cosp, *ub; 314600Sbill char *tagstring(); 315600Sbill 316600Sbill printf("Symbol Table dump:\n"); 317600Sbill for (segno = 0; segno < NLOC + NLOC; segno++){ 318600Sbill printf("Segment number: %d\n", segno); 319600Sbill SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){ 320600Sbill printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n", 32113514Srrh segno, FETCHNAME(sp), 322634Shenry sp->s_value, sp->s_index, 323634Shenry tagstring(sp->s_tag)); 324600Sbill printf("\t\ttype: %d jxbump %d jxfear: %d\n", 325634Shenry sp->s_type, sp->s_jxbump, sp->s_jxfear); 326600Sbill } 327600Sbill printf("\n\n"); 328600Sbill } 329600Sbill } 330600Sbill 331600Sbill static char tagbuff[4]; 332600Sbill 333600Sbill char *tagstring(tag) 334600Sbill unsigned char tag; 335600Sbill { 336600Sbill switch(tag){ 337600Sbill case JXACTIVE: return("active"); 338600Sbill case JXNOTYET: return("notyet"); 339600Sbill case JXALIGN: return("align"); 340600Sbill case JXQUESTIONABLE: return("jxquestionable"); 341600Sbill case JXINACTIVE: return("inactive"); 342600Sbill case JXTUNNEL: return("tunnel"); 343600Sbill case OBSOLETE: return("obsolete"); 344600Sbill case IGNOREBOUND: return("ignorebound"); 345600Sbill case STABFLOATING: return("stabfloating"); 346600Sbill case STABFIXED: return("stabfixed"); 347600Sbill case LABELID: return("labelid"); 348600Sbill case OKTOBUMP: return("oktobump"); 349600Sbill case ISET: return("iset"); 350600Sbill case ILSYM: return("ilsym"); 351600Sbill default: sprintf(tagbuff,"%d", tag); 352600Sbill return(tagbuff); 353600Sbill } 354600Sbill } 355600Sbill #endif DEBUG 356600Sbill 357600Sbill htaballoc() 358600Sbill { 359600Sbill register struct hashdallop *new; 360600Sbill new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop)); 361600Sbill if (htab == 0) 362600Sbill htab = new; 363600Sbill else { /* add AFTER the 1st slot */ 364600Sbill new->h_next = htab->h_next; 365600Sbill htab->h_next = new; 366600Sbill } 367600Sbill } 368600Sbill 369600Sbill #define HASHCLOGGED (NHASH / 2) 370600Sbill 371600Sbill /* 372600Sbill * Lookup a symbol stored in extern yytext. 373600Sbill * All strings passed in via extern yytext had better have 374600Sbill * a trailing null. Strings are placed in yytext for hashing by 375600Sbill * syminstall() and by yylex(); 376600Sbill * 377600Sbill * We take pains to avoid function calls; this functdion 378600Sbill * is called quite frequently, and the calls overhead 379600Sbill * in the vax contributes significantly to the overall 380600Sbill * execution speed of as. 381600Sbill */ 382600Sbill struct symtab **lookup(instflg) 383600Sbill int instflg; /* 0: don't install */ 384600Sbill { 385600Sbill static int initialprobe; 386600Sbill register struct symtab **hp; 387600Sbill register char *from; 388600Sbill register char *to; 389600Sbill register int len; 390600Sbill register int nprobes; 39113514Srrh static struct hashdallop *hdallop; 39213514Srrh static struct symtab **emptyslot; 39313514Srrh static struct hashdallop *emptyhd; 39413514Srrh static struct symtab **hp_ub; 395600Sbill 396600Sbill emptyslot = 0; 397600Sbill for (nprobes = 0, from = yytext; 398600Sbill *from; 399600Sbill nprobes <<= 2, nprobes += *from++) 400600Sbill continue; 401600Sbill nprobes += from[-1] << 5; 402600Sbill nprobes %= NHASH; 403600Sbill if (nprobes < 0) 404600Sbill nprobes += NHASH; 405600Sbill 406600Sbill initialprobe = nprobes; 407600Sbill for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){ 408600Sbill for (hp = &(hdallop->h_htab[initialprobe]), 409600Sbill nprobes = 1, 410600Sbill hp_ub = &(hdallop->h_htab[NHASH]); 411600Sbill (*hp) && (nprobes < NHASH); 412600Sbill hp += nprobes, 413600Sbill hp -= (hp >= hp_ub) ? NHASH:0, 414600Sbill nprobes += 2) 415600Sbill { 416600Sbill from = yytext; 41713514Srrh to = FETCHNAME(*hp); 418600Sbill while (*from && *to) 419600Sbill if (*from++ != *to++) 420600Sbill goto nextprobe; 421600Sbill if (*to == *from) /*assert both are == 0*/ 422600Sbill return(hp); 42313522Srrh nextprobe: ; 424600Sbill } 425600Sbill if (*hp == 0 && emptyslot == 0 && 426600Sbill hdallop->h_nused < HASHCLOGGED) { 427600Sbill emptyslot = hp; 428600Sbill emptyhd = hdallop; 429600Sbill } 430600Sbill } 431600Sbill if (emptyslot == 0) { 432600Sbill htaballoc(); 433600Sbill hdallop = htab->h_next; /* aren't we smart! */ 434600Sbill hp = &hdallop->h_htab[initialprobe]; 435600Sbill } else { 436600Sbill hdallop = emptyhd; 437600Sbill hp = emptyslot; 438600Sbill } 439600Sbill if (instflg) { 440600Sbill *hp = symalloc(); 441600Sbill hdallop->h_nused++; 44213447Srrh for (from = yytext, len = 0; *from++; len++) 443600Sbill continue; 44413572Srrh (*hp)->s_name = (char *)savestr(yytext, len + 1, STR_BOTH); 445600Sbill } 446600Sbill return(hp); 447600Sbill } /*end of lookup*/ 44813447Srrh /* 44913572Srrh * save a string str with len in the places indicated by place 45013447Srrh */ 45113572Srrh struct strdesc *savestr(str, len, place) 45213447Srrh char *str; 45313572Srrh int len; 45413572Srrh int place; 455600Sbill { 45613514Srrh reg struct strdesc *res; 45713514Srrh int tlen; 45813572Srrh /* 45913572Srrh * Compute the total length of the record to live in core 46013572Srrh */ 46113514Srrh tlen = sizeof(struct strdesc) - sizeof(res->sd_string); 46213572Srrh if (place & STR_CORE) 46313572Srrh tlen += len; 46413572Srrh /* 46513572Srrh * See if there is enough space for the record, 46613572Srrh * and allocate the record. 46713572Srrh */ 46813514Srrh if (tlen >= (STRPOOLDALLOP - strplhead->str_nalloc)) 469600Sbill strpoolalloc(); 47013514Srrh res = (struct strdesc *)(strplhead->str_names + strplhead->str_nalloc); 47113572Srrh /* 47213572Srrh * Save the string information that is always present 47313572Srrh */ 47413572Srrh res->sd_stroff = strfilepos; 47513572Srrh res->sd_strlen = len; 47613572Srrh res->sd_place = place; 47713572Srrh /* 47813572Srrh * Now, save the string itself. If str is null, then 47913572Srrh * the characters have already been dumped to the file 48013572Srrh */ 48113572Srrh if ((place & STR_CORE) && str) 48213572Srrh movestr(res[0].sd_string, str, len); 48313572Srrh if (place & STR_FILE){ 48413572Srrh if (str){ 48513572Srrh fwrite(str, 1, len, strfile); 48613572Srrh } 48713572Srrh strfilepos += len; 48813572Srrh } 48913572Srrh /* 49013572Srrh * Adjust the in core string pool size 49113572Srrh */ 49213514Srrh strplhead->str_nalloc += tlen; 49313447Srrh return(res); 494600Sbill } 495600Sbill /* 496600Sbill * The relocation information is saved internally in an array of 497600Sbill * lists of relocation buffers. The relocation buffers are 498600Sbill * exactly the same size as a token buffer; if we use VM for the 499600Sbill * temporary file we reclaim this storage, otherwise we create 500600Sbill * them by mallocing. 501600Sbill */ 502600Sbill #define RELBUFLG TOKBUFLG 503600Sbill #define NRELOC ((TOKBUFLG - \ 504600Sbill (sizeof (int) + sizeof (struct relbufdesc *)) \ 505600Sbill ) / (sizeof (struct relocation_info))) 506600Sbill 507600Sbill struct relbufdesc{ 508600Sbill int rel_count; 509600Sbill struct relbufdesc *rel_next; 510600Sbill struct relocation_info rel_reloc[NRELOC]; 511600Sbill }; 512600Sbill extern struct relbufdesc *tok_free; 513600Sbill #define rel_free tok_free 514600Sbill static struct relbufdesc *rel_temp; 515634Shenry struct relocation_info r_can_1PC; 516634Shenry struct relocation_info r_can_0PC; 517600Sbill 518600Sbill initoutrel() 519600Sbill { 520634Shenry r_can_0PC.r_address = 0; 521634Shenry r_can_0PC.r_symbolnum = 0; 522634Shenry r_can_0PC.r_pcrel = 0; 523634Shenry r_can_0PC.r_length = 0; 524634Shenry r_can_0PC.r_extern = 0; 525634Shenry 526634Shenry r_can_1PC = r_can_0PC; 527600Sbill r_can_1PC.r_pcrel = 1; 528600Sbill } 529600Sbill 530675Shenry outrel(xp, reloc_how) 531675Shenry register struct exp *xp; 5325828Srrh int reloc_how; /* TYPB..TYPH + (possibly)RELOC_PCREL */ 533600Sbill { 534675Shenry struct relocation_info reloc; 535675Shenry register int x_type_mask; 53613447Srrh int pcrel; 537600Sbill 538675Shenry x_type_mask = xp->e_xtype & ~XFORW; 539675Shenry pcrel = reloc_how & RELOC_PCREL; 540675Shenry reloc_how &= ~RELOC_PCREL; 541675Shenry 542600Sbill if (bitoff&07) 543600Sbill yyerror("Padding error"); 544675Shenry if (x_type_mask == XUNDEF) 545600Sbill yyerror("Undefined reference"); 546600Sbill 547675Shenry if ( (x_type_mask != XABS) || pcrel ) { 548675Shenry if (ty_NORELOC[reloc_how]) 5495828Srrh yyerror("Illegal Relocation of floating or large int number."); 550675Shenry reloc = pcrel ? r_can_1PC : r_can_0PC; 551634Shenry reloc.r_address = dotp->e_xvalue - 552640Sbill ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase ); 553675Shenry reloc.r_length = ty_nlg[reloc_how]; 554675Shenry switch(x_type_mask){ 555600Sbill case XXTRN | XUNDEF: 556675Shenry reloc.r_symbolnum = xp->e_xname->s_index; 557600Sbill reloc.r_extern = 1; 558600Sbill break; 559600Sbill default: 560675Shenry if (readonlydata && (x_type_mask&~XXTRN) == XDATA) 561675Shenry x_type_mask = XTEXT | (x_type_mask&XXTRN); 562675Shenry reloc.r_symbolnum = x_type_mask; 563600Sbill break; 564600Sbill } 565600Sbill if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){ 566600Sbill if (rel_free){ 567600Sbill rel_temp = rel_free; 568600Sbill rel_free = rel_temp->rel_next; 569600Sbill } else { 570600Sbill rel_temp = (struct relbufdesc *) 571600Sbill Calloc(1,sizeof (struct relbufdesc)); 572600Sbill } 573600Sbill rel_temp->rel_count = 0; 574600Sbill rel_temp->rel_next = relfil; 575600Sbill relfil = rusefile[dotp - &usedot[0]] = rel_temp; 576600Sbill } 577600Sbill relfil->rel_reloc[relfil->rel_count++] = reloc; 578600Sbill } 579600Sbill /* 580600Sbill * write the unrelocated value to the text file 581600Sbill */ 582675Shenry dotp->e_xvalue += ty_nbyte[reloc_how]; 583675Shenry if (pcrel) 584675Shenry xp->e_xvalue -= dotp->e_xvalue; 5855828Srrh switch(reloc_how){ 5865828Srrh case TYPO: 5875828Srrh case TYPQ: 5885828Srrh 5895828Srrh case TYPF: 5905828Srrh case TYPD: 5915828Srrh case TYPG: 5925828Srrh case TYPH: 5935828Srrh bignumwrite(xp->e_number, reloc_how); 5945828Srrh break; 5955828Srrh 5965828Srrh default: 5975828Srrh bwrite((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil); 5985828Srrh break; 5995828Srrh } 600600Sbill } 601600Sbill /* 602600Sbill * Flush out all of the relocation information. 603600Sbill * Note that the individual lists of buffers are in 604600Sbill * reverse order, so we must reverse them 605600Sbill */ 606600Sbill off_t closeoutrel(relocfile) 607600Sbill BFILE *relocfile; 608600Sbill { 609600Sbill int locindex; 610600Sbill u_long Closeoutrel(); 611600Sbill 612600Sbill trsize = 0; 613600Sbill for (locindex = 0; locindex < NLOC; locindex++){ 614600Sbill trsize += Closeoutrel(rusefile[locindex], relocfile); 615600Sbill } 616600Sbill drsize = 0; 617600Sbill for (locindex = 0; locindex < NLOC; locindex++){ 618600Sbill drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile); 619600Sbill } 620600Sbill return(trsize + drsize); 621600Sbill } 622600Sbill 623600Sbill u_long Closeoutrel(relfil, relocfile) 624600Sbill struct relbufdesc *relfil; 625600Sbill BFILE *relocfile; 626600Sbill { 627600Sbill u_long tail; 628600Sbill if (relfil == 0) 629600Sbill return(0L); 630600Sbill tail = Closeoutrel(relfil->rel_next, relocfile); 631600Sbill bwrite((char *)&relfil->rel_reloc[0], 632600Sbill relfil->rel_count * sizeof (struct relocation_info), 633600Sbill relocfile); 634600Sbill return(tail + relfil->rel_count * sizeof (struct relocation_info)); 635600Sbill } 636600Sbill 637634Shenry #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels)) 638600Sbill int sizesymtab() 639600Sbill { 640634Shenry return (sizeof (struct nlist) * NOUTSYMS); 641600Sbill } 642600Sbill /* 643600Sbill * Write out n symbols to file f, beginning at p 644600Sbill * ignoring symbols that are obsolete, jxxx instructions, and 645600Sbill * possibly, labels 646600Sbill */ 647600Sbill int symwrite(symfile) 648600Sbill BFILE *symfile; 649600Sbill { 65013514Srrh int symsout; /*those actually written*/ 65113514Srrh int symsdesired = NOUTSYMS; 65213514Srrh reg struct symtab *sp, *ub; 65313514Srrh char *name; /* temp to save the name */ 654*14450Srrh int totalstr; 655634Shenry /* 656634Shenry * We use sp->s_index to hold the length of the 657634Shenry * name; it isn't used for anything else 658634Shenry */ 659600Sbill register struct allocbox *allocwalk; 660600Sbill 661600Sbill symsout = 0; 662*14450Srrh totalstr = sizeof(totalstr); 663*14450Srrh DECLITERATE(allocwalk, sp, ub) { 664634Shenry if (sp->s_tag >= IGNOREBOUND) 665600Sbill continue; 666*14450Srrh if (ISLABEL(sp)) 667600Sbill continue; 668600Sbill symsout++; 669634Shenry name = sp->s_name; /* save pointer */ 67013447Srrh /* 67113447Srrh * the length of the symbol table string 672*14450Srrh * always includes the trailing null; 673*14450Srrh * blast the pointer to its a.out value. 67413447Srrh */ 67513514Srrh if (sp->s_name && (sp->s_index = STRLEN(sp))){ 676*14450Srrh sp->s_nmx = totalstr; 677*14450Srrh totalstr += sp->s_index; 678634Shenry } else { 67913447Srrh sp->s_nmx = 0; 680634Shenry } 681*14450Srrh if (sp->s_ptype != 0) 682*14450Srrh sp->s_type = sp->s_ptype; 683*14450Srrh else 684*14450Srrh sp->s_type = (sp->s_type & (~XFORW)); 685640Sbill if (readonlydata && (sp->s_type&~N_EXT) == N_DATA) 686640Sbill sp->s_type = N_TEXT | (sp->s_type & N_EXT); 6875828Srrh bwrite((char *)&sp->s_nm, sizeof (struct nlist), symfile); 688634Shenry sp->s_name = name; /* restore pointer */ 689600Sbill } 690600Sbill if (symsout != symsdesired) 691600Sbill yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n", 692600Sbill symsout, symsdesired); 693600Sbill /* 694*14450Srrh * Construct the string pool from the symbols that were written, 695*14450Srrh * possibly fetching from the string file if the string 696*14450Srrh * is not core resident. 697600Sbill */ 698*14450Srrh bwrite(&totalstr, sizeof(totalstr), symfile); 699*14450Srrh symsout = 0; 700*14450Srrh DECLITERATE(allocwalk, sp, ub) { 701*14450Srrh if (sp->s_tag >= IGNOREBOUND) 702*14450Srrh continue; 703*14450Srrh if (ISLABEL(sp)) 704*14450Srrh continue; 705*14450Srrh symsout++; 706*14450Srrh if (STRLEN(sp) > 0){ 707*14450Srrh if (STRPLACE(sp) & STR_CORE){ 708*14450Srrh bwrite(FETCHNAME(sp), STRLEN(sp), symfile); 709*14450Srrh } else if (STRPLACE(sp) & STR_FILE){ 710*14450Srrh char rbuf[2048]; 711*14450Srrh int left, nread; 712*14450Srrh fseek(strfile, STROFF(sp), 0); 713*14450Srrh for (left = STRLEN(sp); left > 0; left -= nread){ 714*14450Srrh nread = fread(rbuf, sizeof(char), 715*14450Srrh min(sizeof(rbuf), left), strfile); 716*14450Srrh if (nread == 0) 717*14450Srrh break; 718*14450Srrh bwrite(rbuf, nread, symfile); 719*14450Srrh } 720*14450Srrh } 72113447Srrh } 722600Sbill } 723*14450Srrh if (symsout != symsdesired) 724*14450Srrh yyerror("INTERNAL ERROR: Wrote %d strings, wanted %d\n", 725*14450Srrh symsout, symsdesired); 726600Sbill } 727