1: #if !defined(lint) && !defined(DOSCCS) 2: static char sccsid[] = "@(#)nm.c 2.11BSD 1/22/94"; 3: #endif 4: /* 5: * nm - print name list. string table version 6: */ 7: #include <sys/types.h> 8: #include <sys/dir.h> 9: #include <ar.h> 10: #include <stdio.h> 11: #include <ctype.h> 12: #include <a.out.h> 13: #include <sys/file.h> 14: #include "archive.h" 15: #include <string.h> 16: 17: CHDR chdr; 18: 19: #define SELECT archive ? chdr.name : *xargv 20: 21: char aflg, gflg, nflg, oflg, pflg, uflg, rflg = 1, archive; 22: char **xargv; 23: char *strp; 24: union { 25: char mag_armag[SARMAG+1]; 26: struct xexec mag_exp; 27: } mag_un; 28: 29: off_t off, skip(); 30: extern off_t ftell(); 31: extern char *malloc(); 32: extern long strtol(); 33: int compare(), narg, errs; 34: 35: main(argc, argv) 36: int argc; 37: char **argv; 38: { 39: 40: if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) { 41: argv++; 42: while (*++*argv) switch (**argv) { 43: 44: case 'n': 45: nflg++; 46: continue; 47: case 'g': 48: gflg++; 49: continue; 50: case 'u': 51: uflg++; 52: continue; 53: case 'r': 54: rflg = -1; 55: continue; 56: case 'p': 57: pflg++; 58: continue; 59: case 'o': 60: oflg++; 61: continue; 62: case 'a': 63: aflg++; 64: continue; 65: default: 66: fprintf(stderr, "nm: invalid argument -%c\n", 67: *argv[0]); 68: exit(2); 69: } 70: argc--; 71: } 72: if (argc == 0) { 73: argc = 1; 74: argv[1] = "a.out"; 75: } 76: narg = argc; 77: xargv = argv; 78: while (argc--) { 79: ++xargv; 80: namelist(); 81: } 82: exit(errs); 83: } 84: 85: namelist() 86: { 87: char ibuf[BUFSIZ]; 88: register FILE *fi; 89: 90: archive = 0; 91: fi = fopen(*xargv, "r"); 92: if (fi == NULL) { 93: error(0, "cannot open"); 94: return; 95: } 96: setbuf(fi, ibuf); 97: 98: off = 0; 99: fread((char *)&mag_un, 1, sizeof(mag_un), fi); 100: if (strncmp(mag_un.mag_armag, ARMAG, SARMAG)==0) { 101: archive++; 102: off = SARMAG; 103: } 104: else if (N_BADMAG(mag_un.mag_exp.e)) { 105: error(0, "bad format"); 106: goto out; 107: } 108: rewind(fi); 109: 110: if (archive) { 111: nextel(fi); 112: if (narg > 1) 113: printf("\n%s:\n", *xargv); 114: } 115: do { 116: off_t o, curpos, stroff; 117: long strsiz; 118: register i, n; 119: struct nlist *symp = NULL; 120: struct nlist sym; 121: 122: curpos = ftell(fi); 123: fread((char *)&mag_un.mag_exp, 1, sizeof(struct xexec), fi); 124: if (N_BADMAG(mag_un.mag_exp.e)) 125: continue; 126: 127: o = N_SYMOFF(mag_un.mag_exp); 128: fseek(fi, curpos + o, L_SET); 129: n = mag_un.mag_exp.e.a_syms / sizeof(struct nlist); 130: if (n == 0) { 131: error(0, "no name list"); 132: continue; 133: } 134: 135: i = 0; 136: if (strp) 137: free(strp), strp = 0; 138: while (--n >= 0) { 139: fread((char *)&sym, 1, sizeof(sym), fi); 140: if (sym.n_un.n_strx == 0) 141: continue; 142: if (gflg && (sym.n_type & N_EXT) == 0) 143: continue; 144: if (uflg && (sym.n_type & N_TYPE) == N_UNDF && sym.n_value) 145: continue; 146: i++; 147: } 148: 149: fseek(fi, curpos + o, L_SET); 150: symp = (struct nlist *)malloc(i * sizeof (struct nlist)); 151: if (symp == 0) 152: error(1, "out of memory"); 153: i = 0; 154: n = mag_un.mag_exp.e.a_syms / sizeof(struct nlist); 155: while (--n >= 0) { 156: fread((char *)&sym, 1, sizeof(sym), fi); 157: if (sym.n_un.n_strx == 0) 158: continue; 159: if (gflg && (sym.n_type & N_EXT) == 0) 160: continue; 161: if (uflg && (sym.n_type & N_TYPE) == N_UNDF && sym.n_value) 162: continue; 163: symp[i++] = sym; 164: } 165: stroff = curpos + N_STROFF(mag_un.mag_exp); 166: fseek(fi, stroff, L_SET); 167: if (fread(&strsiz, sizeof (long), 1, fi) != 1) 168: error(1, "no string table"); 169: strp = (char *)malloc((int)strsiz); 170: if (strp == NULL || strsiz > 48 * 1024L) 171: error(1, "ran out of memory"); 172: if (fread(strp+sizeof(strsiz),(int)strsiz-sizeof(strsiz),1,fi) != 1) 173: error(1, "error reading strings"); 174: for (n = 0; n < i; n++) 175: symp[n].n_un.n_name = strp + (int)symp[n].n_un.n_strx; 176: 177: if (pflg==0) 178: qsort(symp, i, sizeof(struct nlist), compare); 179: if ((archive || narg>1) && oflg==0) 180: printf("\n%s:\n", SELECT); 181: psyms(symp, i); 182: if (symp) 183: free((char *)symp), symp = NULL; 184: if (strp) 185: free((char *)strp), strp = NULL; 186: } while(archive && nextel(fi)); 187: out: 188: fclose(fi); 189: } 190: 191: psyms(symp, nsyms) 192: register struct nlist *symp; 193: int nsyms; 194: { 195: register int n, c; 196: 197: for (n=0; n<nsyms; n++) { 198: c = symp[n].n_type; 199: if (c == N_FN) 200: c = 'f'; 201: else switch (c&N_TYPE) { 202: 203: case N_UNDF: 204: c = 'u'; 205: if (symp[n].n_value) 206: c = 'c'; 207: break; 208: case N_ABS: 209: c = 'a'; 210: break; 211: case N_TEXT: 212: c = 't'; 213: break; 214: case N_DATA: 215: c = 'd'; 216: break; 217: case N_BSS: 218: c = 'b'; 219: break; 220: case N_REG: 221: c = 'r'; 222: break; 223: default: 224: c = '?'; 225: break; 226: } 227: if (uflg && c!='u') 228: continue; 229: if (oflg) { 230: if (archive) 231: printf("%s:", *xargv); 232: printf("%s:", SELECT); 233: } 234: if (symp[n].n_type&N_EXT) 235: c = toupper(c); 236: if (!uflg) { 237: if (c=='u' || c=='U') 238: printf(" "); 239: else 240: printf(N_FORMAT, symp[n].n_value); 241: printf(" %c ", c); 242: } 243: if (symp[n].n_ovly) 244: printf("%s %d\n", symp[n].n_un.n_name, 245: symp[n].n_ovly & 0xff); 246: else 247: printf("%s\n", symp[n].n_un.n_name); 248: } 249: } 250: 251: compare(p1, p2) 252: register struct nlist *p1, *p2; 253: { 254: 255: if (nflg) { 256: if (p1->n_value > p2->n_value) 257: return(rflg); 258: if (p1->n_value < p2->n_value) 259: return(-rflg); 260: } 261: return (rflg * strcmp(p1->n_un.n_name, p2->n_un.n_name)); 262: } 263: 264: nextel(af) 265: FILE *af; 266: { 267: 268: fseek(af, off, L_SET); 269: if (get_arobj(af) < 0) 270: return(0); 271: off += (sizeof (struct ar_hdr) + chdr.size + 272: (chdr.size + chdr.lname & 1)); 273: return(1); 274: } 275: 276: error(n, s) 277: char *s; 278: { 279: fprintf(stderr, "nm: %s:", *xargv); 280: if (archive) { 281: fprintf(stderr, "(%s)", chdr.name); 282: fprintf(stderr, ": "); 283: } else 284: fprintf(stderr, " "); 285: fprintf(stderr, "%s\n", s); 286: if (n) 287: exit(2); 288: errs = 1; 289: } 290: 291: /* 292: * "borrowed" from 'ar' because we didn't want to drag in everything else 293: * from 'ar'. The error checking was also ripped out, basically if any 294: * of the criteria for being an archive are not met then a -1 is returned 295: * and the rest of 'ld' figures out what to do. 296: */ 297: 298: typedef struct ar_hdr HDR; 299: static char hb[sizeof(HDR) + 1]; /* real header */ 300: 301: /* Convert ar header field to an integer. */ 302: #define AR_ATOI(from, to, len, base) { \ 303: bcopy(from, buf, len); \ 304: buf[len] = '\0'; \ 305: to = strtol(buf, (char **)NULL, base); \ 306: } 307: 308: /* 309: * read the archive header for this member. Use a file pointer 310: * rather than a file descriptor. 311: */ 312: get_arobj(fp) 313: FILE *fp; 314: { 315: HDR *hdr; 316: register int len, nr; 317: register char *p; 318: char buf[20]; 319: 320: nr = fread(hb, 1, sizeof(HDR), fp); 321: if (nr != sizeof(HDR)) 322: return(-1); 323: 324: hdr = (HDR *)hb; 325: if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1)) 326: return(-1); 327: 328: /* Convert the header into the internal format. */ 329: #define DECIMAL 10 330: #define OCTAL 8 331: 332: AR_ATOI(hdr->ar_date, chdr.date, sizeof(hdr->ar_date), DECIMAL); 333: AR_ATOI(hdr->ar_uid, chdr.uid, sizeof(hdr->ar_uid), DECIMAL); 334: AR_ATOI(hdr->ar_gid, chdr.gid, sizeof(hdr->ar_gid), DECIMAL); 335: AR_ATOI(hdr->ar_mode, chdr.mode, sizeof(hdr->ar_mode), OCTAL); 336: AR_ATOI(hdr->ar_size, chdr.size, sizeof(hdr->ar_size), DECIMAL); 337: 338: /* Leading spaces should never happen. */ 339: if (hdr->ar_name[0] == ' ') 340: return(-1); 341: 342: /* 343: * Long name support. Set the "real" size of the file, and the 344: * long name flag/size. 345: */ 346: if (!bcmp(hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1)) { 347: chdr.lname = len = atoi(hdr->ar_name + sizeof(AR_EFMT1) - 1); 348: if (len <= 0 || len > MAXNAMLEN) 349: return(-1); 350: nr = fread(chdr.name, 1, (size_t)len, fp); 351: if (nr != len) 352: return(-1); 353: chdr.name[len] = 0; 354: chdr.size -= len; 355: } else { 356: chdr.lname = 0; 357: bcopy(hdr->ar_name, chdr.name, sizeof(hdr->ar_name)); 358: 359: /* Strip trailing spaces, null terminate. */ 360: for (p = chdr.name + sizeof(hdr->ar_name) - 1; *p == ' '; --p); 361: *++p = '\0'; 362: } 363: return(1); 364: }