1: /* 2: * print symbol tables for 3: * object or archive files 4: * 5: * nm [-goprun] [name ...] 6: */ 7: 8: #include <sys/param.h> 9: #include <ar.h> 10: #include <a.out.h> 11: #include <stdio.h> 12: #include <ctype.h> 13: 14: #ifdef MENLO_OVLY 15: struct nnlist { /* symbol table entry */ 16: char n_name[8]; /* symbol name */ 17: char nn_type; /* type flag */ 18: char nn_ovno; 19: unsigned n_value; /* value */ 20: }; 21: #endif MENLO_OVLY 22: #define SELECT arch_flg ? arp.ar_name : *argv 23: int numsort_flg; 24: int undef_flg; 25: int revsort_flg = 1; 26: int globl_flg; 27: int nosort_flg; 28: int arch_flg; 29: int prep_flg; 30: struct ar_hdr arp; 31: struct exec exp; 32: FILE *fi; 33: long off; 34: long ftell(); 35: char *malloc(); 36: char *realloc(); 37: 38: main(argc, argv) 39: char **argv; 40: { 41: int narg; 42: int compare(); 43: 44: if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) { 45: argv++; 46: while (*++*argv) switch (**argv) { 47: case 'n': /* sort numerically */ 48: numsort_flg++; 49: continue; 50: 51: case 'g': /* globl symbols only */ 52: globl_flg++; 53: continue; 54: 55: case 'u': /* undefined symbols only */ 56: undef_flg++; 57: continue; 58: 59: case 'r': /* sort in reverse order */ 60: revsort_flg = -1; 61: continue; 62: 63: case 'p': /* don't sort -- symbol table order */ 64: nosort_flg++; 65: continue; 66: 67: case 'o': /* prepend a name to each line */ 68: prep_flg++; 69: continue; 70: 71: default: /* oops */ 72: fprintf(stderr, "nm: invalid argument -%c\n", *argv[0]); 73: exit(1); 74: } 75: argc--; 76: } 77: if (argc == 0) { 78: argc = 1; 79: argv[1] = "a.out"; 80: } 81: narg = argc; 82: while(argc--) { 83: fi = fopen(*++argv,"r"); 84: if (fi == NULL) { 85: fprintf(stderr, "nm: cannot open %s\n", *argv); 86: continue; 87: } 88: off = sizeof(exp.a_magic); 89: fread((char *)&exp, 1, sizeof(exp.a_magic), fi); /* get magic no. */ 90: if (exp.a_magic == ARMAG) 91: arch_flg++; 92: else if (N_BADMAG(exp)) { 93: fprintf(stderr, "nm: %s-- bad format\n", *argv); 94: continue; 95: } 96: fseek(fi, 0L, 0); 97: if (arch_flg) { 98: (void) nextel(fi); 99: if (narg > 1) 100: printf("\n%s:\n", *argv); 101: } 102: do { 103: long o; 104: register i, n, c; 105: #ifdef MENLO_OVLY 106: struct nnlist sym; 107: struct nnlist *symp = NULL; 108: unsigned ovsizes[1 + NOVL]; 109: #else 110: struct nlist sym; 111: struct nlist *symp = NULL; 112: #endif MENLO_OVLY 113: 114: fread((char *)&exp, 1, sizeof(struct exec), fi); 115: if (N_BADMAG(exp)) /* archive element not in */ 116: continue; /* proper format - skip it */ 117: #ifdef MENLO_OVLY 118: if (exp.a_magic == A_MAGIC5 || exp.a_magic == A_MAGIC6) { 119: fread((char *)ovsizes, 1, sizeof ovsizes, fi); 120: o = 0L; 121: for (i = 1; i <= NOVL; i++) 122: o += (long) ovsizes[i]; 123: fseek(fi, o, 1); 124: } 125: #endif MENLO_OVLY 126: o = (long)exp.a_text + exp.a_data; 127: if ((exp.a_flag & 01) == 0) 128: o *= 2; 129: fseek(fi, o, 1); 130: n = exp.a_syms / sizeof(struct nlist); 131: if (n == 0) { 132: fprintf(stderr, "nm: %s-- no name list\n", SELECT); 133: continue; 134: } 135: i = 0; 136: while (--n >= 0) { 137: fread((char *)&sym, 1, sizeof(sym), fi); 138: #ifndef MENLO_OVLY 139: if (globl_flg && (sym.n_type&N_EXT)==0) 140: #else MENLO_OVLY 141: if (globl_flg && (sym.nn_type&N_EXT)==0) 142: #endif MENLO_OVLY 143: continue; 144: #ifndef MENLO_OVLY 145: switch (sym.n_type&N_TYPE) 146: #else MENLO_OVLY 147: switch (sym.nn_type&N_TYPE) 148: #endif MENLO_OVLY 149: { 150: 151: case N_UNDF: 152: c = 'u'; 153: if (sym.n_value) 154: c = 'c'; 155: break; 156: 157: default: 158: case N_ABS: 159: c = 'a'; 160: break; 161: 162: case N_TEXT: 163: c = 't'; 164: break; 165: 166: case N_DATA: 167: c = 'd'; 168: break; 169: 170: case N_BSS: 171: c = 'b'; 172: break; 173: 174: case N_FN: 175: c = 'f'; 176: break; 177: 178: case N_REG: 179: c = 'r'; 180: break; 181: } 182: if (undef_flg && c!='u') 183: continue; 184: #ifndef MENLO_OVLY 185: if (sym.n_type&N_EXT) 186: #else MENLO_OVLY 187: if (sym.nn_type&N_EXT) 188: #endif MENLO_OVLY 189: c = toupper(c); 190: #ifndef MENLO_OVLY 191: sym.n_type = c; 192: #else MENLO_OVLY 193: sym.nn_type = c; 194: #endif MENLO_OVLY 195: if (symp==NULL) 196: #ifdef MENLO_OVLY 197: symp = (struct nnlist *)malloc(sizeof(struct nlist)); 198: #else 199: symp = (struct nlist *)malloc(sizeof(struct nlist)); 200: #endif MENLO_OVLY 201: else { 202: #ifdef MENLO_OVLY 203: symp = (struct nnlist *)realloc(symp, (i+1)*sizeof(struct nlist)); 204: #else 205: symp = (struct nlist *)realloc(symp, (i+1)*sizeof(struct nlist)); 206: #endif MENLO_OVLY 207: } 208: if (symp == NULL) { 209: fprintf(stderr, "nm: out of memory on %s\n", *argv); 210: exit(2); 211: } 212: symp[i++] = sym; 213: } 214: if (nosort_flg==0) 215: qsort(symp, i, sizeof(struct nlist), compare); 216: if ((arch_flg || narg>1) && prep_flg==0) 217: printf("\n%s:\n", SELECT); 218: for (n=0; n<i; n++) { 219: if (prep_flg) { 220: if (arch_flg) 221: printf("%s:", *argv); 222: printf("%s:", SELECT); 223: } 224: #ifdef MENLO_OVLY 225: c = symp[n].nn_type; 226: #else 227: c = symp[n].n_type; 228: #endif MENLO_OVLY 229: if (!undef_flg) { 230: if (c=='u' || c=='U') 231: printf(" "); 232: else 233: printf(FORMAT, symp[n].n_value); 234: printf(" %c ", c); 235: } 236: #ifndef MENLO_OVLY 237: printf("%.8s\n", symp[n].n_name); 238: #else MENLO_OVLY 239: if (symp[n].nn_ovno) 240: printf("%-8.8s %d", symp[n].n_name, 241: symp[n].nn_ovno); 242: else 243: printf("%.8s", symp[n].n_name); 244: printf("\n"); 245: #endif MENLO_OVLY 246: } 247: if (symp) 248: free((char *)symp); 249: } while(arch_flg && nextel(fi)); 250: fclose(fi); 251: } 252: exit(0); 253: } 254: 255: compare(p1, p2) 256: register struct nlist *p1, *p2; 257: { 258: register i; 259: 260: if (numsort_flg) { 261: if (p1->n_value > p2->n_value) 262: return(revsort_flg); 263: if (p1->n_value < p2->n_value) 264: return(-revsort_flg); 265: } 266: for(i=0; i<sizeof(p1->n_name); i++) 267: if (p1->n_name[i] != p2->n_name[i]) { 268: if (p1->n_name[i] > p2->n_name[i]) 269: return(revsort_flg); 270: else 271: return(-revsort_flg); 272: } 273: return(0); 274: } 275: 276: nextel(af) 277: register FILE *af; 278: { 279: register r; 280: 281: fseek(af, off, 0); 282: r = fread((char *)&arp, 1, sizeof(struct ar_hdr), af); /* read archive header */ 283: if (r <= 0) 284: return(0); 285: if (arp.ar_size & 1) 286: ++arp.ar_size; 287: off = ftell(af) + arp.ar_size; /* offset to next element */ 288: return(1); 289: }