15828Srrh /* 25828Srrh * Copyright (c) 1982 Regents of the University of California 35828Srrh */ 45828Srrh #ifndef lint 5*12592Scsvaf static char sccsid[] = "@(#)assyms.c 4.8 05/19/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 * If we have flexible names, then we allocate BUFSIZ long 46600Sbill * string, and pack strings into that. Otherwise, we allocate 47600Sbill * symbol storage in fixed hunks NCPS long when we allocate space 48600Sbill * for other symbol attributes. 49600Sbill */ 50600Sbill #ifdef FLEXNAMES 51600Sbill struct strpool *strplhead = 0; 52634Shenry #endif FLEXNAMES 53600Sbill 54600Sbill symtabinit() 55600Sbill { 56600Sbill allochead = 0; 57600Sbill alloctail = 0; 58600Sbill nextsym = 0; 59600Sbill symsleft = 0; 60600Sbill #ifdef FLEXNAMES 61600Sbill strpoolalloc(); /* get the first strpool storage area */ 62600Sbill #endif FLEXNAMES 63600Sbill htab = 0; 64600Sbill htaballoc(); /* get the first part of the hash table */ 65600Sbill } 66600Sbill 67600Sbill /* 68600Sbill * Install all known instructions in the symbol table 69600Sbill */ 70600Sbill syminstall() 71600Sbill { 725828Srrh register Iptr ip; 73600Sbill register struct symtab **hp; 74600Sbill register char *p1, *p2; 755828Srrh register int i; 76600Sbill 775828Srrh for (i = 0; i < NINST; i++) 785828Srrh itab[i] = (Iptr*)BADPOINT; 795828Srrh 80634Shenry #ifdef FLEXNAMES 815828Srrh for (ip = (Iptr)instab; ip->s_name != 0; ip++) { 82634Shenry #else not FLEXNAMES 835828Srrh for (ip = (Iptr)instab; ip->s_name[0] != '\0'; ip++){ 84634Shenry #endif not FLEXNAMES 85634Shenry p1 = ip->s_name; 86600Sbill p2 = yytext; 87600Sbill while (*p2++ = *p1++); 88600Sbill hp = lookup(0); /* 0 => don't install this*/ 89600Sbill if (*hp==NULL) { 90600Sbill *hp = (struct symtab *)ip; 91634Shenry if ( (ip->s_tag!=INSTn) 92634Shenry && (ip->s_tag!=INST0) 93634Shenry && (ip->s_tag!=0)) 94600Sbill continue; /* was pseudo-op */ 955828Srrh if (itab[ip->i_eopcode] == (Iptr*)BADPOINT){ 965828Srrh itab[ip->i_eopcode] = 975828Srrh (Iptr*)ClearCalloc(256, sizeof(Iptr)); 985828Srrh for (i = 0; i < 256; i++) 995828Srrh itab[ip->i_eopcode][i] = 1005828Srrh (Iptr)BADPOINT; 1015828Srrh } 1025828Srrh itab[ip->i_eopcode][ip->i_popcode] = ip; 103600Sbill } 104600Sbill } 105600Sbill } /*end of syminstall*/ 106600Sbill 107600Sbill 108600Sbill /* 109600Sbill * Assign final values to symbols, 110600Sbill * and overwrite the index field with its relative position in 111600Sbill * the symbol table we give to the loader. 112600Sbill */ 113600Sbill extern struct exec hdr; 114600Sbill 115600Sbill freezesymtab() 116600Sbill { 117600Sbill register struct symtab *sp; 118600Sbill long bs; 119600Sbill register int relpos = 0; 120600Sbill register struct symtab *ubsp; 121600Sbill register struct allocbox *allocwalk; 122600Sbill 123600Sbill DECLITERATE(allocwalk, sp, ubsp) 124600Sbill { 125634Shenry if (sp->s_tag >= IGNOREBOUND) 126600Sbill continue; /*totally ignore jxxx entries */ 127600Sbill /* 128600Sbill * Ignore stabs, but give them a symbol table index 129600Sbill */ 130634Shenry if (sp->s_type & STABFLAG) 131600Sbill goto assignindex; 132634Shenry if ((sp->s_type&XTYPE)==XUNDEF) 133634Shenry sp->s_type = XXTRN+XUNDEF; 134634Shenry else if ((sp->s_type&XTYPE)==XDATA) 135634Shenry sp->s_value += usedot[sp->s_index].e_xvalue; 136634Shenry else if ((sp->s_type&XTYPE)==XTEXT) 137634Shenry sp->s_value += usedot[sp->s_index].e_xvalue; 138634Shenry else if ((sp->s_type&XTYPE)==XBSS) { 139634Shenry bs = sp->s_value; 140634Shenry sp->s_value = hdr.a_bss + datbase; 141600Sbill hdr.a_bss += bs; 142600Sbill } 143600Sbill assignindex: 144634Shenry if ( (sp->s_name[0] != 'L') 145634Shenry || (sp->s_tag != LABELID) 146600Sbill || savelabels 147600Sbill ) /*then, we will write it later on*/ 148634Shenry sp->s_index = relpos++; 149600Sbill } 150600Sbill } 151600Sbill 152600Sbill 153600Sbill 154600Sbill /* 155600Sbill * For all of the stabs that had their final value undefined during pass 1 156600Sbill * and during pass 2 assign a final value. 157600Sbill * We have already given stab entrys a initial approximation 158600Sbill * when we constsructed the sorted symbol table. 159600Sbill * Iteration order doesn't matter. 160600Sbill */ 161*12592Scsvaf 162*12592Scsvaf stabfix() 163*12592Scsvaf { 164600Sbill register struct symtab *sp, **cosp; 165600Sbill register struct symtab *p; 166600Sbill 167600Sbill SYMITERATE(cosp, sp){ 168634Shenry if(sp->s_ptype && (sp->s_type & STABFLAG)) { 169634Shenry p = sp->s_dest; 170*12592Scsvaf /* 171*12592Scsvaf * STABFLOATING indicates that the offset has been saved in s_desc, s_other 172*12592Scsvaf */ 173*12592Scsvaf if(sp->s_tag == STABFLOATING) { 174*12592Scsvaf sp->s_value = ( ( ((unsigned char) sp->s_other) << 16) | ( (unsigned short) sp->s_desc ) ); 175*12592Scsvaf sp->s_value = sp->s_value + p->s_value; 176*12592Scsvaf } 177*12592Scsvaf else sp->s_value = p->s_value; 178634Shenry sp->s_index = p->s_index; 179634Shenry sp->s_type = p->s_type; 180*12592Scsvaf 181*12592Scsvaf 182600Sbill } 183600Sbill } 184600Sbill } 185600Sbill 186600Sbill char *Calloc(number, size) 187600Sbill int number, size; 188600Sbill { 189600Sbill register char *newstuff; 1905828Srrh char *sbrk(); 1915828Srrh newstuff = sbrk(number*size); 192600Sbill if ((int)newstuff == -1){ 193600Sbill yyerror("Ran out of Memory"); 194600Sbill delexit(); 195600Sbill } 196600Sbill return(newstuff); 197600Sbill } 198600Sbill 199600Sbill char *ClearCalloc(number, size) 200600Sbill int number, size; 201600Sbill { 202600Sbill register char *newstuff; /* r11 */ 203600Sbill register int length = number * size; /* r10 */ 2045828Srrh #ifdef lint 2055828Srrh length = length; 2065828Srrh #endif length 207600Sbill newstuff = Calloc(number, size); 208600Sbill asm("movc5 $0, (r0), $0, r10, (r11)"); 209600Sbill return(newstuff); 210600Sbill } 211600Sbill 212600Sbill struct symtab *symalloc() 213600Sbill { 214600Sbill if (symsleft == 0){ 215600Sbill newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY); 216600Sbill symsleft = SYMDALLOP; 217600Sbill nextsym = &newbox->symslots[0]; 218600Sbill if (alloctail == 0){ 219600Sbill allochead = alloctail = newbox; 220600Sbill } else { 221600Sbill alloctail->nextalloc = newbox; 222600Sbill alloctail = newbox; 223600Sbill } 224600Sbill } 225600Sbill --symsleft; 226600Sbill ++nsyms; 227600Sbill return(nextsym++); 228600Sbill } 229600Sbill 230600Sbill #ifdef FLEXNAMES 231600Sbill strpoolalloc() 232600Sbill { 233600Sbill register struct strpool *new; 234600Sbill 235600Sbill new = (struct strpool *)Calloc(1, sizeof (struct strpool)); 236600Sbill new->str_nalloc = 0; 237600Sbill new->str_next = strplhead; 238600Sbill strplhead = new; 239600Sbill } 240600Sbill #endif FLEXNAMES 241600Sbill 242600Sbill symcmp(Pptr, Qptr) 243600Sbill struct symtab **Pptr, **Qptr; 244600Sbill { 245600Sbill register struct symtab *p = *Pptr; 246600Sbill register struct symtab *q = *Qptr; 247634Shenry if (p->s_index < q->s_index) 248600Sbill return(-1); 249634Shenry if (p->s_index > q->s_index) 250600Sbill return(1); 251634Shenry if (p->s_value < q->s_value) 252600Sbill return(-1); 253634Shenry if (p->s_value > q->s_value) 254600Sbill return(1); 255600Sbill /* 256600Sbill * Force jxxx entries to virtually preceed labels defined 257600Sbill * to follow the jxxxx instruction, so that bumping the 258600Sbill * jxxx instruction correctly fixes up the following labels 259600Sbill */ 260634Shenry if (p->s_tag >= IGNOREBOUND) /*p points to a jxxx*/ 261600Sbill return(-1); 262634Shenry if (q->s_tag >= IGNOREBOUND) 263600Sbill return(1); 264600Sbill /* 265600Sbill * both are now just plain labels; the relative order doesn't 266600Sbill * matter. Both can't be jxxxes, as they would have different 267600Sbill * values. 268600Sbill */ 269600Sbill return(0); 270600Sbill } /*end of symcmp*/ 271600Sbill 272600Sbill /* 273600Sbill * We construct the auxiliary table of pointers, symptrs and 274600Sbill * symdelim 275600Sbill * We also assign preliminary values to stab entries that did not yet 276600Sbill * have an absolute value (because they initially referred to 277600Sbill * forward references). We don't worry about .stabds, as they 278600Sbill * already have an estimated final value 279600Sbill */ 280600Sbill 281600Sbill sortsymtab() 282600Sbill { 283600Sbill register struct symtab *sp; 284600Sbill register struct symtab **cowalk; 285600Sbill register struct allocbox *allocwalk; 286600Sbill struct symtab *ubsp; 287600Sbill int segno; 288600Sbill int slotno; 289600Sbill int symsin; /*number put into symptrs*/ 290600Sbill 291600Sbill symptrs = (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs); 292600Sbill /* 293600Sbill * Allocate one word at the beginning of the symptr array 294600Sbill * so that backwards scans through the symptr array will 295600Sbill * work correctly while scanning through the zeroth segment 296600Sbill */ 297600Sbill *symptrs++ = 0; 298600Sbill cowalk = symptrs; 299600Sbill symsin = 0; 300600Sbill DECLITERATE(allocwalk, sp, ubsp) { 301634Shenry if (sp->s_ptype && (sp->s_type &STABFLAG)){ 302634Shenry sp->s_value = sp->s_dest->s_value; 303634Shenry sp->s_index = sp->s_dest->s_index; 304600Sbill } 305600Sbill if (symsin >= nsyms) 306600Sbill yyerror("INTERNAL ERROR: overfilled symbol table indirection table"); 307600Sbill *cowalk++ = sp; 308600Sbill symsin++; 309600Sbill } 310600Sbill if (symsin != nsyms) 311600Sbill yyerror("INTERNAL ERROR: installed %d syms, should have installed %d", 312600Sbill symsin, nsyms); 313600Sbill symptrub = &symptrs[nsyms ]; 314600Sbill qsort(symptrs, nsyms, sizeof *symptrs, symcmp); 315600Sbill symdelim[0] = symptrs; 316600Sbill for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1; 317600Sbill segno < NLOC + NLOC; 318600Sbill segno++, slotno++){ 319634Shenry for (; sp && sp->s_index == segno; sp = *++cowalk); 320600Sbill symdelim[slotno] = cowalk; /*forms the ub delimeter*/ 321600Sbill } 322600Sbill } /*end of sortsymtab*/ 323600Sbill 324600Sbill #ifdef DEBUG 325600Sbill dumpsymtab() 326600Sbill { 327600Sbill register int segno; 328600Sbill register struct symtab *sp, **cosp, *ub; 329600Sbill char *tagstring(); 330600Sbill 331600Sbill printf("Symbol Table dump:\n"); 332600Sbill for (segno = 0; segno < NLOC + NLOC; segno++){ 333600Sbill printf("Segment number: %d\n", segno); 334600Sbill SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){ 335600Sbill #ifdef FLEXNAMES 336600Sbill printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n", 337634Shenry segno, sp->s_name, 338634Shenry sp->s_value, sp->s_index, 339634Shenry tagstring(sp->s_tag)); 340600Sbill #else not FLEXNAMES 341600Sbill printf("\tSeg: %d \"%*.*s\" value: %d index: %d tag %s\n", 342634Shenry segno, NCPS, NCPS, sp->s_name, 343634Shenry sp->s_value, sp->s_index, 344634Shenry tagstring(sp->s_tag)); 345600Sbill #endif not FLEXNAMES 346600Sbill printf("\t\ttype: %d jxbump %d jxfear: %d\n", 347634Shenry sp->s_type, sp->s_jxbump, sp->s_jxfear); 348600Sbill } 349600Sbill printf("\n\n"); 350600Sbill } 351600Sbill } 352600Sbill 353600Sbill static char tagbuff[4]; 354600Sbill 355600Sbill char *tagstring(tag) 356600Sbill unsigned char tag; 357600Sbill { 358600Sbill switch(tag){ 359600Sbill case JXACTIVE: return("active"); 360600Sbill case JXNOTYET: return("notyet"); 361600Sbill case JXALIGN: return("align"); 362600Sbill case JXQUESTIONABLE: return("jxquestionable"); 363600Sbill case JXINACTIVE: return("inactive"); 364600Sbill case JXTUNNEL: return("tunnel"); 365600Sbill case OBSOLETE: return("obsolete"); 366600Sbill case IGNOREBOUND: return("ignorebound"); 367600Sbill case STABFLOATING: return("stabfloating"); 368600Sbill case STABFIXED: return("stabfixed"); 369600Sbill case LABELID: return("labelid"); 370600Sbill case OKTOBUMP: return("oktobump"); 371600Sbill case ISET: return("iset"); 372600Sbill case ILSYM: return("ilsym"); 373600Sbill default: sprintf(tagbuff,"%d", tag); 374600Sbill return(tagbuff); 375600Sbill } 376600Sbill } 377600Sbill #endif DEBUG 378600Sbill 379600Sbill htaballoc() 380600Sbill { 381600Sbill register struct hashdallop *new; 382600Sbill new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop)); 383600Sbill if (htab == 0) 384600Sbill htab = new; 385600Sbill else { /* add AFTER the 1st slot */ 386600Sbill new->h_next = htab->h_next; 387600Sbill htab->h_next = new; 388600Sbill } 389600Sbill } 390600Sbill 391600Sbill #define HASHCLOGGED (NHASH / 2) 392600Sbill 393600Sbill /* 394600Sbill * Lookup a symbol stored in extern yytext. 395600Sbill * All strings passed in via extern yytext had better have 396600Sbill * a trailing null. Strings are placed in yytext for hashing by 397600Sbill * syminstall() and by yylex(); 398600Sbill * 399600Sbill * We take pains to avoid function calls; this functdion 400600Sbill * is called quite frequently, and the calls overhead 401600Sbill * in the vax contributes significantly to the overall 402600Sbill * execution speed of as. 403600Sbill */ 404600Sbill struct symtab **lookup(instflg) 405600Sbill int instflg; /* 0: don't install */ 406600Sbill { 407600Sbill static int initialprobe; 408600Sbill register struct symtab **hp; 409600Sbill register char *from; 410600Sbill register char *to; 411600Sbill register int len; 412600Sbill register int nprobes; 413600Sbill static struct hashdallop *hdallop; 414600Sbill static struct symtab **emptyslot; 415600Sbill static struct hashdallop *emptyhd; 416600Sbill static struct symtab **hp_ub; 417600Sbill 418600Sbill emptyslot = 0; 419600Sbill for (nprobes = 0, from = yytext; 420600Sbill *from; 421600Sbill nprobes <<= 2, nprobes += *from++) 422600Sbill continue; 423600Sbill nprobes += from[-1] << 5; 424600Sbill nprobes %= NHASH; 425600Sbill if (nprobes < 0) 426600Sbill nprobes += NHASH; 427600Sbill 428600Sbill initialprobe = nprobes; 429600Sbill for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){ 430600Sbill for (hp = &(hdallop->h_htab[initialprobe]), 431600Sbill nprobes = 1, 432600Sbill hp_ub = &(hdallop->h_htab[NHASH]); 433600Sbill (*hp) && (nprobes < NHASH); 434600Sbill hp += nprobes, 435600Sbill hp -= (hp >= hp_ub) ? NHASH:0, 436600Sbill nprobes += 2) 437600Sbill { 438600Sbill from = yytext; 439634Shenry to = (*hp)->s_name; 440600Sbill #ifndef FLEXNAMES 441600Sbill for (len = 0; (len<NCPS) && *from; len++) 442600Sbill if (*from++ != *to++) 443600Sbill goto nextprobe; 444600Sbill if (len >= NCPS) /*both are maximal length*/ 445600Sbill return(hp); 446600Sbill if (*to == 0) /*assert *from == 0*/ 447600Sbill return(hp); 448600Sbill #else FLEXNAMES 449600Sbill while (*from && *to) 450600Sbill if (*from++ != *to++) 451600Sbill goto nextprobe; 452600Sbill if (*to == *from) /*assert both are == 0*/ 453600Sbill return(hp); 454600Sbill #endif FLEXNAMES 455600Sbill 456600Sbill nextprobe: ; 457600Sbill } 458600Sbill if (*hp == 0 && emptyslot == 0 && 459600Sbill hdallop->h_nused < HASHCLOGGED) { 460600Sbill emptyslot = hp; 461600Sbill emptyhd = hdallop; 462600Sbill } 463600Sbill } 464600Sbill if (emptyslot == 0) { 465600Sbill htaballoc(); 466600Sbill hdallop = htab->h_next; /* aren't we smart! */ 467600Sbill hp = &hdallop->h_htab[initialprobe]; 468600Sbill } else { 469600Sbill hdallop = emptyhd; 470600Sbill hp = emptyslot; 471600Sbill } 472600Sbill if (instflg) { 473600Sbill *hp = symalloc(); 474600Sbill hdallop->h_nused++; 475600Sbill #ifndef FLEXNAMES 476634Shenry for(len = 0, from = yytext, to = (*hp)->s_name; (len<NCPS); len++) 477600Sbill if ((*to++ = *from++) == '\0') 478600Sbill break; 479600Sbill #else FLEXNAMES 480600Sbill for (from = yytext, len = 1; *from++; len++) 481600Sbill continue; 482600Sbill if (len >= (STRPOOLDALLOP - strplhead->str_nalloc)) 483600Sbill strpoolalloc(); 484634Shenry for ( (*hp)->s_name = to = strplhead->str_names + strplhead->str_nalloc, from = yytext; 485600Sbill ( (*to++ = *from++) != '\0'); ) 486600Sbill continue; 487600Sbill strplhead->str_nalloc += len; 488600Sbill #endif FLEXNAMES 489600Sbill } 490600Sbill return(hp); 491600Sbill } /*end of lookup*/ 492600Sbill 4931744Shenry #ifdef FLEXNAMES 494600Sbill char *savestr(str) 495600Sbill char *str; 496600Sbill { 497600Sbill register int len; 498600Sbill register char *from, *to; 499600Sbill char *res; 500600Sbill 501600Sbill for (from = str, len = 1; *from++; len++) 502600Sbill continue; 503600Sbill if (len >= (STRPOOLDALLOP - strplhead->str_nalloc)) 504600Sbill strpoolalloc(); 505600Sbill for ( res = to = strplhead->str_names + strplhead->str_nalloc, from = str; 506600Sbill ( (*to++ = *from++) != '\0'); ) 507600Sbill continue; 508600Sbill strplhead->str_nalloc += len; 509600Sbill return (res); 510600Sbill } 5111744Shenry #endif FLEXNAMES 512600Sbill 513600Sbill /* 514600Sbill * The relocation information is saved internally in an array of 515600Sbill * lists of relocation buffers. The relocation buffers are 516600Sbill * exactly the same size as a token buffer; if we use VM for the 517600Sbill * temporary file we reclaim this storage, otherwise we create 518600Sbill * them by mallocing. 519600Sbill */ 520600Sbill #define RELBUFLG TOKBUFLG 521600Sbill #define NRELOC ((TOKBUFLG - \ 522600Sbill (sizeof (int) + sizeof (struct relbufdesc *)) \ 523600Sbill ) / (sizeof (struct relocation_info))) 524600Sbill 525600Sbill struct relbufdesc{ 526600Sbill int rel_count; 527600Sbill struct relbufdesc *rel_next; 528600Sbill struct relocation_info rel_reloc[NRELOC]; 529600Sbill }; 530600Sbill extern struct relbufdesc *tok_free; 531600Sbill #define rel_free tok_free 532600Sbill static struct relbufdesc *rel_temp; 533634Shenry struct relocation_info r_can_1PC; 534634Shenry struct relocation_info r_can_0PC; 535600Sbill 536600Sbill initoutrel() 537600Sbill { 538634Shenry r_can_0PC.r_address = 0; 539634Shenry r_can_0PC.r_symbolnum = 0; 540634Shenry r_can_0PC.r_pcrel = 0; 541634Shenry r_can_0PC.r_length = 0; 542634Shenry r_can_0PC.r_extern = 0; 543634Shenry 544634Shenry r_can_1PC = r_can_0PC; 545600Sbill r_can_1PC.r_pcrel = 1; 546600Sbill } 547600Sbill 548675Shenry outrel(xp, reloc_how) 549675Shenry register struct exp *xp; 5505828Srrh int reloc_how; /* TYPB..TYPH + (possibly)RELOC_PCREL */ 551600Sbill { 552675Shenry struct relocation_info reloc; 553675Shenry register int x_type_mask; 554675Shenry int pcrel; 555600Sbill 556675Shenry x_type_mask = xp->e_xtype & ~XFORW; 557675Shenry pcrel = reloc_how & RELOC_PCREL; 558675Shenry reloc_how &= ~RELOC_PCREL; 559675Shenry 560600Sbill if (bitoff&07) 561600Sbill yyerror("Padding error"); 562675Shenry if (x_type_mask == XUNDEF) 563600Sbill yyerror("Undefined reference"); 564600Sbill 565675Shenry if ( (x_type_mask != XABS) || pcrel ) { 566675Shenry if (ty_NORELOC[reloc_how]) 5675828Srrh yyerror("Illegal Relocation of floating or large int number."); 568675Shenry reloc = pcrel ? r_can_1PC : r_can_0PC; 569634Shenry reloc.r_address = dotp->e_xvalue - 570640Sbill ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase ); 571675Shenry reloc.r_length = ty_nlg[reloc_how]; 572675Shenry switch(x_type_mask){ 573600Sbill case XXTRN | XUNDEF: 574675Shenry reloc.r_symbolnum = xp->e_xname->s_index; 575600Sbill reloc.r_extern = 1; 576600Sbill break; 577600Sbill default: 578675Shenry if (readonlydata && (x_type_mask&~XXTRN) == XDATA) 579675Shenry x_type_mask = XTEXT | (x_type_mask&XXTRN); 580675Shenry reloc.r_symbolnum = x_type_mask; 581600Sbill break; 582600Sbill } 583600Sbill if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){ 584600Sbill if (rel_free){ 585600Sbill rel_temp = rel_free; 586600Sbill rel_free = rel_temp->rel_next; 587600Sbill } else { 588600Sbill rel_temp = (struct relbufdesc *) 589600Sbill Calloc(1,sizeof (struct relbufdesc)); 590600Sbill } 591600Sbill rel_temp->rel_count = 0; 592600Sbill rel_temp->rel_next = relfil; 593600Sbill relfil = rusefile[dotp - &usedot[0]] = rel_temp; 594600Sbill } 595600Sbill relfil->rel_reloc[relfil->rel_count++] = reloc; 596600Sbill } 597600Sbill /* 598600Sbill * write the unrelocated value to the text file 599600Sbill */ 600675Shenry dotp->e_xvalue += ty_nbyte[reloc_how]; 601675Shenry if (pcrel) 602675Shenry xp->e_xvalue -= dotp->e_xvalue; 6035828Srrh switch(reloc_how){ 6045828Srrh case TYPO: 6055828Srrh case TYPQ: 6065828Srrh 6075828Srrh case TYPF: 6085828Srrh case TYPD: 6095828Srrh case TYPG: 6105828Srrh case TYPH: 6115828Srrh bignumwrite(xp->e_number, reloc_how); 6125828Srrh break; 6135828Srrh 6145828Srrh default: 6155828Srrh bwrite((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil); 6165828Srrh break; 6175828Srrh } 618600Sbill } 619600Sbill /* 620600Sbill * Flush out all of the relocation information. 621600Sbill * Note that the individual lists of buffers are in 622600Sbill * reverse order, so we must reverse them 623600Sbill */ 624600Sbill off_t closeoutrel(relocfile) 625600Sbill BFILE *relocfile; 626600Sbill { 627600Sbill int locindex; 628600Sbill u_long Closeoutrel(); 629600Sbill 630600Sbill trsize = 0; 631600Sbill for (locindex = 0; locindex < NLOC; locindex++){ 632600Sbill trsize += Closeoutrel(rusefile[locindex], relocfile); 633600Sbill } 634600Sbill drsize = 0; 635600Sbill for (locindex = 0; locindex < NLOC; locindex++){ 636600Sbill drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile); 637600Sbill } 638600Sbill return(trsize + drsize); 639600Sbill } 640600Sbill 641600Sbill u_long Closeoutrel(relfil, relocfile) 642600Sbill struct relbufdesc *relfil; 643600Sbill BFILE *relocfile; 644600Sbill { 645600Sbill u_long tail; 646600Sbill if (relfil == 0) 647600Sbill return(0L); 648600Sbill tail = Closeoutrel(relfil->rel_next, relocfile); 649600Sbill bwrite((char *)&relfil->rel_reloc[0], 650600Sbill relfil->rel_count * sizeof (struct relocation_info), 651600Sbill relocfile); 652600Sbill return(tail + relfil->rel_count * sizeof (struct relocation_info)); 653600Sbill } 654600Sbill 655634Shenry #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels)) 656600Sbill int sizesymtab() 657600Sbill { 658634Shenry return (sizeof (struct nlist) * NOUTSYMS); 659600Sbill } 660600Sbill 661600Sbill #ifdef FLEXNAMES 662600Sbill /* 663600Sbill * We write out the flexible length character strings for names 664600Sbill * in two stages. 665600Sbill * 1) We have always! maintain a fixed sized name list entry; 666600Sbill * the string is indexed by a four byte quantity from the beginning 667600Sbill * of the string pool area. Index 0 is reserved, and indicates 668600Sbill * that there is no associated string. The first valid index is 4. 669600Sbill * 2) We concatenate together and write all of the strings 670600Sbill * in the string pool at the end of the name list. The first 671600Sbill * four bytes in the string pool are indexed only by 0 (see above); 672600Sbill * they contain the total number of bytes in the string pool. 673600Sbill */ 674600Sbill #endif FLEXNAMES 675600Sbill 676600Sbill /* 677600Sbill * Write out n symbols to file f, beginning at p 678600Sbill * ignoring symbols that are obsolete, jxxx instructions, and 679600Sbill * possibly, labels 680600Sbill */ 681600Sbill 682600Sbill int symwrite(symfile) 683600Sbill BFILE *symfile; 684600Sbill { 685600Sbill int symsout; /*those actually written*/ 686600Sbill int symsdesired = NOUTSYMS; 687600Sbill register struct symtab *sp, *ub; 688600Sbill #ifdef FLEXNAMES 689634Shenry char *name; /* temp to save the name */ 690600Sbill long stroff = sizeof (stroff); 691634Shenry /* 692634Shenry * We use sp->s_index to hold the length of the 693634Shenry * name; it isn't used for anything else 694634Shenry */ 695600Sbill #endif FLEXNAMES 696600Sbill 697600Sbill register struct allocbox *allocwalk; 698600Sbill 699600Sbill symsout = 0; 700600Sbill DECLITERATE(allocwalk, sp, ub) 701600Sbill { 702634Shenry if (sp->s_tag >= IGNOREBOUND) 703600Sbill continue; 704634Shenry if ((sp->s_name[0] == 'L') && (sp->s_tag == LABELID) && !savelabels) 705600Sbill continue; 706600Sbill symsout++; 707634Shenry 708634Shenry #ifdef FLEXNAMES 709634Shenry name = sp->s_name; /* save pointer */ 710634Shenry if ( (sp->s_index = strlen(sp->s_name)) != 0){ 711634Shenry sp->s_nmx = stroff; /* clobber pointer */ 712634Shenry stroff += sp->s_index + 1; 713634Shenry } else { 714634Shenry sp->s_nmx = 0; /* clobber pointer */ 715634Shenry } 716634Shenry #endif 717634Shenry sp->s_type = (sp->s_ptype != 0) ? sp->s_ptype : (sp->s_type & (~XFORW)); 718640Sbill if (readonlydata && (sp->s_type&~N_EXT) == N_DATA) 719640Sbill sp->s_type = N_TEXT | (sp->s_type & N_EXT); 7205828Srrh bwrite((char *)&sp->s_nm, sizeof (struct nlist), symfile); 721634Shenry #ifdef FLEXNAMES 722634Shenry sp->s_name = name; /* restore pointer */ 723600Sbill #endif FLEXNAMES 724600Sbill } 725600Sbill if (symsout != symsdesired) 726600Sbill yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n", 727600Sbill symsout, symsdesired); 728600Sbill #ifdef FLEXNAMES 729600Sbill /* 730600Sbill * Pass 2 through the string pool 731600Sbill */ 732600Sbill symsout = 0; 7335828Srrh bwrite((char *)&stroff, sizeof (stroff), symfile); 734600Sbill stroff = sizeof (stroff); 735600Sbill symsout = 0; 736600Sbill DECLITERATE(allocwalk, sp, ub) 737600Sbill { 738634Shenry if (sp->s_tag >= IGNOREBOUND) 739600Sbill continue; 740634Shenry if ((sp->s_name[0] == 'L') && (sp->s_tag == LABELID) && !savelabels) 741600Sbill continue; 742634Shenry sp->s_index = strlen(sp->s_name); 743634Shenry if (sp->s_index) 744634Shenry bwrite(sp->s_name, sp->s_index + 1, symfile); 745600Sbill } 746600Sbill #endif FLEXNAMES 747600Sbill } 748