Home | History | Annotate | Download | only in src
      1 /* Print information from ELF file in human-readable form.
      2    Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Red Hat, Inc.
      3    This file is part of Red Hat elfutils.
      4    Written by Ulrich Drepper <drepper (at) redhat.com>, 1999.
      5 
      6    Red Hat elfutils is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by the
      8    Free Software Foundation; version 2 of the License.
      9 
     10    Red Hat elfutils is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13    General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License along
     16    with Red Hat elfutils; if not, write to the Free Software Foundation,
     17    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
     18 
     19    Red Hat elfutils is an included package of the Open Invention Network.
     20    An included package of the Open Invention Network is a package for which
     21    Open Invention Network licensees cross-license their patents.  No patent
     22    license is granted, either expressly or impliedly, by designation as an
     23    included package.  Should you wish to participate in the Open Invention
     24    Network licensing program, please visit www.openinventionnetwork.com
     25    <http://www.openinventionnetwork.com>.  */
     26 
     27 #ifdef HAVE_CONFIG_H
     28 # include <config.h>
     29 #endif
     30 
     31 #include <argp.h>
     32 #include <assert.h>
     33 #include <ctype.h>
     34 #include <dwarf.h>
     35 #include <errno.h>
     36 #include <error.h>
     37 #include <fcntl.h>
     38 #include <gelf.h>
     39 #include <inttypes.h>
     40 #include <langinfo.h>
     41 #include <libdw.h>
     42 #include <libdwfl.h>
     43 #include <libintl.h>
     44 #include <locale.h>
     45 #include <stdarg.h>
     46 #include <stdbool.h>
     47 #include <stdlib.h>
     48 #include <string.h>
     49 #include <time.h>
     50 #include <unistd.h>
     51 #include <sys/param.h>
     52 
     53 #include <system.h>
     54 #include "../libelf/libelfP.h"
     55 #include "../libelf/common.h"
     56 #include "../libebl/libeblP.h"
     57 #include "../libdw/libdwP.h"
     58 #include "../libdwfl/libdwflP.h"
     59 #include "../libdw/memory-access.h"
     60 
     61 
     62 /* Name and version of program.  */
     63 static void print_version (FILE *stream, struct argp_state *state);
     64 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
     65 
     66 /* Bug report address.  */
     67 const char *argp_program_bug_address = PACKAGE_BUGREPORT;
     68 
     69 /* Definitions of arguments for argp functions.  */
     70 static const struct argp_option options[] =
     71 {
     72   { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
     73   { "all", 'a', NULL, 0, N_("Equivalent to: -h -l"), 0 },
     74   { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
     75   { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
     76   { "histogram", 'I', NULL, 0,
     77     N_("Display histogram of bucket list lengths"), 0 },
     78   { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
     79   { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
     80   { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
     81   { "section-headers", 'S', NULL, 0, N_("Display the sections' header"), 0 },
     82   { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
     83   { "symbols", 's', NULL, 0, N_("Display the symbol table"), 0 },
     84   { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
     85   { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
     86     N_("Display DWARF section content.  SECTION can be one of abbrev, "
     87        "aranges, frame, info, loc, line, ranges, pubnames, str, or macinfo."),
     88     0 },
     89   { "notes", 'n', NULL, 0, N_("Display the core notes"), 0 },
     90   { "arch-specific", 'A', NULL, 0,
     91     N_("Display architecture specific information (if any)"), 0 },
     92   { "hex-dump", 'x', "SECTION", 0,
     93     N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
     94   { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
     95     N_("Print string contents of sections"), 0 },
     96   { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
     97   { "archive-index", 'c', NULL, 0,
     98     N_("Display the symbol index of an archive"), 0 },
     99 
    100   { NULL, 0, NULL, 0, N_("Output control:"), 0 },
    101 
    102   { NULL, 0, NULL, 0, NULL, 0 }
    103 };
    104 
    105 /* Short description of program.  */
    106 static const char doc[] = N_("\
    107 Print information from ELF file in human-readable form.");
    108 
    109 /* Strings for arguments in help texts.  */
    110 static const char args_doc[] = N_("FILE...");
    111 
    112 /* Prototype for option handler.  */
    113 static error_t parse_opt (int key, char *arg, struct argp_state *state);
    114 
    115 /* Data structure to communicate with argp functions.  */
    116 static struct argp argp =
    117 {
    118   options, parse_opt, args_doc, doc, NULL, NULL, NULL
    119 };
    120 
    121 
    122 /* Flags set by the option controlling the output.  */
    123 
    124 /* True if dynamic segment should be printed.  */
    125 static bool print_dynamic_table;
    126 
    127 /* True if the file header should be printed.  */
    128 static bool print_file_header;
    129 
    130 /* True if the program headers should be printed.  */
    131 static bool print_program_header;
    132 
    133 /* True if relocations should be printed.  */
    134 static bool print_relocations;
    135 
    136 /* True if the section headers should be printed.  */
    137 static bool print_section_header;
    138 
    139 /* True if the symbol table should be printed.  */
    140 static bool print_symbol_table;
    141 
    142 /* True if the version information should be printed.  */
    143 static bool print_version_info;
    144 
    145 /* True if section groups should be printed.  */
    146 static bool print_section_groups;
    147 
    148 /* True if bucket list length histogram should be printed.  */
    149 static bool print_histogram;
    150 
    151 /* True if the architecture specific data should be printed.  */
    152 static bool print_arch;
    153 
    154 /* True if note section content should be printed.  */
    155 static bool print_notes;
    156 
    157 /* True if SHF_STRINGS section content should be printed.  */
    158 static bool print_string_sections;
    159 
    160 /* True if archive index should be printed.  */
    161 static bool print_archive_index;
    162 
    163 /* True if any of the control options except print_archive_index is set.  */
    164 static bool any_control_option;
    165 
    166 /* Select printing of debugging sections.  */
    167 static enum section_e
    168 {
    169   section_abbrev = 1,	/* .debug_abbrev  */
    170   section_aranges = 2,	/* .debug_aranges  */
    171   section_frame = 4,	/* .debug_frame or .eh_frame  */
    172   section_info = 8,	/* .debug_info  */
    173   section_line = 16,	/* .debug_line  */
    174   section_loc = 32,	/* .debug_loc  */
    175   section_pubnames = 64,/* .debug_pubnames  */
    176   section_str = 128,	/* .debug_str  */
    177   section_macinfo = 256,/* .debug_macinfo  */
    178   section_ranges = 512, /* .debug_ranges  */
    179   section_all = (section_abbrev | section_aranges | section_frame
    180 		 | section_info | section_line | section_loc
    181 		 | section_pubnames | section_str | section_macinfo
    182 		 | section_ranges)
    183 } print_debug_sections;
    184 
    185 /* Select hex dumping of sections.  */
    186 static struct section_argument *dump_data_sections;
    187 static struct section_argument **dump_data_sections_tail = &dump_data_sections;
    188 
    189 /* Select string dumping of sections.  */
    190 static struct section_argument *string_sections;
    191 static struct section_argument **string_sections_tail = &string_sections;
    192 
    193 struct section_argument
    194 {
    195   struct section_argument *next;
    196   const char *arg;
    197 };
    198 
    199 /* Number of sections in the file.  */
    200 static size_t shnum;
    201 
    202 
    203 /* Declarations of local functions.  */
    204 static void process_file (int fd, const char *fname, bool only_one);
    205 static void process_elf_file (Dwfl_Module *dwflmod, int fd);
    206 static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
    207 static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
    208 static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
    209 static void print_scngrp (Ebl *ebl);
    210 static void print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr);
    211 static void print_relocs (Ebl *ebl);
    212 static void handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
    213 static void handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
    214 static void print_symtab (Ebl *ebl, int type);
    215 static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
    216 static void print_verinfo (Ebl *ebl);
    217 static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
    218 static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
    219 static void handle_versym (Ebl *ebl, Elf_Scn *scn,
    220 			   GElf_Shdr *shdr);
    221 static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
    222 static void handle_hash (Ebl *ebl);
    223 static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
    224 static void print_liblist (Ebl *ebl);
    225 static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
    226 static void dump_data (Ebl *ebl);
    227 static void dump_strings (Ebl *ebl);
    228 static void print_strings (Ebl *ebl);
    229 static void dump_archive_index (Elf *, const char *);
    230 
    231 
    232 int
    233 main (int argc, char *argv[])
    234 {
    235   /* Set locale.  */
    236   setlocale (LC_ALL, "");
    237 
    238   /* Initialize the message catalog.  */
    239   textdomain (PACKAGE_TARNAME);
    240 
    241   /* Parse and process arguments.  */
    242   int remaining;
    243   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
    244 
    245   /* Before we start tell the ELF library which version we are using.  */
    246   elf_version (EV_CURRENT);
    247 
    248   /* Now process all the files given at the command line.  */
    249   bool only_one = remaining + 1 == argc;
    250   do
    251     {
    252       /* Open the file.  */
    253       int fd = open (argv[remaining], O_RDONLY);
    254       if (fd == -1)
    255 	{
    256 	  error (0, errno, gettext ("cannot open input file"));
    257 	  continue;
    258 	}
    259 
    260       process_file (fd, argv[remaining], only_one);
    261 
    262       close (fd);
    263     }
    264   while (++remaining < argc);
    265 
    266   return error_message_count != 0;
    267 }
    268 
    269 
    270 /* Handle program arguments.  */
    271 static error_t
    272 parse_opt (int key, char *arg,
    273 	   struct argp_state *state __attribute__ ((unused)))
    274 {
    275   switch (key)
    276     {
    277     case 'a':
    278       print_file_header = true;
    279       print_program_header = true;
    280       print_relocations = true;
    281       print_section_header = true;
    282       print_symbol_table = true;
    283       print_version_info = true;
    284       print_dynamic_table = true;
    285       print_section_groups = true;
    286       print_histogram = true;
    287       print_arch = true;
    288       print_notes = true;
    289       any_control_option = true;
    290       break;
    291     case 'A':
    292       print_arch = true;
    293       any_control_option = true;
    294       break;
    295     case 'd':
    296       print_dynamic_table = true;
    297       any_control_option = true;
    298       break;
    299     case 'g':
    300       print_section_groups = true;
    301       any_control_option = true;
    302       break;
    303     case 'h':
    304       print_file_header = true;
    305       any_control_option = true;
    306       break;
    307     case 'I':
    308       print_histogram = true;
    309       any_control_option = true;
    310       break;
    311     case 'l':
    312       print_program_header = true;
    313       any_control_option = true;
    314       break;
    315     case 'n':
    316       print_notes = true;
    317       any_control_option = true;
    318       break;
    319     case 'r':
    320       print_relocations = true;
    321       any_control_option = true;
    322      break;
    323     case 'S':
    324       print_section_header = true;
    325       any_control_option = true;
    326       break;
    327     case 's':
    328       print_symbol_table = true;
    329       any_control_option = true;
    330       break;
    331     case 'V':
    332       print_version_info = true;
    333       any_control_option = true;
    334       break;
    335     case 'c':
    336       print_archive_index = true;
    337       break;
    338     case 'w':
    339       if (arg == NULL)
    340 	print_debug_sections = section_all;
    341       else if (strcmp (arg, "abbrev") == 0)
    342 	print_debug_sections |= section_abbrev;
    343       else if (strcmp (arg, "aranges") == 0)
    344 	print_debug_sections |= section_aranges;
    345       else if (strcmp (arg, "ranges") == 0)
    346 	print_debug_sections |= section_ranges;
    347       else if (strcmp (arg, "frame") == 0)
    348 	print_debug_sections |= section_frame;
    349       else if (strcmp (arg, "info") == 0)
    350 	print_debug_sections |= section_info;
    351       else if (strcmp (arg, "loc") == 0)
    352 	print_debug_sections |= section_loc;
    353       else if (strcmp (arg, "line") == 0)
    354 	print_debug_sections |= section_line;
    355       else if (strcmp (arg, "pubnames") == 0)
    356 	print_debug_sections |= section_pubnames;
    357       else if (strcmp (arg, "str") == 0)
    358 	print_debug_sections |= section_str;
    359       else if (strcmp (arg, "macinfo") == 0)
    360 	print_debug_sections |= section_macinfo;
    361       else
    362 	{
    363 	  fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
    364 		   arg);
    365 	  argp_help (&argp, stderr, ARGP_HELP_SEE,
    366 		     program_invocation_short_name);
    367 	  exit (1);
    368 	}
    369       any_control_option = true;
    370       break;
    371     case 'p':
    372       any_control_option = true;
    373       if (arg == NULL)
    374 	{
    375 	  print_string_sections = true;
    376 	  break;
    377 	}
    378       /* Fall through.  */
    379     case 'x':
    380       {
    381 	struct section_argument *a = xmalloc (sizeof *a);
    382 	a->arg = arg;
    383 	a->next = NULL;
    384 	struct section_argument ***tailp
    385 	  = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
    386 	**tailp = a;
    387 	*tailp = &a->next;
    388       }
    389       any_control_option = true;
    390       break;
    391     case ARGP_KEY_NO_ARGS:
    392       fputs (gettext ("Missing file name.\n"), stderr);
    393       goto do_argp_help;
    394     case ARGP_KEY_FINI:
    395       if (! any_control_option && ! print_archive_index)
    396 	{
    397 	  fputs (gettext ("No operation specified.\n"), stderr);
    398 	do_argp_help:
    399 	  argp_help (&argp, stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
    400 		     program_invocation_short_name);
    401 	  exit (1);
    402 	}
    403       break;
    404     default:
    405       return ARGP_ERR_UNKNOWN;
    406     }
    407   return 0;
    408 }
    409 
    410 
    411 /* Print the version information.  */
    412 static void
    413 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
    414 {
    415   fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
    416   fprintf (stream, gettext ("\
    417 Copyright (C) %s Red Hat, Inc.\n\
    418 This is free software; see the source for copying conditions.  There is NO\n\
    419 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
    420 "), "2008");
    421   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
    422 }
    423 
    424 
    425 /* Check if the file is an archive, and if so dump its index.  */
    426 static void
    427 check_archive_index (int fd, const char *fname, bool only_one)
    428 {
    429   /* Create an `Elf' descriptor.  */
    430   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
    431   if (elf == NULL)
    432     error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
    433 	   elf_errmsg (-1));
    434   else
    435     {
    436       if (elf_kind (elf) == ELF_K_AR)
    437 	{
    438 	  if (!only_one)
    439 	    printf ("\n%s:\n\n", fname);
    440 	  dump_archive_index (elf, fname);
    441 	}
    442       else
    443 	error (0, 0,
    444 	       gettext ("'%s' is not an archive, cannot print archive index"),
    445 	       fname);
    446 
    447       /* Now we can close the descriptor.  */
    448       if (elf_end (elf) != 0)
    449 	error (0, 0, gettext ("error while closing Elf descriptor: %s"),
    450 	       elf_errmsg (-1));
    451     }
    452 }
    453 
    454 /* Trivial callback used for checking if we opened an archive.  */
    455 static int
    456 count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
    457 	       void **userdata __attribute__ ((unused)),
    458 	       const char *name __attribute__ ((unused)),
    459 	       Dwarf_Addr base __attribute__ ((unused)),
    460 	       void *arg)
    461 {
    462   if (*(bool *) arg)
    463     return DWARF_CB_ABORT;
    464   *(bool *) arg = true;
    465   return DWARF_CB_OK;
    466 }
    467 
    468 struct process_dwflmod_args
    469 {
    470   int fd;
    471   bool only_one;
    472 };
    473 
    474 static int
    475 process_dwflmod (Dwfl_Module *dwflmod,
    476 		 void **userdata __attribute__ ((unused)),
    477 		 const char *name __attribute__ ((unused)),
    478 		 Dwarf_Addr base __attribute__ ((unused)),
    479 		 void *arg)
    480 {
    481   const struct process_dwflmod_args *a = arg;
    482 
    483   /* Print the file name.  */
    484   if (!a->only_one)
    485     {
    486       const char *fname;
    487       dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
    488 
    489       printf ("\n%s:\n\n", fname);
    490     }
    491 
    492   process_elf_file (dwflmod, a->fd);
    493 
    494   return DWARF_CB_OK;
    495 }
    496 
    497 /* Stub libdwfl callback, only the ELF handle already open is ever used.  */
    498 static int
    499 find_no_debuginfo (Dwfl_Module *mod __attribute__ ((unused)),
    500 		   void **userdata __attribute__ ((unused)),
    501 		   const char *modname __attribute__ ((unused)),
    502 		   Dwarf_Addr base __attribute__ ((unused)),
    503 		   const char *file_name __attribute__ ((unused)),
    504 		   const char *debuglink_file __attribute__ ((unused)),
    505 		   GElf_Word debuglink_crc __attribute__ ((unused)),
    506 		   char **debuginfo_file_name __attribute__ ((unused)))
    507 {
    508   return -1;
    509 }
    510 
    511 /* Process one input file.  */
    512 static void
    513 process_file (int fd, const char *fname, bool only_one)
    514 {
    515   if (print_archive_index)
    516     check_archive_index (fd, fname, only_one);
    517 
    518   if (!any_control_option)
    519     return;
    520 
    521   /* Duplicate an fd for dwfl_report_offline to swallow.  */
    522   int dwfl_fd = dup (fd);
    523   if (unlikely (dwfl_fd < 0))
    524     error (EXIT_FAILURE, errno, "dup");
    525 
    526   /* Use libdwfl in a trivial way to open the libdw handle for us.
    527      This takes care of applying relocations to DWARF data in ET_REL files.  */
    528   static const Dwfl_Callbacks callbacks =
    529     {
    530       .section_address = dwfl_offline_section_address,
    531       .find_debuginfo = find_no_debuginfo
    532     };
    533   Dwfl *dwfl = dwfl_begin (&callbacks);
    534   if (likely (dwfl != NULL))
    535     /* Let 0 be the logical address of the file (or first in archive).  */
    536     dwfl->offline_next_address = 0;
    537   if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
    538     {
    539       struct stat64 st;
    540       if (fstat64 (fd, &st) != 0)
    541 	error (0, errno, gettext ("cannot stat input file"));
    542       else if (unlikely (st.st_size == 0))
    543 	error (0, 0, gettext ("input file is empty"));
    544       else
    545 	error (0, 0, gettext ("failed reading '%s': %s"),
    546 	       fname, dwfl_errmsg (-1));
    547     }
    548   else
    549     {
    550       dwfl_report_end (dwfl, NULL, NULL);
    551 
    552       if (only_one)
    553 	{
    554 	  /* Clear ONLY_ONE if we have multiple modules, from an archive.  */
    555 	  bool seen = false;
    556 	  only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
    557 	}
    558 
    559       /* Process the one or more modules gleaned from this file.  */
    560       struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
    561       dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
    562     }
    563   dwfl_end (dwfl);
    564 }
    565 
    566 
    567 /* Process one ELF file.  */
    568 static void
    569 process_elf_file (Dwfl_Module *dwflmod, int fd)
    570 {
    571   GElf_Addr dwflbias;
    572   Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
    573 
    574   GElf_Ehdr ehdr_mem;
    575   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
    576 
    577   if (ehdr == NULL)
    578     {
    579     elf_error:
    580       error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
    581       return;
    582     }
    583 
    584   Ebl *ebl = ebl_openbackend (elf);
    585   if (unlikely (ebl == NULL))
    586     {
    587     ebl_error:
    588       error (0, errno, gettext ("cannot create EBL handle"));
    589       return;
    590     }
    591 
    592   /* Determine the number of sections.  */
    593   if (unlikely (elf_getshnum (ebl->elf, &shnum) < 0))
    594     error (EXIT_FAILURE, 0,
    595 	   gettext ("cannot determine number of sections: %s"),
    596 	   elf_errmsg (-1));
    597 
    598   /* For an ET_REL file, libdwfl has adjusted the in-core shdrs
    599      and may have applied relocation to some sections.
    600      So we need to get a fresh Elf handle on the file to display those.  */
    601   bool print_unrelocated = (print_section_header
    602 			    || print_relocations
    603 			    || dump_data_sections != NULL
    604 			    || print_notes);
    605 
    606   Elf *pure_elf = NULL;
    607   Ebl *pure_ebl = ebl;
    608   if (ehdr->e_type == ET_REL && print_unrelocated)
    609     {
    610       /* Read the file afresh.  */
    611       off64_t aroff = elf_getaroff (elf);
    612       pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
    613       if (aroff > 0)
    614 	{
    615 	  /* Archive member.  */
    616 	  (void) elf_rand (pure_elf, aroff);
    617 	  Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
    618 	  elf_end (pure_elf);
    619 	  pure_elf = armem;
    620 	}
    621       if (pure_elf == NULL)
    622 	goto elf_error;
    623       pure_ebl = ebl_openbackend (pure_elf);
    624       if (pure_ebl == NULL)
    625 	goto ebl_error;
    626     }
    627 
    628   if (print_file_header)
    629     print_ehdr (ebl, ehdr);
    630   if (print_section_header)
    631     print_shdr (pure_ebl, ehdr);
    632   if (print_program_header)
    633     print_phdr (ebl, ehdr);
    634   if (print_section_groups)
    635     print_scngrp (ebl);
    636   if (print_dynamic_table)
    637     print_dynamic (ebl, ehdr);
    638   if (print_relocations)
    639     print_relocs (pure_ebl);
    640   if (print_histogram)
    641     handle_hash (ebl);
    642   if (print_symbol_table)
    643     print_symtab (ebl, SHT_DYNSYM);
    644   if (print_version_info)
    645     print_verinfo (ebl);
    646   if (print_symbol_table)
    647     print_symtab (ebl, SHT_SYMTAB);
    648   if (print_arch)
    649     print_liblist (ebl);
    650   if (print_arch)
    651     print_attributes (ebl, ehdr);
    652   if (dump_data_sections != NULL)
    653     dump_data (pure_ebl);
    654   if (string_sections != NULL)
    655     dump_strings (ebl);
    656   if (print_debug_sections != 0)
    657     print_debug (dwflmod, ebl, ehdr);
    658   if (print_notes)
    659     handle_notes (pure_ebl, ehdr);
    660   if (print_string_sections)
    661     print_strings (ebl);
    662 
    663   ebl_closebackend (ebl);
    664 
    665   if (pure_ebl != ebl)
    666     {
    667       ebl_closebackend (pure_ebl);
    668       elf_end (pure_elf);
    669     }
    670 }
    671 
    672 
    673 /* Print file type.  */
    674 static void
    675 print_file_type (unsigned short int e_type)
    676 {
    677   if (likely (e_type <= ET_CORE))
    678     {
    679       static const char *const knowntypes[] =
    680       {
    681 	N_("NONE (None)"),
    682 	N_("REL (Relocatable file)"),
    683 	N_("EXEC (Executable file)"),
    684 	N_("DYN (Shared object file)"),
    685 	N_("CORE (Core file)")
    686       };
    687       puts (gettext (knowntypes[e_type]));
    688     }
    689   else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
    690     printf (gettext ("OS Specific: (%x)\n"),  e_type);
    691   else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
    692     printf (gettext ("Processor Specific: (%x)\n"),  e_type);
    693   else
    694     puts ("???");
    695 }
    696 
    697 
    698 /* Print ELF header.  */
    699 static void
    700 print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
    701 {
    702   fputs_unlocked (gettext ("ELF Header:\n  Magic:  "), stdout);
    703   for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
    704     printf (" %02hhx", ehdr->e_ident[cnt]);
    705 
    706   printf (gettext ("\n  Class:                             %s\n"),
    707 	  ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
    708 	  : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
    709 	  : "\?\?\?");
    710 
    711   printf (gettext ("  Data:                              %s\n"),
    712 	  ehdr->e_ident[EI_DATA] == ELFDATA2LSB
    713 	  ? "2's complement, little endian"
    714 	  : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
    715 	  ? "2's complement, big endian" : "\?\?\?");
    716 
    717   printf (gettext ("  Ident Version:                     %hhd %s\n"),
    718 	  ehdr->e_ident[EI_VERSION],
    719 	  ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
    720 	  : "(\?\?\?)");
    721 
    722   char buf[512];
    723   printf (gettext ("  OS/ABI:                            %s\n"),
    724 	  ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
    725 
    726   printf (gettext ("  ABI Version:                       %hhd\n"),
    727 	  ehdr->e_ident[EI_ABIVERSION]);
    728 
    729   fputs_unlocked (gettext ("  Type:                              "), stdout);
    730   print_file_type (ehdr->e_type);
    731 
    732   printf (gettext ("  Machine:                           %s\n"), ebl->name);
    733 
    734   printf (gettext ("  Version:                           %d %s\n"),
    735 	  ehdr->e_version,
    736 	  ehdr->e_version  == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
    737 
    738   printf (gettext ("  Entry point address:               %#" PRIx64 "\n"),
    739 	  ehdr->e_entry);
    740 
    741   printf (gettext ("  Start of program headers:          %" PRId64 " %s\n"),
    742 	  ehdr->e_phoff, gettext ("(bytes into file)"));
    743 
    744   printf (gettext ("  Start of section headers:          %" PRId64 " %s\n"),
    745 	  ehdr->e_shoff, gettext ("(bytes into file)"));
    746 
    747   printf (gettext ("  Flags:                             %s\n"),
    748 	  ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
    749 
    750   printf (gettext ("  Size of this header:               %" PRId16 " %s\n"),
    751 	  ehdr->e_ehsize, gettext ("(bytes)"));
    752 
    753   printf (gettext ("  Size of program header entries:    %" PRId16 " %s\n"),
    754 	  ehdr->e_phentsize, gettext ("(bytes)"));
    755 
    756   printf (gettext ("  Number of program headers entries: %" PRId16 "\n"),
    757 	  ehdr->e_phnum);
    758 
    759   printf (gettext ("  Size of section header entries:    %" PRId16 " %s\n"),
    760 	  ehdr->e_shentsize, gettext ("(bytes)"));
    761 
    762   printf (gettext ("  Number of section headers entries: %" PRId16),
    763 	  ehdr->e_shnum);
    764   if (ehdr->e_shnum == 0)
    765     {
    766       GElf_Shdr shdr_mem;
    767       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
    768       if (shdr != NULL)
    769 	printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
    770 		(uint32_t) shdr->sh_size);
    771       else
    772 	fputs_unlocked (gettext (" ([0] not available)"), stdout);
    773     }
    774   fputc_unlocked ('\n', stdout);
    775 
    776   if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
    777     {
    778       GElf_Shdr shdr_mem;
    779       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
    780       if (shdr != NULL)
    781 	/* We managed to get the zeroth section.  */
    782 	snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
    783 		  (uint32_t) shdr->sh_link);
    784       else
    785 	{
    786 	  strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
    787 	  buf[sizeof (buf) - 1] = '\0';
    788 	}
    789 
    790       printf (gettext ("  Section header string table index: XINDEX%s\n\n"),
    791 	      buf);
    792     }
    793   else
    794     printf (gettext ("  Section header string table index: %" PRId16 "\n\n"),
    795 	    ehdr->e_shstrndx);
    796 }
    797 
    798 
    799 static const char *
    800 get_visibility_type (int value)
    801 {
    802   switch (value)
    803     {
    804     case STV_DEFAULT:
    805       return "DEFAULT";
    806     case STV_INTERNAL:
    807       return "INTERNAL";
    808     case STV_HIDDEN:
    809       return "HIDDEN";
    810     case STV_PROTECTED:
    811       return "PROTECTED";
    812     default:
    813       return "???";
    814     }
    815 }
    816 
    817 
    818 /* Print the section headers.  */
    819 static void
    820 print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
    821 {
    822   size_t cnt;
    823   size_t shstrndx;
    824 
    825   if (! print_file_header)
    826     printf (gettext ("\
    827 There are %d section headers, starting at offset %#" PRIx64 ":\n\
    828 \n"),
    829 	    ehdr->e_shnum, ehdr->e_shoff);
    830 
    831   /* Get the section header string table index.  */
    832   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
    833     error (EXIT_FAILURE, 0,
    834 	   gettext ("cannot get section header string table index"));
    835 
    836   puts (gettext ("Section Headers:"));
    837 
    838   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
    839     puts (gettext ("[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al"));
    840   else
    841     puts (gettext ("[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al"));
    842 
    843   for (cnt = 0; cnt < shnum; ++cnt)
    844     {
    845       Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
    846 
    847       if (unlikely (scn == NULL))
    848 	error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
    849 	       elf_errmsg (-1));
    850 
    851       /* Get the section header.  */
    852       GElf_Shdr shdr_mem;
    853       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    854       if (unlikely (shdr == NULL))
    855 	error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
    856 	       elf_errmsg (-1));
    857 
    858       char flagbuf[20];
    859       char *cp = flagbuf;
    860       if (shdr->sh_flags & SHF_WRITE)
    861 	*cp++ = 'W';
    862       if (shdr->sh_flags & SHF_ALLOC)
    863 	*cp++ = 'A';
    864       if (shdr->sh_flags & SHF_EXECINSTR)
    865 	*cp++ = 'X';
    866       if (shdr->sh_flags & SHF_MERGE)
    867 	*cp++ = 'M';
    868       if (shdr->sh_flags & SHF_STRINGS)
    869 	*cp++ = 'S';
    870       if (shdr->sh_flags & SHF_INFO_LINK)
    871 	*cp++ = 'I';
    872       if (shdr->sh_flags & SHF_LINK_ORDER)
    873 	*cp++ = 'L';
    874       if (shdr->sh_flags & SHF_OS_NONCONFORMING)
    875 	*cp++ = 'N';
    876       if (shdr->sh_flags & SHF_GROUP)
    877 	*cp++ = 'G';
    878       if (shdr->sh_flags & SHF_TLS)
    879 	*cp++ = 'T';
    880       if (shdr->sh_flags & SHF_ORDERED)
    881 	*cp++ = 'O';
    882       if (shdr->sh_flags & SHF_EXCLUDE)
    883 	*cp++ = 'E';
    884       *cp = '\0';
    885 
    886       char buf[128];
    887       printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
    888 	      " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
    889 	      " %2" PRId64 "\n",
    890 	      cnt,
    891 	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
    892 	      ?: "<corrupt>",
    893 	      ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
    894 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
    895 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
    896 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
    897 	      shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
    898 	      shdr->sh_addralign);
    899     }
    900 
    901   fputc_unlocked ('\n', stdout);
    902 }
    903 
    904 
    905 /* Print the program header.  */
    906 static void
    907 print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
    908 {
    909   if (ehdr->e_phnum == 0)
    910     /* No program header, this is OK in relocatable objects.  */
    911     return;
    912 
    913   puts (gettext ("Program Headers:"));
    914   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
    915     puts (gettext ("\
    916   Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"));
    917   else
    918     puts (gettext ("\
    919   Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align"));
    920 
    921   /* Process all program headers.  */
    922   bool has_relro = false;
    923   GElf_Addr relro_from = 0;
    924   GElf_Addr relro_to = 0;
    925   for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt)
    926     {
    927       char buf[128];
    928       GElf_Phdr mem;
    929       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
    930 
    931       /* If for some reason the header cannot be returned show this.  */
    932       if (unlikely (phdr == NULL))
    933 	{
    934 	  puts ("  ???");
    935 	  continue;
    936 	}
    937 
    938       printf ("  %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
    939 	      " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
    940 	      ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
    941 	      phdr->p_offset,
    942 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
    943 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
    944 	      phdr->p_filesz,
    945 	      phdr->p_memsz,
    946 	      phdr->p_flags & PF_R ? 'R' : ' ',
    947 	      phdr->p_flags & PF_W ? 'W' : ' ',
    948 	      phdr->p_flags & PF_X ? 'E' : ' ',
    949 	      phdr->p_align);
    950 
    951       if (phdr->p_type == PT_INTERP)
    952 	{
    953 	  /* We can show the user the name of the interpreter.  */
    954 	  size_t maxsize;
    955 	  char *filedata = elf_rawfile (ebl->elf, &maxsize);
    956 
    957 	  if (filedata != NULL && phdr->p_offset < maxsize)
    958 	    printf (gettext ("\t[Requesting program interpreter: %s]\n"),
    959 		    filedata + phdr->p_offset);
    960 	}
    961       else if (phdr->p_type == PT_GNU_RELRO)
    962 	{
    963 	  has_relro = true;
    964 	  relro_from = phdr->p_vaddr;
    965 	  relro_to = relro_from + phdr->p_memsz;
    966 	}
    967     }
    968 
    969   /* Get the section header string table index.  */
    970   size_t shstrndx;
    971   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
    972     error (EXIT_FAILURE, 0,
    973 	   gettext ("cannot get section header string table index"));
    974 
    975   puts (gettext ("\n Section to Segment mapping:\n  Segment Sections..."));
    976 
    977   for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt)
    978     {
    979       /* Print the segment number.  */
    980       printf ("   %2.2zu     ", cnt);
    981 
    982       GElf_Phdr phdr_mem;
    983       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
    984       /* This must not happen.  */
    985       if (unlikely (phdr == NULL))
    986 	error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
    987 	       elf_errmsg (-1));
    988 
    989       /* Iterate over the sections.  */
    990       bool in_relro = false;
    991       bool in_ro = false;
    992       for (size_t inner = 1; inner < shnum; ++inner)
    993 	{
    994 	  Elf_Scn *scn = elf_getscn (ebl->elf, inner);
    995 	  /* This should not happen.  */
    996 	  if (unlikely (scn == NULL))
    997 	    error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
    998 		   elf_errmsg (-1));
    999 
   1000 	  /* Get the section header.  */
   1001 	  GElf_Shdr shdr_mem;
   1002 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1003 	  if (unlikely (shdr == NULL))
   1004 	    error (EXIT_FAILURE, 0,
   1005 		   gettext ("cannot get section header: %s"),
   1006 		   elf_errmsg (-1));
   1007 
   1008 	  if (shdr->sh_size > 0
   1009 	      /* Compare allocated sections by VMA, unallocated
   1010 		 sections by file offset.  */
   1011 	      && (shdr->sh_flags & SHF_ALLOC
   1012 		  ? (shdr->sh_addr >= phdr->p_vaddr
   1013 		     && (shdr->sh_addr + shdr->sh_size
   1014 			 <= phdr->p_vaddr + phdr->p_memsz))
   1015 		  : (shdr->sh_offset >= phdr->p_offset
   1016 		     && (shdr->sh_offset + shdr->sh_size
   1017 			 <= phdr->p_offset + phdr->p_filesz))))
   1018 	    {
   1019 	      if (has_relro && !in_relro
   1020 		  && shdr->sh_addr >= relro_from
   1021 		  && shdr->sh_addr + shdr->sh_size <= relro_to)
   1022 		{
   1023 		  fputs_unlocked (" [RELRO:", stdout);
   1024 		  in_relro = true;
   1025 		}
   1026 	      else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
   1027 		{
   1028 		  fputs_unlocked ("]", stdout);
   1029 		  in_relro =  false;
   1030 		}
   1031 	      else if (has_relro && in_relro
   1032 		       && shdr->sh_addr + shdr->sh_size > relro_to)
   1033 		fputs_unlocked ("] <RELRO:", stdout);
   1034 	      else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
   1035 		{
   1036 		  if (!in_ro)
   1037 		    {
   1038 		      fputs_unlocked (" [RO:", stdout);
   1039 		      in_ro = true;
   1040 		    }
   1041 		}
   1042 	      else
   1043 		{
   1044 		  /* Determine the segment this section is part of.  */
   1045 		  size_t cnt2;
   1046 		  GElf_Phdr *phdr2 = NULL;
   1047 		  for (cnt2 = 0; cnt2 < ehdr->e_phnum; ++cnt2)
   1048 		    {
   1049 		      GElf_Phdr phdr2_mem;
   1050 		      phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
   1051 
   1052 		      if (phdr2 != NULL && phdr2->p_type == PT_LOAD
   1053 			  && shdr->sh_addr >= phdr2->p_vaddr
   1054 			  && (shdr->sh_addr + shdr->sh_size
   1055 			      <= phdr2->p_vaddr + phdr2->p_memsz))
   1056 			break;
   1057 		    }
   1058 
   1059 		  if (cnt2 < ehdr->e_phnum)
   1060 		    {
   1061 		      if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
   1062 			{
   1063 			  fputs_unlocked (" [RO:", stdout);
   1064 			  in_ro = true;
   1065 			}
   1066 		      else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
   1067 			{
   1068 			  fputs_unlocked ("]", stdout);
   1069 			  in_ro = false;
   1070 			}
   1071 		    }
   1072 		}
   1073 
   1074 	      printf (" %s",
   1075 		      elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
   1076 
   1077 	      /* Signal that this sectin is only partially covered.  */
   1078 	      if (has_relro && in_relro
   1079 		       && shdr->sh_addr + shdr->sh_size > relro_to)
   1080 		{
   1081 		  fputs_unlocked (">", stdout);
   1082 		  in_relro =  false;
   1083 		}
   1084 	    }
   1085 	}
   1086       if (in_relro || in_ro)
   1087 	fputs_unlocked ("]", stdout);
   1088 
   1089       /* Finish the line.  */
   1090       fputc_unlocked ('\n', stdout);
   1091     }
   1092 }
   1093 
   1094 
   1095 static void
   1096 handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   1097 {
   1098   /* Get the data of the section.  */
   1099   Elf_Data *data = elf_getdata (scn, NULL);
   1100 
   1101   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
   1102   GElf_Shdr symshdr_mem;
   1103   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
   1104   Elf_Data *symdata = elf_getdata (symscn, NULL);
   1105 
   1106   if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
   1107       || symdata == NULL)
   1108     return;
   1109 
   1110   /* Get the section header string table index.  */
   1111   size_t shstrndx;
   1112   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
   1113     error (EXIT_FAILURE, 0,
   1114 	   gettext ("cannot get section header string table index"));
   1115 
   1116   Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
   1117 
   1118   GElf_Sym sym_mem;
   1119   printf ((grpref[0] & GRP_COMDAT)
   1120 	  ? ngettext ("\
   1121 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
   1122 		      "\
   1123 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
   1124 		      data->d_size / sizeof (Elf32_Word) - 1)
   1125 	  : ngettext ("\
   1126 \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
   1127 \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
   1128 		      data->d_size / sizeof (Elf32_Word) - 1),
   1129 	  elf_ndxscn (scn),
   1130 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   1131 	  elf_strptr (ebl->elf, symshdr->sh_link,
   1132 		      gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name)
   1133 	  ?: gettext ("<INVALID SYMBOL>"),
   1134 	  data->d_size / sizeof (Elf32_Word) - 1);
   1135 
   1136   for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
   1137     {
   1138       GElf_Shdr grpshdr_mem;
   1139       GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
   1140 					 &grpshdr_mem);
   1141 
   1142       const char *str;
   1143       printf ("  [%2u] %s\n",
   1144 	      grpref[cnt],
   1145 	      grpshdr != NULL
   1146 	      && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
   1147 	      ? str : gettext ("<INVALID SECTION>"));
   1148     }
   1149 }
   1150 
   1151 
   1152 static void
   1153 print_scngrp (Ebl *ebl)
   1154 {
   1155   /* Find all relocation sections and handle them.  */
   1156   Elf_Scn *scn = NULL;
   1157 
   1158   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   1159     {
   1160        /* Handle the section if it is a symbol table.  */
   1161       GElf_Shdr shdr_mem;
   1162       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1163 
   1164       if (shdr != NULL && shdr->sh_type == SHT_GROUP)
   1165 	handle_scngrp (ebl, scn, shdr);
   1166     }
   1167 }
   1168 
   1169 
   1170 static const struct flags
   1171 {
   1172   int mask;
   1173   const char *str;
   1174 } dt_flags[] =
   1175   {
   1176     { DF_ORIGIN, "ORIGIN" },
   1177     { DF_SYMBOLIC, "SYMBOLIC" },
   1178     { DF_TEXTREL, "TEXTREL" },
   1179     { DF_BIND_NOW, "BIND_NOW" },
   1180     { DF_STATIC_TLS, "STATIC_TLS" }
   1181   };
   1182 static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
   1183 
   1184 static const struct flags dt_flags_1[] =
   1185   {
   1186     { DF_1_NOW, "NOW" },
   1187     { DF_1_GLOBAL, "GLOBAL" },
   1188     { DF_1_GROUP, "GROUP" },
   1189     { DF_1_NODELETE, "NODELETE" },
   1190     { DF_1_LOADFLTR, "LOADFLTR" },
   1191     { DF_1_INITFIRST, "INITFIRST" },
   1192     { DF_1_NOOPEN, "NOOPEN" },
   1193     { DF_1_ORIGIN, "ORIGIN" },
   1194     { DF_1_DIRECT, "DIRECT" },
   1195     { DF_1_TRANS, "TRANS" },
   1196     { DF_1_INTERPOSE, "INTERPOSE" },
   1197     { DF_1_NODEFLIB, "NODEFLIB" },
   1198     { DF_1_NODUMP, "NODUMP" },
   1199     { DF_1_CONFALT, "CONFALT" },
   1200     { DF_1_ENDFILTEE, "ENDFILTEE" },
   1201     { DF_1_DISPRELDNE, "DISPRELDNE" },
   1202     { DF_1_DISPRELPND, "DISPRELPND" },
   1203   };
   1204 static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
   1205 
   1206 static const struct flags dt_feature_1[] =
   1207   {
   1208     { DTF_1_PARINIT, "PARINIT" },
   1209     { DTF_1_CONFEXP, "CONFEXP" }
   1210   };
   1211 static const int ndt_feature_1 = (sizeof (dt_feature_1)
   1212 				  / sizeof (dt_feature_1[0]));
   1213 
   1214 static const struct flags dt_posflag_1[] =
   1215   {
   1216     { DF_P1_LAZYLOAD, "LAZYLOAD" },
   1217     { DF_P1_GROUPPERM, "GROUPPERM" }
   1218   };
   1219 static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
   1220 				  / sizeof (dt_posflag_1[0]));
   1221 
   1222 
   1223 static void
   1224 print_flags (int class, GElf_Xword d_val, const struct flags *flags,
   1225 		int nflags)
   1226 {
   1227   bool first = true;
   1228   int cnt;
   1229 
   1230   for (cnt = 0; cnt < nflags; ++cnt)
   1231     if (d_val & flags[cnt].mask)
   1232       {
   1233 	if (!first)
   1234 	  putchar_unlocked (' ');
   1235 	fputs_unlocked (flags[cnt].str, stdout);
   1236 	d_val &= ~flags[cnt].mask;
   1237 	first = false;
   1238       }
   1239 
   1240   if (d_val != 0)
   1241     {
   1242       if (!first)
   1243 	putchar_unlocked (' ');
   1244       printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
   1245     }
   1246 
   1247   putchar_unlocked ('\n');
   1248 }
   1249 
   1250 
   1251 static void
   1252 print_dt_flags (int class, GElf_Xword d_val)
   1253 {
   1254   print_flags (class, d_val, dt_flags, ndt_flags);
   1255 }
   1256 
   1257 
   1258 static void
   1259 print_dt_flags_1 (int class, GElf_Xword d_val)
   1260 {
   1261   print_flags (class, d_val, dt_flags_1, ndt_flags_1);
   1262 }
   1263 
   1264 
   1265 static void
   1266 print_dt_feature_1 (int class, GElf_Xword d_val)
   1267 {
   1268   print_flags (class, d_val, dt_feature_1, ndt_feature_1);
   1269 }
   1270 
   1271 
   1272 static void
   1273 print_dt_posflag_1 (int class, GElf_Xword d_val)
   1274 {
   1275   print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
   1276 }
   1277 
   1278 
   1279 static void
   1280 handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   1281 {
   1282   int class = gelf_getclass (ebl->elf);
   1283   GElf_Shdr glink;
   1284   Elf_Data *data;
   1285   size_t cnt;
   1286   size_t shstrndx;
   1287 
   1288   /* Get the data of the section.  */
   1289   data = elf_getdata (scn, NULL);
   1290   if (data == NULL)
   1291     return;
   1292 
   1293   /* Get the section header string table index.  */
   1294   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
   1295     error (EXIT_FAILURE, 0,
   1296 	   gettext ("cannot get section header string table index"));
   1297 
   1298   printf (ngettext ("\
   1299 \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   1300 		    "\
   1301 \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   1302 		    shdr->sh_size / shdr->sh_entsize),
   1303 	  (unsigned long int) (shdr->sh_size / shdr->sh_entsize),
   1304 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   1305 	  shdr->sh_offset,
   1306 	  (int) shdr->sh_link,
   1307 	  elf_strptr (ebl->elf, shstrndx,
   1308 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   1309 				    &glink)->sh_name));
   1310   fputs_unlocked (gettext ("  Type              Value\n"), stdout);
   1311 
   1312   for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
   1313     {
   1314       GElf_Dyn dynmem;
   1315       GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
   1316       if (dyn == NULL)
   1317 	break;
   1318 
   1319       char buf[64];
   1320       printf ("  %-17s ",
   1321 	      ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
   1322 
   1323       switch (dyn->d_tag)
   1324 	{
   1325 	case DT_NULL:
   1326 	case DT_DEBUG:
   1327 	case DT_BIND_NOW:
   1328 	case DT_TEXTREL:
   1329 	  /* No further output.  */
   1330 	  fputc_unlocked ('\n', stdout);
   1331 	  break;
   1332 
   1333 	case DT_NEEDED:
   1334 	  printf (gettext ("Shared library: [%s]\n"),
   1335 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1336 	  break;
   1337 
   1338 	case DT_SONAME:
   1339 	  printf (gettext ("Library soname: [%s]\n"),
   1340 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1341 	  break;
   1342 
   1343 	case DT_RPATH:
   1344 	  printf (gettext ("Library rpath: [%s]\n"),
   1345 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1346 	  break;
   1347 
   1348 	case DT_RUNPATH:
   1349 	  printf (gettext ("Library runpath: [%s]\n"),
   1350 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1351 	  break;
   1352 
   1353 	case DT_PLTRELSZ:
   1354 	case DT_RELASZ:
   1355 	case DT_STRSZ:
   1356 	case DT_RELSZ:
   1357 	case DT_RELAENT:
   1358 	case DT_SYMENT:
   1359 	case DT_RELENT:
   1360 	case DT_PLTPADSZ:
   1361 	case DT_MOVEENT:
   1362 	case DT_MOVESZ:
   1363 	case DT_INIT_ARRAYSZ:
   1364 	case DT_FINI_ARRAYSZ:
   1365 	case DT_SYMINSZ:
   1366 	case DT_SYMINENT:
   1367 	case DT_GNU_CONFLICTSZ:
   1368 	case DT_GNU_LIBLISTSZ:
   1369 	  printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
   1370 	  break;
   1371 
   1372 	case DT_VERDEFNUM:
   1373 	case DT_VERNEEDNUM:
   1374 	case DT_RELACOUNT:
   1375 	case DT_RELCOUNT:
   1376 	  printf ("%" PRId64 "\n", dyn->d_un.d_val);
   1377 	  break;
   1378 
   1379 	case DT_PLTREL:
   1380 	  puts (ebl_dynamic_tag_name (ebl, dyn->d_un.d_val, NULL, 0));
   1381 	  break;
   1382 
   1383 	case DT_FLAGS:
   1384 	  print_dt_flags (class, dyn->d_un.d_val);
   1385 	  break;
   1386 
   1387 	case DT_FLAGS_1:
   1388 	  print_dt_flags_1 (class, dyn->d_un.d_val);
   1389 	  break;
   1390 
   1391 	case DT_FEATURE_1:
   1392 	  print_dt_feature_1 (class, dyn->d_un.d_val);
   1393 	  break;
   1394 
   1395 	case DT_POSFLAG_1:
   1396 	  print_dt_posflag_1 (class, dyn->d_un.d_val);
   1397 	  break;
   1398 
   1399 	default:
   1400 	  printf ("%#0*" PRIx64 "\n",
   1401 		  class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
   1402 	  break;
   1403 	}
   1404     }
   1405 }
   1406 
   1407 
   1408 /* Print the dynamic segment.  */
   1409 static void
   1410 print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr)
   1411 {
   1412   for (int i = 0; i < ehdr->e_phnum; ++i)
   1413     {
   1414       GElf_Phdr phdr_mem;
   1415       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
   1416 
   1417       if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
   1418 	{
   1419 	  Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
   1420 	  GElf_Shdr shdr_mem;
   1421 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1422 	  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
   1423 	    handle_dynamic (ebl, scn, shdr);
   1424 	  break;
   1425 	}
   1426     }
   1427 }
   1428 
   1429 
   1430 /* Print relocations.  */
   1431 static void
   1432 print_relocs (Ebl *ebl)
   1433 {
   1434   /* Find all relocation sections and handle them.  */
   1435   Elf_Scn *scn = NULL;
   1436 
   1437   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   1438     {
   1439        /* Handle the section if it is a symbol table.  */
   1440       GElf_Shdr shdr_mem;
   1441       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1442 
   1443       if (likely (shdr != NULL))
   1444 	{
   1445 	  if (shdr->sh_type == SHT_REL)
   1446 	    handle_relocs_rel (ebl, scn, shdr);
   1447 	  else if (shdr->sh_type == SHT_RELA)
   1448 	    handle_relocs_rela (ebl, scn, shdr);
   1449 	}
   1450     }
   1451 }
   1452 
   1453 
   1454 /* Handle a relocation section.  */
   1455 static void
   1456 handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   1457 {
   1458   int class = gelf_getclass (ebl->elf);
   1459   int nentries = shdr->sh_size / shdr->sh_entsize;
   1460 
   1461   /* Get the data of the section.  */
   1462   Elf_Data *data = elf_getdata (scn, NULL);
   1463   if (data == NULL)
   1464     return;
   1465 
   1466   /* Get the symbol table information.  */
   1467   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
   1468   GElf_Shdr symshdr_mem;
   1469   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
   1470   Elf_Data *symdata = elf_getdata (symscn, NULL);
   1471 
   1472   /* Get the section header of the section the relocations are for.  */
   1473   GElf_Shdr destshdr_mem;
   1474   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
   1475 				      &destshdr_mem);
   1476 
   1477   if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
   1478     {
   1479       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
   1480 	      shdr->sh_offset);
   1481       return;
   1482     }
   1483 
   1484   /* Search for the optional extended section index table.  */
   1485   Elf_Data *xndxdata = NULL;
   1486   int xndxscnidx = elf_scnshndx (scn);
   1487   if (unlikely (xndxscnidx > 0))
   1488     xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
   1489 
   1490   /* Get the section header string table index.  */
   1491   size_t shstrndx;
   1492   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
   1493     error (EXIT_FAILURE, 0,
   1494 	   gettext ("cannot get section header string table index"));
   1495 
   1496   if (shdr->sh_info != 0)
   1497     printf (ngettext ("\
   1498 \nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   1499 		    "\
   1500 \nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   1501 		      nentries),
   1502 	    (unsigned int) elf_ndxscn (scn),
   1503 	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   1504 	    (unsigned int) shdr->sh_info,
   1505 	    elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
   1506 	    shdr->sh_offset,
   1507 	    nentries);
   1508   else
   1509     /* The .rel.dyn section does not refer to a specific section but
   1510        instead of section index zero.  Do not try to print a section
   1511        name.  */
   1512     printf (ngettext ("\
   1513 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   1514 		    "\
   1515 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   1516 		      nentries),
   1517 	    (unsigned int) elf_ndxscn (scn),
   1518 	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   1519 	    shdr->sh_offset,
   1520 	    nentries);
   1521   fputs_unlocked (class == ELFCLASS32
   1522 		  ? gettext ("\
   1523   Offset      Type                 Value       Name\n")
   1524 		  : gettext ("\
   1525   Offset              Type                 Value               Name\n"),
   1526 	 stdout);
   1527 
   1528   for (int cnt = 0; cnt < nentries; ++cnt)
   1529     {
   1530       GElf_Rel relmem;
   1531       GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
   1532       if (likely (rel != NULL))
   1533 	{
   1534 	  char buf[128];
   1535 	  GElf_Sym symmem;
   1536 	  Elf32_Word xndx;
   1537 	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
   1538 					    GELF_R_SYM (rel->r_info),
   1539 					    &symmem, &xndx);
   1540 	  if (unlikely (sym == NULL))
   1541 	    printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
   1542 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1543 		    ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1544 		    /* Avoid the leading R_ which isn't carrying any
   1545 		       information.  */
   1546 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1547 					   buf, sizeof (buf)) + 2
   1548 		    : gettext ("<INVALID RELOC>"),
   1549 		    gettext ("INVALID SYMBOL"),
   1550 		    (long int) GELF_R_SYM (rel->r_info));
   1551 	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
   1552 	    printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
   1553 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1554 		    likely (ebl_reloc_type_check (ebl,
   1555 						  GELF_R_TYPE (rel->r_info)))
   1556 		    /* Avoid the leading R_ which isn't carrying any
   1557 		       information.  */
   1558 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1559 					   buf, sizeof (buf)) + 2
   1560 		    : gettext ("<INVALID RELOC>"),
   1561 		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
   1562 		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
   1563 	  else
   1564 	    {
   1565 	      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
   1566 						   sym->st_shndx == SHN_XINDEX
   1567 						   ? xndx : sym->st_shndx),
   1568 				       &destshdr_mem);
   1569 
   1570 	      if (unlikely (destshdr == NULL))
   1571 		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
   1572 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1573 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1574 			/* Avoid the leading R_ which isn't carrying any
   1575 			   information.  */
   1576 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1577 					       buf, sizeof (buf)) + 2
   1578 			: gettext ("<INVALID RELOC>"),
   1579 			gettext ("INVALID SECTION"),
   1580 			(long int) (sym->st_shndx == SHN_XINDEX
   1581 				    ? xndx : sym->st_shndx));
   1582 	      else
   1583 		printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
   1584 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1585 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1586 			/* Avoid the leading R_ which isn't carrying any
   1587 			   information.  */
   1588 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1589 					       buf, sizeof (buf)) + 2
   1590 			: gettext ("<INVALID RELOC>"),
   1591 			class == ELFCLASS32 ? 10 : 18, sym->st_value,
   1592 			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
   1593 	    }
   1594 	}
   1595     }
   1596 }
   1597 
   1598 
   1599 /* Handle a relocation section.  */
   1600 static void
   1601 handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   1602 {
   1603   int class = gelf_getclass (ebl->elf);
   1604   int nentries = shdr->sh_size / shdr->sh_entsize;
   1605 
   1606   /* Get the data of the section.  */
   1607   Elf_Data *data = elf_getdata (scn, NULL);
   1608   if (data == NULL)
   1609     return;
   1610 
   1611   /* Get the symbol table information.  */
   1612   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
   1613   GElf_Shdr symshdr_mem;
   1614   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
   1615   Elf_Data *symdata = elf_getdata (symscn, NULL);
   1616 
   1617   /* Get the section header of the section the relocations are for.  */
   1618   GElf_Shdr destshdr_mem;
   1619   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
   1620 				      &destshdr_mem);
   1621 
   1622   if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
   1623     {
   1624       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
   1625 	      shdr->sh_offset);
   1626       return;
   1627     }
   1628 
   1629   /* Search for the optional extended section index table.  */
   1630   Elf_Data *xndxdata = NULL;
   1631   int xndxscnidx = elf_scnshndx (scn);
   1632   if (unlikely (xndxscnidx > 0))
   1633     xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
   1634 
   1635   /* Get the section header string table index.  */
   1636   size_t shstrndx;
   1637   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
   1638     error (EXIT_FAILURE, 0,
   1639 	   gettext ("cannot get section header string table index"));
   1640 
   1641   printf (ngettext ("\
   1642 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   1643 		    "\
   1644 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   1645 		    nentries),
   1646 	  elf_ndxscn (scn),
   1647 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   1648 	  (unsigned int) shdr->sh_info,
   1649 	  elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
   1650 	  shdr->sh_offset,
   1651 	  nentries);
   1652   fputs_unlocked (class == ELFCLASS32
   1653 		  ? gettext ("\
   1654   Offset      Type            Value       Addend Name\n")
   1655 		  : gettext ("\
   1656   Offset              Type            Value               Addend Name\n"),
   1657 		  stdout);
   1658 
   1659   for (int cnt = 0; cnt < nentries; ++cnt)
   1660     {
   1661       GElf_Rela relmem;
   1662       GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
   1663       if (likely (rel != NULL))
   1664 	{
   1665 	  char buf[64];
   1666 	  GElf_Sym symmem;
   1667 	  Elf32_Word xndx;
   1668 	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
   1669 					    GELF_R_SYM (rel->r_info),
   1670 					    &symmem, &xndx);
   1671 
   1672 	  if (unlikely (sym == NULL))
   1673 	    printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
   1674 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1675 		    ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1676 		    /* Avoid the leading R_ which isn't carrying any
   1677 		       information.  */
   1678 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1679 					   buf, sizeof (buf)) + 2
   1680 		    : gettext ("<INVALID RELOC>"),
   1681 		    gettext ("INVALID SYMBOL"),
   1682 		    (long int) GELF_R_SYM (rel->r_info));
   1683 	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
   1684 	    printf ("\
   1685   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
   1686 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1687 		    likely (ebl_reloc_type_check (ebl,
   1688 						  GELF_R_TYPE (rel->r_info)))
   1689 		    /* Avoid the leading R_ which isn't carrying any
   1690 		       information.  */
   1691 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1692 					   buf, sizeof (buf)) + 2
   1693 		    : gettext ("<INVALID RELOC>"),
   1694 		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
   1695 		    rel->r_addend,
   1696 		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
   1697 	  else
   1698 	    {
   1699 	      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
   1700 						   sym->st_shndx == SHN_XINDEX
   1701 						   ? xndx : sym->st_shndx),
   1702 				       &destshdr_mem);
   1703 
   1704 	      if (unlikely (shdr == NULL))
   1705 		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
   1706 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1707 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1708 			/* Avoid the leading R_ which isn't carrying any
   1709 			   information.  */
   1710 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1711 					       buf, sizeof (buf)) + 2
   1712 			: gettext ("<INVALID RELOC>"),
   1713 			gettext ("INVALID SECTION"),
   1714 			(long int) (sym->st_shndx == SHN_XINDEX
   1715 				    ? xndx : sym->st_shndx));
   1716 	      else
   1717 		printf ("\
   1718   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
   1719 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1720 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1721 			/* Avoid the leading R_ which isn't carrying any
   1722 			   information.  */
   1723 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1724 					       buf, sizeof (buf)) + 2
   1725 			: gettext ("<INVALID RELOC>"),
   1726 			class == ELFCLASS32 ? 10 : 18, sym->st_value,
   1727 			rel->r_addend,
   1728 			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
   1729 	    }
   1730 	}
   1731     }
   1732 }
   1733 
   1734 
   1735 /* Print the program header.  */
   1736 static void
   1737 print_symtab (Ebl *ebl, int type)
   1738 {
   1739   /* Find the symbol table(s).  For this we have to search through the
   1740      section table.  */
   1741   Elf_Scn *scn = NULL;
   1742 
   1743   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   1744     {
   1745       /* Handle the section if it is a symbol table.  */
   1746       GElf_Shdr shdr_mem;
   1747       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1748 
   1749       if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
   1750 	handle_symtab (ebl, scn, shdr);
   1751     }
   1752 }
   1753 
   1754 
   1755 static void
   1756 handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   1757 {
   1758   Elf_Data *versym_data = NULL;
   1759   Elf_Data *verneed_data = NULL;
   1760   Elf_Data *verdef_data = NULL;
   1761   Elf_Data *xndx_data = NULL;
   1762   int class = gelf_getclass (ebl->elf);
   1763   Elf32_Word verneed_stridx = 0;
   1764   Elf32_Word verdef_stridx = 0;
   1765 
   1766   /* Get the data of the section.  */
   1767   Elf_Data *data = elf_getdata (scn, NULL);
   1768   if (data == NULL)
   1769     return;
   1770 
   1771   /* Find out whether we have other sections we might need.  */
   1772   Elf_Scn *runscn = NULL;
   1773   while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
   1774     {
   1775       GElf_Shdr runshdr_mem;
   1776       GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
   1777 
   1778       if (likely (runshdr != NULL))
   1779 	{
   1780 	  if (runshdr->sh_type == SHT_GNU_versym
   1781 	      && runshdr->sh_link == elf_ndxscn (scn))
   1782 	    /* Bingo, found the version information.  Now get the data.  */
   1783 	    versym_data = elf_getdata (runscn, NULL);
   1784 	  else if (runshdr->sh_type == SHT_GNU_verneed)
   1785 	    {
   1786 	      /* This is the information about the needed versions.  */
   1787 	      verneed_data = elf_getdata (runscn, NULL);
   1788 	      verneed_stridx = runshdr->sh_link;
   1789 	    }
   1790 	  else if (runshdr->sh_type == SHT_GNU_verdef)
   1791 	    {
   1792 	      /* This is the information about the defined versions.  */
   1793 	      verdef_data = elf_getdata (runscn, NULL);
   1794 	      verdef_stridx = runshdr->sh_link;
   1795 	    }
   1796 	  else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
   1797 	      && runshdr->sh_link == elf_ndxscn (scn))
   1798 	    /* Extended section index.  */
   1799 	    xndx_data = elf_getdata (runscn, NULL);
   1800 	}
   1801     }
   1802 
   1803   /* Get the section header string table index.  */
   1804   size_t shstrndx;
   1805   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
   1806     error (EXIT_FAILURE, 0,
   1807 	   gettext ("cannot get section header string table index"));
   1808 
   1809   /* Now we can compute the number of entries in the section.  */
   1810   unsigned int nsyms = data->d_size / (class == ELFCLASS32
   1811 				       ? sizeof (Elf32_Sym)
   1812 				       : sizeof (Elf64_Sym));
   1813 
   1814   printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
   1815 		    "\nSymbol table [%2u] '%s' contains %u entries:\n",
   1816 		    nsyms),
   1817 	  (unsigned int) elf_ndxscn (scn),
   1818 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
   1819   GElf_Shdr glink;
   1820   printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
   1821 		    " %lu local symbols  String table: [%2u] '%s'\n",
   1822 		    shdr->sh_info),
   1823 	  (unsigned long int) shdr->sh_info,
   1824 	  (unsigned int) shdr->sh_link,
   1825 	  elf_strptr (ebl->elf, shstrndx,
   1826 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   1827 				    &glink)->sh_name));
   1828 
   1829   fputs_unlocked (class == ELFCLASS32
   1830 		  ? gettext ("\
   1831   Num:    Value   Size Type    Bind   Vis          Ndx Name\n")
   1832 		  : gettext ("\
   1833   Num:            Value   Size Type    Bind   Vis          Ndx Name\n"),
   1834 		  stdout);
   1835 
   1836   for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
   1837     {
   1838       char typebuf[64];
   1839       char bindbuf[64];
   1840       char scnbuf[64];
   1841       Elf32_Word xndx;
   1842       GElf_Sym sym_mem;
   1843       GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
   1844 
   1845       if (unlikely (sym == NULL))
   1846 	continue;
   1847 
   1848       /* Determine the real section index.  */
   1849       if (likely (sym->st_shndx != SHN_XINDEX))
   1850 	xndx = sym->st_shndx;
   1851 
   1852       printf (gettext ("\
   1853 %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
   1854 	      cnt,
   1855 	      class == ELFCLASS32 ? 8 : 16,
   1856 	      sym->st_value,
   1857 	      sym->st_size,
   1858 	      ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
   1859 				    typebuf, sizeof (typebuf)),
   1860 	      ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
   1861 				       bindbuf, sizeof (bindbuf)),
   1862 	      get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
   1863 	      ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
   1864 				sizeof (scnbuf), NULL, shnum),
   1865 	      elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
   1866 
   1867       if (versym_data != NULL)
   1868 	{
   1869 	  /* Get the version information.  */
   1870 	  GElf_Versym versym_mem;
   1871 	  GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
   1872 
   1873 	  if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
   1874 	    {
   1875 	      bool is_nobits = false;
   1876 	      bool check_def = xndx != SHN_UNDEF;
   1877 
   1878 	      if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
   1879 		{
   1880 		  GElf_Shdr symshdr_mem;
   1881 		  GElf_Shdr *symshdr =
   1882 		    gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
   1883 
   1884 		  is_nobits = (symshdr != NULL
   1885 			       && symshdr->sh_type == SHT_NOBITS);
   1886 		}
   1887 
   1888 	      if (is_nobits || ! check_def)
   1889 		{
   1890 		  /* We must test both.  */
   1891 		  GElf_Vernaux vernaux_mem;
   1892 		  GElf_Vernaux *vernaux = NULL;
   1893 		  size_t vn_offset = 0;
   1894 
   1895 		  GElf_Verneed verneed_mem;
   1896 		  GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
   1897 							   &verneed_mem);
   1898 		  while (verneed != NULL)
   1899 		    {
   1900 		      size_t vna_offset = vn_offset;
   1901 
   1902 		      vernaux = gelf_getvernaux (verneed_data,
   1903 						 vna_offset += verneed->vn_aux,
   1904 						 &vernaux_mem);
   1905 		      while (vernaux != NULL
   1906 			     && vernaux->vna_other != *versym
   1907 			     && vernaux->vna_next != 0)
   1908 			{
   1909 			  /* Update the offset.  */
   1910 			  vna_offset += vernaux->vna_next;
   1911 
   1912 			  vernaux = (vernaux->vna_next == 0
   1913 				     ? NULL
   1914 				     : gelf_getvernaux (verneed_data,
   1915 							vna_offset,
   1916 							&vernaux_mem));
   1917 			}
   1918 
   1919 		      /* Check whether we found the version.  */
   1920 		      if (vernaux != NULL && vernaux->vna_other == *versym)
   1921 			/* Found it.  */
   1922 			break;
   1923 
   1924 		      vn_offset += verneed->vn_next;
   1925 		      verneed = (verneed->vn_next == 0
   1926 				 ? NULL
   1927 				 : gelf_getverneed (verneed_data, vn_offset,
   1928 						    &verneed_mem));
   1929 		    }
   1930 
   1931 		  if (vernaux != NULL && vernaux->vna_other == *versym)
   1932 		    {
   1933 		      printf ("@%s (%u)",
   1934 			      elf_strptr (ebl->elf, verneed_stridx,
   1935 					  vernaux->vna_name),
   1936 			      (unsigned int) vernaux->vna_other);
   1937 		      check_def = 0;
   1938 		    }
   1939 		  else if (unlikely (! is_nobits))
   1940 		    error (0, 0, gettext ("bad dynamic symbol"));
   1941 		  else
   1942 		    check_def = 1;
   1943 		}
   1944 
   1945 	      if (check_def && *versym != 0x8001)
   1946 		{
   1947 		  /* We must test both.  */
   1948 		  size_t vd_offset = 0;
   1949 
   1950 		  GElf_Verdef verdef_mem;
   1951 		  GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
   1952 							&verdef_mem);
   1953 		  while (verdef != NULL)
   1954 		    {
   1955 		      if (verdef->vd_ndx == (*versym & 0x7fff))
   1956 			/* Found the definition.  */
   1957 			break;
   1958 
   1959 		      vd_offset += verdef->vd_next;
   1960 		      verdef = (verdef->vd_next == 0
   1961 				? NULL
   1962 				: gelf_getverdef (verdef_data, vd_offset,
   1963 						  &verdef_mem));
   1964 		    }
   1965 
   1966 		  if (verdef != NULL)
   1967 		    {
   1968 		      GElf_Verdaux verdaux_mem;
   1969 		      GElf_Verdaux *verdaux
   1970 			= gelf_getverdaux (verdef_data,
   1971 					   vd_offset + verdef->vd_aux,
   1972 					   &verdaux_mem);
   1973 
   1974 		      if (verdaux != NULL)
   1975 			printf ((*versym & 0x8000) ? "@%s" : "@@%s",
   1976 				elf_strptr (ebl->elf, verdef_stridx,
   1977 					    verdaux->vda_name));
   1978 		    }
   1979 		}
   1980 	    }
   1981 	}
   1982 
   1983       putchar_unlocked ('\n');
   1984     }
   1985 }
   1986 
   1987 
   1988 /* Print version information.  */
   1989 static void
   1990 print_verinfo (Ebl *ebl)
   1991 {
   1992   /* Find the version information sections.  For this we have to
   1993      search through the section table.  */
   1994   Elf_Scn *scn = NULL;
   1995 
   1996   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   1997     {
   1998       /* Handle the section if it is part of the versioning handling.  */
   1999       GElf_Shdr shdr_mem;
   2000       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   2001 
   2002       if (likely (shdr != NULL))
   2003 	{
   2004 	  if (shdr->sh_type == SHT_GNU_verneed)
   2005 	    handle_verneed (ebl, scn, shdr);
   2006 	  else if (shdr->sh_type == SHT_GNU_verdef)
   2007 	    handle_verdef (ebl, scn, shdr);
   2008 	  else if (shdr->sh_type == SHT_GNU_versym)
   2009 	    handle_versym (ebl, scn, shdr);
   2010 	}
   2011     }
   2012 }
   2013 
   2014 
   2015 static const char *
   2016 get_ver_flags (unsigned int flags)
   2017 {
   2018   static char buf[32];
   2019   char *endp;
   2020 
   2021   if (flags == 0)
   2022     return gettext ("none");
   2023 
   2024   if (flags & VER_FLG_BASE)
   2025     endp = stpcpy (buf, "BASE ");
   2026   else
   2027     endp = buf;
   2028 
   2029   if (flags & VER_FLG_WEAK)
   2030     {
   2031       if (endp != buf)
   2032         endp = stpcpy (endp, "| ");
   2033 
   2034       endp = stpcpy (endp, "WEAK ");
   2035     }
   2036 
   2037   if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
   2038     {
   2039       strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
   2040       buf[sizeof (buf) - 1] = '\0';
   2041     }
   2042 
   2043   return buf;
   2044 }
   2045 
   2046 
   2047 static void
   2048 handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   2049 {
   2050   int class = gelf_getclass (ebl->elf);
   2051 
   2052   /* Get the data of the section.  */
   2053   Elf_Data *data = elf_getdata (scn, NULL);
   2054   if (data == NULL)
   2055     return;
   2056 
   2057   /* Get the section header string table index.  */
   2058   size_t shstrndx;
   2059   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
   2060     error (EXIT_FAILURE, 0,
   2061 	   gettext ("cannot get section header string table index"));
   2062 
   2063   GElf_Shdr glink;
   2064   printf (ngettext ("\
   2065 \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2066 		    "\
   2067 \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2068 		    shdr->sh_info),
   2069 	  (unsigned int) elf_ndxscn (scn),
   2070 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
   2071 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   2072 	  shdr->sh_offset,
   2073 	  (unsigned int) shdr->sh_link,
   2074 	  elf_strptr (ebl->elf, shstrndx,
   2075 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   2076 				    &glink)->sh_name));
   2077 
   2078   unsigned int offset = 0;
   2079   for (int cnt = shdr->sh_info; --cnt >= 0; )
   2080     {
   2081       /* Get the data at the next offset.  */
   2082       GElf_Verneed needmem;
   2083       GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
   2084       if (unlikely (need == NULL))
   2085 	break;
   2086 
   2087       printf (gettext ("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
   2088 	      offset, (unsigned short int) need->vn_version,
   2089 	      elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
   2090 	      (unsigned short int) need->vn_cnt);
   2091 
   2092       unsigned int auxoffset = offset + need->vn_aux;
   2093       for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
   2094 	{
   2095 	  GElf_Vernaux auxmem;
   2096 	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
   2097 	  if (unlikely (aux == NULL))
   2098 	    break;
   2099 
   2100 	  printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
   2101 		  auxoffset,
   2102 		  elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
   2103 		  get_ver_flags (aux->vna_flags),
   2104 		  (unsigned short int) aux->vna_other);
   2105 
   2106 	  auxoffset += aux->vna_next;
   2107 	}
   2108 
   2109       /* Find the next offset.  */
   2110       offset += need->vn_next;
   2111     }
   2112 }
   2113 
   2114 
   2115 static void
   2116 handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   2117 {
   2118   /* Get the data of the section.  */
   2119   Elf_Data *data = elf_getdata (scn, NULL);
   2120   if (data == NULL)
   2121     return;
   2122 
   2123   /* Get the section header string table index.  */
   2124   size_t shstrndx;
   2125   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
   2126     error (EXIT_FAILURE, 0,
   2127 	   gettext ("cannot get section header string table index"));
   2128 
   2129   int class = gelf_getclass (ebl->elf);
   2130   GElf_Shdr glink;
   2131   printf (ngettext ("\
   2132 \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2133 		    "\
   2134 \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2135 		    shdr->sh_info),
   2136 	  (unsigned int) elf_ndxscn (scn),
   2137 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2138 	  shdr->sh_info,
   2139 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   2140 	  shdr->sh_offset,
   2141 	  (unsigned int) shdr->sh_link,
   2142 	  elf_strptr (ebl->elf, shstrndx,
   2143 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   2144 				    &glink)->sh_name));
   2145 
   2146   unsigned int offset = 0;
   2147   for (int cnt = shdr->sh_info; --cnt >= 0; )
   2148     {
   2149       /* Get the data at the next offset.  */
   2150       GElf_Verdef defmem;
   2151       GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
   2152       if (unlikely (def == NULL))
   2153 	break;
   2154 
   2155       unsigned int auxoffset = offset + def->vd_aux;
   2156       GElf_Verdaux auxmem;
   2157       GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
   2158       if (unlikely (aux == NULL))
   2159 	break;
   2160 
   2161       printf (gettext ("\
   2162   %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"),
   2163 	      offset, def->vd_version,
   2164 	      get_ver_flags (def->vd_flags),
   2165 	      def->vd_ndx,
   2166 	      def->vd_cnt,
   2167 	      elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
   2168 
   2169       auxoffset += aux->vda_next;
   2170       for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
   2171 	{
   2172 	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
   2173 	  if (unlikely (aux == NULL))
   2174 	    break;
   2175 
   2176 	  printf (gettext ("  %#06x: Parent %d: %s\n"),
   2177 		  auxoffset, cnt2,
   2178 		  elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
   2179 
   2180 	  auxoffset += aux->vda_next;
   2181 	}
   2182 
   2183       /* Find the next offset.  */
   2184       offset += def->vd_next;
   2185     }
   2186 }
   2187 
   2188 
   2189 static void
   2190 handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   2191 {
   2192   int class = gelf_getclass (ebl->elf);
   2193   const char **vername;
   2194   const char **filename;
   2195 
   2196   /* Get the data of the section.  */
   2197   Elf_Data *data = elf_getdata (scn, NULL);
   2198   if (data == NULL)
   2199     return;
   2200 
   2201   /* Get the section header string table index.  */
   2202   size_t shstrndx;
   2203   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
   2204     error (EXIT_FAILURE, 0,
   2205 	   gettext ("cannot get section header string table index"));
   2206 
   2207   /* We have to find the version definition section and extract the
   2208      version names.  */
   2209   Elf_Scn *defscn = NULL;
   2210   Elf_Scn *needscn = NULL;
   2211 
   2212   Elf_Scn *verscn = NULL;
   2213   while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
   2214     {
   2215       GElf_Shdr vershdr_mem;
   2216       GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
   2217 
   2218       if (likely (vershdr != NULL))
   2219 	{
   2220 	  if (vershdr->sh_type == SHT_GNU_verdef)
   2221 	    defscn = verscn;
   2222 	  else if (vershdr->sh_type == SHT_GNU_verneed)
   2223 	    needscn = verscn;
   2224 	}
   2225     }
   2226 
   2227   size_t nvername;
   2228   if (defscn != NULL || needscn != NULL)
   2229     {
   2230       /* We have a version information (better should have).  Now get
   2231 	 the version names.  First find the maximum version number.  */
   2232       nvername = 0;
   2233       if (defscn != NULL)
   2234 	{
   2235 	  /* Run through the version definitions and find the highest
   2236 	     index.  */
   2237 	  unsigned int offset = 0;
   2238 	  Elf_Data *defdata;
   2239 	  GElf_Shdr defshdrmem;
   2240 	  GElf_Shdr *defshdr;
   2241 
   2242 	  defdata = elf_getdata (defscn, NULL);
   2243 	  if (unlikely (defdata == NULL))
   2244 	    return;
   2245 
   2246 	  defshdr = gelf_getshdr (defscn, &defshdrmem);
   2247 	  if (unlikely (defshdr == NULL))
   2248 	    return;
   2249 
   2250 	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
   2251 	    {
   2252 	      GElf_Verdef defmem;
   2253 	      GElf_Verdef *def;
   2254 
   2255 	      /* Get the data at the next offset.  */
   2256 	      def = gelf_getverdef (defdata, offset, &defmem);
   2257 	      if (unlikely (def == NULL))
   2258 		break;
   2259 
   2260 	      nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
   2261 
   2262 	      offset += def->vd_next;
   2263 	    }
   2264 	}
   2265       if (needscn != NULL)
   2266 	{
   2267 	  unsigned int offset = 0;
   2268 	  Elf_Data *needdata;
   2269 	  GElf_Shdr needshdrmem;
   2270 	  GElf_Shdr *needshdr;
   2271 
   2272 	  needdata = elf_getdata (needscn, NULL);
   2273 	  if (unlikely (needdata == NULL))
   2274 	    return;
   2275 
   2276 	  needshdr = gelf_getshdr (needscn, &needshdrmem);
   2277 	  if (unlikely (needshdr == NULL))
   2278 	    return;
   2279 
   2280 	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
   2281 	    {
   2282 	      GElf_Verneed needmem;
   2283 	      GElf_Verneed *need;
   2284 	      unsigned int auxoffset;
   2285 	      int cnt2;
   2286 
   2287 	      /* Get the data at the next offset.  */
   2288 	      need = gelf_getverneed (needdata, offset, &needmem);
   2289 	      if (unlikely (need == NULL))
   2290 		break;
   2291 
   2292 	      /* Run through the auxiliary entries.  */
   2293 	      auxoffset = offset + need->vn_aux;
   2294 	      for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
   2295 		{
   2296 		  GElf_Vernaux auxmem;
   2297 		  GElf_Vernaux *aux;
   2298 
   2299 		  aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
   2300 		  if (unlikely (aux == NULL))
   2301 		    break;
   2302 
   2303 		  nvername = MAX (nvername,
   2304 				  (size_t) (aux->vna_other & 0x7fff));
   2305 
   2306 		  auxoffset += aux->vna_next;
   2307 		}
   2308 
   2309 	      offset += need->vn_next;
   2310 	    }
   2311 	}
   2312 
   2313       /* This is the number of versions we know about.  */
   2314       ++nvername;
   2315 
   2316       /* Allocate the array.  */
   2317       vername = (const char **) alloca (nvername * sizeof (const char *));
   2318       filename = (const char **) alloca (nvername * sizeof (const char *));
   2319 
   2320       /* Run through the data structures again and collect the strings.  */
   2321       if (defscn != NULL)
   2322 	{
   2323 	  /* Run through the version definitions and find the highest
   2324 	     index.  */
   2325 	  unsigned int offset = 0;
   2326 	  Elf_Data *defdata;
   2327 	  GElf_Shdr defshdrmem;
   2328 	  GElf_Shdr *defshdr;
   2329 
   2330 	  defdata = elf_getdata (defscn, NULL);
   2331 	  if (unlikely (defdata == NULL))
   2332 	    return;
   2333 
   2334 	  defshdr = gelf_getshdr (defscn, &defshdrmem);
   2335 	  if (unlikely (defshdr == NULL))
   2336 	    return;
   2337 
   2338 	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
   2339 	    {
   2340 
   2341 	      /* Get the data at the next offset.  */
   2342 	      GElf_Verdef defmem;
   2343 	      GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
   2344 	      GElf_Verdaux auxmem;
   2345 	      GElf_Verdaux *aux = gelf_getverdaux (defdata,
   2346 						   offset + def->vd_aux,
   2347 						   &auxmem);
   2348 	      if (unlikely (def == NULL || aux == NULL))
   2349 		break;
   2350 
   2351 	      vername[def->vd_ndx & 0x7fff]
   2352 		= elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
   2353 	      filename[def->vd_ndx & 0x7fff] = NULL;
   2354 
   2355 	      offset += def->vd_next;
   2356 	    }
   2357 	}
   2358       if (needscn != NULL)
   2359 	{
   2360 	  unsigned int offset = 0;
   2361 
   2362 	  Elf_Data *needdata = elf_getdata (needscn, NULL);
   2363 	  GElf_Shdr needshdrmem;
   2364 	  GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
   2365 	  if (unlikely (needdata == NULL || needshdr == NULL))
   2366 	    return;
   2367 
   2368 	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
   2369 	    {
   2370 	      /* Get the data at the next offset.  */
   2371 	      GElf_Verneed needmem;
   2372 	      GElf_Verneed *need = gelf_getverneed (needdata, offset,
   2373 						    &needmem);
   2374 	      if (unlikely (need == NULL))
   2375 		break;
   2376 
   2377 	      /* Run through the auxiliary entries.  */
   2378 	      unsigned int auxoffset = offset + need->vn_aux;
   2379 	      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
   2380 		{
   2381 		  GElf_Vernaux auxmem;
   2382 		  GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
   2383 						       &auxmem);
   2384 		  if (unlikely (aux == NULL))
   2385 		    break;
   2386 
   2387 		  vername[aux->vna_other & 0x7fff]
   2388 		    = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
   2389 		  filename[aux->vna_other & 0x7fff]
   2390 		    = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
   2391 
   2392 		  auxoffset += aux->vna_next;
   2393 		}
   2394 
   2395 	      offset += need->vn_next;
   2396 	    }
   2397 	}
   2398     }
   2399   else
   2400     {
   2401       vername = NULL;
   2402       nvername = 1;
   2403       filename = NULL;
   2404     }
   2405 
   2406   /* Print the header.  */
   2407   GElf_Shdr glink;
   2408   printf (ngettext ("\
   2409 \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
   2410 		    "\
   2411 \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
   2412 		    shdr->sh_size / shdr->sh_entsize),
   2413 	  (unsigned int) elf_ndxscn (scn),
   2414 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2415 	  (int) (shdr->sh_size / shdr->sh_entsize),
   2416 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   2417 	  shdr->sh_offset,
   2418 	  (unsigned int) shdr->sh_link,
   2419 	  elf_strptr (ebl->elf, shstrndx,
   2420 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   2421 				    &glink)->sh_name));
   2422 
   2423   /* Now we can finally look at the actual contents of this section.  */
   2424   for (unsigned int cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
   2425     {
   2426       if (cnt % 2 == 0)
   2427 	printf ("\n %4d:", cnt);
   2428 
   2429       GElf_Versym symmem;
   2430       GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
   2431       if (sym == NULL)
   2432 	break;
   2433 
   2434       switch (*sym)
   2435 	{
   2436 	  ssize_t n;
   2437 	case 0:
   2438 	  fputs_unlocked (gettext ("   0 *local*                     "),
   2439 			  stdout);
   2440 	  break;
   2441 
   2442 	case 1:
   2443 	  fputs_unlocked (gettext ("   1 *global*                    "),
   2444 			  stdout);
   2445 	  break;
   2446 
   2447 	default:
   2448 	  n = printf ("%4d%c%s",
   2449 		      *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
   2450 		      (unsigned int) (*sym & 0x7fff) < nvername
   2451 		      ? vername[*sym & 0x7fff] : "???");
   2452 	  if ((unsigned int) (*sym & 0x7fff) < nvername
   2453 	      && filename[*sym & 0x7fff] != NULL)
   2454 	    n += printf ("(%s)", filename[*sym & 0x7fff]);
   2455 	  printf ("%*s", MAX (0, 33 - (int) n), " ");
   2456 	  break;
   2457 	}
   2458     }
   2459   putchar_unlocked ('\n');
   2460 }
   2461 
   2462 
   2463 static void
   2464 print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
   2465 		 uint_fast32_t maxlength, Elf32_Word nbucket,
   2466 		 uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
   2467 {
   2468   uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
   2469 
   2470   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
   2471     ++counts[lengths[cnt]];
   2472 
   2473   GElf_Shdr glink;
   2474   printf (ngettext ("\
   2475 \nHistogram for bucket list length in section [%2u] '%s' (total of %d bucket):\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2476 		    "\
   2477 \nHistogram for bucket list length in section [%2u] '%s' (total of %d buckets):\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2478 		    nbucket),
   2479 	  (unsigned int) elf_ndxscn (scn),
   2480 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2481 	  (int) nbucket,
   2482 	  gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
   2483 	  shdr->sh_addr,
   2484 	  shdr->sh_offset,
   2485 	  (unsigned int) shdr->sh_link,
   2486 	  elf_strptr (ebl->elf, shstrndx,
   2487 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   2488 				    &glink)->sh_name));
   2489 
   2490   if (extrastr != NULL)
   2491     fputs (extrastr, stdout);
   2492 
   2493   if (likely (nbucket > 0))
   2494     {
   2495       uint64_t success = 0;
   2496 
   2497       fputs_unlocked (gettext ("\
   2498  Length  Number  % of total  Coverage\n"), stdout);
   2499       printf (gettext ("      0  %6" PRIu32 "      %5.1f%%\n"),
   2500 	      counts[0], (counts[0] * 100.0) / nbucket);
   2501 
   2502       uint64_t nzero_counts = 0;
   2503       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
   2504 	{
   2505 	  nzero_counts += counts[cnt] * cnt;
   2506 	  printf (gettext ("\
   2507 %7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
   2508 		  (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
   2509 		  (nzero_counts * 100.0) / nsyms);
   2510 	}
   2511 
   2512       Elf32_Word acc = 0;
   2513       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
   2514 	{
   2515 	  acc += cnt;
   2516 	  success += counts[cnt] * acc;
   2517 	}
   2518 
   2519       printf (gettext ("\
   2520  Average number of tests:   successful lookup: %f\n\
   2521                           unsuccessful lookup: %f\n"),
   2522 	      (double) success / (double) nzero_counts,
   2523 	      (double) nzero_counts / (double) nbucket);
   2524     }
   2525 
   2526   free (counts);
   2527 }
   2528 
   2529 
   2530 /* This function handles the traditional System V-style hash table format.  */
   2531 static void
   2532 handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
   2533 {
   2534   Elf_Data *data = elf_getdata (scn, NULL);
   2535   if (unlikely (data == NULL))
   2536     {
   2537       error (0, 0, gettext ("cannot get data for section %d: %s"),
   2538 	     (int) elf_ndxscn (scn), elf_errmsg (-1));
   2539       return;
   2540     }
   2541 
   2542   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
   2543   Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
   2544   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
   2545   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
   2546 
   2547   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
   2548 
   2549   uint_fast32_t maxlength = 0;
   2550   uint_fast32_t nsyms = 0;
   2551   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
   2552     {
   2553       Elf32_Word inner = bucket[cnt];
   2554       while (inner > 0 && inner < nchain)
   2555 	{
   2556 	  ++nsyms;
   2557 	  if (maxlength < ++lengths[cnt])
   2558 	    ++maxlength;
   2559 
   2560 	  inner = chain[inner];
   2561 	}
   2562     }
   2563 
   2564   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
   2565 		   lengths, NULL);
   2566 
   2567   free (lengths);
   2568 }
   2569 
   2570 
   2571 /* This function handles the incorrect, System V-style hash table
   2572    format some 64-bit architectures use.  */
   2573 static void
   2574 handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
   2575 {
   2576   Elf_Data *data = elf_getdata (scn, NULL);
   2577   if (unlikely (data == NULL))
   2578     {
   2579       error (0, 0, gettext ("cannot get data for section %d: %s"),
   2580 	     (int) elf_ndxscn (scn), elf_errmsg (-1));
   2581       return;
   2582     }
   2583 
   2584   Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
   2585   Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
   2586   Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
   2587   Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
   2588 
   2589   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
   2590 
   2591   uint_fast32_t maxlength = 0;
   2592   uint_fast32_t nsyms = 0;
   2593   for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
   2594     {
   2595       Elf64_Xword inner = bucket[cnt];
   2596       while (inner > 0 && inner < nchain)
   2597 	{
   2598 	  ++nsyms;
   2599 	  if (maxlength < ++lengths[cnt])
   2600 	    ++maxlength;
   2601 
   2602 	  inner = chain[inner];
   2603 	}
   2604     }
   2605 
   2606   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
   2607 		   lengths, NULL);
   2608 
   2609   free (lengths);
   2610 }
   2611 
   2612 
   2613 /* This function handles the GNU-style hash table format.  */
   2614 static void
   2615 handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
   2616 {
   2617   Elf_Data *data = elf_getdata (scn, NULL);
   2618   if (unlikely (data == NULL))
   2619     {
   2620       error (0, 0, gettext ("cannot get data for section %d: %s"),
   2621 	     (int) elf_ndxscn (scn), elf_errmsg (-1));
   2622       return;
   2623     }
   2624 
   2625   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
   2626   Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
   2627 
   2628   /* Next comes the size of the bitmap.  It's measured in words for
   2629      the architecture.  It's 32 bits for 32 bit archs, and 64 bits for
   2630      64 bit archs.  */
   2631   Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
   2632   if (gelf_getclass (ebl->elf) == ELFCLASS64)
   2633     bitmask_words *= 2;
   2634 
   2635   Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
   2636 
   2637   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
   2638 
   2639   Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
   2640   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
   2641   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
   2642 						    + nbucket];
   2643 
   2644   /* Compute distribution of chain lengths.  */
   2645   uint_fast32_t maxlength = 0;
   2646   uint_fast32_t nsyms = 0;
   2647   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
   2648     if (bucket[cnt] != 0)
   2649       {
   2650 	Elf32_Word inner = bucket[cnt] - symbias;
   2651 	do
   2652 	  {
   2653 	    ++nsyms;
   2654 	    if (maxlength < ++lengths[cnt])
   2655 	      ++maxlength;
   2656 	  }
   2657 	while ((chain[inner++] & 1) == 0);
   2658       }
   2659 
   2660   /* Count bits in bitmask.  */
   2661   uint_fast32_t nbits = 0;
   2662   for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
   2663     {
   2664       uint_fast32_t word = bitmask[cnt];
   2665 
   2666       word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
   2667       word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
   2668       word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
   2669       word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
   2670       nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
   2671     }
   2672 
   2673   char *str;
   2674   if (unlikely (asprintf (&str, gettext ("\
   2675  Symbol Bias: %u\n\
   2676  Bitmask Size: %zu bytes  %" PRIuFAST32 "%% bits set  2nd hash shift: %u\n"),
   2677 			  (unsigned int) symbias,
   2678 			  bitmask_words * sizeof (Elf32_Word),
   2679 			  ((nbits * 100 + 50)
   2680 			   / (uint_fast32_t) (bitmask_words
   2681 					      * sizeof (Elf32_Word) * 8)),
   2682 			  (unsigned int) shift) == -1))
   2683     error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
   2684 
   2685   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
   2686 		   lengths, str);
   2687 
   2688   free (str);
   2689   free (lengths);
   2690 }
   2691 
   2692 
   2693 /* Find the symbol table(s).  For this we have to search through the
   2694    section table.  */
   2695 static void
   2696 handle_hash (Ebl *ebl)
   2697 {
   2698   /* Get the section header string table index.  */
   2699   size_t shstrndx;
   2700   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
   2701     error (EXIT_FAILURE, 0,
   2702 	   gettext ("cannot get section header string table index"));
   2703 
   2704   Elf_Scn *scn = NULL;
   2705   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   2706     {
   2707       /* Handle the section if it is a symbol table.  */
   2708       GElf_Shdr shdr_mem;
   2709       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   2710 
   2711       if (likely (shdr != NULL))
   2712 	{
   2713 	  if (shdr->sh_type == SHT_HASH)
   2714 	    {
   2715 	      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
   2716 		handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
   2717 	      else
   2718 		handle_sysv_hash (ebl, scn, shdr, shstrndx);
   2719 	    }
   2720 	  else if (shdr->sh_type == SHT_GNU_HASH)
   2721 	    handle_gnu_hash (ebl, scn, shdr, shstrndx);
   2722 	}
   2723     }
   2724 }
   2725 
   2726 
   2727 static void
   2728 print_liblist (Ebl *ebl)
   2729 {
   2730   /* Find the library list sections.  For this we have to search
   2731      through the section table.  */
   2732   Elf_Scn *scn = NULL;
   2733 
   2734   /* Get the section header string table index.  */
   2735   size_t shstrndx;
   2736   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
   2737     error (EXIT_FAILURE, 0,
   2738 	   gettext ("cannot get section header string table index"));
   2739 
   2740   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   2741     {
   2742       GElf_Shdr shdr_mem;
   2743       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   2744 
   2745       if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
   2746 	{
   2747 	  int nentries = shdr->sh_size / shdr->sh_entsize;
   2748 	  printf (ngettext ("\
   2749 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   2750 			    "\
   2751 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   2752 			    nentries),
   2753 		  elf_ndxscn (scn),
   2754 		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2755 		  shdr->sh_offset,
   2756 		  nentries);
   2757 
   2758 	  Elf_Data *data = elf_getdata (scn, NULL);
   2759 	  if (data == NULL)
   2760 	    return;
   2761 
   2762 	  puts (gettext ("\
   2763        Library                       Time Stamp          Checksum Version Flags"));
   2764 
   2765 	  for (int cnt = 0; cnt < nentries; ++cnt)
   2766 	    {
   2767 	      GElf_Lib lib_mem;
   2768 	      GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
   2769 	      if (unlikely (lib == NULL))
   2770 		continue;
   2771 
   2772 	      time_t t = (time_t) lib->l_time_stamp;
   2773 	      struct tm *tm = gmtime (&t);
   2774 	      if (unlikely (tm == NULL))
   2775 		continue;
   2776 
   2777 	      printf ("  [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
   2778 		      cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
   2779 		      tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
   2780 		      tm->tm_hour, tm->tm_min, tm->tm_sec,
   2781 		      (unsigned int) lib->l_checksum,
   2782 		      (unsigned int) lib->l_version,
   2783 		      (unsigned int) lib->l_flags);
   2784 	    }
   2785 	}
   2786     }
   2787 }
   2788 
   2789 static void
   2790 print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
   2791 {
   2792   /* Find the object attributes sections.  For this we have to search
   2793      through the section table.  */
   2794   Elf_Scn *scn = NULL;
   2795 
   2796   /* Get the section header string table index.  */
   2797   size_t shstrndx;
   2798   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
   2799     error (EXIT_FAILURE, 0,
   2800 	   gettext ("cannot get section header string table index"));
   2801 
   2802   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   2803     {
   2804       GElf_Shdr shdr_mem;
   2805       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   2806 
   2807       if (shdr == NULL || shdr->sh_type != SHT_GNU_ATTRIBUTES)
   2808 	continue;
   2809 
   2810       printf (gettext ("\
   2811 \nObject attributes section [%2zu] '%s' of %" PRIu64
   2812 		       " bytes at offset %#0" PRIx64 ":\n"),
   2813 	      elf_ndxscn (scn),
   2814 	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2815 	      shdr->sh_size, shdr->sh_offset);
   2816 
   2817       Elf_Data *data = elf_rawdata (scn, NULL);
   2818       if (data == NULL)
   2819 	return;
   2820 
   2821       const unsigned char *p = data->d_buf;
   2822 
   2823       if (unlikely (*p++ != 'A'))
   2824 	return;
   2825 
   2826       fputs_unlocked (gettext ("  Owner          Size\n"), stdout);
   2827 
   2828       inline size_t left (void)
   2829       {
   2830 	return (const unsigned char *) data->d_buf + data->d_size - p;
   2831       }
   2832 
   2833       while (left () >= 4)
   2834 	{
   2835 	  uint32_t len;
   2836 	  memcpy (&len, p, sizeof len);
   2837 
   2838 	  if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
   2839 	    CONVERT (len);
   2840 
   2841 	  if (unlikely (len > left ()))
   2842 	    break;
   2843 
   2844 	  const unsigned char *name = p + sizeof len;
   2845 	  p += len;
   2846 
   2847 	  unsigned const char *q = memchr (name, '\0', len);
   2848 	  if (unlikely (q == NULL))
   2849 	    continue;
   2850 	  ++q;
   2851 
   2852 	  printf (gettext ("  %-13s  %4" PRIu32 "\n"), name, len);
   2853 
   2854 	  if (q - name == sizeof "gnu"
   2855 	      && !memcmp (name, "gnu", sizeof "gnu"))
   2856 	    while (q < p)
   2857 	      {
   2858 		const unsigned char *const sub = q;
   2859 
   2860 		unsigned int subsection_tag;
   2861 		get_uleb128 (subsection_tag, q);
   2862 		if (unlikely (q >= p))
   2863 		  break;
   2864 
   2865 		uint32_t subsection_len;
   2866 		if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
   2867 		  break;
   2868 
   2869 		memcpy (&subsection_len, q, sizeof subsection_len);
   2870 
   2871 		if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
   2872 		  CONVERT (subsection_len);
   2873 
   2874 		if (unlikely (p - sub < (ptrdiff_t) subsection_len))
   2875 		  break;
   2876 
   2877 		const unsigned char *r = q + sizeof subsection_len;
   2878 		q = sub + subsection_len;
   2879 
   2880 		switch (subsection_tag)
   2881 		  {
   2882 		  default:
   2883 		    printf (gettext ("    %-4u %12" PRIu32 "\n"),
   2884 			    subsection_tag, subsection_len);
   2885 		    break;
   2886 
   2887 		  case 1:	/* Tag_File */
   2888 		    printf (gettext ("    File: %11" PRIu32 "\n"),
   2889 			    subsection_len);
   2890 
   2891 		    while (r < q)
   2892 		      {
   2893 			unsigned int tag;
   2894 			get_uleb128 (tag, r);
   2895 			if (unlikely (r >= q))
   2896 			  break;
   2897 
   2898 			uint64_t value = 0;
   2899 			const char *string = NULL;
   2900 			if (tag == 32 || (tag & 1) == 0)
   2901 			  {
   2902 			    get_uleb128 (value, r);
   2903 			    if (r > q)
   2904 			      break;
   2905 			  }
   2906 			if (tag == 32 || (tag & 1) != 0)
   2907 			  {
   2908 			    r = memchr (r, '\0', q - r);
   2909 			    if (r == NULL)
   2910 			      break;
   2911 			    ++r;
   2912 			  }
   2913 
   2914 			const char *tag_name = NULL;
   2915 			const char *value_name = NULL;
   2916 			ebl_check_object_attribute (ebl, (const char *) name,
   2917 						    tag, value,
   2918 						    &tag_name, &value_name);
   2919 
   2920 			if (tag_name != NULL)
   2921 			  {
   2922 			    if (tag == 32)
   2923 			      printf (gettext ("      %s: %" PRId64 ", %s\n"),
   2924 				      tag_name, value, string);
   2925 			    else if (string == NULL && value_name == NULL)
   2926 			      printf (gettext ("      %s: %" PRId64 "\n"),
   2927 				      tag_name, value);
   2928 			    else
   2929 			      printf (gettext ("      %s: %s\n"),
   2930 				      tag_name, string ?: value_name);
   2931 			  }
   2932 			else
   2933 			  {
   2934 			    assert (tag != 32);
   2935 			    if (string == NULL)
   2936 			      printf (gettext ("      %u: %" PRId64 "\n"),
   2937 				      tag, value);
   2938 			    else
   2939 			      printf (gettext ("      %u: %s\n"),
   2940 				      tag, string);
   2941 			  }
   2942 		      }
   2943 		  }
   2944 	      }
   2945 	}
   2946     }
   2947 }
   2948 
   2949 
   2950 static char *
   2951 format_dwarf_addr (Dwfl_Module *dwflmod,
   2952 		   int address_size, Dwarf_Addr address)
   2953 {
   2954   /* See if there is a name we can give for this address.  */
   2955   GElf_Sym sym;
   2956   const char *name = dwfl_module_addrsym (dwflmod, address, &sym, NULL);
   2957   if (name != NULL)
   2958     sym.st_value = address - sym.st_value;
   2959 
   2960   /* Relativize the address.  */
   2961   int n = dwfl_module_relocations (dwflmod);
   2962   int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
   2963 
   2964   /* In an ET_REL file there is a section name to refer to.  */
   2965   const char *scn = (i < 0 ? NULL
   2966 		     : dwfl_module_relocation_info (dwflmod, i, NULL));
   2967 
   2968   char *result;
   2969   if ((name != NULL
   2970        ? (sym.st_value != 0
   2971 	  ? (scn != NULL
   2972 	     ? (address_size == 0
   2973 		? asprintf (&result,
   2974 			    gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
   2975 			    scn, address, name, sym.st_value)
   2976 		: asprintf (&result,
   2977 			    gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
   2978 			    scn, 2 + address_size * 2, address,
   2979 			    name, sym.st_value))
   2980 	     : (address_size == 0
   2981 		? asprintf (&result,
   2982 			    gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
   2983 			    address, name, sym.st_value)
   2984 		: asprintf (&result,
   2985 			    gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
   2986 			    2 + address_size * 2, address,
   2987 			    name, sym.st_value)))
   2988 	  : (scn != NULL
   2989 	     ? (address_size == 0
   2990 		? asprintf (&result,
   2991 			    gettext ("%s+%#" PRIx64 " <%s>"),
   2992 			    scn, address, name)
   2993 		: asprintf (&result,
   2994 			    gettext ("%s+%#0*" PRIx64 " <%s>"),
   2995 			    scn, 2 + address_size * 2, address, name))
   2996 	     : (address_size == 0
   2997 		? asprintf (&result,
   2998 			    gettext ("%#" PRIx64 " <%s>"),
   2999 			    address, name)
   3000 		: asprintf (&result,
   3001 			    gettext ("%#0*" PRIx64 " <%s>"),
   3002 			    2 + address_size * 2, address, name))))
   3003        : (scn != NULL
   3004 	  ? (address_size == 0
   3005 	     ? asprintf (&result,
   3006 			 gettext ("%s+%#" PRIx64),
   3007 			 scn, address)
   3008 	     : asprintf (&result,
   3009 			 gettext ("%s+%#0*" PRIx64),
   3010 			 scn, 2 + address_size * 2, address))
   3011 	  : (address_size == 0
   3012 	     ? asprintf (&result,
   3013 			 "%#" PRIx64,
   3014 			 address)
   3015 	     : asprintf (&result,
   3016 			 "%#0*" PRIx64,
   3017 			 2 + address_size * 2, address)))) < 0)
   3018     error (EXIT_FAILURE, 0, _("memory exhausted"));
   3019 
   3020   return result;
   3021 }
   3022 
   3023 static const char *
   3024 dwarf_tag_string (unsigned int tag)
   3025 {
   3026   static const char *const known_tags[]  =
   3027     {
   3028       [DW_TAG_array_type] = "array_type",
   3029       [DW_TAG_class_type] = "class_type",
   3030       [DW_TAG_entry_point] = "entry_point",
   3031       [DW_TAG_enumeration_type] = "enumeration_type",
   3032       [DW_TAG_formal_parameter] = "formal_parameter",
   3033       [DW_TAG_imported_declaration] = "imported_declaration",
   3034       [DW_TAG_label] = "label",
   3035       [DW_TAG_lexical_block] = "lexical_block",
   3036       [DW_TAG_member] = "member",
   3037       [DW_TAG_pointer_type] = "pointer_type",
   3038       [DW_TAG_reference_type] = "reference_type",
   3039       [DW_TAG_compile_unit] = "compile_unit",
   3040       [DW_TAG_string_type] = "string_type",
   3041       [DW_TAG_structure_type] = "structure_type",
   3042       [DW_TAG_subroutine_type] = "subroutine_type",
   3043       [DW_TAG_typedef] = "typedef",
   3044       [DW_TAG_union_type] = "union_type",
   3045       [DW_TAG_unspecified_parameters] = "unspecified_parameters",
   3046       [DW_TAG_variant] = "variant",
   3047       [DW_TAG_common_block] = "common_block",
   3048       [DW_TAG_common_inclusion] = "common_inclusion",
   3049       [DW_TAG_inheritance] = "inheritance",
   3050       [DW_TAG_inlined_subroutine] = "inlined_subroutine",
   3051       [DW_TAG_module] = "module",
   3052       [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
   3053       [DW_TAG_set_type] = "set_type",
   3054       [DW_TAG_subrange_type] = "subrange_type",
   3055       [DW_TAG_with_stmt] = "with_stmt",
   3056       [DW_TAG_access_declaration] = "access_declaration",
   3057       [DW_TAG_base_type] = "base_type",
   3058       [DW_TAG_catch_block] = "catch_block",
   3059       [DW_TAG_const_type] = "const_type",
   3060       [DW_TAG_constant] = "constant",
   3061       [DW_TAG_enumerator] = "enumerator",
   3062       [DW_TAG_file_type] = "file_type",
   3063       [DW_TAG_friend] = "friend",
   3064       [DW_TAG_namelist] = "namelist",
   3065       [DW_TAG_namelist_item] = "namelist_item",
   3066       [DW_TAG_packed_type] = "packed_type",
   3067       [DW_TAG_subprogram] = "subprogram",
   3068       [DW_TAG_template_type_parameter] = "template_type_parameter",
   3069       [DW_TAG_template_value_parameter] = "template_value_parameter",
   3070       [DW_TAG_thrown_type] = "thrown_type",
   3071       [DW_TAG_try_block] = "try_block",
   3072       [DW_TAG_variant_part] = "variant_part",
   3073       [DW_TAG_variable] = "variable",
   3074       [DW_TAG_volatile_type] = "volatile_type",
   3075       [DW_TAG_dwarf_procedure] = "dwarf_procedure",
   3076       [DW_TAG_restrict_type] = "restrict_type",
   3077       [DW_TAG_interface_type] = "interface_type",
   3078       [DW_TAG_namespace] = "namespace",
   3079       [DW_TAG_imported_module] = "imported_module",
   3080       [DW_TAG_unspecified_type] = "unspecified_type",
   3081       [DW_TAG_partial_unit] = "partial_unit",
   3082       [DW_TAG_imported_unit] = "imported_unit",
   3083       [DW_TAG_mutable_type] = "mutable_type",
   3084       [DW_TAG_condition] = "condition",
   3085       [DW_TAG_shared_type] = "shared_type",
   3086     };
   3087   const unsigned int nknown_tags = (sizeof (known_tags)
   3088 				    / sizeof (known_tags[0]));
   3089   static char buf[40];
   3090   const char *result = NULL;
   3091 
   3092   if (likely (tag < nknown_tags))
   3093     result = known_tags[tag];
   3094 
   3095   if (unlikely (result == NULL))
   3096     /* There are a few known extensions.  */
   3097     switch (tag)
   3098       {
   3099       case DW_TAG_MIPS_loop:
   3100 	result = "MIPS_loop";
   3101 	break;
   3102 
   3103       case DW_TAG_format_label:
   3104 	result = "format_label";
   3105 	break;
   3106 
   3107       case DW_TAG_function_template:
   3108 	result = "function_template";
   3109 	break;
   3110 
   3111       case DW_TAG_class_template:
   3112 	result = "class_template";
   3113 	break;
   3114 
   3115       default:
   3116 	if (tag < DW_TAG_lo_user)
   3117 	  snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag);
   3118 	else
   3119 	  snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag);
   3120 	result = buf;
   3121 	break;
   3122       }
   3123 
   3124   return result;
   3125 }
   3126 
   3127 
   3128 static const char *
   3129 dwarf_attr_string (unsigned int attrnum)
   3130 {
   3131   static const char *const known_attrs[] =
   3132     {
   3133       [DW_AT_sibling] = "sibling",
   3134       [DW_AT_location] = "location",
   3135       [DW_AT_name] = "name",
   3136       [DW_AT_ordering] = "ordering",
   3137       [DW_AT_subscr_data] = "subscr_data",
   3138       [DW_AT_byte_size] = "byte_size",
   3139       [DW_AT_bit_offset] = "bit_offset",
   3140       [DW_AT_bit_size] = "bit_size",
   3141       [DW_AT_element_list] = "element_list",
   3142       [DW_AT_stmt_list] = "stmt_list",
   3143       [DW_AT_low_pc] = "low_pc",
   3144       [DW_AT_high_pc] = "high_pc",
   3145       [DW_AT_language] = "language",
   3146       [DW_AT_member] = "member",
   3147       [DW_AT_discr] = "discr",
   3148       [DW_AT_discr_value] = "discr_value",
   3149       [DW_AT_visibility] = "visibility",
   3150       [DW_AT_import] = "import",
   3151       [DW_AT_string_length] = "string_length",
   3152       [DW_AT_common_reference] = "common_reference",
   3153       [DW_AT_comp_dir] = "comp_dir",
   3154       [DW_AT_const_value] = "const_value",
   3155       [DW_AT_containing_type] = "containing_type",
   3156       [DW_AT_default_value] = "default_value",
   3157       [DW_AT_inline] = "inline",
   3158       [DW_AT_is_optional] = "is_optional",
   3159       [DW_AT_lower_bound] = "lower_bound",
   3160       [DW_AT_producer] = "producer",
   3161       [DW_AT_prototyped] = "prototyped",
   3162       [DW_AT_return_addr] = "return_addr",
   3163       [DW_AT_start_scope] = "start_scope",
   3164       [DW_AT_bit_stride] = "bit_stride",
   3165       [DW_AT_upper_bound] = "upper_bound",
   3166       [DW_AT_abstract_origin] = "abstract_origin",
   3167       [DW_AT_accessibility] = "accessibility",
   3168       [DW_AT_address_class] = "address_class",
   3169       [DW_AT_artificial] = "artificial",
   3170       [DW_AT_base_types] = "base_types",
   3171       [DW_AT_calling_convention] = "calling_convention",
   3172       [DW_AT_count] = "count",
   3173       [DW_AT_data_member_location] = "data_member_location",
   3174       [DW_AT_decl_column] = "decl_column",
   3175       [DW_AT_decl_file] = "decl_file",
   3176       [DW_AT_decl_line] = "decl_line",
   3177       [DW_AT_declaration] = "declaration",
   3178       [DW_AT_discr_list] = "discr_list",
   3179       [DW_AT_encoding] = "encoding",
   3180       [DW_AT_external] = "external",
   3181       [DW_AT_frame_base] = "frame_base",
   3182       [DW_AT_friend] = "friend",
   3183       [DW_AT_identifier_case] = "identifier_case",
   3184       [DW_AT_macro_info] = "macro_info",
   3185       [DW_AT_namelist_item] = "namelist_item",
   3186       [DW_AT_priority] = "priority",
   3187       [DW_AT_segment] = "segment",
   3188       [DW_AT_specification] = "specification",
   3189       [DW_AT_static_link] = "static_link",
   3190       [DW_AT_type] = "type",
   3191       [DW_AT_use_location] = "use_location",
   3192       [DW_AT_variable_parameter] = "variable_parameter",
   3193       [DW_AT_virtuality] = "virtuality",
   3194       [DW_AT_vtable_elem_location] = "vtable_elem_location",
   3195       [DW_AT_allocated] = "allocated",
   3196       [DW_AT_associated] = "associated",
   3197       [DW_AT_data_location] = "data_location",
   3198       [DW_AT_byte_stride] = "byte_stride",
   3199       [DW_AT_entry_pc] = "entry_pc",
   3200       [DW_AT_use_UTF8] = "use_UTF8",
   3201       [DW_AT_extension] = "extension",
   3202       [DW_AT_ranges] = "ranges",
   3203       [DW_AT_trampoline] = "trampoline",
   3204       [DW_AT_call_column] = "call_column",
   3205       [DW_AT_call_file] = "call_file",
   3206       [DW_AT_call_line] = "call_line",
   3207       [DW_AT_description] = "description",
   3208       [DW_AT_binary_scale] = "binary_scale",
   3209       [DW_AT_decimal_scale] = "decimal_scale",
   3210       [DW_AT_small] = "small",
   3211       [DW_AT_decimal_sign] = "decimal_sign",
   3212       [DW_AT_digit_count] = "digit_count",
   3213       [DW_AT_picture_string] = "picture_string",
   3214       [DW_AT_mutable] = "mutable",
   3215       [DW_AT_threads_scaled] = "threads_scaled",
   3216       [DW_AT_explicit] = "explicit",
   3217       [DW_AT_object_pointer] = "object_pointer",
   3218       [DW_AT_endianity] = "endianity",
   3219       [DW_AT_elemental] = "elemental",
   3220       [DW_AT_pure] = "pure",
   3221       [DW_AT_recursive] = "recursive",
   3222     };
   3223   const unsigned int nknown_attrs = (sizeof (known_attrs)
   3224 				     / sizeof (known_attrs[0]));
   3225   static char buf[40];
   3226   const char *result = NULL;
   3227 
   3228   if (likely (attrnum < nknown_attrs))
   3229     result = known_attrs[attrnum];
   3230 
   3231   if (unlikely (result == NULL))
   3232     /* There are a few known extensions.  */
   3233     switch (attrnum)
   3234       {
   3235       case DW_AT_MIPS_fde:
   3236 	result = "MIPS_fde";
   3237 	break;
   3238 
   3239       case DW_AT_MIPS_loop_begin:
   3240 	result = "MIPS_loop_begin";
   3241 	break;
   3242 
   3243       case DW_AT_MIPS_tail_loop_begin:
   3244 	result = "MIPS_tail_loop_begin";
   3245 	break;
   3246 
   3247       case DW_AT_MIPS_epilog_begin:
   3248 	result = "MIPS_epilog_begin";
   3249 	break;
   3250 
   3251       case DW_AT_MIPS_loop_unroll_factor:
   3252 	result = "MIPS_loop_unroll_factor";
   3253 	break;
   3254 
   3255       case DW_AT_MIPS_software_pipeline_depth:
   3256 	result = "MIPS_software_pipeline_depth";
   3257 	break;
   3258 
   3259       case DW_AT_MIPS_linkage_name:
   3260 	result = "MIPS_linkage_name";
   3261 	break;
   3262 
   3263       case DW_AT_MIPS_stride:
   3264 	result = "MIPS_stride";
   3265 	break;
   3266 
   3267       case DW_AT_MIPS_abstract_name:
   3268 	result = "MIPS_abstract_name";
   3269 	break;
   3270 
   3271       case DW_AT_MIPS_clone_origin:
   3272 	result = "MIPS_clone_origin";
   3273 	break;
   3274 
   3275       case DW_AT_MIPS_has_inlines:
   3276 	result = "MIPS_has_inlines";
   3277 	break;
   3278 
   3279       case DW_AT_MIPS_stride_byte:
   3280 	result = "MIPS_stride_byte";
   3281 	break;
   3282 
   3283       case DW_AT_MIPS_stride_elem:
   3284 	result = "MIPS_stride_elem";
   3285 	break;
   3286 
   3287       case DW_AT_MIPS_ptr_dopetype:
   3288 	result = "MIPS_ptr_dopetype";
   3289 	break;
   3290 
   3291       case DW_AT_MIPS_allocatable_dopetype:
   3292 	result = "MIPS_allocatable_dopetype";
   3293 	break;
   3294 
   3295       case DW_AT_MIPS_assumed_shape_dopetype:
   3296 	result = "MIPS_assumed_shape_dopetype";
   3297 	break;
   3298 
   3299       case DW_AT_MIPS_assumed_size:
   3300 	result = "MIPS_assumed_size";
   3301 	break;
   3302 
   3303       case DW_AT_sf_names:
   3304 	result = "sf_names";
   3305 	break;
   3306 
   3307       case DW_AT_src_info:
   3308 	result = "src_info";
   3309 	break;
   3310 
   3311       case DW_AT_mac_info:
   3312 	result = "mac_info";
   3313 	break;
   3314 
   3315       case DW_AT_src_coords:
   3316 	result = "src_coords";
   3317 	break;
   3318 
   3319       case DW_AT_body_begin:
   3320 	result = "body_begin";
   3321 	break;
   3322 
   3323       case DW_AT_body_end:
   3324 	result = "body_end";
   3325 	break;
   3326 
   3327       default:
   3328 	if (attrnum < DW_AT_lo_user)
   3329 	  snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"),
   3330 		    attrnum);
   3331 	else
   3332 	  snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"),
   3333 		    attrnum);
   3334 	result = buf;
   3335 	break;
   3336       }
   3337 
   3338   return result;
   3339 }
   3340 
   3341 
   3342 static const char *
   3343 dwarf_form_string (unsigned int form)
   3344 {
   3345   static const char *const known_forms[] =
   3346     {
   3347       [DW_FORM_addr] = "addr",
   3348       [DW_FORM_block2] = "block2",
   3349       [DW_FORM_block4] = "block4",
   3350       [DW_FORM_data2] = "data2",
   3351       [DW_FORM_data4] = "data4",
   3352       [DW_FORM_data8] = "data8",
   3353       [DW_FORM_string] = "string",
   3354       [DW_FORM_block] = "block",
   3355       [DW_FORM_block1] = "block1",
   3356       [DW_FORM_data1] = "data1",
   3357       [DW_FORM_flag] = "flag",
   3358       [DW_FORM_sdata] = "sdata",
   3359       [DW_FORM_strp] = "strp",
   3360       [DW_FORM_udata] = "udata",
   3361       [DW_FORM_ref_addr] = "ref_addr",
   3362       [DW_FORM_ref1] = "ref1",
   3363       [DW_FORM_ref2] = "ref2",
   3364       [DW_FORM_ref4] = "ref4",
   3365       [DW_FORM_ref8] = "ref8",
   3366       [DW_FORM_ref_udata] = "ref_udata",
   3367       [DW_FORM_indirect] = "indirect"
   3368     };
   3369   const unsigned int nknown_forms = (sizeof (known_forms)
   3370 				     / sizeof (known_forms[0]));
   3371   static char buf[40];
   3372   const char *result = NULL;
   3373 
   3374   if (likely (form < nknown_forms))
   3375     result = known_forms[form];
   3376 
   3377   if (unlikely (result == NULL))
   3378     snprintf (buf, sizeof buf, gettext ("unknown form %" PRIx64),
   3379 	      (uint64_t) form);
   3380 
   3381   return result;
   3382 }
   3383 
   3384 
   3385 static const char *
   3386 dwarf_lang_string (unsigned int lang)
   3387 {
   3388   static const char *const known[] =
   3389     {
   3390       [DW_LANG_C89] = "ISO C89",
   3391       [DW_LANG_C] = "C",
   3392       [DW_LANG_Ada83] = "Ada83",
   3393       [DW_LANG_C_plus_plus] = "C++",
   3394       [DW_LANG_Cobol74] = "Cobol74",
   3395       [DW_LANG_Cobol85] = "Cobol85",
   3396       [DW_LANG_Fortran77] = "Fortran77",
   3397       [DW_LANG_Fortran90] = "Fortran90",
   3398       [DW_LANG_Pascal83] = "Pascal83",
   3399       [DW_LANG_Modula2] = "Modula2",
   3400       [DW_LANG_Java] = "Java",
   3401       [DW_LANG_C99] = "ISO C99",
   3402       [DW_LANG_Ada95] = "Ada95",
   3403       [DW_LANG_Fortran95] = "Fortran95",
   3404       [DW_LANG_PL1] = "PL1",
   3405       [DW_LANG_Objc] = "Objective C",
   3406       [DW_LANG_ObjC_plus_plus] = "Objective C++",
   3407       [DW_LANG_UPC] = "UPC",
   3408       [DW_LANG_D] = "D",
   3409     };
   3410 
   3411   if (likely (lang < sizeof (known) / sizeof (known[0])))
   3412     return known[lang];
   3413   else if (lang == DW_LANG_Mips_Assembler)
   3414     /* This language tag is used for assembler in general.  */
   3415     return "Assembler";
   3416 
   3417   if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user)
   3418     {
   3419       static char buf[30];
   3420       snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user);
   3421       return buf;
   3422     }
   3423 
   3424   return "???";
   3425 }
   3426 
   3427 
   3428 static const char *
   3429 dwarf_inline_string (unsigned int code)
   3430 {
   3431   static const char *const known[] =
   3432     {
   3433       [DW_INL_not_inlined] = "not_inlined",
   3434       [DW_INL_inlined] = "inlined",
   3435       [DW_INL_declared_not_inlined] = "declared_not_inlined",
   3436       [DW_INL_declared_inlined] = "declared_inlined"
   3437     };
   3438 
   3439   if (likely (code < sizeof (known) / sizeof (known[0])))
   3440     return known[code];
   3441 
   3442   return "???";
   3443 }
   3444 
   3445 
   3446 static const char *
   3447 dwarf_encoding_string (unsigned int code)
   3448 {
   3449   static const char *const known[] =
   3450     {
   3451       [DW_ATE_void] = "void",
   3452       [DW_ATE_address] = "address",
   3453       [DW_ATE_boolean] = "boolean",
   3454       [DW_ATE_complex_float] = "complex_float",
   3455       [DW_ATE_float] = "float",
   3456       [DW_ATE_signed] = "signed",
   3457       [DW_ATE_signed_char] = "signed_char",
   3458       [DW_ATE_unsigned] = "unsigned",
   3459       [DW_ATE_unsigned_char] = "unsigned_char",
   3460       [DW_ATE_imaginary_float] = "imaginary_float",
   3461       [DW_ATE_packed_decimal] = "packed_decimal",
   3462       [DW_ATE_numeric_string] = "numeric_string",
   3463       [DW_ATE_edited] = "edited",
   3464       [DW_ATE_signed_fixed] = "signed_fixed",
   3465       [DW_ATE_unsigned_fixed] = "unsigned_fixed",
   3466       [DW_ATE_decimal_float] = "decimal_float",
   3467     };
   3468 
   3469   if (likely (code < sizeof (known) / sizeof (known[0])))
   3470     return known[code];
   3471 
   3472   if (code >= DW_ATE_lo_user && code <= DW_ATE_hi_user)
   3473     {
   3474       static char buf[30];
   3475       snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_ATE_lo_user);
   3476       return buf;
   3477     }
   3478 
   3479   return "???";
   3480 }
   3481 
   3482 
   3483 static const char *
   3484 dwarf_access_string (unsigned int code)
   3485 {
   3486   static const char *const known[] =
   3487     {
   3488       [DW_ACCESS_public] = "public",
   3489       [DW_ACCESS_protected] = "protected",
   3490       [DW_ACCESS_private] = "private"
   3491     };
   3492 
   3493   if (likely (code < sizeof (known) / sizeof (known[0])))
   3494     return known[code];
   3495 
   3496   return "???";
   3497 }
   3498 
   3499 
   3500 static const char *
   3501 dwarf_visibility_string (unsigned int code)
   3502 {
   3503   static const char *const known[] =
   3504     {
   3505       [DW_VIS_local] = "local",
   3506       [DW_VIS_exported] = "exported",
   3507       [DW_VIS_qualified] = "qualified"
   3508     };
   3509 
   3510   if (likely (code < sizeof (known) / sizeof (known[0])))
   3511     return known[code];
   3512 
   3513   return "???";
   3514 }
   3515 
   3516 
   3517 static const char *
   3518 dwarf_virtuality_string (unsigned int code)
   3519 {
   3520   static const char *const known[] =
   3521     {
   3522       [DW_VIRTUALITY_none] = "none",
   3523       [DW_VIRTUALITY_virtual] = "virtual",
   3524       [DW_VIRTUALITY_pure_virtual] = "pure_virtual"
   3525     };
   3526 
   3527   if (likely (code < sizeof (known) / sizeof (known[0])))
   3528     return known[code];
   3529 
   3530   return "???";
   3531 }
   3532 
   3533 
   3534 static const char *
   3535 dwarf_identifier_case_string (unsigned int code)
   3536 {
   3537   static const char *const known[] =
   3538     {
   3539       [DW_ID_case_sensitive] = "sensitive",
   3540       [DW_ID_up_case] = "up_case",
   3541       [DW_ID_down_case] = "down_case",
   3542       [DW_ID_case_insensitive] = "insensitive"
   3543     };
   3544 
   3545   if (likely (code < sizeof (known) / sizeof (known[0])))
   3546     return known[code];
   3547 
   3548   return "???";
   3549 }
   3550 
   3551 
   3552 static const char *
   3553 dwarf_calling_convention_string (unsigned int code)
   3554 {
   3555   static const char *const known[] =
   3556     {
   3557       [DW_CC_normal] = "normal",
   3558       [DW_CC_program] = "program",
   3559       [DW_CC_nocall] = "nocall",
   3560     };
   3561 
   3562   if (likely (code < sizeof (known) / sizeof (known[0])))
   3563     return known[code];
   3564 
   3565   if (code >= DW_CC_lo_user && code <= DW_CC_hi_user)
   3566     {
   3567       static char buf[30];
   3568       snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_CC_lo_user);
   3569       return buf;
   3570     }
   3571 
   3572   return "???";
   3573 }
   3574 
   3575 
   3576 static const char *
   3577 dwarf_ordering_string (unsigned int code)
   3578 {
   3579   static const char *const known[] =
   3580     {
   3581       [DW_ORD_row_major] = "row_major",
   3582       [DW_ORD_col_major] = "col_major"
   3583     };
   3584 
   3585   if (likely (code < sizeof (known) / sizeof (known[0])))
   3586     return known[code];
   3587 
   3588   return "???";
   3589 }
   3590 
   3591 
   3592 static const char *
   3593 dwarf_discr_list_string (unsigned int code)
   3594 {
   3595   static const char *const known[] =
   3596     {
   3597       [DW_DSC_label] = "label",
   3598       [DW_DSC_range] = "range"
   3599     };
   3600 
   3601   if (likely (code < sizeof (known) / sizeof (known[0])))
   3602     return known[code];
   3603 
   3604   return "???";
   3605 }
   3606 
   3607 
   3608 static void
   3609 print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
   3610 	   unsigned int addrsize, Dwarf_Word len, const unsigned char *data)
   3611 {
   3612   static const char *const known[] =
   3613     {
   3614       [DW_OP_addr] = "addr",
   3615       [DW_OP_deref] = "deref",
   3616       [DW_OP_const1u] = "const1u",
   3617       [DW_OP_const1s] = "const1s",
   3618       [DW_OP_const2u] = "const2u",
   3619       [DW_OP_const2s] = "const2s",
   3620       [DW_OP_const4u] = "const4u",
   3621       [DW_OP_const4s] = "const4s",
   3622       [DW_OP_const8u] = "const8u",
   3623       [DW_OP_const8s] = "const8s",
   3624       [DW_OP_constu] = "constu",
   3625       [DW_OP_consts] = "consts",
   3626       [DW_OP_dup] = "dup",
   3627       [DW_OP_drop] = "drop",
   3628       [DW_OP_over] = "over",
   3629       [DW_OP_pick] = "pick",
   3630       [DW_OP_swap] = "swap",
   3631       [DW_OP_rot] = "rot",
   3632       [DW_OP_xderef] = "xderef",
   3633       [DW_OP_abs] = "abs",
   3634       [DW_OP_and] = "and",
   3635       [DW_OP_div] = "div",
   3636       [DW_OP_minus] = "minus",
   3637       [DW_OP_mod] = "mod",
   3638       [DW_OP_mul] = "mul",
   3639       [DW_OP_neg] = "neg",
   3640       [DW_OP_not] = "not",
   3641       [DW_OP_or] = "or",
   3642       [DW_OP_plus] = "plus",
   3643       [DW_OP_plus_uconst] = "plus_uconst",
   3644       [DW_OP_shl] = "shl",
   3645       [DW_OP_shr] = "shr",
   3646       [DW_OP_shra] = "shra",
   3647       [DW_OP_xor] = "xor",
   3648       [DW_OP_bra] = "bra",
   3649       [DW_OP_eq] = "eq",
   3650       [DW_OP_ge] = "ge",
   3651       [DW_OP_gt] = "gt",
   3652       [DW_OP_le] = "le",
   3653       [DW_OP_lt] = "lt",
   3654       [DW_OP_ne] = "ne",
   3655       [DW_OP_skip] = "skip",
   3656       [DW_OP_lit0] = "lit0",
   3657       [DW_OP_lit1] = "lit1",
   3658       [DW_OP_lit2] = "lit2",
   3659       [DW_OP_lit3] = "lit3",
   3660       [DW_OP_lit4] = "lit4",
   3661       [DW_OP_lit5] = "lit5",
   3662       [DW_OP_lit6] = "lit6",
   3663       [DW_OP_lit7] = "lit7",
   3664       [DW_OP_lit8] = "lit8",
   3665       [DW_OP_lit9] = "lit9",
   3666       [DW_OP_lit10] = "lit10",
   3667       [DW_OP_lit11] = "lit11",
   3668       [DW_OP_lit12] = "lit12",
   3669       [DW_OP_lit13] = "lit13",
   3670       [DW_OP_lit14] = "lit14",
   3671       [DW_OP_lit15] = "lit15",
   3672       [DW_OP_lit16] = "lit16",
   3673       [DW_OP_lit17] = "lit17",
   3674       [DW_OP_lit18] = "lit18",
   3675       [DW_OP_lit19] = "lit19",
   3676       [DW_OP_lit20] = "lit20",
   3677       [DW_OP_lit21] = "lit21",
   3678       [DW_OP_lit22] = "lit22",
   3679       [DW_OP_lit23] = "lit23",
   3680       [DW_OP_lit24] = "lit24",
   3681       [DW_OP_lit25] = "lit25",
   3682       [DW_OP_lit26] = "lit26",
   3683       [DW_OP_lit27] = "lit27",
   3684       [DW_OP_lit28] = "lit28",
   3685       [DW_OP_lit29] = "lit29",
   3686       [DW_OP_lit30] = "lit30",
   3687       [DW_OP_lit31] = "lit31",
   3688       [DW_OP_reg0] = "reg0",
   3689       [DW_OP_reg1] = "reg1",
   3690       [DW_OP_reg2] = "reg2",
   3691       [DW_OP_reg3] = "reg3",
   3692       [DW_OP_reg4] = "reg4",
   3693       [DW_OP_reg5] = "reg5",
   3694       [DW_OP_reg6] = "reg6",
   3695       [DW_OP_reg7] = "reg7",
   3696       [DW_OP_reg8] = "reg8",
   3697       [DW_OP_reg9] = "reg9",
   3698       [DW_OP_reg10] = "reg10",
   3699       [DW_OP_reg11] = "reg11",
   3700       [DW_OP_reg12] = "reg12",
   3701       [DW_OP_reg13] = "reg13",
   3702       [DW_OP_reg14] = "reg14",
   3703       [DW_OP_reg15] = "reg15",
   3704       [DW_OP_reg16] = "reg16",
   3705       [DW_OP_reg17] = "reg17",
   3706       [DW_OP_reg18] = "reg18",
   3707       [DW_OP_reg19] = "reg19",
   3708       [DW_OP_reg20] = "reg20",
   3709       [DW_OP_reg21] = "reg21",
   3710       [DW_OP_reg22] = "reg22",
   3711       [DW_OP_reg23] = "reg23",
   3712       [DW_OP_reg24] = "reg24",
   3713       [DW_OP_reg25] = "reg25",
   3714       [DW_OP_reg26] = "reg26",
   3715       [DW_OP_reg27] = "reg27",
   3716       [DW_OP_reg28] = "reg28",
   3717       [DW_OP_reg29] = "reg29",
   3718       [DW_OP_reg30] = "reg30",
   3719       [DW_OP_reg31] = "reg31",
   3720       [DW_OP_breg0] = "breg0",
   3721       [DW_OP_breg1] = "breg1",
   3722       [DW_OP_breg2] = "breg2",
   3723       [DW_OP_breg3] = "breg3",
   3724       [DW_OP_breg4] = "breg4",
   3725       [DW_OP_breg5] = "breg5",
   3726       [DW_OP_breg6] = "breg6",
   3727       [DW_OP_breg7] = "breg7",
   3728       [DW_OP_breg8] = "breg8",
   3729       [DW_OP_breg9] = "breg9",
   3730       [DW_OP_breg10] = "breg10",
   3731       [DW_OP_breg11] = "breg11",
   3732       [DW_OP_breg12] = "breg12",
   3733       [DW_OP_breg13] = "breg13",
   3734       [DW_OP_breg14] = "breg14",
   3735       [DW_OP_breg15] = "breg15",
   3736       [DW_OP_breg16] = "breg16",
   3737       [DW_OP_breg17] = "breg17",
   3738       [DW_OP_breg18] = "breg18",
   3739       [DW_OP_breg19] = "breg19",
   3740       [DW_OP_breg20] = "breg20",
   3741       [DW_OP_breg21] = "breg21",
   3742       [DW_OP_breg22] = "breg22",
   3743       [DW_OP_breg23] = "breg23",
   3744       [DW_OP_breg24] = "breg24",
   3745       [DW_OP_breg25] = "breg25",
   3746       [DW_OP_breg26] = "breg26",
   3747       [DW_OP_breg27] = "breg27",
   3748       [DW_OP_breg28] = "breg28",
   3749       [DW_OP_breg29] = "breg29",
   3750       [DW_OP_breg30] = "breg30",
   3751       [DW_OP_breg31] = "breg31",
   3752       [DW_OP_regx] = "regx",
   3753       [DW_OP_fbreg] = "fbreg",
   3754       [DW_OP_bregx] = "bregx",
   3755       [DW_OP_piece] = "piece",
   3756       [DW_OP_deref_size] = "deref_size",
   3757       [DW_OP_xderef_size] = "xderef_size",
   3758       [DW_OP_nop] = "nop",
   3759       [DW_OP_push_object_address] = "push_object_address",
   3760       [DW_OP_call2] = "call2",
   3761       [DW_OP_call4] = "call4",
   3762       [DW_OP_call_ref] = "call_ref",
   3763       [DW_OP_form_tls_address] = "form_tls_address",
   3764       [DW_OP_call_frame_cfa] = "call_frame_cfa",
   3765       [DW_OP_bit_piece] = "bit_piece",
   3766     };
   3767 
   3768   Dwarf_Word offset = 0;
   3769   while (len-- > 0)
   3770     {
   3771       uint_fast8_t op = *data++;
   3772 
   3773       switch (op)
   3774 	{
   3775 	case DW_OP_call_ref:
   3776 	case DW_OP_addr:;
   3777 	  /* Address operand.  */
   3778 	  Dwarf_Word addr;
   3779 	  if (addrsize == 4)
   3780 	    addr = read_4ubyte_unaligned (dbg, data);
   3781 	  else
   3782 	    {
   3783 	      assert (addrsize == 8);
   3784 	      addr = read_8ubyte_unaligned (dbg, data);
   3785 	    }
   3786 	  data += addrsize;
   3787 	  len -= addrsize;
   3788 
   3789 	  if (op == DW_OP_addr)
   3790 	    {
   3791 	      char *a = format_dwarf_addr (dwflmod, 0, addr);
   3792 	      printf ("%*s[%4" PRIuMAX "] %s %s\n",
   3793 		      indent, "", (uintmax_t) offset,
   3794 		      known[op] ?: "???", a);
   3795 	      free (a);
   3796 	    }
   3797 	  else
   3798 	    printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
   3799 		    indent, "", (uintmax_t) offset,
   3800 		    known[op] ?: "???", (uintmax_t) addr);
   3801 	  offset += 1 + addrsize;
   3802 	  break;
   3803 
   3804 	case DW_OP_deref_size:
   3805 	case DW_OP_xderef_size:
   3806 	case DW_OP_pick:
   3807 	case DW_OP_const1u:
   3808 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
   3809 		  indent, "", (uintmax_t) offset,
   3810 		  known[op] ?: "???", *((uint8_t *) data));
   3811 	  ++data;
   3812 	  --len;
   3813 	  offset += 2;
   3814 	  break;
   3815 
   3816 	case DW_OP_const2u:
   3817 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
   3818 		  indent, "", (uintmax_t) offset,
   3819 		  known[op] ?: "???", read_2ubyte_unaligned (dbg, data));
   3820 	  len -= 2;
   3821 	  data += 2;
   3822 	  offset += 3;
   3823 	  break;
   3824 
   3825 	case DW_OP_const4u:
   3826 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
   3827 		  indent, "", (uintmax_t) offset,
   3828 		  known[op] ?: "???", read_4ubyte_unaligned (dbg, data));
   3829 	  len -= 4;
   3830 	  data += 4;
   3831 	  offset += 5;
   3832 	  break;
   3833 
   3834 	case DW_OP_const8u:
   3835 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
   3836 		  indent, "", (uintmax_t) offset,
   3837 		  known[op] ?: "???", read_8ubyte_unaligned (dbg, data));
   3838 	  len -= 8;
   3839 	  data += 8;
   3840 	  offset += 9;
   3841 	  break;
   3842 
   3843 	case DW_OP_const1s:
   3844 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
   3845 		  indent, "", (uintmax_t) offset,
   3846 		  known[op] ?: "???", *((int8_t *) data));
   3847 	  ++data;
   3848 	  --len;
   3849 	  offset += 2;
   3850 	  break;
   3851 
   3852 	case DW_OP_const2s:
   3853 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
   3854 		  indent, "", (uintmax_t) offset,
   3855 		  known[op] ?: "???", read_2sbyte_unaligned (dbg, data));
   3856 	  len -= 2;
   3857 	  data += 2;
   3858 	  offset += 3;
   3859 	  break;
   3860 
   3861 	case DW_OP_const4s:
   3862 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
   3863 		  indent, "", (uintmax_t) offset,
   3864 		  known[op] ?: "???", read_4sbyte_unaligned (dbg, data));
   3865 	  len -= 4;
   3866 	  data += 4;
   3867 	  offset += 5;
   3868 	  break;
   3869 
   3870 	case DW_OP_const8s:
   3871 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
   3872 		  indent, "", (uintmax_t) offset,
   3873 		  known[op] ?: "???", read_8sbyte_unaligned (dbg, data));
   3874 	  len -= 8;
   3875 	  data += 8;
   3876 	  offset += 9;
   3877 	  break;
   3878 
   3879 	case DW_OP_piece:
   3880 	case DW_OP_regx:
   3881 	case DW_OP_plus_uconst:
   3882 	case DW_OP_constu:;
   3883 	  const unsigned char *start = data;
   3884 	  unsigned int uleb;
   3885 	  get_uleb128 (uleb, data);
   3886 	  printf ("%*s[%4" PRIuMAX "] %s %u\n",
   3887 		  indent, "", (uintmax_t) offset,
   3888 		  known[op] ?: "???", uleb);
   3889 	  len -= data - start;
   3890 	  offset += 1 + (data - start);
   3891 	  break;
   3892 
   3893 	case DW_OP_bit_piece:
   3894 	  start = data;
   3895 	  unsigned int uleb2;
   3896 	  get_uleb128 (uleb, data);
   3897 	  get_uleb128 (uleb2, data);
   3898 	  printf ("%*s[%4" PRIuMAX "] %s %u, %u\n",
   3899 		  indent, "", (uintmax_t) offset,
   3900 		  known[op] ?: "???", uleb, uleb2);
   3901 	  len -= data - start;
   3902 	  offset += 1 + (data - start);
   3903 	  break;
   3904 
   3905 	case DW_OP_fbreg:
   3906 	case DW_OP_breg0 ... DW_OP_breg31:
   3907 	case DW_OP_consts:
   3908 	  start = data;
   3909 	  unsigned int sleb;
   3910 	  get_sleb128 (sleb, data);
   3911 	  printf ("%*s[%4" PRIuMAX "] %s %d\n",
   3912 		  indent, "", (uintmax_t) offset,
   3913 		  known[op] ?: "???", sleb);
   3914 	  len -= data - start;
   3915 	  offset += 1 + (data - start);
   3916 	  break;
   3917 
   3918 	case DW_OP_bregx:
   3919 	  start = data;
   3920 	  get_uleb128 (uleb, data);
   3921 	  get_sleb128 (sleb, data);
   3922 	  printf ("%*s[%4" PRIuMAX "] %s %u %d\n",
   3923 		  indent, "", (uintmax_t) offset,
   3924 		  known[op] ?: "???", uleb, sleb);
   3925 	  len -= data - start;
   3926 	  offset += 1 + (data - start);
   3927 	  break;
   3928 
   3929 	case DW_OP_call2:
   3930 	case DW_OP_call4:
   3931 	case DW_OP_skip:
   3932 	case DW_OP_bra:
   3933 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
   3934 		  indent, "", (uintmax_t) offset,
   3935 		  known[op] ?: "???",
   3936 		  (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
   3937 	  len -= 2;
   3938 	  data += 2;
   3939 	  offset += 3;
   3940 	  break;
   3941 
   3942 	default:
   3943 	  /* No Operand.  */
   3944 	  if (op < sizeof known / sizeof known[0] && known[op] != NULL)
   3945 	    printf ("%*s[%4" PRIuMAX "] %s\n",
   3946 		    indent, "", (uintmax_t) offset, known[op]);
   3947 	  else
   3948 	    printf ("%*s[%4" PRIuMAX "] %#x\n",
   3949 		    indent, "", (uintmax_t) offset, op);
   3950 	  ++offset;
   3951 	  break;
   3952 	}
   3953 
   3954       indent = indentrest;
   3955     }
   3956 }
   3957 
   3958 
   3959 static void
   3960 print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   3961 			    Ebl *ebl __attribute__ ((unused)),
   3962 			    GElf_Ehdr *ehdr __attribute__ ((unused)),
   3963 			    Elf_Scn *scn __attribute__ ((unused)),
   3964 			    GElf_Shdr *shdr, Dwarf *dbg)
   3965 {
   3966   printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
   3967 		   " [ Code]\n"),
   3968 	  ".debug_abbrev", (uint64_t) shdr->sh_offset);
   3969 
   3970   Dwarf_Off offset = 0;
   3971   while (offset < shdr->sh_size)
   3972     {
   3973       printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
   3974 	      offset);
   3975 
   3976       while (1)
   3977 	{
   3978 	  size_t length;
   3979 	  Dwarf_Abbrev abbrev;
   3980 
   3981 	  int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
   3982 	  if (res != 0)
   3983 	    {
   3984 	      if (unlikely (res < 0))
   3985 		{
   3986 		  printf (gettext ("\
   3987  *** error while reading abbreviation: %s\n"),
   3988 			  dwarf_errmsg (-1));
   3989 		  return;
   3990 		}
   3991 
   3992 	      /* This is the NUL byte at the end of the section.  */
   3993 	      ++offset;
   3994 	      break;
   3995 	    }
   3996 
   3997 	  /* We know these calls can never fail.  */
   3998 	  unsigned int code = dwarf_getabbrevcode (&abbrev);
   3999 	  unsigned int tag = dwarf_getabbrevtag (&abbrev);
   4000 	  int has_children = dwarf_abbrevhaschildren (&abbrev);
   4001 
   4002 	  printf (gettext (" [%5u] offset: %" PRId64
   4003 			   ", children: %s, tag: %s\n"),
   4004 		  code, (int64_t) offset,
   4005 		  has_children ? gettext ("yes") : gettext ("no"),
   4006 		  dwarf_tag_string (tag));
   4007 
   4008 	  size_t cnt = 0;
   4009 	  unsigned int name;
   4010 	  unsigned int form;
   4011 	  Dwarf_Off enoffset;
   4012 	  while (dwarf_getabbrevattr (&abbrev, cnt,
   4013 				      &name, &form, &enoffset) == 0)
   4014 	    {
   4015 	      printf ("          attr: %s, form: %s, offset: %#" PRIx64 "\n",
   4016 		      dwarf_attr_string (name), dwarf_form_string (form),
   4017 		      (uint64_t) enoffset);
   4018 
   4019 	      ++cnt;
   4020 	    }
   4021 
   4022 	  offset += length;
   4023 	}
   4024     }
   4025 }
   4026 
   4027 
   4028 /* Print content of DWARF .debug_aranges section.  We fortunately do
   4029    not have to know a bit about the structure of the section, libdwarf
   4030    takes care of it.  */
   4031 static void
   4032 print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   4033 			     Ebl *ebl __attribute__ ((unused)),
   4034 			     GElf_Ehdr *ehdr __attribute__ ((unused)),
   4035 			     Elf_Scn *scn __attribute__ ((unused)),
   4036 			     GElf_Shdr *shdr, Dwarf *dbg)
   4037 {
   4038   Dwarf_Aranges *aranges;
   4039   size_t cnt;
   4040   if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
   4041     {
   4042       error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
   4043 	     dwarf_errmsg (-1));
   4044       return;
   4045     }
   4046 
   4047   printf (ngettext ("\
   4048 \nDWARF section '%s' at offset %#" PRIx64 " contains %zu entry:\n",
   4049 		    "\
   4050 \nDWARF section '%s' at offset %#" PRIx64 " contains %zu entries:\n",
   4051 		    cnt),
   4052 	  ".debug_aranges", (uint64_t) shdr->sh_offset, cnt);
   4053 
   4054   /* Compute floor(log16(cnt)).  */
   4055   size_t tmp = cnt;
   4056   int digits = 1;
   4057   while (tmp >= 16)
   4058     {
   4059       ++digits;
   4060       tmp >>= 4;
   4061     }
   4062 
   4063   for (size_t n = 0; n < cnt; ++n)
   4064     {
   4065       Dwarf_Arange *runp = dwarf_onearange (aranges, n);
   4066       if (unlikely (runp == NULL))
   4067 	{
   4068 	  printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
   4069 	  return;
   4070 	}
   4071 
   4072       Dwarf_Addr start;
   4073       Dwarf_Word length;
   4074       Dwarf_Off offset;
   4075 
   4076       if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
   4077 	printf (gettext (" [%*zu] ???\n"), digits, n);
   4078       else
   4079 	printf (gettext (" [%*zu] start: %0#*" PRIx64
   4080 			 ", length: %5" PRIu64 ", CU DIE offset: %6"
   4081 			 PRId64 "\n"),
   4082 		digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
   4083 		(uint64_t) start, (uint64_t) length, (int64_t) offset);
   4084     }
   4085 }
   4086 
   4087 /* Print content of DWARF .debug_ranges section.  */
   4088 static void
   4089 print_debug_ranges_section (Dwfl_Module *dwflmod,
   4090 			    Ebl *ebl __attribute__ ((unused)),
   4091 			    GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr,
   4092 			    Dwarf *dbg)
   4093 {
   4094   Elf_Data *data = elf_rawdata (scn, NULL);
   4095 
   4096   if (unlikely (data == NULL))
   4097     {
   4098       error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
   4099 	     elf_errmsg (-1));
   4100       return;
   4101     }
   4102 
   4103   printf (gettext ("\
   4104 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
   4105 	  ".debug_ranges", (uint64_t) shdr->sh_offset);
   4106 
   4107   size_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
   4108 
   4109   bool first = true;
   4110   unsigned char *readp = data->d_buf;
   4111   while (readp < (unsigned char *) data->d_buf + data->d_size)
   4112     {
   4113       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
   4114 
   4115       if (unlikely (data->d_size - offset < address_size * 2))
   4116 	{
   4117 	  printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
   4118 	  break;
   4119 	}
   4120 
   4121       Dwarf_Addr begin;
   4122       Dwarf_Addr end;
   4123       if (address_size == 8)
   4124 	{
   4125 	  begin = read_8ubyte_unaligned_inc (dbg, readp);
   4126 	  end = read_8ubyte_unaligned_inc (dbg, readp);
   4127 	}
   4128       else
   4129 	{
   4130 	  begin = read_4ubyte_unaligned_inc (dbg, readp);
   4131 	  end = read_4ubyte_unaligned_inc (dbg, readp);
   4132 	  if (begin == (Dwarf_Addr) (uint32_t) -1)
   4133 	    begin = (Dwarf_Addr) -1l;
   4134 	}
   4135 
   4136       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
   4137 	{
   4138 	  char *b = format_dwarf_addr (dwflmod, address_size, end);
   4139 	  printf (gettext (" [%6tx]  base address %s\n"), offset, b);
   4140 	  free (b);
   4141 	}
   4142       else if (begin == 0 && end == 0) /* End of list entry.  */
   4143 	first = true;
   4144       else
   4145 	{
   4146 	  char *b = format_dwarf_addr (dwflmod, address_size, begin);
   4147 	  char *e = format_dwarf_addr (dwflmod, address_size, end);
   4148 	  /* We have an address range entry.  */
   4149 	  if (first)		/* First address range entry in a list.  */
   4150 	    printf (gettext (" [%6tx]  %s..%s\n"), offset, b, e);
   4151 	  else
   4152 	    printf (gettext ("           %s..%s\n"), b, e);
   4153 	  free (b);
   4154 	  free (e);
   4155 
   4156 	  first = false;
   4157 	}
   4158     }
   4159 }
   4160 
   4161 
   4162 static void
   4163 print_debug_frame_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   4164 			   Ebl *ebl __attribute__ ((unused)),
   4165 			   GElf_Ehdr *ehdr __attribute__ ((unused)),
   4166 			   Elf_Scn *scn __attribute__ ((unused)),
   4167 			   GElf_Shdr *shdr __attribute__ ((unused)),
   4168 			   Dwarf *dbg __attribute__ ((unused)))
   4169 {
   4170 }
   4171 
   4172 
   4173 struct attrcb_args
   4174 {
   4175   Dwfl_Module *dwflmod;
   4176   Dwarf *dbg;
   4177   int level;
   4178   unsigned int addrsize;
   4179   Dwarf_Off cu_offset;
   4180 };
   4181 
   4182 
   4183 static int
   4184 attr_callback (Dwarf_Attribute *attrp, void *arg)
   4185 {
   4186   struct attrcb_args *cbargs = (struct attrcb_args *) arg;
   4187   const int level = cbargs->level;
   4188 
   4189   unsigned int attr = dwarf_whatattr (attrp);
   4190   if (unlikely (attr == 0))
   4191     {
   4192       error (0, 0, gettext ("cannot get attribute code: %s"),
   4193 	     dwarf_errmsg (-1));
   4194       return DWARF_CB_ABORT;
   4195     }
   4196 
   4197   unsigned int form = dwarf_whatform (attrp);
   4198   if (unlikely (form == 0))
   4199     {
   4200       error (0, 0, gettext ("cannot get attribute form: %s"),
   4201 	     dwarf_errmsg (-1));
   4202       return DWARF_CB_ABORT;
   4203     }
   4204 
   4205   switch (form)
   4206     {
   4207     case DW_FORM_addr:
   4208       {
   4209 	Dwarf_Addr addr;
   4210 	if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
   4211 	  {
   4212 	  attrval_out:
   4213 	    error (0, 0, gettext ("cannot get attribute value: %s"),
   4214 		   dwarf_errmsg (-1));
   4215 	    return DWARF_CB_ABORT;
   4216 	  }
   4217 	char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr);
   4218 	printf ("           %*s%-20s %s\n",
   4219 		(int) (level * 2), "", dwarf_attr_string (attr), a);
   4220 	free (a);
   4221       }
   4222       break;
   4223 
   4224     case DW_FORM_indirect:
   4225     case DW_FORM_strp:
   4226     case DW_FORM_string:;
   4227       const char *str = dwarf_formstring (attrp);
   4228       if (unlikely (str == NULL))
   4229 	goto attrval_out;
   4230       printf ("           %*s%-20s \"%s\"\n",
   4231 	      (int) (level * 2), "", dwarf_attr_string (attr), str);
   4232       break;
   4233 
   4234     case DW_FORM_ref_addr:
   4235     case DW_FORM_ref_udata:
   4236     case DW_FORM_ref8:
   4237     case DW_FORM_ref4:
   4238     case DW_FORM_ref2:
   4239     case DW_FORM_ref1:;
   4240       Dwarf_Die ref;
   4241       if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
   4242 	goto attrval_out;
   4243 
   4244       printf ("           %*s%-20s [%6" PRIxMAX "]\n",
   4245 	      (int) (level * 2), "", dwarf_attr_string (attr),
   4246 	      (uintmax_t) dwarf_dieoffset (&ref));
   4247       break;
   4248 
   4249     case DW_FORM_udata:
   4250     case DW_FORM_sdata:
   4251     case DW_FORM_data8:
   4252     case DW_FORM_data4:
   4253     case DW_FORM_data2:
   4254     case DW_FORM_data1:;
   4255       Dwarf_Word num;
   4256       if (unlikely (dwarf_formudata (attrp, &num) != 0))
   4257 	goto attrval_out;
   4258 
   4259       const char *valuestr = NULL;
   4260       switch (attr)
   4261 	{
   4262 	case DW_AT_location:
   4263 	case DW_AT_data_location:
   4264 	case DW_AT_data_member_location:
   4265 	case DW_AT_vtable_elem_location:
   4266 	case DW_AT_string_length:
   4267 	case DW_AT_use_location:
   4268 	case DW_AT_frame_base:
   4269 	case DW_AT_return_addr:
   4270 	case DW_AT_static_link:
   4271 	  printf ("           %*s%-20s location list [%6" PRIxMAX "]\n",
   4272 		  (int) (level * 2), "", dwarf_attr_string (attr),
   4273 		  (uintmax_t) num);
   4274 	  return DWARF_CB_OK;
   4275 
   4276 	case DW_AT_ranges:
   4277 	  printf ("           %*s%-20s range list [%6" PRIxMAX "]\n",
   4278 		  (int) (level * 2), "", dwarf_attr_string (attr),
   4279 		  (uintmax_t) num);
   4280 	  return DWARF_CB_OK;
   4281 
   4282 	case DW_AT_language:
   4283 	  valuestr = dwarf_lang_string (num);
   4284 	  break;
   4285 	case DW_AT_encoding:
   4286 	  valuestr = dwarf_encoding_string (num);
   4287 	  break;
   4288 	case DW_AT_accessibility:
   4289 	  valuestr = dwarf_access_string (num);
   4290 	  break;
   4291 	case DW_AT_visibility:
   4292 	  valuestr = dwarf_visibility_string (num);
   4293 	  break;
   4294 	case DW_AT_virtuality:
   4295 	  valuestr = dwarf_virtuality_string (num);
   4296 	  break;
   4297 	case DW_AT_identifier_case:
   4298 	  valuestr = dwarf_identifier_case_string (num);
   4299 	  break;
   4300 	case DW_AT_calling_convention:
   4301 	  valuestr = dwarf_calling_convention_string (num);
   4302 	  break;
   4303 	case DW_AT_inline:
   4304 	  valuestr = dwarf_inline_string (num);
   4305 	  break;
   4306 	case DW_AT_ordering:
   4307 	  valuestr = dwarf_ordering_string (num);
   4308 	  break;
   4309 	case DW_AT_discr_list:
   4310 	  valuestr = dwarf_discr_list_string (num);
   4311 	  break;
   4312 	default:
   4313 	  /* Nothing.  */
   4314 	  break;
   4315 	}
   4316 
   4317       if (valuestr == NULL)
   4318 	printf ("           %*s%-20s %" PRIuMAX "\n",
   4319 		(int) (level * 2), "", dwarf_attr_string (attr),
   4320 		(uintmax_t) num);
   4321       else
   4322 	printf ("           %*s%-20s %s (%" PRIuMAX ")\n",
   4323 		(int) (level * 2), "", dwarf_attr_string (attr),
   4324 		valuestr, (uintmax_t) num);
   4325       break;
   4326 
   4327     case DW_FORM_flag:;
   4328       bool flag;
   4329       if (unlikely (dwarf_formflag (attrp, &flag) != 0))
   4330 	goto attrval_out;
   4331 
   4332       printf ("           %*s%-20s %s\n",
   4333 	      (int) (level * 2), "", dwarf_attr_string (attr),
   4334 	      nl_langinfo (flag ? YESSTR : NOSTR));
   4335       break;
   4336 
   4337     case DW_FORM_block4:
   4338     case DW_FORM_block2:
   4339     case DW_FORM_block1:
   4340     case DW_FORM_block:;
   4341       Dwarf_Block block;
   4342       if (unlikely (dwarf_formblock (attrp, &block) != 0))
   4343 	goto attrval_out;
   4344 
   4345       printf ("           %*s%-20s %" PRIxMAX " byte block\n",
   4346 	      (int) (level * 2), "", dwarf_attr_string (attr),
   4347 	      (uintmax_t) block.length);
   4348 
   4349       switch (attr)
   4350 	{
   4351 	case DW_AT_location:
   4352 	case DW_AT_data_location:
   4353 	case DW_AT_data_member_location:
   4354 	case DW_AT_vtable_elem_location:
   4355 	case DW_AT_string_length:
   4356 	case DW_AT_use_location:
   4357 	case DW_AT_frame_base:
   4358 	case DW_AT_return_addr:
   4359 	case DW_AT_static_link:
   4360 	case DW_AT_allocated:
   4361 	case DW_AT_associated:
   4362 	case DW_AT_bit_size:
   4363 	case DW_AT_bit_offset:
   4364 	case DW_AT_bit_stride:
   4365 	case DW_AT_byte_size:
   4366 	case DW_AT_byte_stride:
   4367 	case DW_AT_count:
   4368 	case DW_AT_lower_bound:
   4369 	case DW_AT_upper_bound:
   4370 	  print_ops (cbargs->dwflmod, cbargs->dbg,
   4371 		     12 + level * 2, 12 + level * 2,
   4372 		     cbargs->addrsize, block.length, block.data);
   4373 	  break;
   4374 	}
   4375       break;
   4376 
   4377     default:
   4378       printf ("           %*s%-20s [form: %d] ???\n",
   4379 	      (int) (level * 2), "", dwarf_attr_string (attr),
   4380 	      (int) form);
   4381       break;
   4382     }
   4383 
   4384   return DWARF_CB_OK;
   4385 }
   4386 
   4387 
   4388 static void
   4389 print_debug_info_section (Dwfl_Module *dwflmod,
   4390 			  Ebl *ebl __attribute__ ((unused)),
   4391 			  GElf_Ehdr *ehdr __attribute__ ((unused)),
   4392 			  Elf_Scn *scn __attribute__ ((unused)),
   4393 			  GElf_Shdr *shdr, Dwarf *dbg)
   4394 {
   4395   printf (gettext ("\
   4396 \nDWARF section '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
   4397 	  ".debug_info", (uint64_t) shdr->sh_offset);
   4398 
   4399   /* If the section is empty we don't have to do anything.  */
   4400   if (shdr->sh_size == 0)
   4401     return;
   4402 
   4403   int maxdies = 20;
   4404   Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
   4405 
   4406   Dwarf_Off offset = 0;
   4407 
   4408   /* New compilation unit.  */
   4409   size_t cuhl;
   4410   //Dwarf_Half version;
   4411   Dwarf_Off abbroffset;
   4412   uint8_t addrsize;
   4413   uint8_t offsize;
   4414   Dwarf_Off nextcu;
   4415  next_cu:
   4416   if (dwarf_nextcu (dbg, offset, &nextcu, &cuhl, &abbroffset, &addrsize,
   4417 		    &offsize) != 0)
   4418     goto do_return;
   4419 
   4420   printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
   4421 		   " Version: %" PRIu16 ", Abbreviation section offset: %"
   4422 		   PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8 "\n"),
   4423 	  (uint64_t) offset, /*version*/2, abbroffset, addrsize, offsize);
   4424 
   4425 
   4426   struct attrcb_args args;
   4427   args.dwflmod = dwflmod;
   4428   args.dbg = dbg;
   4429   args.addrsize = addrsize;
   4430   args.cu_offset = offset;
   4431 
   4432   offset += cuhl;
   4433 
   4434   int level = 0;
   4435 
   4436   if (unlikely (dwarf_offdie (dbg, offset, &dies[level]) == NULL))
   4437     {
   4438       error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
   4439 			    " in section '%s': %s"),
   4440 	     (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
   4441       goto do_return;
   4442     }
   4443 
   4444   do
   4445     {
   4446       offset = dwarf_dieoffset (&dies[level]);
   4447       if (unlikely (offset == ~0ul))
   4448 	{
   4449 	  error (0, 0, gettext ("cannot get DIE offset: %s"),
   4450 		 dwarf_errmsg (-1));
   4451 	  goto do_return;
   4452 	}
   4453 
   4454       int tag = dwarf_tag (&dies[level]);
   4455       if (unlikely (tag == DW_TAG_invalid))
   4456 	{
   4457 	  error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
   4458 				" in section '%s': %s"),
   4459 		 (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
   4460 	  goto do_return;
   4461 	}
   4462 
   4463       printf (" [%6" PRIx64 "]  %*s%s\n",
   4464 	      (uint64_t) offset, (int) (level * 2), "",
   4465 	      dwarf_tag_string (tag));
   4466 
   4467       /* Print the attribute values.  */
   4468       args.level = level;
   4469       (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
   4470 
   4471       /* Make room for the next level's DIE.  */
   4472       if (level + 1 == maxdies)
   4473 	dies = (Dwarf_Die *) xrealloc (dies,
   4474 				       (maxdies += 10)
   4475 				       * sizeof (Dwarf_Die));
   4476 
   4477       int res = dwarf_child (&dies[level], &dies[level + 1]);
   4478       if (res > 0)
   4479 	{
   4480 	  while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
   4481 	    if (level-- == 0)
   4482 	      break;
   4483 
   4484 	  if (unlikely (res == -1))
   4485 	    {
   4486 	      error (0, 0, gettext ("cannot get next DIE: %s\n"),
   4487 		     dwarf_errmsg (-1));
   4488 	      goto do_return;
   4489 	    }
   4490 	}
   4491       else if (unlikely (res < 0))
   4492 	{
   4493 	  error (0, 0, gettext ("cannot get next DIE: %s"),
   4494 		 dwarf_errmsg (-1));
   4495 	  goto do_return;
   4496 	}
   4497       else
   4498 	++level;
   4499     }
   4500   while (level >= 0);
   4501 
   4502   offset = nextcu;
   4503   if (offset != 0)
   4504      goto next_cu;
   4505 
   4506  do_return:
   4507   free (dies);
   4508 }
   4509 
   4510 
   4511 static void
   4512 print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
   4513 			  GElf_Ehdr *ehdr __attribute__ ((unused)),
   4514 			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   4515 {
   4516   printf (gettext ("\
   4517 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
   4518 	  ".debug_line", (uint64_t) shdr->sh_offset);
   4519 
   4520   if (shdr->sh_size == 0)
   4521     return;
   4522 
   4523   /* There is no functionality in libdw to read the information in the
   4524      way it is represented here.  Hardcode the decoder.  */
   4525   Elf_Data *data = elf_getdata (scn, NULL);
   4526   if (unlikely (data == NULL || data->d_buf == NULL))
   4527     {
   4528       error (0, 0, gettext ("cannot get line data section data: %s"),
   4529 	     elf_errmsg (-1));
   4530       return;
   4531     }
   4532 
   4533   const unsigned char *linep = (const unsigned char *) data->d_buf;
   4534   const unsigned char *lineendp;
   4535 
   4536   while (linep
   4537 	 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
   4538     {
   4539       size_t start_offset = linep - (const unsigned char *) data->d_buf;
   4540 
   4541       printf (gettext ("\nTable at offset %Zu:\n"), start_offset);
   4542 
   4543       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
   4544       unsigned int length = 4;
   4545       if (unlikely (unit_length == 0xffffffff))
   4546 	{
   4547 	  if (unlikely (linep + 8 > lineendp))
   4548 	    {
   4549 	    invalid_data:
   4550 	      error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
   4551 		     elf_ndxscn (scn), ".debug_line");
   4552 	      return;
   4553 	    }
   4554 	  unit_length = read_8ubyte_unaligned_inc (dbg, linep);
   4555 	  length = 8;
   4556 	}
   4557 
   4558       /* Check whether we have enough room in the section.  */
   4559       if (unit_length < 2 + length + 5 * 1
   4560 	  || unlikely (linep + unit_length > lineendp))
   4561 	goto invalid_data;
   4562       lineendp = linep + unit_length;
   4563 
   4564       /* The next element of the header is the version identifier.  */
   4565       uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
   4566 
   4567       /* Next comes the header length.  */
   4568       Dwarf_Word header_length;
   4569       if (length == 4)
   4570 	header_length = read_4ubyte_unaligned_inc (dbg, linep);
   4571       else
   4572 	header_length = read_8ubyte_unaligned_inc (dbg, linep);
   4573       //const unsigned char *header_start = linep;
   4574 
   4575       /* Next the minimum instruction length.  */
   4576       uint_fast8_t minimum_instr_len = *linep++;
   4577 
   4578         /* Then the flag determining the default value of the is_stmt
   4579 	   register.  */
   4580       uint_fast8_t default_is_stmt = *linep++;
   4581 
   4582       /* Now the line base.  */
   4583       int_fast8_t line_base = *((const int_fast8_t *) linep);
   4584       ++linep;
   4585 
   4586       /* And the line range.  */
   4587       uint_fast8_t line_range = *linep++;
   4588 
   4589       /* The opcode base.  */
   4590       uint_fast8_t opcode_base = *linep++;
   4591 
   4592       /* Print what we got so far.  */
   4593       printf (gettext ("\n"
   4594 		       " Length:                     %" PRIu64 "\n"
   4595 		       " DWARF version:              %" PRIuFAST16 "\n"
   4596 		       " Prologue length:            %" PRIu64 "\n"
   4597 		       " Minimum instruction length: %" PRIuFAST8 "\n"
   4598 		       " Initial value if '%s': %" PRIuFAST8 "\n"
   4599 		       " Line base:                  %" PRIdFAST8 "\n"
   4600 		       " Line range:                 %" PRIuFAST8 "\n"
   4601 		       " Opcode base:                %" PRIuFAST8 "\n"
   4602 		       "\n"
   4603 		       "Opcodes:\n"),
   4604 	      (uint64_t) unit_length, version, (uint64_t) header_length,
   4605 	      minimum_instr_len, "is_stmt", default_is_stmt, line_base,
   4606 	      line_range, opcode_base);
   4607 
   4608       if (unlikely (linep + opcode_base - 1 >= lineendp))
   4609 	{
   4610 	invalid_unit:
   4611 	  error (0, 0,
   4612 		 gettext ("invalid data at offset %tu in section [%zu] '%s'"),
   4613 		 linep - (const unsigned char *) data->d_buf,
   4614 		 elf_ndxscn (scn), ".debug_line");
   4615 	  linep = lineendp;
   4616 	  continue;
   4617 	}
   4618       int opcode_base_l10 = 1;
   4619       unsigned int tmp = opcode_base;
   4620       while (tmp > 10)
   4621 	{
   4622 	  tmp /= 10;
   4623 	  ++opcode_base_l10;
   4624 	}
   4625       const uint8_t *standard_opcode_lengths = linep - 1;
   4626       for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
   4627 	printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
   4628 			  "  [%*" PRIuFAST8 "]  %hhu arguments\n",
   4629 			  (int) linep[cnt - 1]),
   4630 		opcode_base_l10, cnt, linep[cnt - 1]);
   4631       linep += opcode_base - 1;
   4632       if (unlikely (linep >= lineendp))
   4633 	goto invalid_unit;
   4634 
   4635       puts (gettext ("\nDirectory table:"));
   4636       while (*linep != 0)
   4637 	{
   4638 	  unsigned char *endp = memchr (linep, '\0', lineendp - linep);
   4639 	  if (unlikely (endp == NULL))
   4640 	    goto invalid_unit;
   4641 
   4642 	  printf (" %s\n", (char *) linep);
   4643 
   4644 	  linep = endp + 1;
   4645 	}
   4646       /* Skip the final NUL byte.  */
   4647       ++linep;
   4648 
   4649       if (unlikely (linep >= lineendp))
   4650 	goto invalid_unit;
   4651       puts (gettext ("\nFile name table:\n"
   4652 		     " Entry Dir   Time      Size      Name"));
   4653       for (unsigned int cnt = 1; *linep != 0; ++cnt)
   4654 	{
   4655 	  /* First comes the file name.  */
   4656 	  char *fname = (char *) linep;
   4657 	  unsigned char *endp = memchr (fname, '\0', lineendp - linep);
   4658 	  if (unlikely (endp == NULL))
   4659 	    goto invalid_unit;
   4660 	  linep = endp + 1;
   4661 
   4662 	  /* Then the index.  */
   4663 	  unsigned int diridx;
   4664 	  get_uleb128 (diridx, linep);
   4665 
   4666 	  /* Next comes the modification time.  */
   4667 	  unsigned int mtime;
   4668 	  get_uleb128 (mtime, linep);
   4669 
   4670 	  /* Finally the length of the file.  */
   4671 	  unsigned int fsize;
   4672 	  get_uleb128 (fsize, linep);
   4673 
   4674 	  printf (" %-5u %-5u %-9u %-9u %s\n",
   4675 		  cnt, diridx, mtime, fsize, fname);
   4676 	}
   4677       /* Skip the final NUL byte.  */
   4678       ++linep;
   4679 
   4680       puts (gettext ("\nLine number statements:"));
   4681       Dwarf_Word address = 0;
   4682       size_t line = 1;
   4683       uint_fast8_t is_stmt = default_is_stmt;
   4684 
   4685       /* Default address value, in case we do not find the CU.  */
   4686       size_t address_size
   4687 	= elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
   4688 
   4689       /* Determine the CU this block is for.  */
   4690       Dwarf_Off cuoffset;
   4691       Dwarf_Off ncuoffset = 0;
   4692       size_t hsize;
   4693       while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
   4694 			   NULL, NULL, NULL) == 0)
   4695 	{
   4696 	  Dwarf_Die cudie;
   4697 	  if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
   4698 	    continue;
   4699 	  Dwarf_Attribute stmt_list;
   4700 	  if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
   4701 	    continue;
   4702 	  Dwarf_Word lineoff;
   4703 	  if (dwarf_formudata (&stmt_list, &lineoff) != 0)
   4704 	    continue;
   4705 	  if (lineoff == start_offset)
   4706 	    {
   4707 	      /* Found the CU.  */
   4708 	      address_size = cudie.cu->address_size;
   4709 	      break;
   4710 	    }
   4711 	}
   4712 
   4713       while (linep < lineendp)
   4714 	{
   4715 	  unsigned int u128;
   4716 	  int s128;
   4717 
   4718 	  /* Read the opcode.  */
   4719 	  unsigned int opcode = *linep++;
   4720 
   4721 	  /* Is this a special opcode?  */
   4722 	  if (likely (opcode >= opcode_base))
   4723 	    {
   4724 	      /* Yes.  Handling this is quite easy since the opcode value
   4725 		 is computed with
   4726 
   4727 		 opcode = (desired line increment - line_base)
   4728 		           + (line_range * address advance) + opcode_base
   4729 	      */
   4730 	      int line_increment = (line_base
   4731 				    + (opcode - opcode_base) % line_range);
   4732 	      unsigned int address_increment = (minimum_instr_len
   4733 						* ((opcode - opcode_base)
   4734 						   / line_range));
   4735 
   4736 	      /* Perform the increments.  */
   4737 	      line += line_increment;
   4738 	      address += address_increment;
   4739 
   4740 	      char *a = format_dwarf_addr (dwflmod, 0, address);
   4741 	      printf (gettext ("\
   4742  special opcode %u: address+%u = %s, line%+d = %zu\n"),
   4743 		      opcode, address_increment, a, line_increment, line);
   4744 	      free (a);
   4745 	    }
   4746 	  else if (opcode == 0)
   4747 	    {
   4748 	      /* This an extended opcode.  */
   4749 	      if (unlikely (linep + 2 > lineendp))
   4750 		goto invalid_unit;
   4751 
   4752 	      /* The length.  */
   4753 	      unsigned int len = *linep++;
   4754 
   4755 	      if (unlikely (linep + len > lineendp))
   4756 		goto invalid_unit;
   4757 
   4758 	      /* The sub-opcode.  */
   4759 	      opcode = *linep++;
   4760 
   4761 	      printf (gettext (" extended opcode %u: "), opcode);
   4762 
   4763 	      switch (opcode)
   4764 		{
   4765 		case DW_LNE_end_sequence:
   4766 		  puts (gettext ("end of sequence"));
   4767 
   4768 		  /* Reset the registers we care about.  */
   4769 		  address = 0;
   4770 		  line = 1;
   4771 		  is_stmt = default_is_stmt;
   4772 		  break;
   4773 
   4774 		case DW_LNE_set_address:
   4775 		  if (address_size == 4)
   4776 		    address = read_4ubyte_unaligned_inc (dbg, linep);
   4777 		  else
   4778 		    address = read_8ubyte_unaligned_inc (dbg, linep);
   4779 		  {
   4780 		    char *a = format_dwarf_addr (dwflmod, 0, address);
   4781 		    printf (gettext ("set address to %s\n"), a);
   4782 		    free (a);
   4783 		  }
   4784 		  break;
   4785 
   4786 		case DW_LNE_define_file:
   4787 		  {
   4788 		    char *fname = (char *) linep;
   4789 		    unsigned char *endp = memchr (linep, '\0',
   4790 						  lineendp - linep);
   4791 		    if (unlikely (endp == NULL))
   4792 		      goto invalid_unit;
   4793 		    linep = endp + 1;
   4794 
   4795 		    unsigned int diridx;
   4796 		    get_uleb128 (diridx, linep);
   4797 		    Dwarf_Word mtime;
   4798 		    get_uleb128 (mtime, linep);
   4799 		    Dwarf_Word filelength;
   4800 		    get_uleb128 (filelength, linep);
   4801 
   4802 		    printf (gettext ("\
   4803 define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
   4804 			    diridx, (uint64_t) mtime, (uint64_t) filelength,
   4805 			    fname);
   4806 		  }
   4807 		  break;
   4808 
   4809 		default:
   4810 		  /* Unknown, ignore it.  */
   4811 		  puts (gettext ("unknown opcode"));
   4812 		  linep += len - 1;
   4813 		  break;
   4814 		}
   4815 	    }
   4816 	  else if (opcode <= DW_LNS_set_epilogue_begin)
   4817 	    {
   4818 	      /* This is a known standard opcode.  */
   4819 	      switch (opcode)
   4820 		{
   4821 		case DW_LNS_copy:
   4822 		  /* Takes no argument.  */
   4823 		  puts (gettext (" copy"));
   4824 		  break;
   4825 
   4826 		case DW_LNS_advance_pc:
   4827 		  /* Takes one uleb128 parameter which is added to the
   4828 		     address.  */
   4829 		  get_uleb128 (u128, linep);
   4830 		  address += minimum_instr_len * u128;
   4831 		  {
   4832 		    char *a = format_dwarf_addr (dwflmod, 0, address);
   4833 		    printf (gettext ("advance address by %u to %s\n"),
   4834 			    u128, a);
   4835 		    free (a);
   4836 		  }
   4837 		  break;
   4838 
   4839 		case DW_LNS_advance_line:
   4840 		  /* Takes one sleb128 parameter which is added to the
   4841 		     line.  */
   4842 		  get_sleb128 (s128, linep);
   4843 		  line += s128;
   4844 		  printf (gettext ("\
   4845  advance line by constant %d to %" PRId64 "\n"),
   4846 			  s128, (int64_t) line);
   4847 		  break;
   4848 
   4849 		case DW_LNS_set_file:
   4850 		  /* Takes one uleb128 parameter which is stored in file.  */
   4851 		  get_uleb128 (u128, linep);
   4852 		  printf (gettext (" set file to %" PRIu64 "\n"),
   4853 			  (uint64_t) u128);
   4854 		  break;
   4855 
   4856 		case DW_LNS_set_column:
   4857 		  /* Takes one uleb128 parameter which is stored in column.  */
   4858 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
   4859 		    goto invalid_unit;
   4860 
   4861 		  get_uleb128 (u128, linep);
   4862 		  printf (gettext (" set column to %" PRIu64 "\n"),
   4863 			  (uint64_t) u128);
   4864 		  break;
   4865 
   4866 		case DW_LNS_negate_stmt:
   4867 		  /* Takes no argument.  */
   4868 		  is_stmt = 1 - is_stmt;
   4869 		  printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
   4870 			  "is_stmt", is_stmt);
   4871 		  break;
   4872 
   4873 		case DW_LNS_set_basic_block:
   4874 		  /* Takes no argument.  */
   4875 		  puts (gettext (" set basic block flag"));
   4876 		  break;
   4877 
   4878 		case DW_LNS_const_add_pc:
   4879 		  /* Takes no argument.  */
   4880 		  u128 = (minimum_instr_len
   4881 			  * ((255 - opcode_base) / line_range));
   4882 		  address += u128;
   4883 		  {
   4884 		    char *a = format_dwarf_addr (dwflmod, 0, address);
   4885 		    printf (gettext ("advance address by constant %u to %s\n"),
   4886 			    u128, a);
   4887 		    free (a);
   4888 		  }
   4889 		  break;
   4890 
   4891 		case DW_LNS_fixed_advance_pc:
   4892 		  /* Takes one 16 bit parameter which is added to the
   4893 		     address.  */
   4894 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
   4895 		    goto invalid_unit;
   4896 
   4897 		  u128 = read_2ubyte_unaligned_inc (dbg, linep);
   4898 		  address += u128;
   4899 		  {
   4900 		    char *a = format_dwarf_addr (dwflmod, 0, address);
   4901 		    printf (gettext ("\
   4902 advance address by fixed value %u to %s\n"),
   4903 			    u128, a);
   4904 		    free (a);
   4905 		  }
   4906 		  break;
   4907 
   4908 		case DW_LNS_set_prologue_end:
   4909 		  /* Takes no argument.  */
   4910 		  puts (gettext (" set prologue end flag"));
   4911 		  break;
   4912 
   4913 		case DW_LNS_set_epilogue_begin:
   4914 		  /* Takes no argument.  */
   4915 		  puts (gettext (" set epilogue begin flag"));
   4916 		  break;
   4917 		}
   4918 	    }
   4919 	  else
   4920 	    {
   4921 	      /* This is a new opcode the generator but not we know about.
   4922 		 Read the parameters associated with it but then discard
   4923 		 everything.  Read all the parameters for this opcode.  */
   4924 	      printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
   4925 				" unknown opcode with %" PRIu8 " parameters:",
   4926 				standard_opcode_lengths[opcode]),
   4927 		      standard_opcode_lengths[opcode]);
   4928 	      for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
   4929 		{
   4930 		  get_uleb128 (u128, linep);
   4931 		  if (n != standard_opcode_lengths[opcode])
   4932 		    putc_unlocked (',', stdout);
   4933 		  printf (" %u", u128);
   4934 		}
   4935 
   4936 	      /* Next round, ignore this opcode.  */
   4937 	      continue;
   4938 	    }
   4939 	}
   4940     }
   4941 
   4942   /* There must only be one data block.  */
   4943   assert (elf_getdata (scn, data) == NULL);
   4944 }
   4945 
   4946 
   4947 static void
   4948 print_debug_loc_section (Dwfl_Module *dwflmod,
   4949 			 Ebl *ebl __attribute__ ((unused)),
   4950 			 GElf_Ehdr *ehdr __attribute__ ((unused)),
   4951 			 Elf_Scn *scn __attribute__ ((unused)),
   4952 			 GElf_Shdr *shdr,
   4953 			 Dwarf *dbg __attribute__ ((unused)))
   4954 {
   4955   Elf_Data *data = elf_rawdata (scn, NULL);
   4956 
   4957   if (unlikely (data == NULL))
   4958     {
   4959       error (0, 0, gettext ("cannot get .debug_loc content: %s"),
   4960 	     elf_errmsg (-1));
   4961       return;
   4962     }
   4963 
   4964   printf (gettext ("\
   4965 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
   4966 	  ".debug_loc", (uint64_t) shdr->sh_offset);
   4967 
   4968   size_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
   4969 
   4970   bool first = true;
   4971   unsigned char *readp = data->d_buf;
   4972   while (readp < (unsigned char *) data->d_buf + data->d_size)
   4973     {
   4974       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
   4975 
   4976       if (unlikely (data->d_size - offset < address_size * 2))
   4977 	{
   4978 	  printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
   4979 	  break;
   4980 	}
   4981 
   4982       Dwarf_Addr begin;
   4983       Dwarf_Addr end;
   4984       if (address_size == 8)
   4985 	{
   4986 	  begin = read_8ubyte_unaligned_inc (dbg, readp);
   4987 	  end = read_8ubyte_unaligned_inc (dbg, readp);
   4988 	}
   4989       else
   4990 	{
   4991 	  begin = read_4ubyte_unaligned_inc (dbg, readp);
   4992 	  end = read_4ubyte_unaligned_inc (dbg, readp);
   4993 	  if (begin == (Dwarf_Addr) (uint32_t) -1)
   4994 	    begin = (Dwarf_Addr) -1l;
   4995 	}
   4996 
   4997       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
   4998 	{
   4999 	  char *b = format_dwarf_addr (dwflmod, address_size, end);
   5000 	  printf (gettext (" [%6tx]  base address %s\n"), offset, b);
   5001 	  free (b);
   5002 	}
   5003       else if (begin == 0 && end == 0) /* End of list entry.  */
   5004 	first = true;
   5005       else
   5006 	{
   5007 	  /* We have a location expression entry.  */
   5008 	  uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
   5009 
   5010 	  char *b = format_dwarf_addr (dwflmod, address_size, begin);
   5011 	  char *e = format_dwarf_addr (dwflmod, address_size, end);
   5012 
   5013 	  if (first)		/* First entry in a list.  */
   5014 	    printf (gettext (" [%6tx]  %s..%s"), offset, b, e);
   5015 	  else
   5016 	    printf (gettext ("           %s..%s"), b, e);
   5017 
   5018 	  free (b);
   5019 	  free (e);
   5020 
   5021 	  print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
   5022 		     address_size, len, readp);
   5023 
   5024 	  first = false;
   5025 	  readp += len;
   5026 	}
   5027     }
   5028 }
   5029 
   5030 struct mac_culist
   5031 {
   5032   Dwarf_Die die;
   5033   Dwarf_Off offset;
   5034   Dwarf_Files *files;
   5035   struct mac_culist *next;
   5036 };
   5037 
   5038 
   5039 static int
   5040 mac_compare (const void *p1, const void *p2)
   5041 {
   5042   struct mac_culist *m1 = (struct mac_culist *) p1;
   5043   struct mac_culist *m2 = (struct mac_culist *) p2;
   5044 
   5045   if (m1->offset < m2->offset)
   5046     return -1;
   5047   if (m1->offset > m2->offset)
   5048     return 1;
   5049   return 0;
   5050 }
   5051 
   5052 
   5053 static void
   5054 print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   5055 			     Ebl *ebl __attribute__ ((unused)),
   5056 			     GElf_Ehdr *ehdr __attribute__ ((unused)),
   5057 			     Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   5058 {
   5059   printf (gettext ("\
   5060 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
   5061 	  ".debug_macinfo", (uint64_t) shdr->sh_offset);
   5062   putc_unlocked ('\n', stdout);
   5063 
   5064   /* There is no function in libdw to iterate over the raw content of
   5065      the section but it is easy enough to do.  */
   5066   Elf_Data *data = elf_getdata (scn, NULL);
   5067   if (unlikely (data == NULL || data->d_buf == NULL))
   5068     {
   5069       error (0, 0, gettext ("cannot get macro information section data: %s"),
   5070 	     elf_errmsg (-1));
   5071       return;
   5072     }
   5073 
   5074   /* Get the source file information for all CUs.  */
   5075   Dwarf_Off offset;
   5076   Dwarf_Off ncu = 0;
   5077   size_t hsize;
   5078   struct mac_culist *culist = NULL;
   5079   size_t nculist = 0;
   5080   while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
   5081     {
   5082       Dwarf_Die cudie;
   5083       if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
   5084 	continue;
   5085 
   5086       Dwarf_Attribute attr;
   5087       if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
   5088 	continue;
   5089 
   5090       Dwarf_Word macoff;
   5091       if (dwarf_formudata (&attr, &macoff) != 0)
   5092 	continue;
   5093 
   5094       struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
   5095       newp->die = cudie;
   5096       newp->offset = macoff;
   5097       newp->files = NULL;
   5098       newp->next = culist;
   5099       culist = newp;
   5100       ++nculist;
   5101     }
   5102 
   5103   /* Convert the list into an array for easier consumption.  */
   5104   struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
   5105 							 * sizeof (*cus));
   5106   /* Add sentinel.  */
   5107   cus[nculist].offset = data->d_size;
   5108   if (nculist > 0)
   5109     {
   5110       for (size_t cnt = nculist - 1; culist != NULL; --cnt)
   5111 	{
   5112 	  assert (cnt < nculist);
   5113 	  cus[cnt] = *culist;
   5114 	  culist = culist->next;
   5115 	}
   5116 
   5117       /* Sort the array according to the offset in the .debug_macinfo
   5118 	 section.  Note we keep the sentinel at the end.  */
   5119       qsort (cus, nculist, sizeof (*cus), mac_compare);
   5120     }
   5121 
   5122   const unsigned char *readp = (const unsigned char *) data->d_buf;
   5123   const unsigned char *readendp = readp + data->d_size;
   5124   int level = 1;
   5125 
   5126   while (readp < readendp)
   5127     {
   5128       unsigned int opcode = *readp++;
   5129       unsigned int u128;
   5130       unsigned int u128_2;
   5131       const unsigned char *endp;
   5132 
   5133       switch (opcode)
   5134 	{
   5135 	case DW_MACINFO_define:
   5136 	case DW_MACINFO_undef:
   5137 	case DW_MACINFO_vendor_ext:
   5138 	  /*  For the first two opcodes the parameters are
   5139 	        line, string
   5140 	      For the latter
   5141 	        number, string.
   5142 	      We can treat these cases together.  */
   5143 	  get_uleb128 (u128, readp);
   5144 
   5145 	  endp = memchr (readp, '\0', readendp - readp);
   5146 	  if (unlikely (endp == NULL))
   5147 	    {
   5148 	      printf (gettext ("\
   5149 %*s*** non-terminated string at end of section"),
   5150 		      level, "");
   5151 	      return;
   5152 	    }
   5153 
   5154 	  if (opcode == DW_MACINFO_define)
   5155 	    printf ("%*s#define %s, line %u\n",
   5156 		    level, "", (char *) readp, u128);
   5157 	  else if (opcode == DW_MACINFO_undef)
   5158 	    printf ("%*s#undef %s, line %u\n",
   5159 		    level, "", (char *) readp, u128);
   5160 	  else
   5161 	    printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
   5162 
   5163 	  readp = endp + 1;
   5164 	  break;
   5165 
   5166 	case DW_MACINFO_start_file:
   5167 	  /* The two parameters are line and file index, in this order.  */
   5168 	  get_uleb128 (u128, readp);
   5169 	  get_uleb128 (u128_2, readp);
   5170 
   5171 	  /* Find the CU DIE for this file.  */
   5172 	  size_t macoff = readp - (const unsigned char *) data->d_buf;
   5173 	  const char *fname = "???";
   5174 	  if (macoff >= cus[0].offset)
   5175 	    {
   5176 	      while (macoff >= cus[1].offset)
   5177 		++cus;
   5178 
   5179 	      if (cus[0].files == NULL
   5180 		&& dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
   5181 		cus[0].files = (Dwarf_Files *) -1l;
   5182 
   5183 	      if (cus[0].files != (Dwarf_Files *) -1l)
   5184 		fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
   5185 			 ?: "???");
   5186 	    }
   5187 
   5188 	  printf ("%*sstart_file %u, [%u] %s\n",
   5189 		  level, "", u128, u128_2, fname);
   5190 	  ++level;
   5191 	  break;
   5192 
   5193 	case DW_MACINFO_end_file:
   5194 	  --level;
   5195 	  printf ("%*send_file\n", level, "");
   5196 	  /* Nothing more to do.  */
   5197 	  break;
   5198 
   5199 	default:
   5200 	  // XXX gcc seems to generate files with a trailing zero.
   5201 	  if (unlikely (opcode != 0 || readp != readendp))
   5202 	    printf ("%*s*** invalid opcode %u\n", level, "", opcode);
   5203 	  break;
   5204 	}
   5205     }
   5206 }
   5207 
   5208 
   5209 /* Callback for printing global names.  */
   5210 static int
   5211 print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
   5212 		void *arg)
   5213 {
   5214   int *np = (int *) arg;
   5215 
   5216   printf (gettext (" [%5d] DIE offset: %6" PRId64
   5217 		   ", CU DIE offset: %6" PRId64 ", name: %s\n"),
   5218 	  (*np)++, global->die_offset, global->cu_offset, global->name);
   5219 
   5220   return 0;
   5221 }
   5222 
   5223 
   5224 /* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
   5225 static void
   5226 print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   5227 			      Ebl *ebl __attribute__ ((unused)),
   5228 			      GElf_Ehdr *ehdr __attribute__ ((unused)),
   5229 			      Elf_Scn *scn __attribute__ ((unused)),
   5230 			      GElf_Shdr *shdr, Dwarf *dbg)
   5231 {
   5232   printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
   5233 	  ".debug_pubnames", (uint64_t) shdr->sh_offset);
   5234 
   5235   int n = 0;
   5236   (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
   5237 }
   5238 
   5239 /* Print the content of the DWARF string section '.debug_str'.  */
   5240 static void
   5241 print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   5242 			 Ebl *ebl __attribute__ ((unused)),
   5243 			 GElf_Ehdr *ehdr __attribute__ ((unused)),
   5244 			 Elf_Scn *scn __attribute__ ((unused)),
   5245 			 GElf_Shdr *shdr, Dwarf *dbg)
   5246 {
   5247   /* Compute floor(log16(shdr->sh_size)).  */
   5248   GElf_Addr tmp = shdr->sh_size;
   5249   int digits = 1;
   5250   while (tmp >= 16)
   5251     {
   5252       ++digits;
   5253       tmp >>= 4;
   5254     }
   5255   digits = MAX (4, digits);
   5256 
   5257   printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
   5258 		   " %*s  String\n"),
   5259 	  ".debug_str", (uint64_t) shdr->sh_offset,
   5260 	  /* TRANS: the debugstr| prefix makes the string unique.  */
   5261 	  digits + 2, sgettext ("debugstr|Offset"));
   5262 
   5263   Dwarf_Off offset = 0;
   5264   while (offset < shdr->sh_size)
   5265     {
   5266       size_t len;
   5267       const char *str = dwarf_getstring (dbg, offset, &len);
   5268       if (unlikely (str == NULL))
   5269 	{
   5270 	  printf (gettext (" *** error while reading strings: %s\n"),
   5271 		  dwarf_errmsg (-1));
   5272 	  break;
   5273 	}
   5274 
   5275       printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
   5276 
   5277       offset += len + 1;
   5278     }
   5279 }
   5280 
   5281 static void
   5282 print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
   5283 {
   5284   /* Before we start the real work get a debug context descriptor.  */
   5285   Dwarf_Addr dwbias;
   5286   Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
   5287   if (dbg == NULL)
   5288     {
   5289       error (0, 0, gettext ("cannot get debug context descriptor: %s"),
   5290 	     dwfl_errmsg (-1));
   5291       return;
   5292     }
   5293 
   5294   /* Get the section header string table index.  */
   5295   size_t shstrndx;
   5296   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
   5297     error (EXIT_FAILURE, 0,
   5298 	   gettext ("cannot get section header string table index"));
   5299 
   5300   /* Look through all the sections for the debugging sections to print.  */
   5301   Elf_Scn *scn = NULL;
   5302   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   5303     {
   5304       GElf_Shdr shdr_mem;
   5305       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   5306 
   5307       if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
   5308 	{
   5309 	  static const struct
   5310 	  {
   5311 	    const char *name;
   5312 	    enum section_e bitmask;
   5313 	    void (*fp) (Dwfl_Module *, Ebl *,
   5314 			GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
   5315 	  } debug_sections[] =
   5316 	    {
   5317 #define NEW_SECTION(name) \
   5318 	      { ".debug_" #name, section_##name, print_debug_##name##_section }
   5319 	      NEW_SECTION (abbrev),
   5320 	      NEW_SECTION (aranges),
   5321 	      NEW_SECTION (frame),
   5322 	      NEW_SECTION (info),
   5323 	      NEW_SECTION (line),
   5324 	      NEW_SECTION (loc),
   5325 	      NEW_SECTION (pubnames),
   5326 	      NEW_SECTION (str),
   5327 	      NEW_SECTION (macinfo),
   5328 	      NEW_SECTION (ranges),
   5329 	      { ".eh_frame", section_frame, print_debug_frame_section }
   5330 	    };
   5331 	  const int ndebug_sections = (sizeof (debug_sections)
   5332 				       / sizeof (debug_sections[0]));
   5333 	  const char *name = elf_strptr (ebl->elf, shstrndx,
   5334 					 shdr->sh_name);
   5335 	  int n;
   5336 
   5337 	  for (n = 0; n < ndebug_sections; ++n)
   5338 	    if (strcmp (name, debug_sections[n].name) == 0)
   5339 	      {
   5340 		if (print_debug_sections & debug_sections[n].bitmask)
   5341 		  debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
   5342 		break;
   5343 	      }
   5344 	}
   5345     }
   5346 }
   5347 
   5348 
   5349 #define ITEM_INDENT		4
   5350 #define ITEM_WRAP_COLUMN	150
   5351 #define REGISTER_WRAP_COLUMN	75
   5352 
   5353 /* Print "NAME: FORMAT", wrapping when FORMAT_MAX chars of FORMAT would
   5354    make the line exceed ITEM_WRAP_COLUMN.  Unpadded numbers look better
   5355    for the core items.  But we do not want the line breaks to depend on
   5356    the particular values.  */
   5357 static unsigned int
   5358 __attribute__ ((format (printf, 7, 8)))
   5359 print_core_item (unsigned int colno, char sep, unsigned int wrap,
   5360 		 size_t name_width, const char *name,
   5361 		 size_t format_max, const char *format, ...)
   5362 {
   5363   size_t len = strlen (name);
   5364   if (name_width < len)
   5365     name_width = len;
   5366 
   5367   size_t n = name_width + sizeof ": " - 1 + format_max;
   5368 
   5369   if (colno == 0)
   5370     {
   5371       printf ("%*s", ITEM_INDENT, "");
   5372       colno = ITEM_INDENT + n;
   5373     }
   5374   else if (colno + 2 + n < wrap)
   5375     {
   5376       printf ("%c ", sep);
   5377       colno += 2 + n;
   5378     }
   5379   else
   5380     {
   5381       printf ("\n%*s", ITEM_INDENT, "");
   5382       colno = ITEM_INDENT + n;
   5383     }
   5384 
   5385   printf ("%s: %*s", name, (int) (name_width - len), "");
   5386 
   5387   va_list ap;
   5388   va_start (ap, format);
   5389   vprintf (format, ap);
   5390   va_end (ap);
   5391 
   5392   return colno;
   5393 }
   5394 
   5395 static const void *
   5396 convert (Elf *core, Elf_Type type, uint_fast16_t count,
   5397 	 void *value, const void *data, size_t size)
   5398 {
   5399   Elf_Data valuedata =
   5400     {
   5401       .d_type = type,
   5402       .d_buf = value,
   5403       .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
   5404       .d_version = EV_CURRENT,
   5405     };
   5406   Elf_Data indata =
   5407     {
   5408       .d_type = type,
   5409       .d_buf = (void *) data,
   5410       .d_size = valuedata.d_size,
   5411       .d_version = EV_CURRENT,
   5412     };
   5413 
   5414   Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
   5415 		 ? elf32_xlatetom : elf64_xlatetom)
   5416     (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
   5417   if (d == NULL)
   5418     error (EXIT_FAILURE, 0,
   5419 	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   5420 
   5421   return data + indata.d_size;
   5422 }
   5423 
   5424 typedef uint8_t GElf_Byte;
   5425 
   5426 static unsigned int
   5427 handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
   5428 		  unsigned int colno, size_t *repeated_size)
   5429 {
   5430   uint_fast16_t count = item->count ?: 1;
   5431 
   5432 #define TYPES								      \
   5433   DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8, 4);			      \
   5434   DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16, 6);			      \
   5435   DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32, 11);			      \
   5436   DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32, 11);			      \
   5437   DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64, 20);		      \
   5438   DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64, 20)
   5439 
   5440 #define DO_TYPE(NAME, Name, hex, dec, max) GElf_##Name Name[count]
   5441   union { TYPES; } value;
   5442 #undef DO_TYPE
   5443 
   5444   void *data = &value;
   5445   size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
   5446   size_t convsize = size;
   5447   if (repeated_size != NULL)
   5448     {
   5449       if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
   5450 	{
   5451 	  data = alloca (*repeated_size);
   5452 	  count *= *repeated_size / size;
   5453 	  convsize = count * size;
   5454 	  *repeated_size -= convsize;
   5455 	}
   5456       else
   5457 	*repeated_size -= size;
   5458     }
   5459 
   5460   desc = convert (core, item->type, count, data, desc + item->offset, convsize);
   5461 
   5462   Elf_Type type = item->type;
   5463   if (type == ELF_T_ADDR)
   5464     type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
   5465 
   5466   switch (item->format)
   5467     {
   5468     case 'd':
   5469       assert (count == 1);
   5470       switch (type)
   5471 	{
   5472 #define DO_TYPE(NAME, Name, hex, dec, max)				      \
   5473 	  case ELF_T_##NAME:						      \
   5474 	    colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN,	      \
   5475 				     0, item->name, max, dec, value.Name[0]); \
   5476 	    break
   5477 	  TYPES;
   5478 #undef DO_TYPE
   5479 	default:
   5480 	  abort ();
   5481 	}
   5482       break;
   5483 
   5484     case 'x':
   5485       assert (count == 1);
   5486       switch (type)
   5487 	{
   5488 #define DO_TYPE(NAME, Name, hex, dec, max)				      \
   5489 	  case ELF_T_##NAME:						      \
   5490 	    colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN,	      \
   5491 				     0, item->name, max, hex, value.Name[0]); \
   5492 	    break
   5493 	  TYPES;
   5494 #undef DO_TYPE
   5495 	default:
   5496 	  abort ();
   5497 	}
   5498       break;
   5499 
   5500     case 'b':
   5501     case 'B':
   5502       assert (size % sizeof (unsigned int) == 0);
   5503       unsigned int nbits = count * size * 8;
   5504       unsigned int pop = 0;
   5505       for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
   5506 	pop += __builtin_popcount (*i);
   5507       bool negate = pop > nbits / 2;
   5508       const unsigned int bias = item->format == 'b';
   5509 
   5510       {
   5511 	char printed[(negate ? nbits - pop : pop) * 16];
   5512 	char *p = printed;
   5513 	*p = '\0';
   5514 
   5515 	if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
   5516 	  {
   5517 	    assert (size == sizeof (unsigned int) * 2);
   5518 	    for (unsigned int *i = data;
   5519 		 (void *) i < data + count * size; i += 2)
   5520 	      {
   5521 		unsigned int w = i[1];
   5522 		i[1] = i[0];
   5523 		i[0] = w;
   5524 	      }
   5525 	  }
   5526 
   5527 	unsigned int lastbit = 0;
   5528 	for (const unsigned int *i = data;
   5529 	     (void *) i < data + count * size; ++i)
   5530 	  {
   5531 	    unsigned int bit = ((void *) i - data) * 8;
   5532 	    unsigned int w = negate ? ~*i : *i;
   5533 	    while (w != 0)
   5534 	      {
   5535 		int n = ffs (w);
   5536 		w >>= n;
   5537 		bit += n;
   5538 
   5539 		if (lastbit + 1 != bit)
   5540 		  p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
   5541 		else if (lastbit == 0)
   5542 		  p += sprintf (p, "%u", bit - bias);
   5543 
   5544 		lastbit = bit;
   5545 	      }
   5546 	  }
   5547 	if (lastbit > 0 && lastbit + 1 != nbits)
   5548 	  p += sprintf (p, "-%u", nbits - bias);
   5549 
   5550 	colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
   5551 				 4 + nbits * 4,
   5552 				 negate ? "~<%s>" : "<%s>", printed);
   5553       }
   5554       break;
   5555 
   5556     case 'T':
   5557     case (char) ('T'|0x80):
   5558       assert (count == 2);
   5559       Dwarf_Word sec;
   5560       Dwarf_Word usec;
   5561       size_t maxfmt = 7;
   5562       switch (type)
   5563 	{
   5564 #define DO_TYPE(NAME, Name, hex, dec, max)				      \
   5565 	  case ELF_T_##NAME:						      \
   5566 	    sec = value.Name[0];					      \
   5567 	    usec = value.Name[1];					      \
   5568 	    maxfmt += max;						      \
   5569 	    break
   5570 	  TYPES;
   5571 #undef DO_TYPE
   5572 	default:
   5573 	  abort ();
   5574 	}
   5575       if (unlikely (item->format == (char) ('T'|0x80)))
   5576 	{
   5577 	  /* This is a hack for an ill-considered 64-bit ABI where
   5578 	     tv_usec is actually a 32-bit field with 32 bits of padding
   5579 	     rounding out struct timeval.  We've already converted it as
   5580 	     a 64-bit field.  For little-endian, this just means the
   5581 	     high half is the padding; it's presumably zero, but should
   5582 	     be ignored anyway.  For big-endian, it means the 32-bit
   5583 	     field went into the high half of USEC.  */
   5584 	  GElf_Ehdr ehdr_mem;
   5585 	  GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
   5586 	  if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
   5587 	    usec >>= 32;
   5588 	  else
   5589 	    usec &= UINT32_MAX;
   5590 	}
   5591       colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
   5592 			       maxfmt, "%" PRIu64 ".%.6" PRIu64, sec, usec);
   5593       break;
   5594 
   5595     case 'c':
   5596       assert (count == 1);
   5597       colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
   5598 			       1, "%c", value.Byte[0]);
   5599       break;
   5600 
   5601     case 's':
   5602       colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
   5603 			       count, "%.*s", (int) count, value.Byte);
   5604       break;
   5605 
   5606     default:
   5607       error (0, 0, "XXX not handling format '%c' for %s",
   5608 	     item->format, item->name);
   5609       break;
   5610     }
   5611 
   5612 #undef TYPES
   5613 
   5614   return colno;
   5615 }
   5616 
   5617 
   5618 /* Sort items by group, and by layout offset within each group.  */
   5619 static int
   5620 compare_core_items (const void *a, const void *b)
   5621 {
   5622   const Ebl_Core_Item *const *p1 = a;
   5623   const Ebl_Core_Item *const *p2 = b;
   5624   const Ebl_Core_Item *item1 = *p1;
   5625   const Ebl_Core_Item *item2 = *p2;
   5626 
   5627   return ((item1->group == item2->group ? 0
   5628 	   : strcmp (item1->group, item2->group))
   5629 	  ?: (int) item1->offset - (int) item2->offset);
   5630 }
   5631 
   5632 /* Sort item groups by layout offset of the first item in the group.  */
   5633 static int
   5634 compare_core_item_groups (const void *a, const void *b)
   5635 {
   5636   const Ebl_Core_Item *const *const *p1 = a;
   5637   const Ebl_Core_Item *const *const *p2 = b;
   5638   const Ebl_Core_Item *const *group1 = *p1;
   5639   const Ebl_Core_Item *const *group2 = *p2;
   5640   const Ebl_Core_Item *item1 = *group1;
   5641   const Ebl_Core_Item *item2 = *group2;
   5642 
   5643   return (int) item1->offset - (int) item2->offset;
   5644 }
   5645 
   5646 static unsigned int
   5647 handle_core_items (Elf *core, const void *desc, size_t descsz,
   5648 		   const Ebl_Core_Item *items, size_t nitems)
   5649 {
   5650   if (nitems == 0)
   5651     return 0;
   5652 
   5653   /* Sort to collect the groups together.  */
   5654   const Ebl_Core_Item *sorted_items[nitems];
   5655   for (size_t i = 0; i < nitems; ++i)
   5656     sorted_items[i] = &items[i];
   5657   qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
   5658 
   5659   /* Collect the unique groups and sort them.  */
   5660   const Ebl_Core_Item **groups[nitems];
   5661   groups[0] = &sorted_items[0];
   5662   size_t ngroups = 1;
   5663   for (size_t i = 1; i < nitems; ++i)
   5664     if (sorted_items[i]->group != sorted_items[i - 1]->group
   5665 	&& strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
   5666       groups[ngroups++] = &sorted_items[i];
   5667   qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
   5668 
   5669   /* Write out all the groups.  */
   5670   unsigned int colno = 0;
   5671 
   5672   const void *last = desc;
   5673   if (nitems == 1)
   5674     {
   5675       size_t size = descsz;
   5676       colno = handle_core_item (core, sorted_items[0], desc, colno, &size);
   5677       if (size == 0)
   5678 	return colno;
   5679       desc += descsz - size;
   5680       descsz = size;
   5681     }
   5682 
   5683   do
   5684     {
   5685       for (size_t i = 0; i < ngroups; ++i)
   5686 	{
   5687 	  for (const Ebl_Core_Item **item = groups[i];
   5688 	       (item < &sorted_items[nitems]
   5689 		&& ((*item)->group == groups[i][0]->group
   5690 		    || !strcmp ((*item)->group, groups[i][0]->group)));
   5691 	       ++item)
   5692 	    colno = handle_core_item (core, *item, desc, colno, NULL);
   5693 
   5694 	  /* Force a line break at the end of the group.  */
   5695 	  colno = ITEM_WRAP_COLUMN;
   5696 	}
   5697 
   5698       if (descsz == 0)
   5699 	break;
   5700 
   5701       /* This set of items consumed a certain amount of the note's data.
   5702 	 If there is more data there, we have another unit of the same size.
   5703 	 Loop to print that out too.  */
   5704       const Ebl_Core_Item *item = &items[nitems - 1];
   5705       size_t eltsz = item->offset + gelf_fsize (core, item->type,
   5706 						item->count ?: 1, EV_CURRENT);
   5707 
   5708       int reps = -1;
   5709       do
   5710 	{
   5711 	  ++reps;
   5712 	  desc += eltsz;
   5713 	  descsz -= eltsz;
   5714 	}
   5715       while (descsz >= eltsz && !memcmp (desc, last, eltsz));
   5716 
   5717       if (reps == 1)
   5718 	{
   5719 	  /* For just one repeat, print it unabridged twice.  */
   5720 	  desc -= eltsz;
   5721 	  descsz += eltsz;
   5722 	}
   5723       else if (reps > 1)
   5724 	printf (gettext ("\n%*s... <repeats %u more times> ..."),
   5725 		ITEM_INDENT, "", reps);
   5726 
   5727       last = desc;
   5728     }
   5729   while (descsz > 0);
   5730 
   5731   return colno;
   5732 }
   5733 
   5734 static unsigned int
   5735 handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
   5736 		      unsigned int colno)
   5737 {
   5738   desc += regloc->offset;
   5739 
   5740   abort ();			/* XXX */
   5741   return colno;
   5742 }
   5743 
   5744 
   5745 static unsigned int
   5746 handle_core_register (Ebl *ebl, Elf *core, int maxregname,
   5747 		      const Ebl_Register_Location *regloc, const void *desc,
   5748 		      unsigned int colno)
   5749 {
   5750   if (regloc->bits % 8 != 0)
   5751     return handle_bit_registers (regloc, desc, colno);
   5752 
   5753   desc += regloc->offset;
   5754 
   5755   for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
   5756     {
   5757       const char *pfx;
   5758       const char *set;
   5759       char name[16];
   5760       int bits;
   5761       int type;
   5762       ssize_t n = ebl_register_info (ebl, reg, name, sizeof name,
   5763 				     &pfx, &set, &bits, &type);
   5764       if (n <= 0)
   5765 	error (EXIT_FAILURE, 0,
   5766 	       gettext ("unable to handle register number %d"),
   5767 	       regloc->regno);
   5768 
   5769 #define TYPES								      \
   5770       BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8, 4);			      \
   5771       BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16, 6);			      \
   5772       BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32, 11);		      \
   5773       BITS (64, XWORD, "%20" PRId64, "  0x%.16" PRIx64, 20)
   5774 
   5775 #define BITS(bits, xtype, sfmt, ufmt, max)				\
   5776       uint##bits##_t b##bits; int##bits##_t b##bits##s
   5777       union { TYPES; uint64_t b128[2]; } value;
   5778 #undef	BITS
   5779 
   5780       switch (type)
   5781 	{
   5782 	case DW_ATE_unsigned:
   5783 	case DW_ATE_signed:
   5784 	case DW_ATE_address:
   5785 	  switch (bits)
   5786 	    {
   5787 #define BITS(bits, xtype, sfmt, ufmt, max)				      \
   5788 	    case bits:							      \
   5789 	      desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0);	      \
   5790 	      if (type == DW_ATE_signed)				      \
   5791 		colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,    \
   5792 					 maxregname, name,		      \
   5793 					 max, sfmt, value.b##bits##s);	      \
   5794 	      else							      \
   5795 		colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,    \
   5796 					 maxregname, name,		      \
   5797 					 max, ufmt, value.b##bits);	      \
   5798 	      break
   5799 
   5800 	    TYPES;
   5801 
   5802 	    case 128:
   5803 	      assert (type == DW_ATE_unsigned);
   5804 	      desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
   5805 	      int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
   5806 	      colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
   5807 				       maxregname, name,
   5808 				       34, "0x%.16" PRIx64 "%.16" PRIx64,
   5809 				       value.b128[!be], value.b128[be]);
   5810 	      break;
   5811 
   5812 	    default:
   5813 	      abort ();
   5814 #undef	BITS
   5815 	    }
   5816 	  break;
   5817 
   5818 	default:
   5819 	  /* Print each byte in hex, the whole thing in native byte order.  */
   5820 	  assert (bits % 8 == 0);
   5821 	  const uint8_t *bytes = desc;
   5822 	  desc += bits / 8;
   5823 	  char hex[bits / 4 + 1];
   5824 	  hex[bits / 4] = '\0';
   5825 	  int incr = 1;
   5826 	  if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
   5827 	    {
   5828 	      bytes += bits / 8 - 1;
   5829 	      incr = -1;
   5830 	    }
   5831 	  size_t idx = 0;
   5832 	  for (char *h = hex; bits > 0; bits -= 8, idx += incr)
   5833 	    {
   5834 	      *h++ = "0123456789abcdef"[bytes[idx] >> 4];
   5835 	      *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
   5836 	    }
   5837 	  colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
   5838 				   maxregname, name,
   5839 				   2 + sizeof hex - 1, "0x%s", hex);
   5840 	  break;
   5841 	}
   5842       desc += regloc->pad;
   5843 
   5844 #undef TYPES
   5845     }
   5846 
   5847   return colno;
   5848 }
   5849 
   5850 
   5851 struct register_info
   5852 {
   5853   const Ebl_Register_Location *regloc;
   5854   const char *set;
   5855   char name[16];
   5856   Dwarf_Half regno;
   5857   uint8_t bits;
   5858   uint8_t type;
   5859 };
   5860 
   5861 static int
   5862 register_bitpos (const struct register_info *r)
   5863 {
   5864   return (r->regloc->offset * 8
   5865 	  + ((r->regno - r->regloc->regno)
   5866 	     * (r->regloc->bits + r->regloc->pad * 8)));
   5867 }
   5868 
   5869 static int
   5870 compare_sets_by_info (const struct register_info *r1,
   5871 		      const struct register_info *r2)
   5872 {
   5873   return ((int) r2->bits - (int) r1->bits
   5874 	  ?: register_bitpos (r1) - register_bitpos (r2));
   5875 }
   5876 
   5877 /* Sort registers by set, and by size and layout offset within each set.  */
   5878 static int
   5879 compare_registers (const void *a, const void *b)
   5880 {
   5881   const struct register_info *r1 = a;
   5882   const struct register_info *r2 = b;
   5883 
   5884   /* Unused elements sort last.  */
   5885   if (r1->regloc == NULL)
   5886     return r2->regloc == NULL ? 0 : 1;
   5887   if (r2->regloc == NULL)
   5888     return -1;
   5889 
   5890   return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
   5891 	  ?: compare_sets_by_info (r1, r2));
   5892 }
   5893 
   5894 /* Sort register sets by layout offset of the first register in the set.  */
   5895 static int
   5896 compare_register_sets (const void *a, const void *b)
   5897 {
   5898   const struct register_info *const *p1 = a;
   5899   const struct register_info *const *p2 = b;
   5900   return compare_sets_by_info (*p1, *p2);
   5901 }
   5902 
   5903 static unsigned int
   5904 handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
   5905 		       const Ebl_Register_Location *reglocs, size_t nregloc)
   5906 {
   5907   if (nregloc == 0)
   5908     return 0;
   5909 
   5910   ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
   5911   if (maxnreg <= 0)
   5912     error (EXIT_FAILURE, 0,
   5913 	   gettext ("cannot register info: %s"), elf_errmsg (-1));
   5914 
   5915   struct register_info regs[maxnreg];
   5916   memset (regs, 0, sizeof regs);
   5917 
   5918   /* Sort to collect the sets together.  */
   5919   int maxreg = 0;
   5920   for (size_t i = 0; i < nregloc; ++i)
   5921     for (int reg = reglocs[i].regno;
   5922 	 reg < reglocs[i].regno + reglocs[i].count;
   5923 	 ++reg)
   5924       {
   5925 	assert (reg < maxnreg);
   5926 	if (reg > maxreg)
   5927 	  maxreg = reg;
   5928 	struct register_info *info = &regs[reg];
   5929 
   5930 	const char *pfx;
   5931 	int bits;
   5932 	int type;
   5933 	ssize_t n = ebl_register_info (ebl, reg, info->name, sizeof info->name,
   5934 				       &pfx, &info->set, &bits, &type);
   5935 	if (n <= 0)
   5936 	  error (EXIT_FAILURE, 0,
   5937 		 gettext ("cannot register info: %s"), elf_errmsg (-1));
   5938 
   5939 	info->regloc = &reglocs[i];
   5940 	info->regno = reg;
   5941 	info->bits = bits;
   5942 	info->type = type;
   5943       }
   5944   qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
   5945 
   5946   /* Collect the unique sets and sort them.  */
   5947   inline bool same_set (const struct register_info *a,
   5948 			const struct register_info *b)
   5949   {
   5950     return (a < &regs[maxnreg] && a->regloc != NULL
   5951 	    && b < &regs[maxnreg] && b->regloc != NULL
   5952 	    && a->bits == b->bits
   5953 	    && (a->set == b->set || !strcmp (a->set, b->set)));
   5954   }
   5955   struct register_info *sets[maxreg + 1];
   5956   sets[0] = &regs[0];
   5957   size_t nsets = 1;
   5958   for (int i = 1; i <= maxreg; ++i)
   5959     if (regs[i].regloc != NULL && !same_set (&regs[i], &regs[i - 1]))
   5960       sets[nsets++] = &regs[i];
   5961   qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
   5962 
   5963   /* Write out all the sets.  */
   5964   unsigned int colno = 0;
   5965   for (size_t i = 0; i < nsets; ++i)
   5966     {
   5967       /* Find the longest name of a register in this set.  */
   5968       size_t maxname = 0;
   5969       const struct register_info *end;
   5970       for (end = sets[i]; same_set (sets[i], end); ++end)
   5971 	{
   5972 	  size_t len = strlen (end->name);
   5973 	  if (len > maxname)
   5974 	    maxname = len;
   5975 	}
   5976 
   5977       for (const struct register_info *reg = sets[i];
   5978 	   reg < end;
   5979 	   reg += reg->regloc->count ?: 1)
   5980 	colno = handle_core_register (ebl, core, maxname,
   5981 				      reg->regloc, desc, colno);
   5982 
   5983       /* Force a line break at the end of the group.  */
   5984       colno = REGISTER_WRAP_COLUMN;
   5985     }
   5986 
   5987   return colno;
   5988 }
   5989 
   5990 static void
   5991 handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
   5992 {
   5993   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
   5994   if (data == NULL)
   5995   elf_error:
   5996     error (EXIT_FAILURE, 0,
   5997 	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   5998 
   5999   const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
   6000   for (size_t i = 0; i < nauxv; ++i)
   6001     {
   6002       GElf_auxv_t av_mem;
   6003       GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
   6004       if (av == NULL)
   6005 	goto elf_error;
   6006 
   6007       const char *name;
   6008       const char *fmt;
   6009       if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
   6010 	{
   6011 	  /* Unknown type.  */
   6012 	  if (av->a_un.a_val == 0)
   6013 	    printf ("    %" PRIu64 "\n", av->a_type);
   6014 	  else
   6015 	    printf ("    %" PRIu64 ": %#" PRIx64 "\n",
   6016 		    av->a_type, av->a_un.a_val);
   6017 	}
   6018       else
   6019 	switch (fmt[0])
   6020 	  {
   6021 	  case '\0':		/* Normally zero.  */
   6022 	    if (av->a_un.a_val == 0)
   6023 	      {
   6024 		printf ("    %s\n", name);
   6025 		break;
   6026 	      }
   6027 	    /* Fall through */
   6028 	  case 'x':		/* hex */
   6029 	  case 'p':		/* address */
   6030 	  case 's':		/* address of string */
   6031 	    printf ("    %s: %#" PRIx64 "\n", name, av->a_un.a_val);
   6032 	    break;
   6033 	  case 'u':
   6034 	    printf ("    %s: %" PRIu64 "\n", name, av->a_un.a_val);
   6035 	    break;
   6036 	  case 'd':
   6037 	    printf ("    %s: %" PRId64 "\n", name, av->a_un.a_val);
   6038 	    break;
   6039 
   6040 	  case 'b':
   6041 	    printf ("    %s: %#" PRIx64 "  ", name, av->a_un.a_val);
   6042 	    GElf_Xword bit = 1;
   6043 	    const char *pfx = "<";
   6044 	    for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
   6045 	      {
   6046 		if (av->a_un.a_val & bit)
   6047 		  {
   6048 		    printf ("%s%s", pfx, p);
   6049 		    pfx = " ";
   6050 		  }
   6051 		bit <<= 1;
   6052 	      }
   6053 	    printf (">\n");
   6054 	    break;
   6055 
   6056 	  default:
   6057 	    abort ();
   6058 	  }
   6059     }
   6060 }
   6061 
   6062 static void
   6063 handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr, const void *desc)
   6064 {
   6065   GElf_Word regs_offset;
   6066   size_t nregloc;
   6067   const Ebl_Register_Location *reglocs;
   6068   size_t nitems;
   6069   const Ebl_Core_Item *items;
   6070 
   6071   if (! ebl_core_note (ebl, nhdr->n_type, nhdr->n_descsz,
   6072 		       &regs_offset, &nregloc, &reglocs, &nitems, &items))
   6073     return;
   6074 
   6075   /* Pass 0 for DESCSZ when there are registers in the note,
   6076      so that the ITEMS array does not describe the whole thing.
   6077      For non-register notes, the actual descsz might be a multiple
   6078      of the unit size, not just exactly the unit size.  */
   6079   unsigned int colno = handle_core_items (ebl->elf, desc,
   6080 					  nregloc == 0 ? nhdr->n_descsz : 0,
   6081 					  items, nitems);
   6082   if (colno != 0)
   6083     putchar_unlocked ('\n');
   6084 
   6085   colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
   6086 				 reglocs, nregloc);
   6087   if (colno != 0)
   6088     putchar_unlocked ('\n');
   6089 }
   6090 
   6091 static void
   6092 handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
   6093 		   GElf_Off start, Elf_Data *data)
   6094 {
   6095   fputs_unlocked (gettext ("  Owner          Data size  Type\n"), stdout);
   6096 
   6097   if (data == NULL)
   6098     goto bad_note;
   6099 
   6100   size_t offset = 0;
   6101   GElf_Nhdr nhdr;
   6102   size_t name_offset;
   6103   size_t desc_offset;
   6104   while (offset < data->d_size
   6105 	 && (offset = gelf_getnote (data, offset,
   6106 				    &nhdr, &name_offset, &desc_offset)) > 0)
   6107     {
   6108       const char *name = data->d_buf + name_offset;
   6109       const char *desc = data->d_buf + desc_offset;
   6110 
   6111       char buf[100];
   6112       char buf2[100];
   6113       printf (gettext ("  %-13.*s  %9" PRId32 "  %s\n"),
   6114 	      (int) nhdr.n_namesz, name, nhdr.n_descsz,
   6115 	      ehdr->e_type == ET_CORE
   6116 	      ? ebl_core_note_type_name (ebl, nhdr.n_type,
   6117 					 buf, sizeof (buf))
   6118 	      : ebl_object_note_type_name (ebl, nhdr.n_type,
   6119 					   buf2, sizeof (buf2)));
   6120 
   6121       /* Filter out invalid entries.  */
   6122       if (memchr (name, '\0', nhdr.n_namesz) != NULL
   6123 	  /* XXX For now help broken Linux kernels.  */
   6124 	  || 1)
   6125 	{
   6126 	  if (ehdr->e_type == ET_CORE)
   6127 	    {
   6128 	      if (nhdr.n_type == NT_AUXV)
   6129 		handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
   6130 				  start + desc_offset);
   6131 	      else
   6132 		handle_core_note (ebl, &nhdr, desc);
   6133 	    }
   6134 	  else
   6135 	    ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc);
   6136 	}
   6137     }
   6138 
   6139   if (offset == data->d_size)
   6140     return;
   6141 
   6142  bad_note:
   6143   error (EXIT_FAILURE, 0,
   6144 	 gettext ("cannot get content of note section: %s"),
   6145 	 elf_errmsg (-1));
   6146 }
   6147 
   6148 static void
   6149 handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
   6150 {
   6151   /* If we have section headers, just look for SHT_NOTE sections.
   6152      In a debuginfo file, the program headers are not reliable.  */
   6153   if (shnum != 0)
   6154     {
   6155       /* Get the section header string table index.  */
   6156       size_t shstrndx;
   6157       if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
   6158 	error (EXIT_FAILURE, 0,
   6159 	       gettext ("cannot get section header string table index"));
   6160 
   6161       Elf_Scn *scn = NULL;
   6162       while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   6163 	{
   6164 	  GElf_Shdr shdr_mem;
   6165 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   6166 
   6167 	  if (shdr == NULL || shdr->sh_type != SHT_NOTE)
   6168 	    /* Not what we are looking for.  */
   6169 	    continue;
   6170 
   6171 	  printf (gettext ("\
   6172 \nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
   6173 		  elf_ndxscn (scn),
   6174 		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   6175 		  shdr->sh_size, shdr->sh_offset);
   6176 
   6177 	  handle_notes_data (ebl, ehdr, shdr->sh_offset,
   6178 			     elf_getdata (scn, NULL));
   6179 	}
   6180       return;
   6181     }
   6182 
   6183   /* We have to look through the program header to find the note
   6184      sections.  There can be more than one.  */
   6185   for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt)
   6186     {
   6187       GElf_Phdr mem;
   6188       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
   6189 
   6190       if (phdr == NULL || phdr->p_type != PT_NOTE)
   6191 	/* Not what we are looking for.  */
   6192 	continue;
   6193 
   6194       printf (gettext ("\
   6195 \nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
   6196 	      phdr->p_filesz, phdr->p_offset);
   6197 
   6198       handle_notes_data (ebl, ehdr, phdr->p_offset,
   6199 			 elf_getdata_rawchunk (ebl->elf,
   6200 					       phdr->p_offset, phdr->p_filesz,
   6201 					       ELF_T_NHDR));
   6202     }
   6203 }
   6204 
   6205 
   6206 static void
   6207 hex_dump (const uint8_t *data, size_t len)
   6208 {
   6209   size_t pos = 0;
   6210   while (pos < len)
   6211     {
   6212       printf ("  0x%08Zx ", pos);
   6213 
   6214       const size_t chunk = MIN (len - pos, 16);
   6215 
   6216       for (size_t i = 0; i < chunk; ++i)
   6217 	if (i % 4 == 3)
   6218 	  printf ("%02x ", data[pos + i]);
   6219 	else
   6220 	  printf ("%02x", data[pos + i]);
   6221 
   6222       if (chunk < 16)
   6223 	printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
   6224 
   6225       for (size_t i = 0; i < chunk; ++i)
   6226 	{
   6227 	  unsigned char b = data[pos + i];
   6228 	  printf ("%c", isprint (b) ? b : '.');
   6229 	}
   6230 
   6231       putchar ('\n');
   6232       pos += chunk;
   6233     }
   6234 }
   6235 
   6236 static void
   6237 dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
   6238 {
   6239   if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
   6240     printf (gettext ("\nSection [%Zu] '%s' has no data to dump.\n"),
   6241 	    elf_ndxscn (scn), name);
   6242   else
   6243     {
   6244       Elf_Data *data = elf_rawdata (scn, NULL);
   6245       if (data == NULL)
   6246 	error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
   6247 	       elf_ndxscn (scn), name, elf_errmsg (-1));
   6248       else
   6249 	{
   6250 	  printf (gettext ("\nHex dump of section [%Zu] '%s', %" PRIu64
   6251 			   " bytes at offset %#0" PRIx64 ":\n"),
   6252 		  elf_ndxscn (scn), name,
   6253 		  shdr->sh_size, shdr->sh_offset);
   6254 	  hex_dump (data->d_buf, data->d_size);
   6255 	}
   6256     }
   6257 }
   6258 
   6259 static void
   6260 print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
   6261 {
   6262   if (shdr->sh_size == 0)
   6263     printf (gettext ("\nSection [%Zu] '%s' is empty.\n"),
   6264 	    elf_ndxscn (scn), name);
   6265 
   6266   Elf_Data *data = elf_rawdata (scn, NULL);
   6267   if (data == NULL)
   6268     error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
   6269 	   elf_ndxscn (scn), name, elf_errmsg (-1));
   6270   else
   6271     {
   6272       printf (gettext ("\nString section [%Zu] '%s' contains %" PRIu64
   6273 		       " bytes at offset %#0" PRIx64 ":\n"),
   6274 	      elf_ndxscn (scn), name,
   6275 	      shdr->sh_size, shdr->sh_offset);
   6276 
   6277       const char *start = data->d_buf;
   6278       const char *const limit = start + data->d_size;
   6279       do
   6280 	{
   6281 	  const char *end = memchr (start, '\0', limit - start);
   6282 	  const size_t pos = start - (const char *) data->d_buf;
   6283 	  if (unlikely (end == NULL))
   6284 	    {
   6285 	      printf ("  [%6Zx]- %.*s\n",
   6286 		      pos, (int) (limit - start), start);
   6287 	      break;
   6288 	    }
   6289 	  printf ("  [%6Zx]  %s\n", pos, start);
   6290 	  start = end + 1;
   6291 	} while (start < limit);
   6292     }
   6293 }
   6294 
   6295 static void
   6296 for_each_section_argument (Elf *elf, const struct section_argument *list,
   6297 			   void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
   6298 					 const char *name))
   6299 {
   6300   /* Get the section header string table index.  */
   6301   size_t shstrndx;
   6302   if (elf_getshstrndx (elf, &shstrndx) < 0)
   6303     error (EXIT_FAILURE, 0,
   6304 	   gettext ("cannot get section header string table index"));
   6305 
   6306   for (const struct section_argument *a = list; a != NULL; a = a->next)
   6307     {
   6308       Elf_Scn *scn;
   6309       GElf_Shdr shdr_mem;
   6310       const char *name = NULL;
   6311 
   6312       char *endp = NULL;
   6313       unsigned long int shndx = strtoul (a->arg, &endp, 0);
   6314       if (endp != a->arg && *endp == '\0')
   6315 	{
   6316 	  scn = elf_getscn (elf, shndx);
   6317 	  if (scn == NULL)
   6318 	    {
   6319 	      error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
   6320 	      continue;
   6321 	    }
   6322 
   6323 	  if (gelf_getshdr (scn, &shdr_mem) == NULL)
   6324 	    error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
   6325 		   elf_errmsg (-1));
   6326 	  name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
   6327 	}
   6328       else
   6329 	{
   6330 	  /* Need to look up the section by name.  */
   6331 	  scn = NULL;
   6332 	  while ((scn = elf_nextscn (elf, scn)) != NULL)
   6333 	    {
   6334 	      if (gelf_getshdr (scn, &shdr_mem) == NULL)
   6335 		continue;
   6336 	      name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
   6337 	      if (name == NULL)
   6338 		continue;
   6339 	      if (!strcmp (name, a->arg))
   6340 		break;
   6341 	    }
   6342 
   6343 	  if (unlikely (scn == NULL))
   6344 	    {
   6345 	      error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
   6346 	      continue;
   6347 	    }
   6348 	}
   6349 
   6350       (*dump) (scn, &shdr_mem, name);
   6351     }
   6352 }
   6353 
   6354 static void
   6355 dump_data (Ebl *ebl)
   6356 {
   6357   for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
   6358 }
   6359 
   6360 static void
   6361 dump_strings (Ebl *ebl)
   6362 {
   6363   for_each_section_argument (ebl->elf, string_sections, &print_string_section);
   6364 }
   6365 
   6366 static void
   6367 print_strings (Ebl *ebl)
   6368 {
   6369   /* Get the section header string table index.  */
   6370   size_t shstrndx;
   6371   if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
   6372     error (EXIT_FAILURE, 0,
   6373 	   gettext ("cannot get section header string table index"));
   6374 
   6375   Elf_Scn *scn;
   6376   GElf_Shdr shdr_mem;
   6377   const char *name;
   6378   scn = NULL;
   6379   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   6380     {
   6381       if (gelf_getshdr (scn, &shdr_mem) == NULL)
   6382 	continue;
   6383 
   6384       if (shdr_mem.sh_type != SHT_PROGBITS
   6385 	  || !(shdr_mem.sh_flags & SHF_STRINGS))
   6386 	continue;
   6387 
   6388       name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
   6389       if (name == NULL)
   6390 	continue;
   6391 
   6392       print_string_section (scn, &shdr_mem, name);
   6393     }
   6394 }
   6395 
   6396 static void
   6397 dump_archive_index (Elf *elf, const char *fname)
   6398 {
   6399   size_t narsym;
   6400   const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
   6401   if (arsym == NULL)
   6402     {
   6403       int result = elf_errno ();
   6404       if (unlikely (result != ELF_E_NO_INDEX))
   6405 	error (EXIT_FAILURE, 0,
   6406 	       gettext ("cannot get symbol index of archive '%s': %s"),
   6407 	       fname, elf_errmsg (result));
   6408       else
   6409 	printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
   6410       return;
   6411     }
   6412 
   6413   printf (gettext ("\nIndex of archive '%s' has %Zu entries:\n"),
   6414 	  fname, narsym);
   6415 
   6416   size_t as_off = 0;
   6417   for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
   6418     {
   6419       if (s->as_off != as_off)
   6420 	{
   6421 	  as_off = s->as_off;
   6422 
   6423 	  Elf *subelf;
   6424 	  if (unlikely (elf_rand (elf, as_off) == 0)
   6425 	      || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
   6426 			   == NULL))
   6427 #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
   6428 	    while (1)
   6429 #endif
   6430 	      error (EXIT_FAILURE, 0,
   6431 		     gettext ("cannot extract member at offset %Zu in '%s': %s"),
   6432 		     as_off, fname, elf_errmsg (-1));
   6433 
   6434 	  const Elf_Arhdr *h = elf_getarhdr (subelf);
   6435 
   6436 	  printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
   6437 
   6438 	  elf_end (subelf);
   6439 	}
   6440 
   6441       printf ("\t%s\n", s->as_name);
   6442     }
   6443 }
   6444 
   6445 #include "debugpred.h"
   6446