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