125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print size information from ELF file. 203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Copyright (C) 2000-2007,2009,2012,2014 Red Hat, Inc. 303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is part of elfutils. 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Written by Ulrich Drepper <drepper@redhat.com>, 2000. 525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is free software; you can redistribute it and/or modify 703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes it under the terms of the GNU General Public License as published by 803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the Free Software Foundation; either version 3 of the License, or 903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes (at your option) any later version. 1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elfutils is distributed in the hope that it will be useful, but 1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GNU General Public License for more details. 1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes You should have received a copy of the GNU General Public License 1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H 2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h> 2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <argp.h> 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <error.h> 2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <fcntl.h> 2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <gelf.h> 2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <inttypes.h> 2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libelf.h> 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libintl.h> 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <locale.h> 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <mcheck.h> 3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h> 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdio.h> 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdio_ext.h> 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h> 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h> 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h> 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h> 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <system.h> 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Name and version of program. */ 4425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_version (FILE *stream, struct argp_state *state); 4525b3c049e70834cf33790a28643ab058b507b35cBen ChengARGP_PROGRAM_VERSION_HOOK_DEF = print_version; 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Bug report address. */ 4825b3c049e70834cf33790a28643ab058b507b35cBen ChengARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Values for the parameters which have no short form. */ 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define OPT_FORMAT 0x100 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define OPT_RADIX 0x101 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Definitions of arguments for argp functions. */ 5625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct argp_option options[] = 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { NULL, 0, NULL, 0, N_("Output format:"), 0 }, 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { "format", OPT_FORMAT, "FORMAT", 0, 6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng N_("Use the output format FORMAT. FORMAT can be `bsd' or `sysv'. " 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng "The default is `bsd'"), 0 }, 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { NULL, 'A', NULL, 0, N_("Same as `--format=sysv'"), 0 }, 6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { NULL, 'B', NULL, 0, N_("Same as `--format=bsd'"), 0 }, 6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { "radix", OPT_RADIX, "RADIX", 0, N_("Use RADIX for printing symbol values"), 6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 0}, 6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { NULL, 'd', NULL, 0, N_("Same as `--radix=10'"), 0 }, 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { NULL, 'o', NULL, 0, N_("Same as `--radix=8'"), 0 }, 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { NULL, 'x', NULL, 0, N_("Same as `--radix=16'"), 0 }, 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { NULL, 'f', NULL, 0, 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng N_("Similar to `--format=sysv' output but in one line"), 0 }, 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { NULL, 0, NULL, 0, N_("Output options:"), 0 }, 7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { NULL, 'F', NULL, 0, 7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng N_("Print size and permission flags for loadable segments"), 0 }, 7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { "totals", 't', NULL, 0, N_("Display the total sizes (bsd only)"), 0 }, 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { NULL, 0, NULL, 0, NULL, 0 } 7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}; 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Short description of program. */ 8025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char doc[] = N_("\ 8125b3c049e70834cf33790a28643ab058b507b35cBen ChengList section sizes of FILEs (a.out by default)."); 8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Strings for arguments in help texts. */ 8425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char args_doc[] = N_("[FILE...]"); 8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Prototype for option handler. */ 8725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic error_t parse_opt (int key, char *arg, struct argp_state *state); 8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Data structure to communicate with argp functions. */ 9025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct argp argp = 9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng options, parse_opt, args_doc, doc, NULL, NULL, NULL 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}; 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print symbols in file named FNAME. */ 9725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int process_file (const char *fname); 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle content of archive. */ 10025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname); 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle ELF file. */ 10325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_elf (Elf *elf, const char *fullname, const char *fname); 10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Show total size. */ 10625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void show_bsd_totals (void); 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define INTERNAL_ERROR(fname) \ 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \ 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1)) 11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* User-selectable options. */ 11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* The selected output format. */ 11625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic enum 11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng format_bsd = 0, 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng format_sysv, 12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng format_sysv_one_line, 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng format_segments 12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} format; 12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Radix for printed numbers. */ 12525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic enum 12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng radix_decimal = 0, 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng radix_hex, 12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng radix_octal 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} radix; 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Mapping of radix and binary class to length. */ 13425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const int length_map[2][3] = 13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng [ELFCLASS32 - 1] = 13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng [radix_hex] = 8, 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng [radix_decimal] = 10, 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng [radix_octal] = 11 14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng }, 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng [ELFCLASS64 - 1] = 14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng [radix_hex] = 16, 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng [radix_decimal] = 20, 14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng [radix_octal] = 22 14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}; 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if total sizes should be printed. */ 15125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool totals; 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* To print the total sizes in a reasonable format remember the higest 15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng "class" of ELF binaries processed. */ 15425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int totals_class; 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15725b3c049e70834cf33790a28643ab058b507b35cBen Chengint 15825b3c049e70834cf33790a28643ab058b507b35cBen Chengmain (int argc, char *argv[]) 15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int remaining; 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng int result = 0; 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make memory leak detection possible. */ 16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng mtrace (); 16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We use no threads here which can interfere with handling a stream. */ 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng __fsetlocking (stdin, FSETLOCKING_BYCALLER); 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng __fsetlocking (stdout, FSETLOCKING_BYCALLER); 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng __fsetlocking (stderr, FSETLOCKING_BYCALLER); 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Set locale. */ 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng setlocale (LC_ALL, ""); 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make sure the message catalog can be found. */ 17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng bindtextdomain (PACKAGE_TARNAME, LOCALEDIR); 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Initialize the message catalog. */ 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng textdomain (PACKAGE_TARNAME); 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Parse and process arguments. */ 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng argp_parse (&argp, argc, argv, 0, &remaining, NULL); 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Tell the library which version we are expecting. */ 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_version (EV_CURRENT); 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (remaining == argc) 18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The user didn't specify a name so we use a.out. */ 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng result = process_file ("a.out"); 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Process all the remaining files. */ 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng do 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng result |= process_file (argv[remaining]); 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (++remaining < argc); 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Print the total sizes but only if the output format is BSD and at 19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng least one file has been correctly read (i.e., we recognized the 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng class). */ 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (totals && format == format_bsd && totals_class != 0) 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng show_bsd_totals (); 20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return result; 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the version information. */ 20725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 20825b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused))) 20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng fprintf (stream, "size (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng fprintf (stream, gettext ("\ 21225b3c049e70834cf33790a28643ab058b507b35cBen ChengCopyright (C) %s Red Hat, Inc.\n\ 21325b3c049e70834cf33790a28643ab058b507b35cBen ChengThis is free software; see the source for copying conditions. There is NO\n\ 21425b3c049e70834cf33790a28643ab058b507b35cBen Chengwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng"), "2012"); 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle program arguments. */ 22125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic error_t 22225b3c049e70834cf33790a28643ab058b507b35cBen Chengparse_opt (int key, char *arg, 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct argp_state *state __attribute__ ((unused))) 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (key) 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'd': 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng radix = radix_decimal; 22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'f': 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng format = format_sysv_one_line; 23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'o': 23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng radix = radix_octal; 23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'x': 24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng radix = radix_hex; 24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'A': 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng format = format_sysv; 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'B': 24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng format = format_bsd; 24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'F': 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng format = format_segments; 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case OPT_FORMAT: 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strcmp (arg, "bsd") == 0 || strcmp (arg, "berkeley") == 0) 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng format = format_bsd; 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (likely (strcmp (arg, "sysv") == 0)) 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng format = format_sysv; 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng error (EXIT_FAILURE, 0, gettext ("Invalid format: %s"), arg); 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng case OPT_RADIX: 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strcmp (arg, "x") == 0 || strcmp (arg, "16") == 0) 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng radix = radix_hex; 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (strcmp (arg, "d") == 0 || strcmp (arg, "10") == 0) 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng radix = radix_decimal; 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (strcmp (arg, "o") == 0 || strcmp (arg, "8") == 0) 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng radix = radix_octal; 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng error (EXIT_FAILURE, 0, gettext ("Invalid radix: %s"), arg); 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 't': 27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng totals = true; 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return ARGP_ERR_UNKNOWN; 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Open the file and determine the type. */ 28725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 28825b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_file (const char *fname) 28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int fd = open (fname, O_RDONLY); 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (fd == -1)) 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng error (0, errno, gettext ("cannot open '%s'"), fname); 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Now get the ELF descriptor. */ 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL); 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely (elf != NULL)) 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf_kind (elf) == ELF_K_ELF) 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng handle_elf (elf, NULL, fname); 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (elf_end (elf) != 0)) 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng INTERNAL_ERROR (fname); 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (close (fd) != 0)) 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname); 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (likely (elf_kind (elf) == ELF_K_AR)) 31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng int result = handle_ar (fd, elf, NULL, fname); 31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (close (fd) != 0)) 31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname); 31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return result; 32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We cannot handle this type. Close the descriptor anyway. */ 32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (elf_end (elf) != 0)) 32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng INTERNAL_ERROR (fname); 32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (close (fd) != 0)) 32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname); 33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng error (0, 0, gettext ("%s: file format not recognized"), fname); 33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the BSD-style header. This is done exactly once. */ 33825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 33925b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_header (Elf *elf) 34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng static int done; 34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (! done) 34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng int ddigits = length_map[gelf_getclass (elf) - 1][radix_decimal]; 34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng int xdigits = length_map[gelf_getclass (elf) - 1][radix_hex]; 34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf ("%*s %*s %*s %*s %*s %s\n", 34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ddigits - 2, sgettext ("bsd|text"), 35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ddigits - 2, sgettext ("bsd|data"), 35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ddigits - 2, sgettext ("bsd|bss"), 35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ddigits - 2, sgettext ("bsd|dec"), 35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng xdigits - 2, sgettext ("bsd|hex"), 35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sgettext ("bsd|filename")); 35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng done = 1; 35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 36225b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_ar (int fd, Elf *elf, const char *prefix, const char *fname) 36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t prefix_len = prefix == NULL ? 0 : strlen (prefix); 36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t fname_len = strlen (fname) + 1; 36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng char new_prefix[prefix_len + 1 + fname_len]; 36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *cp = new_prefix; 36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Create the full name of the file. */ 37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefix != NULL) 37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng cp = mempcpy (cp, prefix, prefix_len); 37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = ':'; 37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (cp, fname, fname_len); 37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Process all the files contained in the archive. */ 37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int result = 0; 37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *subelf; 38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Cmd cmd = ELF_C_READ_MMAP; 38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((subelf = elf_begin (fd, cmd, elf)) != NULL) 38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The the header for this element. */ 38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Arhdr *arhdr = elf_getarhdr (subelf); 38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf_kind (subelf) == ELF_K_ELF) 38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng handle_elf (subelf, new_prefix, arhdr->ar_name); 38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (likely (elf_kind (subelf) == ELF_K_AR)) 38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name); 39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* else signal error??? */ 39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get next archive element. */ 39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng cmd = elf_next (subelf); 39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (elf_end (subelf) != 0)) 39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng INTERNAL_ERROR (fname); 39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (elf_end (elf) != 0)) 39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng INTERNAL_ERROR (fname); 40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return result; 40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Show sizes in SysV format. */ 40625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 40725b3c049e70834cf33790a28643ab058b507b35cBen Chengshow_sysv (Elf *elf, const char *prefix, const char *fname, 40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *fullname) 40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int maxlen = 10; 41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const int digits = length_map[gelf_getclass (elf) - 1][radix]; 41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get the section header string table index. */ 41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t shstrndx; 41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0)) 41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng error (EXIT_FAILURE, 0, 41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng gettext ("cannot get section header string table index")); 41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* First round over the sections: determine the longest section name. */ 42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = NULL; 42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((scn = elf_nextscn (elf, scn)) != NULL) 42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr == NULL) 42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng INTERNAL_ERROR (fullname); 42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Ignore all sections which are not used at runtime. */ 43003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const char *name = elf_strptr (elf, shstrndx, shdr->sh_name); 43103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (name != NULL && (shdr->sh_flags & SHF_ALLOC) != 0) 43203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes maxlen = MAX (maxlen, (int) strlen (name)); 43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng fputs_unlocked (fname, stdout); 43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefix != NULL) 43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf (gettext (" (ex %s)"), prefix); 43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf (":\n%-*s %*s %*s\n", 43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng maxlen, sgettext ("sysv|section"), 44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng digits - 2, sgettext ("sysv|size"), 44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng digits, sgettext ("sysv|addr")); 44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Iterate over all sections. */ 44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off total = 0; 44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((scn = elf_nextscn (elf, scn)) != NULL) 44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Ignore all sections which are not used at runtime. */ 45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((shdr->sh_flags & SHF_ALLOC) != 0) 45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 45303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ((radix == radix_hex 45403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes ? "%-*s %*" PRIx64 " %*" PRIx64 "\n" 45503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes : (radix == radix_decimal 45603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes ? "%-*s %*" PRId64 " %*" PRId64 "\n" 45703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes : "%-*s %*" PRIo64 " %*" PRIo64 "\n")), 45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng maxlen, elf_strptr (elf, shstrndx, shdr->sh_name), 45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng digits - 2, shdr->sh_size, 46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng digits, shdr->sh_addr); 46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng total += shdr->sh_size; 46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (radix == radix_hex) 46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf ("%-*s %*" PRIx64 "\n\n\n", maxlen, sgettext ("sysv|Total"), 46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng digits - 2, total); 46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (radix == radix_decimal) 47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf ("%-*s %*" PRId64 "\n\n\n", maxlen, sgettext ("sysv|Total"), 47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng digits - 2, total); 47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf ("%-*s %*" PRIo64 "\n\n\n", maxlen, sgettext ("sysv|Total"), 47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng digits - 2, total); 47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Show sizes in SysV format in one line. */ 47925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 48025b3c049e70834cf33790a28643ab058b507b35cBen Chengshow_sysv_one_line (Elf *elf) 48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get the section header string table index. */ 48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t shstrndx; 48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0)) 48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng error (EXIT_FAILURE, 0, 48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng gettext ("cannot get section header string table index")); 48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Iterate over all sections. */ 48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off total = 0; 49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool first = true; 49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = NULL; 49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((scn = elf_nextscn (elf, scn)) != NULL) 49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Ignore all sections which are not used at runtime. */ 49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((shdr->sh_flags & SHF_ALLOC) == 0) 49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (! first) 50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng fputs_unlocked (" + ", stdout); 50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng first = false; 50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 50503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ((radix == radix_hex ? "%" PRIx64 "(%s)" 50603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes : (radix == radix_decimal ? "%" PRId64 "(%s)" 50703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes : "%" PRIo64 "(%s)")), 50803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes shdr->sh_size, elf_strptr (elf, shstrndx, shdr->sh_name)); 50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng total += shdr->sh_size; 51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (radix == radix_hex) 51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf (" = %#" PRIx64 "\n", total); 51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (radix == radix_decimal) 51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf (" = %" PRId64 "\n", total); 51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf (" = %" PRIo64 "\n", total); 51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Variables to add up the sizes of all files. */ 52325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic uintmax_t total_textsize; 52425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic uintmax_t total_datasize; 52525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic uintmax_t total_bsssize; 52625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Show sizes in BSD format. */ 52925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 53025b3c049e70834cf33790a28643ab058b507b35cBen Chengshow_bsd (Elf *elf, const char *prefix, const char *fname, 53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *fullname) 53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off textsize = 0; 53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off datasize = 0; 53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off bsssize = 0; 53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng const int ddigits = length_map[gelf_getclass (elf) - 1][radix_decimal]; 53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng const int xdigits = length_map[gelf_getclass (elf) - 1][radix_hex]; 53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Iterate over all sections. */ 54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = NULL; 54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((scn = elf_nextscn (elf, scn)) != NULL) 54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr == NULL) 54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng INTERNAL_ERROR (fullname); 54825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Ignore all sections which are not marked as loaded. */ 55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((shdr->sh_flags & SHF_ALLOC) == 0) 55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((shdr->sh_flags & SHF_WRITE) == 0) 55425b3c049e70834cf33790a28643ab058b507b35cBen Cheng textsize += shdr->sh_size; 55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (shdr->sh_type == SHT_NOBITS) 55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng bsssize += shdr->sh_size; 55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 55825b3c049e70834cf33790a28643ab058b507b35cBen Cheng datasize += shdr->sh_size; 55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf ("%*" PRId64 " %*" PRId64 " %*" PRId64 " %*" PRId64 " %*" 56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng PRIx64 " %s", 56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ddigits - 2, textsize, 56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ddigits - 2, datasize, 56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ddigits - 2, bsssize, 56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ddigits - 2, textsize + datasize + bsssize, 56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng xdigits - 2, textsize + datasize + bsssize, 56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng fname); 56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefix != NULL) 57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf (gettext (" (ex %s)"), prefix); 57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng fputs_unlocked ("\n", stdout); 57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng total_textsize += textsize; 57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng total_datasize += datasize; 57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng total_bsssize += bsssize; 57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng totals_class = MAX (totals_class, gelf_getclass (elf)); 57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Show total size. */ 58225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 58325b3c049e70834cf33790a28643ab058b507b35cBen Chengshow_bsd_totals (void) 58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng int ddigits = length_map[totals_class - 1][radix_decimal]; 58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng int xdigits = length_map[totals_class - 1][radix_hex]; 58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf ("%*" PRIuMAX " %*" PRIuMAX " %*" PRIuMAX " %*" PRIuMAX " %*" 58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng PRIxMAX " %s", 59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ddigits - 2, total_textsize, 59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ddigits - 2, total_datasize, 59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ddigits - 2, total_bsssize, 59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ddigits - 2, total_textsize + total_datasize + total_bsssize, 59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng xdigits - 2, total_textsize + total_datasize + total_bsssize, 59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng gettext ("(TOTALS)\n")); 59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Show size and permission of loadable segments. */ 60025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 60125b3c049e70834cf33790a28643ab058b507b35cBen Chengshow_segments (Elf *elf, const char *fullname) 60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 60303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes size_t phnum; 60403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (elf_getphdrnum (elf, &phnum) != 0) 60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng INTERNAL_ERROR (fullname); 60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off total = 0; 60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool first = true; 60903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes for (size_t cnt = 0; cnt < phnum; ++cnt) 61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr_mem; 61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr *phdr; 61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdr = gelf_getphdr (elf, cnt, &phdr_mem); 61525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr == NULL) 61625b3c049e70834cf33790a28643ab058b507b35cBen Cheng INTERNAL_ERROR (fullname); 61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_type != PT_LOAD) 61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Only load segments. */ 62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (! first) 62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng fputs_unlocked (" + ", stdout); 62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng first = false; 62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf (radix == radix_hex ? "%" PRIx64 "(%c%c%c)" 62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng : (radix == radix_decimal ? "%" PRId64 "(%c%c%c)" 62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng : "%" PRIo64 "(%c%c%c)"), 62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdr->p_memsz, 63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng (phdr->p_flags & PF_R) == 0 ? '-' : 'r', 63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng (phdr->p_flags & PF_W) == 0 ? '-' : 'w', 63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (phdr->p_flags & PF_X) == 0 ? '-' : 'x'); 63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng total += phdr->p_memsz; 63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (radix == radix_hex) 63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf (" = %#" PRIx64 "\n", total); 63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (radix == radix_decimal) 64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf (" = %" PRId64 "\n", total); 64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf (" = %" PRIo64 "\n", total); 64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 64525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 64625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 64725b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_elf (Elf *elf, const char *prefix, const char *fname) 64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t prefix_len = prefix == NULL ? 0 : strlen (prefix); 65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t fname_len = strlen (fname) + 1; 65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng char fullname[prefix_len + 1 + fname_len]; 65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *cp = fullname; 65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Create the full name of the file. */ 65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefix != NULL) 65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng cp = mempcpy (cp, prefix, prefix_len); 65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = ':'; 65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (cp, fname, fname_len); 66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (format == format_sysv) 66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng show_sysv (elf, prefix, fname, fullname); 66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (format == format_sysv_one_line) 66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng show_sysv_one_line (elf); 66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (format == format_segments) 66725b3c049e70834cf33790a28643ab058b507b35cBen Cheng show_segments (elf, fullname); 66825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng print_header (elf); 67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng show_bsd (elf, prefix, fname, fullname); 67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "debugpred.h" 678