plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

nm.c (4945B)


      1 /*
      2  * nm.c -- drive nm
      3  */
      4 #include <u.h>
      5 #include <libc.h>
      6 #include <ar.h>
      7 #include <bio.h>
      8 #include <mach.h>
      9 
     10 enum{
     11 	CHUNK	=	256	/* must be power of 2 */
     12 };
     13 
     14 char	*errs;			/* exit status */
     15 char	*filename;		/* current file */
     16 char	symname[]="__.SYMDEF";	/* table of contents file name */
     17 int	multifile;		/* processing multiple files */
     18 int	aflag;
     19 int	gflag;
     20 int	hflag;
     21 int	nflag;
     22 int	sflag;
     23 int	uflag;
     24 
     25 Symbol	**fnames;		/* file path translation table */
     26 Symbol	**symptr;
     27 int	nsym;
     28 Biobuf	bout;
     29 
     30 int	cmp(void*, void*);
     31 void	error(char*, ...);
     32 void	execsyms(int);
     33 void	psym(Symbol*, void*);
     34 void	printsyms(Symbol**, long);
     35 void	doar(Biobuf*);
     36 void	dofile(Biobuf*);
     37 void	zenter(Symbol*);
     38 
     39 void
     40 main(int argc, char *argv[])
     41 {
     42 	int i;
     43 	Biobuf	*bin;
     44 
     45 	Binit(&bout, 1, OWRITE);
     46 	argv0 = argv[0];
     47 	ARGBEGIN {
     48 	case 'a':	aflag = 1; break;
     49 	case 'g':	gflag = 1; break;
     50 	case 'h':	hflag = 1; break;
     51 	case 'n':	nflag = 1; break;
     52 	case 's':	sflag = 1; break;
     53 	case 'u':	uflag = 1; break;
     54 	} ARGEND
     55 	if (argc > 1)
     56 		multifile++;
     57 	for(i=0; i<argc; i++){
     58 		filename = argv[i];
     59 		bin = Bopen(filename, OREAD);
     60 		if(bin == 0){
     61 			error("cannot open %s", filename);
     62 			continue;
     63 		}
     64 		if (isar(bin))
     65 			doar(bin);
     66 		else{
     67 			Bseek(bin, 0, 0);
     68 			dofile(bin);
     69 		}
     70 		Bterm(bin);
     71 	}
     72 	exits(errs);
     73 }
     74 
     75 /*
     76  * read an archive file,
     77  * processing the symbols for each intermediate file in it.
     78  */
     79 void
     80 doar(Biobuf *bp)
     81 {
     82 	int offset, size, obj;
     83 	char membername[SARNAME];
     84 
     85 	multifile = 1;
     86 	for (offset = Boffset(bp);;offset += size) {
     87 		size = nextar(bp, offset, membername);
     88 		if (size < 0) {
     89 			error("phase error on ar header %ld", offset);
     90 			return;
     91 		}
     92 		if (size == 0)
     93 			return;
     94 		if (strcmp(membername, symname) == 0)
     95 			continue;
     96 		obj = objtype(bp, 0);
     97 		if (obj < 0) {
     98 			error("inconsistent file %s in %s",
     99 					membername, filename);
    100 			return;
    101 		}
    102 		if (!readar(bp, obj, offset+size, 1)) {
    103 			error("invalid symbol reference in file %s",
    104 					membername);
    105 			return;
    106 		}
    107 		filename = membername;
    108 		nsym=0;
    109 		objtraverse(psym, 0);
    110 		printsyms(symptr, nsym);
    111 	}
    112 }
    113 
    114 /*
    115  * process symbols in a file
    116  */
    117 void
    118 dofile(Biobuf *bp)
    119 {
    120 	int obj;
    121 
    122 	obj = objtype(bp, 0);
    123 	if (obj < 0)
    124 		execsyms(Bfildes(bp));
    125 	else
    126 	if (readobj(bp, obj)) {
    127 		nsym = 0;
    128 		objtraverse(psym, 0);
    129 		printsyms(symptr, nsym);
    130 	}
    131 }
    132 
    133 /*
    134  * comparison routine for sorting the symbol table
    135  *	this screws up on 'z' records when aflag == 1
    136  */
    137 int
    138 cmp(void *vs, void *vt)
    139 {
    140 	Symbol **s, **t;
    141 
    142 	s = vs;
    143 	t = vt;
    144 	if(nflag)
    145 		if((*s)->value < (*t)->value)
    146 			return -1;
    147 		else
    148 			return (*s)->value > (*t)->value;
    149 	return strcmp((*s)->name, (*t)->name);
    150 }
    151 /*
    152  * enter a symbol in the table of filename elements
    153  */
    154 void
    155 zenter(Symbol *s)
    156 {
    157 	static int maxf = 0;
    158 
    159 	if (s->value > maxf) {
    160 		maxf = (s->value+CHUNK-1) &~ (CHUNK-1);
    161 		fnames = realloc(fnames, (maxf+1)*sizeof(*fnames));
    162 		if(fnames == 0) {
    163 			error("out of memory", argv0);
    164 			exits("memory");
    165 		}
    166 	}
    167 	fnames[s->value] = s;
    168 }
    169 
    170 /*
    171  * get the symbol table from an executable file, if it has one
    172  */
    173 void
    174 execsyms(int fd)
    175 {
    176 	Fhdr f;
    177 	Symbol *s;
    178 	long n;
    179 
    180 	seek(fd, 0, 0);
    181 	if (crackhdr(fd, &f) == 0) {
    182 		error("Can't read header for %s", filename);
    183 		return;
    184 	}
    185 	if (syminit(fd, &f) < 0)
    186 		return;
    187 	s = symbase(&n);
    188 	nsym = 0;
    189 	while(n--)
    190 		psym(s++, 0);
    191 
    192 	printsyms(symptr, nsym);
    193 }
    194 
    195 void
    196 psym(Symbol *s, void* p)
    197 {
    198 	USED(p);
    199 	switch(s->type) {
    200 	case 'T':
    201 	case 'L':
    202 	case 'D':
    203 	case 'B':
    204 		if (uflag)
    205 			return;
    206 		if (!aflag && ((s->name[0] == '.' || s->name[0] == '$')))
    207 			return;
    208 		break;
    209 	case 'b':
    210 	case 'd':
    211 	case 'l':
    212 	case 't':
    213 		if (uflag || gflag)
    214 			return;
    215 		if (!aflag && ((s->name[0] == '.' || s->name[0] == '$')))
    216 			return;
    217 		break;
    218 	case 'U':
    219 		if (gflag)
    220 			return;
    221 		break;
    222 	case 'Z':
    223 		if (!aflag)
    224 			return;
    225 		break;
    226 	case 'm':
    227 	case 'f':	/* we only see a 'z' when the following is true*/
    228 		if(!aflag || uflag || gflag)
    229 			return;
    230 		if (strcmp(s->name, ".frame"))
    231 			zenter(s);
    232 		break;
    233 	case 'a':
    234 	case 'p':
    235 	case 'z':
    236 	default:
    237 		if(!aflag || uflag || gflag)
    238 			return;
    239 		break;
    240 	}
    241 	symptr = realloc(symptr, (nsym+1)*sizeof(Sym*));
    242 	if (symptr == 0) {
    243 		error("out of memory");
    244 		exits("memory");
    245 	}
    246 	symptr[nsym++] = s;
    247 }
    248 
    249 void
    250 printsyms(Symbol **symptr, long nsym)
    251 {
    252 	Symbol *s;
    253 	char *cp;
    254 	char path[512];
    255 
    256 	if(!sflag)
    257 		qsort(symptr, nsym, sizeof(*symptr), cmp);
    258 	while (nsym-- > 0) {
    259 		s = *symptr++;
    260 		if (multifile && !hflag)
    261 			Bprint(&bout, "%s:", filename);
    262 		if (s->type == 'z') {
    263 			fileelem(fnames, (uchar *) s->name, path, 512);
    264 			cp = path;
    265 		} else
    266 			cp = s->name;
    267 		if (s->value || s->type == 'a' || s->type == 'p')
    268 			Bprint(&bout, "%8lux %c %s\n", s->value, s->type, cp);
    269 		else
    270 			Bprint(&bout, "         %c %s\n", s->type, cp);
    271 	}
    272 }
    273 
    274 void
    275 error(char *fmt, ...)
    276 {
    277 	Fmt f;
    278 	char buf[128];
    279 	va_list arg;
    280 
    281 	fmtfdinit(&f, 2, buf, sizeof buf);
    282 	fmtprint(&f, "%s: ", argv0);
    283 	va_start(arg, fmt);
    284 	fmtvprint(&f, fmt, arg);
    285 	va_end(arg);
    286 	fmtprint(&f, "\n");
    287 	fmtfdflush(&f);
    288 	errs = "errors";
    289 }