|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1987 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)nm.c 4.8 4/7/87"; ! 9: #endif ! 10: ! 11: /* ! 12: * nm - print name list; VAX string table version ! 13: */ ! 14: ! 15: #include <sys/types.h> ! 16: #include <sys/file.h> ! 17: #include <ar.h> ! 18: #include <stdio.h> ! 19: #include <ctype.h> ! 20: #include <a.out.h> ! 21: #include <stab.h> ! 22: #include <ranlib.h> ! 23: ! 24: #define OARMAG 0177545 /* OLD archive magic number */ ! 25: #define SELECT (archive ? archdr.ar_name : *xargv) ! 26: ! 27: #define YES 1 ! 28: #define NO 0 ! 29: ! 30: #define u_strx n_un.n_strx ! 31: #define u_name n_un.n_name ! 32: ! 33: typedef struct nlist NLIST; ! 34: ! 35: union { /* exec header, or magic string from library */ ! 36: char mag_armag[SARMAG + 1]; ! 37: struct exec mag_exp; ! 38: } mag_un; ! 39: ! 40: struct ar_hdr archdr; /* archive file header structure */ ! 41: FILE *fi; /* input file stream */ ! 42: off_t off; /* offset into file */ ! 43: int aflg, /* print debugger symbols */ ! 44: gflg, /* print only global (external symbols */ ! 45: nflg, /* sort numerically, not alphabetically */ ! 46: oflg, /* prepend element name to each output line */ ! 47: pflg, /* don't sort */ ! 48: rflg = 1, /* how to sort */ ! 49: uflg, /* print only undefined symbols */ ! 50: narg, /* global number of arguments */ ! 51: errs, /* global error flag */ ! 52: archive; /* if file is an archive */ ! 53: char **xargv; /* global pointer to file name */ ! 54: ! 55: main(argc, argv) ! 56: int argc; ! 57: char **argv; ! 58: { ! 59: extern int optind; ! 60: int ch; /* getopts char */ ! 61: ! 62: while ((ch = getopt(argc, argv, "agnopru")) != EOF) ! 63: switch((char)ch) { ! 64: case 'a': ! 65: aflg = YES; ! 66: break; ! 67: case 'g': ! 68: gflg = YES; ! 69: break; ! 70: case 'n': ! 71: nflg = YES; ! 72: break; ! 73: case 'o': ! 74: oflg = YES; ! 75: break; ! 76: case 'p': ! 77: pflg = YES; ! 78: break; ! 79: case 'r': ! 80: rflg = -1; ! 81: break; ! 82: case 'u': ! 83: uflg = YES; ! 84: break; ! 85: case '?': ! 86: default: ! 87: fputs("usage: nm [-agnopru] [file ...]\n", stderr); ! 88: exit(2); ! 89: } ! 90: argc -= optind; ! 91: argv += optind; ! 92: if (!argc) { ! 93: argc = 1; ! 94: argv[0] = "a.out"; ! 95: } ! 96: narg = argc; ! 97: for (xargv = argv; argc--; ++xargv) ! 98: if (fi = fopen(*xargv, "r")) { ! 99: namelist(); ! 100: (void)fclose(fi); ! 101: } ! 102: else ! 103: error(NO, "cannot open"); ! 104: exit(errs); ! 105: } ! 106: ! 107: namelist() ! 108: { ! 109: register NLIST *N, **L; ! 110: register int symcount, nsyms; ! 111: static NLIST *symp, **list; ! 112: static int lastnsyms = -1, ! 113: laststrsiz = -1; ! 114: static char *strp; ! 115: off_t strsiz; ! 116: long lseek(); ! 117: int compare(); ! 118: char *malloc(), *realloc(); ! 119: ! 120: /* ! 121: * read first few bytes, determine if an archive, ! 122: * or executable; if executable, check magic number ! 123: */ ! 124: /*NOSTRICT*/ ! 125: if (!fread((char *)&mag_un, sizeof(mag_un), 1, fi)) { ! 126: error(NO, "unable to read file"); ! 127: return; ! 128: } ! 129: if (mag_un.mag_exp.a_magic == OARMAG) { ! 130: error(NO, "old archive"); ! 131: return; ! 132: } ! 133: if (bcmp(mag_un.mag_armag, ARMAG, SARMAG)) { ! 134: if (N_BADMAG(mag_un.mag_exp)) { ! 135: error(NO, "bad format"); ! 136: return; ! 137: } ! 138: archive = NO; ! 139: rewind(fi); ! 140: } ! 141: else { ! 142: /* ! 143: * if archive, skip first entry ! 144: * if ranlib'd, skip second entry ! 145: */ ! 146: off = SARMAG; /* see nextel() */ ! 147: (void)nextel(); ! 148: if (!strcmp(RANLIBMAG, archdr.ar_name)) ! 149: (void)nextel(); ! 150: if (narg > 1) ! 151: printf("\n%s:\n", *xargv); ! 152: archive = YES; ! 153: } ! 154: ! 155: do { ! 156: /* check for bad magic number */ ! 157: /*NOSTRICT*/ ! 158: if (!fread((char *)&mag_un.mag_exp, sizeof(struct exec), 1, fi)) { ! 159: error(NO, "unable to read magic number"); ! 160: return; ! 161: } ! 162: if (N_BADMAG(mag_un.mag_exp)) ! 163: continue; ! 164: ! 165: /* calculate number of symbols in object */ ! 166: if (!(nsyms = mag_un.mag_exp.a_syms / sizeof(NLIST))) { ! 167: error(NO, "no name list"); ! 168: continue; ! 169: } ! 170: ! 171: /* seek to and read symbols */ ! 172: (void)fseek(fi, (long)(N_SYMOFF(mag_un.mag_exp) - sizeof(struct exec)), L_INCR); ! 173: if (!symp || nsyms > lastnsyms) { ! 174: if (!symp) { ! 175: /*NOSTRICT*/ ! 176: symp = (NLIST *)malloc((u_int)(nsyms * sizeof(NLIST))); ! 177: /*NOSTRICT*/ ! 178: list = (NLIST **)malloc((u_int)(nsyms * sizeof(NLIST *))); ! 179: } ! 180: else { ! 181: /*NOSTRICT*/ ! 182: symp = (NLIST *)realloc((char *)symp, (u_int)(nsyms * sizeof(NLIST))); ! 183: /*NOSTRICT*/ ! 184: list = (NLIST **)realloc((char *)list, (u_int)(nsyms * sizeof(NLIST *))); ! 185: } ! 186: if (!symp || !list) ! 187: error(YES, "out of memory"); ! 188: lastnsyms = nsyms; ! 189: } ! 190: /*NOSTRICT*/ ! 191: if (fread((char *)symp, sizeof(NLIST), nsyms, fi) != nsyms) { ! 192: error(NO, "bad symbol table"); ! 193: continue; ! 194: } ! 195: ! 196: /* read number of strings, string table */ ! 197: /*NOSTRICT*/ ! 198: if (!fread((char *)&strsiz, sizeof(strsiz), 1, fi)) { ! 199: error(NO, "no string table (old format .o?)"); ! 200: continue; ! 201: } ! 202: if (!strp || strsiz > laststrsiz) { ! 203: strp = strp ? realloc(strp, (u_int)strsiz) : malloc((u_int)strsiz); ! 204: if (!strp) ! 205: error(YES, "out of memory"); ! 206: laststrsiz = strsiz; ! 207: } ! 208: if (!fread(strp + sizeof(strsiz), 1, (int)(strsiz - sizeof(strsiz)), fi)) { ! 209: error(NO, "no string table (old format .o?)"); ! 210: continue; ! 211: } ! 212: ! 213: for (symcount = nsyms, L = list, N = symp;--nsyms >= 0;++N) ! 214: if (!(N->n_type & N_EXT) && gflg || N->n_type & N_STAB && (!aflg || gflg || uflg)) ! 215: --symcount; ! 216: else { ! 217: N->u_name = N->u_strx ? strp + N->u_strx : ""; ! 218: *L++ = N; ! 219: } ! 220: ! 221: if (!pflg) ! 222: qsort(list, symcount, sizeof(NLIST *), compare); ! 223: ! 224: if ((archive || narg > 1) && !oflg) ! 225: printf("\n%s:\n", SELECT); ! 226: ! 227: psyms(list, symcount); ! 228: } while(archive && nextel()); ! 229: } ! 230: ! 231: psyms(list, nsyms) ! 232: NLIST **list; ! 233: register int nsyms; ! 234: { ! 235: register NLIST *L; ! 236: register u_char type; ! 237: char *stab(); ! 238: ! 239: while (nsyms--) { ! 240: L = *list++; ! 241: type = L->n_type; ! 242: if (type & N_STAB) { ! 243: if (oflg) { ! 244: if (archive) ! 245: printf("%s:", *xargv); ! 246: printf("%s:", SELECT); ! 247: } ! 248: printf("%08x - %02x %04x %5.5s %s\n", (int)L->n_value, L->n_other & 0xff, L->n_desc & 0xffff, stab(L->n_type), L->u_name); ! 249: continue; ! 250: } ! 251: switch (type & N_TYPE) { ! 252: case N_UNDF: ! 253: type = L->n_value ? 'c' : 'u'; ! 254: break; ! 255: case N_ABS: ! 256: type = 'a'; ! 257: break; ! 258: case N_TEXT: ! 259: type = 't'; ! 260: break; ! 261: case N_DATA: ! 262: type = 'd'; ! 263: break; ! 264: case N_BSS: ! 265: type = 'b'; ! 266: break; ! 267: case N_FN: ! 268: type = 'f'; ! 269: break; ! 270: default: ! 271: type = '?'; ! 272: break; ! 273: } ! 274: if (uflg && type != 'u') ! 275: continue; ! 276: if (oflg) { ! 277: if (archive) ! 278: printf("%s:", *xargv); ! 279: printf("%s:", SELECT); ! 280: } ! 281: if (L->n_type & N_EXT) ! 282: type = toupper(type); ! 283: if (!uflg) { ! 284: if (type == 'u' || type == 'U') ! 285: fputs(" ", stdout); ! 286: else ! 287: printf(N_FORMAT, (int)L->n_value); ! 288: printf(" %c ", (char)type); ! 289: } ! 290: puts(L->u_name); ! 291: } ! 292: } ! 293: ! 294: compare(p1, p2) ! 295: NLIST **p1, **p2; ! 296: { ! 297: if (nflg) { ! 298: if ((*p1)->n_value > (*p2)->n_value) ! 299: return(rflg); ! 300: if ((*p1)->n_value < (*p2)->n_value) ! 301: return(-rflg); ! 302: } ! 303: return(rflg * strcmp((*p1)->u_name, (*p2)->u_name)); ! 304: } ! 305: ! 306: nextel() ! 307: { ! 308: register char *cp; ! 309: long arsize, ! 310: lseek(); ! 311: ! 312: (void)fseek(fi, off, L_SET); ! 313: /*NOSTRICT*/ ! 314: if (!fread((char *)&archdr, sizeof(struct ar_hdr), 1, fi)) ! 315: return(0); ! 316: for (cp = archdr.ar_name; cp < &archdr.ar_name[sizeof(archdr.ar_name)]; ++cp) ! 317: if (*cp == ' ') { ! 318: *cp = '\0'; ! 319: break; ! 320: } ! 321: arsize = atol(archdr.ar_size); ! 322: if (arsize & 1) ! 323: ++arsize; ! 324: off = ftell(fi) + arsize; /* beginning of next element */ ! 325: return(1); ! 326: } ! 327: ! 328: struct stabnames { ! 329: int st_value; ! 330: char *st_name; ! 331: } stabnames[] ={ ! 332: N_GSYM, "GSYM", ! 333: N_FNAME, "FNAME", ! 334: N_FUN, "FUN", ! 335: N_STSYM, "STSYM", ! 336: N_LCSYM, "LCSYM", ! 337: N_RSYM, "RSYM", ! 338: N_SLINE, "SLINE", ! 339: N_SSYM, "SSYM", ! 340: N_SO, "SO", ! 341: N_LSYM, "LSYM", ! 342: N_SOL, "SOL", ! 343: N_PSYM, "PSYM", ! 344: N_ENTRY, "ENTRY", ! 345: N_LBRAC, "LBRAC", ! 346: N_RBRAC, "RBRAC", ! 347: N_BCOMM, "BCOMM", ! 348: N_ECOMM, "ECOMM", ! 349: N_ECOML, "ECOML", ! 350: N_LENG, "LENG", ! 351: N_PC, "PC", ! 352: 0, 0 ! 353: }; ! 354: ! 355: char * ! 356: stab(val) ! 357: register u_char val; ! 358: { ! 359: register struct stabnames *sp; ! 360: static char prbuf[5]; ! 361: ! 362: for (sp = stabnames; sp->st_value; ++sp) ! 363: if (sp->st_value == val) ! 364: return(sp->st_name); ! 365: (void)sprintf(prbuf, "%02x", (int)val); ! 366: return(prbuf); ! 367: } ! 368: ! 369: error(doexit, msg) ! 370: int doexit; ! 371: char *msg; ! 372: { ! 373: fprintf(stderr, "nm: %s:", *xargv); ! 374: if (archive) ! 375: fprintf(stderr, "(%s): %s\n", archdr.ar_name, msg); ! 376: else ! 377: fprintf(stderr, " %s\n", msg); ! 378: if (doexit) ! 379: exit(2); ! 380: errs = 1; ! 381: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.