1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Print symbol information from ELF file in human-readable form.
2587c4b3e94c6ef877137d067d5d0f574f69b1391Mark Wielaard   Copyright (C) 2000-2008, 2009, 2011, 2012, 2014, 2015 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
7de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of the GNU General Public License as published by
8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the Free Software Foundation; either version 3 of the License, or
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   (at your option) any later version.
10b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
12361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   GNU General Public License for more details.
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received a copy of the GNU General Public License
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
19b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#ifdef HAVE_CONFIG_H
20b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper# include <config.h>
21b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
22b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
23b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <ar.h>
24b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <argp.h>
25b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <assert.h>
26b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <ctype.h>
27b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <dwarf.h>
28b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <errno.h>
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <error.h>
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <fcntl.h>
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <gelf.h>
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <inttypes.h>
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <libdw.h>
34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <libintl.h>
35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <locale.h>
36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <obstack.h>
37b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <search.h>
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdbool.h>
39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdio.h>
40b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdio_ext.h>
41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdlib.h>
42b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <string.h>
43b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <unistd.h>
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <sys/param.h>
45b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
46b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <system.h>
47b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "../libebl/libeblP.h"
4870cd907e38757283f3696465771f723a342cc3d1Mark Wielaard#include "../libdwfl/libdwflP.h"
49b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
50b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
51b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Name and version of program.  */
52b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void print_version (FILE *stream, struct argp_state *state);
53fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich DrepperARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
54b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Bug report address.  */
56fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich DrepperARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
57b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
58b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
59b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Values for the parameters which have no short form.  */
602356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper#define OPT_DEFINED		0x100
612356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper#define OPT_MARK_SPECIAL	0x101
62b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
63b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Definitions of arguments for argp functions.  */
64b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const struct argp_option options[] =
65b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
66b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
67b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "debug-syms", 'a', NULL, 0, N_("Display debugger-only symbols"), 0 },
68b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "defined-only", OPT_DEFINED, NULL, 0, N_("Display only defined symbols"),
69b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    0 },
70b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "dynamic", 'D', NULL, 0,
71b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Display dynamic symbols instead of normal symbols"), 0 },
72b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "extern-only", 'g', NULL, 0, N_("Display only external symbols"), 0 },
73b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "undefined-only", 'u', NULL, 0, N_("Display only undefined symbols"), 0 },
74b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "print-armap", 's', NULL, 0,
75b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Include index for symbols from archive members"), 0 },
76b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
77b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, N_("Output format:"), 0 },
78b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "print-file-name", 'A', NULL, 0,
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Print name of the input file before every symbol"), 0 },
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 'o', NULL, OPTION_HIDDEN, "Same as -A", 0 },
81b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "format", 'f', "FORMAT", 0,
82b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Use the output format FORMAT.  FORMAT can be `bsd', `sysv' or `posix'.  The default is `sysv'"),
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    0 },
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 'B', NULL, 0, N_("Same as --format=bsd"), 0 },
85b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "portability", 'P', NULL, 0, N_("Same as --format=posix"), 0 },
86b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "radix", 't', "RADIX", 0, N_("Use RADIX for printing symbol values"), 0 },
872356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper  { "mark-special", OPT_MARK_SPECIAL, NULL, 0, N_("Mark special symbols"), 0 },
882356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper  { "mark-weak", OPT_MARK_SPECIAL, NULL, OPTION_HIDDEN, "", 0 },
89b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "print-size", 'S', NULL, 0, N_("Print size of defined symbols"), 0 },
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, N_("Output options:"), 0 },
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "numeric-sort", 'n', NULL, 0, N_("Sort symbols numerically by address"),
93b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    0 },
94b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "no-sort", 'p', NULL, 0, N_("Do not sort the symbols"), 0 },
95b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "reverse-sort", 'r', NULL, 0, N_("Reverse the sense of the sort"), 0 },
96b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
97b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper  { "demangle", 'C', NULL, 0,
98b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper    N_("Decode low-level symbol names into source code names"), 0 },
99b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, NULL, 0 }
102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Short description of program.  */
105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char doc[] = N_("List symbols from FILEs (a.out by default).");
106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Strings for arguments in help texts.  */
108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char args_doc[] = N_("[FILE...]");
109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Prototype for option handler.  */
111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
113c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper/* Parser children.  */
114c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepperstatic struct argp_child argp_children[] =
115c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper  {
116c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper    { &color_argp, 0, N_("Output formatting"), 2 },
117c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper    { NULL, 0, NULL, 0}
118c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper  };
119c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper
120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Data structure to communicate with argp functions.  */
121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic struct argp argp =
122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
123c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper  options, parse_opt, args_doc, doc, argp_children, NULL, NULL
124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
127b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Print symbols in file named FNAME.  */
128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int process_file (const char *fname, bool more_than_one);
129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Handle content of archive.  */
131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      const char *suffix);
133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Handle ELF file.  */
13570cd907e38757283f3696465771f723a342cc3d1Mark Wielaardstatic int handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       const char *suffix);
137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define INTERNAL_ERROR(fname) \
140587c4b3e94c6ef877137d067d5d0f574f69b1391Mark Wielaard  error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s): %s"),      \
141587c4b3e94c6ef877137d067d5d0f574f69b1391Mark Wielaard	 fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1))
142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Internal representation of symbols.  */
145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppertypedef struct GElf_SymX
146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Sym sym;
148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf32_Word xndx;
149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *where;
150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} GElf_SymX;
151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* User-selectable options.  */
154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* The selected output format.  */
156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic enum
157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  format_sysv = 0,
159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  format_bsd,
160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  format_posix
161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} format;
162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Print defined, undefined, or both?  */
164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool hide_undefined;
165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool hide_defined;
166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Print local symbols also?  */
168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool hide_local;
169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Nonzero if full filename should precede every symbol.  */
171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool print_file_name;
172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* If true print size of defined symbols in BSD format.  */
174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool print_size;
175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* If true print archive index.  */
177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool print_armap;
178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* If true reverse sorting.  */
180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool reverse_sort;
181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
182b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
183b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper/* If true demangle symbols.  */
184b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepperstatic bool demangle;
185b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
186b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Type of the section we are printing.  */
188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic GElf_Word symsec_type = SHT_SYMTAB;
189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Sorting selection.  */
191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic enum
192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  sort_name = 0,
194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  sort_numeric,
195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  sort_nosort
196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} sort;
197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Radix for printed numbers.  */
199b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic enum
200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  radix_hex = 0,
202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  radix_decimal,
203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  radix_octal
204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} radix;
205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2062356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper/* If nonzero mark special symbols:
2072356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper   - weak symbols are distinguished from global symbols by adding
2082356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper     a `*' after the identifying letter for the symbol class and type.
2092356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper   - TLS symbols are distinguished from normal symbols by adding
2102356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper     a '@' after the identifying letter for the symbol class and type.  */
2112356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepperstatic bool mark_special;
212b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
213b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
215b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermain (int argc, char *argv[])
216b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
217b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int remaining;
218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int result = 0;
219b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We use no threads here which can interfere with handling a stream.  */
221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
222b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Set locale.  */
226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (void) setlocale (LC_ALL, "");
227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Make sure the message catalog can be found.  */
229b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Initialize the message catalog.  */
232b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  (void) textdomain (PACKAGE_TARNAME);
233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Parse and process arguments.  */
235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Tell the library which version we are expecting.  */
238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (void) elf_version (EV_CURRENT);
239b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (remaining == argc)
241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* The user didn't specify a name so we use a.out.  */
242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    result = process_file ("a.out", false);
243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Process all the remaining files.  */
246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const bool more_than_one = remaining + 1 < argc;
247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      do
249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	result |= process_file (argv[remaining], more_than_one);
250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      while (++remaining < argc);
251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Print the version information.  */
258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
261b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  fprintf (stream, "nm (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("\
263b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperCopyright (C) %s Red Hat, Inc.\n\
264b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperThis is free software; see the source for copying conditions.  There is NO\n\
265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
2663a64a3087f53ab860c7de04da0e53dabef459520Ulrich Drepper"), "2012");
267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Handle program arguments.  */
272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t
273b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperparse_opt (int key, char *arg,
274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   struct argp_state *state __attribute__ ((unused)))
275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
276b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (key)
277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'a':
279b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* XXX */
280b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
282b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
283b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper    case 'C':
284b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper      demangle = true;
285b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper      break;
286b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
287b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'f':
289b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (strcmp (arg, "bsd") == 0)
290b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	format = format_bsd;
291b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (strcmp (arg, "posix") == 0)
292b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	format = format_posix;
293b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Be bug compatible.  The BFD implementation also defaulted to
295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   using the SysV format if nothing else matches.  */
296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	format = format_sysv;
297b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
298b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
299b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'g':
300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      hide_local = true;
301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'n':
304b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      sort = sort_numeric;
305b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
306b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
307b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'p':
308b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      sort = sort_nosort;
309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 't':
312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (strcmp (arg, "10") == 0 || strcmp (arg, "d") == 0)
313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	radix = radix_decimal;
314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (strcmp (arg, "8") == 0 || strcmp (arg, "o") == 0)
315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	radix = radix_octal;
316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	radix = radix_hex;
318b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'u':
321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      hide_undefined = false;
322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      hide_defined = true;
323b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'A':
326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'o':
327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      print_file_name = true;
328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'B':
331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      format = format_bsd;
332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'D':
335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      symsec_type = SHT_DYNSYM;
336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'P':
339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      format = format_posix;
340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
341b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case OPT_DEFINED:
343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      hide_undefined = true;
344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      hide_defined = false;
345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3472356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper    case OPT_MARK_SPECIAL:
3482356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper      mark_special = true;
349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'S':
352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      print_size = true;
353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 's':
356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      print_armap = true;
357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'r':
360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      reverse_sort = true;
361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return ARGP_ERR_UNKNOWN;
365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Open the file and determine the type.  */
371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprocess_file (const char *fname, bool more_than_one)
373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Open the file.  */
375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int fd = open (fname, O_RDONLY);
376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (fd == -1)
377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, errno, gettext ("cannot open '%s'"), fname);
379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return 1;
380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now get the ELF descriptor.  */
383b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf != NULL)
385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf_kind (elf) == ELF_K_ELF)
387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
38870cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	  int result = handle_elf (fd, elf, more_than_one ? "" : NULL,
389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   fname, NULL);
390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (elf_end (elf) != 0)
392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    INTERNAL_ERROR (fname);
393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (close (fd) != 0)
395d112ef86686e4f47aad5b30ee38b4618a2bea611Ulrich Drepper	    error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  return result;
398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (elf_kind (elf) == ELF_K_AR)
400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  int result = handle_ar (fd, elf, NULL, fname, NULL);
402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (elf_end (elf) != 0)
404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    INTERNAL_ERROR (fname);
405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (close (fd) != 0)
407d112ef86686e4f47aad5b30ee38b4618a2bea611Ulrich Drepper	    error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  return result;
410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We cannot handle this type.  Close the descriptor anyway.  */
413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf_end (elf) != 0)
414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	INTERNAL_ERROR (fname);
415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  error (0, 0, gettext ("%s: File format not recognized"), fname);
418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 1;
420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperhandle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   const char *suffix)
426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t fname_len = strlen (fname) + 1;
428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t prefix_len = prefix != NULL ? strlen (prefix) : 0;
429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char new_prefix[prefix_len + fname_len + 2];
430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t suffix_len = suffix != NULL ? strlen (suffix) : 0;
431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char new_suffix[suffix_len + 2];
432b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *subelf;
433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Cmd cmd = ELF_C_READ_MMAP;
434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int result = 0;
435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *cp = new_prefix;
437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (prefix != NULL)
438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    cp = stpcpy (cp, prefix);
439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  cp = stpcpy (cp, fname);
440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  stpcpy (cp, "[");
441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  cp = new_suffix;
443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (suffix != NULL)
444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    cp = stpcpy (cp, suffix);
445b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  stpcpy (cp, "]");
446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* First print the archive index if this is wanted.  */
448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (print_armap)
449b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
450b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf_Arsym *arsym = elf_getarsym (elf, NULL);
451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (arsym != NULL)
453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  Elf_Arhdr *arhdr = NULL;
455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t arhdr_off = 0;	/* Note: 0 is no valid offset.  */
456b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
457c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	  fputs_unlocked (gettext("\nArchive index:\n"), stdout);
458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
459b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  while (arsym->as_off != 0)
460b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (arhdr_off != arsym->as_off
462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  && (elf_rand (elf, arsym->as_off) != arsym->as_off
463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      || (subelf = elf_begin (fd, cmd, elf)) == NULL
464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      || (arhdr = elf_getarhdr (subelf)) == NULL))
465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  error (0, 0, gettext ("invalid offset %zu for symbol %s"),
467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 arsym->as_off, arsym->as_name);
4680b799ad9822f4866aaf1eb34564681e83bdaf9f1Mark Wielaard		  break;
469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      printf (gettext ("%s in %s\n"), arsym->as_name, arhdr->ar_name);
472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
473b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ++arsym;
474b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
475b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
476b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (elf_rand (elf, SARMAG) != SARMAG)
477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
478b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      error (0, 0,
479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     gettext ("cannot reset archive offset to beginning"));
480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      return 1;
481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
482b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
483b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
485b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Process all the files contained in the archive.  */
486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
487b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* The the header for this element.  */
489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Skip over the index entries.  */
492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (strcmp (arhdr->ar_name, "/") != 0
4938fb260f7137a231caf250dbe4ba64fcebd33b68dMark Wielaard	  && strcmp (arhdr->ar_name, "//") != 0
4948fb260f7137a231caf250dbe4ba64fcebd33b68dMark Wielaard	  && strcmp (arhdr->ar_name, "/SYM64/") != 0)
495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (elf_kind (subelf) == ELF_K_ELF)
49770cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	    result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name,
498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				  new_suffix);
499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (elf_kind (subelf) == ELF_K_AR)
500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name,
501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				 new_suffix);
502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
504b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      error (0, 0, gettext ("%s%s%s: file format not recognized"),
505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     new_prefix, arhdr->ar_name, new_suffix);
506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      result = 1;
507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Get next archive element.  */
511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      cmd = elf_next (subelf);
512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf_end (subelf) != 0)
513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	INTERNAL_ERROR (fname);
514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Mapping of radix and binary class to length.  */
521b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const int length_map[2][3] =
522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  [ELFCLASS32 - 1] =
524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    [radix_hex] = 8,
526b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    [radix_decimal] = 10,
527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    [radix_octal] = 11
528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  },
529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  [ELFCLASS64 - 1] =
530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    [radix_hex] = 16,
532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    [radix_decimal] = 20,
533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    [radix_octal] = 22
534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  }
535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperglobal_compare (const void *p1, const void *p2)
540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const Dwarf_Global *g1 = (const Dwarf_Global *) p1;
542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const Dwarf_Global *g2 = (const Dwarf_Global *) p2;
543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
544b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return strcmp (g1->name, g2->name);
545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void *global_root;
549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperget_global (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    void *arg __attribute__ ((unused)))
554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  tsearch (memcpy (xmalloc (sizeof (Dwarf_Global)), global,
556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   sizeof (Dwarf_Global)),
557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   &global_root, global_compare);
558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return DWARF_CB_OK;
560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstruct local_name
564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const char *name;
566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const char *file;
567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwarf_Word lineno;
568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwarf_Addr lowpc;
569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwarf_Addr highpc;
570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperlocal_compare (const void *p1, const void *p2)
575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct local_name *g1 = (struct local_name *) p1;
577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct local_name *g2 = (struct local_name *) p2;
578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int result;
579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  result = strcmp (g1->name, g2->name);
581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (result == 0)
582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (g1->lowpc <= g2->lowpc && g1->highpc >= g2->highpc)
584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* g2 is contained in g1.  Update the data.  */
586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  g2->lowpc = g1->lowpc;
587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  g2->highpc = g1->highpc;
588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 0;
589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (g2->lowpc <= g1->lowpc && g2->highpc >= g1->highpc)
591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* g1 is contained in g2.  Update the data.  */
593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  g1->lowpc = g2->lowpc;
594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  g1->highpc = g2->highpc;
595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 0;
596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	result = g1->lowpc < g2->lowpc ? -1 : 1;
599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperget_var_range (Dwarf_Die *die, Dwarf_Word *lowpc, Dwarf_Word *highpc)
607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwarf_Attribute locattr_mem;
609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwarf_Attribute *locattr = dwarf_attr (die, DW_AT_location, &locattr_mem);
610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if  (locattr == NULL)
611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return 1;
612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6136724c90d02659f7466b67b357563042e403d154eRoland McGrath  Dwarf_Op *loc;
614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t nloc;
6156724c90d02659f7466b67b357563042e403d154eRoland McGrath  if (dwarf_getlocation (locattr, &loc, &nloc) != 0)
616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return 1;
617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Interpret the location expressions.  */
619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  // XXX For now just the simple one:
620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (nloc == 1 && loc[0].atom == DW_OP_addr)
621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      *lowpc = *highpc = loc[0].number;
623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return 0;
624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 1;
627b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
631b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void *local_root;
632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperget_local_names (Dwarf *dbg)
636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwarf_Off offset = 0;
638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwarf_Off old_offset;
639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t hsize;
640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (dwarf_nextcu (dbg, old_offset = offset, &offset, &hsize, NULL, NULL,
642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       NULL) == 0)
643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Dwarf_Die cudie_mem;
645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Dwarf_Die *cudie = dwarf_offdie (dbg, old_offset + hsize, &cudie_mem);
646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If we cannot get the CU DIE there is no need to go on with
648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 this CU.  */
649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (cudie == NULL)
650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	continue;
651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* This better be a CU DIE.  */
652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dwarf_tag (cudie) != DW_TAG_compile_unit)
653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	continue;
654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Get the line information.  */
656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Dwarf_Files *files;
657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t nfiles;
658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dwarf_getsrcfiles (cudie, &files, &nfiles) != 0)
659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	continue;
660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Dwarf_Die die_mem;
662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Dwarf_Die *die = &die_mem;
663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dwarf_child (cudie, die) == 0)
664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Iterate over all immediate children of the CU DIE.  */
665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	do
666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    int tag = dwarf_tag (die);
668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (tag != DW_TAG_subprogram && tag != DW_TAG_variable)
669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      continue;
670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* We are interested in five attributes: name, decl_file,
672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       decl_line, low_pc, and high_pc.  */
673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    Dwarf_Attribute attr_mem;
674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    Dwarf_Attribute *attr = dwarf_attr (die, DW_AT_name, &attr_mem);
675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    const char *name = dwarf_formstring (attr);
676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (name == NULL)
677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      continue;
678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    Dwarf_Word fileidx;
680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    attr = dwarf_attr (die, DW_AT_decl_file, &attr_mem);
681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (dwarf_formudata (attr, &fileidx) != 0 || fileidx >= nfiles)
682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      continue;
683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    Dwarf_Word lineno;
685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    attr = dwarf_attr (die, DW_AT_decl_line, &attr_mem);
686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (dwarf_formudata (attr, &lineno) != 0 || lineno == 0)
687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      continue;
688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    Dwarf_Addr lowpc;
690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    Dwarf_Addr highpc;
691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (tag == DW_TAG_subprogram)
692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (dwarf_lowpc (die, &lowpc) != 0
694b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    || dwarf_highpc (die, &highpc) != 0)
695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  continue;
696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    else
698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (get_var_range (die, &lowpc, &highpc) != 0)
700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  continue;
701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* We have all the information.  Create a record.  */
704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    struct local_name *newp
705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      = (struct local_name *) xmalloc (sizeof (*newp));
706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    newp->name = name;
707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    newp->file = dwarf_filesrc (files, fileidx, NULL, NULL);
708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    newp->lineno = lineno;
709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    newp->lowpc = lowpc;
710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    newp->highpc = highpc;
711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
7123fbd857267a6bffc57225857690aaa383ac58426Mark Wielaard	   /* Check whether a similar local_name is already in the
7133fbd857267a6bffc57225857690aaa383ac58426Mark Wielaard	      cache.  That should not happen.  But if it does, we
7143fbd857267a6bffc57225857690aaa383ac58426Mark Wielaard	      don't want to leak memory.  */
7153fbd857267a6bffc57225857690aaa383ac58426Mark Wielaard	    struct local_name **tres = tsearch (newp, &local_root,
7163fbd857267a6bffc57225857690aaa383ac58426Mark Wielaard						local_compare);
7173fbd857267a6bffc57225857690aaa383ac58426Mark Wielaard	    if (tres == NULL)
7183fbd857267a6bffc57225857690aaa383ac58426Mark Wielaard              error (EXIT_FAILURE, errno,
7193fbd857267a6bffc57225857690aaa383ac58426Mark Wielaard                     gettext ("cannot create search tree"));
7203fbd857267a6bffc57225857690aaa383ac58426Mark Wielaard	    else if (*tres != newp)
7213fbd857267a6bffc57225857690aaa383ac58426Mark Wielaard	      free (newp);
722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	while (dwarf_siblingof (die, die) == 0);
724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
727468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath/* Do elf_strptr, but return a backup string and never NULL.  */
728468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrathstatic const char *
729468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrathsym_name (Elf *elf, GElf_Word strndx, GElf_Word st_name, char buf[], size_t n)
730468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath{
731468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath  const char *symstr = elf_strptr (elf, strndx, st_name);
732468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath  if (symstr == NULL)
733468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath    {
734468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath      snprintf (buf, n, "[invalid st_name %#" PRIx32 "]", st_name);
735468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath      symstr = buf;
736468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath    }
737468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath  return symstr;
738468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath}
739b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
740b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Show symbols in SysV format.  */
741b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
742c8920de1429631ab53b8a388acdd3f8064305bd3Marek Polacekshow_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname,
743b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   GElf_SymX *syms, size_t nsyms, int longest_name,
744b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   int longest_where)
745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t shnum;
747f189493154d0041deced00e6a99cc5426dc9d260Ulrich Drepper  if (elf_getshdrnum (ebl->elf, &shnum) < 0)
748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    INTERNAL_ERROR (fullname);
749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool scnnames_malloced = shnum * sizeof (const char *) > 128 * 1024;
751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const char **scnnames;
752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (scnnames_malloced)
753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    scnnames = (const char **) xmalloc (sizeof (const char *) * shnum);
754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    scnnames = (const char **) alloca (sizeof (const char *) * shnum);
756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Get the section header string table index.  */
757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t shstrndx;
758f189493154d0041deced00e6a99cc5426dc9d260Ulrich Drepper  if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    error (EXIT_FAILURE, 0,
760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   gettext ("cannot get section header string table index"));
761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Cache the section names.  */
763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *scn = NULL;
764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t cnt = 1;
765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr shdr_mem;
768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
76903d76f4aec5e750b81198c7a24571e119e754b40Mark Wielaard      assert (elf_ndxscn (scn) == cnt);
77003d76f4aec5e750b81198c7a24571e119e754b40Mark Wielaard      cnt++;
771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
772468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath      char *name = elf_strptr (ebl->elf, shstrndx,
773468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath			       gelf_getshdr (scn, &shdr_mem)->sh_name);
774468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath      if (unlikely (name == NULL))
775468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath	{
7767df3d2cd70932cd70515dbeb75e4db66fd27f192Mark Wielaard	  const size_t bufsz = sizeof "[invalid sh_name 0x12345678]";
77757bd66cabf6e6b9ecf622cdbf350804897a8df58Roland McGrath	  name = alloca (bufsz);
77857bd66cabf6e6b9ecf622cdbf350804897a8df58Roland McGrath	  snprintf (name, bufsz, "[invalid sh_name %#" PRIx32 "]",
779468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath		    gelf_getshdr (scn, &shdr_mem)->sh_name);
780468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath	}
781468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath      scnnames[elf_ndxscn (scn)] = name;
782b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
783b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
784b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int digits = length_map[gelf_getclass (ebl->elf) - 1][radix];
785b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
786b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We always print this prolog.  */
787c8920de1429631ab53b8a388acdd3f8064305bd3Marek Polacek  printf (gettext ("\n\nSymbols from %s:\n\n"), fullname);
788b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
789b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* The header line.  */
790b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  printf (gettext ("%*s%-*s %-*s Class  Type     %-*s %*s Section\n\n"),
791b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  print_file_name ? (int) strlen (fullname) + 1: 0, "",
792b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  longest_name, sgettext ("sysv|Name"),
793b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* TRANS: the "sysv|" parts makes the string unique.  */
794b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  digits, sgettext ("sysv|Value"),
795b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* TRANS: the "sysv|" parts makes the string unique.  */
796b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  digits, sgettext ("sysv|Size"),
797b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* TRANS: the "sysv|" parts makes the string unique.  */
798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  longest_where, sgettext ("sysv|Line"));
799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
800b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
801b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper  size_t demangle_buffer_len = 0;
802b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper  char *demangle_buffer = NULL;
803b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
804b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
805b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Iterate over all symbols.  */
80666f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper  for (cnt = 1; cnt < nsyms; ++cnt)
807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
80866f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper      /* In this format SECTION entries are not printed.  */
80966f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper      if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_SECTION)
81066f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper	continue;
81166f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper
812468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath      char symstrbuf[50];
813468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath      const char *symstr = sym_name (ebl->elf, strndx, syms[cnt].sym.st_name,
814468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath				     symstrbuf, sizeof symstrbuf);
815468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath
816b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
8177c6e785e6eca774080a64801f950bd61785c469eJan Kratochvil      /* Demangle if necessary.  Require GNU v3 ABI by the "_Z" prefix.  */
8187c6e785e6eca774080a64801f950bd61785c469eJan Kratochvil      if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
819b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	{
820b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	  int status = -1;
821b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
822b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper					   &demangle_buffer_len, &status);
823b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
824b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	  if (status == 0)
825b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	    symstr = dmsymstr;
826b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	}
827b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
828b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
829b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      char symbindbuf[50];
830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      char symtypebuf[50];
831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      char secnamebuf[1024];
83266f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper      char addressbuf[(64 + 2) / 3 + 1];
83366f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper      char sizebuf[(64 + 2) / 3 + 1];
834b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
835b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If we have to precede the line with the file name.  */
836b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (print_file_name)
837b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
838b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  fputs_unlocked (fullname, stdout);
839b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  putchar_unlocked (':');
840b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
841b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
84266f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper      /* Covert the address.  */
84366f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper      if (syms[cnt].sym.st_shndx == SHN_UNDEF)
84466f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper	addressbuf[0] = sizebuf[0] = '\0';
84566f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper      else
84666f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper	{
847f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard	  snprintf (addressbuf, sizeof (addressbuf),
848f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		    (radix == radix_hex ? "%0*" PRIx64
849f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		     : (radix == radix_decimal ? "%0*" PRId64
850f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard			: "%0*" PRIo64)),
85166f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper		    digits, syms[cnt].sym.st_value);
852f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard	  snprintf (sizebuf, sizeof (sizebuf),
853f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		    (radix == radix_hex ? "%0*" PRIx64
854f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		     : (radix == radix_decimal ? "%0*" PRId64
855f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard			: "%0*" PRIo64)),
85666f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper		    digits, syms[cnt].sym.st_size);
85766f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper	}
85866f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper
859b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Print the actual string.  */
86066f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper      printf ("%-*s|%s|%-6s|%-8s|%s|%*s|%s\n",
86166f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper	      longest_name, symstr, addressbuf,
862b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ebl_symbol_binding_name (ebl,
863b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				       GELF_ST_BIND (syms[cnt].sym.st_info),
864b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				       symbindbuf, sizeof (symbindbuf)),
865b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ebl_symbol_type_name (ebl, GELF_ST_TYPE (syms[cnt].sym.st_info),
866b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				    symtypebuf, sizeof (symtypebuf)),
86766f4c37d497bdde040a33f299b12163f044b1bf2Ulrich Drepper	      sizebuf, longest_where, syms[cnt].where,
868b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ebl_section_name (ebl, syms[cnt].sym.st_shndx, syms[cnt].xndx,
869b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				secnamebuf, sizeof (secnamebuf), scnnames,
870b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				shnum));
871b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
872b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
873b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
874b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper  free (demangle_buffer);
875b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
876b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
877b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (scnnames_malloced)
878b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    free (scnnames);
879b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
880b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
881b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
882b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic char
8832356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepperclass_type_char (Elf *elf, const GElf_Ehdr *ehdr, GElf_Sym *sym)
884b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
885b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int local_p = GELF_ST_BIND (sym->st_info) == STB_LOCAL;
886b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
887b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* XXX Add support for architecture specific types and classes.  */
888b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (sym->st_shndx == SHN_ABS)
889b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return local_p ? 'a' : 'A';
890b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
891b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (sym->st_shndx == SHN_UNDEF)
892b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* Undefined symbols must be global.  */
893b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return 'U';
894b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
8952356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper  char result = "NDTSFBD         "[GELF_ST_TYPE (sym->st_info)];
8962356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper
8972356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper  if (result == 'D')
8982356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper    {
8992356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper      /* Special handling: unique data symbols.  */
9002356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper      if (ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX
9012356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper	  && GELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
9022356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper	result = 'u';
9032356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper      else
9042356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper	{
9052356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper	  GElf_Shdr shdr_mem;
9062356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, sym->st_shndx),
9072356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper					  &shdr_mem);
9082356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper	  if (shdr != NULL)
9092356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper	    {
9102356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper	      if ((shdr->sh_flags & SHF_WRITE) == 0)
9112356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper		result = 'R';
9122356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper	      else if (shdr->sh_type == SHT_NOBITS)
9132356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper		result = 'B';
9142356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper	    }
9152356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper	}
9162356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper    }
917b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
918b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return local_p ? tolower (result) : result;
919b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
920b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
921b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
922b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
9232356ba04aeb670b90925ae88c3e579d75085a381Ulrich Dreppershow_symbols_bsd (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
924b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  const char *prefix, const char *fname, const char *fullname,
925b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_SymX *syms, size_t nsyms)
926b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
927b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int digits = length_map[gelf_getclass (elf) - 1][radix];
928b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
929b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (prefix != NULL && ! print_file_name)
930b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    printf ("\n%s:\n", fname);
931b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
932b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
933b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper  size_t demangle_buffer_len = 0;
934b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper  char *demangle_buffer = NULL;
935b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
936b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
937b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Iterate over all symbols.  */
938b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (size_t cnt = 0; cnt < nsyms; ++cnt)
939b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
940468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath      char symstrbuf[50];
941468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath      const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
942468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath				     symstrbuf, sizeof symstrbuf);
943b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
944b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Printing entries with a zero-length name makes the output
945b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 not very well parseable.  Since these entries don't carry
946b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 much information we leave them out.  */
947b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (symstr[0] == '\0')
948b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	continue;
949b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
950c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper      /* We do not print the entries for files.  */
951c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper      if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_FILE)
952c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	continue;
953c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper
954b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
9557c6e785e6eca774080a64801f950bd61785c469eJan Kratochvil      /* Demangle if necessary.  Require GNU v3 ABI by the "_Z" prefix.  */
9567c6e785e6eca774080a64801f950bd61785c469eJan Kratochvil      if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
957b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	{
958b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	  int status = -1;
959b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
960b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper					   &demangle_buffer_len, &status);
961b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
962b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	  if (status == 0)
963b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	    symstr = dmsymstr;
964b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	}
965b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
966b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
967b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If we have to precede the line with the file name.  */
968b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (print_file_name)
969b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
970b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  fputs_unlocked (fullname, stdout);
971b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  putchar_unlocked (':');
972b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
973b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
974c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper      bool is_tls = GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS;
975c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper      bool is_weak = GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK;
976c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper      const char *marker = (mark_special
977c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper			    ? (is_tls ? "@" : (is_weak ? "*" : " ")) : "");
978c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper
979b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (syms[cnt].sym.st_shndx == SHN_UNDEF)
980c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	{
981c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	  const char *color = "";
982c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	  if (color_mode)
983c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	    {
984c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	      if (is_tls)
985c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper		color = color_undef_tls;
986c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	      else if (is_weak)
987c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper		color = color_undef_weak;
988c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	      else
989c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper		color = color_undef;
990c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	    }
991c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper
992c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	  printf ("%*s %sU%s %s", digits, "", color, marker, symstr);
993c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	}
994b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
995c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	{
996c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	  const char *color = "";
997c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	  if (color_mode)
998c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	    {
999c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	      if (is_tls)
1000c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper		color = color_tls;
1001c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	      else if (is_weak)
1002c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper		color = color_weak;
1003c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	      else
1004c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper		color = color_symbol;
1005c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	    }
1006f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard	  if (print_size && syms[cnt].sym.st_size != 0)
1007f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard	    {
1008f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard#define HEXFMT "%6$s%2$0*1$" PRIx64 "%8$s %10$0*9$" PRIx64 " %7$s%3$c%4$s %5$s"
1009f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard#define DECFMT "%6$s%2$*1$" PRId64 "%8$s %10$*9$" PRId64 " %7$s%3$c%4$s %5$s"
1010f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard#define OCTFMT "%6$s%2$0*1$" PRIo64 "%8$s %10$0*9$" PRIo64 " %7$s%3$c%4$s %5$s"
1011f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard	      printf ((radix == radix_hex ? HEXFMT
1012f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		       : (radix == radix_decimal ? DECFMT : OCTFMT)),
1013f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		      digits, syms[cnt].sym.st_value,
1014f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		      class_type_char (elf, ehdr, &syms[cnt].sym), marker,
1015f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		      symstr,
1016f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		      color_mode ? color_address : "",
1017f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		      color,
1018f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		      color_mode ? color_off : "",
1019f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		      digits, (uint64_t) syms[cnt].sym.st_size);
1020f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard#undef HEXFMT
1021f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard#undef DECFMT
1022f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard#undef OCTFMT
1023f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard	    }
1024f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard	  else
1025f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard	    {
1026f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard#define HEXFMT "%6$s%2$0*1$" PRIx64 "%8$s %7$s%3$c%4$s %5$s"
1027f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard#define DECFMT "%6$s%2$*1$" PRId64 "%8$s %7$s%3$c%4$s %5$s"
1028f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard#define OCTFMT "%6$s%2$0*1$" PRIo64 "%8$s %7$s%3$c%4$s %5$s"
1029f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard	      printf ((radix == radix_hex ? HEXFMT
1030f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		       : (radix == radix_decimal ? DECFMT : OCTFMT)),
1031f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		      digits, syms[cnt].sym.st_value,
1032f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		      class_type_char (elf, ehdr, &syms[cnt].sym), marker,
1033f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		      symstr,
1034f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		      color_mode ? color_address : "",
1035f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		      color,
1036f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		      color_mode ? color_off : "");
1037f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard#undef HEXFMT
1038f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard#undef DECFMT
1039f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard#undef OCTFMT
1040f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard	    }
1041c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	}
1042c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper
1043c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper      if (color_mode)
1044c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper	fputs_unlocked (color_off, stdout);
1045c6b3d0c27833c8e0936cb6b8973e8578e3a9421fUlrich Drepper      putchar_unlocked ('\n');
1046b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1047b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
1048b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
1049b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper  free (demangle_buffer);
1050b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
1051b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1052b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1053b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1054b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
10552356ba04aeb670b90925ae88c3e579d75085a381Ulrich Dreppershow_symbols_posix (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
10562356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper		    const char *prefix, const char *fullname, GElf_SymX *syms,
10572356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper		    size_t nsyms)
1058b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1059b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (prefix != NULL && ! print_file_name)
1060b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    printf ("%s:\n", fullname);
1061b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1062b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int digits = length_map[gelf_getclass (elf) - 1][radix];
1063b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1064b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
1065b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper  size_t demangle_buffer_len = 0;
1066b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper  char *demangle_buffer = NULL;
1067b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
1068b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
1069b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Iterate over all symbols.  */
1070b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (size_t cnt = 0; cnt < nsyms; ++cnt)
1071b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1072468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath      char symstrbuf[50];
1073468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath      const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
1074468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath				     symstrbuf, sizeof symstrbuf);
1075b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1076b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Printing entries with a zero-length name makes the output
1077b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 not very well parseable.  Since these entries don't carry
1078b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 much information we leave them out.  */
1079b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (symstr[0] == '\0')
1080b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	continue;
1081b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1082b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
10837c6e785e6eca774080a64801f950bd61785c469eJan Kratochvil      /* Demangle if necessary.  Require GNU v3 ABI by the "_Z" prefix.  */
10847c6e785e6eca774080a64801f950bd61785c469eJan Kratochvil      if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
1085b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	{
1086b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	  int status = -1;
1087b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
1088b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper					   &demangle_buffer_len, &status);
1089b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
1090b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	  if (status == 0)
1091b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	    symstr = dmsymstr;
1092b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	}
1093b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
1094b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
1095b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If we have to precede the line with the file name.  */
1096b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (print_file_name)
1097b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1098b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  fputs_unlocked (fullname, stdout);
1099b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  putchar_unlocked (':');
1100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  putchar_unlocked (' ');
1101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1103f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard      printf ((radix == radix_hex
1104f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard	       ? "%s %c%s %0*" PRIx64 " %0*" PRIx64 "\n"
1105f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard	       : (radix == radix_decimal
1106f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		  ? "%s %c%s %*" PRId64 " %*" PRId64 "\n"
1107f48eb6b15fee66e54b488d71738979fc608f25eeMark Wielaard		  : "%s %c%s %0*" PRIo64 " %0*" PRIo64 "\n")),
1108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      symstr,
11092356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper	      class_type_char (elf, ehdr, &syms[cnt].sym),
11102356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper	      mark_special
11112356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper	      ? (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS
11122356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper		 ? "@"
11132356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper		 : (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK
11142356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper		    ? "*" : " "))
1115b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      : "",
1116b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      digits, syms[cnt].sym.st_value,
1117b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      digits, syms[cnt].sym.st_size);
1118b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1119b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
1120b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
1121b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper  free (demangle_buffer);
1122b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
1123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Maximum size of memory we allocate on the stack.  */
1127b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define MAX_STACK_ALLOC	65536
1128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1129cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrathstatic int
1130cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrathsort_by_address (const void *p1, const void *p2)
1131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1132cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  GElf_SymX *s1 = (GElf_SymX *) p1;
1133cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  GElf_SymX *s2 = (GElf_SymX *) p2;
1134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1135cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  int result = (s1->sym.st_value < s2->sym.st_value
1136cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath		? -1 : (s1->sym.st_value == s2->sym.st_value ? 0 : 1));
1137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1138cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  return reverse_sort ? -result : result;
1139cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath}
1140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1141cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrathstatic Elf_Data *sort_by_name_strtab;
1142cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
1143cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrathstatic int
1144cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrathsort_by_name (const void *p1, const void *p2)
1145cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath{
1146cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  GElf_SymX *s1 = (GElf_SymX *) p1;
1147cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  GElf_SymX *s2 = (GElf_SymX *) p2;
1148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1149cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  const char *n1 = sort_by_name_strtab->d_buf + s1->sym.st_name;
1150cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  const char *n2 = sort_by_name_strtab->d_buf + s2->sym.st_name;
1151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1152cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  int result = strcmp (n1, n2);
1153cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
1154cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  return reverse_sort ? -result : result;
1155cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath}
1156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
115770cd907e38757283f3696465771f723a342cc3d1Mark Wielaard/* Stub libdwfl callback, only the ELF handle already open is ever
115870cd907e38757283f3696465771f723a342cc3d1Mark Wielaard   used.  Only used for finding the alternate debug file if the Dwarf
115970cd907e38757283f3696465771f723a342cc3d1Mark Wielaard   comes from the main file.  We are not interested in separate
116070cd907e38757283f3696465771f723a342cc3d1Mark Wielaard   debuginfo.  */
116170cd907e38757283f3696465771f723a342cc3d1Mark Wielaardstatic int
116270cd907e38757283f3696465771f723a342cc3d1Mark Wielaardfind_no_debuginfo (Dwfl_Module *mod,
116370cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		   void **userdata,
116470cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		   const char *modname,
116570cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		   Dwarf_Addr base,
116670cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		   const char *file_name,
116770cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		   const char *debuglink_file,
116870cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		   GElf_Word debuglink_crc,
116970cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		   char **debuginfo_file_name)
117070cd907e38757283f3696465771f723a342cc3d1Mark Wielaard{
117170cd907e38757283f3696465771f723a342cc3d1Mark Wielaard  Dwarf_Addr dwbias;
117270cd907e38757283f3696465771f723a342cc3d1Mark Wielaard  dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
117370cd907e38757283f3696465771f723a342cc3d1Mark Wielaard
117470cd907e38757283f3696465771f723a342cc3d1Mark Wielaard  /* We are only interested if the Dwarf has been setup on the main
117570cd907e38757283f3696465771f723a342cc3d1Mark Wielaard     elf file but is only missing the alternate debug link.  If dwbias
117670cd907e38757283f3696465771f723a342cc3d1Mark Wielaard     hasn't even been setup, this is searching for separate debuginfo
117770cd907e38757283f3696465771f723a342cc3d1Mark Wielaard     for the main elf.  We don't care in that case.  */
117870cd907e38757283f3696465771f723a342cc3d1Mark Wielaard  if (dwbias == (Dwarf_Addr) -1)
117970cd907e38757283f3696465771f723a342cc3d1Mark Wielaard    return -1;
118070cd907e38757283f3696465771f723a342cc3d1Mark Wielaard
118170cd907e38757283f3696465771f723a342cc3d1Mark Wielaard  return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
118270cd907e38757283f3696465771f723a342cc3d1Mark Wielaard				       file_name, debuglink_file,
118370cd907e38757283f3696465771f723a342cc3d1Mark Wielaard				       debuglink_crc, debuginfo_file_name);
118470cd907e38757283f3696465771f723a342cc3d1Mark Wielaard}
118570cd907e38757283f3696465771f723a342cc3d1Mark Wielaard
118670cd907e38757283f3696465771f723a342cc3d1Mark Wielaard/* Get the Dwarf for the module/file we want.  */
118770cd907e38757283f3696465771f723a342cc3d1Mark Wielaardstruct getdbg
118870cd907e38757283f3696465771f723a342cc3d1Mark Wielaard{
118970cd907e38757283f3696465771f723a342cc3d1Mark Wielaard  const char *name;
119070cd907e38757283f3696465771f723a342cc3d1Mark Wielaard  Dwarf **dbg;
119170cd907e38757283f3696465771f723a342cc3d1Mark Wielaard};
119270cd907e38757283f3696465771f723a342cc3d1Mark Wielaard
119370cd907e38757283f3696465771f723a342cc3d1Mark Wielaardstatic int
119470cd907e38757283f3696465771f723a342cc3d1Mark Wielaardgetdbg_dwflmod (Dwfl_Module *dwflmod,
119570cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		void **userdata __attribute__ ((unused)),
119670cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		const char *name,
119770cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		Dwarf_Addr base __attribute__ ((unused)),
119870cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		void *arg)
119970cd907e38757283f3696465771f723a342cc3d1Mark Wielaard{
120070cd907e38757283f3696465771f723a342cc3d1Mark Wielaard  struct getdbg *get = (struct getdbg *) arg;
120170cd907e38757283f3696465771f723a342cc3d1Mark Wielaard  if (get != NULL && get->name != NULL && strcmp (get->name, name) == 0)
120270cd907e38757283f3696465771f723a342cc3d1Mark Wielaard    {
120370cd907e38757283f3696465771f723a342cc3d1Mark Wielaard      Dwarf_Addr bias;
120470cd907e38757283f3696465771f723a342cc3d1Mark Wielaard      *get->dbg = dwfl_module_getdwarf (dwflmod, &bias);
120570cd907e38757283f3696465771f723a342cc3d1Mark Wielaard      return DWARF_CB_ABORT;
120670cd907e38757283f3696465771f723a342cc3d1Mark Wielaard    }
120770cd907e38757283f3696465771f723a342cc3d1Mark Wielaard
120870cd907e38757283f3696465771f723a342cc3d1Mark Wielaard  return DWARF_CB_OK;
120970cd907e38757283f3696465771f723a342cc3d1Mark Wielaard}
121070cd907e38757283f3696465771f723a342cc3d1Mark Wielaard
1211cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrathstatic void
121270cd907e38757283f3696465771f723a342cc3d1Mark Wielaardshow_symbols (int fd, Ebl *ebl, GElf_Ehdr *ehdr,
121370cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	      Elf_Scn *scn, Elf_Scn *xndxscn,
1214cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	      GElf_Shdr *shdr, const char *prefix, const char *fname,
1215cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	      const char *fullname)
1216cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath{
1217b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Get the section header string table index.  */
1218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t shstrndx;
1219f189493154d0041deced00e6a99cc5426dc9d260Ulrich Drepper  if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
1220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    error (EXIT_FAILURE, 0,
1221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   gettext ("cannot get section header string table index"));
1222b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* The section is that large.  */
1224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t size = shdr->sh_size;
1225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* One entry is this large.  */
1226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t entsize = shdr->sh_entsize;
1227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Consistency checks.  */
1229309e712fea93473ac9b1aa361456fce8d3867baaMark Wielaard  if (entsize == 0
1230a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard      || entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT))
1231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    error (0, 0,
1232309e712fea93473ac9b1aa361456fce8d3867baaMark Wielaard	   gettext ("%s: entry size in section %zd `%s' is not what we expect"),
1233309e712fea93473ac9b1aa361456fce8d3867baaMark Wielaard	   fullname, elf_ndxscn (scn),
1234309e712fea93473ac9b1aa361456fce8d3867baaMark Wielaard	   elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else if (size % entsize != 0)
1236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    error (0, 0,
1237309e712fea93473ac9b1aa361456fce8d3867baaMark Wielaard	   gettext ("%s: size of section %zd `%s' is not multiple of entry size"),
1238309e712fea93473ac9b1aa361456fce8d3867baaMark Wielaard	   fullname, elf_ndxscn (scn),
1239309e712fea93473ac9b1aa361456fce8d3867baaMark Wielaard	   elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Compute number of entries.  Handle buggy entsize values.  */
1242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t nentries = size / (entsize ?: 1);
1243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define obstack_chunk_alloc xmalloc
1246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define obstack_chunk_free free
1247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct obstack whereob;
1248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  obstack_init (&whereob);
1249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Get a DWARF debugging descriptor.  It's no problem if this isn't
1251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     possible.  We just won't print any line number information.  */
1252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwarf *dbg = NULL;
125370cd907e38757283f3696465771f723a342cc3d1Mark Wielaard  Dwfl *dwfl = NULL;
1254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (format == format_sysv)
1255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
125670cd907e38757283f3696465771f723a342cc3d1Mark Wielaard      if (ehdr->e_type != ET_REL)
125770cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
125870cd907e38757283f3696465771f723a342cc3d1Mark Wielaard      else
125970cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	{
126070cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	  /* Abuse libdwfl to do the relocations for us.  This is just
126170cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	     for the ET_REL file containing Dwarf, so no need for
126270cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	     fancy lookups.  */
126370cd907e38757283f3696465771f723a342cc3d1Mark Wielaard
126470cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	  /* Duplicate an fd for dwfl_report_offline to swallow.  */
126570cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	  int dwfl_fd = dup (fd);
126670cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	  if (likely (dwfl_fd >= 0))
126770cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	    {
126870cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	      static const Dwfl_Callbacks callbacks =
126970cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		{
127070cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		  .section_address = dwfl_offline_section_address,
127170cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		  .find_debuginfo = find_no_debuginfo
127270cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		};
127370cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	      dwfl = dwfl_begin (&callbacks);
127470cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	      if (likely (dwfl != NULL))
127570cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		{
127670cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		  /* Let 0 be the logical address of the file (or
127770cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		     first in archive).  */
127870cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		  dwfl->offline_next_address = 0;
127970cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		  if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd)
128070cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		      == NULL)
128170cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		    {
128270cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		      /* Consumed on success, not on failure.  */
128370cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		      close (dwfl_fd);
128470cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		    }
128570cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		  else
128670cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		    {
128770cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		      dwfl_report_end (dwfl, NULL, NULL);
128870cd907e38757283f3696465771f723a342cc3d1Mark Wielaard
128970cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		      struct getdbg get = { .name = fname, .dbg = &dbg };
129070cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		      dwfl_getmodules (dwfl, &getdbg_dwflmod, &get, 0);
129170cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		    }
129270cd907e38757283f3696465771f723a342cc3d1Mark Wielaard		}
129370cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	    }
129470cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	}
1295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dbg != NULL)
1296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1297b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  (void) dwarf_getpubnames (dbg, get_global, NULL, 0);
1298b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1299b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  get_local_names (dbg);
1300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1303c08079a076420f67742be98d060500965eb22340Mark Wielaard  /* Get the data of the section.  */
1304c08079a076420f67742be98d060500965eb22340Mark Wielaard  Elf_Data *data = elf_getdata (scn, NULL);
1305c08079a076420f67742be98d060500965eb22340Mark Wielaard  Elf_Data *xndxdata = elf_getdata (xndxscn, NULL);
1306c08079a076420f67742be98d060500965eb22340Mark Wielaard  if (data == NULL || (xndxscn != NULL && xndxdata == NULL))
1307c08079a076420f67742be98d060500965eb22340Mark Wielaard    INTERNAL_ERROR (fullname);
1308c08079a076420f67742be98d060500965eb22340Mark Wielaard
1309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Allocate the memory.
1310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     XXX We can use a dirty trick here.  Since GElf_Sym == Elf64_Sym we
1312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     can use the data memory instead of copying again if what we read
1313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     is a 64 bit file.  */
1314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_SymX *sym_mem;
1315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (nentries * sizeof (GElf_SymX) < MAX_STACK_ALLOC)
1316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    sym_mem = (GElf_SymX *) alloca (nentries * sizeof (GElf_SymX));
1317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
1318b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    sym_mem = (GElf_SymX *) xmalloc (nentries * sizeof (GElf_SymX));
1319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Iterate over all symbols.  */
1321b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
1322b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper  size_t demangle_buffer_len = 0;
1323b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper  char *demangle_buffer = NULL;
1324b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
1325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int longest_name = 4;
1326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int longest_where = 4;
1327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t nentries_used = 0;
1328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (size_t cnt = 0; cnt < nentries; ++cnt)
1329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, cnt,
1331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					&sym_mem[nentries_used].sym,
1332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					&sym_mem[nentries_used].xndx);
1333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym == NULL)
1334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	INTERNAL_ERROR (fullname);
1335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Filter out administrative symbols without a name and those
1337b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	 deselected by the user with command line options.  */
1338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((hide_undefined && sym->st_shndx == SHN_UNDEF)
1339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || (hide_defined && sym->st_shndx != SHN_UNDEF)
1340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || (hide_local && GELF_ST_BIND (sym->st_info) == STB_LOCAL))
1341b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	continue;
1342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      sym_mem[nentries_used].where = "";
1344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (format == format_sysv)
1345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  const char *symstr = elf_strptr (ebl->elf, shdr->sh_link,
1347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					   sym->st_name);
1348468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath	  if (symstr == NULL)
1349468fe4d81a3e92157f4c0446675487dc230b2ec6Roland McGrath	    continue;
1350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1351b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
13527c6e785e6eca774080a64801f950bd61785c469eJan Kratochvil	  /* Demangle if necessary.  Require GNU v3 ABI by the "_Z" prefix.  */
13537c6e785e6eca774080a64801f950bd61785c469eJan Kratochvil	  if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
1354b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	    {
1355b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	      int status = -1;
1356b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	      char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
1357b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper					       &demangle_buffer_len, &status);
1358b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
1359b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	      if (status == 0)
1360b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper		symstr = dmsymstr;
1361b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	    }
1362b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
1363b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper
1364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  longest_name = MAX ((size_t) longest_name, strlen (symstr));
1365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (sym->st_shndx != SHN_UNDEF
1367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && GELF_ST_BIND (sym->st_info) != STB_LOCAL
1368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && global_root != NULL)
1369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      Dwarf_Global fake = { .name = symstr };
1371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      Dwarf_Global **found = tfind (&fake, &global_root,
1372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					    global_compare);
1373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (found != NULL)
1374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
1375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  Dwarf_Die die_mem;
1376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  Dwarf_Die *die = dwarf_offdie (dbg, (*found)->die_offset,
1377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						 &die_mem);
1378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  Dwarf_Die cudie_mem;
1380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  Dwarf_Die *cudie = NULL;
1381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  Dwarf_Addr lowpc;
1383b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  Dwarf_Addr highpc;
1384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (die != NULL
1385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && dwarf_lowpc (die, &lowpc) == 0
1386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && lowpc <= sym->st_value
1387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && dwarf_highpc (die, &highpc) == 0
1388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && highpc > sym->st_value)
1389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    cudie = dwarf_offdie (dbg, (*found)->cu_offset,
1390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					  &cudie_mem);
1391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (cudie != NULL)
1392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
1393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      Dwarf_Line *line = dwarf_getsrc_die (cudie,
1394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper							   sym->st_value);
1395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (line != NULL)
1396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
1397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  /* We found the line.  */
1398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  int lineno;
1399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  (void) dwarf_lineno (line, &lineno);
1400a3344c7a785888ecd31475efaaf456db41897423Mark Wielaard			  const char *file = dwarf_linesrc (line, NULL, NULL);
1401a3344c7a785888ecd31475efaaf456db41897423Mark Wielaard			  file = (file != NULL) ? basename (file) : "???";
1402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  int n;
1403a3344c7a785888ecd31475efaaf456db41897423Mark Wielaard			  n = obstack_printf (&whereob, "%s:%d%c", file,
1404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					      lineno, '\0');
1405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  sym_mem[nentries_used].where
1406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    = obstack_finish (&whereob);
1407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  /* The return value of obstack_print included the
1409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     NUL byte, so subtract one.  */
1410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  if (--n > (int) longest_where)
1411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    longest_where = (size_t) n;
1412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
1413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
1414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
1415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1417b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper	  /* Try to find the symbol among the local symbols.  */
1418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (sym_mem[nentries_used].where[0] == '\0')
1419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      struct local_name fake =
1421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
1422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  .name = symstr,
1423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  .lowpc = sym->st_value,
1424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  .highpc = sym->st_value,
1425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		};
1426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      struct local_name **found = tfind (&fake, &local_root,
1427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						 local_compare);
1428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (found != NULL)
1429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
1430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* We found the line.  */
1431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  int n = obstack_printf (&whereob, "%s:%" PRIu64 "%c",
1432b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					  basename ((*found)->file),
1433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					  (*found)->lineno,
1434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					  '\0');
1435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  sym_mem[nentries_used].where = obstack_finish (&whereob);
1436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* The return value of obstack_print included the
1438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     NUL byte, so subtract one.  */
1439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (--n > (int) longest_where)
1440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    longest_where = (size_t) n;
1441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
1442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1445b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We use this entry.  */
1446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ++nentries_used;
1447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1448b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#ifdef USE_DEMANGLE
1449b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper  free (demangle_buffer);
1450b4a16cf0c61746e9b2414570e82e0efcfdf1e721Ulrich Drepper#endif
1451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now we know the exact number.  */
1452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  nentries = nentries_used;
1453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Sort the entries according to the users wishes.  */
1455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (sort == sort_name)
1456cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath    {
1457cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      sort_by_name_strtab = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link),
1458cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath					 NULL);
1459cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_name);
1460cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath    }
1461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else if (sort == sort_numeric)
1462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_address);
1463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Finally print according to the users selection.  */
1465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (format)
1466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case format_sysv:
1468c8920de1429631ab53b8a388acdd3f8064305bd3Marek Polacek      show_symbols_sysv (ebl, shdr->sh_link, fullname, sym_mem, nentries,
1469c8920de1429631ab53b8a388acdd3f8064305bd3Marek Polacek			 longest_name, longest_where);
1470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
1471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case format_bsd:
14732356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper      show_symbols_bsd (ebl->elf, ehdr, shdr->sh_link, prefix, fname, fullname,
1474b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			sym_mem, nentries);
1475b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
1476b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case format_posix:
1478b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
1479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      assert (format == format_posix);
14802356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper      show_symbols_posix (ebl->elf, ehdr, shdr->sh_link, prefix, fullname,
14812356ba04aeb670b90925ae88c3e579d75085a381Ulrich Drepper			  sym_mem, nentries);
1482b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
1483b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1485b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Free all memory.  */
14869beaa94e56fb8b717f838e02905e100647138bf9Mark Wielaard  if (nentries * sizeof (sym_mem[0]) >= MAX_STACK_ALLOC)
1487b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    free (sym_mem);
1488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  obstack_free (&whereob, NULL);
1490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (dbg != NULL)
1492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      tdestroy (global_root, free);
1494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      global_root = NULL;
1495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      tdestroy (local_root, free);
1497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      local_root = NULL;
1498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
149970cd907e38757283f3696465771f723a342cc3d1Mark Wielaard      if (dwfl == NULL)
150070cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	(void) dwarf_end (dbg);
1501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
150270cd907e38757283f3696465771f723a342cc3d1Mark Wielaard  if (dwfl != NULL)
150370cd907e38757283f3696465771f723a342cc3d1Mark Wielaard    dwfl_end (dwfl);
1504b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
150870cd907e38757283f3696465771f723a342cc3d1Mark Wielaardhandle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
1509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    const char *suffix)
1510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
1512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
1513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t fname_len = strlen (fname) + 1;
1514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char fullname[prefix_len + 1 + fname_len + suffix_len];
1515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *cp = fullname;
1516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *scn = NULL;
1517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int any = 0;
1518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int result = 0;
1519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr ehdr_mem;
1520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr *ehdr;
1521b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Ebl *ebl;
1522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Get the backend for this object file type.  */
1524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ebl = ebl_openbackend (elf);
1525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1526b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We need the ELF header in a few places.  */
1527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ehdr = gelf_getehdr (elf, &ehdr_mem);
1528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr == NULL)
1529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    INTERNAL_ERROR (fullname);
1530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If we are asked to print the dynamic symbol table and this is
1532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     executable or dynamic executable, fail.  */
1533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symsec_type == SHT_DYNSYM
1534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* XXX Add machine specific object file types.  */
1537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("%s%s%s%s: Invalid operation"),
1538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     prefix ?: "", prefix ? "(" : "", fname, prefix ? ")" : "");
1539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result = 1;
1540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      goto out;
1541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Create the full name of the file.  */
1544b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (prefix != NULL)
1545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    cp = mempcpy (cp, prefix, prefix_len);
1546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  cp = mempcpy (cp, fname, fname_len);
1547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (suffix != NULL)
1548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    memcpy (cp - 1, suffix, suffix_len + 1);
1549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Find the symbol table.
1551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     XXX Can there be more than one?  Do we print all?  Currently we do.  */
1553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while ((scn = elf_nextscn (elf, scn)) != NULL)
1554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr shdr_mem;
1556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr == NULL)
1559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	INTERNAL_ERROR (fullname);
1560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_type == symsec_type)
1562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  Elf_Scn *xndxscn = NULL;
1564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* We have a symbol table.  First make sure we remember this.  */
1566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  any = 1;
1567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Look for an extended section index table for this section.  */
1569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (symsec_type == SHT_SYMTAB)
1570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      size_t scnndx = elf_ndxscn (scn);
1572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      while ((xndxscn = elf_nextscn (elf, xndxscn)) != NULL)
1574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
1575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Shdr xndxshdr_mem;
1576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
1577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (xndxshdr == NULL)
1579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    INTERNAL_ERROR (fullname);
1580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
1582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && xndxshdr->sh_link == scnndx)
1583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    break;
1584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
1585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
158770cd907e38757283f3696465771f723a342cc3d1Mark Wielaard	  show_symbols (fd, ebl, ehdr, scn, xndxscn, shdr, prefix, fname,
1588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			fullname);
1589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (! any)
1593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("%s%s%s: no symbols"),
1595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     prefix ?: "", prefix ? ":" : "", fname);
1596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result = 1;
1597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper out:
1600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Close the ELF backend library descriptor.  */
1601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ebl_closebackend (ebl);
1602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
1604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
16053cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
16063cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
16073cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper#include "debugpred.h"
1608