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