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