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