2 * Copyright (c) 2007 Hyogeol Lee <hyogeollee@gmail.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
27 #include <sys/queue.h>
28 #include <sys/types.h>
51 ELFTC_VCSID("$Id: nm.c 3472 2016-05-17 20:11:16Z emaste $");
53 /* symbol information list */
54 STAILQ_HEAD(sym_head
, sym_entry
);
59 STAILQ_ENTRY(sym_entry
) sym_entries
;
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 *);
67 /* output filter list */
68 static SLIST_HEAD(filter_head
, filter_entry
) nm_out_filter
=
69 SLIST_HEAD_INITIALIZER(nm_out_filter
);
73 SLIST_ENTRY(filter_entry
) filter_entries
;
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
;
84 const char *def_filename
;
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
;
94 SLIST_HEAD(line_info_head
, line_info_entry
);
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
;
105 SLIST_HEAD(func_info_head
, func_info_entry
);
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
;
115 SLIST_HEAD(var_info_head
, var_info_entry
);
117 /* output numric type */
124 /* output symbol type, PRINT_SYM_DYN for dynamic symbol only */
130 /* output name type */
137 struct nm_prog_options
{
138 enum print_symbol print_symbol
;
139 enum print_name print_name
;
153 * function pointer to sort symbol list.
154 * possible function - cmp_name, cmp_none, cmp_size, cmp_value
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
164 fn_elem_print elem_print_fn
;
166 fn_sym_print value_print_fn
;
167 fn_sym_print size_print_fn
;
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)
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,
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
*,
206 static int sym_elem_nondebug(char, const GElf_Sym
*, const char *);
207 static int sym_elem_nonzero_size(char, const GElf_Sym
*,
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 *,
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);
234 static struct nm_prog_info nm_info
;
235 static struct nm_prog_options nm_opts
;
236 static int nm_elfclass
;
239 * Point to current sym_print_data to use portable qsort function.
240 * (e.g. There is no qsort_r function in NetBSD.)
242 * Using in sym_list_sort.
244 static struct sym_print_data
*nm_print_data
;
246 static const struct option nm_longopts
[] = {
247 { "debug-syms", no_argument
, NULL
, 'a' },
248 { "defined-only", no_argument
, &nm_opts
.def_only
, 1},
249 { "demangle", optional_argument
, NULL
, 'C' },
250 { "dynamic", no_argument
, NULL
, 'D' },
251 { "extern-only", no_argument
, NULL
, 'g' },
252 { "format", required_argument
, NULL
, 'F' },
253 { "help", no_argument
, NULL
, 'h' },
254 { "line-numbers", no_argument
, NULL
, 'l' },
255 { "no-demangle", no_argument
, &nm_opts
.no_demangle
,
257 { "no-sort", no_argument
, NULL
, 'p' },
258 { "numeric-sort", no_argument
, NULL
, 'v' },
259 { "print-armap", no_argument
, NULL
, 's' },
260 { "print-file-name", no_argument
, NULL
, 'A' },
261 { "print-size", no_argument
, NULL
, 'S' },
262 { "radix", required_argument
, NULL
, 't' },
263 { "reverse-sort", no_argument
, NULL
, 'r' },
264 { "size-sort", no_argument
, &nm_opts
.sort_size
, 1},
265 { "undefined-only", no_argument
, NULL
, 'u' },
266 { "version", no_argument
, NULL
, 'V' },
270 #if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS)
271 static __inline
uint32_t
272 be32dec(const void *pp
)
274 unsigned char const *p
= (unsigned char const *)pp
;
276 return ((p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3]);
279 static __inline
uint32_t
280 le32dec(const void *pp
)
282 unsigned char const *p
= (unsigned char const *)pp
;
284 return ((p
[3] << 24) | (p
[2] << 16) | (p
[1] << 8) | p
[0]);
287 static __inline
uint64_t
288 be64dec(const void *pp
)
290 unsigned char const *p
= (unsigned char const *)pp
;
292 return (((uint64_t)be32dec(p
) << 32) | be32dec(p
+ 4));
295 static __inline
uint64_t
296 le64dec(const void *pp
)
298 unsigned char const *p
= (unsigned char const *)pp
;
300 return (((uint64_t)le32dec(p
+ 4) << 32) | le32dec(p
));
305 cmp_name(const void *l
, const void *r
)
310 assert(((const struct sym_entry
*)l
)->name
!= NULL
);
311 assert(((const struct sym_entry
*)r
)->name
!= NULL
);
313 return (strcmp(((const struct sym_entry
*)l
)->name
,
314 ((const struct sym_entry
*)r
)->name
));
318 cmp_none(const void *l
, const void *r
)
327 /* Size comparison. If l and r have same size, compare their name. */
329 cmp_size(const void *lp
, const void *rp
)
331 const struct sym_entry
*l
, *r
;
337 assert(l
->name
!= NULL
);
338 assert(l
->sym
!= NULL
);
340 assert(r
->name
!= NULL
);
341 assert(r
->sym
!= NULL
);
343 if (l
->sym
->st_size
== r
->sym
->st_size
)
344 return (strcmp(l
->name
, r
->name
));
346 return (l
->sym
->st_size
- r
->sym
->st_size
);
349 /* Value comparison. Undefined symbols come first. */
351 cmp_value(const void *lp
, const void *rp
)
353 const struct sym_entry
*l
, *r
;
355 int l_is_undef
, r_is_undef
;
360 assert(nm_print_data
!= NULL
);
361 ttable
= nm_print_data
->t_table
;
364 assert(l
->name
!= NULL
);
365 assert(l
->sym
!= NULL
);
367 assert(r
->name
!= NULL
);
368 assert(r
->sym
!= NULL
);
369 assert(ttable
!= NULL
);
371 l_is_undef
= IS_UNDEF_SYM_TYPE(get_sym_type(l
->sym
, ttable
)) ? 1 : 0;
372 r_is_undef
= IS_UNDEF_SYM_TYPE(get_sym_type(r
->sym
, ttable
)) ? 1 : 0;
374 assert(l_is_undef
+ r_is_undef
>= 0);
375 assert(l_is_undef
+ r_is_undef
<= 2);
377 switch (l_is_undef
+ r_is_undef
) {
380 if (l
->sym
->st_value
== r
->sym
->st_value
)
381 return (strcmp(l
->name
, r
->name
));
382 return (l
->sym
->st_value
> r
->sym
->st_value
? 1 : -1);
385 return (l_is_undef
== 0 ? 1 : -1);
388 return (strcmp(l
->name
, r
->name
));
392 return (l
->sym
->st_value
- r
->sym
->st_value
);
398 struct filter_entry
*e
;
400 while (!SLIST_EMPTY(&nm_out_filter
)) {
401 e
= SLIST_FIRST(&nm_out_filter
);
402 SLIST_REMOVE_HEAD(&nm_out_filter
, filter_entries
);
408 filter_insert(fn_filter filter_fn
)
410 struct filter_entry
*e
;
412 assert(filter_fn
!= NULL
);
414 if ((e
= malloc(sizeof(struct filter_entry
))) == NULL
) {
419 SLIST_INSERT_HEAD(&nm_out_filter
, e
, filter_entries
);
425 parse_demangle_option(const char *opt
)
429 return (ELFTC_DEM_UNKNOWN
);
430 else if (!strncasecmp(opt
, "gnu-v2", 6))
431 return (ELFTC_DEM_GNU2
);
432 else if (!strncasecmp(opt
, "gnu-v3", 6))
433 return (ELFTC_DEM_GNU3
);
434 else if (!strncasecmp(opt
, "arm", 3))
435 return (ELFTC_DEM_ARM
);
437 errx(EXIT_FAILURE
, "unknown demangling style '%s'", opt
);
444 get_opt(int argc
, char **argv
)
447 bool is_posix
, oflag
;
449 if (argc
<= 0 || argv
== NULL
)
452 oflag
= is_posix
= false;
453 nm_opts
.t
= RADIX_HEX
;
454 while ((ch
= getopt_long(argc
, argv
, "ABCDF:PSVaefghlnoprst:uvx",
455 nm_longopts
, NULL
)) != -1) {
458 nm_opts
.print_name
= PRINT_NAME_FULL
;
461 nm_opts
.elem_print_fn
= &sym_elem_print_all
;
464 nm_opts
.demangle_type
= parse_demangle_option(optarg
);
467 nm_opts
.print_symbol
= PRINT_SYM_DYN
;
470 /* sysv, bsd, posix */
474 nm_opts
.elem_print_fn
= &sym_elem_print_all
;
479 nm_opts
.elem_print_fn
=
480 &sym_elem_print_all_portable
;
484 nm_opts
.elem_print_fn
=
485 &sym_elem_print_all_sysv
;
488 warnx("%s: Invalid format", optarg
);
495 nm_opts
.elem_print_fn
= &sym_elem_print_all_portable
;
498 nm_opts
.print_size
= 1;
504 nm_opts
.print_debug
= true;
507 filter_insert(sym_elem_global_static
);
512 filter_insert(sym_elem_global
);
518 nm_opts
.debug_line
= true;
522 nm_opts
.sort_fn
= &cmp_value
;
528 nm_opts
.sort_fn
= &cmp_none
;
531 nm_opts
.sort_reverse
= true;
534 nm_opts
.print_armap
= true;
537 /* t require always argument to getopt_long */
540 nm_opts
.t
= RADIX_DEC
;
543 nm_opts
.t
= RADIX_OCT
;
546 nm_opts
.t
= RADIX_HEX
;
549 warnx("%s: Invalid radix", optarg
);
554 filter_insert(sym_elem_undef
);
555 nm_opts
.undef_only
= true;
557 /* case 'v': see case 'n' above. */
559 nm_opts
.t
= RADIX_HEX
;
562 if (nm_opts
.sort_size
!= 0) {
563 nm_opts
.sort_fn
= &cmp_size
;
564 filter_insert(sym_elem_def
);
565 filter_insert(sym_elem_nonzero_size
);
567 if (nm_opts
.def_only
!= 0)
568 filter_insert(sym_elem_def
);
569 if (nm_opts
.no_demangle
!= 0)
570 nm_opts
.demangle_type
= -1;
578 * In POSIX mode, the '-o' option controls the output radix.
579 * In non-POSIX mode, the option is a synonym for the '-A' and
580 * '--print-file-name' options.
584 nm_opts
.t
= RADIX_OCT
;
586 nm_opts
.print_name
= PRINT_NAME_FULL
;
589 assert(nm_opts
.sort_fn
!= NULL
&& "nm_opts.sort_fn is null");
590 assert(nm_opts
.elem_print_fn
!= NULL
&&
591 "nm_opts.elem_print_fn is null");
592 assert(nm_opts
.value_print_fn
!= NULL
&&
593 "nm_opts.value_print_fn is null");
595 set_opt_value_print_fn(nm_opts
.t
);
597 if (nm_opts
.undef_only
== true) {
598 if (nm_opts
.sort_fn
== &cmp_size
)
600 "--size-sort with -u is meaningless");
601 if (nm_opts
.def_only
!= 0)
603 "-u with --defined-only is meaningless");
605 if (nm_opts
.print_debug
== false)
606 filter_insert(sym_elem_nondebug
);
607 if (nm_opts
.sort_reverse
== true && nm_opts
.sort_fn
== cmp_none
)
608 nm_opts
.sort_reverse
= false;
612 * Get symbol information from elf.
615 get_sym(Elf
*elf
, struct sym_head
*headp
, int shnum
, size_t dynndx
,
616 size_t strndx
, const char *type_table
, const char **sec_table
,
623 struct filter_entry
*fep
;
626 const char *sym_name
;
632 assert(headp
!= NULL
);
635 for (i
= 1; i
< shnum
; i
++) {
636 if ((scn
= elf_getscn(elf
, i
)) == NULL
) {
637 warnx("elf_getscn failed: %s", elf_errmsg(-1));
640 if (gelf_getshdr(scn
, &shdr
) != &shdr
) {
641 warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
644 if (shdr
.sh_type
== SHT_SYMTAB
) {
645 if (nm_opts
.print_symbol
!= PRINT_SYM_SYM
)
647 } else if (shdr
.sh_type
== SHT_DYNSYM
) {
648 if (nm_opts
.print_symbol
!= PRINT_SYM_DYN
)
653 ndx
= shdr
.sh_type
== SHT_DYNSYM
? dynndx
: strndx
;
656 while ((data
= elf_getdata(scn
, data
)) != NULL
) {
658 while (gelf_getsym(data
, j
++, &sym
) != NULL
) {
659 sym_name
= get_sym_name(elf
, &sym
, ndx
,
660 sec_table
, sec_table_size
);
662 type
= get_sym_type(&sym
, type_table
);
663 SLIST_FOREACH(fep
, &nm_out_filter
,
665 if (!fep
->fn(type
, &sym
, sym_name
)) {
670 if (filter
== false) {
671 if (sym_list_insert(headp
, sym_name
,
684 get_sym_name(Elf
*elf
, const GElf_Sym
*sym
, size_t ndx
, const char **sec_table
,
687 const char *sym_name
;
691 /* Show section name as symbol name for STT_SECTION symbols. */
692 if (GELF_ST_TYPE(sym
->st_info
) == STT_SECTION
) {
693 if (sec_table
!= NULL
&& sym
->st_shndx
< sec_table_size
)
694 sym_name
= sec_table
[sym
->st_shndx
];
696 sym_name
= elf_strptr(elf
, ndx
, sym
->st_name
);
698 if (sym_name
== NULL
)
705 get_sym_type(const GElf_Sym
*sym
, const char *type_table
)
709 if (sym
== NULL
|| type_table
== NULL
)
712 is_local
= sym
->st_info
>> 4 == STB_LOCAL
;
714 if (sym
->st_shndx
== SHN_ABS
) /* absolute */
715 return (is_local
? 'a' : 'A');
717 if (sym
->st_shndx
== SHN_COMMON
) /* common */
720 if ((sym
->st_info
) >> 4 == STB_WEAK
) { /* weak */
721 if ((sym
->st_info
& 0xf) == STT_OBJECT
)
722 return (sym
->st_shndx
== SHN_UNDEF
? 'v' : 'V');
724 return (sym
->st_shndx
== SHN_UNDEF
? 'w' : 'W');
727 if (sym
->st_shndx
== SHN_UNDEF
) /* undefined */
730 return (is_local
== true && type_table
[sym
->st_shndx
] != 'N' ?
731 tolower((unsigned char) type_table
[sym
->st_shndx
]) :
732 type_table
[sym
->st_shndx
]);
746 if (elf_version(EV_CURRENT
) == EV_NONE
)
747 errx(EXIT_FAILURE
, "elf_version error");
749 nm_info
.name
= ELFTC_GETPROGNAME();
750 nm_info
.def_filename
= "a.out";
751 nm_opts
.print_symbol
= PRINT_SYM_SYM
;
752 nm_opts
.print_name
= PRINT_NAME_NONE
;
753 nm_opts
.demangle_type
= -1;
754 nm_opts
.print_debug
= false;
755 nm_opts
.print_armap
= false;
756 nm_opts
.print_size
= 0;
757 nm_opts
.debug_line
= false;
758 nm_opts
.def_only
= 0;
759 nm_opts
.undef_only
= false;
760 nm_opts
.sort_size
= 0;
761 nm_opts
.sort_reverse
= false;
762 nm_opts
.no_demangle
= 0;
763 nm_opts
.sort_fn
= &cmp_name
;
764 nm_opts
.elem_print_fn
= &sym_elem_print_all
;
765 nm_opts
.value_print_fn
= &sym_value_dec_print
;
766 nm_opts
.size_print_fn
= &sym_size_dec_print
;
767 SLIST_INIT(&nm_out_filter
);
771 is_sec_data(GElf_Shdr
*s
)
774 assert(s
!= NULL
&& "shdr is NULL");
776 return (((s
->sh_flags
& SHF_ALLOC
) != 0) && s
->sh_type
!= SHT_NOBITS
);
780 is_sec_debug(const char *shname
)
782 const char *dbg_sec
[] = {
796 for (p
= dbg_sec
; *p
; p
++) {
797 if (!strncmp(shname
, *p
, strlen(*p
)))
805 is_sec_nobits(GElf_Shdr
*s
)
808 assert(s
!= NULL
&& "shdr is NULL");
810 return (s
->sh_type
== SHT_NOBITS
);
814 is_sec_readonly(GElf_Shdr
*s
)
817 assert(s
!= NULL
&& "shdr is NULL");
819 return ((s
->sh_flags
& SHF_WRITE
) == 0);
823 is_sec_text(GElf_Shdr
*s
)
826 assert(s
!= NULL
&& "shdr is NULL");
828 return ((s
->sh_flags
& SHF_EXECINSTR
) != 0);
832 print_ar_index(int fd
, Elf
*arf
)
844 if ((arsym
= elf_getarsym(arf
, &arsym_size
)) == NULL
)
847 printf("\nArchive index:\n");
849 start
= arsym
->as_off
;
851 while (arsym_size
> 1) {
852 if (elf_rand(arf
, arsym
->as_off
) == arsym
->as_off
&&
853 (elf
= elf_begin(fd
, cmd
, arf
)) != NULL
) {
854 if ((arhdr
= elf_getarhdr(elf
)) != NULL
)
855 printf("%s in %s\n", arsym
->as_name
,
856 arhdr
->ar_name
!= NULL
?
857 arhdr
->ar_name
: arhdr
->ar_rawname
);
864 elf_rand(arf
, start
);
867 #define DEMANGLED_BUFFER_SIZE (8 * 1024)
868 #define PRINT_DEMANGLED_NAME(FORMAT, NAME) do { \
869 char _demangled[DEMANGLED_BUFFER_SIZE]; \
870 if (nm_opts.demangle_type < 0 || \
871 elftc_demangle((NAME), _demangled, sizeof(_demangled), \
872 nm_opts.demangle_type) < 0) \
873 printf((FORMAT), (NAME)); \
875 printf((FORMAT), _demangled); \
879 print_header(const char *file
, const char *obj
)
885 if (nm_opts
.elem_print_fn
== &sym_elem_print_all_sysv
) {
886 printf("\n\n%s from %s",
887 nm_opts
.undef_only
== false ? "Symbols" :
888 "Undefined symbols", file
);
894 Name Value Class Type Size Line Section\n\n");
896 /* archive file without -A option and POSIX */
897 if (nm_opts
.print_name
!= PRINT_NAME_FULL
&& obj
!= NULL
) {
898 if (nm_opts
.elem_print_fn
==
899 sym_elem_print_all_portable
)
900 printf("%s[%s]:\n", file
, obj
);
901 else if (nm_opts
.elem_print_fn
== sym_elem_print_all
)
902 printf("\n%s:\n", obj
);
903 /* multiple files(not archive) without -A option */
904 } else if (nm_opts
.print_name
== PRINT_NAME_MULTI
) {
905 if (nm_opts
.elem_print_fn
== sym_elem_print_all
)
907 printf("%s:\n", file
);
916 (void) printf("%s (%s)\n", nm_info
.name
, elftc_version());
921 get_block_value(Dwarf_Debug dbg
, Dwarf_Block
*block
)
927 if (dwarf_get_elf(dbg
, &elf
, &de
) != DW_DLV_OK
) {
928 warnx("dwarf_get_elf failed: %s", dwarf_errmsg(de
));
932 if (gelf_getehdr(elf
, &eh
) != &eh
) {
933 warnx("gelf_getehdr failed: %s", elf_errmsg(-1));
937 if (block
->bl_len
== 5) {
938 if (eh
.e_ident
[EI_DATA
] == ELFDATA2LSB
)
939 return (le32dec((uint8_t *) block
->bl_data
+ 1));
941 return (be32dec((uint8_t *) block
->bl_data
+ 1));
942 } else if (block
->bl_len
== 9) {
943 if (eh
.e_ident
[EI_DATA
] == ELFDATA2LSB
)
944 return (le64dec((uint8_t *) block
->bl_data
+ 1));
946 return (be64dec((uint8_t *) block
->bl_data
+ 1));
953 find_object_name(Dwarf_Debug dbg
, Dwarf_Die die
)
962 if (dwarf_attrval_string(die
, DW_AT_name
, &str
, &de
) == DW_DLV_OK
) {
963 if ((name
= strdup(str
)) == NULL
) {
970 if (dwarf_attr(die
, DW_AT_specification
, &at
, &de
) != DW_DLV_OK
)
973 if (dwarf_global_formref(at
, &off
, &de
) != DW_DLV_OK
)
976 if (dwarf_offdie(dbg
, off
, &ret_die
, &de
) != DW_DLV_OK
)
979 return (find_object_name(dbg
, ret_die
));
983 search_line_attr(Dwarf_Debug dbg
, struct func_info_head
*func_info
,
984 struct var_info_head
*var_info
, Dwarf_Die die
, char **src_files
,
985 Dwarf_Signed filecount
)
988 Dwarf_Unsigned udata
;
994 struct func_info_entry
*func
;
995 struct var_info_entry
*var
;
998 if (dwarf_tag(die
, &tag
, &de
) != DW_DLV_OK
) {
999 warnx("dwarf_tag failed: %s", dwarf_errmsg(de
));
1003 /* We're interested in DIEs which define functions or variables. */
1004 if (tag
!= DW_TAG_subprogram
&& tag
!= DW_TAG_entry_point
&&
1005 tag
!= DW_TAG_inlined_subroutine
&& tag
!= DW_TAG_variable
)
1008 if (tag
== DW_TAG_variable
) {
1010 /* Ignore "artificial" variable. */
1011 if (dwarf_attrval_flag(die
, DW_AT_artificial
, &flag
, &de
) ==
1015 /* Ignore pure declaration. */
1016 if (dwarf_attrval_flag(die
, DW_AT_declaration
, &flag
, &de
) ==
1020 /* Ignore stack varaibles. */
1021 if (dwarf_attrval_flag(die
, DW_AT_external
, &flag
, &de
) !=
1025 if ((var
= calloc(1, sizeof(*var
))) == NULL
) {
1026 warn("calloc failed");
1030 if (dwarf_attrval_unsigned(die
, DW_AT_decl_file
, &udata
,
1031 &de
) == DW_DLV_OK
&& udata
> 0 &&
1032 (Dwarf_Signed
) (udata
- 1) < filecount
) {
1033 var
->file
= strdup(src_files
[udata
- 1]);
1034 if (var
->file
== NULL
) {
1041 if (dwarf_attrval_unsigned(die
, DW_AT_decl_line
, &udata
, &de
) ==
1045 var
->name
= find_object_name(dbg
, die
);
1046 if (var
->name
== NULL
) {
1053 if (dwarf_attr(die
, DW_AT_location
, &at
, &de
) == DW_DLV_OK
&&
1054 dwarf_formblock(at
, &block
, &de
) == DW_DLV_OK
) {
1056 * Since we ignored stack variables, the rest are the
1057 * external varaibles which should always use DW_OP_addr
1058 * operator for DW_AT_location value.
1060 if (*((uint8_t *)block
->bl_data
) == DW_OP_addr
)
1061 var
->addr
= get_block_value(dbg
, block
);
1064 SLIST_INSERT_HEAD(var_info
, var
, entries
);
1068 if ((func
= calloc(1, sizeof(*func
))) == NULL
) {
1069 warn("calloc failed");
1074 * Note that dwarf_attrval_unsigned() handles DW_AT_abstract_origin
1075 * internally, so it can retrieve DW_AT_decl_file/DW_AT_decl_line
1076 * attributes for inlined functions as well.
1078 if (dwarf_attrval_unsigned(die
, DW_AT_decl_file
, &udata
,
1079 &de
) == DW_DLV_OK
&& udata
> 0 &&
1080 (Dwarf_Signed
) (udata
- 1) < filecount
) {
1081 func
->file
= strdup(src_files
[udata
- 1]);
1082 if (func
->file
== NULL
) {
1089 if (dwarf_attrval_unsigned(die
, DW_AT_decl_line
, &udata
, &de
) ==
1093 func
->name
= find_object_name(dbg
, die
);
1094 if (func
->name
== NULL
) {
1101 if (dwarf_attrval_unsigned(die
, DW_AT_low_pc
, &udata
, &de
) ==
1103 func
->lowpc
= udata
;
1104 if (dwarf_attrval_unsigned(die
, DW_AT_high_pc
, &udata
, &de
) ==
1106 func
->highpc
= udata
;
1108 SLIST_INSERT_HEAD(func_info
, func
, entries
);
1113 /* Search children. */
1114 ret
= dwarf_child(die
, &ret_die
, &de
);
1115 if (ret
== DW_DLV_ERROR
)
1116 warnx("dwarf_child: %s", dwarf_errmsg(de
));
1117 else if (ret
== DW_DLV_OK
)
1118 search_line_attr(dbg
, func_info
, var_info
, ret_die
, src_files
,
1121 /* Search sibling. */
1122 ret
= dwarf_siblingof(dbg
, die
, &ret_die
, &de
);
1123 if (ret
== DW_DLV_ERROR
)
1124 warnx("dwarf_siblingof: %s", dwarf_errmsg(de
));
1125 else if (ret
== DW_DLV_OK
)
1126 search_line_attr(dbg
, func_info
, var_info
, ret_die
, src_files
,
1129 dwarf_dealloc(dbg
, die
, DW_DLA_DIE
);
1133 * Read elf file and collect symbol information, sort them, print.
1134 * Return 1 at failed, 0 at success.
1137 read_elf(Elf
*elf
, const char *filename
, Elf_Kind kind
)
1148 Dwarf_Unsigned lineno
;
1149 Dwarf_Signed lcount
, filecount
;
1150 Dwarf_Addr lineaddr
;
1151 struct sym_print_data p_data
;
1152 struct sym_head list_head
;
1153 struct line_info_head
*line_info
;
1154 struct func_info_head
*func_info
;
1155 struct var_info_head
*var_info
;
1156 struct line_info_entry
*lie
;
1157 struct func_info_entry
*func
;
1158 struct var_info_entry
*var
;
1159 const char *shname
, *objname
;
1160 char *type_table
, **sec_table
, *sfile
, **src_files
;
1161 size_t shstrndx
, shnum
, dynndx
, strndx
;
1162 int ret
, rtn
, e_err
;
1164 #define OBJNAME (objname == NULL ? filename : objname)
1166 assert(filename
!= NULL
&& "filename is null");
1168 STAILQ_INIT(&list_head
);
1179 nm_elfclass
= gelf_getclass(elf
);
1181 if (kind
== ELF_K_AR
) {
1182 if ((arhdr
= elf_getarhdr(elf
)) == NULL
)
1184 objname
= arhdr
->ar_name
!= NULL
? arhdr
->ar_name
:
1187 if (!elf_getshnum(elf
, &shnum
)) {
1188 if ((e_err
= elf_errno()) != 0)
1189 warnx("%s: %s", OBJNAME
, elf_errmsg(e_err
));
1191 warnx("%s: cannot get section number", OBJNAME
);
1196 warnx("%s: has no section", OBJNAME
);
1200 if (!elf_getshstrndx(elf
, &shstrndx
)) {
1201 warnx("%s: cannot get str index", OBJNAME
);
1205 /* type_table for type determine */
1206 if ((type_table
= malloc(sizeof(char) * shnum
)) == NULL
) {
1207 warn("%s: malloc", OBJNAME
);
1211 /* sec_table for section name to display in sysv format */
1212 if ((sec_table
= calloc(shnum
, sizeof(char *))) == NULL
) {
1213 warn("%s: calloc", OBJNAME
);
1218 type_table
[0] = 'U';
1219 if ((sec_table
[0] = strdup("*UND*")) == NULL
) {
1224 for (i
= 1; i
< shnum
; ++i
) {
1225 type_table
[i
] = 'U';
1226 if ((scn
= elf_getscn(elf
, i
)) == NULL
) {
1227 if ((e_err
= elf_errno()) != 0)
1228 warnx("%s: %s", OBJNAME
, elf_errmsg(e_err
));
1230 warnx("%s: cannot get section", OBJNAME
);
1234 if (gelf_getshdr(scn
, &shdr
) == NULL
)
1238 * Cannot test by type and attribute for dynstr, strtab
1240 shname
= elf_strptr(elf
, shstrndx
, (size_t) shdr
.sh_name
);
1241 if (shname
!= NULL
) {
1242 if ((sec_table
[i
] = strdup(shname
)) == NULL
) {
1246 if (!strncmp(shname
, ".dynstr", 7)) {
1247 dynndx
= elf_ndxscn(scn
);
1248 if (dynndx
== SHN_UNDEF
) {
1249 warnx("%s: elf_ndxscn failed: %s",
1250 OBJNAME
, elf_errmsg(-1));
1254 if (!strncmp(shname
, ".strtab", 7)) {
1255 strndx
= elf_ndxscn(scn
);
1256 if (strndx
== SHN_UNDEF
) {
1257 warnx("%s: elf_ndxscn failed: %s",
1258 OBJNAME
, elf_errmsg(-1));
1263 sec_table
[i
] = strdup("*UND*");
1264 if (sec_table
[i
] == NULL
) {
1271 if (is_sec_text(&shdr
))
1272 type_table
[i
] = 'T';
1273 else if (is_sec_data(&shdr
)) {
1274 if (is_sec_readonly(&shdr
))
1275 type_table
[i
] = 'R';
1277 type_table
[i
] = 'D';
1278 } else if (is_sec_nobits(&shdr
))
1279 type_table
[i
] = 'B';
1280 else if (is_sec_debug(shname
))
1281 type_table
[i
] = 'N';
1282 else if (is_sec_readonly(&shdr
) && !is_sec_nobits(&shdr
))
1283 type_table
[i
] = 'n';
1286 print_header(filename
, objname
);
1288 if ((dynndx
== SHN_UNDEF
&& nm_opts
.print_symbol
== PRINT_SYM_DYN
) ||
1289 (strndx
== SHN_UNDEF
&& nm_opts
.print_symbol
== PRINT_SYM_SYM
)) {
1290 warnx("%s: no symbols", OBJNAME
);
1291 /* This is not an error case */
1295 STAILQ_INIT(&list_head
);
1297 if (!nm_opts
.debug_line
)
1301 * Collect dwarf line number information.
1304 if (dwarf_elf_init(elf
, DW_DLC_READ
, NULL
, NULL
, &dbg
, &de
) !=
1306 warnx("dwarf_elf_init failed: %s", dwarf_errmsg(de
));
1310 line_info
= malloc(sizeof(struct line_info_head
));
1311 func_info
= malloc(sizeof(struct func_info_head
));
1312 var_info
= malloc(sizeof(struct var_info_head
));
1313 if (line_info
== NULL
|| func_info
== NULL
|| var_info
== NULL
) {
1315 (void) dwarf_finish(dbg
, &de
);
1318 SLIST_INIT(line_info
);
1319 SLIST_INIT(func_info
);
1320 SLIST_INIT(var_info
);
1322 while ((ret
= dwarf_next_cu_header(dbg
, NULL
, NULL
, NULL
, NULL
, NULL
,
1323 &de
)) == DW_DLV_OK
) {
1325 while (dwarf_siblingof(dbg
, die
, &die
, &de
) == DW_DLV_OK
) {
1326 if (dwarf_tag(die
, &tag
, &de
) != DW_DLV_OK
) {
1327 warnx("dwarf_tag failed: %s",
1331 /* XXX: What about DW_TAG_partial_unit? */
1332 if (tag
== DW_TAG_compile_unit
)
1336 warnx("could not find DW_TAG_compile_unit die");
1340 /* Retrieve source file list. */
1341 ret
= dwarf_srcfiles(die
, &src_files
, &filecount
, &de
);
1342 if (ret
== DW_DLV_ERROR
)
1343 warnx("dwarf_srclines: %s", dwarf_errmsg(de
));
1344 if (ret
!= DW_DLV_OK
)
1348 * Retrieve line number information from .debug_line section.
1351 ret
= dwarf_srclines(die
, &lbuf
, &lcount
, &de
);
1352 if (ret
== DW_DLV_ERROR
)
1353 warnx("dwarf_srclines: %s", dwarf_errmsg(de
));
1354 if (ret
!= DW_DLV_OK
)
1356 for (i
= 0; (Dwarf_Signed
) i
< lcount
; i
++) {
1357 if (dwarf_lineaddr(lbuf
[i
], &lineaddr
, &de
)) {
1358 warnx("dwarf_lineaddr: %s", dwarf_errmsg(de
));
1361 if (dwarf_lineno(lbuf
[i
], &lineno
, &de
)) {
1362 warnx("dwarf_lineno: %s", dwarf_errmsg(de
));
1365 if (dwarf_linesrc(lbuf
[i
], &sfile
, &de
)) {
1366 warnx("dwarf_linesrc: %s", dwarf_errmsg(de
));
1369 if ((lie
= malloc(sizeof(*lie
))) == NULL
) {
1373 lie
->addr
= lineaddr
;
1375 lie
->file
= strdup(sfile
);
1376 if (lie
->file
== NULL
) {
1381 SLIST_INSERT_HEAD(line_info
, lie
, entries
);
1385 /* Retrieve line number information from DIEs. */
1386 search_line_attr(dbg
, func_info
, var_info
, die
, src_files
, filecount
);
1389 (void) dwarf_finish(dbg
, &de
);
1393 p_data
.list_num
= get_sym(elf
, &list_head
, shnum
, dynndx
, strndx
,
1394 type_table
, (void *) sec_table
, shnum
);
1396 if (p_data
.list_num
== 0)
1399 p_data
.headp
= &list_head
;
1400 p_data
.sh_num
= shnum
;
1401 p_data
.t_table
= type_table
;
1402 p_data
.s_table
= (void *) sec_table
;
1403 p_data
.filename
= filename
;
1404 p_data
.objname
= objname
;
1406 sym_list_print(&p_data
, func_info
, var_info
, line_info
);
1409 if (nm_opts
.debug_line
) {
1410 if (func_info
!= NULL
) {
1411 while (!SLIST_EMPTY(func_info
)) {
1412 func
= SLIST_FIRST(func_info
);
1413 SLIST_REMOVE_HEAD(func_info
, entries
);
1421 if (var_info
!= NULL
) {
1422 while (!SLIST_EMPTY(var_info
)) {
1423 var
= SLIST_FIRST(var_info
);
1424 SLIST_REMOVE_HEAD(var_info
, entries
);
1432 if (line_info
!= NULL
) {
1433 while (!SLIST_EMPTY(line_info
)) {
1434 lie
= SLIST_FIRST(line_info
);
1435 SLIST_REMOVE_HEAD(line_info
, entries
);
1444 if (sec_table
!= NULL
)
1445 for (i
= 0; i
< shnum
; ++i
)
1450 sym_list_dest(&list_head
);
1458 read_object(const char *filename
)
1465 assert(filename
!= NULL
&& "filename is null");
1467 if ((fd
= open(filename
, O_RDONLY
)) == -1) {
1468 warn("'%s'", filename
);
1472 elf_cmd
= ELF_C_READ
;
1473 if ((arf
= elf_begin(fd
, elf_cmd
, (Elf
*) NULL
)) == NULL
) {
1474 if ((e_err
= elf_errno()) != 0)
1475 warnx("elf_begin error: %s", elf_errmsg(e_err
));
1477 warnx("elf_begin error");
1482 assert(arf
!= NULL
&& "arf is null.");
1485 if ((kind
= elf_kind(arf
)) == ELF_K_NONE
) {
1486 warnx("%s: File format not recognized", filename
);
1491 if (kind
== ELF_K_AR
) {
1492 if (nm_opts
.print_name
== PRINT_NAME_MULTI
&&
1493 nm_opts
.elem_print_fn
== sym_elem_print_all
)
1494 printf("\n%s:\n", filename
);
1495 if (nm_opts
.print_armap
== true)
1496 print_ar_index(fd
, arf
);
1499 while ((elf
= elf_begin(fd
, elf_cmd
, arf
)) != NULL
) {
1500 rtn
|= read_elf(elf
, filename
, kind
);
1503 * If file is not archive, elf_next return ELF_C_NULL and
1506 elf_cmd
= elf_next(elf
);
1517 read_files(int argc
, char **argv
)
1521 if (argc
< 0 || argv
== NULL
)
1525 rtn
|= read_object(nm_info
.def_filename
);
1527 if (nm_opts
.print_name
== PRINT_NAME_NONE
&& argc
> 1)
1528 nm_opts
.print_name
= PRINT_NAME_MULTI
;
1530 rtn
|= read_object(*argv
);
1540 print_lineno(struct sym_entry
*ep
, struct func_info_head
*func_info
,
1541 struct var_info_head
*var_info
, struct line_info_head
*line_info
)
1543 struct func_info_entry
*func
;
1544 struct var_info_entry
*var
;
1545 struct line_info_entry
*lie
;
1547 /* For function symbol, search the function line information list. */
1548 if ((ep
->sym
->st_info
& 0xf) == STT_FUNC
&& func_info
!= NULL
) {
1549 SLIST_FOREACH(func
, func_info
, entries
) {
1550 if (func
->name
!= NULL
&&
1551 !strcmp(ep
->name
, func
->name
) &&
1552 ep
->sym
->st_value
>= func
->lowpc
&&
1553 ep
->sym
->st_value
< func
->highpc
) {
1554 printf("\t%s:%" PRIu64
, func
->file
, func
->line
);
1560 /* For variable symbol, search the variable line information list. */
1561 if ((ep
->sym
->st_info
& 0xf) == STT_OBJECT
&& var_info
!= NULL
) {
1562 SLIST_FOREACH(var
, var_info
, entries
) {
1563 if (!strcmp(ep
->name
, var
->name
) &&
1564 ep
->sym
->st_value
== var
->addr
) {
1565 printf("\t%s:%" PRIu64
, var
->file
, var
->line
);
1571 /* Otherwise search line number information the .debug_line section. */
1572 if (line_info
!= NULL
) {
1573 SLIST_FOREACH(lie
, line_info
, entries
) {
1574 if (ep
->sym
->st_value
== lie
->addr
) {
1575 printf("\t%s:%" PRIu64
, lie
->file
, lie
->line
);
1583 set_opt_value_print_fn(enum radix t
)
1588 nm_opts
.value_print_fn
= &sym_value_oct_print
;
1589 nm_opts
.size_print_fn
= &sym_size_oct_print
;
1593 nm_opts
.value_print_fn
= &sym_value_dec_print
;
1594 nm_opts
.size_print_fn
= &sym_size_dec_print
;
1599 nm_opts
.value_print_fn
= &sym_value_hex_print
;
1600 nm_opts
.size_print_fn
= &sym_size_hex_print
;
1603 assert(nm_opts
.value_print_fn
!= NULL
&&
1604 "nm_opts.value_print_fn is null");
1608 sym_elem_print_all(char type
, const char *sec
, const GElf_Sym
*sym
,
1612 if (sec
== NULL
|| sym
== NULL
|| name
== NULL
||
1613 nm_opts
.value_print_fn
== NULL
)
1616 if (IS_UNDEF_SYM_TYPE(type
)) {
1617 if (nm_opts
.t
== RADIX_HEX
&& nm_elfclass
== ELFCLASS32
)
1620 printf("%-16s", "");
1622 switch ((nm_opts
.sort_fn
== & cmp_size
? 2 : 0) +
1623 nm_opts
.print_size
) {
1625 if (sym
->st_size
!= 0) {
1626 nm_opts
.value_print_fn(sym
);
1628 nm_opts
.size_print_fn(sym
);
1633 if (sym
->st_size
!= 0)
1634 nm_opts
.size_print_fn(sym
);
1638 nm_opts
.value_print_fn(sym
);
1639 if (sym
->st_size
!= 0) {
1641 nm_opts
.size_print_fn(sym
);
1647 nm_opts
.value_print_fn(sym
);
1651 printf(" %c ", type
);
1652 PRINT_DEMANGLED_NAME("%s", name
);
1656 sym_elem_print_all_portable(char type
, const char *sec
, const GElf_Sym
*sym
,
1660 if (sec
== NULL
|| sym
== NULL
|| name
== NULL
||
1661 nm_opts
.value_print_fn
== NULL
)
1664 PRINT_DEMANGLED_NAME("%s", name
);
1665 printf(" %c ", type
);
1666 if (!IS_UNDEF_SYM_TYPE(type
)) {
1667 nm_opts
.value_print_fn(sym
);
1669 if (sym
->st_size
!= 0)
1670 nm_opts
.size_print_fn(sym
);
1676 sym_elem_print_all_sysv(char type
, const char *sec
, const GElf_Sym
*sym
,
1680 if (sec
== NULL
|| sym
== NULL
|| name
== NULL
||
1681 nm_opts
.value_print_fn
== NULL
)
1684 PRINT_DEMANGLED_NAME("%-20s|", name
);
1685 if (IS_UNDEF_SYM_TYPE(type
))
1688 nm_opts
.value_print_fn(sym
);
1690 printf("| %c |", type
);
1692 switch (sym
->st_info
& 0xf) {
1694 printf("%18s|", "OBJECT");
1698 printf("%18s|", "FUNC");
1702 printf("%18s|", "SECTION");
1706 printf("%18s|", "FILE");
1710 printf("%18s|", "LOPROC");
1714 printf("%18s|", "HIPROC");
1719 printf("%18s|", "NOTYPE");
1722 if (sym
->st_size
!= 0)
1723 nm_opts
.size_print_fn(sym
);
1727 printf("| |%s", sec
);
1731 sym_elem_def(char type
, const GElf_Sym
*sym
, const char *name
)
1734 assert(IS_SYM_TYPE((unsigned char) type
));
1739 return (!IS_UNDEF_SYM_TYPE((unsigned char) type
));
1743 sym_elem_global(char type
, const GElf_Sym
*sym
, const char *name
)
1746 assert(IS_SYM_TYPE((unsigned char) type
));
1751 /* weak symbols resemble global. */
1752 return (isupper((unsigned char) type
) || type
== 'w');
1756 sym_elem_global_static(char type
, const GElf_Sym
*sym
, const char *name
)
1760 assert(sym
!= NULL
);
1765 info
= sym
->st_info
>> 4;
1767 return (info
== STB_LOCAL
||
1768 info
== STB_GLOBAL
||
1773 sym_elem_nondebug(char type
, const GElf_Sym
*sym
, const char *name
)
1776 assert(sym
!= NULL
);
1781 if (sym
->st_value
== 0 && (sym
->st_info
& 0xf) == STT_FILE
)
1783 if (sym
->st_name
== 0)
1790 sym_elem_nonzero_size(char type
, const GElf_Sym
*sym
, const char *name
)
1793 assert(sym
!= NULL
);
1798 return (sym
->st_size
> 0);
1802 sym_elem_undef(char type
, const GElf_Sym
*sym
, const char *name
)
1805 assert(IS_SYM_TYPE((unsigned char) type
));
1810 return (IS_UNDEF_SYM_TYPE((unsigned char) type
));
1814 sym_list_dest(struct sym_head
*headp
)
1816 struct sym_entry
*ep
, *ep_n
;
1821 ep
= STAILQ_FIRST(headp
);
1822 while (ep
!= NULL
) {
1823 ep_n
= STAILQ_NEXT(ep
, sym_entries
);
1832 sym_list_insert(struct sym_head
*headp
, const char *name
, const GElf_Sym
*sym
)
1834 struct sym_entry
*e
;
1836 if (headp
== NULL
|| name
== NULL
|| sym
== NULL
)
1838 if ((e
= malloc(sizeof(struct sym_entry
))) == NULL
) {
1842 if ((e
->name
= strdup(name
)) == NULL
) {
1847 if ((e
->sym
= malloc(sizeof(GElf_Sym
))) == NULL
) {
1854 memcpy(e
->sym
, sym
, sizeof(GElf_Sym
));
1856 /* Display size instead of value for common symbol. */
1857 if (sym
->st_shndx
== SHN_COMMON
)
1858 e
->sym
->st_value
= sym
->st_size
;
1860 STAILQ_INSERT_TAIL(headp
, e
, sym_entries
);
1865 /* If file has not .debug_info, line_info will be NULL */
1867 sym_list_print(struct sym_print_data
*p
, struct func_info_head
*func_info
,
1868 struct var_info_head
*var_info
, struct line_info_head
*line_info
)
1870 struct sym_entry
*e_v
;
1874 if (p
== NULL
|| CHECK_SYM_PRINT_DATA(p
))
1876 if ((e_v
= sym_list_sort(p
)) == NULL
)
1878 if (nm_opts
.sort_reverse
== false)
1879 for (si
= 0; si
!= p
->list_num
; ++si
)
1880 sym_list_print_each(&e_v
[si
], p
, func_info
, var_info
,
1883 for (i
= p
->list_num
- 1; i
!= -1; --i
)
1884 sym_list_print_each(&e_v
[i
], p
, func_info
, var_info
,
1890 /* If file has not .debug_info, line_info will be NULL */
1892 sym_list_print_each(struct sym_entry
*ep
, struct sym_print_data
*p
,
1893 struct func_info_head
*func_info
, struct var_info_head
*var_info
,
1894 struct line_info_head
*line_info
)
1899 if (ep
== NULL
|| CHECK_SYM_PRINT_DATA(p
))
1902 assert(ep
->name
!= NULL
);
1903 assert(ep
->sym
!= NULL
);
1905 type
= get_sym_type(ep
->sym
, p
->t_table
);
1907 if (nm_opts
.print_name
== PRINT_NAME_FULL
) {
1908 printf("%s", p
->filename
);
1909 if (nm_opts
.elem_print_fn
== &sym_elem_print_all_portable
) {
1910 if (p
->objname
!= NULL
)
1911 printf("[%s]", p
->objname
);
1914 if (p
->objname
!= NULL
)
1915 printf(":%s", p
->objname
);
1920 switch (ep
->sym
->st_shndx
) {
1922 /* LOPROC or LORESERVE */
1941 /* HIRESERVE or XINDEX */
1942 sec
= "*HIRESERVE*";
1945 if (ep
->sym
->st_shndx
> p
->sh_num
)
1947 sec
= p
->s_table
[ep
->sym
->st_shndx
];
1951 nm_opts
.elem_print_fn(type
, sec
, ep
->sym
, ep
->name
);
1953 if (nm_opts
.debug_line
== true && !IS_UNDEF_SYM_TYPE(type
))
1954 print_lineno(ep
, func_info
, var_info
, line_info
);
1959 static struct sym_entry
*
1960 sym_list_sort(struct sym_print_data
*p
)
1962 struct sym_entry
*ep
, *e_v
;
1965 if (p
== NULL
|| CHECK_SYM_PRINT_DATA(p
))
1968 if ((e_v
= malloc(sizeof(struct sym_entry
) * p
->list_num
)) == NULL
) {
1974 STAILQ_FOREACH(ep
, p
->headp
, sym_entries
) {
1975 if (ep
->name
!= NULL
&& ep
->sym
!= NULL
) {
1976 e_v
[idx
].name
= ep
->name
;
1977 e_v
[idx
].sym
= ep
->sym
;
1982 assert((size_t)idx
== p
->list_num
);
1984 if (nm_opts
.sort_fn
!= &cmp_none
) {
1986 assert(nm_print_data
!= NULL
);
1987 qsort(e_v
, p
->list_num
, sizeof(struct sym_entry
),
1995 sym_size_oct_print(const GElf_Sym
*sym
)
1998 assert(sym
!= NULL
&& "sym is null");
1999 printf("%016" PRIo64
, sym
->st_size
);
2003 sym_size_hex_print(const GElf_Sym
*sym
)
2006 assert(sym
!= NULL
&& "sym is null");
2007 if (nm_elfclass
== ELFCLASS32
)
2008 printf("%08" PRIx64
, sym
->st_size
);
2010 printf("%016" PRIx64
, sym
->st_size
);
2014 sym_size_dec_print(const GElf_Sym
*sym
)
2017 assert(sym
!= NULL
&& "sym is null");
2018 printf("%016" PRId64
, sym
->st_size
);
2022 sym_value_oct_print(const GElf_Sym
*sym
)
2025 assert(sym
!= NULL
&& "sym is null");
2026 printf("%016" PRIo64
, sym
->st_value
);
2030 sym_value_hex_print(const GElf_Sym
*sym
)
2033 assert(sym
!= NULL
&& "sym is null");
2034 if (nm_elfclass
== ELFCLASS32
)
2035 printf("%08" PRIx64
, sym
->st_value
);
2037 printf("%016" PRIx64
, sym
->st_value
);
2041 sym_value_dec_print(const GElf_Sym
*sym
)
2044 assert(sym
!= NULL
&& "sym is null");
2045 printf("%016" PRId64
, sym
->st_value
);
2052 printf("Usage: %s [options] file ...\
2053 \n Display symbolic information in file.\n\
2055 \n -A, --print-file-name Write the full pathname or library name of an\
2056 \n object on each line.\
2057 \n -a, --debug-syms Display all symbols include debugger-only\
2058 \n symbols.", nm_info
.name
);
2060 \n -B Equivalent to specifying \"--format=bsd\".\
2061 \n -C, --demangle[=style] Decode low-level symbol names.\
2062 \n --no-demangle Do not demangle low-level symbol names.\
2063 \n -D, --dynamic Display only dynamic symbols.\
2064 \n -e Display only global and static symbols.");
2066 \n -f Produce full output (default).\
2067 \n --format=format Display output in specific format. Allowed\
2068 \n formats are: \"bsd\", \"posix\" and \"sysv\".\
2069 \n -g, --extern-only Display only global symbol information.\
2070 \n -h, --help Show this help message.\
2071 \n -l, --line-numbers Display filename and linenumber using\
2072 \n debugging information.\
2073 \n -n, --numeric-sort Sort symbols numerically by value.");
2075 \n -o Write numeric values in octal. Equivalent to\
2076 \n specifying \"-t o\".\
2077 \n -p, --no-sort Do not sort symbols.\
2078 \n -P Write information in a portable output format.\
2079 \n Equivalent to specifying \"--format=posix\".\
2080 \n -r, --reverse-sort Reverse the order of the sort.\
2081 \n -S, --print-size Print symbol sizes instead values.\
2082 \n -s, --print-armap Include an index of archive members.\
2083 \n --size-sort Sort symbols by size.");
2085 \n -t, --radix=format Write each numeric value in the specified\
2089 \n x In hexadecimal.");
2091 \n -u, --undefined-only Display only undefined symbols.\
2092 \n --defined-only Display only defined symbols.\
2093 \n -V, --version Show the version identifier for %s.\
2094 \n -v Sort output by value.\
2095 \n -x Write numeric values in hexadecimal.\
2096 \n Equivalent to specifying \"-t x\".",
2099 \n The default options are: output in bsd format, use a hexadecimal radix,\
2100 \n sort by symbol name, do not demangle names.\n");
2106 * Display symbolic information in file.
2107 * Return 0 at success, >0 at failed.
2110 main(int argc
, char **argv
)
2115 get_opt(argc
, argv
);
2116 rtn
= read_files(argc
- optind
, argv
+ optind
);