scc-nm.c (4797B)
1 #include <ctype.h> 2 #include <errno.h> 3 #include <stdarg.h> 4 #include <stdint.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 9 #include <scc/ar.h> 10 #include <scc/arg.h> 11 #include <scc/mach.h> 12 13 14 struct symtbl { 15 Symbol **buf; 16 size_t nsyms; 17 }; 18 19 char *argv0; 20 static int status, multi; 21 static int radix = 16; 22 static int Pflag; 23 static int Aflag; 24 static int vflag; 25 static int gflag; 26 static int uflag; 27 static int fflag; 28 static char *filename, *membname; 29 30 static void 31 error(char *fmt, ...) 32 { 33 va_list va; 34 35 va_start(va, fmt); 36 fprintf(stderr, "nm: %s: ", filename); 37 if (membname) 38 fprintf(stderr, "%s: ", membname); 39 vfprintf(stderr, fmt, va); 40 putc('\n', stderr); 41 va_end(va); 42 43 status = EXIT_FAILURE; 44 } 45 46 static int 47 cmp(const void *p1, const void *p2) 48 { 49 Symbol **s1 = (Symbol **) p1, **s2 = (Symbol **) p2; 50 Symbol *sym1 = *s1, *sym2 = *s2; 51 52 if (vflag) { 53 if (sym1->value > sym2->value) 54 return 1; 55 if (sym1->value < sym2->value) 56 return -1; 57 if (sym1->type == 'U' && sym2->type == 'U') 58 return 0; 59 if (sym1->type == 'U') 60 return -1; 61 if (sym2->type == 'U') 62 return 1; 63 return 0; 64 } else { 65 return strcmp(sym1->name, sym2->name); 66 } 67 } 68 69 static void 70 printsyms(Symbol **syms, size_t nsym) 71 { 72 size_t i; 73 74 if (nsym == 0) { 75 error("no symbols"); 76 return; 77 } 78 qsort(syms, nsym, sizeof(syms), cmp); 79 80 if (!Aflag) { 81 if (multi || membname) 82 printf("%s:\n", (membname) ? membname : filename); 83 } 84 85 for (i = 0; i < nsym; i++) { 86 Symbol *sym = syms[i]; 87 int type = sym->type; 88 char *fmt; 89 90 if (Aflag) { 91 fmt = (membname) ? "%s[%s]: " : "%s: "; 92 printf(fmt, filename, membname); 93 } 94 95 if (Pflag) { 96 printf("%s %c", sym->name, sym->type); 97 if (type != 'U') { 98 if (radix == 8) 99 fmt = " %016.16llo %lo"; 100 else if (radix == 10) 101 fmt = " %016.16llu %lu"; 102 else 103 fmt = " %016.16llx %lx"; 104 printf(fmt, sym->value, sym->size); 105 } 106 } else { 107 if (type == 'U') 108 fmt = " "; 109 else if (radix == 8) 110 fmt = "%016.16llo"; 111 else if (radix == 10) 112 fmt = "%016.16lld"; 113 else 114 fmt = "%016.16llx"; 115 printf(fmt, sym->value); 116 printf(" %c %s", sym->type, sym->name); 117 } 118 putchar('\n'); 119 } 120 } 121 122 static int 123 newsym(Symbol *sym, struct symtbl *tbl) 124 { 125 Symbol **p, *s; 126 size_t n, size; 127 int type = sym->type; 128 int stype = sym->stype; 129 130 if (type == '?' && !fflag 131 || type == 'N' && !fflag 132 || stype != SYMFUNC && stype != SYMOBJECT && !fflag 133 || uflag && type != 'U' 134 || gflag && !isupper(type)) { 135 return 0; 136 } 137 138 n = tbl->nsyms+1; 139 size = n *sizeof(*p); 140 p = realloc(tbl->buf, size); 141 s = malloc(sizeof(*s)); 142 if (!p || !s) { 143 free(p); 144 free(s); 145 error(strerror(errno)); 146 return -1; 147 } 148 149 *s = *sym; 150 tbl->buf = p; 151 p[tbl->nsyms++] = s; 152 return 0; 153 } 154 155 static void 156 nmobj(FILE *fp, int type) 157 { 158 int i, err = 1; 159 Obj *obj; 160 Symbol sym; 161 struct symtbl tbl = {NULL, 0}; 162 163 if ((obj = newobj(type)) == NULL) { 164 error(strerror(errno)); 165 goto err1; 166 } 167 168 if (readobj(obj, fp) < 0) 169 goto err2; 170 171 for (i = 0; getsym(obj, &i, &sym); i++) { 172 if (newsym(&sym, &tbl) < 0) 173 goto err3; 174 } 175 176 printsyms(tbl.buf, tbl.nsyms); 177 err = 0; 178 179 err3: 180 free(tbl.buf); 181 err2: 182 delobj(obj); 183 err1: 184 if (err) 185 error("object file corrupted"); 186 } 187 188 static void 189 nmlib(FILE *fp) 190 { 191 int t; 192 long off, cur; 193 char memb[SARNAM+1]; 194 195 for (;;) { 196 cur = ftell(fp); 197 off = armember(fp, memb); 198 switch (off) { 199 case -1: 200 error("library corrupted"); 201 if (ferror(fp)) 202 error(strerror(errno)); 203 case 0: 204 return; 205 default: 206 membname = memb; 207 if ((t = objprobe(fp, NULL)) != -1) 208 nmobj(fp, t); 209 membname = NULL; 210 fseek(fp, cur, SEEK_SET); 211 fseek(fp, off, SEEK_CUR); 212 break; 213 } 214 } 215 } 216 217 static void 218 nm(char *fname) 219 { 220 int t; 221 FILE *fp; 222 223 filename = fname; 224 membname = NULL; 225 226 if ((fp = fopen(fname, "rb")) == NULL) { 227 error(strerror(errno)); 228 return; 229 } 230 231 if ((t = objprobe(fp, NULL)) != -1) 232 nmobj(fp, t); 233 else if (archive(fp)) 234 nmlib(fp); 235 else 236 error("bad format"); 237 238 fclose(fp); 239 } 240 241 static void 242 usage(void) 243 { 244 fputs("nm [-APvfa][-g|-u][-t format] [file...]\n", stderr); 245 exit(1); 246 } 247 248 int 249 main(int argc, char *argv[]) 250 { 251 char *t; 252 253 ARGBEGIN { 254 case 'P': 255 Pflag = 1; 256 break; 257 case 'A': 258 Aflag = 1; 259 break; 260 case 'g': 261 gflag = 1; 262 break; 263 case 'a': 264 case 'f': 265 fflag = 1; 266 break; 267 case 'u': 268 uflag = 1; 269 break; 270 case 'v': 271 vflag = 1; 272 break; 273 case 't': 274 t = EARGF(usage()); 275 if (!strcmp(t, "o")) 276 radix = 8; 277 else if (!strcmp(t, "d")) 278 radix = 10; 279 else if (!strcmp(t, "x")) 280 radix = 16; 281 else 282 usage(); 283 break; 284 default: 285 usage(); 286 } ARGEND 287 288 if (argc == 0) { 289 nm("a.out"); 290 } else { 291 if (argc > 1) 292 multi = 1; 293 for ( ; *argv; ++argv) 294 nm(*argv); 295 } 296 297 if (fflush(stdout) == EOF) { 298 fprintf(stderr, 299 "nm: error writing in output:%s\n", 300 strerror(errno)); 301 status = 1; 302 } 303 304 return status; 305 }