xref: /freebsd/contrib/elftoolchain/nm/nm.c (revision dcf58f92e2c19a32fc171f763698e711c719badc)
1 /*-
2  * Copyright (c) 2007 Hyogeol Lee <hyogeollee@gmail.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer
10  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/queue.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <ar.h>
31 #include <assert.h>
32 #include <ctype.h>
33 #include <dwarf.h>
34 #include <err.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <gelf.h>
38 #include <getopt.h>
39 #include <inttypes.h>
40 #include <libdwarf.h>
41 #include <libelftc.h>
42 #include <stdbool.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <strings.h>
47 #include <unistd.h>
48 
49 #include "_elftc.h"
50 
51 ELFTC_VCSID("$Id: nm.c 2484 2012-04-07 15:52:05Z kaiwang27 $");
52 
53 /* symbol information list */
54 STAILQ_HEAD(sym_head, sym_entry);
55 
56 struct sym_entry {
57 	char		*name;
58 	GElf_Sym	*sym;
59 	STAILQ_ENTRY(sym_entry) sym_entries;
60 };
61 
62 typedef int (*fn_sort)(const void *, const void *);
63 typedef void (*fn_elem_print)(char, const char *, const GElf_Sym *, const char *);
64 typedef void (*fn_sym_print)(const GElf_Sym *);
65 typedef int (*fn_filter)(char, const GElf_Sym *, const char *);
66 
67 /* output filter list */
68 SLIST_HEAD(filter_head, filter_entry) nm_out_filter =
69     SLIST_HEAD_INITIALIZER(nm_out_filter);
70 
71 struct filter_entry {
72 	fn_filter	fn;
73 	SLIST_ENTRY(filter_entry) filter_entries;
74 };
75 
76 struct sym_print_data {
77 	struct sym_head	*headp;
78 	size_t		sh_num, list_num;
79 	const char	*t_table, **s_table, *filename, *objname;
80 };
81 
82 struct nm_prog_info {
83 	const char	*name;
84 	const char	*def_filename;
85 };
86 
87 /* List for line number information. */
88 struct line_info_entry {
89 	uint64_t	addr;	/* address */
90 	uint64_t	line;	/* line number */
91 	char		*file;	/* file name with path */
92 	SLIST_ENTRY(line_info_entry) entries;
93 };
94 SLIST_HEAD(line_info_head, line_info_entry);
95 
96 /* List for function line number information. */
97 struct func_info_entry {
98 	char		*name;	/* function name */
99 	char		*file;	/* file name with path */
100 	uint64_t	lowpc;	/* low address */
101 	uint64_t	highpc;	/* high address */
102 	uint64_t	line;	/* line number */
103 	SLIST_ENTRY(func_info_entry) entries;
104 };
105 SLIST_HEAD(func_info_head, func_info_entry);
106 
107 /* List for variable line number information. */
108 struct var_info_entry {
109 	char		*name;	/* variable name */
110 	char		*file;	/* file name with path */
111 	uint64_t	addr;	/* address */
112 	uint64_t	line;	/* line number */
113 	SLIST_ENTRY(var_info_entry) entries;
114 };
115 SLIST_HEAD(var_info_head, var_info_entry);
116 
117 /* output numric type */
118 enum radix {
119 	RADIX_OCT,
120 	RADIX_HEX,
121 	RADIX_DEC
122 };
123 
124 /* output symbol type, PRINT_SYM_DYN for dynamic symbol only */
125 enum print_symbol {
126 	PRINT_SYM_SYM,
127 	PRINT_SYM_DYN
128 };
129 
130 /* output name type */
131 enum print_name {
132 	PRINT_NAME_NONE,
133 	PRINT_NAME_FULL,
134 	PRINT_NAME_MULTI
135 };
136 
137 struct nm_prog_options {
138 	enum print_symbol	print_symbol;
139 	enum print_name		print_name;
140 	enum radix		t;
141 	int			demangle_type;
142 	bool			print_debug;
143 	bool			print_armap;
144 	int			print_size;
145 	bool			debug_line;
146 	int			def_only;
147 	bool			undef_only;
148 	int			sort_size;
149 	bool			sort_reverse;
150 	int			no_demangle;
151 
152 	/*
153 	 * function pointer to sort symbol list.
154 	 * possible function - cmp_name, cmp_none, cmp_size, cmp_value
155 	 */
156 	fn_sort			sort_fn;
157 
158 	/*
159 	 * function pointer to print symbol elem.
160 	 * possible function - sym_elem_print_all
161 	 *		       sym_elem_print_all_portable
162 	 *		       sym_elem_print_all_sysv
163 	 */
164 	fn_elem_print		elem_print_fn;
165 
166 	fn_sym_print		value_print_fn;
167 	fn_sym_print		size_print_fn;
168 };
169 
170 #define	CHECK_SYM_PRINT_DATA(p)	(p->headp == NULL || p->sh_num == 0 ||	      \
171 p->t_table == NULL || p->s_table == NULL || p->filename == NULL)
172 #define	IS_SYM_TYPE(t)		((t) == '?' || isalpha((t)) != 0)
173 #define	IS_UNDEF_SYM_TYPE(t)	((t) == 'U' || (t) == 'v' || (t) == 'w')
174 #define	UNUSED(p)		((void)p)
175 
176 static int		cmp_name(const void *, const void *);
177 static int		cmp_none(const void *, const void *);
178 static int		cmp_size(const void *, const void *);
179 static int		cmp_value(const void *, const void *);
180 static void		filter_dest(void);
181 static int		filter_insert(fn_filter);
182 static void		get_opt(int, char **);
183 static int		get_sym(Elf *, struct sym_head *, int, size_t, size_t,
184 			    const char *, const char **, int);
185 static const char *	get_sym_name(Elf *, const GElf_Sym *, size_t,
186 			    const char **, int);
187 static char		get_sym_type(const GElf_Sym *, const char *);
188 static void		global_dest(void);
189 static void		global_init(void);
190 static bool		is_sec_data(GElf_Shdr *);
191 static bool		is_sec_debug(const char *);
192 static bool		is_sec_nobits(GElf_Shdr *);
193 static bool		is_sec_readonly(GElf_Shdr *);
194 static bool		is_sec_text(GElf_Shdr *);
195 static void		print_ar_index(int, Elf *);
196 static void		print_header(const char *, const char *);
197 static void		print_version(void);
198 static int		read_elf(Elf *, const char *, Elf_Kind);
199 static int		read_object(const char *);
200 static int		read_files(int, char **);
201 static void		set_opt_value_print_fn(enum radix);
202 static int		sym_elem_def(char, const GElf_Sym *, const char *);
203 static int		sym_elem_global(char, const GElf_Sym *, const char *);
204 static int		sym_elem_global_static(char, const GElf_Sym *,
205 			    const char *);
206 static int		sym_elem_nondebug(char, const GElf_Sym *, const char *);
207 static int		sym_elem_nonzero_size(char, const GElf_Sym *,
208 			    const char *);
209 static void		sym_elem_print_all(char, const char *,
210 			    const GElf_Sym *, const char *);
211 static void		sym_elem_print_all_portable(char, const char *,
212 			    const GElf_Sym *, const char *);
213 static void		sym_elem_print_all_sysv(char, const char *,
214 			    const GElf_Sym *, const char *);
215 static int		sym_elem_undef(char, const GElf_Sym *, const char *);
216 static void		sym_list_dest(struct sym_head *);
217 static int		sym_list_insert(struct sym_head *, const char *,
218 			    const GElf_Sym *);
219 static void		sym_list_print(struct sym_print_data *,
220 			    struct func_info_head *, struct var_info_head *,
221 			    struct line_info_head *);
222 static void		sym_list_print_each(struct sym_entry *,
223 			    struct sym_print_data *, struct func_info_head *,
224 			    struct var_info_head *, struct line_info_head *);
225 static struct sym_entry	*sym_list_sort(struct sym_print_data *);
226 static void		sym_size_oct_print(const GElf_Sym *);
227 static void		sym_size_hex_print(const GElf_Sym *);
228 static void		sym_size_dec_print(const GElf_Sym *);
229 static void		sym_value_oct_print(const GElf_Sym *);
230 static void		sym_value_hex_print(const GElf_Sym *);
231 static void		sym_value_dec_print(const GElf_Sym *);
232 static void		usage(int);
233 
234 static struct nm_prog_info	nm_info;
235 static struct nm_prog_options	nm_opts;
236 static int			nm_elfclass;
237 
238 /*
239  * Point to current sym_print_data to use portable qsort function.
240  *  (e.g. There is no qsort_r function in NetBSD.)
241  *
242  * Using in sym_list_sort.
243  */
244 static struct sym_print_data	*nm_print_data;
245 
246 static const struct option nm_longopts[] = {
247 	{ "debug-syms",		no_argument,		NULL,		'a' },
248 	{ "defined-only",	no_argument,		&nm_opts.def_only, 1},
249 	{ "demangle",		optional_argument,	NULL,		'C' },
250 	{ "dynamic",		no_argument,		NULL,		'D' },
251 	{ "format",		required_argument,	NULL,		'F' },
252 	{ "help",		no_argument,		NULL,		'h' },
253 	{ "line-numbers",	no_argument,		NULL,		'l' },
254 	{ "no-demangle",	no_argument,		&nm_opts.no_demangle,
255 	  1},
256 	{ "no-sort",		no_argument,		NULL,		'p' },
257 	{ "numeric-sort",	no_argument,		NULL,		'v' },
258 	{ "print-armap",	no_argument,		NULL,		's' },
259 	{ "print-file-name",	no_argument,		NULL,		'A' },
260 	{ "print-size",		no_argument,		NULL,		'S' },
261 	{ "radix",		required_argument,	NULL,		't' },
262 	{ "reverse-sort",	no_argument,		NULL,		'r' },
263 	{ "size-sort",		no_argument,		&nm_opts.sort_size, 1},
264 	{ "undefined-only",	no_argument,		NULL,		'u' },
265 	{ "version",		no_argument,		NULL,		'V' },
266 	{ NULL,			0,			NULL,		0   }
267 };
268 
269 #if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS)
270 static __inline uint32_t
271 be32dec(const void *pp)
272 {
273 	unsigned char const *p = (unsigned char const *)pp;
274 
275 	return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
276 }
277 
278 static __inline uint32_t
279 le32dec(const void *pp)
280 {
281 	unsigned char const *p = (unsigned char const *)pp;
282 
283 	return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
284 }
285 
286 static __inline uint64_t
287 be64dec(const void *pp)
288 {
289 	unsigned char const *p = (unsigned char const *)pp;
290 
291 	return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4));
292 }
293 
294 static __inline uint64_t
295 le64dec(const void *pp)
296 {
297 	unsigned char const *p = (unsigned char const *)pp;
298 
299 	return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p));
300 }
301 #endif
302 
303 static int
304 cmp_name(const void *l, const void *r)
305 {
306 
307 	assert(l != NULL);
308 	assert(r != NULL);
309 	assert(((const struct sym_entry *)l)->name != NULL);
310 	assert(((const struct sym_entry *)r)->name != NULL);
311 
312 	return (strcmp(((const struct sym_entry *)l)->name,
313 	    ((const struct sym_entry *)r)->name));
314 }
315 
316 static int
317 cmp_none(const void *l, const void *r)
318 {
319 
320 	UNUSED(l);
321 	UNUSED(r);
322 
323 	return (0);
324 }
325 
326 /* Size comparison. If l and r have same size, compare their name. */
327 static int
328 cmp_size(const void *lp, const void *rp)
329 {
330 	const struct sym_entry *l, *r;
331 
332 	l = lp;
333 	r = rp;
334 
335 	assert(l != NULL);
336 	assert(l->name != NULL);
337 	assert(l->sym != NULL);
338 	assert(r != NULL);
339 	assert(r->name != NULL);
340 	assert(r->sym != NULL);
341 
342 	if (l->sym->st_size == r->sym->st_size)
343 		return (strcmp(l->name, r->name));
344 
345 	return (l->sym->st_size - r->sym->st_size);
346 }
347 
348 /* Value comparison. Undefined symbols come first. */
349 static int
350 cmp_value(const void *lp, const void *rp)
351 {
352 	const struct sym_entry *l, *r;
353 	const char *ttable;
354 	int l_is_undef, r_is_undef;
355 
356 	l = lp;
357 	r = rp;
358 
359 	assert(nm_print_data != NULL);
360 	ttable = nm_print_data->t_table;
361 
362 	assert(l != NULL);
363 	assert(l->name != NULL);
364 	assert(l->sym != NULL);
365 	assert(r != NULL);
366 	assert(r->name != NULL);
367 	assert(r->sym != NULL);
368 	assert(ttable != NULL);
369 
370 	l_is_undef = IS_UNDEF_SYM_TYPE(get_sym_type(l->sym, ttable)) ? 1 : 0;
371 	r_is_undef = IS_UNDEF_SYM_TYPE(get_sym_type(r->sym, ttable)) ? 1 : 0;
372 
373 	assert(l_is_undef + r_is_undef >= 0);
374 	assert(l_is_undef + r_is_undef <= 2);
375 
376 	switch (l_is_undef + r_is_undef) {
377 	case 0:
378 		/* Both defined */
379 		if (l->sym->st_value == r->sym->st_value)
380 			return (strcmp(l->name, r->name));
381 		return (l->sym->st_value - r->sym->st_value);
382 	case 1:
383 		/* One undefined */
384 		return (l_is_undef == 0 ? 1 : -1);
385 	case 2:
386 		/* Both undefined */
387 		return (strcmp(l->name, r->name));
388 	}
389 	/* NOTREACHED */
390 
391 	return (l->sym->st_value - r->sym->st_value);
392 }
393 
394 static void
395 filter_dest(void)
396 {
397 	struct filter_entry *e;
398 
399 	while (!SLIST_EMPTY(&nm_out_filter)) {
400 		e = SLIST_FIRST(&nm_out_filter);
401 		SLIST_REMOVE_HEAD(&nm_out_filter, filter_entries);
402 		free(e);
403 	}
404 }
405 
406 static int
407 filter_insert(fn_filter filter_fn)
408 {
409 	struct filter_entry *e;
410 
411 	assert(filter_fn != NULL);
412 
413 	if ((e = malloc(sizeof(struct filter_entry))) == NULL) {
414 		warn("malloc");
415 		return (0);
416 	}
417 	e->fn = filter_fn;
418 	SLIST_INSERT_HEAD(&nm_out_filter, e, filter_entries);
419 
420 	return (1);
421 }
422 
423 static int
424 parse_demangle_option(const char *opt)
425 {
426 
427 	if (opt == NULL)
428 		return (ELFTC_DEM_UNKNOWN);
429 	else if (!strncasecmp(opt, "gnu-v2", 6))
430 		return (ELFTC_DEM_GNU2);
431 	else if (!strncasecmp(opt, "gnu-v3", 6))
432 		return (ELFTC_DEM_GNU3);
433 	else if (!strncasecmp(opt, "arm", 3))
434 		return (ELFTC_DEM_ARM);
435 	else
436 		errx(EXIT_FAILURE, "unknown demangling style '%s'", opt);
437 
438 	/* NOTREACHED */
439 	return (0);
440 }
441 
442 static void
443 get_opt(int argc, char **argv)
444 {
445 	int ch;
446 	bool is_posix, oflag;
447 
448 	if (argc <= 0 || argv == NULL)
449 		return;
450 
451 	oflag = is_posix = false;
452 	nm_opts.t = RADIX_HEX;
453 	while ((ch = getopt_long(argc, argv, "ABCDF:PSVaefghlnoprst:uvx",
454 		    nm_longopts, NULL)) != -1) {
455 		switch (ch) {
456 		case 'A':
457 			nm_opts.print_name = PRINT_NAME_FULL;
458 			break;
459 		case 'B':
460 			nm_opts.elem_print_fn = &sym_elem_print_all;
461 			break;
462 		case 'C':
463 			nm_opts.demangle_type = parse_demangle_option(optarg);
464 			break;
465 		case 'D':
466 			nm_opts.print_symbol = PRINT_SYM_DYN;
467 			break;
468 		case 'F':
469 			/* sysv, bsd, posix */
470 			switch (optarg[0]) {
471 			case 'B':
472 			case 'b':
473 				nm_opts.elem_print_fn = &sym_elem_print_all;
474 				break;
475 			case 'P':
476 			case 'p':
477 				is_posix = true;
478 				nm_opts.elem_print_fn =
479 				    &sym_elem_print_all_portable;
480 				break;
481 			case 'S':
482 			case 's':
483 				nm_opts.elem_print_fn =
484 				    &sym_elem_print_all_sysv;
485 				break;
486 			default:
487 				warnx("%s: Invalid format", optarg);
488 				usage(1);
489 			}
490 
491 			break;
492 		case 'P':
493 			is_posix = true;
494 			nm_opts.elem_print_fn = &sym_elem_print_all_portable;
495 			break;
496 		case 'S':
497 			nm_opts.print_size = 1;
498 			break;
499 		case 'V':
500 			print_version();
501 			/* NOTREACHED */
502 		case 'a':
503 			nm_opts.print_debug = true;
504 			break;
505 		case 'e':
506 			filter_insert(sym_elem_global_static);
507 			break;
508 		case 'f':
509 			break;
510 		case 'g':
511 			filter_insert(sym_elem_global);
512 			break;
513 		case 'h':
514 			usage(0);
515 			break;
516 		case 'l':
517 			nm_opts.debug_line = true;
518 			break;
519 		case 'n':
520 		case 'v':
521 			nm_opts.sort_fn = &cmp_value;
522 			break;
523 		case 'o':
524 			oflag = true;
525 			break;
526 		case 'p':
527 			nm_opts.sort_fn = &cmp_none;
528 			break;
529 		case 'r':
530 			nm_opts.sort_reverse = true;
531 			break;
532 		case 's':
533 			nm_opts.print_armap = true;
534 			break;
535 		case 't':
536 			/* t require always argument to getopt_long */
537 			switch (optarg[0]) {
538 			case 'd':
539 				nm_opts.t = RADIX_DEC;
540 				break;
541 			case 'o':
542 				nm_opts.t = RADIX_OCT;
543 				break;
544 			case 'x':
545 				nm_opts.t = RADIX_HEX;
546 				break;
547 			default:
548 				warnx("%s: Invalid radix", optarg);
549 				usage(1);
550 			}
551 			break;
552 		case 'u':
553 			filter_insert(sym_elem_undef);
554 			nm_opts.undef_only = true;
555 			break;
556 		/* case 'v': see case 'n' above. */
557 		case 'x':
558 			nm_opts.t = RADIX_HEX;
559 			break;
560 		case 0:
561 			if (nm_opts.sort_size != 0) {
562 				nm_opts.sort_fn = &cmp_size;
563 				filter_insert(sym_elem_def);
564 				filter_insert(sym_elem_nonzero_size);
565 			}
566 			if (nm_opts.def_only != 0)
567 				filter_insert(sym_elem_def);
568 			if (nm_opts.no_demangle != 0)
569 				nm_opts.demangle_type = -1;
570 			break;
571 		default :
572 			usage(1);
573 		}
574 	}
575 
576 	/*
577 	 * In POSIX mode, the '-o' option controls the output radix.
578 	 * In non-POSIX mode, the option is a synonym for the '-A' and
579 	 * '--print-file-name' options.
580 	 */
581 	if (oflag) {
582 		if (is_posix)
583 			nm_opts.t = RADIX_OCT;
584 		else
585 			nm_opts.print_name = PRINT_NAME_FULL;
586 	}
587 
588 	assert(nm_opts.sort_fn != NULL && "nm_opts.sort_fn is null");
589 	assert(nm_opts.elem_print_fn != NULL &&
590 	    "nm_opts.elem_print_fn is null");
591 	assert(nm_opts.value_print_fn != NULL &&
592 	    "nm_opts.value_print_fn is null");
593 
594 	set_opt_value_print_fn(nm_opts.t);
595 
596 	if (nm_opts.undef_only == true) {
597 		if (nm_opts.sort_fn == &cmp_size)
598 			errx(EXIT_FAILURE,
599 			    "--size-sort with -u is meaningless");
600 		if (nm_opts.def_only != 0)
601 			errx(EXIT_FAILURE,
602 			    "-u with --defined-only is meaningless");
603 	}
604 	if (nm_opts.print_debug == false)
605 		filter_insert(sym_elem_nondebug);
606 	if (nm_opts.sort_reverse == true && nm_opts.sort_fn == cmp_none)
607 		nm_opts.sort_reverse = false;
608 }
609 
610 /*
611  * Get symbol information from elf.
612  */
613 static int
614 get_sym(Elf *elf, struct sym_head *headp, int shnum, size_t dynndx,
615     size_t strndx, const char *type_table, const char **sec_table,
616     int sec_table_size)
617 {
618 	Elf_Scn *scn;
619 	Elf_Data *data;
620 	GElf_Shdr shdr;
621 	GElf_Sym sym;
622 	struct filter_entry *fep;
623 	size_t ndx;
624 	int rtn;
625 	const char *sym_name;
626 	char type;
627 	bool filter;
628 	int i, j;
629 
630 	assert(elf != NULL);
631 	assert(headp != NULL);
632 
633 	rtn = 0;
634 	for (i = 1; i < shnum; i++) {
635 		if ((scn = elf_getscn(elf, i)) == NULL) {
636 			warnx("elf_getscn failed: %s", elf_errmsg(-1));
637 			continue;
638 		}
639 		if (gelf_getshdr(scn, &shdr) != &shdr) {
640 			warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
641 			continue;
642 		}
643 		if (shdr.sh_type == SHT_SYMTAB) {
644 			if (nm_opts.print_symbol != PRINT_SYM_SYM)
645 				continue;
646 		} else if (shdr.sh_type == SHT_DYNSYM) {
647 			if (nm_opts.print_symbol != PRINT_SYM_DYN)
648 				continue;
649 		} else
650 			continue;
651 
652 		ndx = shdr.sh_type == SHT_DYNSYM ? dynndx : strndx;
653 
654 		data = NULL;
655 		while ((data = elf_getdata(scn, data)) != NULL) {
656 			j = 1;
657 			while (gelf_getsym(data, j++, &sym) != NULL) {
658 				sym_name = get_sym_name(elf, &sym, ndx,
659 				    sec_table, sec_table_size);
660 				filter = false;
661 				type = get_sym_type(&sym, type_table);
662 				SLIST_FOREACH(fep, &nm_out_filter,
663 				    filter_entries) {
664 					if (!fep->fn(type, &sym, sym_name)) {
665 						filter = true;
666 						break;
667 					}
668 				}
669 				if (filter == false) {
670 					if (sym_list_insert(headp, sym_name,
671 					    &sym) == 0)
672 						return (0);
673 					rtn++;
674 				}
675 			}
676 		}
677 	}
678 
679 	return (rtn);
680 }
681 
682 static const char *
683 get_sym_name(Elf *elf, const GElf_Sym *sym, size_t ndx, const char **sec_table,
684     int sec_table_size)
685 {
686 	const char *sym_name;
687 
688 	sym_name = NULL;
689 
690 	/* Show section name as symbol name for STT_SECTION symbols. */
691 	if (GELF_ST_TYPE(sym->st_info) == STT_SECTION) {
692 		if (sec_table != NULL && sym->st_shndx < sec_table_size)
693 			sym_name = sec_table[sym->st_shndx];
694 	} else
695 		sym_name = elf_strptr(elf, ndx, sym->st_name);
696 
697 	if (sym_name == NULL)
698 		sym_name = "(null)";
699 
700 	return (sym_name);
701 }
702 
703 static char
704 get_sym_type(const GElf_Sym *sym, const char *type_table)
705 {
706 	bool is_local;
707 
708 	if (sym == NULL || type_table == NULL)
709 		return ('?');
710 
711 	is_local = sym->st_info >> 4 == STB_LOCAL;
712 
713 	if (sym->st_shndx == SHN_ABS) /* absolute */
714 		return (is_local ? 'a' : 'A');
715 
716 	if (sym->st_shndx == SHN_COMMON) /* common */
717 		return ('C');
718 
719 	if ((sym->st_info) >> 4 == STB_WEAK) { /* weak */
720 		if ((sym->st_info & 0xf) == STT_OBJECT)
721 			return (sym->st_shndx == SHN_UNDEF ? 'v' : 'V');
722 
723 		return (sym->st_shndx == SHN_UNDEF ? 'w' : 'W');
724 	}
725 
726 	if (sym->st_shndx == SHN_UNDEF) /* undefined */
727 		return ('U');
728 
729 	return (is_local == true && type_table[sym->st_shndx] != 'N' ?
730 	    tolower((unsigned char) type_table[sym->st_shndx]) :
731 	    type_table[sym->st_shndx]);
732 }
733 
734 static void
735 global_dest(void)
736 {
737 
738 	filter_dest();
739 }
740 
741 static void
742 global_init(void)
743 {
744 
745 	if (elf_version(EV_CURRENT) == EV_NONE)
746 		errx(EXIT_FAILURE, "elf_version error");
747 
748 	nm_info.name = ELFTC_GETPROGNAME();
749 	nm_info.def_filename = "a.out";
750 	nm_opts.print_symbol = PRINT_SYM_SYM;
751 	nm_opts.print_name = PRINT_NAME_NONE;
752 	nm_opts.demangle_type = -1;
753 	nm_opts.print_debug = false;
754 	nm_opts.print_armap = false;
755 	nm_opts.print_size = 0;
756 	nm_opts.debug_line = false;
757 	nm_opts.def_only = 0;
758 	nm_opts.undef_only = false;
759 	nm_opts.sort_size = 0;
760 	nm_opts.sort_reverse = false;
761 	nm_opts.no_demangle = 0;
762 	nm_opts.sort_fn = &cmp_name;
763 	nm_opts.elem_print_fn = &sym_elem_print_all;
764 	nm_opts.value_print_fn = &sym_value_dec_print;
765 	nm_opts.size_print_fn = &sym_size_dec_print;
766 	SLIST_INIT(&nm_out_filter);
767 }
768 
769 static bool
770 is_sec_data(GElf_Shdr *s)
771 {
772 
773 	assert(s != NULL && "shdr is NULL");
774 
775 	return (((s->sh_flags & SHF_ALLOC) != 0) && s->sh_type != SHT_NOBITS);
776 }
777 
778 static bool
779 is_sec_debug(const char *shname)
780 {
781 	const char *dbg_sec[] = {
782 		".debug",
783 		".gnu.linkonce.wi.",
784 		".line",
785 		".rel.debug",
786 		".rela.debug",
787 		".stab",
788 		NULL
789 	};
790 	const char **p;
791 
792 	assert(shname != NULL && "shname is NULL");
793 
794 	for (p = dbg_sec; *p; p++) {
795 		if (!strncmp(shname, *p, strlen(*p)))
796 			return (true);
797 	}
798 
799 	return (false);
800 }
801 
802 static bool
803 is_sec_nobits(GElf_Shdr *s)
804 {
805 
806 	assert(s != NULL && "shdr is NULL");
807 
808 	return (s->sh_type == SHT_NOBITS);
809 }
810 
811 static bool
812 is_sec_readonly(GElf_Shdr *s)
813 {
814 
815 	assert(s != NULL && "shdr is NULL");
816 
817 	return ((s->sh_flags & SHF_WRITE) == 0);
818 }
819 
820 static bool
821 is_sec_text(GElf_Shdr *s)
822 {
823 
824 	assert(s != NULL && "shdr is NULL");
825 
826 	return ((s->sh_flags & SHF_EXECINSTR) != 0);
827 }
828 
829 static void
830 print_ar_index(int fd, Elf *arf)
831 {
832 	Elf *elf;
833 	Elf_Arhdr *arhdr;
834 	Elf_Arsym *arsym;
835 	Elf_Cmd cmd;
836 	off_t start;
837 	size_t arsym_size;
838 
839 	if (arf == NULL)
840 		return;
841 
842 	if ((arsym = elf_getarsym(arf, &arsym_size)) == NULL)
843 		return;
844 
845 	printf("\nArchive index:\n");
846 
847 	start = arsym->as_off;
848 	cmd = ELF_C_READ;
849 	while (arsym_size > 1) {
850 		if (elf_rand(arf, arsym->as_off) == arsym->as_off &&
851 		    (elf = elf_begin(fd, cmd, arf)) != NULL) {
852 			if ((arhdr = elf_getarhdr(elf)) != NULL)
853 				printf("%s in %s\n", arsym->as_name,
854 				    arhdr->ar_name != NULL ?
855 				    arhdr->ar_name : arhdr->ar_rawname);
856 			elf_end(elf);
857 		}
858 		++arsym;
859 		--arsym_size;
860 	}
861 
862 	elf_rand(arf, start);
863 }
864 
865 #define	DEMANGLED_BUFFER_SIZE	(8 * 1024)
866 #define	PRINT_DEMANGLED_NAME(FORMAT, NAME) do {				\
867 	char _demangled[DEMANGLED_BUFFER_SIZE];				\
868 	if (nm_opts.demangle_type < 0 ||				\
869 	    elftc_demangle((NAME), _demangled, sizeof(_demangled),	\
870 		nm_opts.demangle_type) < 0)				\
871 		printf((FORMAT), (NAME));				\
872 	else								\
873 		printf((FORMAT), _demangled);				\
874 	} while (0)
875 
876 static void
877 print_header(const char *file, const char *obj)
878 {
879 
880 	if (file == NULL)
881 		return;
882 
883 	if (nm_opts.elem_print_fn == &sym_elem_print_all_sysv) {
884 		printf("\n\n%s from %s",
885 		    nm_opts.undef_only == false ? "Symbols" :
886 		    "Undefined symbols", file);
887 		if (obj != NULL)
888 			printf("[%s]", obj);
889 		printf(":\n\n");
890 
891 		printf("\
892 Name                  Value           Class        Type         Size             Line  Section\n\n");
893 	} else {
894 		/* archive file without -A option and POSIX */
895 		if (nm_opts.print_name != PRINT_NAME_FULL && obj != NULL) {
896 			if (nm_opts.elem_print_fn ==
897 			    sym_elem_print_all_portable)
898 				printf("%s[%s]:\n", file, obj);
899 			else if (nm_opts.elem_print_fn == sym_elem_print_all)
900 				printf("\n%s:\n", obj);
901 			/* multiple files(not archive) without -A option */
902 		} else if (nm_opts.print_name == PRINT_NAME_MULTI) {
903 			if (nm_opts.elem_print_fn == sym_elem_print_all)
904 				printf("\n");
905 			printf("%s:\n", file);
906 		}
907 	}
908 }
909 
910 static void
911 print_version(void)
912 {
913 
914 	(void) printf("%s (%s)\n", nm_info.name, elftc_version());
915 	exit(0);
916 }
917 
918 static uint64_t
919 get_block_value(Dwarf_Debug dbg, Dwarf_Block *block)
920 {
921 	Elf *elf;
922 	GElf_Ehdr eh;
923 	Dwarf_Error de;
924 
925 	if (dwarf_get_elf(dbg, &elf, &de) != DW_DLV_OK) {
926 		warnx("dwarf_get_elf failed: %s", dwarf_errmsg(de));
927 		return (0);
928 	}
929 
930 	if (gelf_getehdr(elf, &eh) != &eh) {
931 		warnx("gelf_getehdr failed: %s", elf_errmsg(-1));
932 		return (0);
933 	}
934 
935 	if (block->bl_len == 5) {
936 		if (eh.e_ident[EI_DATA] == ELFDATA2LSB)
937 			return (le32dec((uint8_t *) block->bl_data + 1));
938 		else
939 			return (be32dec((uint8_t *) block->bl_data + 1));
940 	} else if (block->bl_len == 9) {
941 		if (eh.e_ident[EI_DATA] == ELFDATA2LSB)
942 			return (le64dec((uint8_t *) block->bl_data + 1));
943 		else
944 			return (be64dec((uint8_t *) block->bl_data + 1));
945 	}
946 
947 	return (0);
948 }
949 
950 static void
951 search_line_attr(Dwarf_Debug dbg, struct func_info_head *func_info,
952     struct var_info_head *var_info, Dwarf_Die die, char **src_files,
953     Dwarf_Signed filecount)
954 {
955 	Dwarf_Attribute at;
956 	Dwarf_Unsigned udata;
957 	Dwarf_Half tag;
958 	Dwarf_Block *block;
959 	Dwarf_Bool flag;
960 	Dwarf_Die ret_die;
961 	Dwarf_Error de;
962 	struct func_info_entry *func;
963 	struct var_info_entry *var;
964 	const char *str;
965 	int ret;
966 
967 	if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
968 		warnx("dwarf_tag failed: %s", dwarf_errmsg(de));
969 		goto cont_search;
970 	}
971 
972 	/* We're interested in DIEs which define functions or variables. */
973 	if (tag != DW_TAG_subprogram && tag != DW_TAG_entry_point &&
974 	    tag != DW_TAG_inlined_subroutine && tag != DW_TAG_variable)
975 		goto cont_search;
976 
977 	if (tag == DW_TAG_variable) {
978 
979 		/* Ignore "artificial" variable. */
980 		if (dwarf_attrval_flag(die, DW_AT_artificial, &flag, &de) ==
981 		    DW_DLV_OK && flag)
982 			goto cont_search;
983 
984 		/* Ignore pure declaration. */
985 		if (dwarf_attrval_flag(die, DW_AT_declaration, &flag, &de) ==
986 		    DW_DLV_OK && flag)
987 			goto cont_search;
988 
989 		/* Ignore stack varaibles. */
990 		if (dwarf_attrval_flag(die, DW_AT_external, &flag, &de) !=
991 		    DW_DLV_OK || !flag)
992 			goto cont_search;
993 
994 		if ((var = calloc(1, sizeof(*var))) == NULL) {
995 			warn("calloc failed");
996 			goto cont_search;
997 		}
998 
999 		if (dwarf_attrval_unsigned(die, DW_AT_decl_file, &udata,
1000 		    &de) == DW_DLV_OK && udata > 0 &&
1001 		    (Dwarf_Signed) (udata - 1) < filecount) {
1002 			var->file = strdup(src_files[udata - 1]);
1003 			if (var->file == NULL) {
1004 				warn("strdup");
1005 				free(var);
1006 				goto cont_search;
1007 			}
1008 		}
1009 
1010 		if (dwarf_attrval_unsigned(die, DW_AT_decl_line, &udata, &de) ==
1011 		    DW_DLV_OK)
1012 			var->line = udata;
1013 
1014 		if (dwarf_attrval_string(die, DW_AT_name, &str, &de) ==
1015 		    DW_DLV_OK) {
1016 			var->name = strdup(str);
1017 			if (var->name == NULL) {
1018 				warn("strdup");
1019 				if (var->file)
1020 					free(var->file);
1021 				free(var);
1022 				goto cont_search;
1023 			}
1024 		}
1025 
1026 		if (dwarf_attr(die, DW_AT_location, &at, &de) == DW_DLV_OK &&
1027 		    dwarf_formblock(at, &block, &de) == DW_DLV_OK) {
1028 			/*
1029 			 * Since we ignored stack variables, the rest are the
1030 			 * external varaibles which should always use DW_OP_addr
1031 			 * operator for DW_AT_location value.
1032 			 */
1033 			if (*((uint8_t *)block->bl_data) == DW_OP_addr)
1034 				var->addr = get_block_value(dbg, block);
1035 		}
1036 
1037 		SLIST_INSERT_HEAD(var_info, var, entries);
1038 
1039 	} else {
1040 
1041 		if ((func = calloc(1, sizeof(*func))) == NULL) {
1042 			warn("calloc failed");
1043 			goto cont_search;
1044 		}
1045 
1046 		/*
1047 		 * Note that dwarf_attrval_unsigned() handles DW_AT_abstract_origin
1048 		 * internally, so it can retrieve DW_AT_decl_file/DW_AT_decl_line
1049 		 * attributes for inlined functions as well.
1050 		 */
1051 		if (dwarf_attrval_unsigned(die, DW_AT_decl_file, &udata,
1052 		    &de) == DW_DLV_OK && udata > 0 &&
1053 		    (Dwarf_Signed) (udata - 1) < filecount) {
1054 			func->file = strdup(src_files[udata - 1]);
1055 			if (func->file == NULL) {
1056 				warn("strdup");
1057 				free(func);
1058 				goto cont_search;
1059 			}
1060 		}
1061 
1062 		if (dwarf_attrval_unsigned(die, DW_AT_decl_line, &udata, &de) ==
1063 		    DW_DLV_OK)
1064 			func->line = udata;
1065 
1066 		if (dwarf_attrval_string(die, DW_AT_name, &str, &de) ==
1067 		    DW_DLV_OK) {
1068 			func->name = strdup(str);
1069 			if (func->name == NULL) {
1070 				warn("strdup");
1071 				if (func->file)
1072 					free(func->file);
1073 				free(func);
1074 				goto cont_search;
1075 			}
1076 		}
1077 
1078 		if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &udata, &de) ==
1079 		    DW_DLV_OK)
1080 			func->lowpc = udata;
1081 		if (dwarf_attrval_unsigned(die, DW_AT_high_pc, &udata, &de) ==
1082 		    DW_DLV_OK)
1083 			func->highpc = udata;
1084 
1085 		SLIST_INSERT_HEAD(func_info, func, entries);
1086 	}
1087 
1088 cont_search:
1089 
1090 	/* Search children. */
1091 	ret = dwarf_child(die, &ret_die, &de);
1092 	if (ret == DW_DLV_ERROR)
1093 		warnx("dwarf_child: %s", dwarf_errmsg(de));
1094 	else if (ret == DW_DLV_OK)
1095 		search_line_attr(dbg, func_info, var_info, ret_die, src_files,
1096 		    filecount);
1097 
1098 	/* Search sibling. */
1099 	ret = dwarf_siblingof(dbg, die, &ret_die, &de);
1100 	if (ret == DW_DLV_ERROR)
1101 		warnx("dwarf_siblingof: %s", dwarf_errmsg(de));
1102 	else if (ret == DW_DLV_OK)
1103 		search_line_attr(dbg, func_info, var_info, ret_die, src_files,
1104 		    filecount);
1105 
1106 	dwarf_dealloc(dbg, die, DW_DLA_DIE);
1107 }
1108 
1109 /*
1110  * Read elf file and collect symbol information, sort them, print.
1111  * Return 1 at failed, 0 at success.
1112  */
1113 static int
1114 read_elf(Elf *elf, const char *filename, Elf_Kind kind)
1115 {
1116 	Dwarf_Debug dbg;
1117 	Dwarf_Die die;
1118 	Dwarf_Error de;
1119 	Dwarf_Half tag;
1120 	Elf_Arhdr *arhdr;
1121 	Elf_Scn *scn;
1122 	GElf_Shdr shdr;
1123 	GElf_Half i;
1124 	Dwarf_Line *lbuf;
1125 	Dwarf_Unsigned lineno;
1126 	Dwarf_Signed lcount, filecount;
1127 	Dwarf_Addr lineaddr;
1128 	struct sym_print_data p_data;
1129 	struct sym_head list_head;
1130 	struct line_info_head *line_info;
1131 	struct func_info_head *func_info;
1132 	struct var_info_head *var_info;
1133 	struct line_info_entry *lie;
1134 	struct func_info_entry *func;
1135 	struct var_info_entry *var;
1136 	const char *shname, *objname;
1137 	char *type_table, **sec_table, *sfile, **src_files;
1138 	size_t shstrndx, shnum, dynndx, strndx;
1139 	int ret, rtn, e_err;
1140 
1141 #define	OBJNAME	(objname == NULL ? filename : objname)
1142 
1143 	assert(filename != NULL && "filename is null");
1144 
1145 	STAILQ_INIT(&list_head);
1146 	type_table = NULL;
1147 	sec_table = NULL;
1148 	line_info = NULL;
1149 	func_info = NULL;
1150 	var_info = NULL;
1151 	objname = NULL;
1152 	dynndx = SHN_UNDEF;
1153 	strndx = SHN_UNDEF;
1154 	rtn = 0;
1155 
1156 	nm_elfclass = gelf_getclass(elf);
1157 
1158 	if (kind == ELF_K_AR) {
1159 		if ((arhdr = elf_getarhdr(elf)) == NULL)
1160 			goto next_cmd;
1161 		objname = arhdr->ar_name != NULL ? arhdr->ar_name :
1162 		    arhdr->ar_rawname;
1163 	}
1164 	if (!elf_getshnum(elf, &shnum)) {
1165 		if ((e_err = elf_errno()) != 0)
1166 			warnx("%s: %s", OBJNAME, elf_errmsg(e_err));
1167 		else
1168 			warnx("%s: cannot get section number", OBJNAME);
1169 		rtn = 1;
1170 		goto next_cmd;
1171 	}
1172 	if (shnum == 0) {
1173 		warnx("%s: has no section", OBJNAME);
1174 		rtn = 1;
1175 		goto next_cmd;
1176 	}
1177 	if (!elf_getshstrndx(elf, &shstrndx)) {
1178 		warnx("%s: cannot get str index", OBJNAME);
1179 		rtn = 1;
1180 		goto next_cmd;
1181 	}
1182 	/* type_table for type determine */
1183 	if ((type_table = malloc(sizeof(char) * shnum)) == NULL) {
1184 		warn("%s: malloc", OBJNAME);
1185 		rtn = 1;
1186 		goto next_cmd;
1187 	}
1188 	/* sec_table for section name to display in sysv format */
1189 	if ((sec_table = calloc(shnum, sizeof(char *))) == NULL) {
1190 		warn("%s: calloc", OBJNAME);
1191 		rtn = 1;
1192 		goto next_cmd;
1193 	}
1194 
1195 	type_table[0] = 'U';
1196 	if ((sec_table[0] = strdup("*UND*")) == NULL) {
1197 		warn("strdup");
1198 		goto next_cmd;
1199 	}
1200 
1201 	for (i = 1; i < shnum; ++i) {
1202 		type_table[i] = 'U';
1203 		if ((scn = elf_getscn(elf, i)) == NULL) {
1204 			if ((e_err = elf_errno()) != 0)
1205 				warnx("%s: %s", OBJNAME, elf_errmsg(e_err));
1206 			else
1207 				warnx("%s: cannot get section", OBJNAME);
1208 			rtn = 1;
1209 			goto next_cmd;
1210 		}
1211 		if (gelf_getshdr(scn, &shdr) == NULL)
1212 			goto next_cmd;
1213 
1214 		/*
1215 		 * Cannot test by type and attribute for dynstr, strtab
1216 		 */
1217 		shname = elf_strptr(elf, shstrndx, (size_t) shdr.sh_name);
1218 		if (shname != NULL) {
1219 			if ((sec_table[i] = strdup(shname)) == NULL) {
1220 				warn("strdup");
1221 				goto next_cmd;
1222 			}
1223 			if (!strncmp(shname, ".dynstr", 7)) {
1224 				dynndx = elf_ndxscn(scn);
1225 				if (dynndx == SHN_UNDEF) {
1226 					warnx("%s: elf_ndxscn failed: %s",
1227 					    OBJNAME, elf_errmsg(-1));
1228 					goto next_cmd;
1229 				}
1230 			}
1231 			if (!strncmp(shname, ".strtab", 7)) {
1232 				strndx = elf_ndxscn(scn);
1233 				if (strndx == SHN_UNDEF) {
1234 					warnx("%s: elf_ndxscn failed: %s",
1235 					    OBJNAME, elf_errmsg(-1));
1236 					goto next_cmd;
1237 				}
1238 			}
1239 		} else {
1240 			sec_table[i] = strdup("*UND*");
1241 			if (sec_table[i] == NULL) {
1242 				warn("strdup");
1243 				goto next_cmd;
1244 			}
1245 		}
1246 
1247 
1248 		if (is_sec_text(&shdr))
1249 			type_table[i] = 'T';
1250 		else if (is_sec_data(&shdr)) {
1251 			if (is_sec_readonly(&shdr))
1252 				type_table[i] = 'R';
1253 			else
1254 				type_table[i] = 'D';
1255 		} else if (is_sec_nobits(&shdr))
1256 			type_table[i] = 'B';
1257 		else if (is_sec_debug(shname))
1258 			type_table[i] = 'N';
1259 		else if (is_sec_readonly(&shdr) && !is_sec_nobits(&shdr))
1260 			type_table[i] = 'n';
1261 	}
1262 
1263 	print_header(filename, objname);
1264 
1265 	if ((dynndx == SHN_UNDEF && nm_opts.print_symbol == PRINT_SYM_DYN) ||
1266 	    (strndx == SHN_UNDEF && nm_opts.print_symbol == PRINT_SYM_SYM)) {
1267 		warnx("%s: no symbols", OBJNAME);
1268 		/* This is not an error case */
1269 		goto next_cmd;
1270 	}
1271 
1272 	STAILQ_INIT(&list_head);
1273 
1274 	if (!nm_opts.debug_line)
1275 		goto process_sym;
1276 
1277 	/*
1278 	 * Collect dwarf line number information.
1279 	 */
1280 
1281 	if (dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, &de) !=
1282 	    DW_DLV_OK) {
1283 		warnx("dwarf_elf_init failed: %s", dwarf_errmsg(de));
1284 		goto process_sym;
1285 	}
1286 
1287 	line_info = malloc(sizeof(struct line_info_head));
1288 	func_info = malloc(sizeof(struct func_info_head));
1289 	var_info = malloc(sizeof(struct var_info_head));
1290 	if (line_info == NULL || func_info == NULL || var_info == NULL) {
1291 		warn("malloc");
1292 		(void) dwarf_finish(dbg, &de);
1293 		goto process_sym;
1294 	}
1295 	SLIST_INIT(line_info);
1296 	SLIST_INIT(func_info);
1297 	SLIST_INIT(var_info);
1298 
1299 	while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
1300 	    &de)) ==  DW_DLV_OK) {
1301 		die = NULL;
1302 		while (dwarf_siblingof(dbg, die, &die, &de) == DW_DLV_OK) {
1303 			if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
1304 				warnx("dwarf_tag failed: %s",
1305 				    dwarf_errmsg(de));
1306 				continue;
1307 			}
1308 			/* XXX: What about DW_TAG_partial_unit? */
1309 			if (tag == DW_TAG_compile_unit)
1310 				break;
1311 		}
1312 		if (die == NULL) {
1313 			warnx("could not find DW_TAG_compile_unit die");
1314 			continue;
1315 		}
1316 
1317 		/* Retrieve source file list. */
1318 		ret = dwarf_srcfiles(die, &src_files, &filecount, &de);
1319 		if (ret == DW_DLV_ERROR)
1320 			warnx("dwarf_srclines: %s", dwarf_errmsg(de));
1321 		if (ret != DW_DLV_OK)
1322 			continue;
1323 
1324 		/*
1325 		 * Retrieve line number information from .debug_line section.
1326 		 */
1327 
1328 		ret = dwarf_srclines(die, &lbuf, &lcount, &de);
1329 		if (ret == DW_DLV_ERROR)
1330 			warnx("dwarf_srclines: %s", dwarf_errmsg(de));
1331 		if (ret != DW_DLV_OK)
1332 			goto line_attr;
1333 		for (i = 0; (Dwarf_Signed) i < lcount; i++) {
1334 			if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) {
1335 				warnx("dwarf_lineaddr: %s", dwarf_errmsg(de));
1336 				continue;
1337 			}
1338 			if (dwarf_lineno(lbuf[i], &lineno, &de)) {
1339 				warnx("dwarf_lineno: %s", dwarf_errmsg(de));
1340 				continue;
1341 			}
1342 			if (dwarf_linesrc(lbuf[i], &sfile, &de)) {
1343 				warnx("dwarf_linesrc: %s", dwarf_errmsg(de));
1344 				continue;
1345 			}
1346 			if ((lie = malloc(sizeof(*lie))) == NULL) {
1347 				warn("malloc");
1348 				continue;
1349 			}
1350 			lie->addr = lineaddr;
1351 			lie->line = lineno;
1352 			lie->file = strdup(sfile);
1353 			if (lie->file == NULL) {
1354 				warn("strdup");
1355 				free(lie);
1356 				continue;
1357 			}
1358 			SLIST_INSERT_HEAD(line_info, lie, entries);
1359 		}
1360 
1361 	line_attr:
1362 		/* Retrieve line number information from DIEs. */
1363 		search_line_attr(dbg, func_info, var_info, die, src_files, filecount);
1364 	}
1365 
1366 	(void) dwarf_finish(dbg, &de);
1367 
1368 process_sym:
1369 
1370 	p_data.list_num = get_sym(elf, &list_head, shnum, dynndx, strndx,
1371 	    type_table, (void *) sec_table, shnum);
1372 
1373 	if (p_data.list_num == 0)
1374 		goto next_cmd;
1375 
1376 	p_data.headp = &list_head;
1377 	p_data.sh_num = shnum;
1378 	p_data.t_table = type_table;
1379 	p_data.s_table = (void *) sec_table;
1380 	p_data.filename = filename;
1381 	p_data.objname = objname;
1382 
1383 	sym_list_print(&p_data, func_info, var_info, line_info);
1384 
1385 next_cmd:
1386 	if (nm_opts.debug_line) {
1387 		if (func_info != NULL) {
1388 			while (!SLIST_EMPTY(func_info)) {
1389 				func = SLIST_FIRST(func_info);
1390 				SLIST_REMOVE_HEAD(func_info, entries);
1391 				free(func->file);
1392 				free(func->name);
1393 				free(func);
1394 			}
1395 			free(func_info);
1396 			func_info = NULL;
1397 		}
1398 		if (var_info != NULL) {
1399 			while (!SLIST_EMPTY(var_info)) {
1400 				var = SLIST_FIRST(var_info);
1401 				SLIST_REMOVE_HEAD(var_info, entries);
1402 				free(var->file);
1403 				free(var->name);
1404 				free(var);
1405 			}
1406 			free(var_info);
1407 			var_info = NULL;
1408 		}
1409 		if (line_info != NULL) {
1410 			while (!SLIST_EMPTY(line_info)) {
1411 				lie = SLIST_FIRST(line_info);
1412 				SLIST_REMOVE_HEAD(line_info, entries);
1413 				free(lie->file);
1414 				free(lie);
1415 			}
1416 			free(line_info);
1417 			line_info = NULL;
1418 		}
1419 	}
1420 
1421 	if (sec_table != NULL)
1422 		for (i = 0; i < shnum; ++i)
1423 			free(sec_table[i]);
1424 	free(sec_table);
1425 	free(type_table);
1426 
1427 	sym_list_dest(&list_head);
1428 
1429 	return (rtn);
1430 
1431 #undef	OBJNAME
1432 }
1433 
1434 static int
1435 read_object(const char *filename)
1436 {
1437 	Elf *elf, *arf;
1438 	Elf_Cmd elf_cmd;
1439 	Elf_Kind kind;
1440 	int fd, rtn, e_err;
1441 
1442 	assert(filename != NULL && "filename is null");
1443 
1444 	if ((fd = open(filename, O_RDONLY)) == -1) {
1445 		warn("'%s'", filename);
1446 		return (1);
1447 	}
1448 
1449 	elf_cmd = ELF_C_READ;
1450 	if ((arf = elf_begin(fd, elf_cmd, (Elf *) NULL)) == NULL) {
1451 		if ((e_err = elf_errno()) != 0)
1452 			warnx("elf_begin error: %s", elf_errmsg(e_err));
1453 		else
1454 			warnx("elf_begin error");
1455 		close(fd);
1456 		return (1);
1457 	}
1458 
1459 	assert(arf != NULL && "arf is null.");
1460 
1461 	rtn = 0;
1462 	if ((kind = elf_kind(arf)) == ELF_K_NONE) {
1463 		warnx("%s: File format not recognized", filename);
1464 		elf_end(arf);
1465 		close(fd);
1466 		return (1);
1467 	}
1468 	if (kind == ELF_K_AR) {
1469 		if (nm_opts.print_name == PRINT_NAME_MULTI &&
1470 		    nm_opts.elem_print_fn == sym_elem_print_all)
1471 			printf("\n%s:\n", filename);
1472 		if (nm_opts.print_armap == true)
1473 			print_ar_index(fd, arf);
1474 	}
1475 
1476 	while ((elf = elf_begin(fd, elf_cmd, arf)) != NULL) {
1477 		rtn |= read_elf(elf, filename, kind);
1478 
1479 		/*
1480 		 * If file is not archive, elf_next return ELF_C_NULL and
1481 		 * stop the loop.
1482 		 */
1483 		elf_cmd = elf_next(elf);
1484 		elf_end(elf);
1485 	}
1486 
1487 	elf_end(arf);
1488 	close(fd);
1489 
1490 	return (rtn);
1491 }
1492 
1493 static int
1494 read_files(int argc, char **argv)
1495 {
1496 	int rtn = 0;
1497 
1498 	if (argc < 0 || argv == NULL)
1499 		return (1);
1500 
1501 	if (argc == 0)
1502 		rtn |= read_object(nm_info.def_filename);
1503 	else {
1504 		if (nm_opts.print_name == PRINT_NAME_NONE && argc > 1)
1505 			nm_opts.print_name = PRINT_NAME_MULTI;
1506 		while (argc > 0) {
1507 			rtn |= read_object(*argv);
1508 			--argc;
1509 			++argv;
1510 		}
1511 	}
1512 
1513 	return (rtn);
1514 }
1515 
1516 static void
1517 print_lineno(struct sym_entry *ep, struct func_info_head *func_info,
1518     struct var_info_head *var_info, struct line_info_head *line_info)
1519 {
1520 	struct func_info_entry *func;
1521 	struct var_info_entry *var;
1522 	struct line_info_entry *lie;
1523 
1524 	/* For function symbol, search the function line information list.  */
1525 	if ((ep->sym->st_info & 0xf) == STT_FUNC && func_info != NULL) {
1526 		SLIST_FOREACH(func, func_info, entries) {
1527 			if (!strcmp(ep->name, func->name) &&
1528 			    ep->sym->st_value >= func->lowpc &&
1529 			    ep->sym->st_value < func->highpc) {
1530 				printf("\t%s:%" PRIu64, func->file, func->line);
1531 				return;
1532 			}
1533 		}
1534 	}
1535 
1536 	/* For variable symbol, search the variable line information list.  */
1537 	if ((ep->sym->st_info & 0xf) == STT_OBJECT && var_info != NULL) {
1538 		SLIST_FOREACH(var, var_info, entries) {
1539 			if (!strcmp(ep->name, var->name) &&
1540 			    ep->sym->st_value == var->addr) {
1541 				printf("\t%s:%" PRIu64, var->file, var->line);
1542 				return;
1543 			}
1544 		}
1545 	}
1546 
1547 	/* Otherwise search line number information the .debug_line section. */
1548 	if (line_info != NULL) {
1549 		SLIST_FOREACH(lie, line_info, entries) {
1550 			if (ep->sym->st_value == lie->addr) {
1551 				printf("\t%s:%" PRIu64, lie->file, lie->line);
1552 				return;
1553 			}
1554 		}
1555 	}
1556 }
1557 
1558 static void
1559 set_opt_value_print_fn(enum radix t)
1560 {
1561 
1562 	switch (t) {
1563 	case RADIX_OCT:
1564 		nm_opts.value_print_fn = &sym_value_oct_print;
1565 		nm_opts.size_print_fn = &sym_size_oct_print;
1566 
1567 		break;
1568 	case RADIX_DEC:
1569 		nm_opts.value_print_fn = &sym_value_dec_print;
1570 		nm_opts.size_print_fn = &sym_size_dec_print;
1571 
1572 		break;
1573 	case RADIX_HEX:
1574 	default :
1575 		nm_opts.value_print_fn = &sym_value_hex_print;
1576 		nm_opts.size_print_fn  = &sym_size_hex_print;
1577 	}
1578 
1579 	assert(nm_opts.value_print_fn != NULL &&
1580 	    "nm_opts.value_print_fn is null");
1581 }
1582 
1583 static void
1584 sym_elem_print_all(char type, const char *sec, const GElf_Sym *sym,
1585     const char *name)
1586 {
1587 
1588 	if (sec == NULL || sym == NULL || name == NULL ||
1589 	    nm_opts.value_print_fn == NULL)
1590 		return;
1591 
1592 	if (IS_UNDEF_SYM_TYPE(type)) {
1593 		if (nm_opts.t == RADIX_HEX && nm_elfclass == ELFCLASS32)
1594 			printf("%-8s", "");
1595 		else
1596 			printf("%-16s", "");
1597 	} else {
1598 		switch ((nm_opts.sort_fn == & cmp_size ? 2 : 0) +
1599 		    nm_opts.print_size) {
1600 		case 3:
1601 			if (sym->st_size != 0) {
1602 				nm_opts.value_print_fn(sym);
1603 				printf(" ");
1604 				nm_opts.size_print_fn(sym);
1605 			}
1606 			break;
1607 
1608 		case 2:
1609 			if (sym->st_size != 0)
1610 				nm_opts.size_print_fn(sym);
1611 			break;
1612 
1613 		case 1:
1614 			nm_opts.value_print_fn(sym);
1615 			if (sym->st_size != 0) {
1616 				printf(" ");
1617 				nm_opts.size_print_fn(sym);
1618 			}
1619 			break;
1620 
1621 		case 0:
1622 		default:
1623 			nm_opts.value_print_fn(sym);
1624 		}
1625 	}
1626 
1627 	printf(" %c ", type);
1628 	PRINT_DEMANGLED_NAME("%s", name);
1629 }
1630 
1631 static void
1632 sym_elem_print_all_portable(char type, const char *sec, const GElf_Sym *sym,
1633     const char *name)
1634 {
1635 
1636 	if (sec == NULL || sym == NULL || name == NULL ||
1637 	    nm_opts.value_print_fn == NULL)
1638 		return;
1639 
1640 	PRINT_DEMANGLED_NAME("%s", name);
1641 	printf(" %c ", type);
1642 	if (!IS_UNDEF_SYM_TYPE(type)) {
1643 		nm_opts.value_print_fn(sym);
1644 		printf(" ");
1645 		if (sym->st_size != 0)
1646 			nm_opts.size_print_fn(sym);
1647 	} else
1648 		printf("        ");
1649 }
1650 
1651 static void
1652 sym_elem_print_all_sysv(char type, const char *sec, const GElf_Sym *sym,
1653     const char *name)
1654 {
1655 
1656 	if (sec == NULL || sym == NULL || name == NULL ||
1657 	    nm_opts.value_print_fn == NULL)
1658 		return;
1659 
1660 	PRINT_DEMANGLED_NAME("%-20s|", name);
1661 	if (IS_UNDEF_SYM_TYPE(type))
1662 		printf("                ");
1663 	else
1664 		nm_opts.value_print_fn(sym);
1665 
1666 	printf("|   %c  |", type);
1667 
1668 	switch (sym->st_info & 0xf) {
1669 	case STT_OBJECT:
1670 		printf("%18s|", "OBJECT");
1671 		break;
1672 
1673 	case STT_FUNC:
1674 		printf("%18s|", "FUNC");
1675 		break;
1676 
1677 	case STT_SECTION:
1678 		printf("%18s|", "SECTION");
1679 		break;
1680 
1681 	case STT_FILE:
1682 		printf("%18s|", "FILE");
1683 		break;
1684 
1685 	case STT_LOPROC:
1686 		printf("%18s|", "LOPROC");
1687 		break;
1688 
1689 	case STT_HIPROC:
1690 		printf("%18s|", "HIPROC");
1691 		break;
1692 
1693 	case STT_NOTYPE:
1694 	default:
1695 		printf("%18s|", "NOTYPE");
1696 	};
1697 
1698 	if (sym->st_size != 0)
1699 		nm_opts.size_print_fn(sym);
1700 	else
1701 		printf("                ");
1702 
1703 	printf("|     |%s", sec);
1704 }
1705 
1706 static int
1707 sym_elem_def(char type, const GElf_Sym *sym, const char *name)
1708 {
1709 
1710 	assert(IS_SYM_TYPE((unsigned char) type));
1711 
1712 	UNUSED(sym);
1713 	UNUSED(name);
1714 
1715 	return (!IS_UNDEF_SYM_TYPE((unsigned char) type));
1716 }
1717 
1718 static int
1719 sym_elem_global(char type, const GElf_Sym *sym, const char *name)
1720 {
1721 
1722 	assert(IS_SYM_TYPE((unsigned char) type));
1723 
1724 	UNUSED(sym);
1725 	UNUSED(name);
1726 
1727 	/* weak symbols resemble global. */
1728 	return (isupper((unsigned char) type) || type == 'w');
1729 }
1730 
1731 static int
1732 sym_elem_global_static(char type, const GElf_Sym *sym, const char *name)
1733 {
1734 	unsigned char info;
1735 
1736 	assert(sym != NULL);
1737 
1738 	UNUSED(type);
1739 	UNUSED(name);
1740 
1741 	info = sym->st_info >> 4;
1742 
1743 	return (info == STB_LOCAL ||
1744 	    info == STB_GLOBAL ||
1745 	    info == STB_WEAK);
1746 }
1747 
1748 static int
1749 sym_elem_nondebug(char type, const GElf_Sym *sym, const char *name)
1750 {
1751 
1752 	assert(sym != NULL);
1753 
1754 	UNUSED(type);
1755 	UNUSED(name);
1756 
1757 	if (sym->st_value == 0 && (sym->st_info & 0xf) == STT_FILE)
1758 		return (0);
1759 	if (sym->st_name == 0)
1760 		return (0);
1761 
1762 	return (1);
1763 }
1764 
1765 static int
1766 sym_elem_nonzero_size(char type, const GElf_Sym *sym, const char *name)
1767 {
1768 
1769 	assert(sym != NULL);
1770 
1771 	UNUSED(type);
1772 	UNUSED(name);
1773 
1774 	return (sym->st_size > 0);
1775 }
1776 
1777 static int
1778 sym_elem_undef(char type, const GElf_Sym *sym, const char *name)
1779 {
1780 
1781 	assert(IS_SYM_TYPE((unsigned char) type));
1782 
1783 	UNUSED(sym);
1784 	UNUSED(name);
1785 
1786 	return (IS_UNDEF_SYM_TYPE((unsigned char) type));
1787 }
1788 
1789 static void
1790 sym_list_dest(struct sym_head *headp)
1791 {
1792 	struct sym_entry *ep, *ep_n;
1793 
1794 	if (headp == NULL)
1795 		return;
1796 
1797 	ep = STAILQ_FIRST(headp);
1798 	while (ep != NULL) {
1799 		ep_n = STAILQ_NEXT(ep, sym_entries);
1800 		free(ep->sym);
1801 		free(ep->name);
1802 		free(ep);
1803 		ep = ep_n;
1804 	}
1805 }
1806 
1807 static int
1808 sym_list_insert(struct sym_head *headp, const char *name, const GElf_Sym *sym)
1809 {
1810 	struct sym_entry *e;
1811 
1812 	if (headp == NULL || name == NULL || sym == NULL)
1813 		return (0);
1814 	if ((e = malloc(sizeof(struct sym_entry))) == NULL) {
1815 		warn("malloc");
1816 		return (0);
1817 	}
1818 	if ((e->name = strdup(name)) == NULL) {
1819 		warn("strdup");
1820 		free(e);
1821 		return (0);
1822 	}
1823 	if ((e->sym = malloc(sizeof(GElf_Sym))) == NULL) {
1824 		warn("malloc");
1825 		free(e->name);
1826 		free(e);
1827 		return (0);
1828 	}
1829 
1830 	memcpy(e->sym, sym, sizeof(GElf_Sym));
1831 
1832 	/* Display size instead of value for common symbol. */
1833 	if (sym->st_shndx == SHN_COMMON)
1834 		e->sym->st_value = sym->st_size;
1835 
1836 	STAILQ_INSERT_TAIL(headp, e, sym_entries);
1837 
1838 	return (1);
1839 }
1840 
1841 /* If file has not .debug_info, line_info will be NULL */
1842 static void
1843 sym_list_print(struct sym_print_data *p, struct func_info_head *func_info,
1844     struct var_info_head *var_info, struct line_info_head *line_info)
1845 {
1846 	struct sym_entry *e_v;
1847 	size_t si;
1848 	int i;
1849 
1850 	if (p == NULL || CHECK_SYM_PRINT_DATA(p))
1851 		return;
1852 	if ((e_v = sym_list_sort(p)) == NULL)
1853 		return;
1854 	if (nm_opts.sort_reverse == false)
1855 		for (si = 0; si != p->list_num; ++si)
1856 			sym_list_print_each(&e_v[si], p, func_info, var_info,
1857 			    line_info);
1858 	else
1859 		for (i = p->list_num - 1; i != -1; --i)
1860 			sym_list_print_each(&e_v[i], p, func_info, var_info,
1861 			    line_info);
1862 
1863 	free(e_v);
1864 }
1865 
1866 /* If file has not .debug_info, line_info will be NULL */
1867 static void
1868 sym_list_print_each(struct sym_entry *ep, struct sym_print_data *p,
1869     struct func_info_head *func_info, struct var_info_head *var_info,
1870     struct line_info_head *line_info)
1871 {
1872 	const char *sec;
1873 	char type;
1874 
1875 	if (ep == NULL || CHECK_SYM_PRINT_DATA(p))
1876 		return;
1877 
1878 	assert(ep->name != NULL);
1879 	assert(ep->sym != NULL);
1880 
1881 	type = get_sym_type(ep->sym, p->t_table);
1882 
1883 	if (nm_opts.print_name == PRINT_NAME_FULL) {
1884 		printf("%s", p->filename);
1885 		if (nm_opts.elem_print_fn == &sym_elem_print_all_portable) {
1886 			if (p->objname != NULL)
1887 				printf("[%s]", p->objname);
1888 			printf(": ");
1889 		} else {
1890 			if (p->objname != NULL)
1891 				printf(":%s", p->objname);
1892 			printf(":");
1893 		}
1894 	}
1895 
1896 	switch (ep->sym->st_shndx) {
1897 	case SHN_LOPROC:
1898 		/* LOPROC or LORESERVE */
1899 		sec = "*LOPROC*";
1900 		break;
1901 	case SHN_HIPROC:
1902 		sec = "*HIPROC*";
1903 		break;
1904 	case SHN_LOOS:
1905 		sec = "*LOOS*";
1906 		break;
1907 	case SHN_HIOS:
1908 		sec = "*HIOS*";
1909 		break;
1910 	case SHN_ABS:
1911 		sec = "*ABS*";
1912 		break;
1913 	case SHN_COMMON:
1914 		sec = "*COM*";
1915 		break;
1916 	case SHN_HIRESERVE:
1917 		/* HIRESERVE or XINDEX */
1918 		sec = "*HIRESERVE*";
1919 		break;
1920 	default:
1921 		if (ep->sym->st_shndx > p->sh_num)
1922 			return;
1923 		sec = p->s_table[ep->sym->st_shndx];
1924 		break;
1925 	};
1926 
1927 	nm_opts.elem_print_fn(type, sec, ep->sym, ep->name);
1928 
1929 	if (nm_opts.debug_line == true && !IS_UNDEF_SYM_TYPE(type))
1930 		print_lineno(ep, func_info, var_info, line_info);
1931 
1932 	printf("\n");
1933 }
1934 
1935 static struct sym_entry	*
1936 sym_list_sort(struct sym_print_data *p)
1937 {
1938 	struct sym_entry *ep, *e_v;
1939 	int idx;
1940 
1941 	if (p == NULL || CHECK_SYM_PRINT_DATA(p))
1942 		return (NULL);
1943 
1944 	if ((e_v = malloc(sizeof(struct sym_entry) * p->list_num)) == NULL) {
1945 		warn("malloc");
1946 		return (NULL);
1947 	}
1948 
1949 	idx = 0;
1950 	STAILQ_FOREACH(ep, p->headp, sym_entries) {
1951 		if (ep->name != NULL && ep->sym != NULL) {
1952 			e_v[idx].name = ep->name;
1953 			e_v[idx].sym = ep->sym;
1954 			++idx;
1955 		}
1956 	}
1957 
1958 	assert((size_t)idx == p->list_num);
1959 
1960 	if (nm_opts.sort_fn != &cmp_none) {
1961 		nm_print_data = p;
1962 		assert(nm_print_data != NULL);
1963 		qsort(e_v, p->list_num, sizeof(struct sym_entry),
1964 		    nm_opts.sort_fn);
1965 	}
1966 
1967 	return (e_v);
1968 }
1969 
1970 static void
1971 sym_size_oct_print(const GElf_Sym *sym)
1972 {
1973 
1974 	assert(sym != NULL && "sym is null");
1975 	printf("%016" PRIo64, sym->st_size);
1976 }
1977 
1978 static void
1979 sym_size_hex_print(const GElf_Sym *sym)
1980 {
1981 
1982 	assert(sym != NULL && "sym is null");
1983 	if (nm_elfclass == ELFCLASS32)
1984 		printf("%08" PRIx64, sym->st_size);
1985 	else
1986 		printf("%016" PRIx64, sym->st_size);
1987 }
1988 
1989 static void
1990 sym_size_dec_print(const GElf_Sym *sym)
1991 {
1992 
1993 	assert(sym != NULL && "sym is null");
1994 	printf("%016" PRId64, sym->st_size);
1995 }
1996 
1997 static void
1998 sym_value_oct_print(const GElf_Sym *sym)
1999 {
2000 
2001 	assert(sym != NULL && "sym is null");
2002 	printf("%016" PRIo64, sym->st_value);
2003 }
2004 
2005 static void
2006 sym_value_hex_print(const GElf_Sym *sym)
2007 {
2008 
2009 	assert(sym != NULL && "sym is null");
2010 	if (nm_elfclass == ELFCLASS32)
2011 		printf("%08" PRIx64, sym->st_value);
2012 	else
2013 		printf("%016" PRIx64, sym->st_value);
2014 }
2015 
2016 static void
2017 sym_value_dec_print(const GElf_Sym *sym)
2018 {
2019 
2020 	assert(sym != NULL && "sym is null");
2021 	printf("%016" PRId64, sym->st_value);
2022 }
2023 
2024 static void
2025 usage(int exitcode)
2026 {
2027 
2028 	printf("Usage: %s [options] file ...\
2029 \n  Display symbolic information in file.\n\
2030 \n  Options: \
2031 \n  -A, --print-file-name     Write the full pathname or library name of an\
2032 \n                            object on each line.\
2033 \n  -a, --debug-syms          Display all symbols include debugger-only\
2034 \n                            symbols.", nm_info.name);
2035 	printf("\
2036 \n  -B                        Equivalent to specifying \"--format=bsd\".\
2037 \n  -C, --demangle[=style]    Decode low-level symbol names.\
2038 \n      --no-demangle         Do not demangle low-level symbol names.\
2039 \n  -D, --dynamic             Display only dynamic symbols.\
2040 \n  -e                        Display only global and static symbols.");
2041 	printf("\
2042 \n  -f                        Produce full output (default).\
2043 \n      --format=format       Display output in specific format.  Allowed\
2044 \n                            formats are: \"bsd\", \"posix\" and \"sysv\".\
2045 \n  -g                        Display only global symbol information.\
2046 \n  -h, --help                Show this help message.\
2047 \n  -l, --line-numbers        Display filename and linenumber using\
2048 \n                            debugging information.\
2049 \n  -n, --numeric-sort        Sort symbols numerically by value.");
2050 	printf("\
2051 \n  -o                        Write numeric values in octal. Equivalent to\
2052 \n                            specifying \"-t o\".\
2053 \n  -p, --no-sort             Do not sort symbols.\
2054 \n  -P                        Write information in a portable output format.\
2055 \n                            Equivalent to specifying \"--format=posix\".\
2056 \n  -r, --reverse-sort        Reverse the order of the sort.\
2057 \n  -S, --print-size          Print symbol sizes instead values.\
2058 \n  -s, --print-armap         Include an index of archive members.\
2059 \n      --size-sort           Sort symbols by size.");
2060 	printf("\
2061 \n  -t, --radix=format        Write each numeric value in the specified\
2062 \n                            format:\
2063 \n                               d   In decimal,\
2064 \n                               o   In octal,\
2065 \n                               x   In hexadecimal.");
2066 	printf("\
2067 \n  -u, --undefined-only      Display only undefined symbols.\
2068 \n      --defined-only        Display only defined symbols.\
2069 \n  -V, --version             Show the version identifier for %s.\
2070 \n  -v                        Sort output by value.\
2071 \n  -x                        Write numeric values in hexadecimal.\
2072 \n                            Equivalent to specifying \"-t x\".",
2073 	    nm_info.name);
2074 	printf("\n\
2075 \n  The default options are: output in bsd format, use a hexadecimal radix,\
2076 \n  sort by symbol name, do not demangle names.\n");
2077 
2078 	exit(exitcode);
2079 }
2080 
2081 /*
2082  * Display symbolic information in file.
2083  * Return 0 at success, >0 at failed.
2084  */
2085 int
2086 main(int argc, char **argv)
2087 {
2088 	int rtn;
2089 
2090 	global_init();
2091 	get_opt(argc, argv);
2092 	rtn = read_files(argc - optind, argv + optind);
2093 	global_dest();
2094 
2095 	exit(rtn);
2096 }
2097