1*12672Ssam #ifndef lint 2*12672Ssam static char sccsid[] = "@(#)nm.c 4.2 05/22/83"; 3*12672Ssam #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> 13619Sbill #include <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"); 102619Sbill return; 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"); 108619Sbill return; 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) > 136653Sbill (archive ? off : stb.st_size)) 137619Sbill error(1, "old format .o (no string table) or truncated file"); 138619Sbill i = 0; 139619Sbill if (strp) 140619Sbill free(strp), strp = 0; 141619Sbill while (--n >= 0) { 142619Sbill fread((char *)&sym, 1, sizeof(sym), fi); 143619Sbill if (gflg && (sym.n_type&N_EXT)==0) 144619Sbill continue; 145619Sbill if ((sym.n_type&N_STAB) && (!aflg||gflg||uflg)) 146619Sbill continue; 147619Sbill if (symp==NULL) 148619Sbill symp = (struct nlist *) 149619Sbill malloc(sizeof(struct nlist)); 150619Sbill else 151619Sbill symp = (struct nlist *) 152619Sbill realloc(symp, 153619Sbill (i+1)*sizeof(struct nlist)); 154619Sbill if (symp == NULL) 155619Sbill error(1, "out of memory"); 156619Sbill symp[i++] = sym; 157619Sbill } 158619Sbill if (archive && ftell(fi)+sizeof(off_t) >= off) { 159619Sbill error(0, "no string table (old format .o?)"); 160619Sbill continue; 161619Sbill } 162619Sbill if (fread((char *)&strsiz,sizeof(strsiz),1,fi) != 1) { 163619Sbill error(0, "no string table (old format .o?)"); 164619Sbill goto out; 165619Sbill } 166619Sbill strp = (char *)malloc(strsiz); 167619Sbill if (strp == NULL) 168619Sbill error(1, "ran out of memory"); 169619Sbill if (fread(strp+sizeof(strsiz),strsiz-sizeof(strsiz),1,fi) != 1) 170619Sbill error(1, "error reading string table"); 171619Sbill for (j = 0; j < i; j++) 172619Sbill if (symp[j].n_un.n_strx) 173619Sbill symp[j].n_un.n_name = 174619Sbill symp[j].n_un.n_strx + strp; 175619Sbill else 176619Sbill symp[j].n_un.n_name = ""; 177619Sbill if (pflg==0) 178619Sbill qsort(symp, i, sizeof(struct nlist), compare); 179619Sbill if ((archive || narg>1) && oflg==0) 180619Sbill printf("\n%s:\n", SELECT); 181619Sbill psyms(symp, i); 182619Sbill if (symp) 183619Sbill free((char *)symp), symp = 0; 184619Sbill if (strp) 185619Sbill free((char *)strp), strp = 0; 186619Sbill } while(archive && nextel(fi)); 187619Sbill out: 188619Sbill fclose(fi); 189619Sbill } 190619Sbill 191619Sbill psyms(symp, nsyms) 192619Sbill register struct nlist *symp; 193619Sbill int nsyms; 194619Sbill { 195619Sbill register int n, c; 196619Sbill 197619Sbill for (n=0; n<nsyms; n++) { 198619Sbill c = symp[n].n_type; 199619Sbill if (c & N_STAB) { 200619Sbill if (oflg) { 201619Sbill if (archive) 202619Sbill printf("%s:", *xargv); 203619Sbill printf("%s:", SELECT); 204619Sbill } 205619Sbill printf("%08x - %02x %04x %5.5s %s\n", 206619Sbill symp[n].n_value, 207619Sbill symp[n].n_other & 0xff, symp[n].n_desc & 0xffff, 208619Sbill stab(symp[n].n_type & 0xff), 209619Sbill symp[n].n_un.n_name); 210619Sbill continue; 211619Sbill } 212619Sbill switch (c&N_TYPE) { 213619Sbill 214619Sbill case N_UNDF: 215619Sbill c = 'u'; 216619Sbill if (symp[n].n_value) 217619Sbill c = 'c'; 218619Sbill break; 219619Sbill case N_ABS: 220619Sbill c = 'a'; 221619Sbill break; 222619Sbill case N_TEXT: 223619Sbill c = 't'; 224619Sbill break; 225619Sbill case N_DATA: 226619Sbill c = 'd'; 227619Sbill break; 228619Sbill case N_BSS: 229619Sbill c = 'b'; 230619Sbill break; 231619Sbill case N_FN: 232619Sbill c = 'f'; 233619Sbill break; 234619Sbill } 235619Sbill if (uflg && c!='u') 236619Sbill continue; 237619Sbill if (oflg) { 238619Sbill if (archive) 239619Sbill printf("%s:", *xargv); 240619Sbill printf("%s:", SELECT); 241619Sbill } 242619Sbill if (symp[n].n_type&N_EXT) 243619Sbill c = toupper(c); 244619Sbill if (!uflg) { 245619Sbill if (c=='u' || c=='U') 246619Sbill printf(" "); 247619Sbill else 248619Sbill printf(N_FORMAT, symp[n].n_value); 249619Sbill printf(" %c ", c); 250619Sbill } 251619Sbill printf("%s\n", symp[n].n_un.n_name); 252619Sbill l1: ; 253619Sbill } 254619Sbill } 255619Sbill 256619Sbill compare(p1, p2) 257619Sbill struct nlist *p1, *p2; 258619Sbill { 259619Sbill register i; 260619Sbill 261619Sbill if (nflg) { 262619Sbill if (p1->n_value > p2->n_value) 263619Sbill return(rflg); 264619Sbill if (p1->n_value < p2->n_value) 265619Sbill return(-rflg); 266619Sbill } 267619Sbill return (rflg * strcmp(p1->n_un.n_name, p2->n_un.n_name)); 268619Sbill } 269619Sbill 270619Sbill nextel(af) 271619Sbill FILE *af; 272619Sbill { 273619Sbill register char *cp; 274619Sbill register r; 275619Sbill long arsize; 276619Sbill 277619Sbill fseek(af, off, 0); 278619Sbill r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af); 279619Sbill if (r != sizeof(struct ar_hdr)) 280619Sbill return(0); 281619Sbill for (cp = archdr.ar_name; cp < &archdr.ar_name[sizeof(archdr.ar_name)]; cp++) 282619Sbill if (*cp == ' ') 283619Sbill *cp = '\0'; 284619Sbill arsize = atol(archdr.ar_size); 285619Sbill if (arsize & 1) 286619Sbill ++arsize; 287619Sbill off = ftell(af) + arsize; /* beginning of next element */ 288619Sbill return(1); 289619Sbill } 290619Sbill 291619Sbill error(n, s) 292619Sbill char *s; 293619Sbill { 294619Sbill fprintf(stderr, "nm: %s:", *xargv); 295619Sbill if (archive) { 296619Sbill fprintf(stderr, "(%s)", archdr.ar_name); 297619Sbill fprintf(stderr, ": "); 298619Sbill } else 299619Sbill fprintf(stderr, " "); 300619Sbill fprintf(stderr, "%s\n", s); 301619Sbill if (n) 302619Sbill exit(2); 303619Sbill errs = 1; 304619Sbill } 305619Sbill 306619Sbill struct stabnames { 307619Sbill int st_value; 308619Sbill char *st_name; 309619Sbill } stabnames[] ={ 310619Sbill N_GSYM, "GSYM", 311619Sbill N_FNAME, "FNAME", 312619Sbill N_FUN, "FUN", 313619Sbill N_STSYM, "STSYM", 314619Sbill N_LCSYM, "LCSYM", 315619Sbill N_RSYM, "RSYM", 316619Sbill N_SLINE, "SLINE", 317619Sbill N_SSYM, "SSYM", 318619Sbill N_SO, "SO", 319619Sbill N_LSYM, "LSYM", 320619Sbill N_SOL, "SOL", 321619Sbill N_PSYM, "PSYM", 322619Sbill N_ENTRY, "ENTRY", 323619Sbill N_LBRAC, "LBRAC", 324619Sbill N_RBRAC, "RBRAC", 325619Sbill N_BCOMM, "BCOMM", 326619Sbill N_ECOMM, "ECOMM", 327619Sbill N_ECOML, "ECOML", 328619Sbill N_LENG, "LENG", 329859Sbill N_PC, "PC", 330619Sbill 0, 0 331619Sbill }; 332619Sbill 333619Sbill char * 334619Sbill stab(val) 335619Sbill { 336619Sbill register struct stabnames *sp; 337619Sbill static char prbuf[32]; 338619Sbill 339619Sbill for (sp = stabnames; sp->st_name; sp++) 340619Sbill if (sp->st_value == val) 341619Sbill return (sp->st_name); 342619Sbill sprintf(prbuf, "%02x", val); 343619Sbill return (prbuf); 344619Sbill } 345