112672Ssam #ifndef lint 2*28296Skarels static char sccsid[] = "@(#)nm.c 4.7 05/19/86"; 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"); 10217853Sralph 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"); 10817853Sralph 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 } 214*28296Skarels if (c == N_FN) 215*28296Skarels c = 'f'; 216*28296Skarels else switch (c&N_TYPE) { 217619Sbill 218619Sbill case N_UNDF: 219619Sbill c = 'u'; 220619Sbill if (symp[n].n_value) 221619Sbill c = 'c'; 222619Sbill break; 223619Sbill case N_ABS: 224619Sbill c = 'a'; 225619Sbill break; 226619Sbill case N_TEXT: 227619Sbill c = 't'; 228619Sbill break; 229619Sbill case N_DATA: 230619Sbill c = 'd'; 231619Sbill break; 232619Sbill case N_BSS: 233619Sbill c = 'b'; 234619Sbill break; 235*28296Skarels default: 236*28296Skarels c = '?'; 237619Sbill break; 238619Sbill } 239619Sbill if (uflg && c!='u') 240619Sbill continue; 241619Sbill if (oflg) { 242619Sbill if (archive) 243619Sbill printf("%s:", *xargv); 244619Sbill printf("%s:", SELECT); 245619Sbill } 246619Sbill if (symp[n].n_type&N_EXT) 247619Sbill c = toupper(c); 248619Sbill if (!uflg) { 249619Sbill if (c=='u' || c=='U') 250619Sbill printf(" "); 251619Sbill else 252619Sbill printf(N_FORMAT, symp[n].n_value); 253619Sbill printf(" %c ", c); 254619Sbill } 255619Sbill printf("%s\n", symp[n].n_un.n_name); 256619Sbill l1: ; 257619Sbill } 258619Sbill } 259619Sbill 260619Sbill compare(p1, p2) 261619Sbill struct nlist *p1, *p2; 262619Sbill { 263619Sbill register i; 264619Sbill 265619Sbill if (nflg) { 266619Sbill if (p1->n_value > p2->n_value) 267619Sbill return(rflg); 268619Sbill if (p1->n_value < p2->n_value) 269619Sbill return(-rflg); 270619Sbill } 271619Sbill return (rflg * strcmp(p1->n_un.n_name, p2->n_un.n_name)); 272619Sbill } 273619Sbill 274619Sbill nextel(af) 275619Sbill FILE *af; 276619Sbill { 277619Sbill register char *cp; 278619Sbill register r; 279619Sbill long arsize; 280619Sbill 281619Sbill fseek(af, off, 0); 282619Sbill r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af); 283619Sbill if (r != sizeof(struct ar_hdr)) 284619Sbill return(0); 285619Sbill for (cp = archdr.ar_name; cp < &archdr.ar_name[sizeof(archdr.ar_name)]; cp++) 286619Sbill if (*cp == ' ') 287619Sbill *cp = '\0'; 288619Sbill arsize = atol(archdr.ar_size); 289619Sbill if (arsize & 1) 290619Sbill ++arsize; 291619Sbill off = ftell(af) + arsize; /* beginning of next element */ 292619Sbill return(1); 293619Sbill } 294619Sbill 295619Sbill error(n, s) 296619Sbill char *s; 297619Sbill { 298619Sbill fprintf(stderr, "nm: %s:", *xargv); 299619Sbill if (archive) { 300619Sbill fprintf(stderr, "(%s)", archdr.ar_name); 301619Sbill fprintf(stderr, ": "); 302619Sbill } else 303619Sbill fprintf(stderr, " "); 304619Sbill fprintf(stderr, "%s\n", s); 305619Sbill if (n) 306619Sbill exit(2); 307619Sbill errs = 1; 308619Sbill } 309619Sbill 310619Sbill struct stabnames { 311619Sbill int st_value; 312619Sbill char *st_name; 313619Sbill } stabnames[] ={ 314619Sbill N_GSYM, "GSYM", 315619Sbill N_FNAME, "FNAME", 316619Sbill N_FUN, "FUN", 317619Sbill N_STSYM, "STSYM", 318619Sbill N_LCSYM, "LCSYM", 319619Sbill N_RSYM, "RSYM", 320619Sbill N_SLINE, "SLINE", 321619Sbill N_SSYM, "SSYM", 322619Sbill N_SO, "SO", 323619Sbill N_LSYM, "LSYM", 324619Sbill N_SOL, "SOL", 325619Sbill N_PSYM, "PSYM", 326619Sbill N_ENTRY, "ENTRY", 327619Sbill N_LBRAC, "LBRAC", 328619Sbill N_RBRAC, "RBRAC", 329619Sbill N_BCOMM, "BCOMM", 330619Sbill N_ECOMM, "ECOMM", 331619Sbill N_ECOML, "ECOML", 332619Sbill N_LENG, "LENG", 333859Sbill N_PC, "PC", 334619Sbill 0, 0 335619Sbill }; 336619Sbill 337619Sbill char * 338619Sbill stab(val) 339619Sbill { 340619Sbill register struct stabnames *sp; 341619Sbill static char prbuf[32]; 342619Sbill 343619Sbill for (sp = stabnames; sp->st_name; sp++) 344619Sbill if (sp->st_value == val) 345619Sbill return (sp->st_name); 346619Sbill sprintf(prbuf, "%02x", val); 347619Sbill return (prbuf); 348619Sbill } 349