Blame src/size.c

Packit Service 97d2fb
/* Print size information from ELF file.
Packit Service 97d2fb
   Copyright (C) 2000-2007,2009,2012,2014,2015 Red Hat, Inc.
Packit Service 97d2fb
   This file is part of elfutils.
Packit Service 97d2fb
   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
Packit Service 97d2fb
Packit Service 97d2fb
   This file is free software; you can redistribute it and/or modify
Packit Service 97d2fb
   it under the terms of the GNU General Public License as published by
Packit Service 97d2fb
   the Free Software Foundation; either version 3 of the License, or
Packit Service 97d2fb
   (at your option) any later version.
Packit Service 97d2fb
Packit Service 97d2fb
   elfutils is distributed in the hope that it will be useful, but
Packit Service 97d2fb
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 97d2fb
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 97d2fb
   GNU General Public License for more details.
Packit Service 97d2fb
Packit Service 97d2fb
   You should have received a copy of the GNU General Public License
Packit Service 97d2fb
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service 97d2fb
Packit Service 97d2fb
#ifdef HAVE_CONFIG_H
Packit Service 97d2fb
# include <config.h>
Packit Service 97d2fb
#endif
Packit Service 97d2fb
Packit Service 97d2fb
#include <argp.h>
Packit Service 97d2fb
#include <fcntl.h>
Packit Service 97d2fb
#include <gelf.h>
Packit Service 97d2fb
#include <inttypes.h>
Packit Service 97d2fb
#include <libelf.h>
Packit Service 97d2fb
#include <libintl.h>
Packit Service 97d2fb
#include <locale.h>
Packit Service 97d2fb
#include <stdbool.h>
Packit Service 97d2fb
#include <stdio.h>
Packit Service 97d2fb
#include <stdio_ext.h>
Packit Service 97d2fb
#include <stdlib.h>
Packit Service 97d2fb
#include <string.h>
Packit Service 97d2fb
#include <unistd.h>
Packit Service 97d2fb
Packit Service 97d2fb
#include <system.h>
Packit Service 97d2fb
#include <printversion.h>
Packit Service 97d2fb
Packit Service 97d2fb
/* Name and version of program.  */
Packit Service 97d2fb
ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
Packit Service 97d2fb
Packit Service 97d2fb
/* Bug report address.  */
Packit Service 97d2fb
ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Values for the parameters which have no short form.  */
Packit Service 97d2fb
#define OPT_FORMAT	0x100
Packit Service 97d2fb
#define OPT_RADIX	0x101
Packit Service 97d2fb
Packit Service 97d2fb
/* Definitions of arguments for argp functions.  */
Packit Service 97d2fb
static const struct argp_option options[] =
Packit Service 97d2fb
{
Packit Service 97d2fb
  { NULL, 0, NULL, 0, N_("Output format:"), 0 },
Packit Service 97d2fb
  { "format", OPT_FORMAT, "FORMAT", 0,
Packit Service 97d2fb
    N_("Use the output format FORMAT.  FORMAT can be `bsd' or `sysv'.  "
Packit Service 97d2fb
       "The default is `bsd'"), 0 },
Packit Service 97d2fb
  { NULL, 'A', NULL, 0, N_("Same as `--format=sysv'"), 0 },
Packit Service 97d2fb
  { NULL, 'B', NULL, 0, N_("Same as `--format=bsd'"), 0 },
Packit Service 97d2fb
  { "radix", OPT_RADIX, "RADIX", 0, N_("Use RADIX for printing symbol values"),
Packit Service 97d2fb
    0},
Packit Service 97d2fb
  { NULL, 'd', NULL, 0, N_("Same as `--radix=10'"), 0 },
Packit Service 97d2fb
  { NULL, 'o', NULL, 0, N_("Same as `--radix=8'"), 0 },
Packit Service 97d2fb
  { NULL, 'x', NULL, 0, N_("Same as `--radix=16'"), 0 },
Packit Service 97d2fb
  { NULL, 'f', NULL, 0,
Packit Service 97d2fb
    N_("Similar to `--format=sysv' output but in one line"), 0 },
Packit Service 97d2fb
Packit Service 97d2fb
  { NULL, 0, NULL, 0, N_("Output options:"), 0 },
Packit Service 97d2fb
  { NULL, 'F', NULL, 0,
Packit Service 97d2fb
    N_("Print size and permission flags for loadable segments"), 0 },
Packit Service 97d2fb
  { "totals", 't', NULL, 0, N_("Display the total sizes (bsd only)"), 0 },
Packit Service 97d2fb
  { NULL, 0, NULL, 0, NULL, 0 }
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
/* Short description of program.  */
Packit Service 97d2fb
static const char doc[] = N_("\
Packit Service 97d2fb
List section sizes of FILEs (a.out by default).");
Packit Service 97d2fb
Packit Service 97d2fb
/* Strings for arguments in help texts.  */
Packit Service 97d2fb
static const char args_doc[] = N_("[FILE...]");
Packit Service 97d2fb
Packit Service 97d2fb
/* Prototype for option handler.  */
Packit Service 97d2fb
static error_t parse_opt (int key, char *arg, struct argp_state *state);
Packit Service 97d2fb
Packit Service 97d2fb
/* Data structure to communicate with argp functions.  */
Packit Service 97d2fb
static struct argp argp =
Packit Service 97d2fb
{
Packit Service 97d2fb
  options, parse_opt, args_doc, doc, NULL, NULL, NULL
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Print symbols in file named FNAME.  */
Packit Service 97d2fb
static int process_file (const char *fname);
Packit Service 97d2fb
Packit Service 97d2fb
/* Handle content of archive.  */
Packit Service 97d2fb
static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname);
Packit Service 97d2fb
Packit Service 97d2fb
/* Handle ELF file.  */
Packit Service 97d2fb
static void handle_elf (Elf *elf, const char *fullname, const char *fname);
Packit Service 97d2fb
Packit Service 97d2fb
/* Show total size.  */
Packit Service 97d2fb
static void show_bsd_totals (void);
Packit Service 97d2fb
Packit Service 97d2fb
#define INTERNAL_ERROR(fname) \
Packit Service 97d2fb
  error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s): %s"),      \
Packit Service 97d2fb
	 fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1))
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* User-selectable options.  */
Packit Service 97d2fb
Packit Service 97d2fb
/* The selected output format.  */
Packit Service 97d2fb
static enum
Packit Service 97d2fb
{
Packit Service 97d2fb
  format_bsd = 0,
Packit Service 97d2fb
  format_sysv,
Packit Service 97d2fb
  format_sysv_one_line,
Packit Service 97d2fb
  format_segments
Packit Service 97d2fb
} format;
Packit Service 97d2fb
Packit Service 97d2fb
/* Radix for printed numbers.  */
Packit Service 97d2fb
static enum
Packit Service 97d2fb
{
Packit Service 97d2fb
  radix_decimal = 0,
Packit Service 97d2fb
  radix_hex,
Packit Service 97d2fb
  radix_octal
Packit Service 97d2fb
} radix;
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Mapping of radix and binary class to length.  */
Packit Service 97d2fb
static const int length_map[2][3] =
Packit Service 97d2fb
{
Packit Service 97d2fb
  [ELFCLASS32 - 1] =
Packit Service 97d2fb
  {
Packit Service 97d2fb
    [radix_hex] = 8,
Packit Service 97d2fb
    [radix_decimal] = 10,
Packit Service 97d2fb
    [radix_octal] = 11
Packit Service 97d2fb
  },
Packit Service 97d2fb
  [ELFCLASS64 - 1] =
Packit Service 97d2fb
  {
Packit Service 97d2fb
    [radix_hex] = 16,
Packit Service 97d2fb
    [radix_decimal] = 20,
Packit Service 97d2fb
    [radix_octal] = 22
Packit Service 97d2fb
  }
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
/* True if total sizes should be printed.  */
Packit Service 97d2fb
static bool totals;
Packit Service 97d2fb
/* To print the total sizes in a reasonable format remember the higest
Packit Service 97d2fb
   "class" of ELF binaries processed.  */
Packit Service 97d2fb
static int totals_class;
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
int
Packit Service 97d2fb
main (int argc, char *argv[])
Packit Service 97d2fb
{
Packit Service 97d2fb
  int remaining;
Packit Service 97d2fb
  int result = 0;
Packit Service 97d2fb
Packit Service 97d2fb
  /* We use no threads here which can interfere with handling a stream.  */
Packit Service 97d2fb
  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
Packit Service 97d2fb
  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
Packit Service 97d2fb
  __fsetlocking (stderr, FSETLOCKING_BYCALLER);
Packit Service 97d2fb
Packit Service 97d2fb
  /* Set locale.  */
Packit Service 97d2fb
  setlocale (LC_ALL, "");
Packit Service 97d2fb
Packit Service 97d2fb
  /* Make sure the message catalog can be found.  */
Packit Service 97d2fb
  bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
Packit Service 97d2fb
Packit Service 97d2fb
  /* Initialize the message catalog.  */
Packit Service 97d2fb
  textdomain (PACKAGE_TARNAME);
Packit Service 97d2fb
Packit Service 97d2fb
  /* Parse and process arguments.  */
Packit Service 97d2fb
  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
  /* Tell the library which version we are expecting.  */
Packit Service 97d2fb
  elf_version (EV_CURRENT);
Packit Service 97d2fb
Packit Service 97d2fb
  if (remaining == argc)
Packit Service 97d2fb
    /* The user didn't specify a name so we use a.out.  */
Packit Service 97d2fb
    result = process_file ("a.out");
Packit Service 97d2fb
  else
Packit Service 97d2fb
    /* Process all the remaining files.  */
Packit Service 97d2fb
    do
Packit Service 97d2fb
      result |= process_file (argv[remaining]);
Packit Service 97d2fb
    while (++remaining < argc);
Packit Service 97d2fb
Packit Service 97d2fb
  /* Print the total sizes but only if the output format is BSD and at
Packit Service 97d2fb
     least one file has been correctly read (i.e., we recognized the
Packit Service 97d2fb
     class).  */
Packit Service 97d2fb
  if (totals && format == format_bsd && totals_class != 0)
Packit Service 97d2fb
    show_bsd_totals ();
Packit Service 97d2fb
Packit Service 97d2fb
  return result;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Handle program arguments.  */
Packit Service 97d2fb
static error_t
Packit Service 97d2fb
parse_opt (int key, char *arg,
Packit Service 97d2fb
	   struct argp_state *state __attribute__ ((unused)))
Packit Service 97d2fb
{
Packit Service 97d2fb
  switch (key)
Packit Service 97d2fb
    {
Packit Service 97d2fb
    case 'd':
Packit Service 97d2fb
      radix = radix_decimal;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case 'f':
Packit Service 97d2fb
      format = format_sysv_one_line;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case 'o':
Packit Service 97d2fb
      radix = radix_octal;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case 'x':
Packit Service 97d2fb
      radix = radix_hex;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case 'A':
Packit Service 97d2fb
      format = format_sysv;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case 'B':
Packit Service 97d2fb
      format = format_bsd;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case 'F':
Packit Service 97d2fb
      format = format_segments;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case OPT_FORMAT:
Packit Service 97d2fb
      if (strcmp (arg, "bsd") == 0 || strcmp (arg, "berkeley") == 0)
Packit Service 97d2fb
	format = format_bsd;
Packit Service 97d2fb
      else if (likely (strcmp (arg, "sysv") == 0))
Packit Service 97d2fb
	format = format_sysv;
Packit Service 97d2fb
      else
Packit Service 97d2fb
	error (EXIT_FAILURE, 0, gettext ("Invalid format: %s"), arg);
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case OPT_RADIX:
Packit Service 97d2fb
      if (strcmp (arg, "x") == 0 || strcmp (arg, "16") == 0)
Packit Service 97d2fb
	radix = radix_hex;
Packit Service 97d2fb
      else if (strcmp (arg, "d") == 0 || strcmp (arg, "10") == 0)
Packit Service 97d2fb
	radix = radix_decimal;
Packit Service 97d2fb
      else if (strcmp (arg, "o") == 0 || strcmp (arg, "8") == 0)
Packit Service 97d2fb
	radix = radix_octal;
Packit Service 97d2fb
      else
Packit Service 97d2fb
	error (EXIT_FAILURE, 0, gettext ("Invalid radix: %s"), arg);
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case 't':
Packit Service 97d2fb
      totals = true;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    default:
Packit Service 97d2fb
      return ARGP_ERR_UNKNOWN;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  return 0;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Open the file and determine the type.  */
Packit Service 97d2fb
static int
Packit Service 97d2fb
process_file (const char *fname)
Packit Service 97d2fb
{
Packit Service 97d2fb
  int fd = open (fname, O_RDONLY);
Packit Service 97d2fb
  if (unlikely (fd == -1))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      error (0, errno, gettext ("cannot open '%s'"), fname);
Packit Service 97d2fb
      return 1;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* Now get the ELF descriptor.  */
Packit Service 97d2fb
  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
Packit Service 97d2fb
  if (likely (elf != NULL))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      if (elf_kind (elf) == ELF_K_ELF)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  handle_elf (elf, NULL, fname);
Packit Service 97d2fb
Packit Service 97d2fb
	  if (unlikely (elf_end (elf) != 0))
Packit Service 97d2fb
	    INTERNAL_ERROR (fname);
Packit Service 97d2fb
Packit Service 97d2fb
	  if (unlikely (close (fd) != 0))
Packit Service 97d2fb
	    error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
Packit Service 97d2fb
Packit Service 97d2fb
	  return 0;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      else if (likely (elf_kind (elf) == ELF_K_AR))
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  int result = handle_ar (fd, elf, NULL, fname);
Packit Service 97d2fb
Packit Service 97d2fb
	  if (unlikely  (close (fd) != 0))
Packit Service 97d2fb
	    error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
Packit Service 97d2fb
Packit Service 97d2fb
	  return result;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      /* We cannot handle this type.  Close the descriptor anyway.  */
Packit Service 97d2fb
      if (unlikely (elf_end (elf) != 0))
Packit Service 97d2fb
	INTERNAL_ERROR (fname);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (unlikely (close (fd) != 0))
Packit Service 97d2fb
    error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
Packit Service 97d2fb
Packit Service 97d2fb
  error (0, 0, gettext ("%s: file format not recognized"), fname);
Packit Service 97d2fb
Packit Service 97d2fb
  return 1;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Print the BSD-style header.  This is done exactly once.  */
Packit Service 97d2fb
static void
Packit Service 97d2fb
print_header (Elf *elf)
Packit Service 97d2fb
{
Packit Service 97d2fb
  static int done;
Packit Service 97d2fb
Packit Service 97d2fb
  if (! done)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      int ddigits = length_map[gelf_getclass (elf) - 1][radix_decimal];
Packit Service 97d2fb
      int xdigits = length_map[gelf_getclass (elf) - 1][radix_hex];
Packit Service 97d2fb
Packit Service 97d2fb
      printf ("%*s %*s %*s %*s %*s %s\n",
Packit Service 97d2fb
	      ddigits - 2, sgettext ("bsd|text"),
Packit Service 97d2fb
	      ddigits - 2, sgettext ("bsd|data"),
Packit Service 97d2fb
	      ddigits - 2, sgettext ("bsd|bss"),
Packit Service 97d2fb
	      ddigits - 2, sgettext ("bsd|dec"),
Packit Service 97d2fb
	      xdigits - 2, sgettext ("bsd|hex"),
Packit Service 97d2fb
	      sgettext ("bsd|filename"));
Packit Service 97d2fb
Packit Service 97d2fb
      done = 1;
Packit Service 97d2fb
    }
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
static int
Packit Service 97d2fb
handle_ar (int fd, Elf *elf, const char *prefix, const char *fname)
Packit Service 97d2fb
{
Packit Service 97d2fb
  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
Packit Service 97d2fb
  size_t fname_len = strlen (fname) + 1;
Packit Service 97d2fb
  char new_prefix[prefix_len + 1 + fname_len];
Packit Service 97d2fb
  char *cp = new_prefix;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Create the full name of the file.  */
Packit Service 97d2fb
  if (prefix != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      cp = mempcpy (cp, prefix, prefix_len);
Packit Service 97d2fb
      *cp++ = ':';
Packit Service 97d2fb
    }
Packit Service 97d2fb
  memcpy (cp, fname, fname_len);
Packit Service 97d2fb
Packit Service 97d2fb
  /* Process all the files contained in the archive.  */
Packit Service 97d2fb
  int result = 0;
Packit Service 97d2fb
  Elf *subelf;
Packit Service 97d2fb
  Elf_Cmd cmd = ELF_C_READ_MMAP;
Packit Service 97d2fb
  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* The the header for this element.  */
Packit Service 97d2fb
      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
Packit Service 97d2fb
Packit Service 97d2fb
      if (elf_kind (subelf) == ELF_K_ELF)
Packit Service 97d2fb
	handle_elf (subelf, new_prefix, arhdr->ar_name);
Packit Service 97d2fb
      else if (likely (elf_kind (subelf) == ELF_K_AR))
Packit Service 97d2fb
	result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name);
Packit Service 97d2fb
      /* else signal error??? */
Packit Service 97d2fb
Packit Service 97d2fb
      /* Get next archive element.  */
Packit Service 97d2fb
      cmd = elf_next (subelf);
Packit Service 97d2fb
      if (unlikely (elf_end (subelf) != 0))
Packit Service 97d2fb
	INTERNAL_ERROR (fname);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* Only close ELF handle if this was a "top level" ar file.  */
Packit Service 97d2fb
  if (prefix == NULL)
Packit Service 97d2fb
    if (unlikely (elf_end (elf) != 0))
Packit Service 97d2fb
      INTERNAL_ERROR (fname);
Packit Service 97d2fb
Packit Service 97d2fb
  return result;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Show sizes in SysV format.  */
Packit Service 97d2fb
static void
Packit Service 97d2fb
show_sysv (Elf *elf, const char *prefix, const char *fname,
Packit Service 97d2fb
	   const char *fullname)
Packit Service 97d2fb
{
Packit Service 97d2fb
  int maxlen = 10;
Packit Service 97d2fb
  const int digits = length_map[gelf_getclass (elf) - 1][radix];
Packit Service 97d2fb
Packit Service 97d2fb
  /* Get the section header string table index.  */
Packit Service 97d2fb
  size_t shstrndx;
Packit Service 97d2fb
  if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0))
Packit Service 97d2fb
    error (EXIT_FAILURE, 0,
Packit Service 97d2fb
	   gettext ("cannot get section header string table index"));
Packit Service 97d2fb
Packit Service 97d2fb
  /* First round over the sections: determine the longest section name.  */
Packit Service 97d2fb
  Elf_Scn *scn = NULL;
Packit Service 97d2fb
  while ((scn = elf_nextscn (elf, scn)) != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      GElf_Shdr shdr_mem;
Packit Service 97d2fb
      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Packit Service 97d2fb
Packit Service 97d2fb
      if (shdr == NULL)
Packit Service 97d2fb
	INTERNAL_ERROR (fullname);
Packit Service 97d2fb
Packit Service 97d2fb
      /* Ignore all sections which are not used at runtime.  */
Packit Service 97d2fb
      const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
Packit Service 97d2fb
      if (name != NULL && (shdr->sh_flags & SHF_ALLOC) != 0)
Packit Service 97d2fb
	maxlen = MAX (maxlen, (int) strlen (name));
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  fputs_unlocked (fname, stdout);
Packit Service 97d2fb
  if (prefix != NULL)
Packit Service 97d2fb
    printf (gettext (" (ex %s)"), prefix);
Packit Service 97d2fb
  printf (":\n%-*s %*s %*s\n",
Packit Service 97d2fb
	  maxlen, sgettext ("sysv|section"),
Packit Service 97d2fb
	  digits - 2, sgettext ("sysv|size"),
Packit Service 97d2fb
	  digits, sgettext ("sysv|addr"));
Packit Service 97d2fb
Packit Service 97d2fb
  /* Iterate over all sections.  */
Packit Service 97d2fb
  GElf_Off total = 0;
Packit Service 97d2fb
  while ((scn = elf_nextscn (elf, scn)) != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      GElf_Shdr shdr_mem;
Packit Service 97d2fb
      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Packit Service 97d2fb
Packit Service 97d2fb
      if (shdr == NULL)
Packit Service 97d2fb
	INTERNAL_ERROR (fullname);
Packit Service 97d2fb
Packit Service 97d2fb
      /* Ignore all sections which are not used at runtime.  */
Packit Service 97d2fb
      if ((shdr->sh_flags & SHF_ALLOC) != 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  printf ((radix == radix_hex
Packit Service 97d2fb
		   ? "%-*s %*" PRIx64 " %*" PRIx64 "\n"
Packit Service 97d2fb
		   : (radix == radix_decimal
Packit Service 97d2fb
		      ? "%-*s %*" PRId64 " %*" PRId64 "\n"
Packit Service 97d2fb
		      : "%-*s %*" PRIo64 " %*" PRIo64 "\n")),
Packit Service 97d2fb
		  maxlen, elf_strptr (elf, shstrndx, shdr->sh_name),
Packit Service 97d2fb
		  digits - 2, shdr->sh_size,
Packit Service 97d2fb
		  digits, shdr->sh_addr);
Packit Service 97d2fb
Packit Service 97d2fb
	  total += shdr->sh_size;
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (radix == radix_hex)
Packit Service 97d2fb
    printf ("%-*s %*" PRIx64 "\n\n\n", maxlen, sgettext ("sysv|Total"),
Packit Service 97d2fb
	    digits - 2, total);
Packit Service 97d2fb
  else if (radix == radix_decimal)
Packit Service 97d2fb
    printf ("%-*s %*" PRId64 "\n\n\n", maxlen, sgettext ("sysv|Total"),
Packit Service 97d2fb
	    digits - 2, total);
Packit Service 97d2fb
  else
Packit Service 97d2fb
    printf ("%-*s %*" PRIo64 "\n\n\n", maxlen, sgettext ("sysv|Total"),
Packit Service 97d2fb
	    digits - 2, total);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Show sizes in SysV format in one line.  */
Packit Service 97d2fb
static void
Packit Service 97d2fb
show_sysv_one_line (Elf *elf)
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* Get the section header string table index.  */
Packit Service 97d2fb
  size_t shstrndx;
Packit Service 97d2fb
  if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0))
Packit Service 97d2fb
    error (EXIT_FAILURE, 0,
Packit Service 97d2fb
	   gettext ("cannot get section header string table index"));
Packit Service 97d2fb
Packit Service 97d2fb
  /* Iterate over all sections.  */
Packit Service 97d2fb
  GElf_Off total = 0;
Packit Service 97d2fb
  bool first = true;
Packit Service 97d2fb
  Elf_Scn *scn = NULL;
Packit Service 97d2fb
  while ((scn = elf_nextscn (elf, scn)) != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      GElf_Shdr shdr_mem;
Packit Service 97d2fb
      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Packit Service 97d2fb
Packit Service 97d2fb
      if (unlikely (shdr == NULL))
Packit Service 97d2fb
	error (EXIT_FAILURE, 0, gettext ("cannot get section header"));
Packit Service 97d2fb
Packit Service 97d2fb
      /* Ignore all sections which are not used at runtime.  */
Packit Service 97d2fb
      if ((shdr->sh_flags & SHF_ALLOC) == 0)
Packit Service 97d2fb
	continue;
Packit Service 97d2fb
Packit Service 97d2fb
      if (! first)
Packit Service 97d2fb
	fputs_unlocked (" + ", stdout);
Packit Service 97d2fb
      first = false;
Packit Service 97d2fb
Packit Service 97d2fb
      printf ((radix == radix_hex ? "%" PRIx64 "(%s)"
Packit Service 97d2fb
	       : (radix == radix_decimal ? "%" PRId64 "(%s)"
Packit Service 97d2fb
		  : "%" PRIo64 "(%s)")),
Packit Service 97d2fb
	      shdr->sh_size, elf_strptr (elf, shstrndx, shdr->sh_name));
Packit Service 97d2fb
Packit Service 97d2fb
      total += shdr->sh_size;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (radix == radix_hex)
Packit Service 97d2fb
    printf (" = %#" PRIx64 "\n", total);
Packit Service 97d2fb
  else if (radix == radix_decimal)
Packit Service 97d2fb
    printf (" = %" PRId64 "\n", total);
Packit Service 97d2fb
  else
Packit Service 97d2fb
    printf (" = %" PRIo64 "\n", total);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Variables to add up the sizes of all files.  */
Packit Service 97d2fb
static uintmax_t total_textsize;
Packit Service 97d2fb
static uintmax_t total_datasize;
Packit Service 97d2fb
static uintmax_t total_bsssize;
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Show sizes in BSD format.  */
Packit Service 97d2fb
static void
Packit Service 97d2fb
show_bsd (Elf *elf, const char *prefix, const char *fname,
Packit Service 97d2fb
	  const char *fullname)
Packit Service 97d2fb
{
Packit Service 97d2fb
  GElf_Off textsize = 0;
Packit Service 97d2fb
  GElf_Off datasize = 0;
Packit Service 97d2fb
  GElf_Off bsssize = 0;
Packit Service 97d2fb
  const int ddigits = length_map[gelf_getclass (elf) - 1][radix_decimal];
Packit Service 97d2fb
  const int xdigits = length_map[gelf_getclass (elf) - 1][radix_hex];
Packit Service 97d2fb
Packit Service 97d2fb
  /* Iterate over all sections.  */
Packit Service 97d2fb
  Elf_Scn *scn = NULL;
Packit Service 97d2fb
  while ((scn = elf_nextscn (elf, scn)) != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      GElf_Shdr shdr_mem;
Packit Service 97d2fb
      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Packit Service 97d2fb
Packit Service 97d2fb
      if (shdr == NULL)
Packit Service 97d2fb
	INTERNAL_ERROR (fullname);
Packit Service 97d2fb
Packit Service 97d2fb
      /* Ignore all sections which are not marked as loaded.  */
Packit Service 97d2fb
      if ((shdr->sh_flags & SHF_ALLOC) == 0)
Packit Service 97d2fb
	continue;
Packit Service 97d2fb
Packit Service 97d2fb
      if ((shdr->sh_flags & SHF_WRITE) == 0)
Packit Service 97d2fb
	textsize += shdr->sh_size;
Packit Service 97d2fb
      else if (shdr->sh_type == SHT_NOBITS)
Packit Service 97d2fb
	bsssize += shdr->sh_size;
Packit Service 97d2fb
      else
Packit Service 97d2fb
	datasize += shdr->sh_size;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  printf (radix == radix_decimal
Packit Service 97d2fb
          ? "%*" PRId64 " %*" PRId64 " %*" PRId64 " %*" PRId64 " %*" PRIx64 " %s"
Packit Service 97d2fb
	  : radix == radix_hex
Packit Service 97d2fb
	  ? "%#*" PRIx64 " %#*" PRIx64 " %#*" PRIx64 " %*" PRId64 " %*" PRIx64 " %s"
Packit Service 97d2fb
	  : "%#*" PRIo64 " %#*" PRIo64 " %#*" PRIo64 " %*" PRId64 " %*" PRIx64 " %s",
Packit Service 97d2fb
	  ddigits - 2, textsize,
Packit Service 97d2fb
	  ddigits - 2, datasize,
Packit Service 97d2fb
	  ddigits - 2, bsssize,
Packit Service 97d2fb
	  ddigits - 2, textsize + datasize + bsssize,
Packit Service 97d2fb
	  xdigits - 2, textsize + datasize + bsssize,
Packit Service 97d2fb
	  fname);
Packit Service 97d2fb
  if (prefix != NULL)
Packit Service 97d2fb
    printf (gettext (" (ex %s)"), prefix);
Packit Service 97d2fb
  fputs_unlocked ("\n", stdout);
Packit Service 97d2fb
Packit Service 97d2fb
  total_textsize += textsize;
Packit Service 97d2fb
  total_datasize += datasize;
Packit Service 97d2fb
  total_bsssize += bsssize;
Packit Service 97d2fb
Packit Service 97d2fb
  totals_class = MAX (totals_class, gelf_getclass (elf));
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Show total size.  */
Packit Service 97d2fb
static void
Packit Service 97d2fb
show_bsd_totals (void)
Packit Service 97d2fb
{
Packit Service 97d2fb
  int ddigits = length_map[totals_class - 1][radix_decimal];
Packit Service 97d2fb
  int xdigits = length_map[totals_class - 1][radix_hex];
Packit Service 97d2fb
Packit Service 97d2fb
  printf ("%*" PRIuMAX " %*" PRIuMAX " %*" PRIuMAX " %*" PRIuMAX " %*"
Packit Service 97d2fb
	  PRIxMAX " %s",
Packit Service 97d2fb
	  ddigits - 2, total_textsize,
Packit Service 97d2fb
	  ddigits - 2, total_datasize,
Packit Service 97d2fb
	  ddigits - 2, total_bsssize,
Packit Service 97d2fb
	  ddigits - 2, total_textsize + total_datasize + total_bsssize,
Packit Service 97d2fb
	  xdigits - 2, total_textsize + total_datasize + total_bsssize,
Packit Service 97d2fb
	  gettext ("(TOTALS)\n"));
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Show size and permission of loadable segments.  */
Packit Service 97d2fb
static void
Packit Service 97d2fb
show_segments (Elf *elf, const char *fullname)
Packit Service 97d2fb
{
Packit Service 97d2fb
  size_t phnum;
Packit Service 97d2fb
  if (elf_getphdrnum (elf, &phnum) != 0)
Packit Service 97d2fb
    INTERNAL_ERROR (fullname);
Packit Service 97d2fb
Packit Service 97d2fb
  GElf_Off total = 0;
Packit Service 97d2fb
  bool first = true;
Packit Service 97d2fb
  for (size_t cnt = 0; cnt < phnum; ++cnt)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      GElf_Phdr phdr_mem;
Packit Service 97d2fb
      GElf_Phdr *phdr;
Packit Service 97d2fb
Packit Service 97d2fb
      phdr = gelf_getphdr (elf, cnt, &phdr_mem);
Packit Service 97d2fb
      if (phdr == NULL)
Packit Service 97d2fb
	INTERNAL_ERROR (fullname);
Packit Service 97d2fb
Packit Service 97d2fb
      if (phdr->p_type != PT_LOAD)
Packit Service 97d2fb
	/* Only load segments.  */
Packit Service 97d2fb
	continue;
Packit Service 97d2fb
Packit Service 97d2fb
      if (! first)
Packit Service 97d2fb
	fputs_unlocked (" + ", stdout);
Packit Service 97d2fb
      first = false;
Packit Service 97d2fb
Packit Service 97d2fb
      printf (radix == radix_hex ? "%" PRIx64 "(%c%c%c)"
Packit Service 97d2fb
	      : (radix == radix_decimal ? "%" PRId64 "(%c%c%c)"
Packit Service 97d2fb
		 : "%" PRIo64 "(%c%c%c)"),
Packit Service 97d2fb
	      phdr->p_memsz,
Packit Service 97d2fb
	      (phdr->p_flags & PF_R) == 0 ? '-' : 'r',
Packit Service 97d2fb
	      (phdr->p_flags & PF_W) == 0 ? '-' : 'w',
Packit Service 97d2fb
	      (phdr->p_flags & PF_X) == 0 ? '-' : 'x');
Packit Service 97d2fb
Packit Service 97d2fb
      total += phdr->p_memsz;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (radix == radix_hex)
Packit Service 97d2fb
    printf (" = %#" PRIx64 "\n", total);
Packit Service 97d2fb
  else if (radix == radix_decimal)
Packit Service 97d2fb
    printf (" = %" PRId64 "\n", total);
Packit Service 97d2fb
  else
Packit Service 97d2fb
    printf (" = %" PRIo64 "\n", total);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
static void
Packit Service 97d2fb
handle_elf (Elf *elf, const char *prefix, const char *fname)
Packit Service 97d2fb
{
Packit Service 97d2fb
  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
Packit Service 97d2fb
  size_t fname_len = strlen (fname) + 1;
Packit Service 97d2fb
  char fullname[prefix_len + 1 + fname_len];
Packit Service 97d2fb
  char *cp = fullname;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Create the full name of the file.  */
Packit Service 97d2fb
  if (prefix != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      cp = mempcpy (cp, prefix, prefix_len);
Packit Service 97d2fb
      *cp++ = ':';
Packit Service 97d2fb
    }
Packit Service 97d2fb
  memcpy (cp, fname, fname_len);
Packit Service 97d2fb
Packit Service 97d2fb
  if (format == format_sysv)
Packit Service 97d2fb
    show_sysv (elf, prefix, fname, fullname);
Packit Service 97d2fb
  else if (format == format_sysv_one_line)
Packit Service 97d2fb
    show_sysv_one_line (elf);
Packit Service 97d2fb
  else if (format == format_segments)
Packit Service 97d2fb
    show_segments (elf, fullname);
Packit Service 97d2fb
  else
Packit Service 97d2fb
    {
Packit Service 97d2fb
      print_header (elf);
Packit Service 97d2fb
Packit Service 97d2fb
      show_bsd (elf, prefix, fname, fullname);
Packit Service 97d2fb
    }
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
#include "debugpred.h"