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