1: /* 2: * U N I X 2 . 9 B S D C R A S H A N A L Y Z E R 3: * 4: * S Y M B O L R O U T I N E S 5: */ 6: 7: #include <sys/param.h> 8: #include <sys/ioctl.h> 9: #include <stdio.h> 10: #include <a.out.h> 11: #include "crash.h" 12: 13: #define MAXDIFF 2048L 14: #define SPACE 100 15: 16: /* Global Variables */ 17: int kmem; /* Global FD of dump file */ 18: int sym; /* global fd for symbol file */ 19: 20: unsigned find(), findv(); 21: char *malloc(); 22: 23: /* 24: * G E T S Y M 25: * 26: * 27: * getsym John Stewart 2 Mar 83 28: * takes: symref--string naming file with symbol table 29: * returns: void 30: * it does: loads symtab from symref file 31: * loads ovh 32: * sets globals symtab 33: * messy side effects: loads ovh 34: */ 35: /* 36: * Define symbol table globals here: 37: */ 38: struct symsml *symtab, *maxsym; 39: daddr_t symbas; 40: daddr_t txtbas; 41: unsigned nsyms; 42: struct ovlhdr ovh; /* not really used */ 43: extern int overlay; 44: 45: getsym(symref) 46: char *symref; 47: { 48: long n; 49: register int m; 50: struct syment space[SPACE]; 51: register struct syment *symp; 52: struct symsml *smlp; 53: struct exec xbuf; 54: 55: sym = open(symref,0); 56: if (sym < 0) { 57: printf("Unable to open %s\n",symref); 58: exit(1); 59: } 60: 61: /* 62: * Load the Symbol Table into Core 63: */ 64: symbas = 0L; 65: read(sym, &xbuf, sizeof xbuf); 66: /*printf("read syms %04x\n", xbuf.a_syms);/**/ 67: if (N_BADMAG(xbuf)) { 68: printf("Format error in %s\n",symref); 69: exit(1); 70: } 71: symbas += xbuf.a_text + (long) xbuf.a_data; 72: if (xbuf.a_magic == A_MAGIC5 || xbuf.a_magic == A_MAGIC6) { 73: overlay++; 74: read(sym, &ovh, sizeof (struct ovlhdr)); 75: for(m=0; m<NOVL; m++) { 76: symbas += (long) ovh.ov_siz[m]; 77: } 78: symbas += (long) sizeof ovh; 79: } 80: if (xbuf.a_flag != 1) { 81: symbas *= 2L; 82: } 83: symbas += (long) sizeof xbuf; 84: if (overlay) 85: txtbas = ((((long)xbuf.a_text)+8192L-1L)/8192L)*8192L; 86: lseek(sym, symbas, 0); 87: n = 0; 88: ioctl(sym, FIONREAD, (char *)&n); 89: if (n == 0) { 90: printf("No namelist in %s\n",symref); 91: exit(1); 92: } 93: nsyms = n/sizeof(struct syment); /* number of symbols in table */ 94: m = nsyms * sizeof(struct symsml); /* small table size needed */ 95: symtab = (struct symsml *) malloc(m); 96: if (symtab == (struct symsml *)NULL) { 97: printf("Symbol table too large\n"); 98: exit(1); 99: } 100: /*printf("calc syms %08X nsyms %04x m %04x\n", n, nsyms, m);/**/ 101: smlp = symtab; 102: while (n) { 103: m = sizeof space; 104: if (n < m) 105: m = n; 106: read(sym, (caddr_t)space, m); 107: n -= m; 108: for (symp = space; (m -= sizeof(struct syment)) >= 0;symp++) { 109: /*printf("\t%8s %4x %d\n", symp->name, symp->value, symp->ovno);/**/ 110: smlp->svalue = symp->value; 111: smlp->sovno = symp->ovno; 112: if (symp->flags >= 041 || (symp->flags >= 01 && 113: symp->flags <= 04)) 114: if ((symp->flags & 07) == 02) 115: smlp->sflags = ISYM; 116: else 117: smlp->sflags = DSYM; 118: else 119: smlp->sflags = NSYM; 120: smlp++; 121: } 122: } 123: maxsym = smlp; 124: } 125: 126: /* 127: * S Y M B O L 128: * 129: * 130: * symbol mark kampe 11/17/75 131: * takes: int (an address) 132: * int (the type of symbol you want found TEXT or DATA) 133: * returns: int (address of symbol table entry) 134: * it does: find the global text symbol whose 135: * value is the nearest less than or equal to the 136: * passed address. It then prints out a field 137: * of the form (<symbol>+<offset>). 138: * No value is now returned. (Formerly, 139: * the value returned was the address of 140: * the symbol table entry for that symbol.) 141: */ 142: symbol(val, type, ovno) 143: unsigned val; 144: char type; 145: int ovno; 146: { 147: register struct symsml *i, *minptr; 148: struct syment symt; 149: long mindif, offset, value, symval; 150: int ov = 0; 151: 152: mindif = 0377777L; 153: minptr = (struct symsml *) NULL; 154: if (txtbas && type == ISYM && val > txtbas) 155: ov = ovno; 156: 157: /* Find closest preceeding global symbol */ 158: i = symtab; 159: value = val; 160: while (mindif && i < maxsym) { 161: if (type == i->sflags && (!ov || ov == i->sovno)) { 162: symval = (long)(unsigned) i->svalue; 163: if (((value - symval) < mindif) && (value >= symval)) { 164: mindif = value - symval; 165: minptr = i; 166: } 167: } 168: i++; 169: } 170: 171: if (minptr && mindif < MAXDIFF) { 172: offset = (long)((unsigned) (minptr - symtab)); 173: offset = symbas + offset*sizeof(struct syment); 174: lseek(sym, offset, 0); 175: read(sym, &symt, sizeof(struct syment)); 176: if (mindif) 177: printf("%.8s+0%o", symt.name, (unsigned) mindif); 178: else 179: printf("%-8.8s", symt.name); 180: if (overlay && minptr->sovno && type == ISYM) 181: printf(",kov=%d",minptr->sovno); 182: return(1); 183: } 184: return(0); 185: } 186: 187: /* 188: * F E T C H 189: * 190: * This routine takes a structure of 'fetch' format, 191: * and reads from the core dump file each specified variable 192: * into the given core address. This provides a simple method 193: * of loading our prototype data areas. 194: * Mike Muuss, 6/28/77. 195: */ 196: 197: fetch( table ) 198: register struct fetch *table; 199: { 200: 201: while( table -> f_size ) { 202: if (vf(table->symbol, table->addr, table->f_size ) == 0) { 203: printf("\nCould not find: "); 204: barf(table->symbol); 205: } 206: table++; 207: } 208: } 209: 210: /* 211: * F E T C H A 212: * 213: * This routine is like fetch, except that only addresses are 214: * stuffed 215: */ 216: fetcha( table ) 217: register struct fetch *table; 218: { 219: 220: while( table -> f_size ) { 221: if ((*((unsigned *)table->addr) 222: = (unsigned) find(table->symbol, 1)) == NOTFOUND) { 223: printf("\nCould not find: "); 224: barf(table->symbol); 225: } 226: table++; 227: } 228: } 229: 230: 231: /* 232: * V F 233: * 234: * 235: * Variable Fetch -- Fetch the named symbol, and load it from the dump 236: * returns: 1 if successful, 0 if not 237: */ 238: 239: int vf( name, addr, size ) 240: register char *name; 241: char *addr; 242: { 243: unsigned pos; /* Kernel addr */ 244: 245: /* position ourselves in the file */ 246: if ((pos=findv(name, 1))==NOTFOUND) { 247: return(0); 248: } 249: lseek(kmem, (long) pos, 0); 250: 251: /* Perform the actual transfer */ 252: if (read(kmem, addr, size) == size) 253: return(1); 254: printf( "\n\t***WARNING: unsuccessful read of variable %s\n", name); 255: return(0); 256: } 257: 258: 259: /* 260: * F I N D V 261: * 262: * 263: * Look up the address of the given global variable in 264: * the symbol table 265: * takes: string containing symbol 266: * returns: value of symbol, if found 267: * 0177777, if not found. 268: */ 269: 270: unsigned findv( string, global ) 271: char *string; 272: register global; 273: { 274: struct syment *i, space[SPACE]; 275: register unsigned n; 276: register int m; 277: 278: n = nsyms * sizeof(struct syment); 279: lseek(sym, symbas, 0); 280: while(n) { 281: m = sizeof space; 282: if (n < m) 283: m = n; 284: read(sym, (caddr_t)space, m); 285: n -= m; 286: for (i = space; (m -= sizeof(struct syment)) >= 0; i++) { 287: if( (global && ((i->flags & 077)) < 041)) continue; 288: if( equal( string, i->name ) ) { 289: return( i->value ); 290: } 291: } 292: } 293: 294: return(NOTFOUND); 295: } 296: 297: unsigned find(string, global) 298: char *string; 299: int global; 300: { 301: register unsigned val; 302: 303: if ((val=findv(string, global))!=NOTFOUND) 304: return(val); 305: printf("\nCould not find: "); 306: barf( string ); 307: /*NOTREACHED*/ 308: } 309: 310: /* 311: * Obtain the ova and ovd arrays 312: */ 313: 314: u_long aova, aovd; /* addresses of ova and ovd in core */ 315: unsigned ova[8], ovd[8]; /* overlay addresses and sizes */ 316: 317: getpars() 318: { 319: lseek(kmem, (off_t)aova, 0); /* position of the ova */ 320: read(kmem, ova, sizeof ova); /* read it in */ 321: lseek(kmem, (off_t)aovd, 0); /* position of the ovd */ 322: read(kmem, ovd, sizeof ovd); /* read it in too */ 323: }