15828Srrh /* 2*19833Sdist * Copyright (c) 1982 Regents of the University of California. 3*19833Sdist * All rights reserved. The Berkeley software License Agreement 4*19833Sdist * specifies the terms and conditions for redistribution. 55828Srrh */ 6*19833Sdist 75828Srrh #ifndef lint 8*19833Sdist static char sccsid[] = "@(#)assyms.c 5.1 (Berkeley) 04/30/85"; 95828Srrh #endif not lint 105828Srrh 11600Sbill #include <stdio.h> 12600Sbill #include <ctype.h> 13600Sbill #include "as.h" 14600Sbill #include "asscan.h" 15600Sbill #include "assyms.h" 16600Sbill 17600Sbill /* 18600Sbill * Managers for chunks of symbols allocated from calloc() 19600Sbill * We maintain a linked list of such chunks. 20600Sbill * 21600Sbill */ 22600Sbill struct allocbox *allochead; /*head of chunk list*/ 23600Sbill struct allocbox *alloctail; /*tail*/ 24600Sbill struct allocbox *newbox; /*for creating a new chunk*/ 25600Sbill struct symtab *nextsym; /*next symbol free*/ 26600Sbill int symsleft; /*slots left in current chunk*/ 27600Sbill 28600Sbill struct symtab **symptrs; 29600Sbill struct symtab **symdelim[NLOC + NLOC +1]; 30600Sbill struct symtab **symptrub; 31600Sbill /* 32600Sbill * Managers for the dynamically extendable hash table 33600Sbill */ 34600Sbill struct hashdallop *htab; 35600Sbill 365828Srrh Iptr *itab[NINST]; /*maps opcodes to instructions*/ 37600Sbill /* 38600Sbill * Counts what went into the symbol table, so that the 39600Sbill * size of the symbol table can be computed. 40600Sbill */ 41600Sbill int nsyms; /* total number in the symbol table */ 42600Sbill int njxxx; /* number of jxxx entrys */ 43600Sbill int nforgotten; /* number of symbols erroneously entered */ 44600Sbill int nlabels; /* number of label entries */ 45600Sbill 46600Sbill /* 47600Sbill * Managers of the symbol literal storage. 48600Sbill */ 49600Sbill struct strpool *strplhead = 0; 50600Sbill 51600Sbill symtabinit() 52600Sbill { 53600Sbill allochead = 0; 54600Sbill alloctail = 0; 55600Sbill nextsym = 0; 56600Sbill symsleft = 0; 57600Sbill strpoolalloc(); /* get the first strpool storage area */ 58600Sbill htab = 0; 59600Sbill htaballoc(); /* get the first part of the hash table */ 60600Sbill } 61600Sbill 62600Sbill /* 63600Sbill * Install all known instructions in the symbol table 64600Sbill */ 65600Sbill syminstall() 66600Sbill { 675828Srrh register Iptr ip; 68600Sbill register struct symtab **hp; 69600Sbill register char *p1, *p2; 705828Srrh register int i; 71600Sbill 725828Srrh for (i = 0; i < NINST; i++) 735828Srrh itab[i] = (Iptr*)BADPOINT; 745828Srrh 7513514Srrh for (ip = (Iptr)instab; FETCHNAME(ip)[0]; ip++) { 7613514Srrh p1 = FETCHNAME(ip); 77600Sbill p2 = yytext; 78600Sbill while (*p2++ = *p1++); 79600Sbill hp = lookup(0); /* 0 => don't install this*/ 80600Sbill if (*hp==NULL) { 81600Sbill *hp = (struct symtab *)ip; 82634Shenry if ( (ip->s_tag!=INSTn) 83634Shenry && (ip->s_tag!=INST0) 84634Shenry && (ip->s_tag!=0)) 85600Sbill continue; /* was pseudo-op */ 865828Srrh if (itab[ip->i_eopcode] == (Iptr*)BADPOINT){ 875828Srrh itab[ip->i_eopcode] = 885828Srrh (Iptr*)ClearCalloc(256, sizeof(Iptr)); 895828Srrh for (i = 0; i < 256; i++) 905828Srrh itab[ip->i_eopcode][i] = 915828Srrh (Iptr)BADPOINT; 925828Srrh } 935828Srrh itab[ip->i_eopcode][ip->i_popcode] = ip; 94600Sbill } 95600Sbill } 96600Sbill } /*end of syminstall*/ 97600Sbill 9814450Srrh #define ISLABEL(sp) \ 9914450Srrh ( (!savelabels) \ 10014450Srrh && (sp->s_tag == LABELID) \ 10114450Srrh && (STRPLACE(sp) & STR_CORE) \ 10214450Srrh && (FETCHNAME(sp)[0] == 'L')) 103600Sbill /* 104600Sbill * Assign final values to symbols, 105600Sbill * and overwrite the index field with its relative position in 106600Sbill * the symbol table we give to the loader. 107600Sbill */ 108600Sbill extern struct exec hdr; 109600Sbill 110600Sbill freezesymtab() 111600Sbill { 112600Sbill register struct symtab *sp; 113600Sbill long bs; 114600Sbill register int relpos = 0; 115600Sbill register struct symtab *ubsp; 116600Sbill register struct allocbox *allocwalk; 117600Sbill 118600Sbill DECLITERATE(allocwalk, sp, ubsp) 119600Sbill { 120634Shenry if (sp->s_tag >= IGNOREBOUND) 121600Sbill continue; /*totally ignore jxxx entries */ 122600Sbill /* 123600Sbill * Ignore stabs, but give them a symbol table index 124600Sbill */ 125634Shenry if (sp->s_type & STABFLAG) 126600Sbill goto assignindex; 127634Shenry if ((sp->s_type&XTYPE)==XUNDEF) 128634Shenry sp->s_type = XXTRN+XUNDEF; 129634Shenry else if ((sp->s_type&XTYPE)==XDATA) 130634Shenry sp->s_value += usedot[sp->s_index].e_xvalue; 131634Shenry else if ((sp->s_type&XTYPE)==XTEXT) 132634Shenry sp->s_value += usedot[sp->s_index].e_xvalue; 133634Shenry else if ((sp->s_type&XTYPE)==XBSS) { 134634Shenry bs = sp->s_value; 135634Shenry sp->s_value = hdr.a_bss + datbase; 136600Sbill hdr.a_bss += bs; 137600Sbill } 138600Sbill assignindex: 13914450Srrh if (!ISLABEL(sp)) 14014450Srrh sp->s_index = relpos++; 141600Sbill } 142600Sbill } 143600Sbill 144600Sbill /* 145600Sbill * For all of the stabs that had their final value undefined during pass 1 146600Sbill * and during pass 2 assign a final value. 147600Sbill * We have already given stab entrys a initial approximation 148600Sbill * when we constsructed the sorted symbol table. 149600Sbill * Iteration order doesn't matter. 150600Sbill */ 15112592Scsvaf 15212592Scsvaf stabfix() 15312592Scsvaf { 154600Sbill register struct symtab *sp, **cosp; 155600Sbill register struct symtab *p; 156600Sbill 157600Sbill SYMITERATE(cosp, sp){ 158634Shenry if(sp->s_ptype && (sp->s_type & STABFLAG)) { 159634Shenry p = sp->s_dest; 16012592Scsvaf /* 16112592Scsvaf * STABFLOATING indicates that the offset has been saved in s_desc, s_other 16212592Scsvaf */ 16312592Scsvaf if(sp->s_tag == STABFLOATING) { 16412592Scsvaf sp->s_value = ( ( ((unsigned char) sp->s_other) << 16) | ( (unsigned short) sp->s_desc ) ); 16512592Scsvaf sp->s_value = sp->s_value + p->s_value; 16612592Scsvaf } 16712592Scsvaf else sp->s_value = p->s_value; 168634Shenry sp->s_index = p->s_index; 169634Shenry sp->s_type = p->s_type; 17012592Scsvaf 17112592Scsvaf 172600Sbill } 173600Sbill } 174600Sbill } 175600Sbill 176600Sbill char *Calloc(number, size) 177600Sbill int number, size; 178600Sbill { 179600Sbill register char *newstuff; 1805828Srrh char *sbrk(); 1815828Srrh newstuff = sbrk(number*size); 182600Sbill if ((int)newstuff == -1){ 183600Sbill yyerror("Ran out of Memory"); 184600Sbill delexit(); 185600Sbill } 186600Sbill return(newstuff); 187600Sbill } 188600Sbill 189600Sbill char *ClearCalloc(number, size) 190600Sbill int number, size; 191600Sbill { 192600Sbill register char *newstuff; /* r11 */ 193600Sbill register int length = number * size; /* r10 */ 1945828Srrh #ifdef lint 1955828Srrh length = length; 1965828Srrh #endif length 197600Sbill newstuff = Calloc(number, size); 198600Sbill asm("movc5 $0, (r0), $0, r10, (r11)"); 199600Sbill return(newstuff); 200600Sbill } 201600Sbill 202600Sbill struct symtab *symalloc() 203600Sbill { 204600Sbill if (symsleft == 0){ 205600Sbill newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY); 206600Sbill symsleft = SYMDALLOP; 207600Sbill nextsym = &newbox->symslots[0]; 208600Sbill if (alloctail == 0){ 209600Sbill allochead = alloctail = newbox; 210600Sbill } else { 211600Sbill alloctail->nextalloc = newbox; 212600Sbill alloctail = newbox; 213600Sbill } 214600Sbill } 215600Sbill --symsleft; 216600Sbill ++nsyms; 217600Sbill return(nextsym++); 218600Sbill } 219600Sbill 220600Sbill strpoolalloc() 221600Sbill { 222600Sbill register struct strpool *new; 223600Sbill 224600Sbill new = (struct strpool *)Calloc(1, sizeof (struct strpool)); 225600Sbill new->str_nalloc = 0; 226600Sbill new->str_next = strplhead; 227600Sbill strplhead = new; 228600Sbill } 229600Sbill 230600Sbill symcmp(Pptr, Qptr) 231600Sbill struct symtab **Pptr, **Qptr; 232600Sbill { 233600Sbill register struct symtab *p = *Pptr; 234600Sbill register struct symtab *q = *Qptr; 235634Shenry if (p->s_index < q->s_index) 236600Sbill return(-1); 237634Shenry if (p->s_index > q->s_index) 238600Sbill return(1); 239634Shenry if (p->s_value < q->s_value) 240600Sbill return(-1); 241634Shenry if (p->s_value > q->s_value) 242600Sbill return(1); 243600Sbill /* 244600Sbill * Force jxxx entries to virtually preceed labels defined 245600Sbill * to follow the jxxxx instruction, so that bumping the 246600Sbill * jxxx instruction correctly fixes up the following labels 247600Sbill */ 248634Shenry if (p->s_tag >= IGNOREBOUND) /*p points to a jxxx*/ 249600Sbill return(-1); 250634Shenry if (q->s_tag >= IGNOREBOUND) 251600Sbill return(1); 252600Sbill /* 253600Sbill * both are now just plain labels; the relative order doesn't 254600Sbill * matter. Both can't be jxxxes, as they would have different 255600Sbill * values. 256600Sbill */ 257600Sbill return(0); 258600Sbill } /*end of symcmp*/ 259600Sbill 260600Sbill /* 261600Sbill * We construct the auxiliary table of pointers, symptrs and 262600Sbill * symdelim 263600Sbill * We also assign preliminary values to stab entries that did not yet 264600Sbill * have an absolute value (because they initially referred to 265600Sbill * forward references). We don't worry about .stabds, as they 266600Sbill * already have an estimated final value 267600Sbill */ 268600Sbill 269600Sbill sortsymtab() 270600Sbill { 271600Sbill register struct symtab *sp; 272600Sbill register struct symtab **cowalk; 273600Sbill register struct allocbox *allocwalk; 274600Sbill struct symtab *ubsp; 275600Sbill int segno; 276600Sbill int slotno; 277600Sbill int symsin; /*number put into symptrs*/ 278600Sbill 279600Sbill symptrs = (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs); 280600Sbill /* 281600Sbill * Allocate one word at the beginning of the symptr array 282600Sbill * so that backwards scans through the symptr array will 283600Sbill * work correctly while scanning through the zeroth segment 284600Sbill */ 285600Sbill *symptrs++ = 0; 286600Sbill cowalk = symptrs; 287600Sbill symsin = 0; 288600Sbill DECLITERATE(allocwalk, sp, ubsp) { 289634Shenry if (sp->s_ptype && (sp->s_type &STABFLAG)){ 290634Shenry sp->s_value = sp->s_dest->s_value; 291634Shenry sp->s_index = sp->s_dest->s_index; 292600Sbill } 293600Sbill if (symsin >= nsyms) 294600Sbill yyerror("INTERNAL ERROR: overfilled symbol table indirection table"); 295600Sbill *cowalk++ = sp; 296600Sbill symsin++; 297600Sbill } 298600Sbill if (symsin != nsyms) 299600Sbill yyerror("INTERNAL ERROR: installed %d syms, should have installed %d", 300600Sbill symsin, nsyms); 301600Sbill symptrub = &symptrs[nsyms ]; 302600Sbill qsort(symptrs, nsyms, sizeof *symptrs, symcmp); 303600Sbill symdelim[0] = symptrs; 304600Sbill for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1; 305600Sbill segno < NLOC + NLOC; 306600Sbill segno++, slotno++){ 307634Shenry for (; sp && sp->s_index == segno; sp = *++cowalk); 308600Sbill symdelim[slotno] = cowalk; /*forms the ub delimeter*/ 309600Sbill } 310600Sbill } /*end of sortsymtab*/ 311600Sbill 312600Sbill #ifdef DEBUG 313600Sbill dumpsymtab() 314600Sbill { 315600Sbill register int segno; 316600Sbill register struct symtab *sp, **cosp, *ub; 317600Sbill char *tagstring(); 318600Sbill 319600Sbill printf("Symbol Table dump:\n"); 320600Sbill for (segno = 0; segno < NLOC + NLOC; segno++){ 321600Sbill printf("Segment number: %d\n", segno); 322600Sbill SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){ 323600Sbill printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n", 32413514Srrh segno, FETCHNAME(sp), 325634Shenry sp->s_value, sp->s_index, 326634Shenry tagstring(sp->s_tag)); 327600Sbill printf("\t\ttype: %d jxbump %d jxfear: %d\n", 328634Shenry sp->s_type, sp->s_jxbump, sp->s_jxfear); 329600Sbill } 330600Sbill printf("\n\n"); 331600Sbill } 332600Sbill } 333600Sbill 334600Sbill static char tagbuff[4]; 335600Sbill 336600Sbill char *tagstring(tag) 337600Sbill unsigned char tag; 338600Sbill { 339600Sbill switch(tag){ 340600Sbill case JXACTIVE: return("active"); 341600Sbill case JXNOTYET: return("notyet"); 342600Sbill case JXALIGN: return("align"); 343600Sbill case JXQUESTIONABLE: return("jxquestionable"); 344600Sbill case JXINACTIVE: return("inactive"); 345600Sbill case JXTUNNEL: return("tunnel"); 346600Sbill case OBSOLETE: return("obsolete"); 347600Sbill case IGNOREBOUND: return("ignorebound"); 348600Sbill case STABFLOATING: return("stabfloating"); 349600Sbill case STABFIXED: return("stabfixed"); 350600Sbill case LABELID: return("labelid"); 351600Sbill case OKTOBUMP: return("oktobump"); 352600Sbill case ISET: return("iset"); 353600Sbill case ILSYM: return("ilsym"); 354600Sbill default: sprintf(tagbuff,"%d", tag); 355600Sbill return(tagbuff); 356600Sbill } 357600Sbill } 358600Sbill #endif DEBUG 359600Sbill 360600Sbill htaballoc() 361600Sbill { 362600Sbill register struct hashdallop *new; 363600Sbill new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop)); 364600Sbill if (htab == 0) 365600Sbill htab = new; 366600Sbill else { /* add AFTER the 1st slot */ 367600Sbill new->h_next = htab->h_next; 368600Sbill htab->h_next = new; 369600Sbill } 370600Sbill } 371600Sbill 372600Sbill #define HASHCLOGGED (NHASH / 2) 373600Sbill 374600Sbill /* 375600Sbill * Lookup a symbol stored in extern yytext. 376600Sbill * All strings passed in via extern yytext had better have 377600Sbill * a trailing null. Strings are placed in yytext for hashing by 378600Sbill * syminstall() and by yylex(); 379600Sbill * 380600Sbill * We take pains to avoid function calls; this functdion 381600Sbill * is called quite frequently, and the calls overhead 382600Sbill * in the vax contributes significantly to the overall 383600Sbill * execution speed of as. 384600Sbill */ 385600Sbill struct symtab **lookup(instflg) 386600Sbill int instflg; /* 0: don't install */ 387600Sbill { 388600Sbill static int initialprobe; 389600Sbill register struct symtab **hp; 390600Sbill register char *from; 391600Sbill register char *to; 392600Sbill register int len; 393600Sbill register int nprobes; 39413514Srrh static struct hashdallop *hdallop; 39513514Srrh static struct symtab **emptyslot; 39613514Srrh static struct hashdallop *emptyhd; 39713514Srrh static struct symtab **hp_ub; 398600Sbill 399600Sbill emptyslot = 0; 400600Sbill for (nprobes = 0, from = yytext; 401600Sbill *from; 402600Sbill nprobes <<= 2, nprobes += *from++) 403600Sbill continue; 404600Sbill nprobes += from[-1] << 5; 405600Sbill nprobes %= NHASH; 406600Sbill if (nprobes < 0) 407600Sbill nprobes += NHASH; 408600Sbill 409600Sbill initialprobe = nprobes; 410600Sbill for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){ 411600Sbill for (hp = &(hdallop->h_htab[initialprobe]), 412600Sbill nprobes = 1, 413600Sbill hp_ub = &(hdallop->h_htab[NHASH]); 414600Sbill (*hp) && (nprobes < NHASH); 415600Sbill hp += nprobes, 416600Sbill hp -= (hp >= hp_ub) ? NHASH:0, 417600Sbill nprobes += 2) 418600Sbill { 419600Sbill from = yytext; 42013514Srrh to = FETCHNAME(*hp); 421600Sbill while (*from && *to) 422600Sbill if (*from++ != *to++) 423600Sbill goto nextprobe; 424600Sbill if (*to == *from) /*assert both are == 0*/ 425600Sbill return(hp); 42613522Srrh nextprobe: ; 427600Sbill } 428600Sbill if (*hp == 0 && emptyslot == 0 && 429600Sbill hdallop->h_nused < HASHCLOGGED) { 430600Sbill emptyslot = hp; 431600Sbill emptyhd = hdallop; 432600Sbill } 433600Sbill } 434600Sbill if (emptyslot == 0) { 435600Sbill htaballoc(); 436600Sbill hdallop = htab->h_next; /* aren't we smart! */ 437600Sbill hp = &hdallop->h_htab[initialprobe]; 438600Sbill } else { 439600Sbill hdallop = emptyhd; 440600Sbill hp = emptyslot; 441600Sbill } 442600Sbill if (instflg) { 443600Sbill *hp = symalloc(); 444600Sbill hdallop->h_nused++; 44513447Srrh for (from = yytext, len = 0; *from++; len++) 446600Sbill continue; 44713572Srrh (*hp)->s_name = (char *)savestr(yytext, len + 1, STR_BOTH); 448600Sbill } 449600Sbill return(hp); 450600Sbill } /*end of lookup*/ 45113447Srrh /* 45213572Srrh * save a string str with len in the places indicated by place 45313447Srrh */ 45413572Srrh struct strdesc *savestr(str, len, place) 45513447Srrh char *str; 45613572Srrh int len; 45713572Srrh int place; 458600Sbill { 45913514Srrh reg struct strdesc *res; 46013514Srrh int tlen; 46113572Srrh /* 46213572Srrh * Compute the total length of the record to live in core 46313572Srrh */ 46413514Srrh tlen = sizeof(struct strdesc) - sizeof(res->sd_string); 46513572Srrh if (place & STR_CORE) 46613572Srrh tlen += len; 46713572Srrh /* 46813572Srrh * See if there is enough space for the record, 46913572Srrh * and allocate the record. 47013572Srrh */ 47113514Srrh if (tlen >= (STRPOOLDALLOP - strplhead->str_nalloc)) 472600Sbill strpoolalloc(); 47313514Srrh res = (struct strdesc *)(strplhead->str_names + strplhead->str_nalloc); 47413572Srrh /* 47513572Srrh * Save the string information that is always present 47613572Srrh */ 47713572Srrh res->sd_stroff = strfilepos; 47813572Srrh res->sd_strlen = len; 47913572Srrh res->sd_place = place; 48013572Srrh /* 48113572Srrh * Now, save the string itself. If str is null, then 48213572Srrh * the characters have already been dumped to the file 48313572Srrh */ 48413572Srrh if ((place & STR_CORE) && str) 48513572Srrh movestr(res[0].sd_string, str, len); 48613572Srrh if (place & STR_FILE){ 48713572Srrh if (str){ 48813572Srrh fwrite(str, 1, len, strfile); 48913572Srrh } 49013572Srrh strfilepos += len; 49113572Srrh } 49213572Srrh /* 49313572Srrh * Adjust the in core string pool size 49413572Srrh */ 49513514Srrh strplhead->str_nalloc += tlen; 49613447Srrh return(res); 497600Sbill } 498600Sbill /* 499600Sbill * The relocation information is saved internally in an array of 500600Sbill * lists of relocation buffers. The relocation buffers are 501600Sbill * exactly the same size as a token buffer; if we use VM for the 502600Sbill * temporary file we reclaim this storage, otherwise we create 503600Sbill * them by mallocing. 504600Sbill */ 505600Sbill #define RELBUFLG TOKBUFLG 506600Sbill #define NRELOC ((TOKBUFLG - \ 507600Sbill (sizeof (int) + sizeof (struct relbufdesc *)) \ 508600Sbill ) / (sizeof (struct relocation_info))) 509600Sbill 510600Sbill struct relbufdesc{ 511600Sbill int rel_count; 512600Sbill struct relbufdesc *rel_next; 513600Sbill struct relocation_info rel_reloc[NRELOC]; 514600Sbill }; 515600Sbill extern struct relbufdesc *tok_free; 516600Sbill #define rel_free tok_free 517600Sbill static struct relbufdesc *rel_temp; 518634Shenry struct relocation_info r_can_1PC; 519634Shenry struct relocation_info r_can_0PC; 520600Sbill 521600Sbill initoutrel() 522600Sbill { 523634Shenry r_can_0PC.r_address = 0; 524634Shenry r_can_0PC.r_symbolnum = 0; 525634Shenry r_can_0PC.r_pcrel = 0; 526634Shenry r_can_0PC.r_length = 0; 527634Shenry r_can_0PC.r_extern = 0; 528634Shenry 529634Shenry r_can_1PC = r_can_0PC; 530600Sbill r_can_1PC.r_pcrel = 1; 531600Sbill } 532600Sbill 533675Shenry outrel(xp, reloc_how) 534675Shenry register struct exp *xp; 5355828Srrh int reloc_how; /* TYPB..TYPH + (possibly)RELOC_PCREL */ 536600Sbill { 537675Shenry struct relocation_info reloc; 538675Shenry register int x_type_mask; 53913447Srrh int pcrel; 540600Sbill 541675Shenry x_type_mask = xp->e_xtype & ~XFORW; 542675Shenry pcrel = reloc_how & RELOC_PCREL; 543675Shenry reloc_how &= ~RELOC_PCREL; 544675Shenry 545600Sbill if (bitoff&07) 546600Sbill yyerror("Padding error"); 547675Shenry if (x_type_mask == XUNDEF) 548600Sbill yyerror("Undefined reference"); 549600Sbill 550675Shenry if ( (x_type_mask != XABS) || pcrel ) { 551675Shenry if (ty_NORELOC[reloc_how]) 5525828Srrh yyerror("Illegal Relocation of floating or large int number."); 553675Shenry reloc = pcrel ? r_can_1PC : r_can_0PC; 554634Shenry reloc.r_address = dotp->e_xvalue - 555640Sbill ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase ); 556675Shenry reloc.r_length = ty_nlg[reloc_how]; 557675Shenry switch(x_type_mask){ 558600Sbill case XXTRN | XUNDEF: 559675Shenry reloc.r_symbolnum = xp->e_xname->s_index; 560600Sbill reloc.r_extern = 1; 561600Sbill break; 562600Sbill default: 563675Shenry if (readonlydata && (x_type_mask&~XXTRN) == XDATA) 564675Shenry x_type_mask = XTEXT | (x_type_mask&XXTRN); 565675Shenry reloc.r_symbolnum = x_type_mask; 566600Sbill break; 567600Sbill } 568600Sbill if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){ 569600Sbill if (rel_free){ 570600Sbill rel_temp = rel_free; 571600Sbill rel_free = rel_temp->rel_next; 572600Sbill } else { 573600Sbill rel_temp = (struct relbufdesc *) 574600Sbill Calloc(1,sizeof (struct relbufdesc)); 575600Sbill } 576600Sbill rel_temp->rel_count = 0; 577600Sbill rel_temp->rel_next = relfil; 578600Sbill relfil = rusefile[dotp - &usedot[0]] = rel_temp; 579600Sbill } 580600Sbill relfil->rel_reloc[relfil->rel_count++] = reloc; 581600Sbill } 582600Sbill /* 583600Sbill * write the unrelocated value to the text file 584600Sbill */ 585675Shenry dotp->e_xvalue += ty_nbyte[reloc_how]; 586675Shenry if (pcrel) 587675Shenry xp->e_xvalue -= dotp->e_xvalue; 5885828Srrh switch(reloc_how){ 5895828Srrh case TYPO: 5905828Srrh case TYPQ: 5915828Srrh 5925828Srrh case TYPF: 5935828Srrh case TYPD: 5945828Srrh case TYPG: 5955828Srrh case TYPH: 5965828Srrh bignumwrite(xp->e_number, reloc_how); 5975828Srrh break; 5985828Srrh 5995828Srrh default: 6005828Srrh bwrite((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil); 6015828Srrh break; 6025828Srrh } 603600Sbill } 604600Sbill /* 605600Sbill * Flush out all of the relocation information. 606600Sbill * Note that the individual lists of buffers are in 607600Sbill * reverse order, so we must reverse them 608600Sbill */ 609600Sbill off_t closeoutrel(relocfile) 610600Sbill BFILE *relocfile; 611600Sbill { 612600Sbill int locindex; 613600Sbill u_long Closeoutrel(); 614600Sbill 615600Sbill trsize = 0; 616600Sbill for (locindex = 0; locindex < NLOC; locindex++){ 617600Sbill trsize += Closeoutrel(rusefile[locindex], relocfile); 618600Sbill } 619600Sbill drsize = 0; 620600Sbill for (locindex = 0; locindex < NLOC; locindex++){ 621600Sbill drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile); 622600Sbill } 623600Sbill return(trsize + drsize); 624600Sbill } 625600Sbill 626600Sbill u_long Closeoutrel(relfil, relocfile) 627600Sbill struct relbufdesc *relfil; 628600Sbill BFILE *relocfile; 629600Sbill { 630600Sbill u_long tail; 631600Sbill if (relfil == 0) 632600Sbill return(0L); 633600Sbill tail = Closeoutrel(relfil->rel_next, relocfile); 634600Sbill bwrite((char *)&relfil->rel_reloc[0], 635600Sbill relfil->rel_count * sizeof (struct relocation_info), 636600Sbill relocfile); 637600Sbill return(tail + relfil->rel_count * sizeof (struct relocation_info)); 638600Sbill } 639600Sbill 640634Shenry #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels)) 641600Sbill int sizesymtab() 642600Sbill { 643634Shenry return (sizeof (struct nlist) * NOUTSYMS); 644600Sbill } 645600Sbill /* 646600Sbill * Write out n symbols to file f, beginning at p 647600Sbill * ignoring symbols that are obsolete, jxxx instructions, and 648600Sbill * possibly, labels 649600Sbill */ 650600Sbill int symwrite(symfile) 651600Sbill BFILE *symfile; 652600Sbill { 65313514Srrh int symsout; /*those actually written*/ 65413514Srrh int symsdesired = NOUTSYMS; 65513514Srrh reg struct symtab *sp, *ub; 65613514Srrh char *name; /* temp to save the name */ 65714450Srrh int totalstr; 658634Shenry /* 659634Shenry * We use sp->s_index to hold the length of the 660634Shenry * name; it isn't used for anything else 661634Shenry */ 662600Sbill register struct allocbox *allocwalk; 663600Sbill 664600Sbill symsout = 0; 66514450Srrh totalstr = sizeof(totalstr); 66614450Srrh DECLITERATE(allocwalk, sp, ub) { 667634Shenry if (sp->s_tag >= IGNOREBOUND) 668600Sbill continue; 66914450Srrh if (ISLABEL(sp)) 670600Sbill continue; 671600Sbill symsout++; 672634Shenry name = sp->s_name; /* save pointer */ 67313447Srrh /* 67413447Srrh * the length of the symbol table string 67514450Srrh * always includes the trailing null; 67614450Srrh * blast the pointer to its a.out value. 67713447Srrh */ 67813514Srrh if (sp->s_name && (sp->s_index = STRLEN(sp))){ 67914450Srrh sp->s_nmx = totalstr; 68014450Srrh totalstr += sp->s_index; 681634Shenry } else { 68213447Srrh sp->s_nmx = 0; 683634Shenry } 68414450Srrh if (sp->s_ptype != 0) 68514450Srrh sp->s_type = sp->s_ptype; 68614450Srrh else 68714450Srrh sp->s_type = (sp->s_type & (~XFORW)); 688640Sbill if (readonlydata && (sp->s_type&~N_EXT) == N_DATA) 689640Sbill sp->s_type = N_TEXT | (sp->s_type & N_EXT); 6905828Srrh bwrite((char *)&sp->s_nm, sizeof (struct nlist), symfile); 691634Shenry sp->s_name = name; /* restore pointer */ 692600Sbill } 693600Sbill if (symsout != symsdesired) 694600Sbill yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n", 695600Sbill symsout, symsdesired); 696600Sbill /* 69714450Srrh * Construct the string pool from the symbols that were written, 69814450Srrh * possibly fetching from the string file if the string 69914450Srrh * is not core resident. 700600Sbill */ 70114450Srrh bwrite(&totalstr, sizeof(totalstr), symfile); 70214450Srrh symsout = 0; 70314450Srrh DECLITERATE(allocwalk, sp, ub) { 70414450Srrh if (sp->s_tag >= IGNOREBOUND) 70514450Srrh continue; 70614450Srrh if (ISLABEL(sp)) 70714450Srrh continue; 70814450Srrh symsout++; 70914450Srrh if (STRLEN(sp) > 0){ 71014450Srrh if (STRPLACE(sp) & STR_CORE){ 71114450Srrh bwrite(FETCHNAME(sp), STRLEN(sp), symfile); 71214450Srrh } else if (STRPLACE(sp) & STR_FILE){ 71314450Srrh char rbuf[2048]; 71414450Srrh int left, nread; 71514450Srrh fseek(strfile, STROFF(sp), 0); 71614450Srrh for (left = STRLEN(sp); left > 0; left -= nread){ 71714450Srrh nread = fread(rbuf, sizeof(char), 71814450Srrh min(sizeof(rbuf), left), strfile); 71914450Srrh if (nread == 0) 72014450Srrh break; 72114450Srrh bwrite(rbuf, nread, symfile); 72214450Srrh } 72314450Srrh } 72413447Srrh } 725600Sbill } 72614450Srrh if (symsout != symsdesired) 72714450Srrh yyerror("INTERNAL ERROR: Wrote %d strings, wanted %d\n", 72814450Srrh symsout, symsdesired); 729600Sbill } 730