Home | History | Annotate | Download | only in src
      1 /* Print information from ELF file in human-readable form.
      2    Copyright (C) 1999-2012 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 #include <sys/stat.h>
     53 
     54 #include <system.h>
     55 #include "../libelf/libelfP.h"
     56 #include "../libelf/common.h"
     57 #include "../libebl/libeblP.h"
     58 #include "../libdw/libdwP.h"
     59 #include "../libdwfl/libdwflP.h"
     60 #include "../libdw/memory-access.h"
     61 
     62 
     63 /* Name and version of program.  */
     64 static void print_version (FILE *stream, struct argp_state *state);
     65 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
     66 
     67 /* Bug report address.  */
     68 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
     69 
     70 /* Definitions of arguments for argp functions.  */
     71 static const struct argp_option options[] =
     72 {
     73   { NULL, 0, NULL, 0, N_("ELF output selection:"), 0 },
     74   { "all", 'a', NULL, 0,
     75     N_("All these plus -p .strtab -p .dynstr -p .comment"), 0 },
     76   { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
     77   { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
     78   { "histogram", 'I', NULL, 0,
     79     N_("Display histogram of bucket list lengths"), 0 },
     80   { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
     81   { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
     82   { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
     83   { "section-headers", 'S', NULL, 0, N_("Display the sections' headers"), 0 },
     84   { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
     85   { "symbols", 's', NULL, 0, N_("Display the symbol table"), 0 },
     86   { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
     87   { "notes", 'n', NULL, 0, N_("Display the ELF notes"), 0 },
     88   { "arch-specific", 'A', NULL, 0,
     89     N_("Display architecture specific information, if any"), 0 },
     90   { "exception", 'e', NULL, 0,
     91     N_("Display sections for exception handling"), 0 },
     92 
     93   { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 },
     94   { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
     95     N_("Display DWARF section content.  SECTION can be one of abbrev, "
     96        "aranges, frame, gdb_index, info, loc, line, ranges, pubnames, str, "
     97        "macinfo, or exception"), 0 },
     98   { "hex-dump", 'x', "SECTION", 0,
     99     N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
    100   { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
    101     N_("Print string contents of sections"), 0 },
    102   { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
    103   { "archive-index", 'c', NULL, 0,
    104     N_("Display the symbol index of an archive"), 0 },
    105 
    106   { NULL, 0, NULL, 0, N_("Output control:"), 0 },
    107   { "numeric-addresses", 'N', NULL, 0,
    108     N_("Do not find symbol names for addresses in DWARF data"), 0 },
    109   { "wide", 'W', NULL, 0,
    110     N_("Ignored for compatibility (lines always wide)"), 0 },
    111   { NULL, 0, NULL, 0, NULL, 0 }
    112 };
    113 
    114 /* Short description of program.  */
    115 static const char doc[] = N_("\
    116 Print information from ELF file in human-readable form.");
    117 
    118 /* Strings for arguments in help texts.  */
    119 static const char args_doc[] = N_("FILE...");
    120 
    121 /* Prototype for option handler.  */
    122 static error_t parse_opt (int key, char *arg, struct argp_state *state);
    123 
    124 /* Data structure to communicate with argp functions.  */
    125 static struct argp argp =
    126 {
    127   options, parse_opt, args_doc, doc, NULL, NULL, NULL
    128 };
    129 
    130 
    131 /* Flags set by the option controlling the output.  */
    132 
    133 /* True if dynamic segment should be printed.  */
    134 static bool print_dynamic_table;
    135 
    136 /* True if the file header should be printed.  */
    137 static bool print_file_header;
    138 
    139 /* True if the program headers should be printed.  */
    140 static bool print_program_header;
    141 
    142 /* True if relocations should be printed.  */
    143 static bool print_relocations;
    144 
    145 /* True if the section headers should be printed.  */
    146 static bool print_section_header;
    147 
    148 /* True if the symbol table should be printed.  */
    149 static bool print_symbol_table;
    150 
    151 /* True if the version information should be printed.  */
    152 static bool print_version_info;
    153 
    154 /* True if section groups should be printed.  */
    155 static bool print_section_groups;
    156 
    157 /* True if bucket list length histogram should be printed.  */
    158 static bool print_histogram;
    159 
    160 /* True if the architecture specific data should be printed.  */
    161 static bool print_arch;
    162 
    163 /* True if note section content should be printed.  */
    164 static bool print_notes;
    165 
    166 /* True if SHF_STRINGS section content should be printed.  */
    167 static bool print_string_sections;
    168 
    169 /* True if archive index should be printed.  */
    170 static bool print_archive_index;
    171 
    172 /* True if any of the control options except print_archive_index is set.  */
    173 static bool any_control_option;
    174 
    175 /* True if we should print addresses from DWARF in symbolic form.  */
    176 static bool print_address_names = true;
    177 
    178 /* Select printing of debugging sections.  */
    179 static enum section_e
    180 {
    181   section_abbrev = 1,		/* .debug_abbrev  */
    182   section_aranges = 2,		/* .debug_aranges  */
    183   section_frame = 4,		/* .debug_frame or .eh_frame & al.  */
    184   section_info = 8,		/* .debug_info, .debug_types  */
    185   section_types = section_info,
    186   section_line = 16,		/* .debug_line  */
    187   section_loc = 32,		/* .debug_loc  */
    188   section_pubnames = 64,	/* .debug_pubnames  */
    189   section_str = 128,		/* .debug_str  */
    190   section_macinfo = 256,	/* .debug_macinfo  */
    191   section_ranges = 512, 	/* .debug_ranges  */
    192   section_exception = 1024,	/* .eh_frame & al.  */
    193   section_gdb_index = 2048,	/* .gdb_index  */
    194   section_all = (section_abbrev | section_aranges | section_frame
    195 		 | section_info | section_line | section_loc
    196 		 | section_pubnames | section_str | section_macinfo
    197 		 | section_ranges | section_exception | section_gdb_index)
    198 } print_debug_sections, implicit_debug_sections;
    199 
    200 /* Select hex dumping of sections.  */
    201 static struct section_argument *dump_data_sections;
    202 static struct section_argument **dump_data_sections_tail = &dump_data_sections;
    203 
    204 /* Select string dumping of sections.  */
    205 static struct section_argument *string_sections;
    206 static struct section_argument **string_sections_tail = &string_sections;
    207 
    208 struct section_argument
    209 {
    210   struct section_argument *next;
    211   const char *arg;
    212   bool implicit;
    213 };
    214 
    215 /* Numbers of sections and program headers in the file.  */
    216 static size_t shnum;
    217 static size_t phnum;
    218 
    219 
    220 /* Declarations of local functions.  */
    221 static void process_file (int fd, const char *fname, bool only_one);
    222 static void process_elf_file (Dwfl_Module *dwflmod, int fd);
    223 static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
    224 static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
    225 static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
    226 static void print_scngrp (Ebl *ebl);
    227 static void print_dynamic (Ebl *ebl);
    228 static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
    229 static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
    230 			       GElf_Shdr *shdr);
    231 static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
    232 				GElf_Shdr *shdr);
    233 static void print_symtab (Ebl *ebl, int type);
    234 static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
    235 static void print_verinfo (Ebl *ebl);
    236 static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
    237 static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
    238 static void handle_versym (Ebl *ebl, Elf_Scn *scn,
    239 			   GElf_Shdr *shdr);
    240 static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
    241 static void handle_hash (Ebl *ebl);
    242 static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
    243 static void print_liblist (Ebl *ebl);
    244 static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
    245 static void dump_data (Ebl *ebl);
    246 static void dump_strings (Ebl *ebl);
    247 static void print_strings (Ebl *ebl);
    248 static void dump_archive_index (Elf *, const char *);
    249 
    250 
    251 int
    252 main (int argc, char *argv[])
    253 {
    254   /* Set locale.  */
    255   setlocale (LC_ALL, "");
    256 
    257   /* Initialize the message catalog.  */
    258   textdomain (PACKAGE_TARNAME);
    259 
    260   /* Parse and process arguments.  */
    261   int remaining;
    262   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
    263 
    264   /* Before we start tell the ELF library which version we are using.  */
    265   elf_version (EV_CURRENT);
    266 
    267   /* Now process all the files given at the command line.  */
    268   bool only_one = remaining + 1 == argc;
    269   do
    270     {
    271       /* Open the file.  */
    272       int fd = open (argv[remaining], O_RDONLY);
    273       if (fd == -1)
    274 	{
    275 	  error (0, errno, gettext ("cannot open input file"));
    276 	  continue;
    277 	}
    278 
    279       process_file (fd, argv[remaining], only_one);
    280 
    281       close (fd);
    282     }
    283   while (++remaining < argc);
    284 
    285   return error_message_count != 0;
    286 }
    287 
    288 
    289 /* Handle program arguments.  */
    290 static error_t
    291 parse_opt (int key, char *arg,
    292 	   struct argp_state *state __attribute__ ((unused)))
    293 {
    294   void add_dump_section (const char *name, bool implicit)
    295   {
    296     struct section_argument *a = xmalloc (sizeof *a);
    297     a->arg = name;
    298     a->next = NULL;
    299     a->implicit = implicit;
    300     struct section_argument ***tailp
    301       = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
    302     **tailp = a;
    303     *tailp = &a->next;
    304   }
    305 
    306   switch (key)
    307     {
    308     case 'a':
    309       print_file_header = true;
    310       print_program_header = true;
    311       print_relocations = true;
    312       print_section_header = true;
    313       print_symbol_table = true;
    314       print_version_info = true;
    315       print_dynamic_table = true;
    316       print_section_groups = true;
    317       print_histogram = true;
    318       print_arch = true;
    319       print_notes = true;
    320       implicit_debug_sections |= section_exception;
    321       add_dump_section (".strtab", true);
    322       add_dump_section (".dynstr", true);
    323       add_dump_section (".comment", true);
    324       any_control_option = true;
    325       break;
    326     case 'A':
    327       print_arch = true;
    328       any_control_option = true;
    329       break;
    330     case 'd':
    331       print_dynamic_table = true;
    332       any_control_option = true;
    333       break;
    334     case 'e':
    335       print_debug_sections |= section_exception;
    336       any_control_option = true;
    337       break;
    338     case 'g':
    339       print_section_groups = true;
    340       any_control_option = true;
    341       break;
    342     case 'h':
    343       print_file_header = true;
    344       any_control_option = true;
    345       break;
    346     case 'I':
    347       print_histogram = true;
    348       any_control_option = true;
    349       break;
    350     case 'l':
    351       print_program_header = true;
    352       any_control_option = true;
    353       break;
    354     case 'n':
    355       print_notes = true;
    356       any_control_option = true;
    357       break;
    358     case 'r':
    359       print_relocations = true;
    360       any_control_option = true;
    361      break;
    362     case 'S':
    363       print_section_header = true;
    364       any_control_option = true;
    365       break;
    366     case 's':
    367       print_symbol_table = true;
    368       any_control_option = true;
    369       break;
    370     case 'V':
    371       print_version_info = true;
    372       any_control_option = true;
    373       break;
    374     case 'c':
    375       print_archive_index = true;
    376       break;
    377     case 'w':
    378       if (arg == NULL)
    379 	print_debug_sections = section_all;
    380       else if (strcmp (arg, "abbrev") == 0)
    381 	print_debug_sections |= section_abbrev;
    382       else if (strcmp (arg, "aranges") == 0)
    383 	print_debug_sections |= section_aranges;
    384       else if (strcmp (arg, "ranges") == 0)
    385 	{
    386 	  print_debug_sections |= section_ranges;
    387 	  implicit_debug_sections |= section_info;
    388 	}
    389       else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
    390 	print_debug_sections |= section_frame;
    391       else if (strcmp (arg, "info") == 0)
    392 	print_debug_sections |= section_info;
    393       else if (strcmp (arg, "loc") == 0)
    394 	{
    395 	  print_debug_sections |= section_loc;
    396 	  implicit_debug_sections |= section_info;
    397 	}
    398       else if (strcmp (arg, "line") == 0)
    399 	print_debug_sections |= section_line;
    400       else if (strcmp (arg, "pubnames") == 0)
    401 	print_debug_sections |= section_pubnames;
    402       else if (strcmp (arg, "str") == 0)
    403 	print_debug_sections |= section_str;
    404       else if (strcmp (arg, "macinfo") == 0)
    405 	print_debug_sections |= section_macinfo;
    406       else if (strcmp (arg, "exception") == 0)
    407 	print_debug_sections |= section_exception;
    408       else if (strcmp (arg, "gdb_index") == 0)
    409 	print_debug_sections |= section_gdb_index;
    410       else
    411 	{
    412 	  fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
    413 		   arg);
    414 	  argp_help (&argp, stderr, ARGP_HELP_SEE,
    415 		     program_invocation_short_name);
    416 	  exit (1);
    417 	}
    418       any_control_option = true;
    419       break;
    420     case 'p':
    421       any_control_option = true;
    422       if (arg == NULL)
    423 	{
    424 	  print_string_sections = true;
    425 	  break;
    426 	}
    427       /* Fall through.  */
    428     case 'x':
    429       add_dump_section (arg, false);
    430       any_control_option = true;
    431       break;
    432     case 'N':
    433       print_address_names = false;
    434       break;
    435     case ARGP_KEY_NO_ARGS:
    436       fputs (gettext ("Missing file name.\n"), stderr);
    437       goto do_argp_help;
    438     case ARGP_KEY_FINI:
    439       if (! any_control_option && ! print_archive_index)
    440 	{
    441 	  fputs (gettext ("No operation specified.\n"), stderr);
    442 	do_argp_help:
    443 	  argp_help (&argp, stderr, ARGP_HELP_SEE,
    444 		     program_invocation_short_name);
    445 	  exit (EXIT_FAILURE);
    446 	}
    447       break;
    448     case 'W':			/* Ignored.  */
    449       break;
    450     default:
    451       return ARGP_ERR_UNKNOWN;
    452     }
    453   return 0;
    454 }
    455 
    456 
    457 /* Print the version information.  */
    458 static void
    459 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
    460 {
    461   fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
    462   fprintf (stream, gettext ("\
    463 Copyright (C) %s Red Hat, Inc.\n\
    464 This is free software; see the source for copying conditions.  There is NO\n\
    465 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
    466 "), "2012");
    467   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
    468 }
    469 
    470 
    471 /* Check if the file is an archive, and if so dump its index.  */
    472 static void
    473 check_archive_index (int fd, const char *fname, bool only_one)
    474 {
    475   /* Create an `Elf' descriptor.  */
    476   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
    477   if (elf == NULL)
    478     error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
    479 	   elf_errmsg (-1));
    480   else
    481     {
    482       if (elf_kind (elf) == ELF_K_AR)
    483 	{
    484 	  if (!only_one)
    485 	    printf ("\n%s:\n\n", fname);
    486 	  dump_archive_index (elf, fname);
    487 	}
    488       else
    489 	error (0, 0,
    490 	       gettext ("'%s' is not an archive, cannot print archive index"),
    491 	       fname);
    492 
    493       /* Now we can close the descriptor.  */
    494       if (elf_end (elf) != 0)
    495 	error (0, 0, gettext ("error while closing Elf descriptor: %s"),
    496 	       elf_errmsg (-1));
    497     }
    498 }
    499 
    500 /* Trivial callback used for checking if we opened an archive.  */
    501 static int
    502 count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
    503 	       void **userdata __attribute__ ((unused)),
    504 	       const char *name __attribute__ ((unused)),
    505 	       Dwarf_Addr base __attribute__ ((unused)),
    506 	       void *arg)
    507 {
    508   if (*(bool *) arg)
    509     return DWARF_CB_ABORT;
    510   *(bool *) arg = true;
    511   return DWARF_CB_OK;
    512 }
    513 
    514 struct process_dwflmod_args
    515 {
    516   int fd;
    517   bool only_one;
    518 };
    519 
    520 static int
    521 process_dwflmod (Dwfl_Module *dwflmod,
    522 		 void **userdata __attribute__ ((unused)),
    523 		 const char *name __attribute__ ((unused)),
    524 		 Dwarf_Addr base __attribute__ ((unused)),
    525 		 void *arg)
    526 {
    527   const struct process_dwflmod_args *a = arg;
    528 
    529   /* Print the file name.  */
    530   if (!a->only_one)
    531     {
    532       const char *fname;
    533       dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
    534 
    535       printf ("\n%s:\n\n", fname);
    536     }
    537 
    538   process_elf_file (dwflmod, a->fd);
    539 
    540   return DWARF_CB_OK;
    541 }
    542 
    543 /* Stub libdwfl callback, only the ELF handle already open is ever used.  */
    544 static int
    545 find_no_debuginfo (Dwfl_Module *mod __attribute__ ((unused)),
    546 		   void **userdata __attribute__ ((unused)),
    547 		   const char *modname __attribute__ ((unused)),
    548 		   Dwarf_Addr base __attribute__ ((unused)),
    549 		   const char *file_name __attribute__ ((unused)),
    550 		   const char *debuglink_file __attribute__ ((unused)),
    551 		   GElf_Word debuglink_crc __attribute__ ((unused)),
    552 		   char **debuginfo_file_name __attribute__ ((unused)))
    553 {
    554   return -1;
    555 }
    556 
    557 /* Process one input file.  */
    558 static void
    559 process_file (int fd, const char *fname, bool only_one)
    560 {
    561   if (print_archive_index)
    562     check_archive_index (fd, fname, only_one);
    563 
    564   if (!any_control_option)
    565     return;
    566 
    567   /* Duplicate an fd for dwfl_report_offline to swallow.  */
    568   int dwfl_fd = dup (fd);
    569   if (unlikely (dwfl_fd < 0))
    570     error (EXIT_FAILURE, errno, "dup");
    571 
    572   /* Use libdwfl in a trivial way to open the libdw handle for us.
    573      This takes care of applying relocations to DWARF data in ET_REL files.  */
    574   static const Dwfl_Callbacks callbacks =
    575     {
    576       .section_address = dwfl_offline_section_address,
    577       .find_debuginfo = find_no_debuginfo
    578     };
    579   Dwfl *dwfl = dwfl_begin (&callbacks);
    580   if (likely (dwfl != NULL))
    581     /* Let 0 be the logical address of the file (or first in archive).  */
    582     dwfl->offline_next_address = 0;
    583   if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
    584     {
    585       struct stat64 st;
    586       if (fstat64 (dwfl_fd, &st) != 0)
    587 	error (0, errno, gettext ("cannot stat input file"));
    588       else if (unlikely (st.st_size == 0))
    589 	error (0, 0, gettext ("input file is empty"));
    590       else
    591 	error (0, 0, gettext ("failed reading '%s': %s"),
    592 	       fname, dwfl_errmsg (-1));
    593       close (dwfl_fd);		/* Consumed on success, not on failure.  */
    594     }
    595   else
    596     {
    597       dwfl_report_end (dwfl, NULL, NULL);
    598 
    599       if (only_one)
    600 	{
    601 	  /* Clear ONLY_ONE if we have multiple modules, from an archive.  */
    602 	  bool seen = false;
    603 	  only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
    604 	}
    605 
    606       /* Process the one or more modules gleaned from this file.  */
    607       struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
    608       dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
    609     }
    610   dwfl_end (dwfl);
    611 }
    612 
    613 
    614 /* Process one ELF file.  */
    615 static void
    616 process_elf_file (Dwfl_Module *dwflmod, int fd)
    617 {
    618   GElf_Addr dwflbias;
    619   Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
    620 
    621   GElf_Ehdr ehdr_mem;
    622   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
    623 
    624   if (ehdr == NULL)
    625     {
    626     elf_error:
    627       error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
    628       return;
    629     }
    630 
    631   Ebl *ebl = ebl_openbackend (elf);
    632   if (unlikely (ebl == NULL))
    633     {
    634     ebl_error:
    635       error (0, errno, gettext ("cannot create EBL handle"));
    636       return;
    637     }
    638 
    639   /* Determine the number of sections.  */
    640   if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
    641     error (EXIT_FAILURE, 0,
    642 	   gettext ("cannot determine number of sections: %s"),
    643 	   elf_errmsg (-1));
    644 
    645   /* Determine the number of phdrs.  */
    646   if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
    647     error (EXIT_FAILURE, 0,
    648 	   gettext ("cannot determine number of program headers: %s"),
    649 	   elf_errmsg (-1));
    650 
    651   /* For an ET_REL file, libdwfl has adjusted the in-core shdrs
    652      and may have applied relocation to some sections.
    653      So we need to get a fresh Elf handle on the file to display those.  */
    654   bool print_unrelocated = (print_section_header
    655 			    || print_relocations
    656 			    || dump_data_sections != NULL
    657 			    || print_notes);
    658 
    659   Elf *pure_elf = NULL;
    660   Ebl *pure_ebl = ebl;
    661   if (ehdr->e_type == ET_REL && print_unrelocated)
    662     {
    663       /* Read the file afresh.  */
    664       off64_t aroff = elf_getaroff (elf);
    665       pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
    666       if (aroff > 0)
    667 	{
    668 	  /* Archive member.  */
    669 	  (void) elf_rand (pure_elf, aroff);
    670 	  Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
    671 	  elf_end (pure_elf);
    672 	  pure_elf = armem;
    673 	}
    674       if (pure_elf == NULL)
    675 	goto elf_error;
    676       pure_ebl = ebl_openbackend (pure_elf);
    677       if (pure_ebl == NULL)
    678 	goto ebl_error;
    679     }
    680 
    681   if (print_file_header)
    682     print_ehdr (ebl, ehdr);
    683   if (print_section_header)
    684     print_shdr (pure_ebl, ehdr);
    685   if (print_program_header)
    686     print_phdr (ebl, ehdr);
    687   if (print_section_groups)
    688     print_scngrp (ebl);
    689   if (print_dynamic_table)
    690     print_dynamic (ebl);
    691   if (print_relocations)
    692     print_relocs (pure_ebl, ehdr);
    693   if (print_histogram)
    694     handle_hash (ebl);
    695   if (print_symbol_table)
    696     print_symtab (ebl, SHT_DYNSYM);
    697   if (print_version_info)
    698     print_verinfo (ebl);
    699   if (print_symbol_table)
    700     print_symtab (ebl, SHT_SYMTAB);
    701   if (print_arch)
    702     print_liblist (ebl);
    703   if (print_arch)
    704     print_attributes (ebl, ehdr);
    705   if (dump_data_sections != NULL)
    706     dump_data (pure_ebl);
    707   if (string_sections != NULL)
    708     dump_strings (ebl);
    709   if ((print_debug_sections | implicit_debug_sections) != 0)
    710     print_debug (dwflmod, ebl, ehdr);
    711   if (print_notes)
    712     handle_notes (pure_ebl, ehdr);
    713   if (print_string_sections)
    714     print_strings (ebl);
    715 
    716   ebl_closebackend (ebl);
    717 
    718   if (pure_ebl != ebl)
    719     {
    720       ebl_closebackend (pure_ebl);
    721       elf_end (pure_elf);
    722     }
    723 }
    724 
    725 
    726 /* Print file type.  */
    727 static void
    728 print_file_type (unsigned short int e_type)
    729 {
    730   if (likely (e_type <= ET_CORE))
    731     {
    732       static const char *const knowntypes[] =
    733       {
    734 	N_("NONE (None)"),
    735 	N_("REL (Relocatable file)"),
    736 	N_("EXEC (Executable file)"),
    737 	N_("DYN (Shared object file)"),
    738 	N_("CORE (Core file)")
    739       };
    740       puts (gettext (knowntypes[e_type]));
    741     }
    742   else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
    743     printf (gettext ("OS Specific: (%x)\n"),  e_type);
    744   else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
    745     printf (gettext ("Processor Specific: (%x)\n"),  e_type);
    746   else
    747     puts ("???");
    748 }
    749 
    750 
    751 /* Print ELF header.  */
    752 static void
    753 print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
    754 {
    755   fputs_unlocked (gettext ("ELF Header:\n  Magic:  "), stdout);
    756   for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
    757     printf (" %02hhx", ehdr->e_ident[cnt]);
    758 
    759   printf (gettext ("\n  Class:                             %s\n"),
    760 	  ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
    761 	  : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
    762 	  : "\?\?\?");
    763 
    764   printf (gettext ("  Data:                              %s\n"),
    765 	  ehdr->e_ident[EI_DATA] == ELFDATA2LSB
    766 	  ? "2's complement, little endian"
    767 	  : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
    768 	  ? "2's complement, big endian" : "\?\?\?");
    769 
    770   printf (gettext ("  Ident Version:                     %hhd %s\n"),
    771 	  ehdr->e_ident[EI_VERSION],
    772 	  ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
    773 	  : "(\?\?\?)");
    774 
    775   char buf[512];
    776   printf (gettext ("  OS/ABI:                            %s\n"),
    777 	  ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
    778 
    779   printf (gettext ("  ABI Version:                       %hhd\n"),
    780 	  ehdr->e_ident[EI_ABIVERSION]);
    781 
    782   fputs_unlocked (gettext ("  Type:                              "), stdout);
    783   print_file_type (ehdr->e_type);
    784 
    785   printf (gettext ("  Machine:                           %s\n"), ebl->name);
    786 
    787   printf (gettext ("  Version:                           %d %s\n"),
    788 	  ehdr->e_version,
    789 	  ehdr->e_version  == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
    790 
    791   printf (gettext ("  Entry point address:               %#" PRIx64 "\n"),
    792 	  ehdr->e_entry);
    793 
    794   printf (gettext ("  Start of program headers:          %" PRId64 " %s\n"),
    795 	  ehdr->e_phoff, gettext ("(bytes into file)"));
    796 
    797   printf (gettext ("  Start of section headers:          %" PRId64 " %s\n"),
    798 	  ehdr->e_shoff, gettext ("(bytes into file)"));
    799 
    800   printf (gettext ("  Flags:                             %s\n"),
    801 	  ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
    802 
    803   printf (gettext ("  Size of this header:               %" PRId16 " %s\n"),
    804 	  ehdr->e_ehsize, gettext ("(bytes)"));
    805 
    806   printf (gettext ("  Size of program header entries:    %" PRId16 " %s\n"),
    807 	  ehdr->e_phentsize, gettext ("(bytes)"));
    808 
    809   printf (gettext ("  Number of program headers entries: %" PRId16),
    810 	  ehdr->e_phnum);
    811   if (ehdr->e_phnum == PN_XNUM)
    812     {
    813       GElf_Shdr shdr_mem;
    814       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
    815       if (shdr != NULL)
    816 	printf (gettext (" (%" PRIu32 " in [0].sh_info)"),
    817 		(uint32_t) shdr->sh_info);
    818       else
    819 	fputs_unlocked (gettext (" ([0] not available)"), stdout);
    820     }
    821   fputc_unlocked ('\n', stdout);
    822 
    823   printf (gettext ("  Size of section header entries:    %" PRId16 " %s\n"),
    824 	  ehdr->e_shentsize, gettext ("(bytes)"));
    825 
    826   printf (gettext ("  Number of section headers entries: %" PRId16),
    827 	  ehdr->e_shnum);
    828   if (ehdr->e_shnum == 0)
    829     {
    830       GElf_Shdr shdr_mem;
    831       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
    832       if (shdr != NULL)
    833 	printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
    834 		(uint32_t) shdr->sh_size);
    835       else
    836 	fputs_unlocked (gettext (" ([0] not available)"), stdout);
    837     }
    838   fputc_unlocked ('\n', stdout);
    839 
    840   if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
    841     {
    842       GElf_Shdr shdr_mem;
    843       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
    844       if (shdr != NULL)
    845 	/* We managed to get the zeroth section.  */
    846 	snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
    847 		  (uint32_t) shdr->sh_link);
    848       else
    849 	{
    850 	  strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
    851 	  buf[sizeof (buf) - 1] = '\0';
    852 	}
    853 
    854       printf (gettext ("  Section header string table index: XINDEX%s\n\n"),
    855 	      buf);
    856     }
    857   else
    858     printf (gettext ("  Section header string table index: %" PRId16 "\n\n"),
    859 	    ehdr->e_shstrndx);
    860 }
    861 
    862 
    863 static const char *
    864 get_visibility_type (int value)
    865 {
    866   switch (value)
    867     {
    868     case STV_DEFAULT:
    869       return "DEFAULT";
    870     case STV_INTERNAL:
    871       return "INTERNAL";
    872     case STV_HIDDEN:
    873       return "HIDDEN";
    874     case STV_PROTECTED:
    875       return "PROTECTED";
    876     default:
    877       return "???";
    878     }
    879 }
    880 
    881 
    882 /* Print the section headers.  */
    883 static void
    884 print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
    885 {
    886   size_t cnt;
    887   size_t shstrndx;
    888 
    889   if (! print_file_header)
    890     printf (gettext ("\
    891 There are %d section headers, starting at offset %#" PRIx64 ":\n\
    892 \n"),
    893 	    ehdr->e_shnum, ehdr->e_shoff);
    894 
    895   /* Get the section header string table index.  */
    896   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    897     error (EXIT_FAILURE, 0,
    898 	   gettext ("cannot get section header string table index"));
    899 
    900   puts (gettext ("Section Headers:"));
    901 
    902   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
    903     puts (gettext ("[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al"));
    904   else
    905     puts (gettext ("[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al"));
    906 
    907   for (cnt = 0; cnt < shnum; ++cnt)
    908     {
    909       Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
    910 
    911       if (unlikely (scn == NULL))
    912 	error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
    913 	       elf_errmsg (-1));
    914 
    915       /* Get the section header.  */
    916       GElf_Shdr shdr_mem;
    917       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    918       if (unlikely (shdr == NULL))
    919 	error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
    920 	       elf_errmsg (-1));
    921 
    922       char flagbuf[20];
    923       char *cp = flagbuf;
    924       if (shdr->sh_flags & SHF_WRITE)
    925 	*cp++ = 'W';
    926       if (shdr->sh_flags & SHF_ALLOC)
    927 	*cp++ = 'A';
    928       if (shdr->sh_flags & SHF_EXECINSTR)
    929 	*cp++ = 'X';
    930       if (shdr->sh_flags & SHF_MERGE)
    931 	*cp++ = 'M';
    932       if (shdr->sh_flags & SHF_STRINGS)
    933 	*cp++ = 'S';
    934       if (shdr->sh_flags & SHF_INFO_LINK)
    935 	*cp++ = 'I';
    936       if (shdr->sh_flags & SHF_LINK_ORDER)
    937 	*cp++ = 'L';
    938       if (shdr->sh_flags & SHF_OS_NONCONFORMING)
    939 	*cp++ = 'N';
    940       if (shdr->sh_flags & SHF_GROUP)
    941 	*cp++ = 'G';
    942       if (shdr->sh_flags & SHF_TLS)
    943 	*cp++ = 'T';
    944       if (shdr->sh_flags & SHF_ORDERED)
    945 	*cp++ = 'O';
    946       if (shdr->sh_flags & SHF_EXCLUDE)
    947 	*cp++ = 'E';
    948       *cp = '\0';
    949 
    950       char buf[128];
    951       printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
    952 	      " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
    953 	      " %2" PRId64 "\n",
    954 	      cnt,
    955 	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
    956 	      ?: "<corrupt>",
    957 	      ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
    958 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
    959 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
    960 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
    961 	      shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
    962 	      shdr->sh_addralign);
    963     }
    964 
    965   fputc_unlocked ('\n', stdout);
    966 }
    967 
    968 
    969 /* Print the program header.  */
    970 static void
    971 print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
    972 {
    973   if (ehdr->e_phnum == 0)
    974     /* No program header, this is OK in relocatable objects.  */
    975     return;
    976 
    977   puts (gettext ("Program Headers:"));
    978   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
    979     puts (gettext ("\
    980   Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"));
    981   else
    982     puts (gettext ("\
    983   Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align"));
    984 
    985   /* Process all program headers.  */
    986   bool has_relro = false;
    987   GElf_Addr relro_from = 0;
    988   GElf_Addr relro_to = 0;
    989   for (size_t cnt = 0; cnt < phnum; ++cnt)
    990     {
    991       char buf[128];
    992       GElf_Phdr mem;
    993       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
    994 
    995       /* If for some reason the header cannot be returned show this.  */
    996       if (unlikely (phdr == NULL))
    997 	{
    998 	  puts ("  ???");
    999 	  continue;
   1000 	}
   1001 
   1002       printf ("  %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
   1003 	      " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
   1004 	      ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
   1005 	      phdr->p_offset,
   1006 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
   1007 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
   1008 	      phdr->p_filesz,
   1009 	      phdr->p_memsz,
   1010 	      phdr->p_flags & PF_R ? 'R' : ' ',
   1011 	      phdr->p_flags & PF_W ? 'W' : ' ',
   1012 	      phdr->p_flags & PF_X ? 'E' : ' ',
   1013 	      phdr->p_align);
   1014 
   1015       if (phdr->p_type == PT_INTERP)
   1016 	{
   1017 	  /* We can show the user the name of the interpreter.  */
   1018 	  size_t maxsize;
   1019 	  char *filedata = elf_rawfile (ebl->elf, &maxsize);
   1020 
   1021 	  if (filedata != NULL && phdr->p_offset < maxsize)
   1022 	    printf (gettext ("\t[Requesting program interpreter: %s]\n"),
   1023 		    filedata + phdr->p_offset);
   1024 	}
   1025       else if (phdr->p_type == PT_GNU_RELRO)
   1026 	{
   1027 	  has_relro = true;
   1028 	  relro_from = phdr->p_vaddr;
   1029 	  relro_to = relro_from + phdr->p_memsz;
   1030 	}
   1031     }
   1032 
   1033   if (ehdr->e_shnum == 0)
   1034     /* No sections in the file.  Punt.  */
   1035     return;
   1036 
   1037   /* Get the section header string table index.  */
   1038   size_t shstrndx;
   1039   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   1040     error (EXIT_FAILURE, 0,
   1041 	   gettext ("cannot get section header string table index"));
   1042 
   1043   puts (gettext ("\n Section to Segment mapping:\n  Segment Sections..."));
   1044 
   1045   for (size_t cnt = 0; cnt < phnum; ++cnt)
   1046     {
   1047       /* Print the segment number.  */
   1048       printf ("   %2.2zu     ", cnt);
   1049 
   1050       GElf_Phdr phdr_mem;
   1051       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
   1052       /* This must not happen.  */
   1053       if (unlikely (phdr == NULL))
   1054 	error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
   1055 	       elf_errmsg (-1));
   1056 
   1057       /* Iterate over the sections.  */
   1058       bool in_relro = false;
   1059       bool in_ro = false;
   1060       for (size_t inner = 1; inner < shnum; ++inner)
   1061 	{
   1062 	  Elf_Scn *scn = elf_getscn (ebl->elf, inner);
   1063 	  /* This should not happen.  */
   1064 	  if (unlikely (scn == NULL))
   1065 	    error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
   1066 		   elf_errmsg (-1));
   1067 
   1068 	  /* Get the section header.  */
   1069 	  GElf_Shdr shdr_mem;
   1070 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1071 	  if (unlikely (shdr == NULL))
   1072 	    error (EXIT_FAILURE, 0,
   1073 		   gettext ("cannot get section header: %s"),
   1074 		   elf_errmsg (-1));
   1075 
   1076 	  if (shdr->sh_size > 0
   1077 	      /* Compare allocated sections by VMA, unallocated
   1078 		 sections by file offset.  */
   1079 	      && (shdr->sh_flags & SHF_ALLOC
   1080 		  ? (shdr->sh_addr >= phdr->p_vaddr
   1081 		     && (shdr->sh_addr + shdr->sh_size
   1082 			 <= phdr->p_vaddr + phdr->p_memsz))
   1083 		  : (shdr->sh_offset >= phdr->p_offset
   1084 		     && (shdr->sh_offset + shdr->sh_size
   1085 			 <= phdr->p_offset + phdr->p_filesz))))
   1086 	    {
   1087 	      if (has_relro && !in_relro
   1088 		  && shdr->sh_addr >= relro_from
   1089 		  && shdr->sh_addr + shdr->sh_size <= relro_to)
   1090 		{
   1091 		  fputs_unlocked (" [RELRO:", stdout);
   1092 		  in_relro = true;
   1093 		}
   1094 	      else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
   1095 		{
   1096 		  fputs_unlocked ("]", stdout);
   1097 		  in_relro =  false;
   1098 		}
   1099 	      else if (has_relro && in_relro
   1100 		       && shdr->sh_addr + shdr->sh_size > relro_to)
   1101 		fputs_unlocked ("] <RELRO:", stdout);
   1102 	      else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
   1103 		{
   1104 		  if (!in_ro)
   1105 		    {
   1106 		      fputs_unlocked (" [RO:", stdout);
   1107 		      in_ro = true;
   1108 		    }
   1109 		}
   1110 	      else
   1111 		{
   1112 		  /* Determine the segment this section is part of.  */
   1113 		  size_t cnt2;
   1114 		  GElf_Phdr *phdr2 = NULL;
   1115 		  for (cnt2 = 0; cnt2 < phnum; ++cnt2)
   1116 		    {
   1117 		      GElf_Phdr phdr2_mem;
   1118 		      phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
   1119 
   1120 		      if (phdr2 != NULL && phdr2->p_type == PT_LOAD
   1121 			  && shdr->sh_addr >= phdr2->p_vaddr
   1122 			  && (shdr->sh_addr + shdr->sh_size
   1123 			      <= phdr2->p_vaddr + phdr2->p_memsz))
   1124 			break;
   1125 		    }
   1126 
   1127 		  if (cnt2 < phnum)
   1128 		    {
   1129 		      if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
   1130 			{
   1131 			  fputs_unlocked (" [RO:", stdout);
   1132 			  in_ro = true;
   1133 			}
   1134 		      else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
   1135 			{
   1136 			  fputs_unlocked ("]", stdout);
   1137 			  in_ro = false;
   1138 			}
   1139 		    }
   1140 		}
   1141 
   1142 	      printf (" %s",
   1143 		      elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
   1144 
   1145 	      /* Signal that this sectin is only partially covered.  */
   1146 	      if (has_relro && in_relro
   1147 		       && shdr->sh_addr + shdr->sh_size > relro_to)
   1148 		{
   1149 		  fputs_unlocked (">", stdout);
   1150 		  in_relro =  false;
   1151 		}
   1152 	    }
   1153 	}
   1154       if (in_relro || in_ro)
   1155 	fputs_unlocked ("]", stdout);
   1156 
   1157       /* Finish the line.  */
   1158       fputc_unlocked ('\n', stdout);
   1159     }
   1160 }
   1161 
   1162 
   1163 static const char *
   1164 section_name (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr)
   1165 {
   1166   return elf_strptr (ebl->elf, ehdr->e_shstrndx, shdr->sh_name) ?: "???";
   1167 }
   1168 
   1169 
   1170 static void
   1171 handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   1172 {
   1173   /* Get the data of the section.  */
   1174   Elf_Data *data = elf_getdata (scn, NULL);
   1175 
   1176   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
   1177   GElf_Shdr symshdr_mem;
   1178   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
   1179   Elf_Data *symdata = elf_getdata (symscn, NULL);
   1180 
   1181   if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
   1182       || symdata == NULL)
   1183     return;
   1184 
   1185   /* Get the section header string table index.  */
   1186   size_t shstrndx;
   1187   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   1188     error (EXIT_FAILURE, 0,
   1189 	   gettext ("cannot get section header string table index"));
   1190 
   1191   Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
   1192 
   1193   GElf_Sym sym_mem;
   1194   printf ((grpref[0] & GRP_COMDAT)
   1195 	  ? ngettext ("\
   1196 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
   1197 		      "\
   1198 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
   1199 		      data->d_size / sizeof (Elf32_Word) - 1)
   1200 	  : ngettext ("\
   1201 \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
   1202 \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
   1203 		      data->d_size / sizeof (Elf32_Word) - 1),
   1204 	  elf_ndxscn (scn),
   1205 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   1206 	  elf_strptr (ebl->elf, symshdr->sh_link,
   1207 		      gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name)
   1208 	  ?: gettext ("<INVALID SYMBOL>"),
   1209 	  data->d_size / sizeof (Elf32_Word) - 1);
   1210 
   1211   for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
   1212     {
   1213       GElf_Shdr grpshdr_mem;
   1214       GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
   1215 					 &grpshdr_mem);
   1216 
   1217       const char *str;
   1218       printf ("  [%2u] %s\n",
   1219 	      grpref[cnt],
   1220 	      grpshdr != NULL
   1221 	      && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
   1222 	      ? str : gettext ("<INVALID SECTION>"));
   1223     }
   1224 }
   1225 
   1226 
   1227 static void
   1228 print_scngrp (Ebl *ebl)
   1229 {
   1230   /* Find all relocation sections and handle them.  */
   1231   Elf_Scn *scn = NULL;
   1232 
   1233   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   1234     {
   1235        /* Handle the section if it is a symbol table.  */
   1236       GElf_Shdr shdr_mem;
   1237       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1238 
   1239       if (shdr != NULL && shdr->sh_type == SHT_GROUP)
   1240 	handle_scngrp (ebl, scn, shdr);
   1241     }
   1242 }
   1243 
   1244 
   1245 static const struct flags
   1246 {
   1247   int mask;
   1248   const char *str;
   1249 } dt_flags[] =
   1250   {
   1251     { DF_ORIGIN, "ORIGIN" },
   1252     { DF_SYMBOLIC, "SYMBOLIC" },
   1253     { DF_TEXTREL, "TEXTREL" },
   1254     { DF_BIND_NOW, "BIND_NOW" },
   1255     { DF_STATIC_TLS, "STATIC_TLS" }
   1256   };
   1257 static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
   1258 
   1259 static const struct flags dt_flags_1[] =
   1260   {
   1261     { DF_1_NOW, "NOW" },
   1262     { DF_1_GLOBAL, "GLOBAL" },
   1263     { DF_1_GROUP, "GROUP" },
   1264     { DF_1_NODELETE, "NODELETE" },
   1265     { DF_1_LOADFLTR, "LOADFLTR" },
   1266     { DF_1_INITFIRST, "INITFIRST" },
   1267     { DF_1_NOOPEN, "NOOPEN" },
   1268     { DF_1_ORIGIN, "ORIGIN" },
   1269     { DF_1_DIRECT, "DIRECT" },
   1270     { DF_1_TRANS, "TRANS" },
   1271     { DF_1_INTERPOSE, "INTERPOSE" },
   1272     { DF_1_NODEFLIB, "NODEFLIB" },
   1273     { DF_1_NODUMP, "NODUMP" },
   1274     { DF_1_CONFALT, "CONFALT" },
   1275     { DF_1_ENDFILTEE, "ENDFILTEE" },
   1276     { DF_1_DISPRELDNE, "DISPRELDNE" },
   1277     { DF_1_DISPRELPND, "DISPRELPND" },
   1278   };
   1279 static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
   1280 
   1281 static const struct flags dt_feature_1[] =
   1282   {
   1283     { DTF_1_PARINIT, "PARINIT" },
   1284     { DTF_1_CONFEXP, "CONFEXP" }
   1285   };
   1286 static const int ndt_feature_1 = (sizeof (dt_feature_1)
   1287 				  / sizeof (dt_feature_1[0]));
   1288 
   1289 static const struct flags dt_posflag_1[] =
   1290   {
   1291     { DF_P1_LAZYLOAD, "LAZYLOAD" },
   1292     { DF_P1_GROUPPERM, "GROUPPERM" }
   1293   };
   1294 static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
   1295 				  / sizeof (dt_posflag_1[0]));
   1296 
   1297 
   1298 static void
   1299 print_flags (int class, GElf_Xword d_val, const struct flags *flags,
   1300 		int nflags)
   1301 {
   1302   bool first = true;
   1303   int cnt;
   1304 
   1305   for (cnt = 0; cnt < nflags; ++cnt)
   1306     if (d_val & flags[cnt].mask)
   1307       {
   1308 	if (!first)
   1309 	  putchar_unlocked (' ');
   1310 	fputs_unlocked (flags[cnt].str, stdout);
   1311 	d_val &= ~flags[cnt].mask;
   1312 	first = false;
   1313       }
   1314 
   1315   if (d_val != 0)
   1316     {
   1317       if (!first)
   1318 	putchar_unlocked (' ');
   1319       printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
   1320     }
   1321 
   1322   putchar_unlocked ('\n');
   1323 }
   1324 
   1325 
   1326 static void
   1327 print_dt_flags (int class, GElf_Xword d_val)
   1328 {
   1329   print_flags (class, d_val, dt_flags, ndt_flags);
   1330 }
   1331 
   1332 
   1333 static void
   1334 print_dt_flags_1 (int class, GElf_Xword d_val)
   1335 {
   1336   print_flags (class, d_val, dt_flags_1, ndt_flags_1);
   1337 }
   1338 
   1339 
   1340 static void
   1341 print_dt_feature_1 (int class, GElf_Xword d_val)
   1342 {
   1343   print_flags (class, d_val, dt_feature_1, ndt_feature_1);
   1344 }
   1345 
   1346 
   1347 static void
   1348 print_dt_posflag_1 (int class, GElf_Xword d_val)
   1349 {
   1350   print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
   1351 }
   1352 
   1353 
   1354 static void
   1355 handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   1356 {
   1357   int class = gelf_getclass (ebl->elf);
   1358   GElf_Shdr glink;
   1359   Elf_Data *data;
   1360   size_t cnt;
   1361   size_t shstrndx;
   1362 
   1363   /* Get the data of the section.  */
   1364   data = elf_getdata (scn, NULL);
   1365   if (data == NULL)
   1366     return;
   1367 
   1368   /* Get the section header string table index.  */
   1369   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   1370     error (EXIT_FAILURE, 0,
   1371 	   gettext ("cannot get section header string table index"));
   1372 
   1373   printf (ngettext ("\
   1374 \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   1375 		    "\
   1376 \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   1377 		    shdr->sh_size / shdr->sh_entsize),
   1378 	  (unsigned long int) (shdr->sh_size / shdr->sh_entsize),
   1379 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   1380 	  shdr->sh_offset,
   1381 	  (int) shdr->sh_link,
   1382 	  elf_strptr (ebl->elf, shstrndx,
   1383 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   1384 				    &glink)->sh_name));
   1385   fputs_unlocked (gettext ("  Type              Value\n"), stdout);
   1386 
   1387   for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
   1388     {
   1389       GElf_Dyn dynmem;
   1390       GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
   1391       if (dyn == NULL)
   1392 	break;
   1393 
   1394       char buf[64];
   1395       printf ("  %-17s ",
   1396 	      ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
   1397 
   1398       switch (dyn->d_tag)
   1399 	{
   1400 	case DT_NULL:
   1401 	case DT_DEBUG:
   1402 	case DT_BIND_NOW:
   1403 	case DT_TEXTREL:
   1404 	  /* No further output.  */
   1405 	  fputc_unlocked ('\n', stdout);
   1406 	  break;
   1407 
   1408 	case DT_NEEDED:
   1409 	  printf (gettext ("Shared library: [%s]\n"),
   1410 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1411 	  break;
   1412 
   1413 	case DT_SONAME:
   1414 	  printf (gettext ("Library soname: [%s]\n"),
   1415 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1416 	  break;
   1417 
   1418 	case DT_RPATH:
   1419 	  printf (gettext ("Library rpath: [%s]\n"),
   1420 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1421 	  break;
   1422 
   1423 	case DT_RUNPATH:
   1424 	  printf (gettext ("Library runpath: [%s]\n"),
   1425 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1426 	  break;
   1427 
   1428 	case DT_PLTRELSZ:
   1429 	case DT_RELASZ:
   1430 	case DT_STRSZ:
   1431 	case DT_RELSZ:
   1432 	case DT_RELAENT:
   1433 	case DT_SYMENT:
   1434 	case DT_RELENT:
   1435 	case DT_PLTPADSZ:
   1436 	case DT_MOVEENT:
   1437 	case DT_MOVESZ:
   1438 	case DT_INIT_ARRAYSZ:
   1439 	case DT_FINI_ARRAYSZ:
   1440 	case DT_SYMINSZ:
   1441 	case DT_SYMINENT:
   1442 	case DT_GNU_CONFLICTSZ:
   1443 	case DT_GNU_LIBLISTSZ:
   1444 	  printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
   1445 	  break;
   1446 
   1447 	case DT_VERDEFNUM:
   1448 	case DT_VERNEEDNUM:
   1449 	case DT_RELACOUNT:
   1450 	case DT_RELCOUNT:
   1451 	  printf ("%" PRId64 "\n", dyn->d_un.d_val);
   1452 	  break;
   1453 
   1454 	case DT_PLTREL:;
   1455 	  const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
   1456 						      NULL, 0);
   1457 	  puts (tagname ?: "???");
   1458 	  break;
   1459 
   1460 	case DT_FLAGS:
   1461 	  print_dt_flags (class, dyn->d_un.d_val);
   1462 	  break;
   1463 
   1464 	case DT_FLAGS_1:
   1465 	  print_dt_flags_1 (class, dyn->d_un.d_val);
   1466 	  break;
   1467 
   1468 	case DT_FEATURE_1:
   1469 	  print_dt_feature_1 (class, dyn->d_un.d_val);
   1470 	  break;
   1471 
   1472 	case DT_POSFLAG_1:
   1473 	  print_dt_posflag_1 (class, dyn->d_un.d_val);
   1474 	  break;
   1475 
   1476 	default:
   1477 	  printf ("%#0*" PRIx64 "\n",
   1478 		  class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
   1479 	  break;
   1480 	}
   1481     }
   1482 }
   1483 
   1484 
   1485 /* Print the dynamic segment.  */
   1486 static void
   1487 print_dynamic (Ebl *ebl)
   1488 {
   1489   for (size_t i = 0; i < phnum; ++i)
   1490     {
   1491       GElf_Phdr phdr_mem;
   1492       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
   1493 
   1494       if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
   1495 	{
   1496 	  Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
   1497 	  GElf_Shdr shdr_mem;
   1498 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1499 	  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
   1500 	    handle_dynamic (ebl, scn, shdr);
   1501 	  break;
   1502 	}
   1503     }
   1504 }
   1505 
   1506 
   1507 /* Print relocations.  */
   1508 static void
   1509 print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
   1510 {
   1511   /* Find all relocation sections and handle them.  */
   1512   Elf_Scn *scn = NULL;
   1513 
   1514   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   1515     {
   1516        /* Handle the section if it is a symbol table.  */
   1517       GElf_Shdr shdr_mem;
   1518       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1519 
   1520       if (likely (shdr != NULL))
   1521 	{
   1522 	  if (shdr->sh_type == SHT_REL)
   1523 	    handle_relocs_rel (ebl, ehdr, scn, shdr);
   1524 	  else if (shdr->sh_type == SHT_RELA)
   1525 	    handle_relocs_rela (ebl, ehdr, scn, shdr);
   1526 	}
   1527     }
   1528 }
   1529 
   1530 
   1531 /* Handle a relocation section.  */
   1532 static void
   1533 handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   1534 {
   1535   int class = gelf_getclass (ebl->elf);
   1536   int nentries = shdr->sh_size / shdr->sh_entsize;
   1537 
   1538   /* Get the data of the section.  */
   1539   Elf_Data *data = elf_getdata (scn, NULL);
   1540   if (data == NULL)
   1541     return;
   1542 
   1543   /* Get the symbol table information.  */
   1544   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
   1545   GElf_Shdr symshdr_mem;
   1546   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
   1547   Elf_Data *symdata = elf_getdata (symscn, NULL);
   1548 
   1549   /* Get the section header of the section the relocations are for.  */
   1550   GElf_Shdr destshdr_mem;
   1551   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
   1552 				      &destshdr_mem);
   1553 
   1554   if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
   1555     {
   1556       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
   1557 	      shdr->sh_offset);
   1558       return;
   1559     }
   1560 
   1561   /* Search for the optional extended section index table.  */
   1562   Elf_Data *xndxdata = NULL;
   1563   int xndxscnidx = elf_scnshndx (scn);
   1564   if (unlikely (xndxscnidx > 0))
   1565     xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
   1566 
   1567   /* Get the section header string table index.  */
   1568   size_t shstrndx;
   1569   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   1570     error (EXIT_FAILURE, 0,
   1571 	   gettext ("cannot get section header string table index"));
   1572 
   1573   if (shdr->sh_info != 0)
   1574     printf (ngettext ("\
   1575 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   1576 		    "\
   1577 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   1578 		      nentries),
   1579 	    elf_ndxscn (scn),
   1580 	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   1581 	    (unsigned int) shdr->sh_info,
   1582 	    elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
   1583 	    shdr->sh_offset,
   1584 	    nentries);
   1585   else
   1586     /* The .rel.dyn section does not refer to a specific section but
   1587        instead of section index zero.  Do not try to print a section
   1588        name.  */
   1589     printf (ngettext ("\
   1590 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   1591 		    "\
   1592 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   1593 		      nentries),
   1594 	    (unsigned int) elf_ndxscn (scn),
   1595 	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   1596 	    shdr->sh_offset,
   1597 	    nentries);
   1598   fputs_unlocked (class == ELFCLASS32
   1599 		  ? gettext ("\
   1600   Offset      Type                 Value       Name\n")
   1601 		  : gettext ("\
   1602   Offset              Type                 Value               Name\n"),
   1603 	 stdout);
   1604 
   1605   int is_statically_linked = 0;
   1606   for (int cnt = 0; cnt < nentries; ++cnt)
   1607     {
   1608       GElf_Rel relmem;
   1609       GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
   1610       if (likely (rel != NULL))
   1611 	{
   1612 	  char buf[128];
   1613 	  GElf_Sym symmem;
   1614 	  Elf32_Word xndx;
   1615 	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
   1616 					    GELF_R_SYM (rel->r_info),
   1617 					    &symmem, &xndx);
   1618 	  if (unlikely (sym == NULL))
   1619 	    {
   1620 	      /* As a special case we have to handle relocations in static
   1621 		 executables.  This only happens for IRELATIVE relocations
   1622 		 (so far).  There is no symbol table.  */
   1623 	      if (is_statically_linked == 0)
   1624 		{
   1625 		  /* Find the program header and look for a PT_INTERP entry. */
   1626 		  is_statically_linked = -1;
   1627 		  if (ehdr->e_type == ET_EXEC)
   1628 		    {
   1629 		      is_statically_linked = 1;
   1630 
   1631 		      for (size_t inner = 0; inner < phnum; ++inner)
   1632 			{
   1633 			  GElf_Phdr phdr_mem;
   1634 			  GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
   1635 							  &phdr_mem);
   1636 			  if (phdr != NULL && phdr->p_type == PT_INTERP)
   1637 			    {
   1638 			      is_statically_linked = -1;
   1639 			      break;
   1640 			    }
   1641 			}
   1642 		    }
   1643 		}
   1644 
   1645 	      if (is_statically_linked > 0 && shdr->sh_link == 0)
   1646 		printf ("\
   1647   %#0*" PRIx64 "  %-20s %*s  %s\n",
   1648 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1649 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1650 			/* Avoid the leading R_ which isn't carrying any
   1651 			   information.  */
   1652 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1653 					       buf, sizeof (buf)) + 2
   1654 			: gettext ("<INVALID RELOC>"),
   1655 			class == ELFCLASS32 ? 10 : 18, "",
   1656 			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
   1657 	      else
   1658 		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
   1659 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1660 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1661 			/* Avoid the leading R_ which isn't carrying any
   1662 			   information.  */
   1663 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1664 					       buf, sizeof (buf)) + 2
   1665 			: gettext ("<INVALID RELOC>"),
   1666 			gettext ("INVALID SYMBOL"),
   1667 			(long int) GELF_R_SYM (rel->r_info));
   1668 	    }
   1669 	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
   1670 	    printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
   1671 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1672 		    likely (ebl_reloc_type_check (ebl,
   1673 						  GELF_R_TYPE (rel->r_info)))
   1674 		    /* Avoid the leading R_ which isn't carrying any
   1675 		       information.  */
   1676 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1677 					   buf, sizeof (buf)) + 2
   1678 		    : gettext ("<INVALID RELOC>"),
   1679 		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
   1680 		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
   1681 	  else
   1682 	    {
   1683 	      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
   1684 						   sym->st_shndx == SHN_XINDEX
   1685 						   ? xndx : sym->st_shndx),
   1686 				       &destshdr_mem);
   1687 
   1688 	      if (unlikely (destshdr == NULL))
   1689 		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
   1690 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1691 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1692 			/* Avoid the leading R_ which isn't carrying any
   1693 			   information.  */
   1694 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1695 					       buf, sizeof (buf)) + 2
   1696 			: gettext ("<INVALID RELOC>"),
   1697 			gettext ("INVALID SECTION"),
   1698 			(long int) (sym->st_shndx == SHN_XINDEX
   1699 				    ? xndx : sym->st_shndx));
   1700 	      else
   1701 		printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
   1702 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1703 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1704 			/* Avoid the leading R_ which isn't carrying any
   1705 			   information.  */
   1706 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1707 					       buf, sizeof (buf)) + 2
   1708 			: gettext ("<INVALID RELOC>"),
   1709 			class == ELFCLASS32 ? 10 : 18, sym->st_value,
   1710 			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
   1711 	    }
   1712 	}
   1713     }
   1714 }
   1715 
   1716 
   1717 /* Handle a relocation section.  */
   1718 static void
   1719 handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   1720 {
   1721   int class = gelf_getclass (ebl->elf);
   1722   int nentries = shdr->sh_size / shdr->sh_entsize;
   1723 
   1724   /* Get the data of the section.  */
   1725   Elf_Data *data = elf_getdata (scn, NULL);
   1726   if (data == NULL)
   1727     return;
   1728 
   1729   /* Get the symbol table information.  */
   1730   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
   1731   GElf_Shdr symshdr_mem;
   1732   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
   1733   Elf_Data *symdata = elf_getdata (symscn, NULL);
   1734 
   1735   /* Get the section header of the section the relocations are for.  */
   1736   GElf_Shdr destshdr_mem;
   1737   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
   1738 				      &destshdr_mem);
   1739 
   1740   if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
   1741     {
   1742       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
   1743 	      shdr->sh_offset);
   1744       return;
   1745     }
   1746 
   1747   /* Search for the optional extended section index table.  */
   1748   Elf_Data *xndxdata = NULL;
   1749   int xndxscnidx = elf_scnshndx (scn);
   1750   if (unlikely (xndxscnidx > 0))
   1751     xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
   1752 
   1753   /* Get the section header string table index.  */
   1754   size_t shstrndx;
   1755   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   1756     error (EXIT_FAILURE, 0,
   1757 	   gettext ("cannot get section header string table index"));
   1758 
   1759   printf (ngettext ("\
   1760 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   1761 		    "\
   1762 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   1763 		    nentries),
   1764 	  elf_ndxscn (scn),
   1765 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   1766 	  (unsigned int) shdr->sh_info,
   1767 	  elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
   1768 	  shdr->sh_offset,
   1769 	  nentries);
   1770   fputs_unlocked (class == ELFCLASS32
   1771 		  ? gettext ("\
   1772   Offset      Type            Value       Addend Name\n")
   1773 		  : gettext ("\
   1774   Offset              Type            Value               Addend Name\n"),
   1775 		  stdout);
   1776 
   1777   int is_statically_linked = 0;
   1778   for (int cnt = 0; cnt < nentries; ++cnt)
   1779     {
   1780       GElf_Rela relmem;
   1781       GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
   1782       if (likely (rel != NULL))
   1783 	{
   1784 	  char buf[64];
   1785 	  GElf_Sym symmem;
   1786 	  Elf32_Word xndx;
   1787 	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
   1788 					    GELF_R_SYM (rel->r_info),
   1789 					    &symmem, &xndx);
   1790 
   1791 	  if (unlikely (sym == NULL))
   1792 	    {
   1793 	      /* As a special case we have to handle relocations in static
   1794 		 executables.  This only happens for IRELATIVE relocations
   1795 		 (so far).  There is no symbol table.  */
   1796 	      if (is_statically_linked == 0)
   1797 		{
   1798 		  /* Find the program header and look for a PT_INTERP entry. */
   1799 		  is_statically_linked = -1;
   1800 		  if (ehdr->e_type == ET_EXEC)
   1801 		    {
   1802 		      is_statically_linked = 1;
   1803 
   1804 		      for (size_t inner = 0; inner < phnum; ++inner)
   1805 			{
   1806 			  GElf_Phdr phdr_mem;
   1807 			  GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
   1808 							  &phdr_mem);
   1809 			  if (phdr != NULL && phdr->p_type == PT_INTERP)
   1810 			    {
   1811 			      is_statically_linked = -1;
   1812 			      break;
   1813 			    }
   1814 			}
   1815 		    }
   1816 		}
   1817 
   1818 	      if (is_statically_linked > 0 && shdr->sh_link == 0)
   1819 		printf ("\
   1820   %#0*" PRIx64 "  %-15s %*s  %#6" PRIx64 " %s\n",
   1821 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1822 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1823 			/* Avoid the leading R_ which isn't carrying any
   1824 			   information.  */
   1825 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1826 					       buf, sizeof (buf)) + 2
   1827 			: gettext ("<INVALID RELOC>"),
   1828 			class == ELFCLASS32 ? 10 : 18, "",
   1829 			rel->r_addend,
   1830 			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
   1831 	      else
   1832 		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
   1833 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1834 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1835 			/* Avoid the leading R_ which isn't carrying any
   1836 			   information.  */
   1837 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1838 					       buf, sizeof (buf)) + 2
   1839 			: gettext ("<INVALID RELOC>"),
   1840 			gettext ("INVALID SYMBOL"),
   1841 			(long int) GELF_R_SYM (rel->r_info));
   1842 	    }
   1843 	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
   1844 	    printf ("\
   1845   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
   1846 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1847 		    likely (ebl_reloc_type_check (ebl,
   1848 						  GELF_R_TYPE (rel->r_info)))
   1849 		    /* Avoid the leading R_ which isn't carrying any
   1850 		       information.  */
   1851 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1852 					   buf, sizeof (buf)) + 2
   1853 		    : gettext ("<INVALID RELOC>"),
   1854 		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
   1855 		    rel->r_addend,
   1856 		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
   1857 	  else
   1858 	    {
   1859 	      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
   1860 						   sym->st_shndx == SHN_XINDEX
   1861 						   ? xndx : sym->st_shndx),
   1862 				       &destshdr_mem);
   1863 
   1864 	      if (unlikely (shdr == NULL))
   1865 		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
   1866 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1867 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1868 			/* Avoid the leading R_ which isn't carrying any
   1869 			   information.  */
   1870 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1871 					       buf, sizeof (buf)) + 2
   1872 			: gettext ("<INVALID RELOC>"),
   1873 			gettext ("INVALID SECTION"),
   1874 			(long int) (sym->st_shndx == SHN_XINDEX
   1875 				    ? xndx : sym->st_shndx));
   1876 	      else
   1877 		printf ("\
   1878   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
   1879 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1880 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1881 			/* Avoid the leading R_ which isn't carrying any
   1882 			   information.  */
   1883 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1884 					       buf, sizeof (buf)) + 2
   1885 			: gettext ("<INVALID RELOC>"),
   1886 			class == ELFCLASS32 ? 10 : 18, sym->st_value,
   1887 			rel->r_addend,
   1888 			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
   1889 	    }
   1890 	}
   1891     }
   1892 }
   1893 
   1894 
   1895 /* Print the program header.  */
   1896 static void
   1897 print_symtab (Ebl *ebl, int type)
   1898 {
   1899   /* Find the symbol table(s).  For this we have to search through the
   1900      section table.  */
   1901   Elf_Scn *scn = NULL;
   1902 
   1903   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   1904     {
   1905       /* Handle the section if it is a symbol table.  */
   1906       GElf_Shdr shdr_mem;
   1907       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1908 
   1909       if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
   1910 	handle_symtab (ebl, scn, shdr);
   1911     }
   1912 }
   1913 
   1914 
   1915 static void
   1916 handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   1917 {
   1918   Elf_Data *versym_data = NULL;
   1919   Elf_Data *verneed_data = NULL;
   1920   Elf_Data *verdef_data = NULL;
   1921   Elf_Data *xndx_data = NULL;
   1922   int class = gelf_getclass (ebl->elf);
   1923   Elf32_Word verneed_stridx = 0;
   1924   Elf32_Word verdef_stridx = 0;
   1925 
   1926   /* Get the data of the section.  */
   1927   Elf_Data *data = elf_getdata (scn, NULL);
   1928   if (data == NULL)
   1929     return;
   1930 
   1931   /* Find out whether we have other sections we might need.  */
   1932   Elf_Scn *runscn = NULL;
   1933   while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
   1934     {
   1935       GElf_Shdr runshdr_mem;
   1936       GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
   1937 
   1938       if (likely (runshdr != NULL))
   1939 	{
   1940 	  if (runshdr->sh_type == SHT_GNU_versym
   1941 	      && runshdr->sh_link == elf_ndxscn (scn))
   1942 	    /* Bingo, found the version information.  Now get the data.  */
   1943 	    versym_data = elf_getdata (runscn, NULL);
   1944 	  else if (runshdr->sh_type == SHT_GNU_verneed)
   1945 	    {
   1946 	      /* This is the information about the needed versions.  */
   1947 	      verneed_data = elf_getdata (runscn, NULL);
   1948 	      verneed_stridx = runshdr->sh_link;
   1949 	    }
   1950 	  else if (runshdr->sh_type == SHT_GNU_verdef)
   1951 	    {
   1952 	      /* This is the information about the defined versions.  */
   1953 	      verdef_data = elf_getdata (runscn, NULL);
   1954 	      verdef_stridx = runshdr->sh_link;
   1955 	    }
   1956 	  else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
   1957 	      && runshdr->sh_link == elf_ndxscn (scn))
   1958 	    /* Extended section index.  */
   1959 	    xndx_data = elf_getdata (runscn, NULL);
   1960 	}
   1961     }
   1962 
   1963   /* Get the section header string table index.  */
   1964   size_t shstrndx;
   1965   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   1966     error (EXIT_FAILURE, 0,
   1967 	   gettext ("cannot get section header string table index"));
   1968 
   1969   /* Now we can compute the number of entries in the section.  */
   1970   unsigned int nsyms = data->d_size / (class == ELFCLASS32
   1971 				       ? sizeof (Elf32_Sym)
   1972 				       : sizeof (Elf64_Sym));
   1973 
   1974   printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
   1975 		    "\nSymbol table [%2u] '%s' contains %u entries:\n",
   1976 		    nsyms),
   1977 	  (unsigned int) elf_ndxscn (scn),
   1978 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
   1979   GElf_Shdr glink;
   1980   printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
   1981 		    " %lu local symbols  String table: [%2u] '%s'\n",
   1982 		    shdr->sh_info),
   1983 	  (unsigned long int) shdr->sh_info,
   1984 	  (unsigned int) shdr->sh_link,
   1985 	  elf_strptr (ebl->elf, shstrndx,
   1986 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   1987 				    &glink)->sh_name));
   1988 
   1989   fputs_unlocked (class == ELFCLASS32
   1990 		  ? gettext ("\
   1991   Num:    Value   Size Type    Bind   Vis          Ndx Name\n")
   1992 		  : gettext ("\
   1993   Num:            Value   Size Type    Bind   Vis          Ndx Name\n"),
   1994 		  stdout);
   1995 
   1996   for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
   1997     {
   1998       char typebuf[64];
   1999       char bindbuf[64];
   2000       char scnbuf[64];
   2001       Elf32_Word xndx;
   2002       GElf_Sym sym_mem;
   2003       GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
   2004 
   2005       if (unlikely (sym == NULL))
   2006 	continue;
   2007 
   2008       /* Determine the real section index.  */
   2009       if (likely (sym->st_shndx != SHN_XINDEX))
   2010 	xndx = sym->st_shndx;
   2011 
   2012       printf (gettext ("\
   2013 %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
   2014 	      cnt,
   2015 	      class == ELFCLASS32 ? 8 : 16,
   2016 	      sym->st_value,
   2017 	      sym->st_size,
   2018 	      ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
   2019 				    typebuf, sizeof (typebuf)),
   2020 	      ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
   2021 				       bindbuf, sizeof (bindbuf)),
   2022 	      get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
   2023 	      ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
   2024 				sizeof (scnbuf), NULL, shnum),
   2025 	      elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
   2026 
   2027       if (versym_data != NULL)
   2028 	{
   2029 	  /* Get the version information.  */
   2030 	  GElf_Versym versym_mem;
   2031 	  GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
   2032 
   2033 	  if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
   2034 	    {
   2035 	      bool is_nobits = false;
   2036 	      bool check_def = xndx != SHN_UNDEF;
   2037 
   2038 	      if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
   2039 		{
   2040 		  GElf_Shdr symshdr_mem;
   2041 		  GElf_Shdr *symshdr =
   2042 		    gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
   2043 
   2044 		  is_nobits = (symshdr != NULL
   2045 			       && symshdr->sh_type == SHT_NOBITS);
   2046 		}
   2047 
   2048 	      if (is_nobits || ! check_def)
   2049 		{
   2050 		  /* We must test both.  */
   2051 		  GElf_Vernaux vernaux_mem;
   2052 		  GElf_Vernaux *vernaux = NULL;
   2053 		  size_t vn_offset = 0;
   2054 
   2055 		  GElf_Verneed verneed_mem;
   2056 		  GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
   2057 							   &verneed_mem);
   2058 		  while (verneed != NULL)
   2059 		    {
   2060 		      size_t vna_offset = vn_offset;
   2061 
   2062 		      vernaux = gelf_getvernaux (verneed_data,
   2063 						 vna_offset += verneed->vn_aux,
   2064 						 &vernaux_mem);
   2065 		      while (vernaux != NULL
   2066 			     && vernaux->vna_other != *versym
   2067 			     && vernaux->vna_next != 0)
   2068 			{
   2069 			  /* Update the offset.  */
   2070 			  vna_offset += vernaux->vna_next;
   2071 
   2072 			  vernaux = (vernaux->vna_next == 0
   2073 				     ? NULL
   2074 				     : gelf_getvernaux (verneed_data,
   2075 							vna_offset,
   2076 							&vernaux_mem));
   2077 			}
   2078 
   2079 		      /* Check whether we found the version.  */
   2080 		      if (vernaux != NULL && vernaux->vna_other == *versym)
   2081 			/* Found it.  */
   2082 			break;
   2083 
   2084 		      vn_offset += verneed->vn_next;
   2085 		      verneed = (verneed->vn_next == 0
   2086 				 ? NULL
   2087 				 : gelf_getverneed (verneed_data, vn_offset,
   2088 						    &verneed_mem));
   2089 		    }
   2090 
   2091 		  if (vernaux != NULL && vernaux->vna_other == *versym)
   2092 		    {
   2093 		      printf ("@%s (%u)",
   2094 			      elf_strptr (ebl->elf, verneed_stridx,
   2095 					  vernaux->vna_name),
   2096 			      (unsigned int) vernaux->vna_other);
   2097 		      check_def = 0;
   2098 		    }
   2099 		  else if (unlikely (! is_nobits))
   2100 		    error (0, 0, gettext ("bad dynamic symbol"));
   2101 		  else
   2102 		    check_def = 1;
   2103 		}
   2104 
   2105 	      if (check_def && *versym != 0x8001)
   2106 		{
   2107 		  /* We must test both.  */
   2108 		  size_t vd_offset = 0;
   2109 
   2110 		  GElf_Verdef verdef_mem;
   2111 		  GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
   2112 							&verdef_mem);
   2113 		  while (verdef != NULL)
   2114 		    {
   2115 		      if (verdef->vd_ndx == (*versym & 0x7fff))
   2116 			/* Found the definition.  */
   2117 			break;
   2118 
   2119 		      vd_offset += verdef->vd_next;
   2120 		      verdef = (verdef->vd_next == 0
   2121 				? NULL
   2122 				: gelf_getverdef (verdef_data, vd_offset,
   2123 						  &verdef_mem));
   2124 		    }
   2125 
   2126 		  if (verdef != NULL)
   2127 		    {
   2128 		      GElf_Verdaux verdaux_mem;
   2129 		      GElf_Verdaux *verdaux
   2130 			= gelf_getverdaux (verdef_data,
   2131 					   vd_offset + verdef->vd_aux,
   2132 					   &verdaux_mem);
   2133 
   2134 		      if (verdaux != NULL)
   2135 			printf ((*versym & 0x8000) ? "@%s" : "@@%s",
   2136 				elf_strptr (ebl->elf, verdef_stridx,
   2137 					    verdaux->vda_name));
   2138 		    }
   2139 		}
   2140 	    }
   2141 	}
   2142 
   2143       putchar_unlocked ('\n');
   2144     }
   2145 }
   2146 
   2147 
   2148 /* Print version information.  */
   2149 static void
   2150 print_verinfo (Ebl *ebl)
   2151 {
   2152   /* Find the version information sections.  For this we have to
   2153      search through the section table.  */
   2154   Elf_Scn *scn = NULL;
   2155 
   2156   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   2157     {
   2158       /* Handle the section if it is part of the versioning handling.  */
   2159       GElf_Shdr shdr_mem;
   2160       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   2161 
   2162       if (likely (shdr != NULL))
   2163 	{
   2164 	  if (shdr->sh_type == SHT_GNU_verneed)
   2165 	    handle_verneed (ebl, scn, shdr);
   2166 	  else if (shdr->sh_type == SHT_GNU_verdef)
   2167 	    handle_verdef (ebl, scn, shdr);
   2168 	  else if (shdr->sh_type == SHT_GNU_versym)
   2169 	    handle_versym (ebl, scn, shdr);
   2170 	}
   2171     }
   2172 }
   2173 
   2174 
   2175 static const char *
   2176 get_ver_flags (unsigned int flags)
   2177 {
   2178   static char buf[32];
   2179   char *endp;
   2180 
   2181   if (flags == 0)
   2182     return gettext ("none");
   2183 
   2184   if (flags & VER_FLG_BASE)
   2185     endp = stpcpy (buf, "BASE ");
   2186   else
   2187     endp = buf;
   2188 
   2189   if (flags & VER_FLG_WEAK)
   2190     {
   2191       if (endp != buf)
   2192 	endp = stpcpy (endp, "| ");
   2193 
   2194       endp = stpcpy (endp, "WEAK ");
   2195     }
   2196 
   2197   if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
   2198     {
   2199       strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
   2200       buf[sizeof (buf) - 1] = '\0';
   2201     }
   2202 
   2203   return buf;
   2204 }
   2205 
   2206 
   2207 static void
   2208 handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   2209 {
   2210   int class = gelf_getclass (ebl->elf);
   2211 
   2212   /* Get the data of the section.  */
   2213   Elf_Data *data = elf_getdata (scn, NULL);
   2214   if (data == NULL)
   2215     return;
   2216 
   2217   /* Get the section header string table index.  */
   2218   size_t shstrndx;
   2219   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   2220     error (EXIT_FAILURE, 0,
   2221 	   gettext ("cannot get section header string table index"));
   2222 
   2223   GElf_Shdr glink;
   2224   printf (ngettext ("\
   2225 \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2226 		    "\
   2227 \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2228 		    shdr->sh_info),
   2229 	  (unsigned int) elf_ndxscn (scn),
   2230 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
   2231 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   2232 	  shdr->sh_offset,
   2233 	  (unsigned int) shdr->sh_link,
   2234 	  elf_strptr (ebl->elf, shstrndx,
   2235 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   2236 				    &glink)->sh_name));
   2237 
   2238   unsigned int offset = 0;
   2239   for (int cnt = shdr->sh_info; --cnt >= 0; )
   2240     {
   2241       /* Get the data at the next offset.  */
   2242       GElf_Verneed needmem;
   2243       GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
   2244       if (unlikely (need == NULL))
   2245 	break;
   2246 
   2247       printf (gettext ("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
   2248 	      offset, (unsigned short int) need->vn_version,
   2249 	      elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
   2250 	      (unsigned short int) need->vn_cnt);
   2251 
   2252       unsigned int auxoffset = offset + need->vn_aux;
   2253       for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
   2254 	{
   2255 	  GElf_Vernaux auxmem;
   2256 	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
   2257 	  if (unlikely (aux == NULL))
   2258 	    break;
   2259 
   2260 	  printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
   2261 		  auxoffset,
   2262 		  elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
   2263 		  get_ver_flags (aux->vna_flags),
   2264 		  (unsigned short int) aux->vna_other);
   2265 
   2266 	  auxoffset += aux->vna_next;
   2267 	}
   2268 
   2269       /* Find the next offset.  */
   2270       offset += need->vn_next;
   2271     }
   2272 }
   2273 
   2274 
   2275 static void
   2276 handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   2277 {
   2278   /* Get the data of the section.  */
   2279   Elf_Data *data = elf_getdata (scn, NULL);
   2280   if (data == NULL)
   2281     return;
   2282 
   2283   /* Get the section header string table index.  */
   2284   size_t shstrndx;
   2285   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   2286     error (EXIT_FAILURE, 0,
   2287 	   gettext ("cannot get section header string table index"));
   2288 
   2289   int class = gelf_getclass (ebl->elf);
   2290   GElf_Shdr glink;
   2291   printf (ngettext ("\
   2292 \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2293 		    "\
   2294 \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2295 		    shdr->sh_info),
   2296 	  (unsigned int) elf_ndxscn (scn),
   2297 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2298 	  shdr->sh_info,
   2299 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   2300 	  shdr->sh_offset,
   2301 	  (unsigned int) shdr->sh_link,
   2302 	  elf_strptr (ebl->elf, shstrndx,
   2303 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   2304 				    &glink)->sh_name));
   2305 
   2306   unsigned int offset = 0;
   2307   for (int cnt = shdr->sh_info; --cnt >= 0; )
   2308     {
   2309       /* Get the data at the next offset.  */
   2310       GElf_Verdef defmem;
   2311       GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
   2312       if (unlikely (def == NULL))
   2313 	break;
   2314 
   2315       unsigned int auxoffset = offset + def->vd_aux;
   2316       GElf_Verdaux auxmem;
   2317       GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
   2318       if (unlikely (aux == NULL))
   2319 	break;
   2320 
   2321       printf (gettext ("\
   2322   %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"),
   2323 	      offset, def->vd_version,
   2324 	      get_ver_flags (def->vd_flags),
   2325 	      def->vd_ndx,
   2326 	      def->vd_cnt,
   2327 	      elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
   2328 
   2329       auxoffset += aux->vda_next;
   2330       for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
   2331 	{
   2332 	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
   2333 	  if (unlikely (aux == NULL))
   2334 	    break;
   2335 
   2336 	  printf (gettext ("  %#06x: Parent %d: %s\n"),
   2337 		  auxoffset, cnt2,
   2338 		  elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
   2339 
   2340 	  auxoffset += aux->vda_next;
   2341 	}
   2342 
   2343       /* Find the next offset.  */
   2344       offset += def->vd_next;
   2345     }
   2346 }
   2347 
   2348 
   2349 static void
   2350 handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   2351 {
   2352   int class = gelf_getclass (ebl->elf);
   2353   const char **vername;
   2354   const char **filename;
   2355 
   2356   /* Get the data of the section.  */
   2357   Elf_Data *data = elf_getdata (scn, NULL);
   2358   if (data == NULL)
   2359     return;
   2360 
   2361   /* Get the section header string table index.  */
   2362   size_t shstrndx;
   2363   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   2364     error (EXIT_FAILURE, 0,
   2365 	   gettext ("cannot get section header string table index"));
   2366 
   2367   /* We have to find the version definition section and extract the
   2368      version names.  */
   2369   Elf_Scn *defscn = NULL;
   2370   Elf_Scn *needscn = NULL;
   2371 
   2372   Elf_Scn *verscn = NULL;
   2373   while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
   2374     {
   2375       GElf_Shdr vershdr_mem;
   2376       GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
   2377 
   2378       if (likely (vershdr != NULL))
   2379 	{
   2380 	  if (vershdr->sh_type == SHT_GNU_verdef)
   2381 	    defscn = verscn;
   2382 	  else if (vershdr->sh_type == SHT_GNU_verneed)
   2383 	    needscn = verscn;
   2384 	}
   2385     }
   2386 
   2387   size_t nvername;
   2388   if (defscn != NULL || needscn != NULL)
   2389     {
   2390       /* We have a version information (better should have).  Now get
   2391 	 the version names.  First find the maximum version number.  */
   2392       nvername = 0;
   2393       if (defscn != NULL)
   2394 	{
   2395 	  /* Run through the version definitions and find the highest
   2396 	     index.  */
   2397 	  unsigned int offset = 0;
   2398 	  Elf_Data *defdata;
   2399 	  GElf_Shdr defshdrmem;
   2400 	  GElf_Shdr *defshdr;
   2401 
   2402 	  defdata = elf_getdata (defscn, NULL);
   2403 	  if (unlikely (defdata == NULL))
   2404 	    return;
   2405 
   2406 	  defshdr = gelf_getshdr (defscn, &defshdrmem);
   2407 	  if (unlikely (defshdr == NULL))
   2408 	    return;
   2409 
   2410 	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
   2411 	    {
   2412 	      GElf_Verdef defmem;
   2413 	      GElf_Verdef *def;
   2414 
   2415 	      /* Get the data at the next offset.  */
   2416 	      def = gelf_getverdef (defdata, offset, &defmem);
   2417 	      if (unlikely (def == NULL))
   2418 		break;
   2419 
   2420 	      nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
   2421 
   2422 	      offset += def->vd_next;
   2423 	    }
   2424 	}
   2425       if (needscn != NULL)
   2426 	{
   2427 	  unsigned int offset = 0;
   2428 	  Elf_Data *needdata;
   2429 	  GElf_Shdr needshdrmem;
   2430 	  GElf_Shdr *needshdr;
   2431 
   2432 	  needdata = elf_getdata (needscn, NULL);
   2433 	  if (unlikely (needdata == NULL))
   2434 	    return;
   2435 
   2436 	  needshdr = gelf_getshdr (needscn, &needshdrmem);
   2437 	  if (unlikely (needshdr == NULL))
   2438 	    return;
   2439 
   2440 	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
   2441 	    {
   2442 	      GElf_Verneed needmem;
   2443 	      GElf_Verneed *need;
   2444 	      unsigned int auxoffset;
   2445 	      int cnt2;
   2446 
   2447 	      /* Get the data at the next offset.  */
   2448 	      need = gelf_getverneed (needdata, offset, &needmem);
   2449 	      if (unlikely (need == NULL))
   2450 		break;
   2451 
   2452 	      /* Run through the auxiliary entries.  */
   2453 	      auxoffset = offset + need->vn_aux;
   2454 	      for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
   2455 		{
   2456 		  GElf_Vernaux auxmem;
   2457 		  GElf_Vernaux *aux;
   2458 
   2459 		  aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
   2460 		  if (unlikely (aux == NULL))
   2461 		    break;
   2462 
   2463 		  nvername = MAX (nvername,
   2464 				  (size_t) (aux->vna_other & 0x7fff));
   2465 
   2466 		  auxoffset += aux->vna_next;
   2467 		}
   2468 
   2469 	      offset += need->vn_next;
   2470 	    }
   2471 	}
   2472 
   2473       /* This is the number of versions we know about.  */
   2474       ++nvername;
   2475 
   2476       /* Allocate the array.  */
   2477       vername = (const char **) alloca (nvername * sizeof (const char *));
   2478       filename = (const char **) alloca (nvername * sizeof (const char *));
   2479 
   2480       /* Run through the data structures again and collect the strings.  */
   2481       if (defscn != NULL)
   2482 	{
   2483 	  /* Run through the version definitions and find the highest
   2484 	     index.  */
   2485 	  unsigned int offset = 0;
   2486 	  Elf_Data *defdata;
   2487 	  GElf_Shdr defshdrmem;
   2488 	  GElf_Shdr *defshdr;
   2489 
   2490 	  defdata = elf_getdata (defscn, NULL);
   2491 	  if (unlikely (defdata == NULL))
   2492 	    return;
   2493 
   2494 	  defshdr = gelf_getshdr (defscn, &defshdrmem);
   2495 	  if (unlikely (defshdr == NULL))
   2496 	    return;
   2497 
   2498 	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
   2499 	    {
   2500 
   2501 	      /* Get the data at the next offset.  */
   2502 	      GElf_Verdef defmem;
   2503 	      GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
   2504 	      GElf_Verdaux auxmem;
   2505 	      GElf_Verdaux *aux = gelf_getverdaux (defdata,
   2506 						   offset + def->vd_aux,
   2507 						   &auxmem);
   2508 	      if (unlikely (def == NULL || aux == NULL))
   2509 		break;
   2510 
   2511 	      vername[def->vd_ndx & 0x7fff]
   2512 		= elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
   2513 	      filename[def->vd_ndx & 0x7fff] = NULL;
   2514 
   2515 	      offset += def->vd_next;
   2516 	    }
   2517 	}
   2518       if (needscn != NULL)
   2519 	{
   2520 	  unsigned int offset = 0;
   2521 
   2522 	  Elf_Data *needdata = elf_getdata (needscn, NULL);
   2523 	  GElf_Shdr needshdrmem;
   2524 	  GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
   2525 	  if (unlikely (needdata == NULL || needshdr == NULL))
   2526 	    return;
   2527 
   2528 	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
   2529 	    {
   2530 	      /* Get the data at the next offset.  */
   2531 	      GElf_Verneed needmem;
   2532 	      GElf_Verneed *need = gelf_getverneed (needdata, offset,
   2533 						    &needmem);
   2534 	      if (unlikely (need == NULL))
   2535 		break;
   2536 
   2537 	      /* Run through the auxiliary entries.  */
   2538 	      unsigned int auxoffset = offset + need->vn_aux;
   2539 	      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
   2540 		{
   2541 		  GElf_Vernaux auxmem;
   2542 		  GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
   2543 						       &auxmem);
   2544 		  if (unlikely (aux == NULL))
   2545 		    break;
   2546 
   2547 		  vername[aux->vna_other & 0x7fff]
   2548 		    = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
   2549 		  filename[aux->vna_other & 0x7fff]
   2550 		    = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
   2551 
   2552 		  auxoffset += aux->vna_next;
   2553 		}
   2554 
   2555 	      offset += need->vn_next;
   2556 	    }
   2557 	}
   2558     }
   2559   else
   2560     {
   2561       vername = NULL;
   2562       nvername = 1;
   2563       filename = NULL;
   2564     }
   2565 
   2566   /* Print the header.  */
   2567   GElf_Shdr glink;
   2568   printf (ngettext ("\
   2569 \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
   2570 		    "\
   2571 \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
   2572 		    shdr->sh_size / shdr->sh_entsize),
   2573 	  (unsigned int) elf_ndxscn (scn),
   2574 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2575 	  (int) (shdr->sh_size / shdr->sh_entsize),
   2576 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   2577 	  shdr->sh_offset,
   2578 	  (unsigned int) shdr->sh_link,
   2579 	  elf_strptr (ebl->elf, shstrndx,
   2580 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   2581 				    &glink)->sh_name));
   2582 
   2583   /* Now we can finally look at the actual contents of this section.  */
   2584   for (unsigned int cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
   2585     {
   2586       if (cnt % 2 == 0)
   2587 	printf ("\n %4d:", cnt);
   2588 
   2589       GElf_Versym symmem;
   2590       GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
   2591       if (sym == NULL)
   2592 	break;
   2593 
   2594       switch (*sym)
   2595 	{
   2596 	  ssize_t n;
   2597 	case 0:
   2598 	  fputs_unlocked (gettext ("   0 *local*                     "),
   2599 			  stdout);
   2600 	  break;
   2601 
   2602 	case 1:
   2603 	  fputs_unlocked (gettext ("   1 *global*                    "),
   2604 			  stdout);
   2605 	  break;
   2606 
   2607 	default:
   2608 	  n = printf ("%4d%c%s",
   2609 		      *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
   2610 		      (unsigned int) (*sym & 0x7fff) < nvername
   2611 		      ? vername[*sym & 0x7fff] : "???");
   2612 	  if ((unsigned int) (*sym & 0x7fff) < nvername
   2613 	      && filename[*sym & 0x7fff] != NULL)
   2614 	    n += printf ("(%s)", filename[*sym & 0x7fff]);
   2615 	  printf ("%*s", MAX (0, 33 - (int) n), " ");
   2616 	  break;
   2617 	}
   2618     }
   2619   putchar_unlocked ('\n');
   2620 }
   2621 
   2622 
   2623 static void
   2624 print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
   2625 		 uint_fast32_t maxlength, Elf32_Word nbucket,
   2626 		 uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
   2627 {
   2628   uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
   2629 
   2630   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
   2631     ++counts[lengths[cnt]];
   2632 
   2633   GElf_Shdr glink;
   2634   printf (ngettext ("\
   2635 \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",
   2636 		    "\
   2637 \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",
   2638 		    nbucket),
   2639 	  (unsigned int) elf_ndxscn (scn),
   2640 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2641 	  (int) nbucket,
   2642 	  gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
   2643 	  shdr->sh_addr,
   2644 	  shdr->sh_offset,
   2645 	  (unsigned int) shdr->sh_link,
   2646 	  elf_strptr (ebl->elf, shstrndx,
   2647 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   2648 				    &glink)->sh_name));
   2649 
   2650   if (extrastr != NULL)
   2651     fputs (extrastr, stdout);
   2652 
   2653   if (likely (nbucket > 0))
   2654     {
   2655       uint64_t success = 0;
   2656 
   2657       /* xgettext:no-c-format */
   2658       fputs_unlocked (gettext ("\
   2659  Length  Number  % of total  Coverage\n"), stdout);
   2660       printf (gettext ("      0  %6" PRIu32 "      %5.1f%%\n"),
   2661 	      counts[0], (counts[0] * 100.0) / nbucket);
   2662 
   2663       uint64_t nzero_counts = 0;
   2664       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
   2665 	{
   2666 	  nzero_counts += counts[cnt] * cnt;
   2667 	  printf (gettext ("\
   2668 %7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
   2669 		  (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
   2670 		  (nzero_counts * 100.0) / nsyms);
   2671 	}
   2672 
   2673       Elf32_Word acc = 0;
   2674       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
   2675 	{
   2676 	  acc += cnt;
   2677 	  success += counts[cnt] * acc;
   2678 	}
   2679 
   2680       printf (gettext ("\
   2681  Average number of tests:   successful lookup: %f\n\
   2682 			  unsuccessful lookup: %f\n"),
   2683 	      (double) success / (double) nzero_counts,
   2684 	      (double) nzero_counts / (double) nbucket);
   2685     }
   2686 
   2687   free (counts);
   2688 }
   2689 
   2690 
   2691 /* This function handles the traditional System V-style hash table format.  */
   2692 static void
   2693 handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
   2694 {
   2695   Elf_Data *data = elf_getdata (scn, NULL);
   2696   if (unlikely (data == NULL))
   2697     {
   2698       error (0, 0, gettext ("cannot get data for section %d: %s"),
   2699 	     (int) elf_ndxscn (scn), elf_errmsg (-1));
   2700       return;
   2701     }
   2702 
   2703   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
   2704   Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
   2705   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
   2706   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
   2707 
   2708   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
   2709 
   2710   uint_fast32_t maxlength = 0;
   2711   uint_fast32_t nsyms = 0;
   2712   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
   2713     {
   2714       Elf32_Word inner = bucket[cnt];
   2715       while (inner > 0 && inner < nchain)
   2716 	{
   2717 	  ++nsyms;
   2718 	  if (maxlength < ++lengths[cnt])
   2719 	    ++maxlength;
   2720 
   2721 	  inner = chain[inner];
   2722 	}
   2723     }
   2724 
   2725   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
   2726 		   lengths, NULL);
   2727 
   2728   free (lengths);
   2729 }
   2730 
   2731 
   2732 /* This function handles the incorrect, System V-style hash table
   2733    format some 64-bit architectures use.  */
   2734 static void
   2735 handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
   2736 {
   2737   Elf_Data *data = elf_getdata (scn, NULL);
   2738   if (unlikely (data == NULL))
   2739     {
   2740       error (0, 0, gettext ("cannot get data for section %d: %s"),
   2741 	     (int) elf_ndxscn (scn), elf_errmsg (-1));
   2742       return;
   2743     }
   2744 
   2745   Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
   2746   Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
   2747   Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
   2748   Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
   2749 
   2750   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
   2751 
   2752   uint_fast32_t maxlength = 0;
   2753   uint_fast32_t nsyms = 0;
   2754   for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
   2755     {
   2756       Elf64_Xword inner = bucket[cnt];
   2757       while (inner > 0 && inner < nchain)
   2758 	{
   2759 	  ++nsyms;
   2760 	  if (maxlength < ++lengths[cnt])
   2761 	    ++maxlength;
   2762 
   2763 	  inner = chain[inner];
   2764 	}
   2765     }
   2766 
   2767   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
   2768 		   lengths, NULL);
   2769 
   2770   free (lengths);
   2771 }
   2772 
   2773 
   2774 /* This function handles the GNU-style hash table format.  */
   2775 static void
   2776 handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
   2777 {
   2778   Elf_Data *data = elf_getdata (scn, NULL);
   2779   if (unlikely (data == NULL))
   2780     {
   2781       error (0, 0, gettext ("cannot get data for section %d: %s"),
   2782 	     (int) elf_ndxscn (scn), elf_errmsg (-1));
   2783       return;
   2784     }
   2785 
   2786   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
   2787   Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
   2788 
   2789   /* Next comes the size of the bitmap.  It's measured in words for
   2790      the architecture.  It's 32 bits for 32 bit archs, and 64 bits for
   2791      64 bit archs.  */
   2792   Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
   2793   if (gelf_getclass (ebl->elf) == ELFCLASS64)
   2794     bitmask_words *= 2;
   2795 
   2796   Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
   2797 
   2798   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
   2799 
   2800   Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
   2801   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
   2802   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
   2803 						    + nbucket];
   2804 
   2805   /* Compute distribution of chain lengths.  */
   2806   uint_fast32_t maxlength = 0;
   2807   uint_fast32_t nsyms = 0;
   2808   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
   2809     if (bucket[cnt] != 0)
   2810       {
   2811 	Elf32_Word inner = bucket[cnt] - symbias;
   2812 	do
   2813 	  {
   2814 	    ++nsyms;
   2815 	    if (maxlength < ++lengths[cnt])
   2816 	      ++maxlength;
   2817 	  }
   2818 	while ((chain[inner++] & 1) == 0);
   2819       }
   2820 
   2821   /* Count bits in bitmask.  */
   2822   uint_fast32_t nbits = 0;
   2823   for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
   2824     {
   2825       uint_fast32_t word = bitmask[cnt];
   2826 
   2827       word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
   2828       word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
   2829       word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
   2830       word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
   2831       nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
   2832     }
   2833 
   2834   char *str;
   2835   if (unlikely (asprintf (&str, gettext ("\
   2836  Symbol Bias: %u\n\
   2837  Bitmask Size: %zu bytes  %" PRIuFAST32 "%% bits set  2nd hash shift: %u\n"),
   2838 			  (unsigned int) symbias,
   2839 			  bitmask_words * sizeof (Elf32_Word),
   2840 			  ((nbits * 100 + 50)
   2841 			   / (uint_fast32_t) (bitmask_words
   2842 					      * sizeof (Elf32_Word) * 8)),
   2843 			  (unsigned int) shift) == -1))
   2844     error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
   2845 
   2846   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
   2847 		   lengths, str);
   2848 
   2849   free (str);
   2850   free (lengths);
   2851 }
   2852 
   2853 
   2854 /* Find the symbol table(s).  For this we have to search through the
   2855    section table.  */
   2856 static void
   2857 handle_hash (Ebl *ebl)
   2858 {
   2859   /* Get the section header string table index.  */
   2860   size_t shstrndx;
   2861   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   2862     error (EXIT_FAILURE, 0,
   2863 	   gettext ("cannot get section header string table index"));
   2864 
   2865   Elf_Scn *scn = NULL;
   2866   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   2867     {
   2868       /* Handle the section if it is a symbol table.  */
   2869       GElf_Shdr shdr_mem;
   2870       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   2871 
   2872       if (likely (shdr != NULL))
   2873 	{
   2874 	  if (shdr->sh_type == SHT_HASH)
   2875 	    {
   2876 	      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
   2877 		handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
   2878 	      else
   2879 		handle_sysv_hash (ebl, scn, shdr, shstrndx);
   2880 	    }
   2881 	  else if (shdr->sh_type == SHT_GNU_HASH)
   2882 	    handle_gnu_hash (ebl, scn, shdr, shstrndx);
   2883 	}
   2884     }
   2885 }
   2886 
   2887 
   2888 static void
   2889 print_liblist (Ebl *ebl)
   2890 {
   2891   /* Find the library list sections.  For this we have to search
   2892      through the section table.  */
   2893   Elf_Scn *scn = NULL;
   2894 
   2895   /* Get the section header string table index.  */
   2896   size_t shstrndx;
   2897   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   2898     error (EXIT_FAILURE, 0,
   2899 	   gettext ("cannot get section header string table index"));
   2900 
   2901   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   2902     {
   2903       GElf_Shdr shdr_mem;
   2904       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   2905 
   2906       if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
   2907 	{
   2908 	  int nentries = shdr->sh_size / shdr->sh_entsize;
   2909 	  printf (ngettext ("\
   2910 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   2911 			    "\
   2912 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   2913 			    nentries),
   2914 		  elf_ndxscn (scn),
   2915 		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2916 		  shdr->sh_offset,
   2917 		  nentries);
   2918 
   2919 	  Elf_Data *data = elf_getdata (scn, NULL);
   2920 	  if (data == NULL)
   2921 	    return;
   2922 
   2923 	  puts (gettext ("\
   2924        Library                       Time Stamp          Checksum Version Flags"));
   2925 
   2926 	  for (int cnt = 0; cnt < nentries; ++cnt)
   2927 	    {
   2928 	      GElf_Lib lib_mem;
   2929 	      GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
   2930 	      if (unlikely (lib == NULL))
   2931 		continue;
   2932 
   2933 	      time_t t = (time_t) lib->l_time_stamp;
   2934 	      struct tm *tm = gmtime (&t);
   2935 	      if (unlikely (tm == NULL))
   2936 		continue;
   2937 
   2938 	      printf ("  [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
   2939 		      cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
   2940 		      tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
   2941 		      tm->tm_hour, tm->tm_min, tm->tm_sec,
   2942 		      (unsigned int) lib->l_checksum,
   2943 		      (unsigned int) lib->l_version,
   2944 		      (unsigned int) lib->l_flags);
   2945 	    }
   2946 	}
   2947     }
   2948 }
   2949 
   2950 static void
   2951 print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
   2952 {
   2953   /* Find the object attributes sections.  For this we have to search
   2954      through the section table.  */
   2955   Elf_Scn *scn = NULL;
   2956 
   2957   /* Get the section header string table index.  */
   2958   size_t shstrndx;
   2959   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   2960     error (EXIT_FAILURE, 0,
   2961 	   gettext ("cannot get section header string table index"));
   2962 
   2963   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   2964     {
   2965       GElf_Shdr shdr_mem;
   2966       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   2967 
   2968       if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
   2969 			   && (shdr->sh_type != SHT_ARM_ATTRIBUTES
   2970 			       || ehdr->e_machine != EM_ARM)))
   2971 	continue;
   2972 
   2973       printf (gettext ("\
   2974 \nObject attributes section [%2zu] '%s' of %" PRIu64
   2975 		       " bytes at offset %#0" PRIx64 ":\n"),
   2976 	      elf_ndxscn (scn),
   2977 	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2978 	      shdr->sh_size, shdr->sh_offset);
   2979 
   2980       Elf_Data *data = elf_rawdata (scn, NULL);
   2981       if (data == NULL)
   2982 	return;
   2983 
   2984       const unsigned char *p = data->d_buf;
   2985 
   2986       if (unlikely (*p++ != 'A'))
   2987 	return;
   2988 
   2989       fputs_unlocked (gettext ("  Owner          Size\n"), stdout);
   2990 
   2991       inline size_t left (void)
   2992       {
   2993 	return (const unsigned char *) data->d_buf + data->d_size - p;
   2994       }
   2995 
   2996       while (left () >= 4)
   2997 	{
   2998 	  uint32_t len;
   2999 	  memcpy (&len, p, sizeof len);
   3000 
   3001 	  if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
   3002 	    CONVERT (len);
   3003 
   3004 	  if (unlikely (len > left ()))
   3005 	    break;
   3006 
   3007 	  const unsigned char *name = p + sizeof len;
   3008 	  p += len;
   3009 
   3010 	  unsigned const char *q = memchr (name, '\0', len);
   3011 	  if (unlikely (q == NULL))
   3012 	    continue;
   3013 	  ++q;
   3014 
   3015 	  printf (gettext ("  %-13s  %4" PRIu32 "\n"), name, len);
   3016 
   3017 	  if (shdr->sh_type != SHT_GNU_ATTRIBUTES
   3018 	      || (q - name == sizeof "gnu"
   3019 		  && !memcmp (name, "gnu", sizeof "gnu")))
   3020 	    while (q < p)
   3021 	      {
   3022 		const unsigned char *const sub = q;
   3023 
   3024 		unsigned int subsection_tag;
   3025 		get_uleb128 (subsection_tag, q);
   3026 		if (unlikely (q >= p))
   3027 		  break;
   3028 
   3029 		uint32_t subsection_len;
   3030 		if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
   3031 		  break;
   3032 
   3033 		memcpy (&subsection_len, q, sizeof subsection_len);
   3034 
   3035 		if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
   3036 		  CONVERT (subsection_len);
   3037 
   3038 		if (unlikely (p - sub < (ptrdiff_t) subsection_len))
   3039 		  break;
   3040 
   3041 		const unsigned char *r = q + sizeof subsection_len;
   3042 		q = sub + subsection_len;
   3043 
   3044 		switch (subsection_tag)
   3045 		  {
   3046 		  default:
   3047 		    printf (gettext ("    %-4u %12" PRIu32 "\n"),
   3048 			    subsection_tag, subsection_len);
   3049 		    break;
   3050 
   3051 		  case 1:	/* Tag_File */
   3052 		    printf (gettext ("    File: %11" PRIu32 "\n"),
   3053 			    subsection_len);
   3054 
   3055 		    while (r < q)
   3056 		      {
   3057 			unsigned int tag;
   3058 			get_uleb128 (tag, r);
   3059 			if (unlikely (r >= q))
   3060 			  break;
   3061 
   3062 			uint64_t value = 0;
   3063 			const char *string = NULL;
   3064 			if (tag == 32 || (tag & 1) == 0)
   3065 			  {
   3066 			    get_uleb128 (value, r);
   3067 			    if (r > q)
   3068 			      break;
   3069 			  }
   3070 			if (tag == 32 || (tag & 1) != 0)
   3071 			  {
   3072 			    r = memchr (r, '\0', q - r);
   3073 			    if (r == NULL)
   3074 			      break;
   3075 			    ++r;
   3076 			  }
   3077 
   3078 			const char *tag_name = NULL;
   3079 			const char *value_name = NULL;
   3080 			ebl_check_object_attribute (ebl, (const char *) name,
   3081 						    tag, value,
   3082 						    &tag_name, &value_name);
   3083 
   3084 			if (tag_name != NULL)
   3085 			  {
   3086 			    if (tag == 32)
   3087 			      printf (gettext ("      %s: %" PRId64 ", %s\n"),
   3088 				      tag_name, value, string);
   3089 			    else if (string == NULL && value_name == NULL)
   3090 			      printf (gettext ("      %s: %" PRId64 "\n"),
   3091 				      tag_name, value);
   3092 			    else
   3093 			      printf (gettext ("      %s: %s\n"),
   3094 				      tag_name, string ?: value_name);
   3095 			  }
   3096 			else
   3097 			  {
   3098 			    assert (tag != 32);
   3099 			    if (string == NULL)
   3100 			      printf (gettext ("      %u: %" PRId64 "\n"),
   3101 				      tag, value);
   3102 			    else
   3103 			      printf (gettext ("      %u: %s\n"),
   3104 				      tag, string);
   3105 			  }
   3106 		      }
   3107 		  }
   3108 	      }
   3109 	}
   3110     }
   3111 }
   3112 
   3113 
   3114 static char *
   3115 format_dwarf_addr (Dwfl_Module *dwflmod,
   3116 		   int address_size, Dwarf_Addr address)
   3117 {
   3118   /* See if there is a name we can give for this address.  */
   3119   GElf_Sym sym;
   3120   const char *name = print_address_names
   3121     ? dwfl_module_addrsym (dwflmod, address, &sym, NULL) : NULL;
   3122   if (name != NULL)
   3123     sym.st_value = address - sym.st_value;
   3124 
   3125   /* Relativize the address.  */
   3126   int n = dwfl_module_relocations (dwflmod);
   3127   int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
   3128 
   3129   /* In an ET_REL file there is a section name to refer to.  */
   3130   const char *scn = (i < 0 ? NULL
   3131 		     : dwfl_module_relocation_info (dwflmod, i, NULL));
   3132 
   3133   char *result;
   3134   if ((name != NULL
   3135        ? (sym.st_value != 0
   3136 	  ? (scn != NULL
   3137 	     ? (address_size == 0
   3138 		? asprintf (&result,
   3139 			    gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
   3140 			    scn, address, name, sym.st_value)
   3141 		: asprintf (&result,
   3142 			    gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
   3143 			    scn, 2 + address_size * 2, address,
   3144 			    name, sym.st_value))
   3145 	     : (address_size == 0
   3146 		? asprintf (&result,
   3147 			    gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
   3148 			    address, name, sym.st_value)
   3149 		: asprintf (&result,
   3150 			    gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
   3151 			    2 + address_size * 2, address,
   3152 			    name, sym.st_value)))
   3153 	  : (scn != NULL
   3154 	     ? (address_size == 0
   3155 		? asprintf (&result,
   3156 			    gettext ("%s+%#" PRIx64 " <%s>"),
   3157 			    scn, address, name)
   3158 		: asprintf (&result,
   3159 			    gettext ("%s+%#0*" PRIx64 " <%s>"),
   3160 			    scn, 2 + address_size * 2, address, name))
   3161 	     : (address_size == 0
   3162 		? asprintf (&result,
   3163 			    gettext ("%#" PRIx64 " <%s>"),
   3164 			    address, name)
   3165 		: asprintf (&result,
   3166 			    gettext ("%#0*" PRIx64 " <%s>"),
   3167 			    2 + address_size * 2, address, name))))
   3168        : (scn != NULL
   3169 	  ? (address_size == 0
   3170 	     ? asprintf (&result,
   3171 			 gettext ("%s+%#" PRIx64),
   3172 			 scn, address)
   3173 	     : asprintf (&result,
   3174 			 gettext ("%s+%#0*" PRIx64),
   3175 			 scn, 2 + address_size * 2, address))
   3176 	  : (address_size == 0
   3177 	     ? asprintf (&result,
   3178 			 "%#" PRIx64,
   3179 			 address)
   3180 	     : asprintf (&result,
   3181 			 "%#0*" PRIx64,
   3182 			 2 + address_size * 2, address)))) < 0)
   3183     error (EXIT_FAILURE, 0, _("memory exhausted"));
   3184 
   3185   return result;
   3186 }
   3187 
   3188 static const char *
   3189 dwarf_tag_string (unsigned int tag)
   3190 {
   3191   static const char *const known_tags[]  =
   3192     {
   3193       [DW_TAG_array_type] = "array_type",
   3194       [DW_TAG_class_type] = "class_type",
   3195       [DW_TAG_entry_point] = "entry_point",
   3196       [DW_TAG_enumeration_type] = "enumeration_type",
   3197       [DW_TAG_formal_parameter] = "formal_parameter",
   3198       [DW_TAG_imported_declaration] = "imported_declaration",
   3199       [DW_TAG_label] = "label",
   3200       [DW_TAG_lexical_block] = "lexical_block",
   3201       [DW_TAG_member] = "member",
   3202       [DW_TAG_pointer_type] = "pointer_type",
   3203       [DW_TAG_reference_type] = "reference_type",
   3204       [DW_TAG_compile_unit] = "compile_unit",
   3205       [DW_TAG_string_type] = "string_type",
   3206       [DW_TAG_structure_type] = "structure_type",
   3207       [DW_TAG_subroutine_type] = "subroutine_type",
   3208       [DW_TAG_typedef] = "typedef",
   3209       [DW_TAG_union_type] = "union_type",
   3210       [DW_TAG_unspecified_parameters] = "unspecified_parameters",
   3211       [DW_TAG_variant] = "variant",
   3212       [DW_TAG_common_block] = "common_block",
   3213       [DW_TAG_common_inclusion] = "common_inclusion",
   3214       [DW_TAG_inheritance] = "inheritance",
   3215       [DW_TAG_inlined_subroutine] = "inlined_subroutine",
   3216       [DW_TAG_module] = "module",
   3217       [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
   3218       [DW_TAG_set_type] = "set_type",
   3219       [DW_TAG_subrange_type] = "subrange_type",
   3220       [DW_TAG_with_stmt] = "with_stmt",
   3221       [DW_TAG_access_declaration] = "access_declaration",
   3222       [DW_TAG_base_type] = "base_type",
   3223       [DW_TAG_catch_block] = "catch_block",
   3224       [DW_TAG_const_type] = "const_type",
   3225       [DW_TAG_constant] = "constant",
   3226       [DW_TAG_enumerator] = "enumerator",
   3227       [DW_TAG_file_type] = "file_type",
   3228       [DW_TAG_friend] = "friend",
   3229       [DW_TAG_namelist] = "namelist",
   3230       [DW_TAG_namelist_item] = "namelist_item",
   3231       [DW_TAG_packed_type] = "packed_type",
   3232       [DW_TAG_subprogram] = "subprogram",
   3233       [DW_TAG_template_type_parameter] = "template_type_parameter",
   3234       [DW_TAG_template_value_parameter] = "template_value_parameter",
   3235       [DW_TAG_thrown_type] = "thrown_type",
   3236       [DW_TAG_try_block] = "try_block",
   3237       [DW_TAG_variant_part] = "variant_part",
   3238       [DW_TAG_variable] = "variable",
   3239       [DW_TAG_volatile_type] = "volatile_type",
   3240       [DW_TAG_dwarf_procedure] = "dwarf_procedure",
   3241       [DW_TAG_restrict_type] = "restrict_type",
   3242       [DW_TAG_interface_type] = "interface_type",
   3243       [DW_TAG_namespace] = "namespace",
   3244       [DW_TAG_imported_module] = "imported_module",
   3245       [DW_TAG_unspecified_type] = "unspecified_type",
   3246       [DW_TAG_partial_unit] = "partial_unit",
   3247       [DW_TAG_imported_unit] = "imported_unit",
   3248       [DW_TAG_mutable_type] = "mutable_type",
   3249       [DW_TAG_condition] = "condition",
   3250       [DW_TAG_shared_type] = "shared_type",
   3251       [DW_TAG_type_unit] = "type_unit",
   3252       [DW_TAG_rvalue_reference_type] = "rvalue_reference_type",
   3253       [DW_TAG_template_alias] = "template_alias",
   3254     };
   3255   const unsigned int nknown_tags = (sizeof (known_tags)
   3256 				    / sizeof (known_tags[0]));
   3257   static char buf[40];
   3258   const char *result = NULL;
   3259 
   3260   if (likely (tag < nknown_tags))
   3261     result = known_tags[tag];
   3262 
   3263   if (unlikely (result == NULL))
   3264     /* There are a few known extensions.  */
   3265     switch (tag)
   3266       {
   3267       case DW_TAG_MIPS_loop:
   3268 	result = "MIPS_loop";
   3269 	break;
   3270 
   3271       case DW_TAG_format_label:
   3272 	result = "format_label";
   3273 	break;
   3274 
   3275       case DW_TAG_function_template:
   3276 	result = "function_template";
   3277 	break;
   3278 
   3279       case DW_TAG_class_template:
   3280 	result = "class_template";
   3281 	break;
   3282 
   3283       case DW_TAG_GNU_BINCL:
   3284 	result = "GNU_BINCL";
   3285 	break;
   3286 
   3287       case DW_TAG_GNU_EINCL:
   3288 	result = "GNU_EINCL";
   3289 	break;
   3290 
   3291       case DW_TAG_GNU_template_template_param:
   3292 	result = "GNU_template_template_param";
   3293 	break;
   3294 
   3295       case DW_TAG_GNU_template_parameter_pack:
   3296 	result = "GNU_template_parameter_pack";
   3297 	break;
   3298 
   3299       case DW_TAG_GNU_formal_parameter_pack:
   3300 	result = "GNU_formal_parameter_pack";
   3301 	break;
   3302 
   3303       case DW_TAG_GNU_call_site:
   3304 	result = "GNU_call_site";
   3305 	break;
   3306 
   3307       case DW_TAG_GNU_call_site_parameter:
   3308 	result = "GNU_call_site_parameter";
   3309 	break;
   3310 
   3311       default:
   3312 	if (tag < DW_TAG_lo_user)
   3313 	  snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag);
   3314 	else
   3315 	  snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag);
   3316 	result = buf;
   3317 	break;
   3318       }
   3319 
   3320   return result;
   3321 }
   3322 
   3323 
   3324 static const char *
   3325 dwarf_attr_string (unsigned int attrnum)
   3326 {
   3327   static const char *const known_attrs[] =
   3328     {
   3329       [DW_AT_sibling] = "sibling",
   3330       [DW_AT_location] = "location",
   3331       [DW_AT_name] = "name",
   3332       [DW_AT_ordering] = "ordering",
   3333       [DW_AT_subscr_data] = "subscr_data",
   3334       [DW_AT_byte_size] = "byte_size",
   3335       [DW_AT_bit_offset] = "bit_offset",
   3336       [DW_AT_bit_size] = "bit_size",
   3337       [DW_AT_element_list] = "element_list",
   3338       [DW_AT_stmt_list] = "stmt_list",
   3339       [DW_AT_low_pc] = "low_pc",
   3340       [DW_AT_high_pc] = "high_pc",
   3341       [DW_AT_language] = "language",
   3342       [DW_AT_member] = "member",
   3343       [DW_AT_discr] = "discr",
   3344       [DW_AT_discr_value] = "discr_value",
   3345       [DW_AT_visibility] = "visibility",
   3346       [DW_AT_import] = "import",
   3347       [DW_AT_string_length] = "string_length",
   3348       [DW_AT_common_reference] = "common_reference",
   3349       [DW_AT_comp_dir] = "comp_dir",
   3350       [DW_AT_const_value] = "const_value",
   3351       [DW_AT_containing_type] = "containing_type",
   3352       [DW_AT_default_value] = "default_value",
   3353       [DW_AT_inline] = "inline",
   3354       [DW_AT_is_optional] = "is_optional",
   3355       [DW_AT_lower_bound] = "lower_bound",
   3356       [DW_AT_producer] = "producer",
   3357       [DW_AT_prototyped] = "prototyped",
   3358       [DW_AT_return_addr] = "return_addr",
   3359       [DW_AT_start_scope] = "start_scope",
   3360       [DW_AT_bit_stride] = "bit_stride",
   3361       [DW_AT_upper_bound] = "upper_bound",
   3362       [DW_AT_abstract_origin] = "abstract_origin",
   3363       [DW_AT_accessibility] = "accessibility",
   3364       [DW_AT_address_class] = "address_class",
   3365       [DW_AT_artificial] = "artificial",
   3366       [DW_AT_base_types] = "base_types",
   3367       [DW_AT_calling_convention] = "calling_convention",
   3368       [DW_AT_count] = "count",
   3369       [DW_AT_data_member_location] = "data_member_location",
   3370       [DW_AT_decl_column] = "decl_column",
   3371       [DW_AT_decl_file] = "decl_file",
   3372       [DW_AT_decl_line] = "decl_line",
   3373       [DW_AT_declaration] = "declaration",
   3374       [DW_AT_discr_list] = "discr_list",
   3375       [DW_AT_encoding] = "encoding",
   3376       [DW_AT_external] = "external",
   3377       [DW_AT_frame_base] = "frame_base",
   3378       [DW_AT_friend] = "friend",
   3379       [DW_AT_identifier_case] = "identifier_case",
   3380       [DW_AT_macro_info] = "macro_info",
   3381       [DW_AT_namelist_item] = "namelist_item",
   3382       [DW_AT_priority] = "priority",
   3383       [DW_AT_segment] = "segment",
   3384       [DW_AT_specification] = "specification",
   3385       [DW_AT_static_link] = "static_link",
   3386       [DW_AT_type] = "type",
   3387       [DW_AT_use_location] = "use_location",
   3388       [DW_AT_variable_parameter] = "variable_parameter",
   3389       [DW_AT_virtuality] = "virtuality",
   3390       [DW_AT_vtable_elem_location] = "vtable_elem_location",
   3391       [DW_AT_allocated] = "allocated",
   3392       [DW_AT_associated] = "associated",
   3393       [DW_AT_data_location] = "data_location",
   3394       [DW_AT_byte_stride] = "byte_stride",
   3395       [DW_AT_entry_pc] = "entry_pc",
   3396       [DW_AT_use_UTF8] = "use_UTF8",
   3397       [DW_AT_extension] = "extension",
   3398       [DW_AT_ranges] = "ranges",
   3399       [DW_AT_trampoline] = "trampoline",
   3400       [DW_AT_call_column] = "call_column",
   3401       [DW_AT_call_file] = "call_file",
   3402       [DW_AT_call_line] = "call_line",
   3403       [DW_AT_description] = "description",
   3404       [DW_AT_binary_scale] = "binary_scale",
   3405       [DW_AT_decimal_scale] = "decimal_scale",
   3406       [DW_AT_small] = "small",
   3407       [DW_AT_decimal_sign] = "decimal_sign",
   3408       [DW_AT_digit_count] = "digit_count",
   3409       [DW_AT_picture_string] = "picture_string",
   3410       [DW_AT_mutable] = "mutable",
   3411       [DW_AT_threads_scaled] = "threads_scaled",
   3412       [DW_AT_explicit] = "explicit",
   3413       [DW_AT_object_pointer] = "object_pointer",
   3414       [DW_AT_endianity] = "endianity",
   3415       [DW_AT_elemental] = "elemental",
   3416       [DW_AT_pure] = "pure",
   3417       [DW_AT_recursive] = "recursive",
   3418       [DW_AT_signature] = "signature",
   3419       [DW_AT_main_subprogram] = "main_subprogram",
   3420       [DW_AT_data_bit_offset] = "data_bit_offset",
   3421       [DW_AT_const_expr] = "const_expr",
   3422       [DW_AT_enum_class] = "enum_class",
   3423       [DW_AT_linkage_name] = "linkage_name",
   3424     };
   3425   const unsigned int nknown_attrs = (sizeof (known_attrs)
   3426 				     / sizeof (known_attrs[0]));
   3427   static char buf[40];
   3428   const char *result = NULL;
   3429 
   3430   if (likely (attrnum < nknown_attrs))
   3431     result = known_attrs[attrnum];
   3432 
   3433   if (unlikely (result == NULL))
   3434     /* There are a few known extensions.  */
   3435     switch (attrnum)
   3436       {
   3437       case DW_AT_MIPS_fde:
   3438 	result = "MIPS_fde";
   3439 	break;
   3440 
   3441       case DW_AT_MIPS_loop_begin:
   3442 	result = "MIPS_loop_begin";
   3443 	break;
   3444 
   3445       case DW_AT_MIPS_tail_loop_begin:
   3446 	result = "MIPS_tail_loop_begin";
   3447 	break;
   3448 
   3449       case DW_AT_MIPS_epilog_begin:
   3450 	result = "MIPS_epilog_begin";
   3451 	break;
   3452 
   3453       case DW_AT_MIPS_loop_unroll_factor:
   3454 	result = "MIPS_loop_unroll_factor";
   3455 	break;
   3456 
   3457       case DW_AT_MIPS_software_pipeline_depth:
   3458 	result = "MIPS_software_pipeline_depth";
   3459 	break;
   3460 
   3461       case DW_AT_MIPS_linkage_name:
   3462 	result = "MIPS_linkage_name";
   3463 	break;
   3464 
   3465       case DW_AT_MIPS_stride:
   3466 	result = "MIPS_stride";
   3467 	break;
   3468 
   3469       case DW_AT_MIPS_abstract_name:
   3470 	result = "MIPS_abstract_name";
   3471 	break;
   3472 
   3473       case DW_AT_MIPS_clone_origin:
   3474 	result = "MIPS_clone_origin";
   3475 	break;
   3476 
   3477       case DW_AT_MIPS_has_inlines:
   3478 	result = "MIPS_has_inlines";
   3479 	break;
   3480 
   3481       case DW_AT_MIPS_stride_byte:
   3482 	result = "MIPS_stride_byte";
   3483 	break;
   3484 
   3485       case DW_AT_MIPS_stride_elem:
   3486 	result = "MIPS_stride_elem";
   3487 	break;
   3488 
   3489       case DW_AT_MIPS_ptr_dopetype:
   3490 	result = "MIPS_ptr_dopetype";
   3491 	break;
   3492 
   3493       case DW_AT_MIPS_allocatable_dopetype:
   3494 	result = "MIPS_allocatable_dopetype";
   3495 	break;
   3496 
   3497       case DW_AT_MIPS_assumed_shape_dopetype:
   3498 	result = "MIPS_assumed_shape_dopetype";
   3499 	break;
   3500 
   3501       case DW_AT_MIPS_assumed_size:
   3502 	result = "MIPS_assumed_size";
   3503 	break;
   3504 
   3505       case DW_AT_sf_names:
   3506 	result = "sf_names";
   3507 	break;
   3508 
   3509       case DW_AT_src_info:
   3510 	result = "src_info";
   3511 	break;
   3512 
   3513       case DW_AT_mac_info:
   3514 	result = "mac_info";
   3515 	break;
   3516 
   3517       case DW_AT_src_coords:
   3518 	result = "src_coords";
   3519 	break;
   3520 
   3521       case DW_AT_body_begin:
   3522 	result = "body_begin";
   3523 	break;
   3524 
   3525       case DW_AT_body_end:
   3526 	result = "body_end";
   3527 	break;
   3528 
   3529       case DW_AT_GNU_vector:
   3530 	result = "GNU_vector";
   3531 	break;
   3532 
   3533       case DW_AT_GNU_guarded_by:
   3534 	result = "GNU_guarded_by";
   3535 	break;
   3536 
   3537       case DW_AT_GNU_pt_guarded_by:
   3538 	result = "GNU_pt_guarded_by";
   3539 	break;
   3540 
   3541       case DW_AT_GNU_guarded:
   3542 	result = "GNU_guarded";
   3543 	break;
   3544 
   3545       case DW_AT_GNU_pt_guarded:
   3546 	result = "GNU_pt_guarded";
   3547 	break;
   3548 
   3549       case DW_AT_GNU_locks_excluded:
   3550 	result = "GNU_locks_excluded";
   3551 	break;
   3552 
   3553       case DW_AT_GNU_exclusive_locks_required:
   3554 	result = "GNU_exclusive_locks_required";
   3555 	break;
   3556 
   3557       case DW_AT_GNU_shared_locks_required:
   3558 	result = "GNU_shared_locks_required";
   3559 	break;
   3560 
   3561       case DW_AT_GNU_odr_signature:
   3562 	result = "GNU_odr_signature";
   3563 	break;
   3564 
   3565       case DW_AT_GNU_template_name:
   3566 	result = "GNU_template_name";
   3567 	break;
   3568 
   3569       case DW_AT_GNU_call_site_value:
   3570 	result = "GNU_call_site_value";
   3571 	break;
   3572 
   3573       case DW_AT_GNU_call_site_data_value:
   3574 	result = "GNU_call_site_data_value";
   3575 	break;
   3576 
   3577       case DW_AT_GNU_call_site_target:
   3578 	result = "GNU_call_site_target";
   3579 	break;
   3580 
   3581       case DW_AT_GNU_call_site_target_clobbered:
   3582 	result = "GNU_call_site_target_clobbered";
   3583 	break;
   3584 
   3585       case DW_AT_GNU_tail_call:
   3586 	result = "GNU_tail_call";
   3587 	break;
   3588 
   3589       case DW_AT_GNU_all_tail_call_sites:
   3590 	result = "GNU_all_tail_call_sites";
   3591 	break;
   3592 
   3593       case DW_AT_GNU_all_call_sites:
   3594 	result = "GNU_all_call_sites";
   3595 	break;
   3596 
   3597       case DW_AT_GNU_all_source_call_sites:
   3598 	result = "GNU_all_source_call_sites";
   3599 	break;
   3600 
   3601       default:
   3602 	if (attrnum < DW_AT_lo_user)
   3603 	  snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"),
   3604 		    attrnum);
   3605 	else
   3606 	  snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"),
   3607 		    attrnum);
   3608 	result = buf;
   3609 	break;
   3610       }
   3611 
   3612   return result;
   3613 }
   3614 
   3615 
   3616 static const char *
   3617 dwarf_form_string (unsigned int form)
   3618 {
   3619   static const char *const known_forms[] =
   3620     {
   3621       [DW_FORM_addr] = "addr",
   3622       [DW_FORM_block2] = "block2",
   3623       [DW_FORM_block4] = "block4",
   3624       [DW_FORM_data2] = "data2",
   3625       [DW_FORM_data4] = "data4",
   3626       [DW_FORM_data8] = "data8",
   3627       [DW_FORM_string] = "string",
   3628       [DW_FORM_block] = "block",
   3629       [DW_FORM_block1] = "block1",
   3630       [DW_FORM_data1] = "data1",
   3631       [DW_FORM_flag] = "flag",
   3632       [DW_FORM_sdata] = "sdata",
   3633       [DW_FORM_strp] = "strp",
   3634       [DW_FORM_udata] = "udata",
   3635       [DW_FORM_ref_addr] = "ref_addr",
   3636       [DW_FORM_ref1] = "ref1",
   3637       [DW_FORM_ref2] = "ref2",
   3638       [DW_FORM_ref4] = "ref4",
   3639       [DW_FORM_ref8] = "ref8",
   3640       [DW_FORM_ref_udata] = "ref_udata",
   3641       [DW_FORM_indirect] = "indirect",
   3642       [DW_FORM_sec_offset] = "sec_offset",
   3643       [DW_FORM_exprloc] = "exprloc",
   3644       [DW_FORM_flag_present] = "flag_present",
   3645       [DW_FORM_ref_sig8] = "ref_sig8",
   3646     };
   3647   const unsigned int nknown_forms = (sizeof (known_forms)
   3648 				     / sizeof (known_forms[0]));
   3649   static char buf[40];
   3650   const char *result = NULL;
   3651 
   3652   if (likely (form < nknown_forms))
   3653     result = known_forms[form];
   3654 
   3655   if (unlikely (result == NULL))
   3656     {
   3657       snprintf (buf, sizeof buf, gettext ("unknown form %#" PRIx64),
   3658 		(uint64_t) form);
   3659       result = buf;
   3660     }
   3661 
   3662   return result;
   3663 }
   3664 
   3665 
   3666 static const char *
   3667 dwarf_lang_string (unsigned int lang)
   3668 {
   3669   static const char *const known[] =
   3670     {
   3671       [DW_LANG_C89] = "ISO C89",
   3672       [DW_LANG_C] = "C",
   3673       [DW_LANG_Ada83] = "Ada83",
   3674       [DW_LANG_C_plus_plus] = "C++",
   3675       [DW_LANG_Cobol74] = "Cobol74",
   3676       [DW_LANG_Cobol85] = "Cobol85",
   3677       [DW_LANG_Fortran77] = "Fortran77",
   3678       [DW_LANG_Fortran90] = "Fortran90",
   3679       [DW_LANG_Pascal83] = "Pascal83",
   3680       [DW_LANG_Modula2] = "Modula2",
   3681       [DW_LANG_Java] = "Java",
   3682       [DW_LANG_C99] = "ISO C99",
   3683       [DW_LANG_Ada95] = "Ada95",
   3684       [DW_LANG_Fortran95] = "Fortran95",
   3685       [DW_LANG_PL1] = "PL1",
   3686       [DW_LANG_Objc] = "Objective C",
   3687       [DW_LANG_ObjC_plus_plus] = "Objective C++",
   3688       [DW_LANG_UPC] = "UPC",
   3689       [DW_LANG_D] = "D",
   3690     };
   3691 
   3692   if (likely (lang < sizeof (known) / sizeof (known[0])))
   3693     return known[lang];
   3694   else if (lang == DW_LANG_Mips_Assembler)
   3695     /* This language tag is used for assembler in general.  */
   3696     return "Assembler";
   3697 
   3698   if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user)
   3699     {
   3700       static char buf[30];
   3701       snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user);
   3702       return buf;
   3703     }
   3704 
   3705   return "???";
   3706 }
   3707 
   3708 
   3709 static const char *
   3710 dwarf_inline_string (unsigned int code)
   3711 {
   3712   static const char *const known[] =
   3713     {
   3714       [DW_INL_not_inlined] = "not_inlined",
   3715       [DW_INL_inlined] = "inlined",
   3716       [DW_INL_declared_not_inlined] = "declared_not_inlined",
   3717       [DW_INL_declared_inlined] = "declared_inlined"
   3718     };
   3719 
   3720   if (likely (code < sizeof (known) / sizeof (known[0])))
   3721     return known[code];
   3722 
   3723   return "???";
   3724 }
   3725 
   3726 
   3727 static const char *
   3728 dwarf_encoding_string (unsigned int code)
   3729 {
   3730   static const char *const known[] =
   3731     {
   3732       [DW_ATE_void] = "void",
   3733       [DW_ATE_address] = "address",
   3734       [DW_ATE_boolean] = "boolean",
   3735       [DW_ATE_complex_float] = "complex_float",
   3736       [DW_ATE_float] = "float",
   3737       [DW_ATE_signed] = "signed",
   3738       [DW_ATE_signed_char] = "signed_char",
   3739       [DW_ATE_unsigned] = "unsigned",
   3740       [DW_ATE_unsigned_char] = "unsigned_char",
   3741       [DW_ATE_imaginary_float] = "imaginary_float",
   3742       [DW_ATE_packed_decimal] = "packed_decimal",
   3743       [DW_ATE_numeric_string] = "numeric_string",
   3744       [DW_ATE_edited] = "edited",
   3745       [DW_ATE_signed_fixed] = "signed_fixed",
   3746       [DW_ATE_unsigned_fixed] = "unsigned_fixed",
   3747       [DW_ATE_decimal_float] = "decimal_float",
   3748     };
   3749 
   3750   if (likely (code < sizeof (known) / sizeof (known[0])))
   3751     return known[code];
   3752 
   3753   if (code >= DW_ATE_lo_user && code <= DW_ATE_hi_user)
   3754     {
   3755       static char buf[30];
   3756       snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_ATE_lo_user);
   3757       return buf;
   3758     }
   3759 
   3760   return "???";
   3761 }
   3762 
   3763 
   3764 static const char *
   3765 dwarf_access_string (unsigned int code)
   3766 {
   3767   static const char *const known[] =
   3768     {
   3769       [DW_ACCESS_public] = "public",
   3770       [DW_ACCESS_protected] = "protected",
   3771       [DW_ACCESS_private] = "private"
   3772     };
   3773 
   3774   if (likely (code < sizeof (known) / sizeof (known[0])))
   3775     return known[code];
   3776 
   3777   return "???";
   3778 }
   3779 
   3780 
   3781 static const char *
   3782 dwarf_visibility_string (unsigned int code)
   3783 {
   3784   static const char *const known[] =
   3785     {
   3786       [DW_VIS_local] = "local",
   3787       [DW_VIS_exported] = "exported",
   3788       [DW_VIS_qualified] = "qualified"
   3789     };
   3790 
   3791   if (likely (code < sizeof (known) / sizeof (known[0])))
   3792     return known[code];
   3793 
   3794   return "???";
   3795 }
   3796 
   3797 
   3798 static const char *
   3799 dwarf_virtuality_string (unsigned int code)
   3800 {
   3801   static const char *const known[] =
   3802     {
   3803       [DW_VIRTUALITY_none] = "none",
   3804       [DW_VIRTUALITY_virtual] = "virtual",
   3805       [DW_VIRTUALITY_pure_virtual] = "pure_virtual"
   3806     };
   3807 
   3808   if (likely (code < sizeof (known) / sizeof (known[0])))
   3809     return known[code];
   3810 
   3811   return "???";
   3812 }
   3813 
   3814 
   3815 static const char *
   3816 dwarf_identifier_case_string (unsigned int code)
   3817 {
   3818   static const char *const known[] =
   3819     {
   3820       [DW_ID_case_sensitive] = "sensitive",
   3821       [DW_ID_up_case] = "up_case",
   3822       [DW_ID_down_case] = "down_case",
   3823       [DW_ID_case_insensitive] = "insensitive"
   3824     };
   3825 
   3826   if (likely (code < sizeof (known) / sizeof (known[0])))
   3827     return known[code];
   3828 
   3829   return "???";
   3830 }
   3831 
   3832 
   3833 static const char *
   3834 dwarf_calling_convention_string (unsigned int code)
   3835 {
   3836   static const char *const known[] =
   3837     {
   3838       [DW_CC_normal] = "normal",
   3839       [DW_CC_program] = "program",
   3840       [DW_CC_nocall] = "nocall",
   3841     };
   3842 
   3843   if (likely (code < sizeof (known) / sizeof (known[0])))
   3844     return known[code];
   3845 
   3846   if (code >= DW_CC_lo_user && code <= DW_CC_hi_user)
   3847     {
   3848       static char buf[30];
   3849       snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_CC_lo_user);
   3850       return buf;
   3851     }
   3852 
   3853   return "???";
   3854 }
   3855 
   3856 
   3857 static const char *
   3858 dwarf_ordering_string (unsigned int code)
   3859 {
   3860   static const char *const known[] =
   3861     {
   3862       [DW_ORD_row_major] = "row_major",
   3863       [DW_ORD_col_major] = "col_major"
   3864     };
   3865 
   3866   if (likely (code < sizeof (known) / sizeof (known[0])))
   3867     return known[code];
   3868 
   3869   return "???";
   3870 }
   3871 
   3872 
   3873 static const char *
   3874 dwarf_discr_list_string (unsigned int code)
   3875 {
   3876   static const char *const known[] =
   3877     {
   3878       [DW_DSC_label] = "label",
   3879       [DW_DSC_range] = "range"
   3880     };
   3881 
   3882   if (likely (code < sizeof (known) / sizeof (known[0])))
   3883     return known[code];
   3884 
   3885   return "???";
   3886 }
   3887 
   3888 
   3889 static void
   3890 print_block (size_t n, const void *block)
   3891 {
   3892   if (n == 0)
   3893     puts (_("empty block"));
   3894   else
   3895     {
   3896       printf (_("%zu byte block:"), n);
   3897       const unsigned char *data = block;
   3898       do
   3899 	printf (" %02x", *data++);
   3900       while (--n > 0);
   3901       putchar ('\n');
   3902     }
   3903 }
   3904 
   3905 static void
   3906 print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
   3907 	   unsigned int vers, unsigned int addrsize, unsigned int offset_size,
   3908 	   Dwarf_Word len, const unsigned char *data)
   3909 {
   3910   const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
   3911 
   3912   static const char *const known[] =
   3913     {
   3914       [DW_OP_addr] = "addr",
   3915       [DW_OP_deref] = "deref",
   3916       [DW_OP_const1u] = "const1u",
   3917       [DW_OP_const1s] = "const1s",
   3918       [DW_OP_const2u] = "const2u",
   3919       [DW_OP_const2s] = "const2s",
   3920       [DW_OP_const4u] = "const4u",
   3921       [DW_OP_const4s] = "const4s",
   3922       [DW_OP_const8u] = "const8u",
   3923       [DW_OP_const8s] = "const8s",
   3924       [DW_OP_constu] = "constu",
   3925       [DW_OP_consts] = "consts",
   3926       [DW_OP_dup] = "dup",
   3927       [DW_OP_drop] = "drop",
   3928       [DW_OP_over] = "over",
   3929       [DW_OP_pick] = "pick",
   3930       [DW_OP_swap] = "swap",
   3931       [DW_OP_rot] = "rot",
   3932       [DW_OP_xderef] = "xderef",
   3933       [DW_OP_abs] = "abs",
   3934       [DW_OP_and] = "and",
   3935       [DW_OP_div] = "div",
   3936       [DW_OP_minus] = "minus",
   3937       [DW_OP_mod] = "mod",
   3938       [DW_OP_mul] = "mul",
   3939       [DW_OP_neg] = "neg",
   3940       [DW_OP_not] = "not",
   3941       [DW_OP_or] = "or",
   3942       [DW_OP_plus] = "plus",
   3943       [DW_OP_plus_uconst] = "plus_uconst",
   3944       [DW_OP_shl] = "shl",
   3945       [DW_OP_shr] = "shr",
   3946       [DW_OP_shra] = "shra",
   3947       [DW_OP_xor] = "xor",
   3948       [DW_OP_bra] = "bra",
   3949       [DW_OP_eq] = "eq",
   3950       [DW_OP_ge] = "ge",
   3951       [DW_OP_gt] = "gt",
   3952       [DW_OP_le] = "le",
   3953       [DW_OP_lt] = "lt",
   3954       [DW_OP_ne] = "ne",
   3955       [DW_OP_skip] = "skip",
   3956       [DW_OP_lit0] = "lit0",
   3957       [DW_OP_lit1] = "lit1",
   3958       [DW_OP_lit2] = "lit2",
   3959       [DW_OP_lit3] = "lit3",
   3960       [DW_OP_lit4] = "lit4",
   3961       [DW_OP_lit5] = "lit5",
   3962       [DW_OP_lit6] = "lit6",
   3963       [DW_OP_lit7] = "lit7",
   3964       [DW_OP_lit8] = "lit8",
   3965       [DW_OP_lit9] = "lit9",
   3966       [DW_OP_lit10] = "lit10",
   3967       [DW_OP_lit11] = "lit11",
   3968       [DW_OP_lit12] = "lit12",
   3969       [DW_OP_lit13] = "lit13",
   3970       [DW_OP_lit14] = "lit14",
   3971       [DW_OP_lit15] = "lit15",
   3972       [DW_OP_lit16] = "lit16",
   3973       [DW_OP_lit17] = "lit17",
   3974       [DW_OP_lit18] = "lit18",
   3975       [DW_OP_lit19] = "lit19",
   3976       [DW_OP_lit20] = "lit20",
   3977       [DW_OP_lit21] = "lit21",
   3978       [DW_OP_lit22] = "lit22",
   3979       [DW_OP_lit23] = "lit23",
   3980       [DW_OP_lit24] = "lit24",
   3981       [DW_OP_lit25] = "lit25",
   3982       [DW_OP_lit26] = "lit26",
   3983       [DW_OP_lit27] = "lit27",
   3984       [DW_OP_lit28] = "lit28",
   3985       [DW_OP_lit29] = "lit29",
   3986       [DW_OP_lit30] = "lit30",
   3987       [DW_OP_lit31] = "lit31",
   3988       [DW_OP_reg0] = "reg0",
   3989       [DW_OP_reg1] = "reg1",
   3990       [DW_OP_reg2] = "reg2",
   3991       [DW_OP_reg3] = "reg3",
   3992       [DW_OP_reg4] = "reg4",
   3993       [DW_OP_reg5] = "reg5",
   3994       [DW_OP_reg6] = "reg6",
   3995       [DW_OP_reg7] = "reg7",
   3996       [DW_OP_reg8] = "reg8",
   3997       [DW_OP_reg9] = "reg9",
   3998       [DW_OP_reg10] = "reg10",
   3999       [DW_OP_reg11] = "reg11",
   4000       [DW_OP_reg12] = "reg12",
   4001       [DW_OP_reg13] = "reg13",
   4002       [DW_OP_reg14] = "reg14",
   4003       [DW_OP_reg15] = "reg15",
   4004       [DW_OP_reg16] = "reg16",
   4005       [DW_OP_reg17] = "reg17",
   4006       [DW_OP_reg18] = "reg18",
   4007       [DW_OP_reg19] = "reg19",
   4008       [DW_OP_reg20] = "reg20",
   4009       [DW_OP_reg21] = "reg21",
   4010       [DW_OP_reg22] = "reg22",
   4011       [DW_OP_reg23] = "reg23",
   4012       [DW_OP_reg24] = "reg24",
   4013       [DW_OP_reg25] = "reg25",
   4014       [DW_OP_reg26] = "reg26",
   4015       [DW_OP_reg27] = "reg27",
   4016       [DW_OP_reg28] = "reg28",
   4017       [DW_OP_reg29] = "reg29",
   4018       [DW_OP_reg30] = "reg30",
   4019       [DW_OP_reg31] = "reg31",
   4020       [DW_OP_breg0] = "breg0",
   4021       [DW_OP_breg1] = "breg1",
   4022       [DW_OP_breg2] = "breg2",
   4023       [DW_OP_breg3] = "breg3",
   4024       [DW_OP_breg4] = "breg4",
   4025       [DW_OP_breg5] = "breg5",
   4026       [DW_OP_breg6] = "breg6",
   4027       [DW_OP_breg7] = "breg7",
   4028       [DW_OP_breg8] = "breg8",
   4029       [DW_OP_breg9] = "breg9",
   4030       [DW_OP_breg10] = "breg10",
   4031       [DW_OP_breg11] = "breg11",
   4032       [DW_OP_breg12] = "breg12",
   4033       [DW_OP_breg13] = "breg13",
   4034       [DW_OP_breg14] = "breg14",
   4035       [DW_OP_breg15] = "breg15",
   4036       [DW_OP_breg16] = "breg16",
   4037       [DW_OP_breg17] = "breg17",
   4038       [DW_OP_breg18] = "breg18",
   4039       [DW_OP_breg19] = "breg19",
   4040       [DW_OP_breg20] = "breg20",
   4041       [DW_OP_breg21] = "breg21",
   4042       [DW_OP_breg22] = "breg22",
   4043       [DW_OP_breg23] = "breg23",
   4044       [DW_OP_breg24] = "breg24",
   4045       [DW_OP_breg25] = "breg25",
   4046       [DW_OP_breg26] = "breg26",
   4047       [DW_OP_breg27] = "breg27",
   4048       [DW_OP_breg28] = "breg28",
   4049       [DW_OP_breg29] = "breg29",
   4050       [DW_OP_breg30] = "breg30",
   4051       [DW_OP_breg31] = "breg31",
   4052       [DW_OP_regx] = "regx",
   4053       [DW_OP_fbreg] = "fbreg",
   4054       [DW_OP_bregx] = "bregx",
   4055       [DW_OP_piece] = "piece",
   4056       [DW_OP_deref_size] = "deref_size",
   4057       [DW_OP_xderef_size] = "xderef_size",
   4058       [DW_OP_nop] = "nop",
   4059       [DW_OP_push_object_address] = "push_object_address",
   4060       [DW_OP_call2] = "call2",
   4061       [DW_OP_call4] = "call4",
   4062       [DW_OP_call_ref] = "call_ref",
   4063       [DW_OP_form_tls_address] = "form_tls_address",
   4064       [DW_OP_call_frame_cfa] = "call_frame_cfa",
   4065       [DW_OP_bit_piece] = "bit_piece",
   4066       [DW_OP_implicit_value] = "implicit_value",
   4067       [DW_OP_stack_value] = "stack_value",
   4068       [DW_OP_GNU_implicit_pointer] = "GNU_implicit_pointer",
   4069       [DW_OP_GNU_entry_value] = "GNU_entry_value",
   4070       [DW_OP_GNU_const_type] = "GNU_const_type",
   4071       [DW_OP_GNU_regval_type] = "GNU_regval_type",
   4072       [DW_OP_GNU_deref_type] = "GNU_deref_type",
   4073       [DW_OP_GNU_convert] = "GNU_convert",
   4074       [DW_OP_GNU_reinterpret] = "GNU_reinterpret",
   4075     };
   4076 
   4077   if (len == 0)
   4078     {
   4079       printf ("%*s(empty)\n", indent, "");
   4080       return;
   4081     }
   4082 
   4083 #define NEED(n)		if (len < (Dwarf_Word) (n)) goto invalid
   4084 #define CONSUME(n)	NEED (n); else len -= (n)
   4085 
   4086   Dwarf_Word offset = 0;
   4087   while (len-- > 0)
   4088     {
   4089       uint_fast8_t op = *data++;
   4090 
   4091       switch (op)
   4092 	{
   4093 	case DW_OP_addr:;
   4094 	  /* Address operand.  */
   4095 	  Dwarf_Word addr;
   4096 	  NEED (addrsize);
   4097 	  if (addrsize == 4)
   4098 	    addr = read_4ubyte_unaligned (dbg, data);
   4099 	  else
   4100 	    {
   4101 	      assert (addrsize == 8);
   4102 	      addr = read_8ubyte_unaligned (dbg, data);
   4103 	    }
   4104 	  data += addrsize;
   4105 	  CONSUME (addrsize);
   4106 
   4107 	  char *a = format_dwarf_addr (dwflmod, 0, addr);
   4108 	  printf ("%*s[%4" PRIuMAX "] %s %s\n",
   4109 		  indent, "", (uintmax_t) offset, known[op], a);
   4110 	  free (a);
   4111 
   4112 	  offset += 1 + addrsize;
   4113 	  break;
   4114 
   4115 	case DW_OP_call_ref:
   4116 	  /* Offset operand.  */
   4117 	  NEED (ref_size);
   4118 	  if (ref_size == 4)
   4119 	    addr = read_4ubyte_unaligned (dbg, data);
   4120 	  else
   4121 	    {
   4122 	      assert (ref_size == 8);
   4123 	      addr = read_8ubyte_unaligned (dbg, data);
   4124 	    }
   4125 	  data += ref_size;
   4126 	  CONSUME (ref_size);
   4127 
   4128 	  printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
   4129 		  indent, "", (uintmax_t) offset,
   4130 		  known[op], (uintmax_t) addr);
   4131 	  offset += 1 + ref_size;
   4132 	  break;
   4133 
   4134 	case DW_OP_deref_size:
   4135 	case DW_OP_xderef_size:
   4136 	case DW_OP_pick:
   4137 	case DW_OP_const1u:
   4138 	  // XXX value might be modified by relocation
   4139 	  NEED (1);
   4140 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
   4141 		  indent, "", (uintmax_t) offset,
   4142 		  known[op], *((uint8_t *) data));
   4143 	  ++data;
   4144 	  --len;
   4145 	  offset += 2;
   4146 	  break;
   4147 
   4148 	case DW_OP_const2u:
   4149 	  NEED (2);
   4150 	  // XXX value might be modified by relocation
   4151 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
   4152 		  indent, "", (uintmax_t) offset,
   4153 		  known[op], read_2ubyte_unaligned (dbg, data));
   4154 	  CONSUME (2);
   4155 	  data += 2;
   4156 	  offset += 3;
   4157 	  break;
   4158 
   4159 	case DW_OP_const4u:
   4160 	  NEED (4);
   4161 	  // XXX value might be modified by relocation
   4162 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
   4163 		  indent, "", (uintmax_t) offset,
   4164 		  known[op], read_4ubyte_unaligned (dbg, data));
   4165 	  CONSUME (4);
   4166 	  data += 4;
   4167 	  offset += 5;
   4168 	  break;
   4169 
   4170 	case DW_OP_const8u:
   4171 	  NEED (8);
   4172 	  // XXX value might be modified by relocation
   4173 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
   4174 		  indent, "", (uintmax_t) offset,
   4175 		  known[op], read_8ubyte_unaligned (dbg, data));
   4176 	  CONSUME (8);
   4177 	  data += 8;
   4178 	  offset += 9;
   4179 	  break;
   4180 
   4181 	case DW_OP_const1s:
   4182 	  NEED (1);
   4183 	  // XXX value might be modified by relocation
   4184 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
   4185 		  indent, "", (uintmax_t) offset,
   4186 		  known[op], *((int8_t *) data));
   4187 	  ++data;
   4188 	  --len;
   4189 	  offset += 2;
   4190 	  break;
   4191 
   4192 	case DW_OP_const2s:
   4193 	  NEED (2);
   4194 	  // XXX value might be modified by relocation
   4195 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
   4196 		  indent, "", (uintmax_t) offset,
   4197 		  known[op], read_2sbyte_unaligned (dbg, data));
   4198 	  CONSUME (2);
   4199 	  data += 2;
   4200 	  offset += 3;
   4201 	  break;
   4202 
   4203 	case DW_OP_const4s:
   4204 	  NEED (4);
   4205 	  // XXX value might be modified by relocation
   4206 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
   4207 		  indent, "", (uintmax_t) offset,
   4208 		  known[op], read_4sbyte_unaligned (dbg, data));
   4209 	  CONSUME (4);
   4210 	  data += 4;
   4211 	  offset += 5;
   4212 	  break;
   4213 
   4214 	case DW_OP_const8s:
   4215 	  NEED (8);
   4216 	  // XXX value might be modified by relocation
   4217 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
   4218 		  indent, "", (uintmax_t) offset,
   4219 		  known[op], read_8sbyte_unaligned (dbg, data));
   4220 	  CONSUME (8);
   4221 	  data += 8;
   4222 	  offset += 9;
   4223 	  break;
   4224 
   4225 	case DW_OP_piece:
   4226 	case DW_OP_regx:
   4227 	case DW_OP_plus_uconst:
   4228 	case DW_OP_constu:;
   4229 	  const unsigned char *start = data;
   4230 	  uint64_t uleb;
   4231 	  NEED (1);
   4232 	  get_uleb128 (uleb, data); /* XXX check overrun */
   4233 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
   4234 		  indent, "", (uintmax_t) offset, known[op], uleb);
   4235 	  CONSUME (data - start);
   4236 	  offset += 1 + (data - start);
   4237 	  break;
   4238 
   4239 	case DW_OP_bit_piece:
   4240 	  start = data;
   4241 	  uint64_t uleb2;
   4242 	  NEED (2);
   4243 	  get_uleb128 (uleb, data); /* XXX check overrun */
   4244 	  get_uleb128 (uleb2, data); /* XXX check overrun */
   4245 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
   4246 		  indent, "", (uintmax_t) offset, known[op], uleb, uleb2);
   4247 	  CONSUME (data - start);
   4248 	  offset += 1 + (data - start);
   4249 	  break;
   4250 
   4251 	case DW_OP_fbreg:
   4252 	case DW_OP_breg0 ... DW_OP_breg31:
   4253 	case DW_OP_consts:
   4254 	  start = data;
   4255 	  int64_t sleb;
   4256 	  NEED (1);
   4257 	  get_sleb128 (sleb, data); /* XXX check overrun */
   4258 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
   4259 		  indent, "", (uintmax_t) offset, known[op], sleb);
   4260 	  CONSUME (data - start);
   4261 	  offset += 1 + (data - start);
   4262 	  break;
   4263 
   4264 	case DW_OP_bregx:
   4265 	  start = data;
   4266 	  NEED (2);
   4267 	  get_uleb128 (uleb, data); /* XXX check overrun */
   4268 	  get_sleb128 (sleb, data); /* XXX check overrun */
   4269 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
   4270 		  indent, "", (uintmax_t) offset, known[op], uleb, sleb);
   4271 	  CONSUME (data - start);
   4272 	  offset += 1 + (data - start);
   4273 	  break;
   4274 
   4275 	case DW_OP_call2:
   4276 	  NEED (2);
   4277 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
   4278 		  indent, "", (uintmax_t) offset, known[op],
   4279 		  read_2ubyte_unaligned (dbg, data));
   4280 	  CONSUME (2);
   4281 	  offset += 3;
   4282 	  break;
   4283 
   4284 	case DW_OP_call4:
   4285 	  NEED (4);
   4286 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
   4287 		  indent, "", (uintmax_t) offset, known[op],
   4288 		  read_4ubyte_unaligned (dbg, data));
   4289 	  CONSUME (4);
   4290 	  offset += 5;
   4291 	  break;
   4292 
   4293 	case DW_OP_skip:
   4294 	case DW_OP_bra:
   4295 	  NEED (2);
   4296 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
   4297 		  indent, "", (uintmax_t) offset, known[op],
   4298 		  (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
   4299 	  CONSUME (2);
   4300 	  data += 2;
   4301 	  offset += 3;
   4302 	  break;
   4303 
   4304 	case DW_OP_implicit_value:
   4305 	  start = data;
   4306 	  NEED (1);
   4307 	  get_uleb128 (uleb, data); /* XXX check overrun */
   4308 	  printf ("%*s[%4" PRIuMAX "] %s: ",
   4309 		  indent, "", (uintmax_t) offset, known[op]);
   4310 	  NEED (uleb);
   4311 	  print_block (uleb, data);
   4312 	  data += uleb;
   4313 	  CONSUME (data - start);
   4314 	  offset += 1 + (data - start);
   4315 	  break;
   4316 
   4317 	case DW_OP_GNU_implicit_pointer:
   4318 	  /* DIE offset operand.  */
   4319 	  start = data;
   4320 	  NEED (ref_size + 1);
   4321 	  if (ref_size == 4)
   4322 	    addr = read_4ubyte_unaligned (dbg, data);
   4323 	  else
   4324 	    {
   4325 	      assert (ref_size == 8);
   4326 	      addr = read_8ubyte_unaligned (dbg, data);
   4327 	    }
   4328 	  data += ref_size;
   4329 	  /* Byte offset operand.  */
   4330 	  get_sleb128 (sleb, data); /* XXX check overrun */
   4331 
   4332 	  printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX ", %+" PRId64 "\n",
   4333 		  indent, "", (intmax_t) offset,
   4334 		  known[op], (uintmax_t) addr, sleb);
   4335 	  CONSUME (data - start);
   4336 	  offset += 1 + (data - start);
   4337 	  break;
   4338 
   4339 	case DW_OP_GNU_entry_value:
   4340 	  /* Size plus expression block.  */
   4341 	  start = data;
   4342 	  NEED (1);
   4343 	  get_uleb128 (uleb, data); /* XXX check overrun */
   4344 	  printf ("%*s[%4" PRIuMAX "] %s:\n",
   4345 		  indent, "", (uintmax_t) offset, known[op]);
   4346 	  NEED (uleb);
   4347 	  print_ops (dwflmod, dbg, indent + 6, indent + 6, vers,
   4348 		     addrsize, offset_size, uleb, data);
   4349 	  data += uleb;
   4350 	  CONSUME (data - start);
   4351 	  offset += 1 + (data - start);
   4352 	  break;
   4353 
   4354 	case DW_OP_GNU_const_type:
   4355 	  /* DIE offset, size plus block.  */
   4356 	  start = data;
   4357 	  NEED (2);
   4358 	  get_uleb128 (uleb, data); /* XXX check overrun */
   4359 	  uint8_t usize = *(uint8_t *) data++;
   4360 	  NEED (usize);
   4361 	  printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] ",
   4362 		  indent, "", (uintmax_t) offset, known[op], uleb);
   4363 	  print_block (usize, data);
   4364 	  data += usize;
   4365 	  CONSUME (data - start);
   4366 	  offset += 1 + (data - start);
   4367 	  break;
   4368 
   4369 	case DW_OP_GNU_regval_type:
   4370 	  start = data;
   4371 	  NEED (2);
   4372 	  get_uleb128 (uleb, data); /* XXX check overrun */
   4373 	  get_uleb128 (uleb2, data); /* XXX check overrun */
   4374 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %#" PRIx64 "\n",
   4375 		  indent, "", (uintmax_t) offset, known[op], uleb, uleb2);
   4376 	  CONSUME (data - start);
   4377 	  offset += 1 + (data - start);
   4378 	  break;
   4379 
   4380 	case DW_OP_GNU_deref_type:
   4381 	  start = data;
   4382 	  NEED (2);
   4383 	  usize = *(uint8_t *) data++;
   4384 	  get_uleb128 (uleb, data); /* XXX check overrun */
   4385 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
   4386 		  indent, "", (uintmax_t) offset,
   4387 		  known[op], usize, uleb);
   4388 	  CONSUME (data - start);
   4389 	  offset += 1 + (data - start);
   4390 	  break;
   4391 
   4392 	case DW_OP_GNU_convert:
   4393 	case DW_OP_GNU_reinterpret:
   4394 	  start = data;
   4395 	  NEED (1);
   4396 	  get_uleb128 (uleb, data); /* XXX check overrun */
   4397 	  printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
   4398 		  indent, "", (uintmax_t) offset, known[op], uleb);
   4399 	  CONSUME (data - start);
   4400 	  offset += 1 + (data - start);
   4401 	  break;
   4402 
   4403 	default:
   4404 	  /* No Operand.  */
   4405 	  if (op < sizeof known / sizeof known[0] && known[op] != NULL)
   4406 	    printf ("%*s[%4" PRIuMAX "] %s\n",
   4407 		    indent, "", (uintmax_t) offset, known[op]);
   4408 	  else
   4409 	    printf ("%*s[%4" PRIuMAX "] %#x\n",
   4410 		    indent, "", (uintmax_t) offset, op);
   4411 	  ++offset;
   4412 	  break;
   4413 	}
   4414 
   4415       indent = indentrest;
   4416       continue;
   4417 
   4418     invalid:
   4419       printf (gettext ("%*s[%4" PRIuMAX "] %s  <TRUNCATED>\n"),
   4420 	      indent, "", (uintmax_t) offset, known[op]);
   4421       break;
   4422     }
   4423 }
   4424 
   4425 
   4426 struct listptr
   4427 {
   4428   Dwarf_Off offset:(64 - 3);
   4429   bool addr64:1;
   4430   bool dwarf64:1;
   4431   bool warned:1;
   4432 };
   4433 
   4434 #define listptr_offset_size(p)	((p)->dwarf64 ? 8 : 4)
   4435 #define listptr_address_size(p)	((p)->addr64 ? 8 : 4)
   4436 
   4437 static int
   4438 compare_listptr (const void *a, const void *b, void *arg)
   4439 {
   4440   const char *name = arg;
   4441   struct listptr *p1 = (void *) a;
   4442   struct listptr *p2 = (void *) b;
   4443 
   4444   if (p1->offset < p2->offset)
   4445     return -1;
   4446   if (p1->offset > p2->offset)
   4447     return 1;
   4448 
   4449   if (!p1->warned && !p2->warned)
   4450     {
   4451       if (p1->addr64 != p2->addr64)
   4452 	{
   4453 	  p1->warned = p2->warned = true;
   4454 	  error (0, 0,
   4455 		 gettext ("%s %#" PRIx64 " used with different address sizes"),
   4456 		 name, (uint64_t) p1->offset);
   4457 	}
   4458       if (p1->dwarf64 != p2->dwarf64)
   4459 	{
   4460 	  p1->warned = p2->warned = true;
   4461 	  error (0, 0,
   4462 		 gettext ("%s %#" PRIx64 " used with different offset sizes"),
   4463 		 name, (uint64_t) p1->offset);
   4464 	}
   4465     }
   4466 
   4467   return 0;
   4468 }
   4469 
   4470 struct listptr_table
   4471 {
   4472   size_t n;
   4473   size_t alloc;
   4474   struct listptr *table;
   4475 };
   4476 
   4477 static struct listptr_table known_loclistptr;
   4478 static struct listptr_table known_rangelistptr;
   4479 
   4480 static void
   4481 reset_listptr (struct listptr_table *table)
   4482 {
   4483   free (table->table);
   4484   table->table = NULL;
   4485   table->n = table->alloc = 0;
   4486 }
   4487 
   4488 static void
   4489 notice_listptr (enum section_e section, struct listptr_table *table,
   4490 		uint_fast8_t address_size, uint_fast8_t offset_size,
   4491 		Dwarf_Off offset)
   4492 {
   4493   if (print_debug_sections & section)
   4494     {
   4495       if (table->n == table->alloc)
   4496 	{
   4497 	  if (table->alloc == 0)
   4498 	    table->alloc = 128;
   4499 	  else
   4500 	    table->alloc *= 2;
   4501 	  table->table = xrealloc (table->table,
   4502 				   table->alloc * sizeof table->table[0]);
   4503 	}
   4504 
   4505       struct listptr *p = &table->table[table->n++];
   4506 
   4507       *p = (struct listptr)
   4508 	{
   4509 	  .addr64 = address_size == 8,
   4510 	  .dwarf64 = offset_size == 8,
   4511 	  .offset = offset
   4512 	};
   4513       assert (p->offset == offset);
   4514     }
   4515 }
   4516 
   4517 static void
   4518 sort_listptr (struct listptr_table *table, const char *name)
   4519 {
   4520   if (table->n > 0)
   4521     qsort_r (table->table, table->n, sizeof table->table[0],
   4522 	     &compare_listptr, (void *) name);
   4523 }
   4524 
   4525 static bool
   4526 skip_listptr_hole (struct listptr_table *table, size_t *idxp,
   4527 		   uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
   4528 		   ptrdiff_t offset, unsigned char **readp, unsigned char *endp)
   4529 {
   4530   if (table->n == 0)
   4531     return false;
   4532 
   4533   while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
   4534     ++*idxp;
   4535 
   4536   struct listptr *p = &table->table[*idxp];
   4537 
   4538   if (*idxp == table->n
   4539       || p->offset >= (Dwarf_Off) (endp - *readp + offset))
   4540     {
   4541       *readp = endp;
   4542       printf (gettext (" [%6tx]  <UNUSED GARBAGE IN REST OF SECTION>\n"),
   4543 	      offset);
   4544       return true;
   4545     }
   4546 
   4547   if (p->offset != (Dwarf_Off) offset)
   4548     {
   4549       *readp += p->offset - offset;
   4550       printf (gettext (" [%6tx]  <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
   4551 	      offset, (Dwarf_Off) p->offset - offset);
   4552       return true;
   4553     }
   4554 
   4555   if (address_sizep != NULL)
   4556     *address_sizep = listptr_address_size (p);
   4557   if (offset_sizep != NULL)
   4558     *offset_sizep = listptr_offset_size (p);
   4559 
   4560   return false;
   4561 }
   4562 
   4563 
   4564 static void
   4565 print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   4566 			    Ebl *ebl, GElf_Ehdr *ehdr,
   4567 			    Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   4568 {
   4569   printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
   4570 		   " [ Code]\n"),
   4571 	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
   4572 	  (uint64_t) shdr->sh_offset);
   4573 
   4574   Dwarf_Off offset = 0;
   4575   while (offset < dbg->sectiondata[IDX_debug_abbrev]->d_size)
   4576     {
   4577       printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
   4578 	      offset);
   4579 
   4580       while (1)
   4581 	{
   4582 	  size_t length;
   4583 	  Dwarf_Abbrev abbrev;
   4584 
   4585 	  int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
   4586 	  if (res != 0)
   4587 	    {
   4588 	      if (unlikely (res < 0))
   4589 		{
   4590 		  printf (gettext ("\
   4591  *** error while reading abbreviation: %s\n"),
   4592 			  dwarf_errmsg (-1));
   4593 		  return;
   4594 		}
   4595 
   4596 	      /* This is the NUL byte at the end of the section.  */
   4597 	      ++offset;
   4598 	      break;
   4599 	    }
   4600 
   4601 	  /* We know these calls can never fail.  */
   4602 	  unsigned int code = dwarf_getabbrevcode (&abbrev);
   4603 	  unsigned int tag = dwarf_getabbrevtag (&abbrev);
   4604 	  int has_children = dwarf_abbrevhaschildren (&abbrev);
   4605 
   4606 	  printf (gettext (" [%5u] offset: %" PRId64
   4607 			   ", children: %s, tag: %s\n"),
   4608 		  code, (int64_t) offset,
   4609 		  has_children ? gettext ("yes") : gettext ("no"),
   4610 		  dwarf_tag_string (tag));
   4611 
   4612 	  size_t cnt = 0;
   4613 	  unsigned int name;
   4614 	  unsigned int form;
   4615 	  Dwarf_Off enoffset;
   4616 	  while (dwarf_getabbrevattr (&abbrev, cnt,
   4617 				      &name, &form, &enoffset) == 0)
   4618 	    {
   4619 	      printf ("          attr: %s, form: %s, offset: %#" PRIx64 "\n",
   4620 		      dwarf_attr_string (name), dwarf_form_string (form),
   4621 		      (uint64_t) enoffset);
   4622 
   4623 	      ++cnt;
   4624 	    }
   4625 
   4626 	  offset += length;
   4627 	}
   4628     }
   4629 }
   4630 
   4631 
   4632 /* Print content of DWARF .debug_aranges section.  We fortunately do
   4633    not have to know a bit about the structure of the section, libdwarf
   4634    takes care of it.  */
   4635 static void
   4636 print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   4637 			     Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
   4638 			     GElf_Shdr *shdr, Dwarf *dbg)
   4639 {
   4640   Dwarf_Aranges *aranges;
   4641   size_t cnt;
   4642   if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
   4643     {
   4644       error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
   4645 	     dwarf_errmsg (-1));
   4646       return;
   4647     }
   4648 
   4649   printf (ngettext ("\
   4650 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
   4651 		    "\
   4652 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
   4653 		    cnt),
   4654 	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
   4655 	  (uint64_t) shdr->sh_offset, cnt);
   4656 
   4657   /* Compute floor(log16(cnt)).  */
   4658   size_t tmp = cnt;
   4659   int digits = 1;
   4660   while (tmp >= 16)
   4661     {
   4662       ++digits;
   4663       tmp >>= 4;
   4664     }
   4665 
   4666   for (size_t n = 0; n < cnt; ++n)
   4667     {
   4668       Dwarf_Arange *runp = dwarf_onearange (aranges, n);
   4669       if (unlikely (runp == NULL))
   4670 	{
   4671 	  printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
   4672 	  return;
   4673 	}
   4674 
   4675       Dwarf_Addr start;
   4676       Dwarf_Word length;
   4677       Dwarf_Off offset;
   4678 
   4679       if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
   4680 	printf (gettext (" [%*zu] ???\n"), digits, n);
   4681       else
   4682 	printf (gettext (" [%*zu] start: %0#*" PRIx64
   4683 			 ", length: %5" PRIu64 ", CU DIE offset: %6"
   4684 			 PRId64 "\n"),
   4685 		digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
   4686 		(uint64_t) start, (uint64_t) length, (int64_t) offset);
   4687     }
   4688 }
   4689 
   4690 /* Print content of DWARF .debug_ranges section.  */
   4691 static void
   4692 print_debug_ranges_section (Dwfl_Module *dwflmod,
   4693 			    Ebl *ebl, GElf_Ehdr *ehdr,
   4694 			    Elf_Scn *scn, GElf_Shdr *shdr,
   4695 			    Dwarf *dbg)
   4696 {
   4697   Elf_Data *data = elf_rawdata (scn, NULL);
   4698 
   4699   if (unlikely (data == NULL))
   4700     {
   4701       error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
   4702 	     elf_errmsg (-1));
   4703       return;
   4704     }
   4705 
   4706   printf (gettext ("\
   4707 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
   4708 	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
   4709 	  (uint64_t) shdr->sh_offset);
   4710 
   4711   sort_listptr (&known_rangelistptr, "rangelistptr");
   4712   size_t listptr_idx = 0;
   4713 
   4714   uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
   4715 
   4716   bool first = true;
   4717   unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
   4718   unsigned char *readp = data->d_buf;
   4719   while (readp < endp)
   4720     {
   4721       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
   4722 
   4723       if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
   4724 				      &address_size, NULL,
   4725 				      offset, &readp, endp))
   4726 	continue;
   4727 
   4728       if (unlikely (data->d_size - offset < address_size * 2))
   4729 	{
   4730 	  printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
   4731 	  break;
   4732 	}
   4733 
   4734       Dwarf_Addr begin;
   4735       Dwarf_Addr end;
   4736       if (address_size == 8)
   4737 	{
   4738 	  begin = read_8ubyte_unaligned_inc (dbg, readp);
   4739 	  end = read_8ubyte_unaligned_inc (dbg, readp);
   4740 	}
   4741       else
   4742 	{
   4743 	  begin = read_4ubyte_unaligned_inc (dbg, readp);
   4744 	  end = read_4ubyte_unaligned_inc (dbg, readp);
   4745 	  if (begin == (Dwarf_Addr) (uint32_t) -1)
   4746 	    begin = (Dwarf_Addr) -1l;
   4747 	}
   4748 
   4749       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
   4750 	{
   4751 	  char *b = format_dwarf_addr (dwflmod, address_size, end);
   4752 	  printf (gettext (" [%6tx]  base address %s\n"), offset, b);
   4753 	  free (b);
   4754 	}
   4755       else if (begin == 0 && end == 0) /* End of list entry.  */
   4756 	{
   4757 	  if (first)
   4758 	    printf (gettext (" [%6tx]  empty list\n"), offset);
   4759 	  first = true;
   4760 	}
   4761       else
   4762 	{
   4763 	  char *b = format_dwarf_addr (dwflmod, address_size, begin);
   4764 	  char *e = format_dwarf_addr (dwflmod, address_size, end);
   4765 	  /* We have an address range entry.  */
   4766 	  if (first)		/* First address range entry in a list.  */
   4767 	    printf (gettext (" [%6tx]  %s..%s\n"), offset, b, e);
   4768 	  else
   4769 	    printf (gettext ("           %s..%s\n"), b, e);
   4770 	  free (b);
   4771 	  free (e);
   4772 
   4773 	  first = false;
   4774 	}
   4775     }
   4776 }
   4777 
   4778 #define REGNAMESZ 16
   4779 static const char *
   4780 register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
   4781 	       char name[REGNAMESZ], int *bits, int *type)
   4782 {
   4783   const char *set;
   4784   const char *pfx;
   4785   int ignore;
   4786   ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
   4787 				 bits ?: &ignore, type ?: &ignore);
   4788   if (n <= 0)
   4789     {
   4790       snprintf (name, REGNAMESZ, "reg%u", loc->regno);
   4791       if (bits != NULL)
   4792 	*bits = loc->bits;
   4793       if (type != NULL)
   4794 	*type = DW_ATE_unsigned;
   4795       set = "??? unrecognized";
   4796     }
   4797   else
   4798     {
   4799       if (bits != NULL && *bits <= 0)
   4800 	*bits = loc->bits;
   4801       if (type != NULL && *type == DW_ATE_void)
   4802 	*type = DW_ATE_unsigned;
   4803 
   4804     }
   4805   return set;
   4806 }
   4807 
   4808 static void
   4809 print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
   4810 		   Dwarf_Word vma_base, unsigned int code_align,
   4811 		   int data_align,
   4812 		   unsigned int version, unsigned int ptr_size,
   4813 		   Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
   4814 {
   4815   char regnamebuf[REGNAMESZ];
   4816   const char *regname (unsigned int regno)
   4817   {
   4818     register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
   4819     return regnamebuf;
   4820   }
   4821 
   4822   puts ("\n   Program:");
   4823   Dwarf_Word pc = vma_base;
   4824   while (readp < endp)
   4825     {
   4826       unsigned int opcode = *readp++;
   4827 
   4828       if (opcode < DW_CFA_advance_loc)
   4829 	/* Extended opcode.  */
   4830 	switch (opcode)
   4831 	  {
   4832 	    uint64_t op1;
   4833 	    int64_t sop1;
   4834 	    uint64_t op2;
   4835 	    int64_t sop2;
   4836 
   4837 	  case DW_CFA_nop:
   4838 	    puts ("     nop");
   4839 	    break;
   4840 	  case DW_CFA_set_loc:
   4841 	    // XXX overflow check
   4842 	    get_uleb128 (op1, readp);
   4843 	    op1 += vma_base;
   4844 	    printf ("     set_loc %" PRIu64 "\n", op1 * code_align);
   4845 	    break;
   4846 	  case DW_CFA_advance_loc1:
   4847 	    printf ("     advance_loc1 %u to %#" PRIx64 "\n",
   4848 		    *readp, pc += *readp * code_align);
   4849 	    ++readp;
   4850 	    break;
   4851 	  case DW_CFA_advance_loc2:
   4852 	    op1 = read_2ubyte_unaligned_inc (dbg, readp);
   4853 	    printf ("     advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
   4854 		    op1, pc += op1 * code_align);
   4855 	    break;
   4856 	  case DW_CFA_advance_loc4:
   4857 	    op1 = read_4ubyte_unaligned_inc (dbg, readp);
   4858 	    printf ("     advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
   4859 		    op1, pc += op1 * code_align);
   4860 	    break;
   4861 	  case DW_CFA_offset_extended:
   4862 	    // XXX overflow check
   4863 	    get_uleb128 (op1, readp);
   4864 	    get_uleb128 (op2, readp);
   4865 	    printf ("     offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
   4866 		    "\n",
   4867 		    op1, regname (op1), op2 * data_align);
   4868 	    break;
   4869 	  case DW_CFA_restore_extended:
   4870 	    // XXX overflow check
   4871 	    get_uleb128 (op1, readp);
   4872 	    printf ("     restore_extended r%" PRIu64 " (%s)\n",
   4873 		    op1, regname (op1));
   4874 	    break;
   4875 	  case DW_CFA_undefined:
   4876 	    // XXX overflow check
   4877 	    get_uleb128 (op1, readp);
   4878 	    printf ("     undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
   4879 	    break;
   4880 	  case DW_CFA_same_value:
   4881 	    // XXX overflow check
   4882 	    get_uleb128 (op1, readp);
   4883 	    printf ("     same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
   4884 	    break;
   4885 	  case DW_CFA_register:
   4886 	    // XXX overflow check
   4887 	    get_uleb128 (op1, readp);
   4888 	    get_uleb128 (op2, readp);
   4889 	    printf ("     register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
   4890 		    op1, regname (op1), op2, regname (op2));
   4891 	    break;
   4892 	  case DW_CFA_remember_state:
   4893 	    puts ("     remember_state");
   4894 	    break;
   4895 	  case DW_CFA_restore_state:
   4896 	    puts ("     restore_state");
   4897 	    break;
   4898 	  case DW_CFA_def_cfa:
   4899 	    // XXX overflow check
   4900 	    get_uleb128 (op1, readp);
   4901 	    get_uleb128 (op2, readp);
   4902 	    printf ("     def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
   4903 		    op1, regname (op1), op2);
   4904 	    break;
   4905 	  case DW_CFA_def_cfa_register:
   4906 	    // XXX overflow check
   4907 	    get_uleb128 (op1, readp);
   4908 	    printf ("     def_cfa_register r%" PRIu64 " (%s)\n",
   4909 		    op1, regname (op1));
   4910 	    break;
   4911 	  case DW_CFA_def_cfa_offset:
   4912 	    // XXX overflow check
   4913 	    get_uleb128 (op1, readp);
   4914 	    printf ("     def_cfa_offset %" PRIu64 "\n", op1);
   4915 	    break;
   4916 	  case DW_CFA_def_cfa_expression:
   4917 	    // XXX overflow check
   4918 	    get_uleb128 (op1, readp);	/* Length of DW_FORM_block.  */
   4919 	    printf ("     def_cfa_expression %" PRIu64 "\n", op1);
   4920 	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op1, readp);
   4921 	    readp += op1;
   4922 	    break;
   4923 	  case DW_CFA_expression:
   4924 	    // XXX overflow check
   4925 	    get_uleb128 (op1, readp);
   4926 	    get_uleb128 (op2, readp);	/* Length of DW_FORM_block.  */
   4927 	    printf ("     expression r%" PRIu64 " (%s) \n",
   4928 		    op1, regname (op1));
   4929 	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op2, readp);
   4930 	    readp += op2;
   4931 	    break;
   4932 	  case DW_CFA_offset_extended_sf:
   4933 	    // XXX overflow check
   4934 	    get_uleb128 (op1, readp);
   4935 	    get_sleb128 (sop2, readp);
   4936 	    printf ("     offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
   4937 		    PRId64 "\n",
   4938 		    op1, regname (op1), sop2 * data_align);
   4939 	    break;
   4940 	  case DW_CFA_def_cfa_sf:
   4941 	    // XXX overflow check
   4942 	    get_uleb128 (op1, readp);
   4943 	    get_sleb128 (sop2, readp);
   4944 	    printf ("     def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
   4945 		    op1, regname (op1), sop2 * data_align);
   4946 	    break;
   4947 	  case DW_CFA_def_cfa_offset_sf:
   4948 	    // XXX overflow check
   4949 	    get_sleb128 (sop1, readp);
   4950 	    printf ("     def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
   4951 	    break;
   4952 	  case DW_CFA_val_offset:
   4953 	    // XXX overflow check
   4954 	    get_uleb128 (op1, readp);
   4955 	    get_uleb128 (op2, readp);
   4956 	    printf ("     val_offset %" PRIu64 " at offset %" PRIu64 "\n",
   4957 		    op1, op2 * data_align);
   4958 	    break;
   4959 	  case DW_CFA_val_offset_sf:
   4960 	    // XXX overflow check
   4961 	    get_uleb128 (op1, readp);
   4962 	    get_sleb128 (sop2, readp);
   4963 	    printf ("     val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
   4964 		    op1, sop2 * data_align);
   4965 	    break;
   4966 	  case DW_CFA_val_expression:
   4967 	    // XXX overflow check
   4968 	    get_uleb128 (op1, readp);
   4969 	    get_uleb128 (op2, readp);	/* Length of DW_FORM_block.  */
   4970 	    printf ("     val_expression r%" PRIu64 " (%s)\n",
   4971 		    op1, regname (op1));
   4972 	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op2, readp);
   4973 	    readp += op2;
   4974 	    break;
   4975 	  case DW_CFA_MIPS_advance_loc8:
   4976 	    op1 = read_8ubyte_unaligned_inc (dbg, readp);
   4977 	    printf ("     MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
   4978 		    op1, pc += op1 * code_align);
   4979 	    break;
   4980 	  case DW_CFA_GNU_window_save:
   4981 	    puts ("     GNU_window_save");
   4982 	    break;
   4983 	  case DW_CFA_GNU_args_size:
   4984 	    // XXX overflow check
   4985 	    get_uleb128 (op1, readp);
   4986 	    printf ("     args_size %" PRIu64 "\n", op1);
   4987 	    break;
   4988 	  default:
   4989 	    printf ("     ??? (%u)\n", opcode);
   4990 	    break;
   4991 	  }
   4992       else if (opcode < DW_CFA_offset)
   4993 	printf ("     advance_loc %u to %#" PRIx64 "\n",
   4994 		opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
   4995       else if (opcode < DW_CFA_restore)
   4996 	{
   4997 	  uint64_t offset;
   4998 	  // XXX overflow check
   4999 	  get_uleb128 (offset, readp);
   5000 	  printf ("     offset r%u (%s) at cfa%+" PRId64 "\n",
   5001 		  opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
   5002 	}
   5003       else
   5004 	printf ("     restore r%u (%s)\n",
   5005 		opcode & 0x3f, regname (opcode & 0x3f));
   5006     }
   5007 }
   5008 
   5009 
   5010 static unsigned int
   5011 encoded_ptr_size (int encoding, unsigned int ptr_size)
   5012 {
   5013   switch (encoding & 7)
   5014     {
   5015     case 2:
   5016       return 2;
   5017     case 3:
   5018       return 4;
   5019     case 4:
   5020       return 8;
   5021     default:
   5022       return ptr_size;
   5023     }
   5024 }
   5025 
   5026 
   5027 static unsigned int
   5028 print_encoding (unsigned int val)
   5029 {
   5030   switch (val & 0xf)
   5031     {
   5032     case DW_EH_PE_absptr:
   5033       fputs ("absptr", stdout);
   5034       break;
   5035     case DW_EH_PE_uleb128:
   5036       fputs ("uleb128", stdout);
   5037       break;
   5038     case DW_EH_PE_udata2:
   5039       fputs ("udata2", stdout);
   5040       break;
   5041     case DW_EH_PE_udata4:
   5042       fputs ("udata4", stdout);
   5043       break;
   5044     case DW_EH_PE_udata8:
   5045       fputs ("udata8", stdout);
   5046       break;
   5047     case DW_EH_PE_sleb128:
   5048       fputs ("sleb128", stdout);
   5049       break;
   5050     case DW_EH_PE_sdata2:
   5051       fputs ("sdata2", stdout);
   5052       break;
   5053     case DW_EH_PE_sdata4:
   5054       fputs ("sdata4", stdout);
   5055       break;
   5056     case DW_EH_PE_sdata8:
   5057       fputs ("sdata8", stdout);
   5058       break;
   5059     default:
   5060       /* We did not use any of the bits after all.  */
   5061       return val;
   5062     }
   5063 
   5064   return val & ~0xf;
   5065 }
   5066 
   5067 
   5068 static unsigned int
   5069 print_relinfo (unsigned int val)
   5070 {
   5071   switch (val & 0x70)
   5072     {
   5073     case DW_EH_PE_pcrel:
   5074       fputs ("pcrel", stdout);
   5075       break;
   5076     case DW_EH_PE_textrel:
   5077       fputs ("textrel", stdout);
   5078       break;
   5079     case DW_EH_PE_datarel:
   5080       fputs ("datarel", stdout);
   5081       break;
   5082     case DW_EH_PE_funcrel:
   5083       fputs ("funcrel", stdout);
   5084       break;
   5085     case DW_EH_PE_aligned:
   5086       fputs ("aligned", stdout);
   5087       break;
   5088     default:
   5089       return val;
   5090     }
   5091 
   5092   return val & ~0x70;
   5093 }
   5094 
   5095 
   5096 static void
   5097 print_encoding_base (const char *pfx, unsigned int fde_encoding)
   5098 {
   5099   printf ("(%s", pfx);
   5100 
   5101   if (fde_encoding == DW_EH_PE_omit)
   5102     puts ("omit)");
   5103   else
   5104     {
   5105       unsigned int w = fde_encoding;
   5106 
   5107       w = print_encoding (w);
   5108 
   5109       if (w & 0x70)
   5110 	{
   5111 	  if (w != fde_encoding)
   5112 	    fputc_unlocked (' ', stdout);
   5113 
   5114 	  w = print_relinfo (w);
   5115 	}
   5116 
   5117       if (w != 0)
   5118 	printf ("%s%x", w != fde_encoding ? " " : "", w);
   5119 
   5120       puts (")");
   5121     }
   5122 }
   5123 
   5124 
   5125 static const unsigned char *
   5126 read_encoded (unsigned int encoding, const unsigned char *readp,
   5127 	      const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
   5128 {
   5129   if ((encoding & 0xf) == DW_EH_PE_absptr)
   5130     encoding = gelf_getclass (dbg->elf) == ELFCLASS32
   5131       ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
   5132 
   5133   switch (encoding & 0xf)
   5134     {
   5135     case DW_EH_PE_uleb128:
   5136       // XXX buffer overrun check
   5137       get_uleb128 (*res, readp);
   5138       break;
   5139     case DW_EH_PE_sleb128:
   5140       // XXX buffer overrun check
   5141       get_sleb128 (*res, readp);
   5142       break;
   5143     case DW_EH_PE_udata2:
   5144       if (readp + 2 > endp)
   5145 	goto invalid;
   5146       *res = read_2ubyte_unaligned_inc (dbg, readp);
   5147       break;
   5148     case DW_EH_PE_udata4:
   5149       if (readp + 4 > endp)
   5150 	goto invalid;
   5151       *res = read_4ubyte_unaligned_inc (dbg, readp);
   5152       break;
   5153     case DW_EH_PE_udata8:
   5154       if (readp + 8 > endp)
   5155 	goto invalid;
   5156       *res = read_8ubyte_unaligned_inc (dbg, readp);
   5157       break;
   5158     case DW_EH_PE_sdata2:
   5159       if (readp + 2 > endp)
   5160 	goto invalid;
   5161       *res = read_2sbyte_unaligned_inc (dbg, readp);
   5162       break;
   5163     case DW_EH_PE_sdata4:
   5164       if (readp + 4 > endp)
   5165 	goto invalid;
   5166       *res = read_4sbyte_unaligned_inc (dbg, readp);
   5167       break;
   5168     case DW_EH_PE_sdata8:
   5169       if (readp + 8 > endp)
   5170 	goto invalid;
   5171       *res = read_8sbyte_unaligned_inc (dbg, readp);
   5172       break;
   5173     default:
   5174     invalid:
   5175       error (1, 0,
   5176 	     gettext ("invalid encoding"));
   5177     }
   5178 
   5179   return readp;
   5180 }
   5181 
   5182 
   5183 static void
   5184 print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
   5185 			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   5186 {
   5187   size_t shstrndx;
   5188   /* We know this call will succeed since it did in the caller.  */
   5189   (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
   5190   const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
   5191 
   5192   Elf_Data *data = elf_rawdata (scn, NULL);
   5193 
   5194   if (unlikely (data == NULL))
   5195     {
   5196       error (0, 0, gettext ("cannot get %s content: %s"),
   5197 	     scnname, elf_errmsg (-1));
   5198       return;
   5199     }
   5200   bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
   5201 
   5202   if (is_eh_frame)
   5203     printf (gettext ("\
   5204 \nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
   5205 	    elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
   5206   else
   5207     printf (gettext ("\
   5208 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
   5209 	    elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
   5210 
   5211   struct cieinfo
   5212   {
   5213     ptrdiff_t cie_offset;
   5214     const char *augmentation;
   5215     unsigned int code_alignment_factor;
   5216     unsigned int data_alignment_factor;
   5217     uint8_t address_size;
   5218     uint8_t fde_encoding;
   5219     uint8_t lsda_encoding;
   5220     struct cieinfo *next;
   5221   } *cies = NULL;
   5222 
   5223   const unsigned char *readp = data->d_buf;
   5224   const unsigned char *const dataend = ((unsigned char *) data->d_buf
   5225 					+ data->d_size);
   5226   while (readp < dataend)
   5227     {
   5228       if (unlikely (readp + 4 > dataend))
   5229 	{
   5230 	invalid_data:
   5231 	  error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
   5232 		     elf_ndxscn (scn), scnname);
   5233 	      return;
   5234 	}
   5235 
   5236       /* At the beginning there must be a CIE.  There can be multiple,
   5237 	 hence we test tis in a loop.  */
   5238       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
   5239 
   5240       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
   5241       unsigned int length = 4;
   5242       if (unlikely (unit_length == 0xffffffff))
   5243 	{
   5244 	  if (unlikely (readp + 8 > dataend))
   5245 	    goto invalid_data;
   5246 
   5247 	  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
   5248 	  length = 8;
   5249 	}
   5250 
   5251       if (unlikely (unit_length == 0))
   5252 	{
   5253 	  printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
   5254 	  continue;
   5255 	}
   5256 
   5257       unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
   5258 
   5259       ptrdiff_t start = readp - (unsigned char *) data->d_buf;
   5260       const unsigned char *const cieend = readp + unit_length;
   5261       if (unlikely (cieend > dataend || readp + 8 > dataend))
   5262 	goto invalid_data;
   5263 
   5264       Dwarf_Off cie_id;
   5265       if (length == 4)
   5266 	{
   5267 	  cie_id = read_4ubyte_unaligned_inc (dbg, readp);
   5268 	  if (!is_eh_frame && cie_id == DW_CIE_ID_32)
   5269 	    cie_id = DW_CIE_ID_64;
   5270 	}
   5271       else
   5272 	cie_id = read_8ubyte_unaligned_inc (dbg, readp);
   5273 
   5274       uint_fast8_t version = 2;
   5275       unsigned int code_alignment_factor;
   5276       int data_alignment_factor;
   5277       unsigned int fde_encoding = 0;
   5278       unsigned int lsda_encoding = 0;
   5279       Dwarf_Word initial_location = 0;
   5280       Dwarf_Word vma_base = 0;
   5281 
   5282       if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
   5283 	{
   5284 	  version = *readp++;
   5285 	  const char *const augmentation = (const char *) readp;
   5286 	  readp = memchr (readp, '\0', cieend - readp);
   5287 	  if (unlikely (readp == NULL))
   5288 	    goto invalid_data;
   5289 	  ++readp;
   5290 
   5291 	  uint_fast8_t segment_size = 0;
   5292 	  if (version >= 4)
   5293 	    {
   5294 	      if (cieend - readp < 5)
   5295 		goto invalid_data;
   5296 	      ptr_size = *readp++;
   5297 	      segment_size = *readp++;
   5298 	    }
   5299 
   5300 	  // XXX Check overflow
   5301 	  get_uleb128 (code_alignment_factor, readp);
   5302 	  // XXX Check overflow
   5303 	  get_sleb128 (data_alignment_factor, readp);
   5304 
   5305 	  /* In some variant for unwind data there is another field.  */
   5306 	  if (strcmp (augmentation, "eh") == 0)
   5307 	    readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
   5308 
   5309 	  unsigned int return_address_register;
   5310 	  if (unlikely (version == 1))
   5311 	    return_address_register = *readp++;
   5312 	  else
   5313 	    // XXX Check overflow
   5314 	    get_uleb128 (return_address_register, readp);
   5315 
   5316 	  printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
   5317 		  "   CIE_id:                   %" PRIu64 "\n"
   5318 		  "   version:                  %u\n"
   5319 		  "   augmentation:             \"%s\"\n",
   5320 		  offset, (uint64_t) unit_length, (uint64_t) cie_id,
   5321 		  version, augmentation);
   5322 	  if (version >= 4)
   5323 	    printf ("   address_size:             %u\n"
   5324 		    "   segment_size:             %u\n",
   5325 		    ptr_size, segment_size);
   5326 	  printf ("   code_alignment_factor:    %u\n"
   5327 		  "   data_alignment_factor:    %d\n"
   5328 		  "   return_address_register:  %u\n",
   5329 		  code_alignment_factor,
   5330 		  data_alignment_factor, return_address_register);
   5331 
   5332 	  if (augmentation[0] == 'z')
   5333 	    {
   5334 	      unsigned int augmentationlen;
   5335 	      get_uleb128 (augmentationlen, readp);
   5336 
   5337 	      if (augmentationlen > (size_t) (dataend - readp))
   5338 		error (1, 0, gettext ("invalid augmentation length"));
   5339 
   5340 	      const char *hdr = "Augmentation data:";
   5341 	      const char *cp = augmentation + 1;
   5342 	      while (*cp != '\0')
   5343 		{
   5344 		  printf ("   %-26s%#x ", hdr, *readp);
   5345 		  hdr = "";
   5346 
   5347 		  if (*cp == 'R')
   5348 		    {
   5349 		      fde_encoding = *readp++;
   5350 		      print_encoding_base (gettext ("FDE address encoding: "),
   5351 					   fde_encoding);
   5352 		    }
   5353 		  else if (*cp == 'L')
   5354 		    {
   5355 		      lsda_encoding = *readp++;
   5356 		      print_encoding_base (gettext ("LSDA pointer encoding: "),
   5357 					   lsda_encoding);
   5358 		    }
   5359 		  else if (*cp == 'P')
   5360 		    {
   5361 		      /* Personality.  This field usually has a relocation
   5362 			 attached pointing to __gcc_personality_v0.  */
   5363 		      const unsigned char *startp = readp;
   5364 		      unsigned int encoding = *readp++;
   5365 		      uint64_t val = 0;
   5366 		      readp = read_encoded (encoding, readp,
   5367 					    readp - 1 + augmentationlen,
   5368 					    &val, dbg);
   5369 
   5370 		      while (++startp < readp)
   5371 			printf ("%#x ", *startp);
   5372 
   5373 		      putchar ('(');
   5374 		      print_encoding (encoding);
   5375 		      putchar (' ');
   5376 		      switch (encoding & 0xf)
   5377 			{
   5378 			case DW_EH_PE_sleb128:
   5379 			case DW_EH_PE_sdata2:
   5380 			case DW_EH_PE_sdata4:
   5381 			  printf ("%" PRId64 ")\n", val);
   5382 			  break;
   5383 			default:
   5384 			  printf ("%#" PRIx64 ")\n", val);
   5385 			  break;
   5386 			}
   5387 		    }
   5388 		  else
   5389 		    printf ("(%x)\n", *readp++);
   5390 
   5391 		  ++cp;
   5392 		}
   5393 	    }
   5394 
   5395 	  if (likely (ptr_size == 4 || ptr_size == 8))
   5396 	    {
   5397 	      struct cieinfo *newp = alloca (sizeof (*newp));
   5398 	      newp->cie_offset = offset;
   5399 	      newp->augmentation = augmentation;
   5400 	      newp->fde_encoding = fde_encoding;
   5401 	      newp->lsda_encoding = lsda_encoding;
   5402 	      newp->address_size = ptr_size;
   5403 	      newp->code_alignment_factor = code_alignment_factor;
   5404 	      newp->data_alignment_factor = data_alignment_factor;
   5405 	      newp->next = cies;
   5406 	      cies = newp;
   5407 	    }
   5408 	}
   5409       else
   5410 	{
   5411 	  struct cieinfo *cie = cies;
   5412 	  while (cie != NULL)
   5413 	    if (is_eh_frame
   5414 		? start - (ptrdiff_t) cie_id == cie->cie_offset
   5415 		: (ptrdiff_t) cie_id == cie->cie_offset)
   5416 	      break;
   5417 	    else
   5418 	      cie = cie->next;
   5419 	  if (unlikely (cie == NULL))
   5420 	    {
   5421 	      puts ("invalid CIE reference in FDE");
   5422 	      return;
   5423 	    }
   5424 
   5425 	  /* Initialize from CIE data.  */
   5426 	  fde_encoding = cie->fde_encoding;
   5427 	  lsda_encoding = cie->lsda_encoding;
   5428 	  ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
   5429 	  code_alignment_factor = cie->code_alignment_factor;
   5430 	  data_alignment_factor = cie->data_alignment_factor;
   5431 
   5432 	  const unsigned char *base = readp;
   5433 	  // XXX There are sometimes relocations for this value
   5434 	  initial_location = read_ubyte_unaligned_inc (ptr_size, dbg, readp);
   5435 	  Dwarf_Word address_range
   5436 	    = read_ubyte_unaligned_inc (ptr_size, dbg, readp);
   5437 
   5438 	  char *a = format_dwarf_addr (dwflmod, cie->address_size,
   5439 				       initial_location);
   5440 	  printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
   5441 		  "   CIE_pointer:              %" PRIu64 "\n"
   5442 		  "   initial_location:         %s",
   5443 		  offset, (uint64_t) unit_length,
   5444 		  cie->cie_offset, (uint64_t) cie_id, a);
   5445 	  free (a);
   5446 	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
   5447 	    {
   5448 	      vma_base = (((uint64_t) shdr->sh_offset
   5449 			   + (base - (const unsigned char *) data->d_buf)
   5450 			   + (uint64_t) initial_location)
   5451 			  & (ptr_size == 4
   5452 			     ? UINT64_C (0xffffffff)
   5453 			     : UINT64_C (0xffffffffffffffff)));
   5454 	      printf (gettext (" (offset: %#" PRIx64 ")"),
   5455 		      (uint64_t) vma_base);
   5456 	    }
   5457 
   5458 	  printf ("\n   address_range:            %#" PRIx64,
   5459 		  (uint64_t) address_range);
   5460 	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
   5461 	    printf (gettext (" (end offset: %#" PRIx64 ")"),
   5462 		    ((uint64_t) vma_base + (uint64_t) address_range)
   5463 		    & (ptr_size == 4
   5464 		       ? UINT64_C (0xffffffff)
   5465 		       : UINT64_C (0xffffffffffffffff)));
   5466 	  putchar ('\n');
   5467 
   5468 	  if (cie->augmentation[0] == 'z')
   5469 	    {
   5470 	      unsigned int augmentationlen;
   5471 	      get_uleb128 (augmentationlen, readp);
   5472 
   5473 	      if (augmentationlen > 0)
   5474 		{
   5475 		  const char *hdr = "Augmentation data:";
   5476 		  const char *cp = cie->augmentation + 1;
   5477 		  unsigned int u = 0;
   5478 		  while (*cp != '\0')
   5479 		    {
   5480 		      if (*cp == 'L')
   5481 			{
   5482 			  uint64_t lsda_pointer;
   5483 			  const unsigned char *p
   5484 			    = read_encoded (lsda_encoding, &readp[u],
   5485 					    &readp[augmentationlen],
   5486 					    &lsda_pointer, dbg);
   5487 			  u = p - readp;
   5488 			  printf (gettext ("\
   5489    %-26sLSDA pointer: %#" PRIx64 "\n"),
   5490 				  hdr, lsda_pointer);
   5491 			  hdr = "";
   5492 			}
   5493 		      ++cp;
   5494 		    }
   5495 
   5496 		  while (u < augmentationlen)
   5497 		    {
   5498 		      printf ("   %-26s%#x\n", hdr, readp[u++]);
   5499 		      hdr = "";
   5500 		    }
   5501 		}
   5502 
   5503 	      readp += augmentationlen;
   5504 	    }
   5505 	}
   5506 
   5507       /* Handle the initialization instructions.  */
   5508       print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
   5509 			 data_alignment_factor, version, ptr_size,
   5510 			 dwflmod, ebl, dbg);
   5511       readp = cieend;
   5512     }
   5513 }
   5514 
   5515 
   5516 struct attrcb_args
   5517 {
   5518   Dwfl_Module *dwflmod;
   5519   Dwarf *dbg;
   5520   int level;
   5521   bool silent;
   5522   unsigned int version;
   5523   unsigned int addrsize;
   5524   unsigned int offset_size;
   5525   Dwarf_Off cu_offset;
   5526 };
   5527 
   5528 
   5529 static int
   5530 attr_callback (Dwarf_Attribute *attrp, void *arg)
   5531 {
   5532   struct attrcb_args *cbargs = (struct attrcb_args *) arg;
   5533   const int level = cbargs->level;
   5534 
   5535   unsigned int attr = dwarf_whatattr (attrp);
   5536   if (unlikely (attr == 0))
   5537     {
   5538       if (!cbargs->silent)
   5539 	error (0, 0, gettext ("cannot get attribute code: %s"),
   5540 	       dwarf_errmsg (-1));
   5541       return DWARF_CB_ABORT;
   5542     }
   5543 
   5544   unsigned int form = dwarf_whatform (attrp);
   5545   if (unlikely (form == 0))
   5546     {
   5547       if (!cbargs->silent)
   5548 	error (0, 0, gettext ("cannot get attribute form: %s"),
   5549 	       dwarf_errmsg (-1));
   5550       return DWARF_CB_ABORT;
   5551     }
   5552 
   5553   switch (form)
   5554     {
   5555     case DW_FORM_addr:
   5556       if (!cbargs->silent)
   5557 	{
   5558 	  Dwarf_Addr addr;
   5559 	  if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
   5560 	    {
   5561 	    attrval_out:
   5562 	      if (!cbargs->silent)
   5563 		error (0, 0, gettext ("cannot get attribute value: %s"),
   5564 		       dwarf_errmsg (-1));
   5565 	      return DWARF_CB_ABORT;
   5566 	    }
   5567 	  char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr);
   5568 	  printf ("           %*s%-20s (%s) %s\n",
   5569 		  (int) (level * 2), "", dwarf_attr_string (attr),
   5570 		  dwarf_form_string (form), a);
   5571 	  free (a);
   5572 	}
   5573       break;
   5574 
   5575     case DW_FORM_indirect:
   5576     case DW_FORM_strp:
   5577     case DW_FORM_string:
   5578       if (cbargs->silent)
   5579 	break;
   5580       const char *str = dwarf_formstring (attrp);
   5581       if (unlikely (str == NULL))
   5582 	goto attrval_out;
   5583       printf ("           %*s%-20s (%s) \"%s\"\n",
   5584 	      (int) (level * 2), "", dwarf_attr_string (attr),
   5585 	      dwarf_form_string (form), str);
   5586       break;
   5587 
   5588     case DW_FORM_ref_addr:
   5589     case DW_FORM_ref_udata:
   5590     case DW_FORM_ref8:
   5591     case DW_FORM_ref4:
   5592     case DW_FORM_ref2:
   5593     case DW_FORM_ref1:;
   5594       if (cbargs->silent)
   5595 	break;
   5596       Dwarf_Die ref;
   5597       if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
   5598 	goto attrval_out;
   5599 
   5600       printf ("           %*s%-20s (%s) [%6" PRIxMAX "]\n",
   5601 	      (int) (level * 2), "", dwarf_attr_string (attr),
   5602 	      dwarf_form_string (form), (uintmax_t) dwarf_dieoffset (&ref));
   5603       break;
   5604 
   5605     case DW_FORM_ref_sig8:
   5606       if (cbargs->silent)
   5607 	break;
   5608       printf ("           %*s%-20s (%s) {%6" PRIx64 "}\n",
   5609 	      (int) (level * 2), "", dwarf_attr_string (attr),
   5610 	      dwarf_form_string (form),
   5611 	      read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
   5612       break;
   5613 
   5614     case DW_FORM_sec_offset:
   5615     case DW_FORM_udata:
   5616     case DW_FORM_sdata:
   5617     case DW_FORM_data8:
   5618     case DW_FORM_data4:
   5619     case DW_FORM_data2:
   5620     case DW_FORM_data1:;
   5621       Dwarf_Word num;
   5622       if (unlikely (dwarf_formudata (attrp, &num) != 0))
   5623 	goto attrval_out;
   5624 
   5625       const char *valuestr = NULL;
   5626       switch (attr)
   5627 	{
   5628 	  /* This case can take either a constant or a loclistptr.  */
   5629 	case DW_AT_data_member_location:
   5630 	  if (form != DW_FORM_sec_offset
   5631 	      && (cbargs->version >= 4
   5632 		  || (form != DW_FORM_data4 && form != DW_FORM_data8)))
   5633 	    {
   5634 	      if (!cbargs->silent)
   5635 		printf ("           %*s%-20s (%s) %" PRIxMAX "\n",
   5636 			(int) (level * 2), "", dwarf_attr_string (attr),
   5637 			dwarf_form_string (form), (uintmax_t) num);
   5638 	      return DWARF_CB_OK;
   5639 	    }
   5640 	  /* else fallthrough */
   5641 
   5642 	/* These cases always take a loclistptr and no constant. */
   5643 	case DW_AT_location:
   5644 	case DW_AT_data_location:
   5645 	case DW_AT_vtable_elem_location:
   5646 	case DW_AT_string_length:
   5647 	case DW_AT_use_location:
   5648 	case DW_AT_frame_base:
   5649 	case DW_AT_return_addr:
   5650 	case DW_AT_static_link:
   5651 	case DW_AT_GNU_call_site_value:
   5652 	case DW_AT_GNU_call_site_data_value:
   5653 	case DW_AT_GNU_call_site_target:
   5654 	case DW_AT_GNU_call_site_target_clobbered:
   5655 	  notice_listptr (section_loc, &known_loclistptr,
   5656 			  cbargs->addrsize, cbargs->offset_size, num);
   5657 	  if (!cbargs->silent)
   5658 	    printf ("           %*s%-20s (%s) location list [%6" PRIxMAX "]\n",
   5659 		    (int) (level * 2), "", dwarf_attr_string (attr),
   5660 		    dwarf_form_string (form), (uintmax_t) num);
   5661 	  return DWARF_CB_OK;
   5662 
   5663 	case DW_AT_ranges:
   5664 	  notice_listptr (section_ranges, &known_rangelistptr,
   5665 			  cbargs->addrsize, cbargs->offset_size, num);
   5666 	  if (!cbargs->silent)
   5667 	    printf ("           %*s%-20s (%s) range list [%6" PRIxMAX "]\n",
   5668 		    (int) (level * 2), "", dwarf_attr_string (attr),
   5669 		    dwarf_form_string (form), (uintmax_t) num);
   5670 	  return DWARF_CB_OK;
   5671 
   5672 	case DW_AT_language:
   5673 	  valuestr = dwarf_lang_string (num);
   5674 	  break;
   5675 	case DW_AT_encoding:
   5676 	  valuestr = dwarf_encoding_string (num);
   5677 	  break;
   5678 	case DW_AT_accessibility:
   5679 	  valuestr = dwarf_access_string (num);
   5680 	  break;
   5681 	case DW_AT_visibility:
   5682 	  valuestr = dwarf_visibility_string (num);
   5683 	  break;
   5684 	case DW_AT_virtuality:
   5685 	  valuestr = dwarf_virtuality_string (num);
   5686 	  break;
   5687 	case DW_AT_identifier_case:
   5688 	  valuestr = dwarf_identifier_case_string (num);
   5689 	  break;
   5690 	case DW_AT_calling_convention:
   5691 	  valuestr = dwarf_calling_convention_string (num);
   5692 	  break;
   5693 	case DW_AT_inline:
   5694 	  valuestr = dwarf_inline_string (num);
   5695 	  break;
   5696 	case DW_AT_ordering:
   5697 	  valuestr = dwarf_ordering_string (num);
   5698 	  break;
   5699 	case DW_AT_discr_list:
   5700 	  valuestr = dwarf_discr_list_string (num);
   5701 	  break;
   5702 	default:
   5703 	  /* Nothing.  */
   5704 	  break;
   5705 	}
   5706 
   5707       if (cbargs->silent)
   5708 	break;
   5709 
   5710       if (valuestr == NULL)
   5711 	printf ("           %*s%-20s (%s) %" PRIuMAX "\n",
   5712 		(int) (level * 2), "", dwarf_attr_string (attr),
   5713 		dwarf_form_string (form), (uintmax_t) num);
   5714       else
   5715 	printf ("           %*s%-20s (%s) %s (%" PRIuMAX ")\n",
   5716 		(int) (level * 2), "", dwarf_attr_string (attr),
   5717 		dwarf_form_string (form), valuestr, (uintmax_t) num);
   5718       break;
   5719 
   5720     case DW_FORM_flag:
   5721       if (cbargs->silent)
   5722 	break;
   5723       bool flag;
   5724       if (unlikely (dwarf_formflag (attrp, &flag) != 0))
   5725 	goto attrval_out;
   5726 
   5727       printf ("           %*s%-20s (%s) %s\n",
   5728 	      (int) (level * 2), "", dwarf_attr_string (attr),
   5729 	      dwarf_form_string (form), nl_langinfo (flag ? YESSTR : NOSTR));
   5730       break;
   5731 
   5732     case DW_FORM_flag_present:
   5733       if (cbargs->silent)
   5734 	break;
   5735       printf ("           %*s%-20s (%s) %s\n",
   5736 	      (int) (level * 2), "", dwarf_attr_string (attr),
   5737 	      dwarf_form_string (form), nl_langinfo (YESSTR));
   5738       break;
   5739 
   5740     case DW_FORM_exprloc:
   5741     case DW_FORM_block4:
   5742     case DW_FORM_block2:
   5743     case DW_FORM_block1:
   5744     case DW_FORM_block:
   5745       if (cbargs->silent)
   5746 	break;
   5747       Dwarf_Block block;
   5748       if (unlikely (dwarf_formblock (attrp, &block) != 0))
   5749 	goto attrval_out;
   5750 
   5751       printf ("           %*s%-20s (%s) ",
   5752 	      (int) (level * 2), "", dwarf_attr_string (attr),
   5753 	      dwarf_form_string (form));
   5754 
   5755       switch (attr)
   5756 	{
   5757 	default:
   5758 	  if (form != DW_FORM_exprloc)
   5759 	    {
   5760 	      print_block (block.length, block.data);
   5761 	      break;
   5762 	    }
   5763 	  /* Fall through.  */
   5764 
   5765 	case DW_AT_location:
   5766 	case DW_AT_data_location:
   5767 	case DW_AT_data_member_location:
   5768 	case DW_AT_vtable_elem_location:
   5769 	case DW_AT_string_length:
   5770 	case DW_AT_use_location:
   5771 	case DW_AT_frame_base:
   5772 	case DW_AT_return_addr:
   5773 	case DW_AT_static_link:
   5774 	case DW_AT_allocated:
   5775 	case DW_AT_associated:
   5776 	case DW_AT_bit_size:
   5777 	case DW_AT_bit_offset:
   5778 	case DW_AT_bit_stride:
   5779 	case DW_AT_byte_size:
   5780 	case DW_AT_byte_stride:
   5781 	case DW_AT_count:
   5782 	case DW_AT_lower_bound:
   5783 	case DW_AT_upper_bound:
   5784 	case DW_AT_GNU_call_site_value:
   5785 	case DW_AT_GNU_call_site_data_value:
   5786 	case DW_AT_GNU_call_site_target:
   5787 	case DW_AT_GNU_call_site_target_clobbered:
   5788 	  putchar ('\n');
   5789 	  print_ops (cbargs->dwflmod, cbargs->dbg,
   5790 		     12 + level * 2, 12 + level * 2,
   5791 		     cbargs->version, cbargs->addrsize, cbargs->offset_size,
   5792 		     block.length, block.data);
   5793 	  break;
   5794 	}
   5795       break;
   5796 
   5797     default:
   5798       if (cbargs->silent)
   5799 	break;
   5800       printf ("           %*s%-20s (form: %#x) ???\n",
   5801 	      (int) (level * 2), "", dwarf_attr_string (attr),
   5802 	      (int) form);
   5803       break;
   5804     }
   5805 
   5806   return DWARF_CB_OK;
   5807 }
   5808 
   5809 static void
   5810 print_debug_units (Dwfl_Module *dwflmod,
   5811 		   Ebl *ebl, GElf_Ehdr *ehdr,
   5812 		   Elf_Scn *scn, GElf_Shdr *shdr,
   5813 		   Dwarf *dbg, bool debug_types)
   5814 {
   5815   const bool silent = !(print_debug_sections & section_info);
   5816   const char *secname = section_name (ebl, ehdr, shdr);
   5817 
   5818   if (!silent)
   5819     printf (gettext ("\
   5820 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
   5821 	    elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
   5822 
   5823   /* If the section is empty we don't have to do anything.  */
   5824   if (!silent && shdr->sh_size == 0)
   5825     return;
   5826 
   5827   int maxdies = 20;
   5828   Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
   5829 
   5830   Dwarf_Off offset = 0;
   5831 
   5832   /* New compilation unit.  */
   5833   size_t cuhl;
   5834   Dwarf_Half version;
   5835   Dwarf_Off abbroffset;
   5836   uint8_t addrsize;
   5837   uint8_t offsize;
   5838   Dwarf_Off nextcu;
   5839   uint64_t typesig;
   5840   Dwarf_Off typeoff;
   5841  next_cu:
   5842   if (dwarf_next_unit (dbg, offset, &nextcu, &cuhl, &version,
   5843 		       &abbroffset, &addrsize, &offsize,
   5844 		       debug_types ? &typesig : NULL,
   5845 		       debug_types ? &typeoff : NULL) != 0)
   5846     goto do_return;
   5847 
   5848   if (!silent)
   5849     {
   5850       if (debug_types)
   5851 	printf (gettext (" Type unit at offset %" PRIu64 ":\n"
   5852 			 " Version: %" PRIu16 ", Abbreviation section offset: %"
   5853 			 PRIu64 ", Address size: %" PRIu8
   5854 			 ", Offset size: %" PRIu8
   5855 			 "\n Type signature: %#" PRIx64
   5856 			 ", Type offset: %#" PRIx64 "\n"),
   5857 		(uint64_t) offset, version, abbroffset, addrsize, offsize,
   5858 		typesig, (uint64_t) typeoff);
   5859       else
   5860 	printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
   5861 			 " Version: %" PRIu16 ", Abbreviation section offset: %"
   5862 			 PRIu64 ", Address size: %" PRIu8
   5863 			 ", Offset size: %" PRIu8 "\n"),
   5864 		(uint64_t) offset, version, abbroffset, addrsize, offsize);
   5865     }
   5866 
   5867   struct attrcb_args args =
   5868     {
   5869       .dwflmod = dwflmod,
   5870       .dbg = dbg,
   5871       .silent = silent,
   5872       .version = version,
   5873       .addrsize = addrsize,
   5874       .offset_size = offsize,
   5875       .cu_offset = offset
   5876     };
   5877 
   5878   offset += cuhl;
   5879 
   5880   int level = 0;
   5881 
   5882   if (unlikely ((debug_types ? dwarf_offdie_types : dwarf_offdie)
   5883 		(dbg, offset, &dies[level]) == NULL))
   5884     {
   5885       if (!silent)
   5886 	error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
   5887 			      " in section '%s': %s"),
   5888 	       (uint64_t) offset, secname, dwarf_errmsg (-1));
   5889       goto do_return;
   5890     }
   5891 
   5892   do
   5893     {
   5894       offset = dwarf_dieoffset (&dies[level]);
   5895       if (unlikely (offset == ~0ul))
   5896 	{
   5897 	  if (!silent)
   5898 	    error (0, 0, gettext ("cannot get DIE offset: %s"),
   5899 		   dwarf_errmsg (-1));
   5900 	  goto do_return;
   5901 	}
   5902 
   5903       int tag = dwarf_tag (&dies[level]);
   5904       if (unlikely (tag == DW_TAG_invalid))
   5905 	{
   5906 	  if (!silent)
   5907 	    error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
   5908 				  " in section '%s': %s"),
   5909 		   (uint64_t) offset, secname, dwarf_errmsg (-1));
   5910 	  goto do_return;
   5911 	}
   5912 
   5913       if (!silent)
   5914 	printf (" [%6" PRIx64 "]  %*s%s\n",
   5915 		(uint64_t) offset, (int) (level * 2), "",
   5916 		dwarf_tag_string (tag));
   5917 
   5918       /* Print the attribute values.  */
   5919       args.level = level;
   5920       (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
   5921 
   5922       /* Make room for the next level's DIE.  */
   5923       if (level + 1 == maxdies)
   5924 	dies = (Dwarf_Die *) xrealloc (dies,
   5925 				       (maxdies += 10)
   5926 				       * sizeof (Dwarf_Die));
   5927 
   5928       int res = dwarf_child (&dies[level], &dies[level + 1]);
   5929       if (res > 0)
   5930 	{
   5931 	  while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
   5932 	    if (level-- == 0)
   5933 	      break;
   5934 
   5935 	  if (unlikely (res == -1))
   5936 	    {
   5937 	      if (!silent)
   5938 		error (0, 0, gettext ("cannot get next DIE: %s\n"),
   5939 		       dwarf_errmsg (-1));
   5940 	      goto do_return;
   5941 	    }
   5942 	}
   5943       else if (unlikely (res < 0))
   5944 	{
   5945 	  if (!silent)
   5946 	    error (0, 0, gettext ("cannot get next DIE: %s"),
   5947 		   dwarf_errmsg (-1));
   5948 	  goto do_return;
   5949 	}
   5950       else
   5951 	++level;
   5952     }
   5953   while (level >= 0);
   5954 
   5955   offset = nextcu;
   5956   if (offset != 0)
   5957      goto next_cu;
   5958 
   5959  do_return:
   5960   free (dies);
   5961 }
   5962 
   5963 static void
   5964 print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
   5965 			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   5966 {
   5967   print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
   5968 }
   5969 
   5970 static void
   5971 print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
   5972 			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   5973 {
   5974   print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
   5975 }
   5976 
   5977 
   5978 static void
   5979 print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
   5980 			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   5981 {
   5982   printf (gettext ("\
   5983 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
   5984 	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
   5985 	  (uint64_t) shdr->sh_offset);
   5986 
   5987   if (shdr->sh_size == 0)
   5988     return;
   5989 
   5990   /* There is no functionality in libdw to read the information in the
   5991      way it is represented here.  Hardcode the decoder.  */
   5992   Elf_Data *data = elf_getdata (scn, NULL);
   5993   if (unlikely (data == NULL || data->d_buf == NULL))
   5994     {
   5995       error (0, 0, gettext ("cannot get line data section data: %s"),
   5996 	     elf_errmsg (-1));
   5997       return;
   5998     }
   5999 
   6000   const unsigned char *linep = (const unsigned char *) data->d_buf;
   6001   const unsigned char *lineendp;
   6002 
   6003   while (linep
   6004 	 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
   6005     {
   6006       size_t start_offset = linep - (const unsigned char *) data->d_buf;
   6007 
   6008       printf (gettext ("\nTable at offset %Zu:\n"), start_offset);
   6009 
   6010       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
   6011       unsigned int length = 4;
   6012       if (unlikely (unit_length == 0xffffffff))
   6013 	{
   6014 	  if (unlikely (linep + 8 > lineendp))
   6015 	    {
   6016 	    invalid_data:
   6017 	      error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
   6018 		     elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
   6019 	      return;
   6020 	    }
   6021 	  unit_length = read_8ubyte_unaligned_inc (dbg, linep);
   6022 	  length = 8;
   6023 	}
   6024 
   6025       /* Check whether we have enough room in the section.  */
   6026       if (unit_length < 2 + length + 5 * 1
   6027 	  || unlikely (linep + unit_length > lineendp))
   6028 	goto invalid_data;
   6029       lineendp = linep + unit_length;
   6030 
   6031       /* The next element of the header is the version identifier.  */
   6032       uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
   6033 
   6034       /* Next comes the header length.  */
   6035       Dwarf_Word header_length;
   6036       if (length == 4)
   6037 	header_length = read_4ubyte_unaligned_inc (dbg, linep);
   6038       else
   6039 	header_length = read_8ubyte_unaligned_inc (dbg, linep);
   6040       //const unsigned char *header_start = linep;
   6041 
   6042       /* Next the minimum instruction length.  */
   6043       uint_fast8_t minimum_instr_len = *linep++;
   6044 
   6045       /* Next the maximum operations per instruction, in version 4 format.  */
   6046       uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++;
   6047 
   6048 	/* Then the flag determining the default value of the is_stmt
   6049 	   register.  */
   6050       uint_fast8_t default_is_stmt = *linep++;
   6051 
   6052       /* Now the line base.  */
   6053       int_fast8_t line_base = *((const int_fast8_t *) linep);
   6054       ++linep;
   6055 
   6056       /* And the line range.  */
   6057       uint_fast8_t line_range = *linep++;
   6058 
   6059       /* The opcode base.  */
   6060       uint_fast8_t opcode_base = *linep++;
   6061 
   6062       /* Print what we got so far.  */
   6063       printf (gettext ("\n"
   6064 		       " Length:                     %" PRIu64 "\n"
   6065 		       " DWARF version:              %" PRIuFAST16 "\n"
   6066 		       " Prologue length:            %" PRIu64 "\n"
   6067 		       " Minimum instruction length: %" PRIuFAST8 "\n"
   6068 		       " Maximum operations per instruction: %" PRIuFAST8 "\n"
   6069 		       " Initial value if '%s': %" PRIuFAST8 "\n"
   6070 		       " Line base:                  %" PRIdFAST8 "\n"
   6071 		       " Line range:                 %" PRIuFAST8 "\n"
   6072 		       " Opcode base:                %" PRIuFAST8 "\n"
   6073 		       "\n"
   6074 		       "Opcodes:\n"),
   6075 	      (uint64_t) unit_length, version, (uint64_t) header_length,
   6076 	      minimum_instr_len, max_ops_per_instr,
   6077 	      "is_stmt", default_is_stmt, line_base,
   6078 	      line_range, opcode_base);
   6079 
   6080       if (unlikely (linep + opcode_base - 1 >= lineendp))
   6081 	{
   6082 	invalid_unit:
   6083 	  error (0, 0,
   6084 		 gettext ("invalid data at offset %tu in section [%zu] '%s'"),
   6085 		 linep - (const unsigned char *) data->d_buf,
   6086 		 elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
   6087 	  linep = lineendp;
   6088 	  continue;
   6089 	}
   6090       int opcode_base_l10 = 1;
   6091       unsigned int tmp = opcode_base;
   6092       while (tmp > 10)
   6093 	{
   6094 	  tmp /= 10;
   6095 	  ++opcode_base_l10;
   6096 	}
   6097       const uint8_t *standard_opcode_lengths = linep - 1;
   6098       for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
   6099 	printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
   6100 			  "  [%*" PRIuFAST8 "]  %hhu arguments\n",
   6101 			  (int) linep[cnt - 1]),
   6102 		opcode_base_l10, cnt, linep[cnt - 1]);
   6103       linep += opcode_base - 1;
   6104       if (unlikely (linep >= lineendp))
   6105 	goto invalid_unit;
   6106 
   6107       puts (gettext ("\nDirectory table:"));
   6108       while (*linep != 0)
   6109 	{
   6110 	  unsigned char *endp = memchr (linep, '\0', lineendp - linep);
   6111 	  if (unlikely (endp == NULL))
   6112 	    goto invalid_unit;
   6113 
   6114 	  printf (" %s\n", (char *) linep);
   6115 
   6116 	  linep = endp + 1;
   6117 	}
   6118       /* Skip the final NUL byte.  */
   6119       ++linep;
   6120 
   6121       if (unlikely (linep >= lineendp))
   6122 	goto invalid_unit;
   6123       puts (gettext ("\nFile name table:\n"
   6124 		     " Entry Dir   Time      Size      Name"));
   6125       for (unsigned int cnt = 1; *linep != 0; ++cnt)
   6126 	{
   6127 	  /* First comes the file name.  */
   6128 	  char *fname = (char *) linep;
   6129 	  unsigned char *endp = memchr (fname, '\0', lineendp - linep);
   6130 	  if (unlikely (endp == NULL))
   6131 	    goto invalid_unit;
   6132 	  linep = endp + 1;
   6133 
   6134 	  /* Then the index.  */
   6135 	  unsigned int diridx;
   6136 	  get_uleb128 (diridx, linep);
   6137 
   6138 	  /* Next comes the modification time.  */
   6139 	  unsigned int mtime;
   6140 	  get_uleb128 (mtime, linep);
   6141 
   6142 	  /* Finally the length of the file.  */
   6143 	  unsigned int fsize;
   6144 	  get_uleb128 (fsize, linep);
   6145 
   6146 	  printf (" %-5u %-5u %-9u %-9u %s\n",
   6147 		  cnt, diridx, mtime, fsize, fname);
   6148 	}
   6149       /* Skip the final NUL byte.  */
   6150       ++linep;
   6151 
   6152       puts (gettext ("\nLine number statements:"));
   6153       Dwarf_Word address = 0;
   6154       unsigned int op_index = 0;
   6155       size_t line = 1;
   6156       uint_fast8_t is_stmt = default_is_stmt;
   6157 
   6158       /* Default address value, in case we do not find the CU.  */
   6159       size_t address_size
   6160 	= elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
   6161 
   6162       /* Determine the CU this block is for.  */
   6163       Dwarf_Off cuoffset;
   6164       Dwarf_Off ncuoffset = 0;
   6165       size_t hsize;
   6166       while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
   6167 			   NULL, NULL, NULL) == 0)
   6168 	{
   6169 	  Dwarf_Die cudie;
   6170 	  if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
   6171 	    continue;
   6172 	  Dwarf_Attribute stmt_list;
   6173 	  if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
   6174 	    continue;
   6175 	  Dwarf_Word lineoff;
   6176 	  if (dwarf_formudata (&stmt_list, &lineoff) != 0)
   6177 	    continue;
   6178 	  if (lineoff == start_offset)
   6179 	    {
   6180 	      /* Found the CU.  */
   6181 	      address_size = cudie.cu->address_size;
   6182 	      break;
   6183 	    }
   6184 	}
   6185 
   6186       /* Apply the "operation advance" from a special opcode
   6187 	 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
   6188       unsigned int op_addr_advance;
   6189       bool show_op_index;
   6190       inline void advance_pc (unsigned int op_advance)
   6191       {
   6192 	op_addr_advance = minimum_instr_len * ((op_index + op_advance)
   6193 					       / max_ops_per_instr);
   6194 	address += op_advance;
   6195 	show_op_index = (op_index > 0 ||
   6196 			 (op_index + op_advance) % max_ops_per_instr > 0);
   6197 	op_index = (op_index + op_advance) % max_ops_per_instr;
   6198       }
   6199 
   6200       while (linep < lineendp)
   6201 	{
   6202 	  size_t offset = linep - (const unsigned char *) data->d_buf;
   6203 	  unsigned int u128;
   6204 	  int s128;
   6205 
   6206 	  /* Read the opcode.  */
   6207 	  unsigned int opcode = *linep++;
   6208 
   6209 	  printf (" [%6" PRIx64 "]", (uint64_t)offset);
   6210 	  /* Is this a special opcode?  */
   6211 	  if (likely (opcode >= opcode_base))
   6212 	    {
   6213 	      /* Yes.  Handling this is quite easy since the opcode value
   6214 		 is computed with
   6215 
   6216 		 opcode = (desired line increment - line_base)
   6217 			   + (line_range * address advance) + opcode_base
   6218 	      */
   6219 	      int line_increment = (line_base
   6220 				    + (opcode - opcode_base) % line_range);
   6221 
   6222 	      /* Perform the increments.  */
   6223 	      line += line_increment;
   6224 	      advance_pc ((opcode - opcode_base) / line_range);
   6225 
   6226 	      char *a = format_dwarf_addr (dwflmod, 0, address);
   6227 	      if (show_op_index)
   6228 		printf (gettext ("\
   6229  special opcode %u: address+%u = %s, op_index = %u, line%+d = %zu\n"),
   6230 			opcode, op_addr_advance, a, op_index,
   6231 			line_increment, line);
   6232 	      else
   6233 		printf (gettext ("\
   6234  special opcode %u: address+%u = %s, line%+d = %zu\n"),
   6235 			opcode, op_addr_advance, a, line_increment, line);
   6236 	      free (a);
   6237 	    }
   6238 	  else if (opcode == 0)
   6239 	    {
   6240 	      /* This an extended opcode.  */
   6241 	      if (unlikely (linep + 2 > lineendp))
   6242 		goto invalid_unit;
   6243 
   6244 	      /* The length.  */
   6245 	      unsigned int len = *linep++;
   6246 
   6247 	      if (unlikely (linep + len > lineendp))
   6248 		goto invalid_unit;
   6249 
   6250 	      /* The sub-opcode.  */
   6251 	      opcode = *linep++;
   6252 
   6253 	      printf (gettext (" extended opcode %u: "), opcode);
   6254 
   6255 	      switch (opcode)
   6256 		{
   6257 		case DW_LNE_end_sequence:
   6258 		  puts (gettext (" end of sequence"));
   6259 
   6260 		  /* Reset the registers we care about.  */
   6261 		  address = 0;
   6262 		  op_index = 0;
   6263 		  line = 1;
   6264 		  is_stmt = default_is_stmt;
   6265 		  break;
   6266 
   6267 		case DW_LNE_set_address:
   6268 		  op_index = 0;
   6269 		  if (address_size == 4)
   6270 		    address = read_4ubyte_unaligned_inc (dbg, linep);
   6271 		  else
   6272 		    address = read_8ubyte_unaligned_inc (dbg, linep);
   6273 		  {
   6274 		    char *a = format_dwarf_addr (dwflmod, 0, address);
   6275 		    printf (gettext (" set address to %s\n"), a);
   6276 		    free (a);
   6277 		  }
   6278 		  break;
   6279 
   6280 		case DW_LNE_define_file:
   6281 		  {
   6282 		    char *fname = (char *) linep;
   6283 		    unsigned char *endp = memchr (linep, '\0',
   6284 						  lineendp - linep);
   6285 		    if (unlikely (endp == NULL))
   6286 		      goto invalid_unit;
   6287 		    linep = endp + 1;
   6288 
   6289 		    unsigned int diridx;
   6290 		    get_uleb128 (diridx, linep);
   6291 		    Dwarf_Word mtime;
   6292 		    get_uleb128 (mtime, linep);
   6293 		    Dwarf_Word filelength;
   6294 		    get_uleb128 (filelength, linep);
   6295 
   6296 		    printf (gettext ("\
   6297  define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
   6298 			    diridx, (uint64_t) mtime, (uint64_t) filelength,
   6299 			    fname);
   6300 		  }
   6301 		  break;
   6302 
   6303 		case DW_LNE_set_discriminator:
   6304 		  /* Takes one ULEB128 parameter, the discriminator.  */
   6305 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
   6306 		    goto invalid_unit;
   6307 
   6308 		  get_uleb128 (u128, linep);
   6309 		  printf (gettext (" set discriminator to %u\n"), u128);
   6310 		  break;
   6311 
   6312 		default:
   6313 		  /* Unknown, ignore it.  */
   6314 		  puts (gettext (" unknown opcode"));
   6315 		  linep += len - 1;
   6316 		  break;
   6317 		}
   6318 	    }
   6319 	  else if (opcode <= DW_LNS_set_isa)
   6320 	    {
   6321 	      /* This is a known standard opcode.  */
   6322 	      switch (opcode)
   6323 		{
   6324 		case DW_LNS_copy:
   6325 		  /* Takes no argument.  */
   6326 		  puts (gettext (" copy"));
   6327 		  break;
   6328 
   6329 		case DW_LNS_advance_pc:
   6330 		  /* Takes one uleb128 parameter which is added to the
   6331 		     address.  */
   6332 		  get_uleb128 (u128, linep);
   6333 		  advance_pc (u128);
   6334 		  {
   6335 		    char *a = format_dwarf_addr (dwflmod, 0, address);
   6336 		    if (show_op_index)
   6337 		      printf (gettext ("\
   6338  advance address by %u to %s, op_index to %u\n"),
   6339 			      op_addr_advance, a, op_index);
   6340 		    else
   6341 		      printf (gettext (" advance address by %u to %s\n"),
   6342 			      op_addr_advance, a);
   6343 		    free (a);
   6344 		  }
   6345 		  break;
   6346 
   6347 		case DW_LNS_advance_line:
   6348 		  /* Takes one sleb128 parameter which is added to the
   6349 		     line.  */
   6350 		  get_sleb128 (s128, linep);
   6351 		  line += s128;
   6352 		  printf (gettext ("\
   6353  advance line by constant %d to %" PRId64 "\n"),
   6354 			  s128, (int64_t) line);
   6355 		  break;
   6356 
   6357 		case DW_LNS_set_file:
   6358 		  /* Takes one uleb128 parameter which is stored in file.  */
   6359 		  get_uleb128 (u128, linep);
   6360 		  printf (gettext (" set file to %" PRIu64 "\n"),
   6361 			  (uint64_t) u128);
   6362 		  break;
   6363 
   6364 		case DW_LNS_set_column:
   6365 		  /* Takes one uleb128 parameter which is stored in column.  */
   6366 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
   6367 		    goto invalid_unit;
   6368 
   6369 		  get_uleb128 (u128, linep);
   6370 		  printf (gettext (" set column to %" PRIu64 "\n"),
   6371 			  (uint64_t) u128);
   6372 		  break;
   6373 
   6374 		case DW_LNS_negate_stmt:
   6375 		  /* Takes no argument.  */
   6376 		  is_stmt = 1 - is_stmt;
   6377 		  printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
   6378 			  "is_stmt", is_stmt);
   6379 		  break;
   6380 
   6381 		case DW_LNS_set_basic_block:
   6382 		  /* Takes no argument.  */
   6383 		  puts (gettext (" set basic block flag"));
   6384 		  break;
   6385 
   6386 		case DW_LNS_const_add_pc:
   6387 		  /* Takes no argument.  */
   6388 		  advance_pc ((255 - opcode_base) / line_range);
   6389 		  {
   6390 		    char *a = format_dwarf_addr (dwflmod, 0, address);
   6391 		    if (show_op_index)
   6392 		      printf (gettext ("\
   6393  advance address by constant %u to %s, op_index to %u\n"),
   6394 			      op_addr_advance, a, op_index);
   6395 		    else
   6396 		      printf (gettext ("\
   6397  advance address by constant %u to %s\n"),
   6398 			      op_addr_advance, a);
   6399 		    free (a);
   6400 		  }
   6401 		  break;
   6402 
   6403 		case DW_LNS_fixed_advance_pc:
   6404 		  /* Takes one 16 bit parameter which is added to the
   6405 		     address.  */
   6406 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
   6407 		    goto invalid_unit;
   6408 
   6409 		  u128 = read_2ubyte_unaligned_inc (dbg, linep);
   6410 		  address += u128;
   6411 		  op_index = 0;
   6412 		  {
   6413 		    char *a = format_dwarf_addr (dwflmod, 0, address);
   6414 		    printf (gettext ("\
   6415  advance address by fixed value %u to %s\n"),
   6416 			    u128, a);
   6417 		    free (a);
   6418 		  }
   6419 		  break;
   6420 
   6421 		case DW_LNS_set_prologue_end:
   6422 		  /* Takes no argument.  */
   6423 		  puts (gettext (" set prologue end flag"));
   6424 		  break;
   6425 
   6426 		case DW_LNS_set_epilogue_begin:
   6427 		  /* Takes no argument.  */
   6428 		  puts (gettext (" set epilogue begin flag"));
   6429 		  break;
   6430 
   6431 		case DW_LNS_set_isa:
   6432 		  /* Takes one uleb128 parameter which is stored in isa.  */
   6433 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
   6434 		    goto invalid_unit;
   6435 
   6436 		  get_uleb128 (u128, linep);
   6437 		  printf (gettext (" set isa to %u\n"), u128);
   6438 		  break;
   6439 		}
   6440 	    }
   6441 	  else
   6442 	    {
   6443 	      /* This is a new opcode the generator but not we know about.
   6444 		 Read the parameters associated with it but then discard
   6445 		 everything.  Read all the parameters for this opcode.  */
   6446 	      printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
   6447 				" unknown opcode with %" PRIu8 " parameters:",
   6448 				standard_opcode_lengths[opcode]),
   6449 		      standard_opcode_lengths[opcode]);
   6450 	      for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
   6451 		{
   6452 		  get_uleb128 (u128, linep);
   6453 		  if (n != standard_opcode_lengths[opcode])
   6454 		    putc_unlocked (',', stdout);
   6455 		  printf (" %u", u128);
   6456 		}
   6457 
   6458 	      /* Next round, ignore this opcode.  */
   6459 	      continue;
   6460 	    }
   6461 	}
   6462     }
   6463 
   6464   /* There must only be one data block.  */
   6465   assert (elf_getdata (scn, data) == NULL);
   6466 }
   6467 
   6468 
   6469 static void
   6470 print_debug_loc_section (Dwfl_Module *dwflmod,
   6471 			 Ebl *ebl, GElf_Ehdr *ehdr,
   6472 			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   6473 {
   6474   Elf_Data *data = elf_rawdata (scn, NULL);
   6475 
   6476   if (unlikely (data == NULL))
   6477     {
   6478       error (0, 0, gettext ("cannot get .debug_loc content: %s"),
   6479 	     elf_errmsg (-1));
   6480       return;
   6481     }
   6482 
   6483   printf (gettext ("\
   6484 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
   6485 	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
   6486 	  (uint64_t) shdr->sh_offset);
   6487 
   6488   sort_listptr (&known_loclistptr, "loclistptr");
   6489   size_t listptr_idx = 0;
   6490 
   6491   uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
   6492   uint_fast8_t offset_size = 4;
   6493 
   6494   bool first = true;
   6495   unsigned char *readp = data->d_buf;
   6496   unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
   6497   while (readp < endp)
   6498     {
   6499       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
   6500 
   6501       if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx,
   6502 				      &address_size, &offset_size,
   6503 				      offset, &readp, endp))
   6504 	continue;
   6505 
   6506       if (unlikely (data->d_size - offset < address_size * 2))
   6507 	{
   6508 	  printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
   6509 	  break;
   6510 	}
   6511 
   6512       Dwarf_Addr begin;
   6513       Dwarf_Addr end;
   6514       if (address_size == 8)
   6515 	{
   6516 	  begin = read_8ubyte_unaligned_inc (dbg, readp);
   6517 	  end = read_8ubyte_unaligned_inc (dbg, readp);
   6518 	}
   6519       else
   6520 	{
   6521 	  begin = read_4ubyte_unaligned_inc (dbg, readp);
   6522 	  end = read_4ubyte_unaligned_inc (dbg, readp);
   6523 	  if (begin == (Dwarf_Addr) (uint32_t) -1)
   6524 	    begin = (Dwarf_Addr) -1l;
   6525 	}
   6526 
   6527       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
   6528 	{
   6529 	  char *b = format_dwarf_addr (dwflmod, address_size, end);
   6530 	  printf (gettext (" [%6tx]  base address %s\n"), offset, b);
   6531 	  free (b);
   6532 	}
   6533       else if (begin == 0 && end == 0) /* End of list entry.  */
   6534 	{
   6535 	  if (first)
   6536 	    printf (gettext (" [%6tx]  empty list\n"), offset);
   6537 	  first = true;
   6538 	}
   6539       else
   6540 	{
   6541 	  /* We have a location expression entry.  */
   6542 	  uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
   6543 
   6544 	  char *b = format_dwarf_addr (dwflmod, address_size, begin);
   6545 	  char *e = format_dwarf_addr (dwflmod, address_size, end);
   6546 
   6547 	  if (first)		/* First entry in a list.  */
   6548 	    printf (gettext (" [%6tx]  %s..%s"), offset, b, e);
   6549 	  else
   6550 	    printf (gettext ("           %s..%s"), b, e);
   6551 
   6552 	  free (b);
   6553 	  free (e);
   6554 
   6555 	  if (endp - readp <= (ptrdiff_t) len)
   6556 	    {
   6557 	      fputs (gettext ("   <INVALID DATA>\n"), stdout);
   6558 	      break;
   6559 	    }
   6560 
   6561 	  print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
   6562 		     3 /*XXX*/, address_size, offset_size, len, readp);
   6563 
   6564 	  first = false;
   6565 	  readp += len;
   6566 	}
   6567     }
   6568 }
   6569 
   6570 struct mac_culist
   6571 {
   6572   Dwarf_Die die;
   6573   Dwarf_Off offset;
   6574   Dwarf_Files *files;
   6575   struct mac_culist *next;
   6576 };
   6577 
   6578 
   6579 static int
   6580 mac_compare (const void *p1, const void *p2)
   6581 {
   6582   struct mac_culist *m1 = (struct mac_culist *) p1;
   6583   struct mac_culist *m2 = (struct mac_culist *) p2;
   6584 
   6585   if (m1->offset < m2->offset)
   6586     return -1;
   6587   if (m1->offset > m2->offset)
   6588     return 1;
   6589   return 0;
   6590 }
   6591 
   6592 
   6593 static void
   6594 print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   6595 			     Ebl *ebl, GElf_Ehdr *ehdr,
   6596 			     Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   6597 {
   6598   printf (gettext ("\
   6599 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
   6600 	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
   6601 	  (uint64_t) shdr->sh_offset);
   6602   putc_unlocked ('\n', stdout);
   6603 
   6604   /* There is no function in libdw to iterate over the raw content of
   6605      the section but it is easy enough to do.  */
   6606   Elf_Data *data = elf_getdata (scn, NULL);
   6607   if (unlikely (data == NULL || data->d_buf == NULL))
   6608     {
   6609       error (0, 0, gettext ("cannot get macro information section data: %s"),
   6610 	     elf_errmsg (-1));
   6611       return;
   6612     }
   6613 
   6614   /* Get the source file information for all CUs.  */
   6615   Dwarf_Off offset;
   6616   Dwarf_Off ncu = 0;
   6617   size_t hsize;
   6618   struct mac_culist *culist = NULL;
   6619   size_t nculist = 0;
   6620   while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
   6621     {
   6622       Dwarf_Die cudie;
   6623       if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
   6624 	continue;
   6625 
   6626       Dwarf_Attribute attr;
   6627       if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
   6628 	continue;
   6629 
   6630       Dwarf_Word macoff;
   6631       if (dwarf_formudata (&attr, &macoff) != 0)
   6632 	continue;
   6633 
   6634       struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
   6635       newp->die = cudie;
   6636       newp->offset = macoff;
   6637       newp->files = NULL;
   6638       newp->next = culist;
   6639       culist = newp;
   6640       ++nculist;
   6641     }
   6642 
   6643   /* Convert the list into an array for easier consumption.  */
   6644   struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
   6645 							 * sizeof (*cus));
   6646   /* Add sentinel.  */
   6647   cus[nculist].offset = data->d_size;
   6648   if (nculist > 0)
   6649     {
   6650       for (size_t cnt = nculist - 1; culist != NULL; --cnt)
   6651 	{
   6652 	  assert (cnt < nculist);
   6653 	  cus[cnt] = *culist;
   6654 	  culist = culist->next;
   6655 	}
   6656 
   6657       /* Sort the array according to the offset in the .debug_macinfo
   6658 	 section.  Note we keep the sentinel at the end.  */
   6659       qsort (cus, nculist, sizeof (*cus), mac_compare);
   6660     }
   6661 
   6662   const unsigned char *readp = (const unsigned char *) data->d_buf;
   6663   const unsigned char *readendp = readp + data->d_size;
   6664   int level = 1;
   6665 
   6666   while (readp < readendp)
   6667     {
   6668       unsigned int opcode = *readp++;
   6669       unsigned int u128;
   6670       unsigned int u128_2;
   6671       const unsigned char *endp;
   6672 
   6673       switch (opcode)
   6674 	{
   6675 	case DW_MACINFO_define:
   6676 	case DW_MACINFO_undef:
   6677 	case DW_MACINFO_vendor_ext:
   6678 	  /*  For the first two opcodes the parameters are
   6679 		line, string
   6680 	      For the latter
   6681 		number, string.
   6682 	      We can treat these cases together.  */
   6683 	  get_uleb128 (u128, readp);
   6684 
   6685 	  endp = memchr (readp, '\0', readendp - readp);
   6686 	  if (unlikely (endp == NULL))
   6687 	    {
   6688 	      printf (gettext ("\
   6689 %*s*** non-terminated string at end of section"),
   6690 		      level, "");
   6691 	      return;
   6692 	    }
   6693 
   6694 	  if (opcode == DW_MACINFO_define)
   6695 	    printf ("%*s#define %s, line %u\n",
   6696 		    level, "", (char *) readp, u128);
   6697 	  else if (opcode == DW_MACINFO_undef)
   6698 	    printf ("%*s#undef %s, line %u\n",
   6699 		    level, "", (char *) readp, u128);
   6700 	  else
   6701 	    printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
   6702 
   6703 	  readp = endp + 1;
   6704 	  break;
   6705 
   6706 	case DW_MACINFO_start_file:
   6707 	  /* The two parameters are line and file index, in this order.  */
   6708 	  get_uleb128 (u128, readp);
   6709 	  get_uleb128 (u128_2, readp);
   6710 
   6711 	  /* Find the CU DIE for this file.  */
   6712 	  size_t macoff = readp - (const unsigned char *) data->d_buf;
   6713 	  const char *fname = "???";
   6714 	  if (macoff >= cus[0].offset)
   6715 	    {
   6716 	      while (macoff >= cus[1].offset)
   6717 		++cus;
   6718 
   6719 	      if (cus[0].files == NULL
   6720 		&& dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
   6721 		cus[0].files = (Dwarf_Files *) -1l;
   6722 
   6723 	      if (cus[0].files != (Dwarf_Files *) -1l)
   6724 		fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
   6725 			 ?: "???");
   6726 	    }
   6727 
   6728 	  printf ("%*sstart_file %u, [%u] %s\n",
   6729 		  level, "", u128, u128_2, fname);
   6730 	  ++level;
   6731 	  break;
   6732 
   6733 	case DW_MACINFO_end_file:
   6734 	  --level;
   6735 	  printf ("%*send_file\n", level, "");
   6736 	  /* Nothing more to do.  */
   6737 	  break;
   6738 
   6739 	default:
   6740 	  // XXX gcc seems to generate files with a trailing zero.
   6741 	  if (unlikely (opcode != 0 || readp != readendp))
   6742 	    printf ("%*s*** invalid opcode %u\n", level, "", opcode);
   6743 	  break;
   6744 	}
   6745     }
   6746 }
   6747 
   6748 
   6749 /* Callback for printing global names.  */
   6750 static int
   6751 print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
   6752 		void *arg)
   6753 {
   6754   int *np = (int *) arg;
   6755 
   6756   printf (gettext (" [%5d] DIE offset: %6" PRId64
   6757 		   ", CU DIE offset: %6" PRId64 ", name: %s\n"),
   6758 	  (*np)++, global->die_offset, global->cu_offset, global->name);
   6759 
   6760   return 0;
   6761 }
   6762 
   6763 
   6764 /* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
   6765 static void
   6766 print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   6767 			      Ebl *ebl, GElf_Ehdr *ehdr,
   6768 			      Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   6769 {
   6770   printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
   6771 	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
   6772 	  (uint64_t) shdr->sh_offset);
   6773 
   6774   int n = 0;
   6775   (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
   6776 }
   6777 
   6778 /* Print the content of the DWARF string section '.debug_str'.  */
   6779 static void
   6780 print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   6781 			 Ebl *ebl, GElf_Ehdr *ehdr,
   6782 			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   6783 {
   6784   const size_t sh_size = dbg->sectiondata[IDX_debug_str]->d_size;
   6785 
   6786   /* Compute floor(log16(shdr->sh_size)).  */
   6787   GElf_Addr tmp = sh_size;
   6788   int digits = 1;
   6789   while (tmp >= 16)
   6790     {
   6791       ++digits;
   6792       tmp >>= 4;
   6793     }
   6794   digits = MAX (4, digits);
   6795 
   6796   printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
   6797 		   " %*s  String\n"),
   6798 	  elf_ndxscn (scn),
   6799 	  section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset,
   6800 	  /* TRANS: the debugstr| prefix makes the string unique.  */
   6801 	  digits + 2, sgettext ("debugstr|Offset"));
   6802 
   6803   Dwarf_Off offset = 0;
   6804   while (offset < sh_size)
   6805     {
   6806       size_t len;
   6807       const char *str = dwarf_getstring (dbg, offset, &len);
   6808       if (unlikely (str == NULL))
   6809 	{
   6810 	  printf (gettext (" *** error while reading strings: %s\n"),
   6811 		  dwarf_errmsg (-1));
   6812 	  break;
   6813 	}
   6814 
   6815       printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
   6816 
   6817       offset += len + 1;
   6818     }
   6819 }
   6820 
   6821 
   6822 /* Print the content of the call frame search table section
   6823    '.eh_frame_hdr'.  */
   6824 static void
   6825 print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   6826 			       Ebl *ebl __attribute__ ((unused)),
   6827 			       GElf_Ehdr *ehdr __attribute__ ((unused)),
   6828 			       Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   6829 {
   6830   printf (gettext ("\
   6831 \nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
   6832 	  elf_ndxscn (scn));
   6833 
   6834   Elf_Data *data = elf_rawdata (scn, NULL);
   6835 
   6836   if (unlikely (data == NULL))
   6837     {
   6838       error (0, 0, gettext ("cannot get %s content: %s"),
   6839 	     ".eh_frame_hdr", elf_errmsg (-1));
   6840       return;
   6841     }
   6842 
   6843   const unsigned char *readp = data->d_buf;
   6844   const unsigned char *const dataend = ((unsigned char *) data->d_buf
   6845 					+ data->d_size);
   6846 
   6847   if (unlikely (readp + 4 > dataend))
   6848     {
   6849     invalid_data:
   6850       error (0, 0, gettext ("invalid data"));
   6851       return;
   6852     }
   6853 
   6854   unsigned int version = *readp++;
   6855   unsigned int eh_frame_ptr_enc = *readp++;
   6856   unsigned int fde_count_enc = *readp++;
   6857   unsigned int table_enc = *readp++;
   6858 
   6859   printf (" version:          %u\n"
   6860 	  " eh_frame_ptr_enc: %#x ",
   6861 	  version, eh_frame_ptr_enc);
   6862   print_encoding_base ("", eh_frame_ptr_enc);
   6863   printf (" fde_count_enc:    %#x ", fde_count_enc);
   6864   print_encoding_base ("", fde_count_enc);
   6865   printf (" table_enc:        %#x ", table_enc);
   6866   print_encoding_base ("", table_enc);
   6867 
   6868   uint64_t eh_frame_ptr = 0;
   6869   if (eh_frame_ptr_enc != DW_EH_PE_omit)
   6870     {
   6871       readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
   6872 			    dbg);
   6873       if (unlikely (readp == NULL))
   6874 	goto invalid_data;
   6875 
   6876       printf (" eh_frame_ptr:     %#" PRIx64, eh_frame_ptr);
   6877       if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
   6878 	printf (" (offset: %#" PRIx64 ")",
   6879 		/* +4 because of the 4 byte header of the section.  */
   6880 		(uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
   6881 
   6882       putchar_unlocked ('\n');
   6883     }
   6884 
   6885   uint64_t fde_count = 0;
   6886   if (fde_count_enc != DW_EH_PE_omit)
   6887     {
   6888       readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
   6889       if (unlikely (readp == NULL))
   6890 	goto invalid_data;
   6891 
   6892       printf (" fde_count:        %" PRIu64 "\n", fde_count);
   6893     }
   6894 
   6895   if (fde_count == 0 || table_enc == DW_EH_PE_omit)
   6896     return;
   6897 
   6898   puts (" Table:");
   6899 
   6900   /* Optimize for the most common case.  */
   6901   if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
   6902     while (fde_count > 0 && readp + 8 <= dataend)
   6903       {
   6904 	int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
   6905 	uint64_t initial_offset = ((uint64_t) shdr->sh_offset
   6906 				   + (int64_t) initial_location);
   6907 	int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
   6908 	// XXX Possibly print symbol name or section offset for initial_offset
   6909 	printf ("  %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
   6910 		" fde=[%6" PRIx64 "]\n",
   6911 		initial_location, initial_offset,
   6912 		address, address - (eh_frame_ptr + 4));
   6913       }
   6914   else
   6915     while (0 && readp < dataend)
   6916       {
   6917 
   6918       }
   6919 }
   6920 
   6921 
   6922 /* Print the content of the exception handling table section
   6923    '.eh_frame_hdr'.  */
   6924 static void
   6925 print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
   6926 			     Ebl *ebl __attribute__ ((unused)),
   6927 			     GElf_Ehdr *ehdr __attribute__ ((unused)),
   6928 			     Elf_Scn *scn,
   6929 			     GElf_Shdr *shdr __attribute__ ((unused)),
   6930 			     Dwarf *dbg __attribute__ ((unused)))
   6931 {
   6932   printf (gettext ("\
   6933 \nException handling table section [%2zu] '.gcc_except_table':\n"),
   6934 	  elf_ndxscn (scn));
   6935 
   6936   Elf_Data *data = elf_rawdata (scn, NULL);
   6937 
   6938   if (unlikely (data == NULL))
   6939     {
   6940       error (0, 0, gettext ("cannot get %s content: %s"),
   6941 	     ".gcc_except_table", elf_errmsg (-1));
   6942       return;
   6943     }
   6944 
   6945   const unsigned char *readp = data->d_buf;
   6946   const unsigned char *const dataend = readp + data->d_size;
   6947 
   6948   if (unlikely (readp + 1 > dataend))
   6949     {
   6950     invalid_data:
   6951       error (0, 0, gettext ("invalid data"));
   6952       return;
   6953     }
   6954   unsigned int lpstart_encoding = *readp++;
   6955   printf (gettext (" LPStart encoding:    %#x "), lpstart_encoding);
   6956   print_encoding_base ("", lpstart_encoding);
   6957   if (lpstart_encoding != DW_EH_PE_omit)
   6958     {
   6959       uint64_t lpstart;
   6960       readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
   6961       printf (" LPStart:             %#" PRIx64 "\n", lpstart);
   6962     }
   6963 
   6964   if (unlikely (readp + 1 > dataend))
   6965     goto invalid_data;
   6966   unsigned int ttype_encoding = *readp++;
   6967   printf (gettext (" TType encoding:      %#x "), ttype_encoding);
   6968   print_encoding_base ("", ttype_encoding);
   6969   const unsigned char *ttype_base = NULL;
   6970   if (ttype_encoding != DW_EH_PE_omit)
   6971     {
   6972       unsigned int ttype_base_offset;
   6973       get_uleb128 (ttype_base_offset, readp);
   6974       printf (" TType base offset:   %#x\n", ttype_base_offset);
   6975       ttype_base = readp + ttype_base_offset;
   6976     }
   6977 
   6978   if (unlikely (readp + 1 > dataend))
   6979     goto invalid_data;
   6980   unsigned int call_site_encoding = *readp++;
   6981   printf (gettext (" Call site encoding:  %#x "), call_site_encoding);
   6982   print_encoding_base ("", call_site_encoding);
   6983   unsigned int call_site_table_len;
   6984   get_uleb128 (call_site_table_len, readp);
   6985 
   6986   const unsigned char *const action_table = readp + call_site_table_len;
   6987   if (unlikely (action_table > dataend))
   6988     goto invalid_data;
   6989   unsigned int u = 0;
   6990   unsigned int max_action = 0;
   6991   while (readp < action_table)
   6992     {
   6993       if (u == 0)
   6994 	puts (gettext ("\n Call site table:"));
   6995 
   6996       uint64_t call_site_start;
   6997       readp = read_encoded (call_site_encoding, readp, dataend,
   6998 			    &call_site_start, dbg);
   6999       uint64_t call_site_length;
   7000       readp = read_encoded (call_site_encoding, readp, dataend,
   7001 			    &call_site_length, dbg);
   7002       uint64_t landing_pad;
   7003       readp = read_encoded (call_site_encoding, readp, dataend,
   7004 			    &landing_pad, dbg);
   7005       unsigned int action;
   7006       get_uleb128 (action, readp);
   7007       max_action = MAX (action, max_action);
   7008       printf (gettext (" [%4u] Call site start:   %#" PRIx64 "\n"
   7009 		       "        Call site length:  %" PRIu64 "\n"
   7010 		       "        Landing pad:       %#" PRIx64 "\n"
   7011 		       "        Action:            %u\n"),
   7012 	      u++, call_site_start, call_site_length, landing_pad, action);
   7013     }
   7014   assert (readp == action_table);
   7015 
   7016   unsigned int max_ar_filter = 0;
   7017   if (max_action > 0)
   7018     {
   7019       puts ("\n Action table:");
   7020 
   7021       const unsigned char *const action_table_end
   7022 	= action_table + max_action + 1;
   7023 
   7024       u = 0;
   7025       do
   7026 	{
   7027 	  int ar_filter;
   7028 	  get_sleb128 (ar_filter, readp);
   7029 	  if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
   7030 	    max_ar_filter = ar_filter;
   7031 	  int ar_disp;
   7032 	  get_sleb128 (ar_disp, readp);
   7033 
   7034 	  printf (" [%4u] ar_filter:  % d\n"
   7035 		  "        ar_disp:    % -5d",
   7036 		  u, ar_filter, ar_disp);
   7037 	  if (abs (ar_disp) & 1)
   7038 	    printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
   7039 	  else if (ar_disp != 0)
   7040 	    puts (" -> ???");
   7041 	  else
   7042 	    putchar_unlocked ('\n');
   7043 	  ++u;
   7044 	}
   7045       while (readp < action_table_end);
   7046     }
   7047 
   7048   if (max_ar_filter > 0)
   7049     {
   7050       puts ("\n TType table:");
   7051 
   7052       // XXX Not *4, size of encoding;
   7053       switch (ttype_encoding & 7)
   7054 	{
   7055 	case DW_EH_PE_udata2:
   7056 	case DW_EH_PE_sdata2:
   7057 	  readp = ttype_base - max_ar_filter * 2;
   7058 	  break;
   7059 	case DW_EH_PE_udata4:
   7060 	case DW_EH_PE_sdata4:
   7061 	  readp = ttype_base - max_ar_filter * 4;
   7062 	  break;
   7063 	case DW_EH_PE_udata8:
   7064 	case DW_EH_PE_sdata8:
   7065 	  readp = ttype_base - max_ar_filter * 8;
   7066 	  break;
   7067 	default:
   7068 	  error (1, 0, gettext ("invalid TType encoding"));
   7069 	}
   7070 
   7071       do
   7072 	{
   7073 	  uint64_t ttype;
   7074 	  readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
   7075 				dbg);
   7076 	  printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
   7077 	}
   7078       while (readp < ttype_base);
   7079     }
   7080 }
   7081 
   7082 /* Print the content of the '.gdb_index' section.
   7083    http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
   7084 */
   7085 static void
   7086 print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
   7087 			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   7088 {
   7089   printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
   7090 		   " contains %" PRId64 " bytes :\n"),
   7091 	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
   7092 	  (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
   7093 
   7094   Elf_Data *data = elf_rawdata (scn, NULL);
   7095 
   7096   if (unlikely (data == NULL))
   7097     {
   7098       error (0, 0, gettext ("cannot get %s content: %s"),
   7099 	     ".gdb_index", elf_errmsg (-1));
   7100       return;
   7101     }
   7102 
   7103   // .gdb_index is always in little endian.
   7104   Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
   7105   dbg = &dummy_dbg;
   7106 
   7107   const unsigned char *readp = data->d_buf;
   7108   const unsigned char *const dataend = readp + data->d_size;
   7109 
   7110   if (unlikely (readp + 4 > dataend))
   7111     {
   7112     invalid_data:
   7113       error (0, 0, gettext ("invalid data"));
   7114       return;
   7115     }
   7116 
   7117   int32_t vers = read_4ubyte_unaligned (dbg, readp);
   7118   printf (gettext (" Version:         %" PRId32 "\n"), vers);
   7119 
   7120   // The only difference between version 4 and version 5 is the
   7121   // hash used for generating the table.
   7122   if (vers < 4 || vers > 5)
   7123     {
   7124       printf (gettext ("  unknown version, cannot parse section\n"));
   7125       return;
   7126     }
   7127 
   7128   readp += 4;
   7129   if (unlikely (readp + 4 > dataend))
   7130     goto invalid_data;
   7131 
   7132   uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
   7133   printf (gettext (" CU offset:       %#" PRIx32 "\n"), cu_off);
   7134 
   7135   readp += 4;
   7136   if (unlikely (readp + 4 > dataend))
   7137     goto invalid_data;
   7138 
   7139   uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
   7140   printf (gettext (" TU offset:       %#" PRIx32 "\n"), tu_off);
   7141 
   7142   readp += 4;
   7143   if (unlikely (readp + 4 > dataend))
   7144     goto invalid_data;
   7145 
   7146   uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
   7147   printf (gettext (" address offset:  %#" PRIx32 "\n"), addr_off);
   7148 
   7149   readp += 4;
   7150   if (unlikely (readp + 4 > dataend))
   7151     goto invalid_data;
   7152 
   7153   uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
   7154   printf (gettext (" symbol offset:   %#" PRIx32 "\n"), sym_off);
   7155 
   7156   readp += 4;
   7157   if (unlikely (readp + 4 > dataend))
   7158     goto invalid_data;
   7159 
   7160   uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
   7161   printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
   7162 
   7163   readp = data->d_buf + cu_off;
   7164 
   7165   const unsigned char *nextp = data->d_buf + tu_off;
   7166   size_t nr = (nextp - readp) / 16;
   7167 
   7168   printf (gettext ("\n CU list at offset %#" PRIx32
   7169 		   " contains %zu entries:\n"),
   7170 	  cu_off, nr);
   7171 
   7172   size_t n = 0;
   7173   while (readp + 16 <= dataend && n < nr)
   7174     {
   7175       uint64_t off = read_8ubyte_unaligned (dbg, readp);
   7176       readp += 8;
   7177 
   7178       uint64_t len = read_8ubyte_unaligned (dbg, readp);
   7179       readp += 8;
   7180 
   7181       printf (" [%4zu] start: %0#8" PRIx64
   7182 	      ", length: %5" PRIu64 "\n", n, off, len);
   7183       n++;
   7184     }
   7185 
   7186   readp = data->d_buf + tu_off;
   7187   nextp = data->d_buf + addr_off;
   7188   nr = (nextp - readp) / 24;
   7189 
   7190   printf (gettext ("\n TU list at offset %#" PRIx32
   7191 		   " contains %zu entries:\n"),
   7192 	  tu_off, nr);
   7193 
   7194   n = 0;
   7195   while (readp + 24 <= dataend && n < nr)
   7196     {
   7197       uint64_t off = read_8ubyte_unaligned (dbg, readp);
   7198       readp += 8;
   7199 
   7200       uint64_t type = read_8ubyte_unaligned (dbg, readp);
   7201       readp += 8;
   7202 
   7203       uint64_t sig = read_8ubyte_unaligned (dbg, readp);
   7204       readp += 8;
   7205 
   7206       printf (" [%4zu] CU offset: %5" PRId64
   7207 	      ", type offset: %5" PRId64
   7208 	      ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
   7209       n++;
   7210     }
   7211 
   7212   readp = data->d_buf + addr_off;
   7213   nextp = data->d_buf + sym_off;
   7214   nr = (nextp - readp) / 20;
   7215 
   7216   printf (gettext ("\n Address list at offset %#" PRIx32
   7217 		   " contains %zu entries:\n"),
   7218 	  addr_off, nr);
   7219 
   7220   n = 0;
   7221   while (readp + 20 <= dataend && n < nr)
   7222     {
   7223       uint64_t low = read_8ubyte_unaligned (dbg, readp);
   7224       readp += 8;
   7225 
   7226       uint64_t high = read_8ubyte_unaligned (dbg, readp);
   7227       readp += 8;
   7228 
   7229       uint32_t idx = read_4ubyte_unaligned (dbg, readp);
   7230       readp += 4;
   7231 
   7232       char *l = format_dwarf_addr (dwflmod, 8, low);
   7233       char *h = format_dwarf_addr (dwflmod, 8, high - 1);
   7234       printf (" [%4zu] %s..%s, CU index: %5" PRId32 "\n",
   7235 	      n, l, h, idx);
   7236       n++;
   7237     }
   7238 
   7239   readp = data->d_buf + sym_off;
   7240   nextp = data->d_buf + const_off;
   7241   nr = (nextp - readp) / 8;
   7242 
   7243   printf (gettext ("\n Symbol table at offset %#" PRIx32
   7244 		   " contains %zu slots:\n"),
   7245 	  addr_off, nr);
   7246 
   7247   n = 0;
   7248   while (readp + 8 <= dataend && n < nr)
   7249     {
   7250       uint32_t name = read_4ubyte_unaligned (dbg, readp);
   7251       readp += 4;
   7252 
   7253       uint32_t vector = read_4ubyte_unaligned (dbg, readp);
   7254       readp += 4;
   7255 
   7256       if (name != 0 || vector != 0)
   7257 	{
   7258 	  const unsigned char *sym = data->d_buf + const_off + name;
   7259 	  if (unlikely (sym > dataend))
   7260 	    goto invalid_data;
   7261 
   7262 	  printf (" [%4zu] symbol: %s, CUs: ", n, sym);
   7263 
   7264 	  const unsigned char *readcus = data->d_buf + const_off + vector;
   7265 	  if (unlikely (readcus + 8 > dataend))
   7266 	    goto invalid_data;
   7267 
   7268 	  uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
   7269 	  while (cus--)
   7270 	    {
   7271 	      uint32_t cu;
   7272 	      readcus += 4;
   7273 	      cu = read_4ubyte_unaligned (dbg, readcus);
   7274 	      printf ("%" PRId32 "%s", cu, ((cus > 0) ? ", " : ""));
   7275 	    }
   7276 	  printf ("\n");
   7277 	}
   7278       n++;
   7279     }
   7280 }
   7281 
   7282 static void
   7283 print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
   7284 {
   7285   /* Before we start the real work get a debug context descriptor.  */
   7286   Dwarf_Addr dwbias;
   7287   Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
   7288   Dwarf dummy_dbg =
   7289     {
   7290       .elf = ebl->elf,
   7291       .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
   7292     };
   7293   if (dbg == NULL)
   7294     {
   7295       if ((print_debug_sections & ~section_exception) != 0)
   7296 	error (0, 0, gettext ("cannot get debug context descriptor: %s"),
   7297 	       dwfl_errmsg (-1));
   7298       if ((print_debug_sections & section_exception) == 0)
   7299 	return;
   7300       dbg = &dummy_dbg;
   7301     }
   7302 
   7303   /* Get the section header string table index.  */
   7304   size_t shstrndx;
   7305   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   7306     error (EXIT_FAILURE, 0,
   7307 	   gettext ("cannot get section header string table index"));
   7308 
   7309   /* Look through all the sections for the debugging sections to print.  */
   7310   Elf_Scn *scn = NULL;
   7311   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   7312     {
   7313       GElf_Shdr shdr_mem;
   7314       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   7315 
   7316       if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
   7317 	{
   7318 	  static const struct
   7319 	  {
   7320 	    const char *name;
   7321 	    enum section_e bitmask;
   7322 	    void (*fp) (Dwfl_Module *, Ebl *,
   7323 			GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
   7324 	  } debug_sections[] =
   7325 	    {
   7326 #define NEW_SECTION(name) \
   7327 	      { ".debug_" #name, section_##name, print_debug_##name##_section }
   7328 	      NEW_SECTION (abbrev),
   7329 	      NEW_SECTION (aranges),
   7330 	      NEW_SECTION (frame),
   7331 	      NEW_SECTION (info),
   7332 	      NEW_SECTION (types),
   7333 	      NEW_SECTION (line),
   7334 	      NEW_SECTION (loc),
   7335 	      NEW_SECTION (pubnames),
   7336 	      NEW_SECTION (str),
   7337 	      NEW_SECTION (macinfo),
   7338 	      NEW_SECTION (ranges),
   7339 	      { ".eh_frame", section_frame | section_exception,
   7340 		print_debug_frame_section },
   7341 	      { ".eh_frame_hdr", section_frame | section_exception,
   7342 		print_debug_frame_hdr_section },
   7343 	      { ".gcc_except_table", section_frame | section_exception,
   7344 		print_debug_exception_table },
   7345 	      { ".gdb_index", section_gdb_index, print_gdb_index_section }
   7346 	    };
   7347 	  const int ndebug_sections = (sizeof (debug_sections)
   7348 				       / sizeof (debug_sections[0]));
   7349 	  const char *name = elf_strptr (ebl->elf, shstrndx,
   7350 					 shdr->sh_name);
   7351 	  int n;
   7352 
   7353 	  for (n = 0; n < ndebug_sections; ++n)
   7354 	    if (strcmp (name, debug_sections[n].name) == 0
   7355 #if USE_ZLIB
   7356 		|| (name[0] == '.' && name[1] == 'z'
   7357 		    && debug_sections[n].name[1] == 'd'
   7358 		    && strcmp (&name[2], &debug_sections[n].name[1]) == 0)
   7359 #endif
   7360 		)
   7361 	      {
   7362 		if ((print_debug_sections | implicit_debug_sections)
   7363 		    & debug_sections[n].bitmask)
   7364 		  debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
   7365 		break;
   7366 	      }
   7367 	}
   7368     }
   7369 
   7370   reset_listptr (&known_loclistptr);
   7371   reset_listptr (&known_rangelistptr);
   7372 }
   7373 
   7374 
   7375 #define ITEM_INDENT		4
   7376 #define ITEM_WRAP_COLUMN	150
   7377 #define REGISTER_WRAP_COLUMN	75
   7378 
   7379 /* Print "NAME: FORMAT", wrapping when FORMAT_MAX chars of FORMAT would
   7380    make the line exceed ITEM_WRAP_COLUMN.  Unpadded numbers look better
   7381    for the core items.  But we do not want the line breaks to depend on
   7382    the particular values.  */
   7383 static unsigned int
   7384 __attribute__ ((format (printf, 7, 8)))
   7385 print_core_item (unsigned int colno, char sep, unsigned int wrap,
   7386 		 size_t name_width, const char *name,
   7387 		 size_t format_max, const char *format, ...)
   7388 {
   7389   size_t len = strlen (name);
   7390   if (name_width < len)
   7391     name_width = len;
   7392 
   7393   size_t n = name_width + sizeof ": " - 1 + format_max;
   7394 
   7395   if (colno == 0)
   7396     {
   7397       printf ("%*s", ITEM_INDENT, "");
   7398       colno = ITEM_INDENT + n;
   7399     }
   7400   else if (colno + 2 + n < wrap)
   7401     {
   7402       printf ("%c ", sep);
   7403       colno += 2 + n;
   7404     }
   7405   else
   7406     {
   7407       printf ("\n%*s", ITEM_INDENT, "");
   7408       colno = ITEM_INDENT + n;
   7409     }
   7410 
   7411   printf ("%s: %*s", name, (int) (name_width - len), "");
   7412 
   7413   va_list ap;
   7414   va_start (ap, format);
   7415   vprintf (format, ap);
   7416   va_end (ap);
   7417 
   7418   return colno;
   7419 }
   7420 
   7421 static const void *
   7422 convert (Elf *core, Elf_Type type, uint_fast16_t count,
   7423 	 void *value, const void *data, size_t size)
   7424 {
   7425   Elf_Data valuedata =
   7426     {
   7427       .d_type = type,
   7428       .d_buf = value,
   7429       .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
   7430       .d_version = EV_CURRENT,
   7431     };
   7432   Elf_Data indata =
   7433     {
   7434       .d_type = type,
   7435       .d_buf = (void *) data,
   7436       .d_size = valuedata.d_size,
   7437       .d_version = EV_CURRENT,
   7438     };
   7439 
   7440   Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
   7441 		 ? elf32_xlatetom : elf64_xlatetom)
   7442     (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
   7443   if (d == NULL)
   7444     error (EXIT_FAILURE, 0,
   7445 	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   7446 
   7447   return data + indata.d_size;
   7448 }
   7449 
   7450 typedef uint8_t GElf_Byte;
   7451 
   7452 static unsigned int
   7453 handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
   7454 		  unsigned int colno, size_t *repeated_size)
   7455 {
   7456   uint_fast16_t count = item->count ?: 1;
   7457 
   7458 #define TYPES								      \
   7459   DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8, 4);			      \
   7460   DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16, 6);			      \
   7461   DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32, 11);			      \
   7462   DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32, 11);			      \
   7463   DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64, 20);		      \
   7464   DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64, 20)
   7465 
   7466 #define DO_TYPE(NAME, Name, hex, dec, max) GElf_##Name Name[count]
   7467   union { TYPES; } value;
   7468 #undef DO_TYPE
   7469 
   7470   void *data = &value;
   7471   size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
   7472   size_t convsize = size;
   7473   if (repeated_size != NULL)
   7474     {
   7475       if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
   7476 	{
   7477 	  data = alloca (*repeated_size);
   7478 	  count *= *repeated_size / size;
   7479 	  convsize = count * size;
   7480 	  *repeated_size -= convsize;
   7481 	}
   7482       else if (item->count != 0 || item->format != '\n')
   7483 	*repeated_size -= size;
   7484     }
   7485 
   7486   convert (core, item->type, count, data, desc + item->offset, convsize);
   7487 
   7488   Elf_Type type = item->type;
   7489   if (type == ELF_T_ADDR)
   7490     type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
   7491 
   7492   switch (item->format)
   7493     {
   7494     case 'd':
   7495       assert (count == 1);
   7496       switch (type)
   7497 	{
   7498 #define DO_TYPE(NAME, Name, hex, dec, max)				      \
   7499 	  case ELF_T_##NAME:						      \
   7500 	    colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN,	      \
   7501 				     0, item->name, max, dec, value.Name[0]); \
   7502 	    break
   7503 	  TYPES;
   7504 #undef DO_TYPE
   7505 	default:
   7506 	  abort ();
   7507 	}
   7508       break;
   7509 
   7510     case 'x':
   7511       assert (count == 1);
   7512       switch (type)
   7513 	{
   7514 #define DO_TYPE(NAME, Name, hex, dec, max)				      \
   7515 	  case ELF_T_##NAME:						      \
   7516 	    colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN,	      \
   7517 				     0, item->name, max, hex, value.Name[0]); \
   7518 	    break
   7519 	  TYPES;
   7520 #undef DO_TYPE
   7521 	default:
   7522 	  abort ();
   7523 	}
   7524       break;
   7525 
   7526     case 'b':
   7527     case 'B':
   7528       assert (size % sizeof (unsigned int) == 0);
   7529       unsigned int nbits = count * size * 8;
   7530       unsigned int pop = 0;
   7531       for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
   7532 	pop += __builtin_popcount (*i);
   7533       bool negate = pop > nbits / 2;
   7534       const unsigned int bias = item->format == 'b';
   7535 
   7536       {
   7537 	char printed[(negate ? nbits - pop : pop) * 16];
   7538 	char *p = printed;
   7539 	*p = '\0';
   7540 
   7541 	if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
   7542 	  {
   7543 	    assert (size == sizeof (unsigned int) * 2);
   7544 	    for (unsigned int *i = data;
   7545 		 (void *) i < data + count * size; i += 2)
   7546 	      {
   7547 		unsigned int w = i[1];
   7548 		i[1] = i[0];
   7549 		i[0] = w;
   7550 	      }
   7551 	  }
   7552 
   7553 	unsigned int lastbit = 0;
   7554 	for (const unsigned int *i = data;
   7555 	     (void *) i < data + count * size; ++i)
   7556 	  {
   7557 	    unsigned int bit = ((void *) i - data) * 8;
   7558 	    unsigned int w = negate ? ~*i : *i;
   7559 	    unsigned int run = 0;
   7560 	    while (w != 0)
   7561 	      {
   7562 		int n = ffs (w);
   7563 		w >>= n;
   7564 		bit += n;
   7565 
   7566 		if (lastbit + 1 == bit)
   7567 		  ++run;
   7568 		else
   7569 		  {
   7570 		    if (lastbit == 0)
   7571 		      p += sprintf (p, "%u", bit - bias);
   7572 		    else if (run == 0)
   7573 		      p += sprintf (p, ",%u", bit - bias);
   7574 		    else
   7575 		      p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
   7576 		    run = 0;
   7577 		  }
   7578 
   7579 		lastbit = bit;
   7580 	      }
   7581 	  }
   7582 	if (lastbit > 0 && lastbit + 1 != nbits)
   7583 	  p += sprintf (p, "-%u", nbits - bias);
   7584 
   7585 	colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
   7586 				 4 + nbits * 4,
   7587 				 negate ? "~<%s>" : "<%s>", printed);
   7588       }
   7589       break;
   7590 
   7591     case 'T':
   7592     case (char) ('T'|0x80):
   7593       assert (count == 2);
   7594       Dwarf_Word sec;
   7595       Dwarf_Word usec;
   7596       size_t maxfmt = 7;
   7597       switch (type)
   7598 	{
   7599 #define DO_TYPE(NAME, Name, hex, dec, max)				      \
   7600 	  case ELF_T_##NAME:						      \
   7601 	    sec = value.Name[0];					      \
   7602 	    usec = value.Name[1];					      \
   7603 	    maxfmt += max;						      \
   7604 	    break
   7605 	  TYPES;
   7606 #undef DO_TYPE
   7607 	default:
   7608 	  abort ();
   7609 	}
   7610       if (unlikely (item->format == (char) ('T'|0x80)))
   7611 	{
   7612 	  /* This is a hack for an ill-considered 64-bit ABI where
   7613 	     tv_usec is actually a 32-bit field with 32 bits of padding
   7614 	     rounding out struct timeval.  We've already converted it as
   7615 	     a 64-bit field.  For little-endian, this just means the
   7616 	     high half is the padding; it's presumably zero, but should
   7617 	     be ignored anyway.  For big-endian, it means the 32-bit
   7618 	     field went into the high half of USEC.  */
   7619 	  GElf_Ehdr ehdr_mem;
   7620 	  GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
   7621 	  if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
   7622 	    usec >>= 32;
   7623 	  else
   7624 	    usec &= UINT32_MAX;
   7625 	}
   7626       colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
   7627 			       maxfmt, "%" PRIu64 ".%.6" PRIu64, sec, usec);
   7628       break;
   7629 
   7630     case 'c':
   7631       assert (count == 1);
   7632       colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
   7633 			       1, "%c", value.Byte[0]);
   7634       break;
   7635 
   7636     case 's':
   7637       colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
   7638 			       count, "%.*s", (int) count, value.Byte);
   7639       break;
   7640 
   7641     case '\n':
   7642       /* This is a list of strings separated by '\n'.  */
   7643       assert (item->count == 0);
   7644       assert (repeated_size != NULL);
   7645       assert (item->name == NULL);
   7646       if (unlikely (item->offset >= *repeated_size))
   7647 	break;
   7648 
   7649       const char *s = desc + item->offset;
   7650       size = *repeated_size - item->offset;
   7651       *repeated_size = 0;
   7652       while (size > 0)
   7653 	{
   7654 	  const char *eol = memchr (s, '\n', size);
   7655 	  int len = size;
   7656 	  if (eol != NULL)
   7657 	    len = eol - s;
   7658 	  printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
   7659 	  if (eol == NULL)
   7660 	    break;
   7661 	  size -= eol + 1 - s;
   7662 	  s = eol + 1;
   7663 	}
   7664 
   7665       colno = ITEM_WRAP_COLUMN;
   7666       break;
   7667 
   7668     default:
   7669       error (0, 0, "XXX not handling format '%c' for %s",
   7670 	     item->format, item->name);
   7671       break;
   7672     }
   7673 
   7674 #undef TYPES
   7675 
   7676   return colno;
   7677 }
   7678 
   7679 
   7680 /* Sort items by group, and by layout offset within each group.  */
   7681 static int
   7682 compare_core_items (const void *a, const void *b)
   7683 {
   7684   const Ebl_Core_Item *const *p1 = a;
   7685   const Ebl_Core_Item *const *p2 = b;
   7686   const Ebl_Core_Item *item1 = *p1;
   7687   const Ebl_Core_Item *item2 = *p2;
   7688 
   7689   return ((item1->group == item2->group ? 0
   7690 	   : strcmp (item1->group, item2->group))
   7691 	  ?: (int) item1->offset - (int) item2->offset);
   7692 }
   7693 
   7694 /* Sort item groups by layout offset of the first item in the group.  */
   7695 static int
   7696 compare_core_item_groups (const void *a, const void *b)
   7697 {
   7698   const Ebl_Core_Item *const *const *p1 = a;
   7699   const Ebl_Core_Item *const *const *p2 = b;
   7700   const Ebl_Core_Item *const *group1 = *p1;
   7701   const Ebl_Core_Item *const *group2 = *p2;
   7702   const Ebl_Core_Item *item1 = *group1;
   7703   const Ebl_Core_Item *item2 = *group2;
   7704 
   7705   return (int) item1->offset - (int) item2->offset;
   7706 }
   7707 
   7708 static unsigned int
   7709 handle_core_items (Elf *core, const void *desc, size_t descsz,
   7710 		   const Ebl_Core_Item *items, size_t nitems)
   7711 {
   7712   if (nitems == 0)
   7713     return 0;
   7714 
   7715   /* Sort to collect the groups together.  */
   7716   const Ebl_Core_Item *sorted_items[nitems];
   7717   for (size_t i = 0; i < nitems; ++i)
   7718     sorted_items[i] = &items[i];
   7719   qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
   7720 
   7721   /* Collect the unique groups and sort them.  */
   7722   const Ebl_Core_Item **groups[nitems];
   7723   groups[0] = &sorted_items[0];
   7724   size_t ngroups = 1;
   7725   for (size_t i = 1; i < nitems; ++i)
   7726     if (sorted_items[i]->group != sorted_items[i - 1]->group
   7727 	&& strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
   7728       groups[ngroups++] = &sorted_items[i];
   7729   qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
   7730 
   7731   /* Write out all the groups.  */
   7732   unsigned int colno = 0;
   7733 
   7734   const void *last = desc;
   7735   if (nitems == 1)
   7736     {
   7737       size_t size = descsz;
   7738       colno = handle_core_item (core, sorted_items[0], desc, colno, &size);
   7739       if (size == 0)
   7740 	return colno;
   7741       desc += descsz - size;
   7742       descsz = size;
   7743     }
   7744 
   7745   do
   7746     {
   7747       for (size_t i = 0; i < ngroups; ++i)
   7748 	{
   7749 	  for (const Ebl_Core_Item **item = groups[i];
   7750 	       (item < &sorted_items[nitems]
   7751 		&& ((*item)->group == groups[i][0]->group
   7752 		    || !strcmp ((*item)->group, groups[i][0]->group)));
   7753 	       ++item)
   7754 	    colno = handle_core_item (core, *item, desc, colno, NULL);
   7755 
   7756 	  /* Force a line break at the end of the group.  */
   7757 	  colno = ITEM_WRAP_COLUMN;
   7758 	}
   7759 
   7760       if (descsz == 0)
   7761 	break;
   7762 
   7763       /* This set of items consumed a certain amount of the note's data.
   7764 	 If there is more data there, we have another unit of the same size.
   7765 	 Loop to print that out too.  */
   7766       const Ebl_Core_Item *item = &items[nitems - 1];
   7767       size_t eltsz = item->offset + gelf_fsize (core, item->type,
   7768 						item->count ?: 1, EV_CURRENT);
   7769 
   7770       int reps = -1;
   7771       do
   7772 	{
   7773 	  ++reps;
   7774 	  desc += eltsz;
   7775 	  descsz -= eltsz;
   7776 	}
   7777       while (descsz >= eltsz && !memcmp (desc, last, eltsz));
   7778 
   7779       if (reps == 1)
   7780 	{
   7781 	  /* For just one repeat, print it unabridged twice.  */
   7782 	  desc -= eltsz;
   7783 	  descsz += eltsz;
   7784 	}
   7785       else if (reps > 1)
   7786 	printf (gettext ("\n%*s... <repeats %u more times> ..."),
   7787 		ITEM_INDENT, "", reps);
   7788 
   7789       last = desc;
   7790     }
   7791   while (descsz > 0);
   7792 
   7793   return colno;
   7794 }
   7795 
   7796 static unsigned int
   7797 handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
   7798 		      unsigned int colno)
   7799 {
   7800   desc += regloc->offset;
   7801 
   7802   abort ();			/* XXX */
   7803   return colno;
   7804 }
   7805 
   7806 
   7807 static unsigned int
   7808 handle_core_register (Ebl *ebl, Elf *core, int maxregname,
   7809 		      const Ebl_Register_Location *regloc, const void *desc,
   7810 		      unsigned int colno)
   7811 {
   7812   if (regloc->bits % 8 != 0)
   7813     return handle_bit_registers (regloc, desc, colno);
   7814 
   7815   desc += regloc->offset;
   7816 
   7817   for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
   7818     {
   7819       char name[REGNAMESZ];
   7820       int bits;
   7821       int type;
   7822       register_info (ebl, reg, regloc, name, &bits, &type);
   7823 
   7824 #define TYPES								      \
   7825       BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8, 4);			      \
   7826       BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16, 6);			      \
   7827       BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32, 11);		      \
   7828       BITS (64, XWORD, "%20" PRId64, "  0x%.16" PRIx64, 20)
   7829 
   7830 #define BITS(bits, xtype, sfmt, ufmt, max)				\
   7831       uint##bits##_t b##bits; int##bits##_t b##bits##s
   7832       union { TYPES; uint64_t b128[2]; } value;
   7833 #undef	BITS
   7834 
   7835       switch (type)
   7836 	{
   7837 	case DW_ATE_unsigned:
   7838 	case DW_ATE_signed:
   7839 	case DW_ATE_address:
   7840 	  switch (bits)
   7841 	    {
   7842 #define BITS(bits, xtype, sfmt, ufmt, max)				      \
   7843 	    case bits:							      \
   7844 	      desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0);	      \
   7845 	      if (type == DW_ATE_signed)				      \
   7846 		colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,    \
   7847 					 maxregname, name,		      \
   7848 					 max, sfmt, value.b##bits##s);	      \
   7849 	      else							      \
   7850 		colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,    \
   7851 					 maxregname, name,		      \
   7852 					 max, ufmt, value.b##bits);	      \
   7853 	      break
   7854 
   7855 	    TYPES;
   7856 
   7857 	    case 128:
   7858 	      assert (type == DW_ATE_unsigned);
   7859 	      desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
   7860 	      int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
   7861 	      colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
   7862 				       maxregname, name,
   7863 				       34, "0x%.16" PRIx64 "%.16" PRIx64,
   7864 				       value.b128[!be], value.b128[be]);
   7865 	      break;
   7866 
   7867 	    default:
   7868 	      abort ();
   7869 #undef	BITS
   7870 	    }
   7871 	  break;
   7872 
   7873 	default:
   7874 	  /* Print each byte in hex, the whole thing in native byte order.  */
   7875 	  assert (bits % 8 == 0);
   7876 	  const uint8_t *bytes = desc;
   7877 	  desc += bits / 8;
   7878 	  char hex[bits / 4 + 1];
   7879 	  hex[bits / 4] = '\0';
   7880 	  int incr = 1;
   7881 	  if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
   7882 	    {
   7883 	      bytes += bits / 8 - 1;
   7884 	      incr = -1;
   7885 	    }
   7886 	  size_t idx = 0;
   7887 	  for (char *h = hex; bits > 0; bits -= 8, idx += incr)
   7888 	    {
   7889 	      *h++ = "0123456789abcdef"[bytes[idx] >> 4];
   7890 	      *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
   7891 	    }
   7892 	  colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
   7893 				   maxregname, name,
   7894 				   2 + sizeof hex - 1, "0x%s", hex);
   7895 	  break;
   7896 	}
   7897       desc += regloc->pad;
   7898 
   7899 #undef TYPES
   7900     }
   7901 
   7902   return colno;
   7903 }
   7904 
   7905 
   7906 struct register_info
   7907 {
   7908   const Ebl_Register_Location *regloc;
   7909   const char *set;
   7910   char name[REGNAMESZ];
   7911   int regno;
   7912   int bits;
   7913   int type;
   7914 };
   7915 
   7916 static int
   7917 register_bitpos (const struct register_info *r)
   7918 {
   7919   return (r->regloc->offset * 8
   7920 	  + ((r->regno - r->regloc->regno)
   7921 	     * (r->regloc->bits + r->regloc->pad * 8)));
   7922 }
   7923 
   7924 static int
   7925 compare_sets_by_info (const struct register_info *r1,
   7926 		      const struct register_info *r2)
   7927 {
   7928   return ((int) r2->bits - (int) r1->bits
   7929 	  ?: register_bitpos (r1) - register_bitpos (r2));
   7930 }
   7931 
   7932 /* Sort registers by set, and by size and layout offset within each set.  */
   7933 static int
   7934 compare_registers (const void *a, const void *b)
   7935 {
   7936   const struct register_info *r1 = a;
   7937   const struct register_info *r2 = b;
   7938 
   7939   /* Unused elements sort last.  */
   7940   if (r1->regloc == NULL)
   7941     return r2->regloc == NULL ? 0 : 1;
   7942   if (r2->regloc == NULL)
   7943     return -1;
   7944 
   7945   return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
   7946 	  ?: compare_sets_by_info (r1, r2));
   7947 }
   7948 
   7949 /* Sort register sets by layout offset of the first register in the set.  */
   7950 static int
   7951 compare_register_sets (const void *a, const void *b)
   7952 {
   7953   const struct register_info *const *p1 = a;
   7954   const struct register_info *const *p2 = b;
   7955   return compare_sets_by_info (*p1, *p2);
   7956 }
   7957 
   7958 static unsigned int
   7959 handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
   7960 		       const Ebl_Register_Location *reglocs, size_t nregloc)
   7961 {
   7962   if (nregloc == 0)
   7963     return 0;
   7964 
   7965   ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
   7966   if (maxnreg <= 0)
   7967     {
   7968       for (size_t i = 0; i < nregloc; ++i)
   7969 	if (maxnreg < reglocs[i].regno + reglocs[i].count)
   7970 	  maxnreg = reglocs[i].regno + reglocs[i].count;
   7971       assert (maxnreg > 0);
   7972     }
   7973 
   7974   struct register_info regs[maxnreg];
   7975   memset (regs, 0, sizeof regs);
   7976 
   7977   /* Sort to collect the sets together.  */
   7978   int maxreg = 0;
   7979   for (size_t i = 0; i < nregloc; ++i)
   7980     for (int reg = reglocs[i].regno;
   7981 	 reg < reglocs[i].regno + reglocs[i].count;
   7982 	 ++reg)
   7983       {
   7984 	assert (reg < maxnreg);
   7985 	if (reg > maxreg)
   7986 	  maxreg = reg;
   7987 	struct register_info *info = &regs[reg];
   7988 	info->regloc = &reglocs[i];
   7989 	info->regno = reg;
   7990 	info->set = register_info (ebl, reg, &reglocs[i],
   7991 				   info->name, &info->bits, &info->type);
   7992       }
   7993   qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
   7994 
   7995   /* Collect the unique sets and sort them.  */
   7996   inline bool same_set (const struct register_info *a,
   7997 			const struct register_info *b)
   7998   {
   7999     return (a < &regs[maxnreg] && a->regloc != NULL
   8000 	    && b < &regs[maxnreg] && b->regloc != NULL
   8001 	    && a->bits == b->bits
   8002 	    && (a->set == b->set || !strcmp (a->set, b->set)));
   8003   }
   8004   struct register_info *sets[maxreg + 1];
   8005   sets[0] = &regs[0];
   8006   size_t nsets = 1;
   8007   for (int i = 1; i <= maxreg; ++i)
   8008     if (regs[i].regloc != NULL && !same_set (&regs[i], &regs[i - 1]))
   8009       sets[nsets++] = &regs[i];
   8010   qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
   8011 
   8012   /* Write out all the sets.  */
   8013   unsigned int colno = 0;
   8014   for (size_t i = 0; i < nsets; ++i)
   8015     {
   8016       /* Find the longest name of a register in this set.  */
   8017       size_t maxname = 0;
   8018       const struct register_info *end;
   8019       for (end = sets[i]; same_set (sets[i], end); ++end)
   8020 	{
   8021 	  size_t len = strlen (end->name);
   8022 	  if (len > maxname)
   8023 	    maxname = len;
   8024 	}
   8025 
   8026       for (const struct register_info *reg = sets[i];
   8027 	   reg < end;
   8028 	   reg += reg->regloc->count ?: 1)
   8029 	colno = handle_core_register (ebl, core, maxname,
   8030 				      reg->regloc, desc, colno);
   8031 
   8032       /* Force a line break at the end of the group.  */
   8033       colno = REGISTER_WRAP_COLUMN;
   8034     }
   8035 
   8036   return colno;
   8037 }
   8038 
   8039 static void
   8040 handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
   8041 {
   8042   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
   8043   if (data == NULL)
   8044   elf_error:
   8045     error (EXIT_FAILURE, 0,
   8046 	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   8047 
   8048   const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
   8049   for (size_t i = 0; i < nauxv; ++i)
   8050     {
   8051       GElf_auxv_t av_mem;
   8052       GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
   8053       if (av == NULL)
   8054 	goto elf_error;
   8055 
   8056       const char *name;
   8057       const char *fmt;
   8058       if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
   8059 	{
   8060 	  /* Unknown type.  */
   8061 	  if (av->a_un.a_val == 0)
   8062 	    printf ("    %" PRIu64 "\n", av->a_type);
   8063 	  else
   8064 	    printf ("    %" PRIu64 ": %#" PRIx64 "\n",
   8065 		    av->a_type, av->a_un.a_val);
   8066 	}
   8067       else
   8068 	switch (fmt[0])
   8069 	  {
   8070 	  case '\0':		/* Normally zero.  */
   8071 	    if (av->a_un.a_val == 0)
   8072 	      {
   8073 		printf ("    %s\n", name);
   8074 		break;
   8075 	      }
   8076 	    /* Fall through */
   8077 	  case 'x':		/* hex */
   8078 	  case 'p':		/* address */
   8079 	  case 's':		/* address of string */
   8080 	    printf ("    %s: %#" PRIx64 "\n", name, av->a_un.a_val);
   8081 	    break;
   8082 	  case 'u':
   8083 	    printf ("    %s: %" PRIu64 "\n", name, av->a_un.a_val);
   8084 	    break;
   8085 	  case 'd':
   8086 	    printf ("    %s: %" PRId64 "\n", name, av->a_un.a_val);
   8087 	    break;
   8088 
   8089 	  case 'b':
   8090 	    printf ("    %s: %#" PRIx64 "  ", name, av->a_un.a_val);
   8091 	    GElf_Xword bit = 1;
   8092 	    const char *pfx = "<";
   8093 	    for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
   8094 	      {
   8095 		if (av->a_un.a_val & bit)
   8096 		  {
   8097 		    printf ("%s%s", pfx, p);
   8098 		    pfx = " ";
   8099 		  }
   8100 		bit <<= 1;
   8101 	      }
   8102 	    printf (">\n");
   8103 	    break;
   8104 
   8105 	  default:
   8106 	    abort ();
   8107 	  }
   8108     }
   8109 }
   8110 
   8111 static void
   8112 handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
   8113 		  const char *name, const void *desc)
   8114 {
   8115   GElf_Word regs_offset;
   8116   size_t nregloc;
   8117   const Ebl_Register_Location *reglocs;
   8118   size_t nitems;
   8119   const Ebl_Core_Item *items;
   8120 
   8121   if (! ebl_core_note (ebl, nhdr, name,
   8122 		       &regs_offset, &nregloc, &reglocs, &nitems, &items))
   8123     return;
   8124 
   8125   /* Pass 0 for DESCSZ when there are registers in the note,
   8126      so that the ITEMS array does not describe the whole thing.
   8127      For non-register notes, the actual descsz might be a multiple
   8128      of the unit size, not just exactly the unit size.  */
   8129   unsigned int colno = handle_core_items (ebl->elf, desc,
   8130 					  nregloc == 0 ? nhdr->n_descsz : 0,
   8131 					  items, nitems);
   8132   if (colno != 0)
   8133     putchar_unlocked ('\n');
   8134 
   8135   colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
   8136 				 reglocs, nregloc);
   8137   if (colno != 0)
   8138     putchar_unlocked ('\n');
   8139 }
   8140 
   8141 static void
   8142 handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
   8143 		   GElf_Off start, Elf_Data *data)
   8144 {
   8145   fputs_unlocked (gettext ("  Owner          Data size  Type\n"), stdout);
   8146 
   8147   if (data == NULL)
   8148     goto bad_note;
   8149 
   8150   size_t offset = 0;
   8151   GElf_Nhdr nhdr;
   8152   size_t name_offset;
   8153   size_t desc_offset;
   8154   while (offset < data->d_size
   8155 	 && (offset = gelf_getnote (data, offset,
   8156 				    &nhdr, &name_offset, &desc_offset)) > 0)
   8157     {
   8158       const char *name = data->d_buf + name_offset;
   8159       const char *desc = data->d_buf + desc_offset;
   8160 
   8161       char buf[100];
   8162       char buf2[100];
   8163       printf (gettext ("  %-13.*s  %9" PRId32 "  %s\n"),
   8164 	      (int) nhdr.n_namesz, name, nhdr.n_descsz,
   8165 	      ehdr->e_type == ET_CORE
   8166 	      ? ebl_core_note_type_name (ebl, nhdr.n_type,
   8167 					 buf, sizeof (buf))
   8168 	      : ebl_object_note_type_name (ebl, name, nhdr.n_type,
   8169 					   buf2, sizeof (buf2)));
   8170 
   8171       /* Filter out invalid entries.  */
   8172       if (memchr (name, '\0', nhdr.n_namesz) != NULL
   8173 	  /* XXX For now help broken Linux kernels.  */
   8174 	  || 1)
   8175 	{
   8176 	  if (ehdr->e_type == ET_CORE)
   8177 	    {
   8178 	      if (nhdr.n_type == NT_AUXV
   8179 		  && (nhdr.n_namesz == 4 /* Broken old Linux kernels.  */
   8180 		      || (nhdr.n_namesz == 5 && name[4] == '\0'))
   8181 		  && !memcmp (name, "CORE", 4))
   8182 		handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
   8183 				  start + desc_offset);
   8184 	      else
   8185 		handle_core_note (ebl, &nhdr, name, desc);
   8186 	    }
   8187 	  else
   8188 	    ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc);
   8189 	}
   8190     }
   8191 
   8192   if (offset == data->d_size)
   8193     return;
   8194 
   8195  bad_note:
   8196   error (EXIT_FAILURE, 0,
   8197 	 gettext ("cannot get content of note section: %s"),
   8198 	 elf_errmsg (-1));
   8199 }
   8200 
   8201 static void
   8202 handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
   8203 {
   8204   /* If we have section headers, just look for SHT_NOTE sections.
   8205      In a debuginfo file, the program headers are not reliable.  */
   8206   if (shnum != 0)
   8207     {
   8208       /* Get the section header string table index.  */
   8209       size_t shstrndx;
   8210       if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
   8211 	error (EXIT_FAILURE, 0,
   8212 	       gettext ("cannot get section header string table index"));
   8213 
   8214       Elf_Scn *scn = NULL;
   8215       while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   8216 	{
   8217 	  GElf_Shdr shdr_mem;
   8218 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   8219 
   8220 	  if (shdr == NULL || shdr->sh_type != SHT_NOTE)
   8221 	    /* Not what we are looking for.  */
   8222 	    continue;
   8223 
   8224 	  printf (gettext ("\
   8225 \nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
   8226 		  elf_ndxscn (scn),
   8227 		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   8228 		  shdr->sh_size, shdr->sh_offset);
   8229 
   8230 	  handle_notes_data (ebl, ehdr, shdr->sh_offset,
   8231 			     elf_getdata (scn, NULL));
   8232 	}
   8233       return;
   8234     }
   8235 
   8236   /* We have to look through the program header to find the note
   8237      sections.  There can be more than one.  */
   8238   for (size_t cnt = 0; cnt < phnum; ++cnt)
   8239     {
   8240       GElf_Phdr mem;
   8241       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
   8242 
   8243       if (phdr == NULL || phdr->p_type != PT_NOTE)
   8244 	/* Not what we are looking for.  */
   8245 	continue;
   8246 
   8247       printf (gettext ("\
   8248 \nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
   8249 	      phdr->p_filesz, phdr->p_offset);
   8250 
   8251       handle_notes_data (ebl, ehdr, phdr->p_offset,
   8252 			 elf_getdata_rawchunk (ebl->elf,
   8253 					       phdr->p_offset, phdr->p_filesz,
   8254 					       ELF_T_NHDR));
   8255     }
   8256 }
   8257 
   8258 
   8259 static void
   8260 hex_dump (const uint8_t *data, size_t len)
   8261 {
   8262   size_t pos = 0;
   8263   while (pos < len)
   8264     {
   8265       printf ("  0x%08Zx ", pos);
   8266 
   8267       const size_t chunk = MIN (len - pos, 16);
   8268 
   8269       for (size_t i = 0; i < chunk; ++i)
   8270 	if (i % 4 == 3)
   8271 	  printf ("%02x ", data[pos + i]);
   8272 	else
   8273 	  printf ("%02x", data[pos + i]);
   8274 
   8275       if (chunk < 16)
   8276 	printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
   8277 
   8278       for (size_t i = 0; i < chunk; ++i)
   8279 	{
   8280 	  unsigned char b = data[pos + i];
   8281 	  printf ("%c", isprint (b) ? b : '.');
   8282 	}
   8283 
   8284       putchar ('\n');
   8285       pos += chunk;
   8286     }
   8287 }
   8288 
   8289 static void
   8290 dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
   8291 {
   8292   if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
   8293     printf (gettext ("\nSection [%Zu] '%s' has no data to dump.\n"),
   8294 	    elf_ndxscn (scn), name);
   8295   else
   8296     {
   8297       Elf_Data *data = elf_rawdata (scn, NULL);
   8298       if (data == NULL)
   8299 	error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
   8300 	       elf_ndxscn (scn), name, elf_errmsg (-1));
   8301       else
   8302 	{
   8303 	  printf (gettext ("\nHex dump of section [%Zu] '%s', %" PRIu64
   8304 			   " bytes at offset %#0" PRIx64 ":\n"),
   8305 		  elf_ndxscn (scn), name,
   8306 		  shdr->sh_size, shdr->sh_offset);
   8307 	  hex_dump (data->d_buf, data->d_size);
   8308 	}
   8309     }
   8310 }
   8311 
   8312 static void
   8313 print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
   8314 {
   8315   if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
   8316     printf (gettext ("\nSection [%Zu] '%s' has no strings to dump.\n"),
   8317 	    elf_ndxscn (scn), name);
   8318   else
   8319     {
   8320       Elf_Data *data = elf_rawdata (scn, NULL);
   8321       if (data == NULL)
   8322 	error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
   8323 	       elf_ndxscn (scn), name, elf_errmsg (-1));
   8324       else
   8325 	{
   8326 	  printf (gettext ("\nString section [%Zu] '%s' contains %" PRIu64
   8327 			   " bytes at offset %#0" PRIx64 ":\n"),
   8328 		  elf_ndxscn (scn), name,
   8329 		  shdr->sh_size, shdr->sh_offset);
   8330 
   8331 	  const char *start = data->d_buf;
   8332 	  const char *const limit = start + data->d_size;
   8333 	  do
   8334 	    {
   8335 	      const char *end = memchr (start, '\0', limit - start);
   8336 	      const size_t pos = start - (const char *) data->d_buf;
   8337 	      if (unlikely (end == NULL))
   8338 		{
   8339 		  printf ("  [%6Zx]- %.*s\n",
   8340 			  pos, (int) (limit - start), start);
   8341 		  break;
   8342 		}
   8343 	      printf ("  [%6Zx]  %s\n", pos, start);
   8344 	      start = end + 1;
   8345 	    } while (start < limit);
   8346 	}
   8347     }
   8348 }
   8349 
   8350 static void
   8351 for_each_section_argument (Elf *elf, const struct section_argument *list,
   8352 			   void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
   8353 					 const char *name))
   8354 {
   8355   /* Get the section header string table index.  */
   8356   size_t shstrndx;
   8357   if (elf_getshdrstrndx (elf, &shstrndx) < 0)
   8358     error (EXIT_FAILURE, 0,
   8359 	   gettext ("cannot get section header string table index"));
   8360 
   8361   for (const struct section_argument *a = list; a != NULL; a = a->next)
   8362     {
   8363       Elf_Scn *scn;
   8364       GElf_Shdr shdr_mem;
   8365       const char *name = NULL;
   8366 
   8367       char *endp = NULL;
   8368       unsigned long int shndx = strtoul (a->arg, &endp, 0);
   8369       if (endp != a->arg && *endp == '\0')
   8370 	{
   8371 	  scn = elf_getscn (elf, shndx);
   8372 	  if (scn == NULL)
   8373 	    {
   8374 	      error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
   8375 	      continue;
   8376 	    }
   8377 
   8378 	  if (gelf_getshdr (scn, &shdr_mem) == NULL)
   8379 	    error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
   8380 		   elf_errmsg (-1));
   8381 	  name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
   8382 	}
   8383       else
   8384 	{
   8385 	  /* Need to look up the section by name.  */
   8386 	  scn = NULL;
   8387 	  bool found = false;
   8388 	  while ((scn = elf_nextscn (elf, scn)) != NULL)
   8389 	    {
   8390 	      if (gelf_getshdr (scn, &shdr_mem) == NULL)
   8391 		continue;
   8392 	      name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
   8393 	      if (name == NULL)
   8394 		continue;
   8395 	      if (!strcmp (name, a->arg))
   8396 		{
   8397 		  found = true;
   8398 		  (*dump) (scn, &shdr_mem, name);
   8399 		}
   8400 	    }
   8401 
   8402 	  if (unlikely (!found) && !a->implicit)
   8403 	    error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
   8404 	}
   8405     }
   8406 }
   8407 
   8408 static void
   8409 dump_data (Ebl *ebl)
   8410 {
   8411   for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
   8412 }
   8413 
   8414 static void
   8415 dump_strings (Ebl *ebl)
   8416 {
   8417   for_each_section_argument (ebl->elf, string_sections, &print_string_section);
   8418 }
   8419 
   8420 static void
   8421 print_strings (Ebl *ebl)
   8422 {
   8423   /* Get the section header string table index.  */
   8424   size_t shstrndx;
   8425   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   8426     error (EXIT_FAILURE, 0,
   8427 	   gettext ("cannot get section header string table index"));
   8428 
   8429   Elf_Scn *scn;
   8430   GElf_Shdr shdr_mem;
   8431   const char *name;
   8432   scn = NULL;
   8433   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   8434     {
   8435       if (gelf_getshdr (scn, &shdr_mem) == NULL)
   8436 	continue;
   8437 
   8438       if (shdr_mem.sh_type != SHT_PROGBITS
   8439 	  || !(shdr_mem.sh_flags & SHF_STRINGS))
   8440 	continue;
   8441 
   8442       name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
   8443       if (name == NULL)
   8444 	continue;
   8445 
   8446       print_string_section (scn, &shdr_mem, name);
   8447     }
   8448 }
   8449 
   8450 static void
   8451 dump_archive_index (Elf *elf, const char *fname)
   8452 {
   8453   size_t narsym;
   8454   const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
   8455   if (arsym == NULL)
   8456     {
   8457       int result = elf_errno ();
   8458       if (unlikely (result != ELF_E_NO_INDEX))
   8459 	error (EXIT_FAILURE, 0,
   8460 	       gettext ("cannot get symbol index of archive '%s': %s"),
   8461 	       fname, elf_errmsg (result));
   8462       else
   8463 	printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
   8464       return;
   8465     }
   8466 
   8467   printf (gettext ("\nIndex of archive '%s' has %Zu entries:\n"),
   8468 	  fname, narsym);
   8469 
   8470   size_t as_off = 0;
   8471   for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
   8472     {
   8473       if (s->as_off != as_off)
   8474 	{
   8475 	  as_off = s->as_off;
   8476 
   8477 	  Elf *subelf;
   8478 	  if (unlikely (elf_rand (elf, as_off) == 0)
   8479 	      || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
   8480 			   == NULL))
   8481 #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
   8482 	    while (1)
   8483 #endif
   8484 	      error (EXIT_FAILURE, 0,
   8485 		     gettext ("cannot extract member at offset %Zu in '%s': %s"),
   8486 		     as_off, fname, elf_errmsg (-1));
   8487 
   8488 	  const Elf_Arhdr *h = elf_getarhdr (subelf);
   8489 
   8490 	  printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
   8491 
   8492 	  elf_end (subelf);
   8493 	}
   8494 
   8495       printf ("\t%s\n", s->as_name);
   8496     }
   8497 }
   8498 
   8499 #include "debugpred.h"
   8500