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  }