1: #include <stdio.h> 2: #include "defs.h" 3: #include <fcntl.h> 4: #include <sys/file.h> 5: 6: struct SYMbol *symbol; 7: char localok; 8: int lastframe; 9: u_int maxoff; 10: long maxstor; 11: MAP txtmap; 12: char curov; 13: int overlay; 14: long localval; 15: char *errflg; 16: u_int findsym(); 17: 18: struct SYMcache 19: { 20: char *name; 21: int used; 22: struct SYMbol *syment; 23: }; 24: 25: #ifndef NUM_SYMS_CACHE 26: #define NUM_SYMS_CACHE 50 27: #endif 28: 29: static struct SYMcache symcache[NUM_SYMS_CACHE]; 30: static struct SYMcache *endcache = &symcache[NUM_SYMS_CACHE]; 31: static struct SYMbol *symtab; 32: static FILE *strfp; 33: static int symcnt; 34: static int symnum; 35: static char *sgets(); 36: 37: extern char *myname, *symfil, *strdup(); 38: extern off_t symoff, stroff; 39: 40: /* symbol table and file handling service routines */ 41: 42: valpr(v,idsp) 43: { 44: u_int d; 45: 46: d = findsym(v,idsp); 47: IF d < maxoff 48: THEN printf("%s", cache_sym(symbol)); 49: IF d 50: THEN printf(OFFMODE, d); 51: FI 52: FI 53: } 54: 55: localsym(cframe) 56: long cframe; 57: { 58: int symflg; 59: 60: WHILE symget() && localok && (symflg= (int)symbol->type) != N_FN 61: && *no_cache_sym(symbol) != '~' 62: DO IF symflg>=2 ANDF symflg<=4 63: THEN localval=symbol->value; 64: return(TRUE); 65: ELIF symflg==1 66: THEN localval=leng(shorten(cframe)+symbol->value); 67: return(TRUE); 68: ELIF symflg==20 ANDF lastframe 69: THEN localval=leng(lastframe+2*symbol->value - (overlay?12:10)); 70: return(TRUE); 71: FI 72: OD 73: return(FALSE); 74: } 75: 76: psymoff(v,type,s) 77: long v; 78: int type; 79: char *s; 80: { 81: u_int w; 82: 83: w = findsym(shorten(v),type); 84: IF w >= maxoff 85: THEN printf(LPRMODE,v); 86: ELSE printf("%s", cache_sym(symbol)); 87: IF w THEN printf(OFFMODE,w); FI 88: FI 89: printf(s); 90: } 91: 92: u_int 93: findsym(svalue,type) 94: u_int svalue; 95: int type; 96: { 97: long diff, value, symval; 98: register struct SYMbol *sp; 99: struct SYMbol *symsav; 100: int i; 101: char ov = 0; 102: 103: if (txtmap.bo && type==ISYM && svalue>=txtmap.bo) 104: ov=curov; 105: value = svalue; 106: diff = 0377777L; 107: 108: if (type != NSYM && symnum) 109: { 110: for (i = 0, sp = symtab; diff && i < symnum; i++, sp++) 111: { 112: if (SYMTYPE(sp->type) == type && 113: (!ov || ov == sp->ovno)) 114: { 115: symval = leng(sp->value); 116: if ((value - symval) < diff && 117: value >= symval) 118: { 119: diff = value - symval; 120: symsav = sp; 121: } 122: } 123: } 124: } 125: if (symsav) 126: symcnt = symsav - symtab; 127: symbol = symsav; 128: return(shorten(diff)); 129: } 130: 131: /* sequential search through table */ 132: symset() 133: { 134: 135: symcnt = -1; 136: } 137: 138: struct SYMbol * 139: symget() 140: { 141: 142: if (symcnt >= symnum || !symnum) 143: return(NULL); 144: symcnt++; 145: symbol = &symtab[symcnt]; 146: return(symbol); 147: } 148: 149: /* 150: * This only _looks_ expensive ;-) The extra scan over the symbol 151: * table allows us to cut down the amount of memory needed. This is 152: * where symbols with string table offsets over 64kb are excluded. Also, 153: * a late addition to the program excludes register symbols - the assembler 154: * generates *lots* of them and they're useless to us. 155: */ 156: symINI(ex) 157: struct exec *ex; 158: { 159: register struct SYMbol *sp; 160: register FILE *fp; 161: struct nlist sym; 162: int i, nused, globals_only = 0; 163: 164: fp = fopen(symfil, "r"); 165: strfp = fp; 166: if (!fp) 167: return; 168: fcntl(fileno(fp), F_SETFD, 1); 169: 170: symnum = ex->a_syms / sizeof (sym); 171: 172: fseek(fp, symoff, L_SET); 173: nused = 0; 174: for (i = 0; i < symnum; i++) 175: { 176: fread(&sym, sizeof (sym), 1, fp); 177: if (sym.n_type == N_REG) 178: continue; 179: if (sym.n_un.n_strx >= 0200000L) 180: printf("symbol %d string offset > 64k - ignored\n",i); 181: else 182: nused++; 183: } 184: fseek(fp, symoff, L_SET); 185: 186: symtab = (struct SYMbol *)malloc(nused * sizeof (struct SYMbol)); 187: if (!symtab) 188: { 189: globals_only = 1; 190: nused = 0; 191: for (symcnt = 0; symcnt < symnum; symcnt++) 192: { 193: fread(&sym, 1, sizeof (sym), fp); 194: if (sym.n_type == N_REG) 195: continue; 196: if ((sym.n_type & N_EXT) == 0) 197: continue; 198: if (sym.n_un.n_strx >= 0200000L) 199: continue; 200: nused++; 201: } 202: symtab = (struct SYMbol *)malloc(nused * sizeof(struct SYMbol)); 203: if (!symtab) 204: { 205: printf("%s: no memory for symbols\n", myname); 206: symnum = 0; 207: return; 208: } 209: } 210: fseek(fp, symoff, L_SET); 211: sp = symtab; 212: for (symcnt = 0; symcnt < symnum; symcnt++) 213: { 214: fread(&sym, 1, sizeof (sym), fp); 215: if (sym.n_type == N_REG) 216: continue; 217: if (globals_only && !(sym.n_type & N_EXT)) 218: continue; 219: if (sym.n_un.n_strx >= 0200000L) 220: continue; 221: sp->value = sym.n_value; 222: sp->ovno = sym.n_ovly; 223: sp->type = sym.n_type; 224: sp->soff = shorten(sym.n_un.n_strx); 225: sp++; 226: } 227: symnum = nused; 228: #ifdef debug 229: printf("%d symbols loaded\n", nused); 230: #endif 231: if (globals_only) 232: printf("%s: could only do global symbols\n", myname); 233: symset(); 234: return(0); 235: } 236: 237: /* 238: * Look in the cache for a symbol in memory. If it is not found use 239: * the least recently used entry in the cache and update it with the 240: * symbol name. 241: */ 242: char * 243: cache_sym(symp) 244: register struct SYMbol *symp; 245: { 246: register struct SYMcache *sc = symcache; 247: struct SYMcache *current; 248: int lru; 249: 250: if (!symp) 251: return("?"); 252: for (current = NULL, lru = 30000 ; sc < endcache; sc++) 253: { 254: if (sc->syment == symp) 255: { 256: sc->used++; 257: if (sc->used >= 30000) 258: sc->used = 10000; 259: return(sc->name); 260: } 261: if (sc->used < lru) 262: { 263: lru = sc->used; 264: current = sc; 265: } 266: } 267: sc = current; 268: if (sc->name) 269: free(sc->name); 270: sc->used = 1; 271: sc->syment = symp; 272: sc->name = strdup(sgets(symp->soff)); 273: return(sc->name); 274: } 275: 276: /* 277: * We take a look in the cache but do not update the cache on a miss. 278: * This is done when scanning thru the symbol table (printing all externals 279: * for example) for large numbers of symbols which probably won't be 280: * used again any time soon. 281: */ 282: char * 283: no_cache_sym(symp) 284: register struct SYMbol *symp; 285: { 286: register struct SYMcache *sc = symcache; 287: 288: if (!symp) 289: return("?"); 290: for ( ; sc < endcache; sc++) 291: { 292: if (sc == symp) 293: { 294: sc->used++; 295: if (sc->used >= 30000) 296: sc->used = 10000; 297: return(sc->name); 298: } 299: } 300: return(sgets(symp->soff)); 301: } 302: 303: /* 304: * Looks in the cache for a match by string value rather than string 305: * file offset. 306: */ 307: 308: struct SYMbol * 309: cache_by_string(str, ovsym) 310: char *str; 311: int ovsym; 312: { 313: register struct SYMcache *sc; 314: 315: for (sc = symcache; sc < endcache; sc++) 316: { 317: if (!sc->name) 318: continue; 319: if (eqsym(sc->name, str, ovsym ? '~' : '_')) 320: break; 321: } 322: if (sc < endcache) 323: { 324: sc->used++; 325: if (sc->used > 30000) 326: sc->used = 10000; 327: return(sc->syment); 328: } 329: return(0); 330: } 331: 332: static char * 333: sgets(soff) 334: u_short soff; 335: { 336: static char symname[MAXSYMLEN + 2]; 337: register char *buf = symname; 338: int c; 339: register int i; 340: 341: fseek(strfp, stroff + soff, L_SET); 342: for (i = 0; i < MAXSYMLEN; i++) 343: { 344: c = getc(strfp); 345: *buf++ = c; 346: if (c == '\0') 347: break; 348: } 349: *buf = '\0'; 350: return(symname); 351: }