github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/nm/nm.c (about) 1 // Inferno utils/nm/nm.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/nm/nm.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 /* 32 * nm.c -- drive nm 33 */ 34 #include <u.h> 35 #include <libc.h> 36 #include <ar.h> 37 #include <bio.h> 38 #include <mach.h> 39 40 enum{ 41 CHUNK = 256 /* must be power of 2 */ 42 }; 43 44 char *errs; /* exit status */ 45 char *filename; /* current file */ 46 char symname[]="__.GOSYMDEF"; /* table of contents file name */ 47 int multifile; /* processing multiple files */ 48 int aflag; 49 int gflag; 50 int hflag; 51 int nflag; 52 int sflag; 53 int Sflag; 54 int uflag; 55 int Tflag; 56 int tflag; 57 58 Sym **fnames; /* file path translation table */ 59 Sym **symptr; 60 int nsym; 61 Biobuf bout; 62 63 int cmp(void*, void*); 64 void error(char*, ...); 65 void execsyms(int); 66 void psym(Sym*, void*); 67 void printsyms(Sym**, long); 68 void doar(Biobuf*); 69 void dofile(Biobuf*); 70 void zenter(Sym*); 71 72 void 73 usage(void) 74 { 75 fprint(2, "usage: nm [-aghnsSTu] file ...\n"); 76 exits("usage"); 77 } 78 79 void 80 main(int argc, char *argv[]) 81 { 82 int i; 83 Biobuf *bin; 84 85 Binit(&bout, 1, OWRITE); 86 argv0 = argv[0]; 87 ARGBEGIN { 88 default: usage(); 89 case 'a': aflag = 1; break; 90 case 'g': gflag = 1; break; 91 case 'h': hflag = 1; break; 92 case 'n': nflag = 1; break; 93 case 's': sflag = 1; break; 94 case 'S': nflag = Sflag = 1; break; 95 case 'u': uflag = 1; break; 96 case 't': tflag = 1; break; 97 case 'T': Tflag = 1; break; 98 } ARGEND 99 if (argc == 0) 100 usage(); 101 if (argc > 1) 102 multifile++; 103 for(i=0; i<argc; i++){ 104 filename = argv[i]; 105 bin = Bopen(filename, OREAD); 106 if(bin == 0){ 107 error("cannot open %s", filename); 108 continue; 109 } 110 if (isar(bin)) 111 doar(bin); 112 else{ 113 Bseek(bin, 0, 0); 114 dofile(bin); 115 } 116 Bterm(bin); 117 } 118 exits(errs); 119 } 120 121 /* 122 * read an archive file, 123 * processing the symbols for each intermediate file in it. 124 */ 125 void 126 doar(Biobuf *bp) 127 { 128 int offset, size, obj; 129 char name[SARNAME]; 130 131 multifile = 1; 132 for (offset = Boffset(bp);;offset += size) { 133 size = nextar(bp, offset, name); 134 if (size < 0) { 135 error("phase error on ar header %d", offset); 136 return; 137 } 138 if (size == 0) 139 return; 140 if (strcmp(name, symname) == 0) 141 continue; 142 obj = objtype(bp, 0); 143 if (obj < 0) { 144 // perhaps foreign object 145 if(strlen(name) > 2 && strcmp(name+strlen(name)-2, ".o") == 0) 146 return; 147 error("inconsistent file %s in %s", 148 name, filename); 149 return; 150 } 151 if (!readar(bp, obj, offset+size, 1)) { 152 error("invalid symbol reference in file %s", 153 name); 154 return; 155 } 156 filename = name; 157 nsym=0; 158 objtraverse(psym, 0); 159 printsyms(symptr, nsym); 160 } 161 } 162 163 /* 164 * process symbols in a file 165 */ 166 void 167 dofile(Biobuf *bp) 168 { 169 int obj; 170 171 obj = objtype(bp, 0); 172 if (obj < 0) 173 execsyms(Bfildes(bp)); 174 else 175 if (readobj(bp, obj)) { 176 nsym = 0; 177 objtraverse(psym, 0); 178 printsyms(symptr, nsym); 179 } 180 } 181 182 /* 183 * comparison routine for sorting the symbol table 184 * this screws up on 'z' records when aflag == 1 185 */ 186 int 187 cmp(void *vs, void *vt) 188 { 189 Sym **s, **t; 190 191 s = vs; 192 t = vt; 193 if(nflag) // sort on address (numeric) order 194 if((*s)->value < (*t)->value) 195 return -1; 196 else 197 return (*s)->value > (*t)->value; 198 if(sflag) // sort on file order (sequence) 199 return (*s)->sequence - (*t)->sequence; 200 return strcmp((*s)->name, (*t)->name); 201 } 202 /* 203 * enter a symbol in the table of filename elements 204 */ 205 void 206 zenter(Sym *s) 207 { 208 static int maxf = 0; 209 210 if (s->value > maxf) { 211 maxf = (s->value+CHUNK-1) &~ (CHUNK-1); 212 fnames = realloc(fnames, (maxf+1)*sizeof(*fnames)); 213 if(fnames == 0) { 214 error("out of memory", argv0); 215 exits("memory"); 216 } 217 } 218 fnames[s->value] = s; 219 } 220 221 /* 222 * get the symbol table from an executable file, if it has one 223 */ 224 void 225 execsyms(int fd) 226 { 227 Fhdr f; 228 Sym *s; 229 int32 n; 230 231 seek(fd, 0, 0); 232 if (crackhdr(fd, &f) == 0) { 233 error("Can't read header for %s", filename); 234 return; 235 } 236 if (syminit(fd, &f) < 0) 237 return; 238 s = symbase(&n); 239 nsym = 0; 240 while(n--) 241 psym(s++, 0); 242 243 printsyms(symptr, nsym); 244 } 245 246 void 247 psym(Sym *s, void* p) 248 { 249 USED(p); 250 switch(s->type) { 251 case 'T': 252 case 'L': 253 case 'D': 254 case 'B': 255 if (uflag) 256 return; 257 if (!aflag && ((s->name[0] == '.' || s->name[0] == '$'))) 258 return; 259 break; 260 case 'b': 261 case 'd': 262 case 'l': 263 case 't': 264 if (uflag || gflag) 265 return; 266 if (!aflag && ((s->name[0] == '.' || s->name[0] == '$'))) 267 return; 268 break; 269 case 'U': 270 if (gflag) 271 return; 272 break; 273 case 'Z': 274 if (!aflag) 275 return; 276 break; 277 case 'm': 278 if(!aflag || uflag || gflag) 279 return; 280 break; 281 case 'f': /* we only see a 'z' when the following is true*/ 282 if(!aflag || uflag || gflag) 283 return; 284 zenter(s); 285 break; 286 case 'a': 287 case 'p': 288 case 'z': 289 default: 290 if(!aflag || uflag || gflag) 291 return; 292 break; 293 } 294 symptr = realloc(symptr, (nsym+1)*sizeof(Sym*)); 295 if (symptr == 0) { 296 error("out of memory"); 297 exits("memory"); 298 } 299 symptr[nsym++] = s; 300 } 301 302 const char *skipnames[] = { 303 "bss", 304 "data", 305 "ebss", 306 "edata", 307 "egcbss", 308 "egcdata", 309 "enoptrbss", 310 "enoptrdata", 311 "epclntab", 312 "erodata", 313 "esymtab", 314 "etext", 315 "etypelink", 316 "noptrbss", 317 "noptrdata", 318 "rodata", 319 "text", 320 }; 321 322 int 323 skipsize(char *name) 324 { 325 int i; 326 327 for(i=0; i<nelem(skipnames); i++) 328 if(strcmp(skipnames[i], name) == 0) 329 return 1; 330 return 0; 331 } 332 333 void 334 printsyms(Sym **symptr, long nsym) 335 { 336 int i, j, wid; 337 Sym *s; 338 char *cp; 339 char path[512]; 340 341 qsort(symptr, nsym, sizeof(*symptr), (void*)cmp); 342 343 wid = 0; 344 for (i=0; i<nsym; i++) { 345 s = symptr[i]; 346 if (s->value && wid == 0) 347 wid = 8; 348 else if (s->value >= 0x100000000LL && wid == 8) 349 wid = 16; 350 } 351 for (i=0; i<nsym; i++) { 352 s = symptr[i]; 353 if (multifile && !hflag) 354 Bprint(&bout, "%s:", filename); 355 if (s->type == 'z') { 356 fileelem(fnames, (uchar *) s->name, path, 512); 357 cp = path; 358 } else 359 cp = s->name; 360 if (Tflag) 361 Bprint(&bout, "%8ux ", s->sig); 362 if (s->value || s->type == 'a' || s->type == 'p') 363 Bprint(&bout, "%*llux ", wid, s->value); 364 else 365 Bprint(&bout, "%*s ", wid, ""); 366 if(Sflag && !skipsize(cp)) { 367 vlong siz; 368 369 siz = 0; 370 for(j=i+1; j<nsym; j++) { 371 if(!skipsize(symptr[j]->name) && symptr[j]->type != 'a' && symptr[j]->type != 'p') { 372 siz = symptr[j]->value - s->value; 373 break; 374 } 375 } 376 if(siz > 0) 377 Bprint(&bout, "%*llud ", wid, siz); 378 } 379 Bprint(&bout, "%c %s", s->type, cp); 380 if(tflag && s->gotype) 381 Bprint(&bout, " %*llux", wid, s->gotype); 382 Bprint(&bout, "\n"); 383 } 384 } 385 386 void 387 error(char *fmt, ...) 388 { 389 Fmt f; 390 char buf[128]; 391 va_list arg; 392 393 fmtfdinit(&f, 2, buf, sizeof buf); 394 fmtprint(&f, "%s: ", argv0); 395 va_start(arg, fmt); 396 fmtvprint(&f, fmt, arg); 397 va_end(arg); 398 fmtprint(&f, "\n"); 399 fmtfdflush(&f); 400 errs = "errors"; 401 }