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