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