1 /* Print symbol information from ELF file in human-readable form.
2 Copyright (C) 2000-2008, 2009, 2011, 2012 Red Hat, Inc.
3 This file is part of Red Hat elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2000.
6 Red Hat elfutils is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by the
8 Free Software Foundation; version 2 of the License.
10 Red Hat elfutils is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with Red Hat elfutils; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
19 Red Hat elfutils is an included package of the Open Invention Network.
20 An included package of the Open Invention Network is a package for which
21 Open Invention Network licensees cross-license their patents. No patent
22 license is granted, either expressly or impliedly, by designation as an
23 included package. Should you wish to participate in the Open Invention
24 Network licensing program, please visit www.openinventionnetwork.com
25 <http://www.openinventionnetwork.com>. */
49 #include <stdio_ext.h>
53 #include <sys/param.h>
56 #include "../libebl/libeblP.h"
59 /* Name and version of program. */
60 static void print_version (FILE *stream, struct argp_state *state);
61 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
63 /* Bug report address. */
64 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
67 /* Values for the parameters which have no short form. */
68 #define OPT_DEFINED 0x100
69 #define OPT_MARK_SPECIAL 0x101
71 /* Definitions of arguments for argp functions. */
72 static const struct argp_option options[] =
74 { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
75 { "debug-syms", 'a', NULL, 0, N_("Display debugger-only symbols"), 0 },
76 { "defined-only", OPT_DEFINED, NULL, 0, N_("Display only defined symbols"),
78 { "dynamic", 'D', NULL, 0,
79 N_("Display dynamic symbols instead of normal symbols"), 0 },
80 { "extern-only", 'g', NULL, 0, N_("Display only external symbols"), 0 },
81 { "undefined-only", 'u', NULL, 0, N_("Display only undefined symbols"), 0 },
82 { "print-armap", 's', NULL, 0,
83 N_("Include index for symbols from archive members"), 0 },
85 { NULL, 0, NULL, 0, N_("Output format:"), 0 },
86 { "print-file-name", 'A', NULL, 0,
87 N_("Print name of the input file before every symbol"), 0 },
88 { NULL, 'o', NULL, OPTION_HIDDEN, "Same as -A", 0 },
89 { "format", 'f', "FORMAT", 0,
90 N_("Use the output format FORMAT. FORMAT can be `bsd', `sysv' or `posix'. The default is `sysv'"),
92 { NULL, 'B', NULL, 0, N_("Same as --format=bsd"), 0 },
93 { "portability", 'P', NULL, 0, N_("Same as --format=posix"), 0 },
94 { "radix", 't', "RADIX", 0, N_("Use RADIX for printing symbol values"), 0 },
95 { "mark-special", OPT_MARK_SPECIAL, NULL, 0, N_("Mark special symbols"), 0 },
96 { "mark-weak", OPT_MARK_SPECIAL, NULL, OPTION_HIDDEN, "", 0 },
97 { "print-size", 'S', NULL, 0, N_("Print size of defined symbols"), 0 },
99 { NULL, 0, NULL, 0, N_("Output options:"), 0 },
100 { "numeric-sort", 'n', NULL, 0, N_("Sort symbols numerically by address"),
102 { "no-sort", 'p', NULL, 0, N_("Do not sort the symbols"), 0 },
103 { "reverse-sort", 'r', NULL, 0, N_("Reverse the sense of the sort"), 0 },
105 { "demangle", 'C', NULL, 0,
106 N_("Decode low-level symbol names into source code names"), 0 },
108 { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
109 { NULL, 0, NULL, 0, NULL, 0 }
112 /* Short description of program. */
113 static const char doc[] = N_("List symbols from FILEs (a.out by default).");
115 /* Strings for arguments in help texts. */
116 static const char args_doc[] = N_("[FILE...]");
118 /* Prototype for option handler. */
119 static error_t parse_opt (int key, char *arg, struct argp_state *state);
121 /* Parser children. */
122 static struct argp_child argp_children[] =
124 { &color_argp, 0, N_("Output formatting"), 2 },
128 /* Data structure to communicate with argp functions. */
129 static struct argp argp =
131 options, parse_opt, args_doc, doc, argp_children, NULL, NULL
135 /* Print symbols in file named FNAME. */
136 static int process_file (const char *fname, bool more_than_one);
138 /* Handle content of archive. */
139 static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
142 /* Handle ELF file. */
143 static int handle_elf (Elf *elf, const char *prefix, const char *fname,
147 #define INTERNAL_ERROR(fname) \
148 error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \
149 fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1))
152 /* Internal representation of symbols. */
153 typedef struct GElf_SymX
161 /* User-selectable options. */
163 /* The selected output format. */
171 /* Print defined, undefined, or both? */
172 static bool hide_undefined;
173 static bool hide_defined;
175 /* Print local symbols also? */
176 static bool hide_local;
178 /* Nonzero if full filename should precede every symbol. */
179 static bool print_file_name;
181 /* If true print size of defined symbols in BSD format. */
182 static bool print_size;
184 /* If true print archive index. */
185 static bool print_armap;
187 /* If true reverse sorting. */
188 static bool reverse_sort;
191 /* If true demangle symbols. */
192 static bool demangle;
195 /* Type of the section we are printing. */
196 static GElf_Word symsec_type = SHT_SYMTAB;
198 /* Sorting selection. */
206 /* Radix for printed numbers. */
214 /* If nonzero mark special symbols:
215 - weak symbols are distinguished from global symbols by adding
216 a `*' after the identifying letter for the symbol class and type.
217 - TLS symbols are distinguished from normal symbols by adding
218 a '@' after the identifying letter for the symbol class and type. */
219 static bool mark_special;
223 main (int argc, char *argv[])
228 /* Make memory leak detection possible. */
231 /* We use no threads here which can interfere with handling a stream. */
232 (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
233 (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
234 (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
237 (void) setlocale (LC_ALL, "");
239 /* Make sure the message catalog can be found. */
240 (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
242 /* Initialize the message catalog. */
243 (void) textdomain (PACKAGE_TARNAME);
245 /* Parse and process arguments. */
246 (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
248 /* Tell the library which version we are expecting. */
249 (void) elf_version (EV_CURRENT);
251 if (remaining == argc)
252 /* The user didn't specify a name so we use a.out. */
253 result = process_file ("a.out", false);
256 /* Process all the remaining files. */
257 const bool more_than_one = remaining + 1 < argc;
260 result |= process_file (argv[remaining], more_than_one);
261 while (++remaining < argc);
268 /* Print the version information. */
270 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
272 fprintf (stream, "nm (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
273 fprintf (stream, gettext ("\
274 Copyright (C) %s Red Hat, Inc.\n\
275 This is free software; see the source for copying conditions. There is NO\n\
276 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
278 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
282 /* Handle program arguments. */
284 parse_opt (int key, char *arg,
285 struct argp_state *state __attribute__ ((unused)))
300 if (strcmp (arg, "bsd") == 0)
302 else if (strcmp (arg, "posix") == 0)
303 format = format_posix;
305 /* Be bug compatible. The BFD implementation also defaulted to
306 using the SysV format if nothing else matches. */
307 format = format_sysv;
323 if (strcmp (arg, "10") == 0 || strcmp (arg, "d") == 0)
324 radix = radix_decimal;
325 else if (strcmp (arg, "8") == 0 || strcmp (arg, "o") == 0)
332 hide_undefined = false;
338 print_file_name = true;
346 symsec_type = SHT_DYNSYM;
350 format = format_posix;
354 hide_undefined = true;
355 hide_defined = false;
358 case OPT_MARK_SPECIAL:
375 return ARGP_ERR_UNKNOWN;
381 /* Open the file and determine the type. */
383 process_file (const char *fname, bool more_than_one)
386 int fd = open (fname, O_RDONLY);
389 error (0, errno, gettext ("cannot open '%s'"), fname);
393 /* Now get the ELF descriptor. */
394 Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
397 if (elf_kind (elf) == ELF_K_ELF)
399 int result = handle_elf (elf, more_than_one ? "" : NULL,
402 if (elf_end (elf) != 0)
403 INTERNAL_ERROR (fname);
406 error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
410 else if (elf_kind (elf) == ELF_K_AR)
412 int result = handle_ar (fd, elf, NULL, fname, NULL);
414 if (elf_end (elf) != 0)
415 INTERNAL_ERROR (fname);
418 error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
423 /* We cannot handle this type. Close the descriptor anyway. */
424 if (elf_end (elf) != 0)
425 INTERNAL_ERROR (fname);
428 error (0, 0, gettext ("%s: File format not recognized"), fname);
435 handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
438 size_t fname_len = strlen (fname) + 1;
439 size_t prefix_len = prefix != NULL ? strlen (prefix) : 0;
440 char new_prefix[prefix_len + fname_len + 2];
441 size_t suffix_len = suffix != NULL ? strlen (suffix) : 0;
442 char new_suffix[suffix_len + 2];
444 Elf_Cmd cmd = ELF_C_READ_MMAP;
447 char *cp = new_prefix;
449 cp = stpcpy (cp, prefix);
450 cp = stpcpy (cp, fname);
455 cp = stpcpy (cp, suffix);
458 /* First print the archive index if this is wanted. */
461 Elf_Arsym *arsym = elf_getarsym (elf, NULL);
465 Elf_Arhdr *arhdr = NULL;
466 size_t arhdr_off = 0; /* Note: 0 is no valid offset. */
468 fputs_unlocked (gettext("\nArchive index:\n"), stdout);
470 while (arsym->as_off != 0)
472 if (arhdr_off != arsym->as_off
473 && (elf_rand (elf, arsym->as_off) != arsym->as_off
474 || (subelf = elf_begin (fd, cmd, elf)) == NULL
475 || (arhdr = elf_getarhdr (subelf)) == NULL))
477 error (0, 0, gettext ("invalid offset %zu for symbol %s"),
478 arsym->as_off, arsym->as_name);
482 printf (gettext ("%s in %s\n"), arsym->as_name, arhdr->ar_name);
487 if (elf_rand (elf, SARMAG) != SARMAG)
490 gettext ("cannot reset archive offset to beginning"));
496 /* Process all the files contained in the archive. */
497 while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
499 /* The the header for this element. */
500 Elf_Arhdr *arhdr = elf_getarhdr (subelf);
502 /* Skip over the index entries. */
503 if (strcmp (arhdr->ar_name, "/") != 0
504 && strcmp (arhdr->ar_name, "//") != 0)
506 if (elf_kind (subelf) == ELF_K_ELF)
507 result |= handle_elf (subelf, new_prefix, arhdr->ar_name,
509 else if (elf_kind (subelf) == ELF_K_AR)
510 result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name,
514 error (0, 0, gettext ("%s%s%s: file format not recognized"),
515 new_prefix, arhdr->ar_name, new_suffix);
520 /* Get next archive element. */
521 cmd = elf_next (subelf);
522 if (elf_end (subelf) != 0)
523 INTERNAL_ERROR (fname);
530 /* Mapping of radix and binary class to length. */
531 static const int length_map[2][3] =
536 [radix_decimal] = 10,
542 [radix_decimal] = 20,
549 global_compare (const void *p1, const void *p2)
551 const Dwarf_Global *g1 = (const Dwarf_Global *) p1;
552 const Dwarf_Global *g2 = (const Dwarf_Global *) p2;
554 return strcmp (g1->name, g2->name);
558 static void *global_root;
562 get_global (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
563 void *arg __attribute__ ((unused)))
565 tsearch (memcpy (xmalloc (sizeof (Dwarf_Global)), global,
566 sizeof (Dwarf_Global)),
567 &global_root, global_compare);
584 local_compare (const void *p1, const void *p2)
586 struct local_name *g1 = (struct local_name *) p1;
587 struct local_name *g2 = (struct local_name *) p2;
590 result = strcmp (g1->name, g2->name);
593 if (g1->lowpc <= g2->lowpc && g1->highpc >= g2->highpc)
595 /* g2 is contained in g1. Update the data. */
596 g2->lowpc = g1->lowpc;
597 g2->highpc = g1->highpc;
600 else if (g2->lowpc <= g1->lowpc && g2->highpc >= g1->highpc)
602 /* g1 is contained in g2. Update the data. */
603 g1->lowpc = g2->lowpc;
604 g1->highpc = g2->highpc;
608 result = g1->lowpc < g2->lowpc ? -1 : 1;
616 get_var_range (Dwarf_Die *die, Dwarf_Word *lowpc, Dwarf_Word *highpc)
618 Dwarf_Attribute locattr_mem;
619 Dwarf_Attribute *locattr = dwarf_attr (die, DW_AT_location, &locattr_mem);
625 if (dwarf_getlocation (locattr, &loc, &nloc) != 0)
628 /* Interpret the location expressions. */
629 // XXX For now just the simple one:
630 if (nloc == 1 && loc[0].atom == DW_OP_addr)
632 *lowpc = *highpc = loc[0].number;
641 static void *local_root;
645 get_local_names (Dwarf *dbg)
647 Dwarf_Off offset = 0;
648 Dwarf_Off old_offset;
651 while (dwarf_nextcu (dbg, old_offset = offset, &offset, &hsize, NULL, NULL,
655 Dwarf_Die *cudie = dwarf_offdie (dbg, old_offset + hsize, &cudie_mem);
657 /* If we cannot get the CU DIE there is no need to go on with
661 /* This better be a CU DIE. */
662 if (dwarf_tag (cudie) != DW_TAG_compile_unit)
665 /* Get the line information. */
668 if (dwarf_getsrcfiles (cudie, &files, &nfiles) != 0)
672 Dwarf_Die *die = &die_mem;
673 if (dwarf_child (cudie, die) == 0)
674 /* Iterate over all immediate children of the CU DIE. */
677 int tag = dwarf_tag (die);
678 if (tag != DW_TAG_subprogram && tag != DW_TAG_variable)
681 /* We are interested in five attributes: name, decl_file,
682 decl_line, low_pc, and high_pc. */
683 Dwarf_Attribute attr_mem;
684 Dwarf_Attribute *attr = dwarf_attr (die, DW_AT_name, &attr_mem);
685 const char *name = dwarf_formstring (attr);
690 attr = dwarf_attr (die, DW_AT_decl_file, &attr_mem);
691 if (dwarf_formudata (attr, &fileidx) != 0 || fileidx >= nfiles)
695 attr = dwarf_attr (die, DW_AT_decl_line, &attr_mem);
696 if (dwarf_formudata (attr, &lineno) != 0 || lineno == 0)
701 if (tag == DW_TAG_subprogram)
703 if (dwarf_lowpc (die, &lowpc) != 0
704 || dwarf_highpc (die, &highpc) != 0)
709 if (get_var_range (die, &lowpc, &highpc) != 0)
713 /* We have all the information. Create a record. */
714 struct local_name *newp
715 = (struct local_name *) xmalloc (sizeof (*newp));
717 newp->file = dwarf_filesrc (files, fileidx, NULL, NULL);
718 newp->lineno = lineno;
720 newp->highpc = highpc;
722 /* Since we cannot deallocate individual memory we do not test
723 for duplicates in the tree. This should not happen anyway. */
724 if (tsearch (newp, &local_root, local_compare) == NULL)
725 error (EXIT_FAILURE, errno,
726 gettext ("cannot create search tree"));
728 while (dwarf_siblingof (die, die) == 0);
732 /* Do elf_strptr, but return a backup string and never NULL. */
734 sym_name (Elf *elf, GElf_Word strndx, GElf_Word st_name, char buf[], size_t n)
736 const char *symstr = elf_strptr (elf, strndx, st_name);
739 snprintf (buf, n, "[invalid st_name %#" PRIx32 "]", st_name);
745 /* Show symbols in SysV format. */
747 show_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname,
748 GElf_SymX *syms, size_t nsyms, int longest_name,
752 if (elf_getshdrnum (ebl->elf, &shnum) < 0)
753 INTERNAL_ERROR (fullname);
755 bool scnnames_malloced = shnum * sizeof (const char *) > 128 * 1024;
756 const char **scnnames;
757 if (scnnames_malloced)
758 scnnames = (const char **) xmalloc (sizeof (const char *) * shnum);
760 scnnames = (const char **) alloca (sizeof (const char *) * shnum);
761 /* Get the section header string table index. */
763 if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
764 error (EXIT_FAILURE, 0,
765 gettext ("cannot get section header string table index"));
767 /* Cache the section names. */
770 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
774 assert (elf_ndxscn (scn) == cnt++);
776 char *name = elf_strptr (ebl->elf, shstrndx,
777 gelf_getshdr (scn, &shdr_mem)->sh_name);
778 if (unlikely (name == NULL))
780 name = alloca (sizeof "[invalid sh_name 0x12345678]");
781 snprintf (name, sizeof name, "[invalid sh_name %#" PRIx32 "]",
782 gelf_getshdr (scn, &shdr_mem)->sh_name);
784 scnnames[elf_ndxscn (scn)] = name;
787 int digits = length_map[gelf_getclass (ebl->elf) - 1][radix];
789 /* We always print this prolog. */
790 printf (gettext ("\n\nSymbols from %s:\n\n"), fullname);
792 /* The header line. */
793 printf (gettext ("%*s%-*s %-*s Class Type %-*s %*s Section\n\n"),
794 print_file_name ? (int) strlen (fullname) + 1: 0, "",
795 longest_name, sgettext ("sysv|Name"),
796 /* TRANS: the "sysv|" parts makes the string unique. */
797 digits, sgettext ("sysv|Value"),
798 /* TRANS: the "sysv|" parts makes the string unique. */
799 digits, sgettext ("sysv|Size"),
800 /* TRANS: the "sysv|" parts makes the string unique. */
801 longest_where, sgettext ("sysv|Line"));
803 /* Which format string to use (different radix for numbers). */
804 const char *number_fmtstr;
805 if (radix == radix_hex)
806 number_fmtstr = "%0*" PRIx64;
807 else if (radix == radix_decimal)
808 number_fmtstr = "%0*" PRId64;
810 number_fmtstr = "%0*" PRIo64;
813 size_t demangle_buffer_len = 0;
814 char *demangle_buffer = NULL;
817 /* Iterate over all symbols. */
818 for (cnt = 1; cnt < nsyms; ++cnt)
820 /* In this format SECTION entries are not printed. */
821 if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_SECTION)
825 const char *symstr = sym_name (ebl->elf, strndx, syms[cnt].sym.st_name,
826 symstrbuf, sizeof symstrbuf);
829 /* Demangle if necessary. */
833 char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
834 &demangle_buffer_len, &status);
843 char secnamebuf[1024];
844 char addressbuf[(64 + 2) / 3 + 1];
845 char sizebuf[(64 + 2) / 3 + 1];
847 /* If we have to precede the line with the file name. */
850 fputs_unlocked (fullname, stdout);
851 putchar_unlocked (':');
854 /* Covert the address. */
855 if (syms[cnt].sym.st_shndx == SHN_UNDEF)
856 addressbuf[0] = sizebuf[0] = '\0';
859 snprintf (addressbuf, sizeof (addressbuf), number_fmtstr,
860 digits, syms[cnt].sym.st_value);
861 snprintf (sizebuf, sizeof (sizebuf), number_fmtstr,
862 digits, syms[cnt].sym.st_size);
865 /* Print the actual string. */
866 printf ("%-*s|%s|%-6s|%-8s|%s|%*s|%s\n",
867 longest_name, symstr, addressbuf,
868 ebl_symbol_binding_name (ebl,
869 GELF_ST_BIND (syms[cnt].sym.st_info),
870 symbindbuf, sizeof (symbindbuf)),
871 ebl_symbol_type_name (ebl, GELF_ST_TYPE (syms[cnt].sym.st_info),
872 symtypebuf, sizeof (symtypebuf)),
873 sizebuf, longest_where, syms[cnt].where,
874 ebl_section_name (ebl, syms[cnt].sym.st_shndx, syms[cnt].xndx,
875 secnamebuf, sizeof (secnamebuf), scnnames,
880 free (demangle_buffer);
883 if (scnnames_malloced)
889 class_type_char (Elf *elf, const GElf_Ehdr *ehdr, GElf_Sym *sym)
891 int local_p = GELF_ST_BIND (sym->st_info) == STB_LOCAL;
893 /* XXX Add support for architecture specific types and classes. */
894 if (sym->st_shndx == SHN_ABS)
895 return local_p ? 'a' : 'A';
897 if (sym->st_shndx == SHN_UNDEF)
898 /* Undefined symbols must be global. */
901 char result = "NDTSFBD "[GELF_ST_TYPE (sym->st_info)];
905 /* Special handling: unique data symbols. */
906 if (ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX
907 && GELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
912 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, sym->st_shndx),
916 if ((shdr->sh_flags & SHF_WRITE) == 0)
918 else if (shdr->sh_type == SHT_NOBITS)
924 return local_p ? tolower (result) : result;
929 show_symbols_bsd (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
930 const char *prefix, const char *fname, const char *fullname,
931 GElf_SymX *syms, size_t nsyms)
933 int digits = length_map[gelf_getclass (elf) - 1][radix];
935 if (prefix != NULL && ! print_file_name)
936 printf ("\n%s:\n", fname);
938 static const char *const fmtstrs[] =
940 [radix_hex] = "%8$s%2$0*1$" PRIx64 "%10$s %9$s%3$c%4$s %5$s",
941 [radix_decimal] = "%8$s%*" PRId64 "%10$s %9$s%3$c%4$s %5$s",
942 [radix_octal] = "%8$s%2$0*1$" PRIo64 "%10$s %9$s%3$c%4$s %5$s"
944 static const char *const sfmtstrs[] =
946 [radix_hex] = "%8$s%2$0*1$" PRIx64 "%10$s %7$0*6$" PRIx64 " %9$s%3$c%4$s %5$s",
947 [radix_decimal] = "%8$s%2$*1$" PRId64 "%10$s %7$*6$" PRId64 " %9$s%3$c%4$s %5$s",
948 [radix_octal] = "%8$s%2$0*1$" PRIo64 "%10$s %7$0*6$" PRIo64 " %9$s%3$c%4$s %5$s"
952 size_t demangle_buffer_len = 0;
953 char *demangle_buffer = NULL;
956 /* Iterate over all symbols. */
957 for (size_t cnt = 0; cnt < nsyms; ++cnt)
960 const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
961 symstrbuf, sizeof symstrbuf);
963 /* Printing entries with a zero-length name makes the output
964 not very well parseable. Since these entries don't carry
965 much information we leave them out. */
966 if (symstr[0] == '\0')
969 /* We do not print the entries for files. */
970 if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_FILE)
974 /* Demangle if necessary. */
978 char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
979 &demangle_buffer_len, &status);
986 /* If we have to precede the line with the file name. */
989 fputs_unlocked (fullname, stdout);
990 putchar_unlocked (':');
993 bool is_tls = GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS;
994 bool is_weak = GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK;
995 const char *marker = (mark_special
996 ? (is_tls ? "@" : (is_weak ? "*" : " ")) : "");
998 if (syms[cnt].sym.st_shndx == SHN_UNDEF)
1000 const char *color = "";
1004 color = color_undef_tls;
1006 color = color_undef_weak;
1008 color = color_undef;
1011 printf ("%*s %sU%s %s", digits, "", color, marker, symstr);
1015 const char *color = "";
1023 color = color_symbol;
1026 printf (print_size && syms[cnt].sym.st_size != 0
1027 ? sfmtstrs[radix] : fmtstrs[radix],
1028 digits, syms[cnt].sym.st_value,
1029 class_type_char (elf, ehdr, &syms[cnt].sym), marker,
1031 digits, (uint64_t) syms[cnt].sym.st_size,
1032 color_mode ? color_address : "",
1034 color_mode ? color_off : "");
1038 fputs_unlocked (color_off, stdout);
1039 putchar_unlocked ('\n');
1043 free (demangle_buffer);
1049 show_symbols_posix (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
1050 const char *prefix, const char *fullname, GElf_SymX *syms,
1053 if (prefix != NULL && ! print_file_name)
1054 printf ("%s:\n", fullname);
1057 if (radix == radix_hex)
1058 fmtstr = "%s %c%s %0*" PRIx64 " %0*" PRIx64 "\n";
1059 else if (radix == radix_decimal)
1060 fmtstr = "%s %c%s %*" PRId64 " %*" PRId64 "\n";
1062 fmtstr = "%s %c%s %0*" PRIo64 " %0*" PRIo64 "\n";
1064 int digits = length_map[gelf_getclass (elf) - 1][radix];
1067 size_t demangle_buffer_len = 0;
1068 char *demangle_buffer = NULL;
1071 /* Iterate over all symbols. */
1072 for (size_t cnt = 0; cnt < nsyms; ++cnt)
1075 const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
1076 symstrbuf, sizeof symstrbuf);
1078 /* Printing entries with a zero-length name makes the output
1079 not very well parseable. Since these entries don't carry
1080 much information we leave them out. */
1081 if (symstr[0] == '\0')
1085 /* Demangle if necessary. */
1089 char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
1090 &demangle_buffer_len, &status);
1097 /* If we have to precede the line with the file name. */
1098 if (print_file_name)
1100 fputs_unlocked (fullname, stdout);
1101 putchar_unlocked (':');
1102 putchar_unlocked (' ');
1107 class_type_char (elf, ehdr, &syms[cnt].sym),
1109 ? (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS
1111 : (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK
1114 digits, syms[cnt].sym.st_value,
1115 digits, syms[cnt].sym.st_size);
1119 free (demangle_buffer);
1124 /* Maximum size of memory we allocate on the stack. */
1125 #define MAX_STACK_ALLOC 65536
1128 sort_by_address (const void *p1, const void *p2)
1130 GElf_SymX *s1 = (GElf_SymX *) p1;
1131 GElf_SymX *s2 = (GElf_SymX *) p2;
1133 int result = (s1->sym.st_value < s2->sym.st_value
1134 ? -1 : (s1->sym.st_value == s2->sym.st_value ? 0 : 1));
1136 return reverse_sort ? -result : result;
1139 static Elf_Data *sort_by_name_strtab;
1142 sort_by_name (const void *p1, const void *p2)
1144 GElf_SymX *s1 = (GElf_SymX *) p1;
1145 GElf_SymX *s2 = (GElf_SymX *) p2;
1147 const char *n1 = sort_by_name_strtab->d_buf + s1->sym.st_name;
1148 const char *n2 = sort_by_name_strtab->d_buf + s2->sym.st_name;
1150 int result = strcmp (n1, n2);
1152 return reverse_sort ? -result : result;
1156 show_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn,
1157 GElf_Shdr *shdr, const char *prefix, const char *fname,
1158 const char *fullname)
1160 /* Get the section header string table index. */
1162 if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
1163 error (EXIT_FAILURE, 0,
1164 gettext ("cannot get section header string table index"));
1166 /* The section is that large. */
1167 size_t size = shdr->sh_size;
1168 /* One entry is this large. */
1169 size_t entsize = shdr->sh_entsize;
1171 /* Consistency checks. */
1172 if (entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, ehdr->e_version))
1174 gettext ("%s: entry size in section `%s' is not what we expect"),
1175 fullname, elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1176 else if (size % entsize != 0)
1178 gettext ("%s: size of section `%s' is not multiple of entry size"),
1179 fullname, elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1181 /* Compute number of entries. Handle buggy entsize values. */
1182 size_t nentries = size / (entsize ?: 1);
1185 #define obstack_chunk_alloc xmalloc
1186 #define obstack_chunk_free free
1187 struct obstack whereob;
1188 obstack_init (&whereob);
1190 /* Get a DWARF debugging descriptor. It's no problem if this isn't
1191 possible. We just won't print any line number information. */
1193 if (format == format_sysv)
1195 dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
1198 (void) dwarf_getpubnames (dbg, get_global, NULL, 0);
1200 get_local_names (dbg);
1204 /* Allocate the memory.
1206 XXX We can use a dirty trick here. Since GElf_Sym == Elf64_Sym we
1207 can use the data memory instead of copying again if what we read
1208 is a 64 bit file. */
1210 if (nentries * sizeof (GElf_SymX) < MAX_STACK_ALLOC)
1211 sym_mem = (GElf_SymX *) alloca (nentries * sizeof (GElf_SymX));
1213 sym_mem = (GElf_SymX *) xmalloc (nentries * sizeof (GElf_SymX));
1215 /* Get the data of the section. */
1216 Elf_Data *data = elf_getdata (scn, NULL);
1217 Elf_Data *xndxdata = elf_getdata (xndxscn, NULL);
1218 if (data == NULL || (xndxscn != NULL && xndxdata == NULL))
1219 INTERNAL_ERROR (fullname);
1221 /* Iterate over all symbols. */
1223 size_t demangle_buffer_len = 0;
1224 char *demangle_buffer = NULL;
1226 int longest_name = 4;
1227 int longest_where = 4;
1228 size_t nentries_used = 0;
1229 for (size_t cnt = 0; cnt < nentries; ++cnt)
1231 GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, cnt,
1232 &sym_mem[nentries_used].sym,
1233 &sym_mem[nentries_used].xndx);
1235 INTERNAL_ERROR (fullname);
1237 /* Filter out administrative symbols without a name and those
1238 deselected by the user with command line options. */
1239 if ((hide_undefined && sym->st_shndx == SHN_UNDEF)
1240 || (hide_defined && sym->st_shndx != SHN_UNDEF)
1241 || (hide_local && GELF_ST_BIND (sym->st_info) == STB_LOCAL))
1244 sym_mem[nentries_used].where = "";
1245 if (format == format_sysv)
1247 const char *symstr = elf_strptr (ebl->elf, shdr->sh_link,
1253 /* Demangle if necessary. */
1257 char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
1258 &demangle_buffer_len, &status);
1265 longest_name = MAX ((size_t) longest_name, strlen (symstr));
1267 if (sym->st_shndx != SHN_UNDEF
1268 && GELF_ST_BIND (sym->st_info) != STB_LOCAL
1269 && global_root != NULL)
1271 Dwarf_Global fake = { .name = symstr };
1272 Dwarf_Global **found = tfind (&fake, &global_root,
1277 Dwarf_Die *die = dwarf_offdie (dbg, (*found)->die_offset,
1280 Dwarf_Die cudie_mem;
1281 Dwarf_Die *cudie = NULL;
1286 && dwarf_lowpc (die, &lowpc) == 0
1287 && lowpc <= sym->st_value
1288 && dwarf_highpc (die, &highpc) == 0
1289 && highpc > sym->st_value)
1290 cudie = dwarf_offdie (dbg, (*found)->cu_offset,
1294 Dwarf_Line *line = dwarf_getsrc_die (cudie,
1298 /* We found the line. */
1300 (void) dwarf_lineno (line, &lineno);
1302 n = obstack_printf (&whereob, "%s:%d%c",
1303 basename (dwarf_linesrc (line,
1307 sym_mem[nentries_used].where
1308 = obstack_finish (&whereob);
1310 /* The return value of obstack_print included the
1311 NUL byte, so subtract one. */
1312 if (--n > (int) longest_where)
1313 longest_where = (size_t) n;
1319 /* Try to find the symbol among the local symbols. */
1320 if (sym_mem[nentries_used].where[0] == '\0')
1322 struct local_name fake =
1325 .lowpc = sym->st_value,
1326 .highpc = sym->st_value,
1328 struct local_name **found = tfind (&fake, &local_root,
1332 /* We found the line. */
1333 int n = obstack_printf (&whereob, "%s:%" PRIu64 "%c",
1334 basename ((*found)->file),
1337 sym_mem[nentries_used].where = obstack_finish (&whereob);
1339 /* The return value of obstack_print included the
1340 NUL byte, so subtract one. */
1341 if (--n > (int) longest_where)
1342 longest_where = (size_t) n;
1347 /* We use this entry. */
1351 free (demangle_buffer);
1353 /* Now we know the exact number. */
1354 nentries = nentries_used;
1356 /* Sort the entries according to the users wishes. */
1357 if (sort == sort_name)
1359 sort_by_name_strtab = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link),
1361 qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_name);
1363 else if (sort == sort_numeric)
1364 qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_address);
1366 /* Finally print according to the users selection. */
1370 show_symbols_sysv (ebl, shdr->sh_link, fullname, sym_mem, nentries,
1371 longest_name, longest_where);
1375 show_symbols_bsd (ebl->elf, ehdr, shdr->sh_link, prefix, fname, fullname,
1381 assert (format == format_posix);
1382 show_symbols_posix (ebl->elf, ehdr, shdr->sh_link, prefix, fullname,
1387 /* Free all memory. */
1388 if (nentries * sizeof (GElf_Sym) >= MAX_STACK_ALLOC)
1391 obstack_free (&whereob, NULL);
1395 tdestroy (global_root, free);
1398 tdestroy (local_root, free);
1401 (void) dwarf_end (dbg);
1407 handle_elf (Elf *elf, const char *prefix, const char *fname,
1410 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
1411 size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
1412 size_t fname_len = strlen (fname) + 1;
1413 char fullname[prefix_len + 1 + fname_len + suffix_len];
1414 char *cp = fullname;
1415 Elf_Scn *scn = NULL;
1422 /* Get the backend for this object file type. */
1423 ebl = ebl_openbackend (elf);
1425 /* We need the ELF header in a few places. */
1426 ehdr = gelf_getehdr (elf, &ehdr_mem);
1428 INTERNAL_ERROR (fullname);
1430 /* If we are asked to print the dynamic symbol table and this is
1431 executable or dynamic executable, fail. */
1432 if (symsec_type == SHT_DYNSYM
1433 && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1435 /* XXX Add machine specific object file types. */
1436 error (0, 0, gettext ("%s%s%s%s: Invalid operation"),
1437 prefix ?: "", prefix ? "(" : "", fname, prefix ? ")" : "");
1442 /* Create the full name of the file. */
1444 cp = mempcpy (cp, prefix, prefix_len);
1445 cp = mempcpy (cp, fname, fname_len);
1447 memcpy (cp - 1, suffix, suffix_len + 1);
1449 /* Find the symbol table.
1451 XXX Can there be more than one? Do we print all? Currently we do. */
1452 while ((scn = elf_nextscn (elf, scn)) != NULL)
1455 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1458 INTERNAL_ERROR (fullname);
1460 if (shdr->sh_type == symsec_type)
1462 Elf_Scn *xndxscn = NULL;
1464 /* We have a symbol table. First make sure we remember this. */
1467 /* Look for an extended section index table for this section. */
1468 if (symsec_type == SHT_SYMTAB)
1470 size_t scnndx = elf_ndxscn (scn);
1472 while ((xndxscn = elf_nextscn (elf, xndxscn)) != NULL)
1474 GElf_Shdr xndxshdr_mem;
1475 GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
1477 if (xndxshdr == NULL)
1478 INTERNAL_ERROR (fullname);
1480 if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
1481 && xndxshdr->sh_link == scnndx)
1486 show_symbols (ebl, ehdr, scn, xndxscn, shdr, prefix, fname,
1493 error (0, 0, gettext ("%s%s%s: no symbols"),
1494 prefix ?: "", prefix ? ":" : "", fname);
1499 /* Close the ELF backend library descriptor. */
1500 ebl_closebackend (ebl);
1506 #include "debugpred.h"