112672Ssam #ifndef lint 2*17853Sralph static char sccsid[] = "@(#)nm.c 4.6 01/22/85"; 312672Ssam #endif 4619Sbill /* 5619Sbill * nm - print name list; VAX string table version 6619Sbill */ 7619Sbill #include <sys/types.h> 8653Sbill #include <ar.h> 9619Sbill #include <stdio.h> 10619Sbill #include <ctype.h> 11653Sbill #include <a.out.h> 12619Sbill #include <stab.h> 1313490Ssam #include <sys/stat.h> 14619Sbill 15619Sbill #define SELECT archive ? archdr.ar_name : *xargv 16619Sbill 17619Sbill int aflg, gflg, nflg, oflg, pflg, uflg; 18619Sbill int rflg = 1; 19619Sbill char **xargv; 20619Sbill int archive; 21619Sbill struct ar_hdr archdr; 22619Sbill union { 23619Sbill char mag_armag[SARMAG+1]; 24619Sbill struct exec mag_exp; 25619Sbill } mag_un; 26619Sbill #define OARMAG 0177545 27619Sbill FILE *fi; 28619Sbill off_t off; 29619Sbill off_t ftell(); 30619Sbill char *malloc(); 31619Sbill char *realloc(); 32619Sbill char *strp; 33619Sbill char *stab(); 34619Sbill off_t strsiz; 35619Sbill int compare(); 36619Sbill int narg; 37619Sbill int errs; 38619Sbill 39619Sbill main(argc, argv) 40619Sbill char **argv; 41619Sbill { 42619Sbill 43619Sbill if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) { 44619Sbill argv++; 45619Sbill while (*++*argv) switch (**argv) { 46619Sbill 47619Sbill case 'n': 48619Sbill nflg++; 49619Sbill continue; 50619Sbill case 'g': 51619Sbill gflg++; 52619Sbill continue; 53619Sbill case 'u': 54619Sbill uflg++; 55619Sbill continue; 56619Sbill case 'r': 57619Sbill rflg = -1; 58619Sbill continue; 59619Sbill case 'p': 60619Sbill pflg++; 61619Sbill continue; 62619Sbill case 'o': 63619Sbill oflg++; 64619Sbill continue; 65619Sbill case 'a': 66619Sbill aflg++; 67619Sbill continue; 68619Sbill default: 69619Sbill fprintf(stderr, "nm: invalid argument -%c\n", 70619Sbill *argv[0]); 71619Sbill exit(2); 72619Sbill } 73619Sbill argc--; 74619Sbill } 75619Sbill if (argc == 0) { 76619Sbill argc = 1; 77619Sbill argv[1] = "a.out"; 78619Sbill } 79619Sbill narg = argc; 80619Sbill xargv = argv; 81619Sbill while (argc--) { 82619Sbill ++xargv; 83619Sbill namelist(); 84619Sbill } 85619Sbill exit(errs); 86619Sbill } 87619Sbill 88619Sbill namelist() 89619Sbill { 90619Sbill register int j; 91619Sbill 92619Sbill archive = 0; 93619Sbill fi = fopen(*xargv, "r"); 94619Sbill if (fi == NULL) { 95619Sbill error(0, "cannot open"); 96619Sbill return; 97619Sbill } 98619Sbill off = SARMAG; 99619Sbill fread((char *)&mag_un, 1, sizeof(mag_un), fi); 100619Sbill if (mag_un.mag_exp.a_magic == OARMAG) { 101619Sbill error(0, "old archive"); 102*17853Sralph goto out; 103619Sbill } 104619Sbill if (strncmp(mag_un.mag_armag, ARMAG, SARMAG)==0) 105619Sbill archive++; 106619Sbill else if (N_BADMAG(mag_un.mag_exp)) { 107619Sbill error(0, "bad format"); 108*17853Sralph goto out; 109619Sbill } 110619Sbill fseek(fi, 0L, 0); 111619Sbill if (archive) { 112619Sbill nextel(fi); 113619Sbill if (narg > 1) 114619Sbill printf("\n%s:\n", *xargv); 115619Sbill } 116619Sbill do { 117619Sbill off_t o; 118619Sbill register i, n, c; 119619Sbill struct nlist *symp = NULL; 120619Sbill struct nlist sym; 121619Sbill struct stat stb; 122619Sbill 123619Sbill fread((char *)&mag_un.mag_exp, 1, sizeof(struct exec), fi); 124619Sbill if (N_BADMAG(mag_un.mag_exp)) 125619Sbill continue; 126619Sbill if (archive == 0) 127619Sbill fstat(fileno(fi), &stb); 128619Sbill o = N_SYMOFF(mag_un.mag_exp) - sizeof (struct exec); 129619Sbill fseek(fi, o, 1); 130619Sbill n = mag_un.mag_exp.a_syms / sizeof(struct nlist); 131619Sbill if (n == 0) { 132619Sbill error(0, "no name list"); 133619Sbill continue; 134619Sbill } 135619Sbill if (N_STROFF(mag_un.mag_exp) + sizeof (off_t) > 13617424Sralph (archive ? off : stb.st_size)) { 13717424Sralph error(0, "old format .o (no string table) or truncated file"); 13817424Sralph continue; 13917424Sralph } 140619Sbill i = 0; 141619Sbill if (strp) 142619Sbill free(strp), strp = 0; 143619Sbill while (--n >= 0) { 144619Sbill fread((char *)&sym, 1, sizeof(sym), fi); 145619Sbill if (gflg && (sym.n_type&N_EXT)==0) 146619Sbill continue; 147619Sbill if ((sym.n_type&N_STAB) && (!aflg||gflg||uflg)) 148619Sbill continue; 149619Sbill if (symp==NULL) 150619Sbill symp = (struct nlist *) 151619Sbill malloc(sizeof(struct nlist)); 152619Sbill else 153619Sbill symp = (struct nlist *) 154619Sbill realloc(symp, 155619Sbill (i+1)*sizeof(struct nlist)); 156619Sbill if (symp == NULL) 157619Sbill error(1, "out of memory"); 158619Sbill symp[i++] = sym; 159619Sbill } 160619Sbill if (archive && ftell(fi)+sizeof(off_t) >= off) { 161619Sbill error(0, "no string table (old format .o?)"); 162619Sbill continue; 163619Sbill } 164619Sbill if (fread((char *)&strsiz,sizeof(strsiz),1,fi) != 1) { 165619Sbill error(0, "no string table (old format .o?)"); 166619Sbill goto out; 167619Sbill } 168619Sbill strp = (char *)malloc(strsiz); 169619Sbill if (strp == NULL) 170619Sbill error(1, "ran out of memory"); 171619Sbill if (fread(strp+sizeof(strsiz),strsiz-sizeof(strsiz),1,fi) != 1) 172619Sbill error(1, "error reading string table"); 173619Sbill for (j = 0; j < i; j++) 174619Sbill if (symp[j].n_un.n_strx) 175619Sbill symp[j].n_un.n_name = 176619Sbill symp[j].n_un.n_strx + strp; 177619Sbill else 178619Sbill symp[j].n_un.n_name = ""; 179619Sbill if (pflg==0) 180619Sbill qsort(symp, i, sizeof(struct nlist), compare); 181619Sbill if ((archive || narg>1) && oflg==0) 182619Sbill printf("\n%s:\n", SELECT); 183619Sbill psyms(symp, i); 184619Sbill if (symp) 185619Sbill free((char *)symp), symp = 0; 186619Sbill if (strp) 187619Sbill free((char *)strp), strp = 0; 188619Sbill } while(archive && nextel(fi)); 189619Sbill out: 190619Sbill fclose(fi); 191619Sbill } 192619Sbill 193619Sbill psyms(symp, nsyms) 194619Sbill register struct nlist *symp; 195619Sbill int nsyms; 196619Sbill { 197619Sbill register int n, c; 198619Sbill 199619Sbill for (n=0; n<nsyms; n++) { 200619Sbill c = symp[n].n_type; 201619Sbill if (c & N_STAB) { 202619Sbill if (oflg) { 203619Sbill if (archive) 204619Sbill printf("%s:", *xargv); 205619Sbill printf("%s:", SELECT); 206619Sbill } 207619Sbill printf("%08x - %02x %04x %5.5s %s\n", 208619Sbill symp[n].n_value, 209619Sbill symp[n].n_other & 0xff, symp[n].n_desc & 0xffff, 210619Sbill stab(symp[n].n_type & 0xff), 211619Sbill symp[n].n_un.n_name); 212619Sbill continue; 213619Sbill } 214619Sbill switch (c&N_TYPE) { 215619Sbill 216619Sbill case N_UNDF: 217619Sbill c = 'u'; 218619Sbill if (symp[n].n_value) 219619Sbill c = 'c'; 220619Sbill break; 221619Sbill case N_ABS: 222619Sbill c = 'a'; 223619Sbill break; 224619Sbill case N_TEXT: 225619Sbill c = 't'; 226619Sbill break; 227619Sbill case N_DATA: 228619Sbill c = 'd'; 229619Sbill break; 230619Sbill case N_BSS: 231619Sbill c = 'b'; 232619Sbill break; 233619Sbill case N_FN: 234619Sbill c = 'f'; 235619Sbill break; 236619Sbill } 237619Sbill if (uflg && c!='u') 238619Sbill continue; 239619Sbill if (oflg) { 240619Sbill if (archive) 241619Sbill printf("%s:", *xargv); 242619Sbill printf("%s:", SELECT); 243619Sbill } 244619Sbill if (symp[n].n_type&N_EXT) 245619Sbill c = toupper(c); 246619Sbill if (!uflg) { 247619Sbill if (c=='u' || c=='U') 248619Sbill printf(" "); 249619Sbill else 250619Sbill printf(N_FORMAT, symp[n].n_value); 251619Sbill printf(" %c ", c); 252619Sbill } 253619Sbill printf("%s\n", symp[n].n_un.n_name); 254619Sbill l1: ; 255619Sbill } 256619Sbill } 257619Sbill 258619Sbill compare(p1, p2) 259619Sbill struct nlist *p1, *p2; 260619Sbill { 261619Sbill register i; 262619Sbill 263619Sbill if (nflg) { 264619Sbill if (p1->n_value > p2->n_value) 265619Sbill return(rflg); 266619Sbill if (p1->n_value < p2->n_value) 267619Sbill return(-rflg); 268619Sbill } 269619Sbill return (rflg * strcmp(p1->n_un.n_name, p2->n_un.n_name)); 270619Sbill } 271619Sbill 272619Sbill nextel(af) 273619Sbill FILE *af; 274619Sbill { 275619Sbill register char *cp; 276619Sbill register r; 277619Sbill long arsize; 278619Sbill 279619Sbill fseek(af, off, 0); 280619Sbill r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af); 281619Sbill if (r != sizeof(struct ar_hdr)) 282619Sbill return(0); 283619Sbill for (cp = archdr.ar_name; cp < &archdr.ar_name[sizeof(archdr.ar_name)]; cp++) 284619Sbill if (*cp == ' ') 285619Sbill *cp = '\0'; 286619Sbill arsize = atol(archdr.ar_size); 287619Sbill if (arsize & 1) 288619Sbill ++arsize; 289619Sbill off = ftell(af) + arsize; /* beginning of next element */ 290619Sbill return(1); 291619Sbill } 292619Sbill 293619Sbill error(n, s) 294619Sbill char *s; 295619Sbill { 296619Sbill fprintf(stderr, "nm: %s:", *xargv); 297619Sbill if (archive) { 298619Sbill fprintf(stderr, "(%s)", archdr.ar_name); 299619Sbill fprintf(stderr, ": "); 300619Sbill } else 301619Sbill fprintf(stderr, " "); 302619Sbill fprintf(stderr, "%s\n", s); 303619Sbill if (n) 304619Sbill exit(2); 305619Sbill errs = 1; 306619Sbill } 307619Sbill 308619Sbill struct stabnames { 309619Sbill int st_value; 310619Sbill char *st_name; 311619Sbill } stabnames[] ={ 312619Sbill N_GSYM, "GSYM", 313619Sbill N_FNAME, "FNAME", 314619Sbill N_FUN, "FUN", 315619Sbill N_STSYM, "STSYM", 316619Sbill N_LCSYM, "LCSYM", 317619Sbill N_RSYM, "RSYM", 318619Sbill N_SLINE, "SLINE", 319619Sbill N_SSYM, "SSYM", 320619Sbill N_SO, "SO", 321619Sbill N_LSYM, "LSYM", 322619Sbill N_SOL, "SOL", 323619Sbill N_PSYM, "PSYM", 324619Sbill N_ENTRY, "ENTRY", 325619Sbill N_LBRAC, "LBRAC", 326619Sbill N_RBRAC, "RBRAC", 327619Sbill N_BCOMM, "BCOMM", 328619Sbill N_ECOMM, "ECOMM", 329619Sbill N_ECOML, "ECOML", 330619Sbill N_LENG, "LENG", 331859Sbill N_PC, "PC", 332619Sbill 0, 0 333619Sbill }; 334619Sbill 335619Sbill char * 336619Sbill stab(val) 337619Sbill { 338619Sbill register struct stabnames *sp; 339619Sbill static char prbuf[32]; 340619Sbill 341619Sbill for (sp = stabnames; sp->st_name; sp++) 342619Sbill if (sp->st_value == val) 343619Sbill return (sp->st_name); 344619Sbill sprintf(prbuf, "%02x", val); 345619Sbill return (prbuf); 346619Sbill } 347