1: #ifndef lint 2: static char sccsid[] = "@(#)nm.c 4.7 5/19/86"; 3: #endif 4: /* 5: * nm - print name list; VAX string table version 6: */ 7: #include <sys/types.h> 8: #include <ar.h> 9: #include <stdio.h> 10: #include <ctype.h> 11: #include <a.out.h> 12: #include <stab.h> 13: #include <sys/stat.h> 14: 15: #define SELECT archive ? archdr.ar_name : *xargv 16: 17: int aflg, gflg, nflg, oflg, pflg, uflg; 18: int rflg = 1; 19: char **xargv; 20: int archive; 21: struct ar_hdr archdr; 22: union { 23: char mag_armag[SARMAG+1]; 24: struct exec mag_exp; 25: } mag_un; 26: #define OARMAG 0177545 27: FILE *fi; 28: off_t off; 29: off_t ftell(); 30: char *malloc(); 31: char *realloc(); 32: char *strp; 33: char *stab(); 34: off_t strsiz; 35: int compare(); 36: int narg; 37: int errs; 38: 39: main(argc, argv) 40: char **argv; 41: { 42: 43: if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) { 44: argv++; 45: while (*++*argv) switch (**argv) { 46: 47: case 'n': 48: nflg++; 49: continue; 50: case 'g': 51: gflg++; 52: continue; 53: case 'u': 54: uflg++; 55: continue; 56: case 'r': 57: rflg = -1; 58: continue; 59: case 'p': 60: pflg++; 61: continue; 62: case 'o': 63: oflg++; 64: continue; 65: case 'a': 66: aflg++; 67: continue; 68: default: 69: fprintf(stderr, "nm: invalid argument -%c\n", 70: *argv[0]); 71: exit(2); 72: } 73: argc--; 74: } 75: if (argc == 0) { 76: argc = 1; 77: argv[1] = "a.out"; 78: } 79: narg = argc; 80: xargv = argv; 81: while (argc--) { 82: ++xargv; 83: namelist(); 84: } 85: exit(errs); 86: } 87: 88: namelist() 89: { 90: register int j; 91: 92: archive = 0; 93: fi = fopen(*xargv, "r"); 94: if (fi == NULL) { 95: error(0, "cannot open"); 96: return; 97: } 98: off = SARMAG; 99: fread((char *)&mag_un, 1, sizeof(mag_un), fi); 100: if (mag_un.mag_exp.a_magic == OARMAG) { 101: error(0, "old archive"); 102: goto out; 103: } 104: if (strncmp(mag_un.mag_armag, ARMAG, SARMAG)==0) 105: archive++; 106: else if (N_BADMAG(mag_un.mag_exp)) { 107: error(0, "bad format"); 108: goto out; 109: } 110: fseek(fi, 0L, 0); 111: if (archive) { 112: nextel(fi); 113: if (narg > 1) 114: printf("\n%s:\n", *xargv); 115: } 116: do { 117: off_t o; 118: register i, n, c; 119: struct nlist *symp = NULL; 120: struct nlist sym; 121: struct stat stb; 122: 123: fread((char *)&mag_un.mag_exp, 1, sizeof(struct exec), fi); 124: if (N_BADMAG(mag_un.mag_exp)) 125: continue; 126: if (archive == 0) 127: fstat(fileno(fi), &stb); 128: o = N_SYMOFF(mag_un.mag_exp) - sizeof (struct exec); 129: fseek(fi, o, 1); 130: n = mag_un.mag_exp.a_syms / sizeof(struct nlist); 131: if (n == 0) { 132: error(0, "no name list"); 133: continue; 134: } 135: if (N_STROFF(mag_un.mag_exp) + sizeof (off_t) > 136: (archive ? off : stb.st_size)) { 137: error(0, "old format .o (no string table) or truncated file"); 138: continue; 139: } 140: i = 0; 141: if (strp) 142: free(strp), strp = 0; 143: while (--n >= 0) { 144: fread((char *)&sym, 1, sizeof(sym), fi); 145: if (gflg && (sym.n_type&N_EXT)==0) 146: continue; 147: if ((sym.n_type&N_STAB) && (!aflg||gflg||uflg)) 148: continue; 149: if (symp==NULL) 150: symp = (struct nlist *) 151: malloc(sizeof(struct nlist)); 152: else 153: symp = (struct nlist *) 154: realloc(symp, 155: (i+1)*sizeof(struct nlist)); 156: if (symp == NULL) 157: error(1, "out of memory"); 158: symp[i++] = sym; 159: } 160: if (archive && ftell(fi)+sizeof(off_t) >= off) { 161: error(0, "no string table (old format .o?)"); 162: continue; 163: } 164: if (fread((char *)&strsiz,sizeof(strsiz),1,fi) != 1) { 165: error(0, "no string table (old format .o?)"); 166: goto out; 167: } 168: strp = (char *)malloc(strsiz); 169: if (strp == NULL) 170: error(1, "ran out of memory"); 171: if (fread(strp+sizeof(strsiz),strsiz-sizeof(strsiz),1,fi) != 1) 172: error(1, "error reading string table"); 173: for (j = 0; j < i; j++) 174: if (symp[j].n_un.n_strx) 175: symp[j].n_un.n_name = 176: symp[j].n_un.n_strx + strp; 177: else 178: symp[j].n_un.n_name = ""; 179: if (pflg==0) 180: qsort(symp, i, sizeof(struct nlist), compare); 181: if ((archive || narg>1) && oflg==0) 182: printf("\n%s:\n", SELECT); 183: psyms(symp, i); 184: if (symp) 185: free((char *)symp), symp = 0; 186: if (strp) 187: free((char *)strp), strp = 0; 188: } while(archive && nextel(fi)); 189: out: 190: fclose(fi); 191: } 192: 193: psyms(symp, nsyms) 194: register struct nlist *symp; 195: int nsyms; 196: { 197: register int n, c; 198: 199: for (n=0; n<nsyms; n++) { 200: c = symp[n].n_type; 201: if (c & N_STAB) { 202: if (oflg) { 203: if (archive) 204: printf("%s:", *xargv); 205: printf("%s:", SELECT); 206: } 207: printf("%08x - %02x %04x %5.5s %s\n", 208: symp[n].n_value, 209: symp[n].n_other & 0xff, symp[n].n_desc & 0xffff, 210: stab(symp[n].n_type & 0xff), 211: symp[n].n_un.n_name); 212: continue; 213: } 214: if (c == N_FN) 215: c = 'f'; 216: else switch (c&N_TYPE) { 217: 218: case N_UNDF: 219: c = 'u'; 220: if (symp[n].n_value) 221: c = 'c'; 222: break; 223: case N_ABS: 224: c = 'a'; 225: break; 226: case N_TEXT: 227: c = 't'; 228: break; 229: case N_DATA: 230: c = 'd'; 231: break; 232: case N_BSS: 233: c = 'b'; 234: break; 235: default: 236: c = '?'; 237: break; 238: } 239: if (uflg && c!='u') 240: continue; 241: if (oflg) { 242: if (archive) 243: printf("%s:", *xargv); 244: printf("%s:", SELECT); 245: } 246: if (symp[n].n_type&N_EXT) 247: c = toupper(c); 248: if (!uflg) { 249: if (c=='u' || c=='U') 250: printf(" "); 251: else 252: printf(N_FORMAT, symp[n].n_value); 253: printf(" %c ", c); 254: } 255: printf("%s\n", symp[n].n_un.n_name); 256: l1: ; 257: } 258: } 259: 260: compare(p1, p2) 261: struct nlist *p1, *p2; 262: { 263: register i; 264: 265: if (nflg) { 266: if (p1->n_value > p2->n_value) 267: return(rflg); 268: if (p1->n_value < p2->n_value) 269: return(-rflg); 270: } 271: return (rflg * strcmp(p1->n_un.n_name, p2->n_un.n_name)); 272: } 273: 274: nextel(af) 275: FILE *af; 276: { 277: register char *cp; 278: register r; 279: long arsize; 280: 281: fseek(af, off, 0); 282: r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af); 283: if (r != sizeof(struct ar_hdr)) 284: return(0); 285: for (cp = archdr.ar_name; cp < &archdr.ar_name[sizeof(archdr.ar_name)]; cp++) 286: if (*cp == ' ') 287: *cp = '\0'; 288: arsize = atol(archdr.ar_size); 289: if (arsize & 1) 290: ++arsize; 291: off = ftell(af) + arsize; /* beginning of next element */ 292: return(1); 293: } 294: 295: error(n, s) 296: char *s; 297: { 298: fprintf(stderr, "nm: %s:", *xargv); 299: if (archive) { 300: fprintf(stderr, "(%s)", archdr.ar_name); 301: fprintf(stderr, ": "); 302: } else 303: fprintf(stderr, " "); 304: fprintf(stderr, "%s\n", s); 305: if (n) 306: exit(2); 307: errs = 1; 308: } 309: 310: struct stabnames { 311: int st_value; 312: char *st_name; 313: } stabnames[] ={ 314: N_GSYM, "GSYM", 315: N_FNAME, "FNAME", 316: N_FUN, "FUN", 317: N_STSYM, "STSYM", 318: N_LCSYM, "LCSYM", 319: N_RSYM, "RSYM", 320: N_SLINE, "SLINE", 321: N_SSYM, "SSYM", 322: N_SO, "SO", 323: N_LSYM, "LSYM", 324: N_SOL, "SOL", 325: N_PSYM, "PSYM", 326: N_ENTRY, "ENTRY", 327: N_LBRAC, "LBRAC", 328: N_RBRAC, "RBRAC", 329: N_BCOMM, "BCOMM", 330: N_ECOMM, "ECOMM", 331: N_ECOML, "ECOML", 332: N_LENG, "LENG", 333: N_PC, "PC", 334: 0, 0 335: }; 336: 337: char * 338: stab(val) 339: { 340: register struct stabnames *sp; 341: static char prbuf[32]; 342: 343: for (sp = stabnames; sp->st_name; sp++) 344: if (sp->st_value == val) 345: return (sp->st_name); 346: sprintf(prbuf, "%02x", val); 347: return (prbuf); 348: }