125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print symbol information from ELF file in human-readable form.
225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Copyright (C) 2000-2008, 2009, 2011, 2012 Red Hat, Inc.
325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   This file is part of Red Hat elfutils.
425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is free software; you can redistribute it and/or modify
725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   it under the terms of the GNU General Public License as published by the
825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Free Software Foundation; version 2 of the License.
925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is distributed in the hope that it will be useful, but
1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   General Public License for more details.
1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   You should have received a copy of the GNU General Public License along
1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   with Red Hat elfutils; if not, write to the Free Software Foundation,
1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is an included package of the Open Invention Network.
2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   An included package of the Open Invention Network is a package for which
2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Open Invention Network licensees cross-license their patents.  No patent
2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   license is granted, either expressly or impliedly, by designation as an
2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   included package.  Should you wish to participate in the Open Invention
2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Network licensing program, please visit www.openinventionnetwork.com
2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   <http://www.openinventionnetwork.com>.  */
2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H
2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h>
2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <ar.h>
3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <argp.h>
3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h>
3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <ctype.h>
3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <dwarf.h>
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <errno.h>
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <error.h>
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <fcntl.h>
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <gelf.h>
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <inttypes.h>
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libdw.h>
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libintl.h>
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <locale.h>
4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <mcheck.h>
4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <obstack.h>
4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <search.h>
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h>
4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdio.h>
4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdio_ext.h>
5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h>
5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h>
5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h>
5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h>
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <system.h>
5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libebl/libeblP.h"
5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Name and version of program.  */
6025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_version (FILE *stream, struct argp_state *state);
6125b3c049e70834cf33790a28643ab058b507b35cBen ChengARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Bug report address.  */
6425b3c049e70834cf33790a28643ab058b507b35cBen ChengARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Values for the parameters which have no short form.  */
6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define OPT_DEFINED		0x100
6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define OPT_MARK_SPECIAL	0x101
7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Definitions of arguments for argp functions.  */
7225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct argp_option options[] =
7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "debug-syms", 'a', NULL, 0, N_("Display debugger-only symbols"), 0 },
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "defined-only", OPT_DEFINED, NULL, 0, N_("Display only defined symbols"),
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    0 },
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "dynamic", 'D', NULL, 0,
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Display dynamic symbols instead of normal symbols"), 0 },
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "extern-only", 'g', NULL, 0, N_("Display only external symbols"), 0 },
8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "undefined-only", 'u', NULL, 0, N_("Display only undefined symbols"), 0 },
8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "print-armap", 's', NULL, 0,
8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Include index for symbols from archive members"), 0 },
8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, N_("Output format:"), 0 },
8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "print-file-name", 'A', NULL, 0,
8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Print name of the input file before every symbol"), 0 },
8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'o', NULL, OPTION_HIDDEN, "Same as -A", 0 },
8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "format", 'f', "FORMAT", 0,
9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Use the output format FORMAT.  FORMAT can be `bsd', `sysv' or `posix'.  The default is `sysv'"),
9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    0 },
9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'B', NULL, 0, N_("Same as --format=bsd"), 0 },
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "portability", 'P', NULL, 0, N_("Same as --format=posix"), 0 },
9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "radix", 't', "RADIX", 0, N_("Use RADIX for printing symbol values"), 0 },
9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "mark-special", OPT_MARK_SPECIAL, NULL, 0, N_("Mark special symbols"), 0 },
9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "mark-weak", OPT_MARK_SPECIAL, NULL, OPTION_HIDDEN, "", 0 },
9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "print-size", 'S', NULL, 0, N_("Print size of defined symbols"), 0 },
9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, N_("Output options:"), 0 },
10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "numeric-sort", 'n', NULL, 0, N_("Sort symbols numerically by address"),
10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    0 },
10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "no-sort", 'p', NULL, 0, N_("Do not sort the symbols"), 0 },
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "reverse-sort", 'r', NULL, 0, N_("Reverse the sense of the sort"), 0 },
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "demangle", 'C', NULL, 0,
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Decode low-level symbol names into source code names"), 0 },
10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, NULL, 0 }
11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Short description of program.  */
11325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char doc[] = N_("List symbols from FILEs (a.out by default).");
11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Strings for arguments in help texts.  */
11625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char args_doc[] = N_("[FILE...]");
11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Prototype for option handler.  */
11925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Parser children.  */
12225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct argp_child argp_children[] =
12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { &color_argp, 0, N_("Output formatting"), 2 },
12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { NULL, 0, NULL, 0}
12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  };
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Data structure to communicate with argp functions.  */
12925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct argp argp =
13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  options, parse_opt, args_doc, doc, argp_children, NULL, NULL
13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print symbols in file named FNAME.  */
13625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int process_file (const char *fname, bool more_than_one);
13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle content of archive.  */
13925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      const char *suffix);
14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle ELF file.  */
14325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int handle_elf (Elf *elf, const char *prefix, const char *fname,
14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       const char *suffix);
14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define INTERNAL_ERROR(fname) \
14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"),      \
14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1))
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Internal representation of symbols.  */
15325b3c049e70834cf33790a28643ab058b507b35cBen Chengtypedef struct GElf_SymX
15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Sym sym;
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word xndx;
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *where;
15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} GElf_SymX;
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* User-selectable options.  */
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* The selected output format.  */
16425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic enum
16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  format_sysv = 0,
16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  format_bsd,
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  format_posix
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} format;
17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print defined, undefined, or both?  */
17225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool hide_undefined;
17325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool hide_defined;
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print local symbols also?  */
17625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool hide_local;
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Nonzero if full filename should precede every symbol.  */
17925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_file_name;
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* If true print size of defined symbols in BSD format.  */
18225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_size;
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* If true print archive index.  */
18525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_armap;
18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* If true reverse sorting.  */
18825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool reverse_sort;
18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* If true demangle symbols.  */
19225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool demangle;
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Type of the section we are printing.  */
19625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic GElf_Word symsec_type = SHT_SYMTAB;
19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Sorting selection.  */
19925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic enum
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  sort_name = 0,
20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  sort_numeric,
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  sort_nosort
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} sort;
20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Radix for printed numbers.  */
20725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic enum
20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  radix_hex = 0,
21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  radix_decimal,
21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  radix_octal
21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} radix;
21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* If nonzero mark special symbols:
21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   - weak symbols are distinguished from global symbols by adding
21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     a `*' after the identifying letter for the symbol class and type.
21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   - TLS symbols are distinguished from normal symbols by adding
21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     a '@' after the identifying letter for the symbol class and type.  */
21925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool mark_special;
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22225b3c049e70834cf33790a28643ab058b507b35cBen Chengint
22325b3c049e70834cf33790a28643ab058b507b35cBen Chengmain (int argc, char *argv[])
22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int remaining;
22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int result = 0;
22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Make memory leak detection possible.  */
22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  mtrace ();
23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We use no threads here which can interfere with handling a stream.  */
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Set locale.  */
23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) setlocale (LC_ALL, "");
23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Make sure the message catalog can be found.  */
24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Initialize the message catalog.  */
24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) textdomain (PACKAGE_TARNAME);
24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Parse and process arguments.  */
24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Tell the library which version we are expecting.  */
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) elf_version (EV_CURRENT);
25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (remaining == argc)
25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* The user didn't specify a name so we use a.out.  */
25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    result = process_file ("a.out", false);
25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Process all the remaining files.  */
25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const bool more_than_one = remaining + 1 < argc;
25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do
26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result |= process_file (argv[remaining], more_than_one);
26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (++remaining < argc);
26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the version information.  */
26925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
27025b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, "nm (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, gettext ("\
27425b3c049e70834cf33790a28643ab058b507b35cBen ChengCopyright (C) %s Red Hat, Inc.\n\
27525b3c049e70834cf33790a28643ab058b507b35cBen ChengThis is free software; see the source for copying conditions.  There is NO\n\
27625b3c049e70834cf33790a28643ab058b507b35cBen Chengwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng"), "2012");
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle program arguments.  */
28325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic error_t
28425b3c049e70834cf33790a28643ab058b507b35cBen Chengparse_opt (int key, char *arg,
28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   struct argp_state *state __attribute__ ((unused)))
28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (key)
28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'a':
29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* XXX */
29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'C':
29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      demangle = true;
29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'f':
30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (strcmp (arg, "bsd") == 0)
30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	format = format_bsd;
30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "posix") == 0)
30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	format = format_posix;
30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* Be bug compatible.  The BFD implementation also defaulted to
30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   using the SysV format if nothing else matches.  */
30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	format = format_sysv;
30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'g':
31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      hide_local = true;
31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'n':
31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      sort = sort_numeric;
31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'p':
31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      sort = sort_nosort;
32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 't':
32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (strcmp (arg, "10") == 0 || strcmp (arg, "d") == 0)
32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	radix = radix_decimal;
32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "8") == 0 || strcmp (arg, "o") == 0)
32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	radix = radix_octal;
32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	radix = radix_hex;
32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'u':
33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      hide_undefined = false;
33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      hide_defined = true;
33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'A':
33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'o':
33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_file_name = true;
33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'B':
34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      format = format_bsd;
34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'D':
34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      symsec_type = SHT_DYNSYM;
34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'P':
35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      format = format_posix;
35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case OPT_DEFINED:
35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      hide_undefined = true;
35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      hide_defined = false;
35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case OPT_MARK_SPECIAL:
35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      mark_special = true;
36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'S':
36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_size = true;
36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 's':
36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_armap = true;
36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'r':
37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      reverse_sort = true;
37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return ARGP_ERR_UNKNOWN;
37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Open the file and determine the type.  */
38225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
38325b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_file (const char *fname, bool more_than_one)
38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Open the file.  */
38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int fd = open (fname, O_RDONLY);
38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fd == -1)
38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, errno, gettext ("cannot open '%s'"), fname);
39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 1;
39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Now get the ELF descriptor.  */
39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf != NULL)
39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf_kind (elf) == ELF_K_ELF)
39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int result = handle_elf (elf, more_than_one ? "" : NULL,
40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				   fname, NULL);
40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (elf_end (elf) != 0)
40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    INTERNAL_ERROR (fname);
40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (close (fd) != 0)
40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return result;
40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (elf_kind (elf) == ELF_K_AR)
41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int result = handle_ar (fd, elf, NULL, fname, NULL);
41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (elf_end (elf) != 0)
41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    INTERNAL_ERROR (fname);
41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (close (fd) != 0)
41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return result;
42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We cannot handle this type.  Close the descriptor anyway.  */
42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf_end (elf) != 0)
42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	INTERNAL_ERROR (fname);
42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  error (0, 0, gettext ("%s: File format not recognized"), fname);
42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 1;
43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
43525b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   const char *suffix)
43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t fname_len = strlen (fname) + 1;
43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t prefix_len = prefix != NULL ? strlen (prefix) : 0;
44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char new_prefix[prefix_len + fname_len + 2];
44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t suffix_len = suffix != NULL ? strlen (suffix) : 0;
44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char new_suffix[suffix_len + 2];
44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *subelf;
44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Cmd cmd = ELF_C_READ_MMAP;
44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int result = 0;
44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *cp = new_prefix;
44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (prefix != NULL)
44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    cp = stpcpy (cp, prefix);
45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  cp = stpcpy (cp, fname);
45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  stpcpy (cp, "[");
45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  cp = new_suffix;
45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (suffix != NULL)
45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    cp = stpcpy (cp, suffix);
45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  stpcpy (cp, "]");
45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* First print the archive index if this is wanted.  */
45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_armap)
46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Arsym *arsym = elf_getarsym (elf, NULL);
46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (arsym != NULL)
46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Arhdr *arhdr = NULL;
46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t arhdr_off = 0;	/* Note: 0 is no valid offset.  */
46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fputs_unlocked (gettext("\nArchive index:\n"), stdout);
46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  while (arsym->as_off != 0)
47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (arhdr_off != arsym->as_off
47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && (elf_rand (elf, arsym->as_off) != arsym->as_off
47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      || (subelf = elf_begin (fd, cmd, elf)) == NULL
47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      || (arhdr = elf_getarhdr (subelf)) == NULL))
47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  error (0, 0, gettext ("invalid offset %zu for symbol %s"),
47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 arsym->as_off, arsym->as_name);
47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  continue;
48025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf (gettext ("%s in %s\n"), arsym->as_name, arhdr->ar_name);
48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ++arsym;
48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (elf_rand (elf, SARMAG) != SARMAG)
48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (0, 0,
49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     gettext ("cannot reset archive offset to beginning"));
49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return 1;
49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Process all the files contained in the archive.  */
49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* The the header for this element.  */
50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Skip over the index entries.  */
50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (strcmp (arhdr->ar_name, "/") != 0
50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && strcmp (arhdr->ar_name, "//") != 0)
50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (elf_kind (subelf) == ELF_K_ELF)
50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    result |= handle_elf (subelf, new_prefix, arhdr->ar_name,
50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				  new_suffix);
50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (elf_kind (subelf) == ELF_K_AR)
51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name,
51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 new_suffix);
51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (0, 0, gettext ("%s%s%s: file format not recognized"),
51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     new_prefix, arhdr->ar_name, new_suffix);
51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      result = 1;
51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get next archive element.  */
52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      cmd = elf_next (subelf);
52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf_end (subelf) != 0)
52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	INTERNAL_ERROR (fname);
52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
52525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Mapping of radix and binary class to length.  */
53125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const int length_map[2][3] =
53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  [ELFCLASS32 - 1] =
53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    [radix_hex] = 8,
53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    [radix_decimal] = 10,
53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    [radix_octal] = 11
53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  },
53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  [ELFCLASS64 - 1] =
54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    [radix_hex] = 16,
54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    [radix_decimal] = 20,
54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    [radix_octal] = 22
54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  }
54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
54925b3c049e70834cf33790a28643ab058b507b35cBen Chengglobal_compare (const void *p1, const void *p2)
55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Dwarf_Global *g1 = (const Dwarf_Global *) p1;
55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Dwarf_Global *g2 = (const Dwarf_Global *) p2;
55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return strcmp (g1->name, g2->name);
55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void *global_root;
55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
56225b3c049e70834cf33790a28643ab058b507b35cBen Chengget_global (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    void *arg __attribute__ ((unused)))
56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  tsearch (memcpy (xmalloc (sizeof (Dwarf_Global)), global,
56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   sizeof (Dwarf_Global)),
56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   &global_root, global_compare);
56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return DWARF_CB_OK;
57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57325b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct local_name
57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *name;
57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *file;
57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Word lineno;
57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Addr lowpc;
57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Addr highpc;
58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
58225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
58325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
58425b3c049e70834cf33790a28643ab058b507b35cBen Chenglocal_compare (const void *p1, const void *p2)
58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct local_name *g1 = (struct local_name *) p1;
58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct local_name *g2 = (struct local_name *) p2;
58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int result;
58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  result = strcmp (g1->name, g2->name);
59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (result == 0)
59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (g1->lowpc <= g2->lowpc && g1->highpc >= g2->highpc)
59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* g2 is contained in g1.  Update the data.  */
59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  g2->lowpc = g1->lowpc;
59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  g2->highpc = g1->highpc;
59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  result = 0;
59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (g2->lowpc <= g1->lowpc && g2->highpc >= g1->highpc)
60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* g1 is contained in g2.  Update the data.  */
60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  g1->lowpc = g2->lowpc;
60425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  g1->highpc = g2->highpc;
60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  result = 0;
60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = g1->lowpc < g2->lowpc ? -1 : 1;
60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
61525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
61625b3c049e70834cf33790a28643ab058b507b35cBen Chengget_var_range (Dwarf_Die *die, Dwarf_Word *lowpc, Dwarf_Word *highpc)
61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Attribute locattr_mem;
61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Attribute *locattr = dwarf_attr (die, DW_AT_location, &locattr_mem);
62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if  (locattr == NULL)
62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 1;
62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Op *loc;
62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nloc;
62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (dwarf_getlocation (locattr, &loc, &nloc) != 0)
62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 1;
62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Interpret the location expressions.  */
62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  // XXX For now just the simple one:
63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (nloc == 1 && loc[0].atom == DW_OP_addr)
63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *lowpc = *highpc = loc[0].number;
63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 0;
63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 1;
63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
64125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void *local_root;
64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
64425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
64525b3c049e70834cf33790a28643ab058b507b35cBen Chengget_local_names (Dwarf *dbg)
64625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off offset = 0;
64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off old_offset;
64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t hsize;
65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (dwarf_nextcu (dbg, old_offset = offset, &offset, &hsize, NULL, NULL,
65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       NULL) == 0)
65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Die cudie_mem;
65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Die *cudie = dwarf_offdie (dbg, old_offset + hsize, &cudie_mem);
65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If we cannot get the CU DIE there is no need to go on with
65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 this CU.  */
65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cudie == NULL)
66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This better be a CU DIE.  */
66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (dwarf_tag (cudie) != DW_TAG_compile_unit)
66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get the line information.  */
66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Files *files;
66725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t nfiles;
66825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (dwarf_getsrcfiles (cudie, &files, &nfiles) != 0)
66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Die die_mem;
67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Die *die = &die_mem;
67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (dwarf_child (cudie, die) == 0)
67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* Iterate over all immediate children of the CU DIE.  */
67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	do
67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    int tag = dwarf_tag (die);
67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (tag != DW_TAG_subprogram && tag != DW_TAG_variable)
67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      continue;
68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* We are interested in five attributes: name, decl_file,
68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       decl_line, low_pc, and high_pc.  */
68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    Dwarf_Attribute attr_mem;
68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    Dwarf_Attribute *attr = dwarf_attr (die, DW_AT_name, &attr_mem);
68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    const char *name = dwarf_formstring (attr);
68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (name == NULL)
68725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      continue;
68825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    Dwarf_Word fileidx;
69025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    attr = dwarf_attr (die, DW_AT_decl_file, &attr_mem);
69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (dwarf_formudata (attr, &fileidx) != 0 || fileidx >= nfiles)
69225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      continue;
69325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    Dwarf_Word lineno;
69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    attr = dwarf_attr (die, DW_AT_decl_line, &attr_mem);
69625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (dwarf_formudata (attr, &lineno) != 0 || lineno == 0)
69725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      continue;
69825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
69925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    Dwarf_Addr lowpc;
70025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    Dwarf_Addr highpc;
70125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (tag == DW_TAG_subprogram)
70225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
70325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (dwarf_lowpc (die, &lowpc) != 0
70425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    || dwarf_highpc (die, &highpc) != 0)
70525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  continue;
70625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
70725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    else
70825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
70925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (get_var_range (die, &lowpc, &highpc) != 0)
71025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  continue;
71125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
71225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
71325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* We have all the information.  Create a record.  */
71425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    struct local_name *newp
71525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      = (struct local_name *) xmalloc (sizeof (*newp));
71625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    newp->name = name;
71725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    newp->file = dwarf_filesrc (files, fileidx, NULL, NULL);
71825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    newp->lineno = lineno;
71925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    newp->lowpc = lowpc;
72025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    newp->highpc = highpc;
72125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
72225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Since we cannot deallocate individual memory we do not test
72325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       for duplicates in the tree.  This should not happen anyway.  */
72425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (tsearch (newp, &local_root, local_compare) == NULL)
72525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (EXIT_FAILURE, errno,
72625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     gettext ("cannot create search tree"));
72725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
72825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	while (dwarf_siblingof (die, die) == 0);
72925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
73025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
73125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
73225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Do elf_strptr, but return a backup string and never NULL.  */
73325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
73425b3c049e70834cf33790a28643ab058b507b35cBen Chengsym_name (Elf *elf, GElf_Word strndx, GElf_Word st_name, char buf[], size_t n)
73525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
73625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *symstr = elf_strptr (elf, strndx, st_name);
73725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (symstr == NULL)
73825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
73925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      snprintf (buf, n, "[invalid st_name %#" PRIx32 "]", st_name);
74025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      symstr = buf;
74125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
74225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return symstr;
74325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
74425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
74525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Show symbols in SysV format.  */
74625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
74725b3c049e70834cf33790a28643ab058b507b35cBen Chengshow_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname,
74825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   GElf_SymX *syms, size_t nsyms, int longest_name,
74925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   int longest_where)
75025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
75125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shnum;
75225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf_getshdrnum (ebl->elf, &shnum) < 0)
75325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    INTERNAL_ERROR (fullname);
75425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
75525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool scnnames_malloced = shnum * sizeof (const char *) > 128 * 1024;
75625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char **scnnames;
75725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (scnnames_malloced)
75825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    scnnames = (const char **) xmalloc (sizeof (const char *) * shnum);
75925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
76025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    scnnames = (const char **) alloca (sizeof (const char *) * shnum);
76125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
76225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
76325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
76425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
76525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
76625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
76725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Cache the section names.  */
76825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
76925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t cnt = 1;
77025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
77125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
77225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
77325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
77425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (elf_ndxscn (scn) == cnt++);
77525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
77625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *name = elf_strptr (ebl->elf, shstrndx,
77725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       gelf_getshdr (scn, &shdr_mem)->sh_name);
77825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (name == NULL))
77925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
78025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  name = alloca (sizeof "[invalid sh_name 0x12345678]");
78125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  snprintf (name, sizeof name, "[invalid sh_name %#" PRIx32 "]",
78225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    gelf_getshdr (scn, &shdr_mem)->sh_name);
78325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
78425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      scnnames[elf_ndxscn (scn)] = name;
78525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
78625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
78725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int digits = length_map[gelf_getclass (ebl->elf) - 1][radix];
78825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
78925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We always print this prolog.  */
79025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\n\nSymbols from %s:\n\n"), fullname);
79125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
79225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* The header line.  */
79325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("%*s%-*s %-*s Class  Type     %-*s %*s Section\n\n"),
79425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_file_name ? (int) strlen (fullname) + 1: 0, "",
79525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  longest_name, sgettext ("sysv|Name"),
79625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* TRANS: the "sysv|" parts makes the string unique.  */
79725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  digits, sgettext ("sysv|Value"),
79825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* TRANS: the "sysv|" parts makes the string unique.  */
79925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  digits, sgettext ("sysv|Size"),
80025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* TRANS: the "sysv|" parts makes the string unique.  */
80125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  longest_where, sgettext ("sysv|Line"));
80225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
80325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Which format string to use (different radix for numbers).  */
80425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *number_fmtstr;
80525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (radix == radix_hex)
80625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    number_fmtstr = "%0*" PRIx64;
80725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (radix == radix_decimal)
80825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    number_fmtstr = "%0*" PRId64;
80925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
81025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    number_fmtstr = "%0*" PRIo64;
81125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
81225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
81325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t demangle_buffer_len = 0;
81425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *demangle_buffer = NULL;
81525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
81625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
81725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Iterate over all symbols.  */
81825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (cnt = 1; cnt < nsyms; ++cnt)
81925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
82025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* In this format SECTION entries are not printed.  */
82125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_SECTION)
82225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
82325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
82425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char symstrbuf[50];
82525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *symstr = sym_name (ebl->elf, strndx, syms[cnt].sym.st_name,
82625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     symstrbuf, sizeof symstrbuf);
82725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
82825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
82925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Demangle if necessary.  */
83025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (demangle)
83125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
83225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int status = -1;
83325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
83425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   &demangle_buffer_len, &status);
83525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
83625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (status == 0)
83725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    symstr = dmsymstr;
83825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
83925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
84025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
84125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char symbindbuf[50];
84225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char symtypebuf[50];
84325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char secnamebuf[1024];
84425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char addressbuf[(64 + 2) / 3 + 1];
84525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char sizebuf[(64 + 2) / 3 + 1];
84625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
84725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If we have to precede the line with the file name.  */
84825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (print_file_name)
84925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
85025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fputs_unlocked (fullname, stdout);
85125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  putchar_unlocked (':');
85225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
85325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
85425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Covert the address.  */
85525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (syms[cnt].sym.st_shndx == SHN_UNDEF)
85625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	addressbuf[0] = sizebuf[0] = '\0';
85725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
85825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
85925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  snprintf (addressbuf, sizeof (addressbuf), number_fmtstr,
86025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    digits, syms[cnt].sym.st_value);
86125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  snprintf (sizebuf, sizeof (sizebuf), number_fmtstr,
86225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    digits, syms[cnt].sym.st_size);
86325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
86425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
86525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Print the actual string.  */
86625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("%-*s|%s|%-6s|%-8s|%s|%*s|%s\n",
86725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      longest_name, symstr, addressbuf,
86825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_symbol_binding_name (ebl,
86925b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       GELF_ST_BIND (syms[cnt].sym.st_info),
87025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       symbindbuf, sizeof (symbindbuf)),
87125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_symbol_type_name (ebl, GELF_ST_TYPE (syms[cnt].sym.st_info),
87225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    symtypebuf, sizeof (symtypebuf)),
87325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      sizebuf, longest_where, syms[cnt].where,
87425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_section_name (ebl, syms[cnt].sym.st_shndx, syms[cnt].xndx,
87525b3c049e70834cf33790a28643ab058b507b35cBen Cheng				secnamebuf, sizeof (secnamebuf), scnnames,
87625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				shnum));
87725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
87825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
87925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
88025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (demangle_buffer);
88125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
88225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
88325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (scnnames_malloced)
88425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    free (scnnames);
88525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
88625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
88725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
88825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic char
88925b3c049e70834cf33790a28643ab058b507b35cBen Chengclass_type_char (Elf *elf, const GElf_Ehdr *ehdr, GElf_Sym *sym)
89025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
89125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int local_p = GELF_ST_BIND (sym->st_info) == STB_LOCAL;
89225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
89325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* XXX Add support for architecture specific types and classes.  */
89425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (sym->st_shndx == SHN_ABS)
89525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return local_p ? 'a' : 'A';
89625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
89725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (sym->st_shndx == SHN_UNDEF)
89825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* Undefined symbols must be global.  */
89925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 'U';
90025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
90125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char result = "NDTSFBD         "[GELF_ST_TYPE (sym->st_info)];
90225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
90325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (result == 'D')
90425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
90525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Special handling: unique data symbols.  */
90625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX
90725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && GELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
90825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = 'u';
90925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
91025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
91125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr shdr_mem;
91225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, sym->st_shndx),
91325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					  &shdr_mem);
91425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr != NULL)
91525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
91625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if ((shdr->sh_flags & SHF_WRITE) == 0)
91725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		result = 'R';
91825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else if (shdr->sh_type == SHT_NOBITS)
91925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		result = 'B';
92025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
92125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
92225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
92325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
92425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return local_p ? tolower (result) : result;
92525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
92625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
92725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
92825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
92925b3c049e70834cf33790a28643ab058b507b35cBen Chengshow_symbols_bsd (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
93025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  const char *prefix, const char *fname, const char *fullname,
93125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_SymX *syms, size_t nsyms)
93225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
93325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int digits = length_map[gelf_getclass (elf) - 1][radix];
93425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
93525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (prefix != NULL && ! print_file_name)
93625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf ("\n%s:\n", fname);
93725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
93825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const fmtstrs[] =
93925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
94025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [radix_hex] = "%8$s%2$0*1$" PRIx64 "%10$s %9$s%3$c%4$s %5$s",
94125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [radix_decimal] = "%8$s%*" PRId64 "%10$s %9$s%3$c%4$s %5$s",
94225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [radix_octal] = "%8$s%2$0*1$" PRIo64 "%10$s %9$s%3$c%4$s %5$s"
94325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
94425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const sfmtstrs[] =
94525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
94625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [radix_hex] = "%8$s%2$0*1$" PRIx64 "%10$s %7$0*6$" PRIx64 " %9$s%3$c%4$s %5$s",
94725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [radix_decimal] = "%8$s%2$*1$" PRId64 "%10$s %7$*6$" PRId64 " %9$s%3$c%4$s %5$s",
94825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [radix_octal] = "%8$s%2$0*1$" PRIo64 "%10$s %7$0*6$" PRIo64 " %9$s%3$c%4$s %5$s"
94925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
95025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
95125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
95225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t demangle_buffer_len = 0;
95325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *demangle_buffer = NULL;
95425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
95525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
95625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Iterate over all symbols.  */
95725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t cnt = 0; cnt < nsyms; ++cnt)
95825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
95925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char symstrbuf[50];
96025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
96125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     symstrbuf, sizeof symstrbuf);
96225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
96325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Printing entries with a zero-length name makes the output
96425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 not very well parseable.  Since these entries don't carry
96525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 much information we leave them out.  */
96625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (symstr[0] == '\0')
96725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
96825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
96925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We do not print the entries for files.  */
97025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_FILE)
97125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
97225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
97325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
97425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Demangle if necessary.  */
97525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (demangle)
97625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
97725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int status = -1;
97825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
97925b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   &demangle_buffer_len, &status);
98025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
98125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (status == 0)
98225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    symstr = dmsymstr;
98325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
98425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
98525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
98625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If we have to precede the line with the file name.  */
98725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (print_file_name)
98825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
98925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fputs_unlocked (fullname, stdout);
99025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  putchar_unlocked (':');
99125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
99225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
99325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool is_tls = GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS;
99425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool is_weak = GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK;
99525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *marker = (mark_special
99625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    ? (is_tls ? "@" : (is_weak ? "*" : " ")) : "");
99725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
99825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (syms[cnt].sym.st_shndx == SHN_UNDEF)
99925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
100025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *color = "";
100125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (color_mode)
100225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
100325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (is_tls)
100425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		color = color_undef_tls;
100525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else if (is_weak)
100625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		color = color_undef_weak;
100725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
100825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		color = color_undef;
100925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
101025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
101125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s %sU%s %s", digits, "", color, marker, symstr);
101225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
101325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
101425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
101525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *color = "";
101625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (color_mode)
101725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
101825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (is_tls)
101925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		color = color_tls;
102025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else if (is_weak)
102125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		color = color_weak;
102225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
102325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		color = color_symbol;
102425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
102525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
102625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (print_size && syms[cnt].sym.st_size != 0
102725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ? sfmtstrs[radix] : fmtstrs[radix],
102825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  digits, syms[cnt].sym.st_value,
102925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  class_type_char (elf, ehdr, &syms[cnt].sym), marker,
103025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  symstr,
103125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  digits, (uint64_t) syms[cnt].sym.st_size,
103225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  color_mode ? color_address : "",
103325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  color,
103425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  color_mode ? color_off : "");
103525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
103625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
103725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (color_mode)
103825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	fputs_unlocked (color_off, stdout);
103925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      putchar_unlocked ('\n');
104025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
104125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
104225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
104325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (demangle_buffer);
104425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
104525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
104625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
104725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
104825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
104925b3c049e70834cf33790a28643ab058b507b35cBen Chengshow_symbols_posix (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
105025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    const char *prefix, const char *fullname, GElf_SymX *syms,
105125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    size_t nsyms)
105225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
105325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (prefix != NULL && ! print_file_name)
105425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf ("%s:\n", fullname);
105525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
105625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *fmtstr;
105725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (radix == radix_hex)
105825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    fmtstr = "%s %c%s %0*" PRIx64 " %0*" PRIx64 "\n";
105925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (radix == radix_decimal)
106025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    fmtstr = "%s %c%s %*" PRId64 " %*" PRId64 "\n";
106125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
106225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    fmtstr = "%s %c%s %0*" PRIo64 " %0*" PRIo64 "\n";
106325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
106425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int digits = length_map[gelf_getclass (elf) - 1][radix];
106525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
106625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
106725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t demangle_buffer_len = 0;
106825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *demangle_buffer = NULL;
106925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
107025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
107125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Iterate over all symbols.  */
107225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t cnt = 0; cnt < nsyms; ++cnt)
107325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
107425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char symstrbuf[50];
107525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
107625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     symstrbuf, sizeof symstrbuf);
107725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
107825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Printing entries with a zero-length name makes the output
107925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 not very well parseable.  Since these entries don't carry
108025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 much information we leave them out.  */
108125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (symstr[0] == '\0')
108225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
108325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
108425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
108525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Demangle if necessary.  */
108625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (demangle)
108725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
108825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int status = -1;
108925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
109025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   &demangle_buffer_len, &status);
109125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
109225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (status == 0)
109325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    symstr = dmsymstr;
109425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
109525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
109625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
109725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If we have to precede the line with the file name.  */
109825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (print_file_name)
109925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
110025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fputs_unlocked (fullname, stdout);
110125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  putchar_unlocked (':');
110225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  putchar_unlocked (' ');
110325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
110425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
110525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (fmtstr,
110625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      symstr,
110725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      class_type_char (elf, ehdr, &syms[cnt].sym),
110825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      mark_special
110925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ? (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS
111025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 ? "@"
111125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 : (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK
111225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    ? "*" : " "))
111325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      : "",
111425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      digits, syms[cnt].sym.st_value,
111525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      digits, syms[cnt].sym.st_size);
111625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
111725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
111825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
111925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (demangle_buffer);
112025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
112125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
112225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
112325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
112425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Maximum size of memory we allocate on the stack.  */
112525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MAX_STACK_ALLOC	65536
112625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
112725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
112825b3c049e70834cf33790a28643ab058b507b35cBen Chengsort_by_address (const void *p1, const void *p2)
112925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
113025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_SymX *s1 = (GElf_SymX *) p1;
113125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_SymX *s2 = (GElf_SymX *) p2;
113225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
113325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int result = (s1->sym.st_value < s2->sym.st_value
113425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		? -1 : (s1->sym.st_value == s2->sym.st_value ? 0 : 1));
113525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
113625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return reverse_sort ? -result : result;
113725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
113825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
113925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Elf_Data *sort_by_name_strtab;
114025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
114125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
114225b3c049e70834cf33790a28643ab058b507b35cBen Chengsort_by_name (const void *p1, const void *p2)
114325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
114425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_SymX *s1 = (GElf_SymX *) p1;
114525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_SymX *s2 = (GElf_SymX *) p2;
114625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
114725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *n1 = sort_by_name_strtab->d_buf + s1->sym.st_name;
114825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *n2 = sort_by_name_strtab->d_buf + s2->sym.st_name;
114925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
115025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int result = strcmp (n1, n2);
115125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
115225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return reverse_sort ? -result : result;
115325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
115425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
115525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
115625b3c049e70834cf33790a28643ab058b507b35cBen Chengshow_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn,
115725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Shdr *shdr, const char *prefix, const char *fname,
115825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      const char *fullname)
115925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
116025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
116125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
116225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
116325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
116425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
116525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
116625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* The section is that large.  */
116725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t size = shdr->sh_size;
116825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* One entry is this large.  */
116925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t entsize = shdr->sh_entsize;
117025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
117125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Consistency checks.  */
117225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, ehdr->e_version))
117325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (0, 0,
117425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("%s: entry size in section `%s' is not what we expect"),
117525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   fullname, elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
117625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (size % entsize != 0)
117725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (0, 0,
117825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("%s: size of section `%s' is not multiple of entry size"),
117925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   fullname, elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
118025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
118125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Compute number of entries.  Handle buggy entsize values.  */
118225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nentries = size / (entsize ?: 1);
118325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
118425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
118525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define obstack_chunk_alloc xmalloc
118625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define obstack_chunk_free free
118725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct obstack whereob;
118825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  obstack_init (&whereob);
118925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
119025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get a DWARF debugging descriptor.  It's no problem if this isn't
119125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     possible.  We just won't print any line number information.  */
119225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf *dbg = NULL;
119325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (format == format_sysv)
119425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
119525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
119625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (dbg != NULL)
119725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
119825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (void) dwarf_getpubnames (dbg, get_global, NULL, 0);
119925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
120025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_local_names (dbg);
120125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
120225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
120325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
120425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Allocate the memory.
120525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
120625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     XXX We can use a dirty trick here.  Since GElf_Sym == Elf64_Sym we
120725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     can use the data memory instead of copying again if what we read
120825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     is a 64 bit file.  */
120925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_SymX *sym_mem;
121025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (nentries * sizeof (GElf_SymX) < MAX_STACK_ALLOC)
121125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    sym_mem = (GElf_SymX *) alloca (nentries * sizeof (GElf_SymX));
121225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
121325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    sym_mem = (GElf_SymX *) xmalloc (nentries * sizeof (GElf_SymX));
121425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
121525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
121625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
121725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *xndxdata = elf_getdata (xndxscn, NULL);
121825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL || (xndxscn != NULL && xndxdata == NULL))
121925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    INTERNAL_ERROR (fullname);
122025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
122125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Iterate over all symbols.  */
122225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
122325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t demangle_buffer_len = 0;
122425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *demangle_buffer = NULL;
122525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
122625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int longest_name = 4;
122725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int longest_where = 4;
122825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nentries_used = 0;
122925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t cnt = 0; cnt < nentries; ++cnt)
123025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
123125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, cnt,
123225b3c049e70834cf33790a28643ab058b507b35cBen Cheng					&sym_mem[nentries_used].sym,
123325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					&sym_mem[nentries_used].xndx);
123425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (sym == NULL)
123525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	INTERNAL_ERROR (fullname);
123625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
123725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Filter out administrative symbols without a name and those
123825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 deselected by the user with command line options.  */
123925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((hide_undefined && sym->st_shndx == SHN_UNDEF)
124025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || (hide_defined && sym->st_shndx != SHN_UNDEF)
124125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || (hide_local && GELF_ST_BIND (sym->st_info) == STB_LOCAL))
124225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
124325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
124425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      sym_mem[nentries_used].where = "";
124525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (format == format_sysv)
124625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
124725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *symstr = elf_strptr (ebl->elf, shdr->sh_link,
124825b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   sym->st_name);
124925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (symstr == NULL)
125025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    continue;
125125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
125225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
125325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Demangle if necessary.  */
125425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (demangle)
125525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
125625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      int status = -1;
125725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
125825b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       &demangle_buffer_len, &status);
125925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
126025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (status == 0)
126125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		symstr = dmsymstr;
126225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
126325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
126425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
126525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  longest_name = MAX ((size_t) longest_name, strlen (symstr));
126625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
126725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (sym->st_shndx != SHN_UNDEF
126825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && GELF_ST_BIND (sym->st_info) != STB_LOCAL
126925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && global_root != NULL)
127025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
127125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      Dwarf_Global fake = { .name = symstr };
127225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      Dwarf_Global **found = tfind (&fake, &global_root,
127325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    global_compare);
127425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (found != NULL)
127525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
127625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  Dwarf_Die die_mem;
127725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  Dwarf_Die *die = dwarf_offdie (dbg, (*found)->die_offset,
127825b3c049e70834cf33790a28643ab058b507b35cBen Cheng						 &die_mem);
127925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
128025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  Dwarf_Die cudie_mem;
128125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  Dwarf_Die *cudie = NULL;
128225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
128325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  Dwarf_Addr lowpc;
128425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  Dwarf_Addr highpc;
128525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (die != NULL
128625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      && dwarf_lowpc (die, &lowpc) == 0
128725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      && lowpc <= sym->st_value
128825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      && dwarf_highpc (die, &highpc) == 0
128925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      && highpc > sym->st_value)
129025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    cudie = dwarf_offdie (dbg, (*found)->cu_offset,
129125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					  &cudie_mem);
129225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (cudie != NULL)
129325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
129425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      Dwarf_Line *line = dwarf_getsrc_die (cudie,
129525b3c049e70834cf33790a28643ab058b507b35cBen Cheng							   sym->st_value);
129625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (line != NULL)
129725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
129825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  /* We found the line.  */
129925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  int lineno;
130025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (void) dwarf_lineno (line, &lineno);
130125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  int n;
130225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  n = obstack_printf (&whereob, "%s:%d%c",
130325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      basename (dwarf_linesrc (line,
130425b3c049e70834cf33790a28643ab058b507b35cBen Cheng								       NULL,
130525b3c049e70834cf33790a28643ab058b507b35cBen Cheng								       NULL)),
130625b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      lineno, '\0');
130725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  sym_mem[nentries_used].where
130825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    = obstack_finish (&whereob);
130925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
131025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  /* The return value of obstack_print included the
131125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     NUL byte, so subtract one.  */
131225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  if (--n > (int) longest_where)
131325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    longest_where = (size_t) n;
131425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
131525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
131625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
131725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
131825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
131925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Try to find the symbol among the local symbols.  */
132025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (sym_mem[nentries_used].where[0] == '\0')
132125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
132225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      struct local_name fake =
132325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
132425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  .name = symstr,
132525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  .lowpc = sym->st_value,
132625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  .highpc = sym->st_value,
132725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		};
132825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      struct local_name **found = tfind (&fake, &local_root,
132925b3c049e70834cf33790a28643ab058b507b35cBen Cheng						 local_compare);
133025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (found != NULL)
133125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
133225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* We found the line.  */
133325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  int n = obstack_printf (&whereob, "%s:%" PRIu64 "%c",
133425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					  basename ((*found)->file),
133525b3c049e70834cf33790a28643ab058b507b35cBen Cheng					  (*found)->lineno,
133625b3c049e70834cf33790a28643ab058b507b35cBen Cheng					  '\0');
133725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  sym_mem[nentries_used].where = obstack_finish (&whereob);
133825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
133925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* The return value of obstack_print included the
134025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     NUL byte, so subtract one.  */
134125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (--n > (int) longest_where)
134225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    longest_where = (size_t) n;
134325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
134425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
134525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
134625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
134725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We use this entry.  */
134825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++nentries_used;
134925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
135025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef USE_DEMANGLE
135125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (demangle_buffer);
135225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
135325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Now we know the exact number.  */
135425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  nentries = nentries_used;
135525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
135625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Sort the entries according to the users wishes.  */
135725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (sort == sort_name)
135825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
135925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      sort_by_name_strtab = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link),
136025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 NULL);
136125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_name);
136225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
136325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (sort == sort_numeric)
136425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_address);
136525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
136625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Finally print according to the users selection.  */
136725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (format)
136825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
136925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case format_sysv:
137025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      show_symbols_sysv (ebl, shdr->sh_link, fullname, sym_mem, nentries,
137125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 longest_name, longest_where);
137225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
137325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
137425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case format_bsd:
137525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      show_symbols_bsd (ebl->elf, ehdr, shdr->sh_link, prefix, fname, fullname,
137625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			sym_mem, nentries);
137725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
137825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
137925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case format_posix:
138025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
138125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (format == format_posix);
138225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      show_symbols_posix (ebl->elf, ehdr, shdr->sh_link, prefix, fullname,
138325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  sym_mem, nentries);
138425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
138525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
138625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
138725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Free all memory.  */
138825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (nentries * sizeof (GElf_Sym) >= MAX_STACK_ALLOC)
138925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    free (sym_mem);
139025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
139125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  obstack_free (&whereob, NULL);
139225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
139325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (dbg != NULL)
139425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
139525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      tdestroy (global_root, free);
139625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      global_root = NULL;
139725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
139825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      tdestroy (local_root, free);
139925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      local_root = NULL;
140025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
140125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      (void) dwarf_end (dbg);
140225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
140325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
140425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
140525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
140625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
140725b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_elf (Elf *elf, const char *prefix, const char *fname,
140825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    const char *suffix)
140925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
141025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
141125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
141225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t fname_len = strlen (fname) + 1;
141325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char fullname[prefix_len + 1 + fname_len + suffix_len];
141425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *cp = fullname;
141525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
141625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int any = 0;
141725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int result = 0;
141825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Ehdr ehdr_mem;
141925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Ehdr *ehdr;
142025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Ebl *ebl;
142125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
142225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the backend for this object file type.  */
142325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ebl = ebl_openbackend (elf);
142425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
142525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We need the ELF header in a few places.  */
142625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ehdr = gelf_getehdr (elf, &ehdr_mem);
142725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr == NULL)
142825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    INTERNAL_ERROR (fullname);
142925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
143025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If we are asked to print the dynamic symbol table and this is
143125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     executable or dynamic executable, fail.  */
143225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (symsec_type == SHT_DYNSYM
143325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
143425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
143525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* XXX Add machine specific object file types.  */
143625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("%s%s%s%s: Invalid operation"),
143725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     prefix ?: "", prefix ? "(" : "", fname, prefix ? ")" : "");
143825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result = 1;
143925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      goto out;
144025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
144125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
144225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Create the full name of the file.  */
144325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (prefix != NULL)
144425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    cp = mempcpy (cp, prefix, prefix_len);
144525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  cp = mempcpy (cp, fname, fname_len);
144625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (suffix != NULL)
144725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    memcpy (cp - 1, suffix, suffix_len + 1);
144825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
144925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find the symbol table.
145025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
145125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     XXX Can there be more than one?  Do we print all?  Currently we do.  */
145225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (elf, scn)) != NULL)
145325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
145425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
145525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
145625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
145725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr == NULL)
145825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	INTERNAL_ERROR (fullname);
145925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
146025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_type == symsec_type)
146125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
146225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Scn *xndxscn = NULL;
146325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
146425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We have a symbol table.  First make sure we remember this.  */
146525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  any = 1;
146625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
146725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Look for an extended section index table for this section.  */
146825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (symsec_type == SHT_SYMTAB)
146925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
147025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      size_t scnndx = elf_ndxscn (scn);
147125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
147225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      while ((xndxscn = elf_nextscn (elf, xndxscn)) != NULL)
147325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
147425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Shdr xndxshdr_mem;
147525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
147625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
147725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (xndxshdr == NULL)
147825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    INTERNAL_ERROR (fullname);
147925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
148025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
148125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      && xndxshdr->sh_link == scnndx)
148225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    break;
148325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
148425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
148525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
148625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  show_symbols (ebl, ehdr, scn, xndxscn, shdr, prefix, fname,
148725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			fullname);
148825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
148925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
149025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
149125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (! any)
149225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
149325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("%s%s%s: no symbols"),
149425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     prefix ?: "", prefix ? ":" : "", fname);
149525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result = 1;
149625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
149725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
149825b3c049e70834cf33790a28643ab058b507b35cBen Cheng out:
149925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Close the ELF backend library descriptor.  */
150025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ebl_closebackend (ebl);
150125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
150225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
150325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
150425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
150525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
150625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "debugpred.h"
1507