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