|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)sym.c 1.1 86/02/03 Copyr 1984 Sun Micro"; ! 3: #endif ! 4: ! 5: /* ! 6: * Copyright (c) 1984 by Sun Microsystems, Inc. ! 7: */ ! 8: ! 9: #include <a.out.h> ! 10: #include "as.h" ! 11: #include "scan.h" ! 12: ! 13: /* Allocation increments for symbol buckets and character blocks */ ! 14: #define SYM_INCR 50 ! 15: #define CBLOCK_INCR 512 ! 16: ! 17: extern struct stab_sym_bkt *stabkt_head; ! 18: ! 19: struct sym_bkt *last_symbol; /* last symbol defined */ ! 20: struct sym_bkt *sym_hash_tab[HASH_MAX]; /* Symbol hash table */ ! 21: struct sym_bkt *sym_free = NULL; /* head of free list */ ! 22: char *cblock = NULL; /* storage for symbol names */ ! 23: int ccnt = 0; /* number of chars left in c block */ ! 24: int ntlabels = 0; ! 25: ! 26: /* grab a new symbol bucket off of the free list; allocate space ! 27: * for a new free list if necessary ! 28: */ ! 29: struct sym_bkt * ! 30: gsbkt() ! 31: { register struct sym_bkt *sbp; ! 32: register int i; ! 33: ! 34: if ((sbp = sym_free) != NULL) sym_free = sbp->next_s; ! 35: else { ! 36: sbp = (struct sym_bkt *)calloc(SYM_INCR,sizeof(struct sym_bkt)); ! 37: if (sbp == NULL) sys_error("Symbol storage exceeded\n",0); ! 38: for (i = SYM_INCR-1; i--;) { ! 39: sbp->next_s = sym_free; ! 40: sym_free = sbp++; ! 41: } ! 42: } ! 43: ! 44: return(sbp); ! 45: } ! 46: ! 47: /* initialize hash table */ ! 48: sym_init() ! 49: { register int i; ! 50: ! 51: for (i=0; i<HASH_MAX; i++) sym_hash_tab[i] = NULL; ! 52: } /* end Sym_Init */ ! 53: ! 54: char *sstring(string) ! 55: register char *string; ! 56: { register char *p,*q; /* working char string */ ! 57: register int i; ! 58: ! 59: i = strlen(string); /* get length of string */ ! 60: ! 61: if (++i > ccnt) { /* if not enough room get more */ ! 62: if ((cblock = (char *)calloc(CBLOCK_INCR,1)) == NULL) ! 63: sys_error("Symbol storage exceeded\n",0); ! 64: ccnt = CBLOCK_INCR; ! 65: } ! 66: ! 67: p = q = cblock; /* copy string into permanent storage */ ! 68: while (*p++ = *string++); ! 69: cblock = p; ! 70: ccnt -= i; ! 71: return(q); ! 72: } /* end sstring */ ! 73: ! 74: /* lookup symbol in symbol table */ ! 75: struct sym_bkt * ! 76: lookup(s) ! 77: register char *s; ! 78: { register struct sym_bkt *sbp; /* general purpose ptr */ ! 79: register int Save; /* save subscript in sym_hash_tab */ ! 80: register char *p; ! 81: static char local[250]; /* used for constructing local sym */ ! 82: extern char *ll_format; ! 83: ! 84: if (*s>='0' && *s<='9') { /* local symbol hackery */ ! 85: /* we hope no-one uses really long local symbols */ ! 86: p = local; ! 87: while ((*p++ = *s++) && (p < &local[sizeof local-1]));/* copy local symbol */ ! 88: p--; ! 89: s = last_symbol->name_s; /* add last symbol defined as suffix */ ! 90: while ((*p++ = *s++) && (p < &local[sizeof local-1])); ! 91: s = local; /* this becomes name to deal with */ ! 92: } ! 93: ! 94: /* if the symbol is already in here, return a ptr to it */ ! 95: for (sbp = sym_hash_tab[Save=hash(s)]; sbp != NULL ; sbp = sbp->next_s) ! 96: if (strcmp(sbp->name_s,s) == 0) return(sbp); ! 97: ! 98: /* Since it's not, make a bucket for it, and put the bucket in the symbol table */ ! 99: sbp = gsbkt(); /* get the bucket */ ! 100: sbp->name_s = sstring(s); /* Store it's name */ ! 101: sbp->value_s = sbp->id_s = sbp->attr_s = 0; ! 102: sbp->csect_s = C_UNDEF; ! 103: sbp->next_s = sym_hash_tab[Save]; /* and insert on top of list */ ! 104: if (s == local || *s == *ll_format) sbp->attr_s |= S_LOCAL; ! 105: return(sym_hash_tab[Save] = sbp); ! 106: } ! 107: ! 108: /* Sym_Fix - Assigns index numbers to the symbols. Also performs ! 109: relocation of the symbols assuming data segment follows ! 110: text and bss follows the data. If global flag, make all ! 111: undefined symbols defined to be externals. ! 112: */ ! 113: ! 114: /* symbol value compare -- for sorting */ ! 115: static int ! 116: symvc( a, b ) ! 117: struct sym_bkt **a, **b; ! 118: { ! 119: return ((*a)->value_s - (*b)->value_s); ! 120: } ! 121: ! 122: sym_fix() ! 123: { ! 124: register struct sym_bkt **sbp1, *sbp2; ! 125: int i = 0; ! 126: register int t; ! 127: struct sym_bkt **symlistlist; ! 128: register struct sym_bkt **syml; ! 129: ! 130: symlistlist = syml = (struct sym_bkt **)calloc( ntlabels, sizeof *symlistlist ); ! 131: for (sbp1 = sym_hash_tab; sbp1 < &sym_hash_tab[HASH_MAX]; sbp1++) ! 132: for (sbp2 = *sbp1; sbp2; sbp2 = sbp2->next_s) { ! 133: if ((sbp2->attr_s & (S_DEC|S_DEF)) == 0) { ! 134: sbp2->attr_s |= S_EXT | S_DEC; ! 135: sbp2->csect_s = C_UNDEF; ! 136: } ! 137: switch (sbp2->csect_s) { ! 138: case C_TEXT: ! 139: if (sbp2 != dot_bkt && !(sbp2->attr_s & S_PERM)) ! 140: *syml++ = sbp2; ! 141: break; ! 142: case C_DATA: ! 143: sbp2->value_s += tsize; break; ! 144: case C_DATA1: ! 145: sbp2->value_s += tsize + dsize; break; ! 146: case C_DATA2: ! 147: sbp2->value_s += tsize + dsize + d1size; break; ! 148: case C_BSS: ! 149: sbp2->value_s += tsize + dsize + d1size + d2size; break; ! 150: } ! 151: if (sbp2==dot_bkt || sbp2->attr_s & (S_REG|S_LOCAL|S_PERM)) ! 152: sbp2->id_s = -1; ! 153: else ! 154: sbp2->id_s = i++; ! 155: } ! 156: /* consistancy check */ ! 157: if (syml - symlistlist != ntlabels) ! 158: sys_error("wrong number of text labels: %d found\n", syml-symlistlist); ! 159: /* sort C_TEXT symbols on value */ ! 160: qsort( symlistlist, ntlabels, sizeof *symlistlist, symvc ); ! 161: /* and go update those labels using the sdi information */ ! 162: sdi_sym_update( symlistlist, ntlabels ); ! 163: free( symlistlist ); ! 164: } ! 165: ! 166: ! 167: /* sym_write - Write out the symbols to the specified ! 168: file in b.out format, while computing size ! 169: of the symbol segment in output file. ! 170: */ ! 171: ! 172: redosyms() ! 173: { ! 174: /* Go through the symbol table and get rid of "L" syms if ! 175: we are supposed to. */ ! 176: long size = 0; ! 177: register struct sym_bkt **sbp1, *sbp2; ! 178: ! 179: for (sbp1 = sym_hash_tab; sbp1 < &sym_hash_tab[HASH_MAX]; sbp1++) ! 180: if (sbp2 = *sbp1) ! 181: for (; sbp2; sbp2 = sbp2->next_s) ! 182: { ! 183: if (sbp2->id_s != -1 && chkname(sbp2)) { ! 184: sbp2->final = size++; ! 185: } ! 186: } ! 187: } ! 188: ! 189: long sym_write(file) ! 190: FILE *file; ! 191: { register struct sym_bkt **sbp1, *sbp2; ! 192: long size = 0; ! 193: struct nlist s; ! 194: int strcount = 4; ! 195: struct stab_sym_bkt *t; ! 196: ! 197: for (sbp1 = sym_hash_tab; sbp1 < &sym_hash_tab[HASH_MAX]; sbp1++) ! 198: if (sbp2 = *sbp1) for (; sbp2; sbp2 = sbp2->next_s) ! 199: if (sbp2->id_s != -1 && chkname(sbp2)) { ! 200: /* Write out the symbol table using the VAX a.out format */ ! 201: if ((sbp2->attr_s&S_DEF)== 0) { ! 202: s.n_type = N_UNDF; ! 203: if (*(sbp2->name_s) == 'L' ) { ! 204: prog_warning( E_UNDEFINED_L ); /* Undefined L-symbol */ ! 205: } ! 206: } else { ! 207: switch (sbp2->csect_s){ ! 208: case C_TEXT: ! 209: s.n_type = N_TEXT; break; ! 210: case C_UNDEF: ! 211: s.n_type = N_ABS; break; ! 212: case C_BSS: ! 213: s.n_type = N_BSS; break; ! 214: default: ! 215: s.n_type = (rflag)?N_TEXT:N_DATA; break; ! 216: } ! 217: } ! 218: if (sbp2->attr_s & S_EXT) s.n_type |= N_EXT; ! 219: s.n_value = sbp2->value_s; ! 220: /* For right now, just stuff these with 0 */ ! 221: s.n_other = s.n_desc = 0; ! 222: s.n_un.n_strx = strcount; ! 223: strcount += strlen(sbp2->name_s)+1; ! 224: size += sizeof(s); ! 225: fwrite(&s,sizeof(s),1,file); ! 226: } else if (!(sbp2->attr_s & S_DEF)){ ! 227: PROG_ERROR( E_UNDEFINED_L ); ! 228: } ! 229: ! 230: /* This is to write out the .stabs and .stabd symbols onto the */ ! 231: /* a.out file. This is only being written after the regular */ ! 232: /* symbols have been put out (the prior section of the function). */ ! 233: t = stabkt_head; /* obtain head of stabs/stabd symbol table */ ! 234: while (t != NULL) ! 235: { s.n_type = t->type; ! 236: s.n_other = t->other; ! 237: s.n_desc = t->desc; ! 238: s.n_value = t->value; /* zero for testing now */ ! 239: if (t->id) ! 240: { s.n_un.n_strx = strcount; /* assign string offset */ ! 241: strcount += t->id + 1; /* increment str location */ ! 242: } /* in string table. */ ! 243: else s.n_un.n_strx = 0; /* else if no string is */ ! 244: /* present, assign 0. */ ! 245: size += sizeof(s); ! 246: fwrite(&s, sizeof(s), 1, file); ! 247: t = t->next_stab; ! 248: } /* end while */ ! 249: return(size); ! 250: } ! 251: ! 252: long ! 253: str_write(file) ! 254: FILE *file; ! 255: { ! 256: long size = 0; ! 257: long strcount = 4; ! 258: register struct sym_bkt **sbp1, *sbp2; ! 259: struct stab_sym_bkt *t; ! 260: ! 261: ! 262: fwrite(&strcount,sizeof(long),1,file); ! 263: for (sbp1 = sym_hash_tab; sbp1 < &sym_hash_tab[HASH_MAX]; sbp1++) ! 264: if (sbp2 = *sbp1) for (; sbp2; sbp2 = sbp2->next_s) ! 265: if (chkname(sbp2)) ! 266: { ! 267: if (sbp2->id_s != -1) { ! 268: register i; ! 269: strcount += i = strlen(sbp2->name_s)+1; ! 270: fwrite(sbp2->name_s,i,1,file); ! 271: } ! 272: } ! 273: ! 274: /* This is to write out all the symbols (strings) generated by */ ! 275: /* .stabs and .stabd directives. They are being written onto the */ ! 276: /* string table only after all the regular symbol tables have been */ ! 277: /* written out (by the prior section of this function. */ ! 278: t = stabkt_head; /* head of stabs/stabd link list */ ! 279: while (t != NULL) ! 280: { register i; ! 281: if (t->id) ! 282: { strcount += i = t->id + 1; ! 283: fwrite(t->ch,i,1,file); ! 284: } ! 285: t = t->next_stab; ! 286: } /* end while */ ! 287: return(strcount); ! 288: } ! 289: ! 290: chkname(name) ! 291: struct sym_bkt *name; ! 292: { ! 293: extern char o_lflag; ! 294: ! 295: if(o_lflag) return (1); ! 296: if ( *(name->name_s)!='L') return(1); ! 297: if ( (name->attr_s&S_DEF) == 0) return(1); /* don't zap undef L's */ ! 298: return(0); ! 299: } ! 300: ! 301: /* ! 302: * Perm Flags all currently defined symbols as permanent (and therefore ! 303: * ineligible for redefinition. Also prevents them from being output ! 304: * in the object file). ! 305: */ ! 306: perm() ! 307: { register struct sym_bkt **sbp1, *sbp2; ! 308: ! 309: for (sbp1 = sym_hash_tab; sbp1 < &sym_hash_tab[HASH_MAX]; sbp1++) ! 310: for (sbp2 = *sbp1; sbp2; sbp2 = sbp2->next_s) ! 311: sbp2->attr_s |= S_PERM; ! 312: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.