LCOV - code coverage report
Current view: top level - src - readelf.c (source / functions) Hit Total Coverage
Test: elfutils-0.177 Lines: 3554 6269 56.7 %
Date: 2019-08-14 14:28:26 Functions: 102 136 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Print information from ELF file in human-readable form.
       2             :    Copyright (C) 1999-2018 Red Hat, Inc.
       3             :    This file is part of elfutils.
       4             : 
       5             :    This file is free software; you can redistribute it and/or modify
       6             :    it under the terms of the GNU General Public License as published by
       7             :    the Free Software Foundation; either version 3 of the License, or
       8             :    (at your option) any later version.
       9             : 
      10             :    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
      13             :    GNU General Public License for more details.
      14             : 
      15             :    You should have received a copy of the GNU General Public License
      16             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      17             : 
      18             : #ifdef HAVE_CONFIG_H
      19             : # include <config.h>
      20             : #endif
      21             : 
      22             : #include <argp.h>
      23             : #include <assert.h>
      24             : #include <ctype.h>
      25             : #include <dwarf.h>
      26             : #include <errno.h>
      27             : #include <fcntl.h>
      28             : #include <gelf.h>
      29             : #include <inttypes.h>
      30             : #include <langinfo.h>
      31             : #include <libdw.h>
      32             : #include <libdwfl.h>
      33             : #include <libintl.h>
      34             : #include <locale.h>
      35             : #include <stdarg.h>
      36             : #include <stdbool.h>
      37             : #include <stdio.h>
      38             : #include <stdio_ext.h>
      39             : #include <stdlib.h>
      40             : #include <string.h>
      41             : #include <strings.h>
      42             : #include <time.h>
      43             : #include <unistd.h>
      44             : #include <sys/stat.h>
      45             : #include <signal.h>
      46             : 
      47             : #include <libeu.h>
      48             : #include <system.h>
      49             : #include <printversion.h>
      50             : #include "../libelf/libelfP.h"
      51             : #include "../libelf/common.h"
      52             : #include "../libebl/libeblP.h"
      53             : #include "../libdwelf/libdwelf.h"
      54             : #include "../libdw/libdwP.h"
      55             : #include "../libdwfl/libdwflP.h"
      56             : #include "../libdw/memory-access.h"
      57             : 
      58             : #include "../libdw/known-dwarf.h"
      59             : 
      60             : #ifdef __linux__
      61             : #define CORE_SIGILL  SIGILL
      62             : #define CORE_SIGBUS  SIGBUS
      63             : #define CORE_SIGFPE  SIGFPE
      64             : #define CORE_SIGSEGV SIGSEGV
      65             : #define CORE_SI_USER SI_USER
      66             : #else
      67             : /* We want the linux version of those as that is what shows up in the core files. */
      68             : #define CORE_SIGILL  4  /* Illegal instruction (ANSI).  */
      69             : #define CORE_SIGBUS  7  /* BUS error (4.2 BSD).  */
      70             : #define CORE_SIGFPE  8  /* Floating-point exception (ANSI).  */
      71             : #define CORE_SIGSEGV 11 /* Segmentation violation (ANSI).  */
      72             : #define CORE_SI_USER 0  /* Sent by kill, sigsend.  */
      73             : #endif
      74             : 
      75             : /* Name and version of program.  */
      76             : ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
      77             : 
      78             : /* Bug report address.  */
      79             : ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
      80             : 
      81             : /* argp key value for --elf-section, non-ascii.  */
      82             : #define ELF_INPUT_SECTION 256
      83             : 
      84             : /* argp key value for --dwarf-skeleton, non-ascii.  */
      85             : #define DWARF_SKELETON 257
      86             : 
      87             : /* Terrible hack for hooking unrelated skeleton/split compile units,
      88             :    see __libdw_link_skel_split in print_debug.  */
      89             : static bool do_not_close_dwfl = false;
      90             : 
      91             : /* Definitions of arguments for argp functions.  */
      92             : static const struct argp_option options[] =
      93             : {
      94             :   { NULL, 0, NULL, 0, N_("ELF input selection:"), 0 },
      95             :   { "elf-section", ELF_INPUT_SECTION, "SECTION", OPTION_ARG_OPTIONAL,
      96             :     N_("Use the named SECTION (default .gnu_debugdata) as (compressed) ELF "
      97             :        "input data"), 0 },
      98             :   { "dwarf-skeleton", DWARF_SKELETON, "FILE", 0,
      99             :     N_("Used with -w to find the skeleton Compile Units in FILE associated "
     100             :        "with the Split Compile units in a .dwo input file"), 0 },
     101             :   { NULL, 0, NULL, 0, N_("ELF output selection:"), 0 },
     102             :   { "all", 'a', NULL, 0,
     103             :     N_("All these plus -p .strtab -p .dynstr -p .comment"), 0 },
     104             :   { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
     105             :   { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
     106             :   { "histogram", 'I', NULL, 0,
     107             :     N_("Display histogram of bucket list lengths"), 0 },
     108             :   { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
     109             :   { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
     110             :   { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
     111             :   { "section-groups", 'g', NULL, 0, N_("Display the section groups"), 0 },
     112             :   { "section-headers", 'S', NULL, 0, N_("Display the sections' headers"), 0 },
     113             :   { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
     114             :   { "symbols", 's', "SECTION", OPTION_ARG_OPTIONAL,
     115             :     N_("Display the symbol table sections"), 0 },
     116             :   { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
     117             :   { "notes", 'n', NULL, 0, N_("Display the ELF notes"), 0 },
     118             :   { "arch-specific", 'A', NULL, 0,
     119             :     N_("Display architecture specific information, if any"), 0 },
     120             :   { "exception", 'e', NULL, 0,
     121             :     N_("Display sections for exception handling"), 0 },
     122             : 
     123             :   { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 },
     124             :   { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
     125             :     N_("Display DWARF section content.  SECTION can be one of abbrev, addr, "
     126             :        "aranges, decodedaranges, frame, gdb_index, info, info+, loc, line, "
     127             :        "decodedline, ranges, pubnames, str, macinfo, macro or exception"), 0 },
     128             :   { "hex-dump", 'x', "SECTION", 0,
     129             :     N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
     130             :   { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
     131             :     N_("Print string contents of sections"), 0 },
     132             :   { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
     133             :   { "archive-index", 'c', NULL, 0,
     134             :     N_("Display the symbol index of an archive"), 0 },
     135             : 
     136             :   { NULL, 0, NULL, 0, N_("Output control:"), 0 },
     137             :   { "numeric-addresses", 'N', NULL, 0,
     138             :     N_("Do not find symbol names for addresses in DWARF data"), 0 },
     139             :   { "unresolved-address-offsets", 'U', NULL, 0,
     140             :     N_("Display just offsets instead of resolving values to addresses in DWARF data"), 0 },
     141             :   { "wide", 'W', NULL, 0,
     142             :     N_("Ignored for compatibility (lines always wide)"), 0 },
     143             :   { "decompress", 'z', NULL, 0,
     144             :     N_("Show compression information for compressed sections (when used with -S); decompress section before dumping data (when used with -p or -x)"), 0 },
     145             :   { NULL, 0, NULL, 0, NULL, 0 }
     146             : };
     147             : 
     148             : /* Short description of program.  */
     149             : static const char doc[] = N_("\
     150             : Print information from ELF file in human-readable form.");
     151             : 
     152             : /* Strings for arguments in help texts.  */
     153             : static const char args_doc[] = N_("FILE...");
     154             : 
     155             : /* Prototype for option handler.  */
     156             : static error_t parse_opt (int key, char *arg, struct argp_state *state);
     157             : 
     158             : /* Data structure to communicate with argp functions.  */
     159             : static struct argp argp =
     160             : {
     161             :   options, parse_opt, args_doc, doc, NULL, NULL, NULL
     162             : };
     163             : 
     164             : /* If non-null, the section from which we should read to (compressed) ELF.  */
     165             : static const char *elf_input_section = NULL;
     166             : 
     167             : /* If non-null, the file that contains the skeleton CUs.  */
     168             : static const char *dwarf_skeleton = NULL;
     169             : 
     170             : /* Flags set by the option controlling the output.  */
     171             : 
     172             : /* True if dynamic segment should be printed.  */
     173             : static bool print_dynamic_table;
     174             : 
     175             : /* True if the file header should be printed.  */
     176             : static bool print_file_header;
     177             : 
     178             : /* True if the program headers should be printed.  */
     179             : static bool print_program_header;
     180             : 
     181             : /* True if relocations should be printed.  */
     182             : static bool print_relocations;
     183             : 
     184             : /* True if the section headers should be printed.  */
     185             : static bool print_section_header;
     186             : 
     187             : /* True if the symbol table should be printed.  */
     188             : static bool print_symbol_table;
     189             : 
     190             : /* A specific section name, or NULL to print all symbol tables.  */
     191             : static char *symbol_table_section;
     192             : 
     193             : /* True if the version information should be printed.  */
     194             : static bool print_version_info;
     195             : 
     196             : /* True if section groups should be printed.  */
     197             : static bool print_section_groups;
     198             : 
     199             : /* True if bucket list length histogram should be printed.  */
     200             : static bool print_histogram;
     201             : 
     202             : /* True if the architecture specific data should be printed.  */
     203             : static bool print_arch;
     204             : 
     205             : /* True if note section content should be printed.  */
     206             : static bool print_notes;
     207             : 
     208             : /* True if SHF_STRINGS section content should be printed.  */
     209             : static bool print_string_sections;
     210             : 
     211             : /* True if archive index should be printed.  */
     212             : static bool print_archive_index;
     213             : 
     214             : /* True if any of the control options except print_archive_index is set.  */
     215             : static bool any_control_option;
     216             : 
     217             : /* True if we should print addresses from DWARF in symbolic form.  */
     218             : static bool print_address_names = true;
     219             : 
     220             : /* True if we should print raw values instead of relativized addresses.  */
     221             : static bool print_unresolved_addresses = false;
     222             : 
     223             : /* True if we should print the .debug_aranges section using libdw.  */
     224             : static bool decodedaranges = false;
     225             : 
     226             : /* True if we should print the .debug_aranges section using libdw.  */
     227             : static bool decodedline = false;
     228             : 
     229             : /* True if we want to show more information about compressed sections.  */
     230             : static bool print_decompress = false;
     231             : 
     232             : /* True if we want to show split compile units for debug_info skeletons.  */
     233             : static bool show_split_units = false;
     234             : 
     235             : /* Select printing of debugging sections.  */
     236             : static enum section_e
     237             : {
     238             :   section_abbrev = 1,           /* .debug_abbrev  */
     239             :   section_aranges = 2,          /* .debug_aranges  */
     240             :   section_frame = 4,            /* .debug_frame or .eh_frame & al.  */
     241             :   section_info = 8,             /* .debug_info, (implies .debug_types)  */
     242             :   section_line = 16,            /* .debug_line  */
     243             :   section_loc = 32,             /* .debug_loc  */
     244             :   section_pubnames = 64,        /* .debug_pubnames  */
     245             :   section_str = 128,            /* .debug_str  */
     246             :   section_macinfo = 256,        /* .debug_macinfo  */
     247             :   section_ranges = 512,         /* .debug_ranges  */
     248             :   section_exception = 1024,     /* .eh_frame & al.  */
     249             :   section_gdb_index = 2048,     /* .gdb_index  */
     250             :   section_macro = 4096,         /* .debug_macro  */
     251             :   section_addr = 8192,          /* .debug_addr  */
     252             :   section_types = 16384,        /* .debug_types (implied by .debug_info)  */
     253             :   section_all = (section_abbrev | section_aranges | section_frame
     254             :                  | section_info | section_line | section_loc
     255             :                  | section_pubnames | section_str | section_macinfo
     256             :                  | section_ranges | section_exception | section_gdb_index
     257             :                  | section_macro | section_addr | section_types)
     258             : } print_debug_sections, implicit_debug_sections;
     259             : 
     260             : /* Select hex dumping of sections.  */
     261             : static struct section_argument *dump_data_sections;
     262             : static struct section_argument **dump_data_sections_tail = &dump_data_sections;
     263             : 
     264             : /* Select string dumping of sections.  */
     265             : static struct section_argument *string_sections;
     266             : static struct section_argument **string_sections_tail = &string_sections;
     267             : 
     268             : struct section_argument
     269             : {
     270             :   struct section_argument *next;
     271             :   const char *arg;
     272             :   bool implicit;
     273             : };
     274             : 
     275             : /* Numbers of sections and program headers in the file.  */
     276             : static size_t shnum;
     277             : static size_t phnum;
     278             : 
     279             : 
     280             : /* Declarations of local functions.  */
     281             : static void process_file (int fd, const char *fname, bool only_one);
     282             : static void process_elf_file (Dwfl_Module *dwflmod, int fd);
     283             : static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
     284             : static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
     285             : static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
     286             : static void print_scngrp (Ebl *ebl);
     287             : static void print_dynamic (Ebl *ebl);
     288             : static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
     289             : static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
     290             :                                GElf_Shdr *shdr);
     291             : static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
     292             :                                 GElf_Shdr *shdr);
     293             : static void print_symtab (Ebl *ebl, int type);
     294             : static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
     295             : static void print_verinfo (Ebl *ebl);
     296             : static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
     297             : static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
     298             : static void handle_versym (Ebl *ebl, Elf_Scn *scn,
     299             :                            GElf_Shdr *shdr);
     300             : static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
     301             : static void handle_hash (Ebl *ebl);
     302             : static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
     303             : static void print_liblist (Ebl *ebl);
     304             : static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
     305             : static void dump_data (Ebl *ebl);
     306             : static void dump_strings (Ebl *ebl);
     307             : static void print_strings (Ebl *ebl);
     308             : static void dump_archive_index (Elf *, const char *);
     309             : 
     310             : 
     311             : /* Looked up once with gettext in main.  */
     312             : static char *yes_str;
     313             : static char *no_str;
     314             : 
     315             : static void
     316             : cleanup_list (struct section_argument *list)
     317             : {
     318         716 :   while (list != NULL)
     319             :     {
     320         132 :       struct section_argument *a = list;
     321         132 :       list = a->next;
     322         132 :       free (a);
     323             :     }
     324             : }
     325             : 
     326             : int
     327         292 : main (int argc, char *argv[])
     328             : {
     329             :   /* We use no threads here which can interfere with handling a stream.  */
     330         292 :   (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
     331             : 
     332             :   /* Set locale.  */
     333         292 :   setlocale (LC_ALL, "");
     334             : 
     335             :   /* Initialize the message catalog.  */
     336         292 :   textdomain (PACKAGE_TARNAME);
     337             : 
     338             :   /* Look up once.  */
     339         292 :   yes_str = gettext ("yes");
     340         292 :   no_str = gettext ("no");
     341             : 
     342             :   /* Parse and process arguments.  */
     343         292 :   int remaining;
     344         292 :   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
     345             : 
     346             :   /* Before we start tell the ELF library which version we are using.  */
     347         292 :   elf_version (EV_CURRENT);
     348             : 
     349             :   /* Now process all the files given at the command line.  */
     350         292 :   bool only_one = remaining + 1 == argc;
     351         299 :   do
     352             :     {
     353             :       /* Open the file.  */
     354         299 :       int fd = open (argv[remaining], O_RDONLY);
     355         299 :       if (fd == -1)
     356             :         {
     357           0 :           error (0, errno, gettext ("cannot open input file"));
     358           0 :           continue;
     359             :         }
     360             : 
     361         299 :       process_file (fd, argv[remaining], only_one);
     362             : 
     363         299 :       close (fd);
     364             :     }
     365         299 :   while (++remaining < argc);
     366             : 
     367         292 :   cleanup_list (dump_data_sections);
     368         292 :   cleanup_list (string_sections);
     369             : 
     370         292 :   return error_message_count != 0;
     371             : }
     372             : 
     373             : 
     374             : /* Handle program arguments.  */
     375             : static error_t
     376        1818 : parse_opt (int key, char *arg,
     377             :            struct argp_state *state __attribute__ ((unused)))
     378             : {
     379        1950 :   void add_dump_section (const char *name, bool implicit)
     380             :   {
     381         132 :     struct section_argument *a = xmalloc (sizeof *a);
     382         132 :     a->arg = name;
     383         132 :     a->next = NULL;
     384         132 :     a->implicit = implicit;
     385         264 :     struct section_argument ***tailp
     386         132 :       = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
     387         132 :     **tailp = a;
     388         132 :     *tailp = &a->next;
     389         132 :   }
     390             : 
     391        1818 :   switch (key)
     392             :     {
     393          42 :     case 'a':
     394          42 :       print_file_header = true;
     395          42 :       print_program_header = true;
     396          42 :       print_relocations = true;
     397          42 :       print_section_header = true;
     398          42 :       print_symbol_table = true;
     399          42 :       print_version_info = true;
     400          42 :       print_dynamic_table = true;
     401          42 :       print_section_groups = true;
     402          42 :       print_histogram = true;
     403          42 :       print_arch = true;
     404          42 :       print_notes = true;
     405          42 :       implicit_debug_sections |= section_exception;
     406          42 :       add_dump_section (".strtab", true);
     407          42 :       add_dump_section (".dynstr", true);
     408          42 :       add_dump_section (".comment", true);
     409          42 :       any_control_option = true;
     410          42 :       break;
     411           4 :     case 'A':
     412           4 :       print_arch = true;
     413           4 :       any_control_option = true;
     414           4 :       break;
     415           2 :     case 'd':
     416           2 :       print_dynamic_table = true;
     417           2 :       any_control_option = true;
     418           2 :       break;
     419           0 :     case 'e':
     420           0 :       print_debug_sections |= section_exception;
     421           0 :       any_control_option = true;
     422           0 :       break;
     423           9 :     case 'g':
     424           9 :       print_section_groups = true;
     425           9 :       any_control_option = true;
     426           9 :       break;
     427           0 :     case 'h':
     428           0 :       print_file_header = true;
     429           0 :       any_control_option = true;
     430           0 :       break;
     431           0 :     case 'I':
     432           0 :       print_histogram = true;
     433           0 :       any_control_option = true;
     434           0 :       break;
     435           0 :     case 'l':
     436           0 :       print_program_header = true;
     437           0 :       any_control_option = true;
     438           0 :       break;
     439          20 :     case 'n':
     440          20 :       print_notes = true;
     441          20 :       any_control_option = true;
     442          20 :       break;
     443           1 :     case 'r':
     444           1 :       print_relocations = true;
     445           1 :       any_control_option = true;
     446           1 :      break;
     447          90 :     case 'S':
     448          90 :       print_section_header = true;
     449          90 :       any_control_option = true;
     450          90 :       break;
     451          14 :     case 's':
     452          14 :       print_symbol_table = true;
     453          14 :       any_control_option = true;
     454          14 :       symbol_table_section = arg;
     455          14 :       break;
     456           0 :     case 'V':
     457           0 :       print_version_info = true;
     458           0 :       any_control_option = true;
     459           0 :       break;
     460           2 :     case 'c':
     461           2 :       print_archive_index = true;
     462           2 :       break;
     463         117 :     case 'w':
     464         117 :       if (arg == NULL)
     465             :         {
     466          41 :           print_debug_sections = section_all;
     467          41 :           implicit_debug_sections = section_info;
     468          41 :           show_split_units = true;
     469             :         }
     470          76 :       else if (strcmp (arg, "abbrev") == 0)
     471           0 :         print_debug_sections |= section_abbrev;
     472          76 :       else if (strcmp (arg, "addr") == 0)
     473             :         {
     474           2 :           print_debug_sections |= section_addr;
     475           2 :           implicit_debug_sections |= section_info;
     476             :         }
     477          74 :       else if (strcmp (arg, "aranges") == 0)
     478           3 :         print_debug_sections |= section_aranges;
     479          71 :       else if (strcmp (arg, "decodedaranges") == 0)
     480             :         {
     481           1 :           print_debug_sections |= section_aranges;
     482           1 :           decodedaranges = true;
     483             :         }
     484          70 :       else if (strcmp (arg, "ranges") == 0)
     485             :         {
     486          12 :           print_debug_sections |= section_ranges;
     487          12 :           implicit_debug_sections |= section_info;
     488             :         }
     489          58 :       else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
     490           2 :         print_debug_sections |= section_frame;
     491          56 :       else if (strcmp (arg, "info") == 0)
     492             :         {
     493          18 :           print_debug_sections |= section_info;
     494          18 :           print_debug_sections |= section_types;
     495             :         }
     496          38 :       else if (strcmp (arg, "info+") == 0)
     497             :         {
     498           2 :           print_debug_sections |= section_info;
     499           2 :           print_debug_sections |= section_types;
     500           2 :           show_split_units = true;
     501             :         }
     502          36 :       else if (strcmp (arg, "loc") == 0)
     503             :         {
     504          18 :           print_debug_sections |= section_loc;
     505          18 :           implicit_debug_sections |= section_info;
     506             :         }
     507          18 :       else if (strcmp (arg, "line") == 0)
     508           6 :         print_debug_sections |= section_line;
     509          12 :       else if (strcmp (arg, "decodedline") == 0)
     510             :         {
     511           4 :           print_debug_sections |= section_line;
     512           4 :           decodedline = true;
     513             :         }
     514           8 :       else if (strcmp (arg, "pubnames") == 0)
     515           0 :         print_debug_sections |= section_pubnames;
     516           8 :       else if (strcmp (arg, "str") == 0)
     517             :         {
     518           3 :           print_debug_sections |= section_str;
     519             :           /* For mapping string offset tables to CUs.  */
     520           3 :           implicit_debug_sections |= section_info;
     521             :         }
     522           5 :       else if (strcmp (arg, "macinfo") == 0)
     523           0 :         print_debug_sections |= section_macinfo;
     524           5 :       else if (strcmp (arg, "macro") == 0)
     525           3 :         print_debug_sections |= section_macro;
     526           2 :       else if (strcmp (arg, "exception") == 0)
     527           0 :         print_debug_sections |= section_exception;
     528           2 :       else if (strcmp (arg, "gdb_index") == 0)
     529           2 :         print_debug_sections |= section_gdb_index;
     530             :       else
     531             :         {
     532           0 :           fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
     533             :                    arg);
     534           0 :           argp_help (&argp, stderr, ARGP_HELP_SEE,
     535             :                      program_invocation_short_name);
     536           0 :           exit (1);
     537             :         }
     538         117 :       any_control_option = true;
     539         117 :       break;
     540           1 :     case 'p':
     541           1 :       any_control_option = true;
     542           1 :       if (arg == NULL)
     543             :         {
     544           0 :           print_string_sections = true;
     545           0 :           break;
     546             :         }
     547           6 :       FALLTHROUGH;
     548             :     case 'x':
     549           6 :       add_dump_section (arg, false);
     550           6 :       any_control_option = true;
     551           6 :       break;
     552           2 :     case 'N':
     553           2 :       print_address_names = false;
     554           2 :       break;
     555          27 :     case 'U':
     556          27 :       print_unresolved_addresses = true;
     557          27 :       break;
     558           0 :     case ARGP_KEY_NO_ARGS:
     559           0 :       fputs (gettext ("Missing file name.\n"), stderr);
     560           0 :       goto do_argp_help;
     561         292 :     case ARGP_KEY_FINI:
     562         292 :       if (! any_control_option && ! print_archive_index)
     563             :         {
     564           0 :           fputs (gettext ("No operation specified.\n"), stderr);
     565           0 :         do_argp_help:
     566           0 :           argp_help (&argp, stderr, ARGP_HELP_SEE,
     567             :                      program_invocation_short_name);
     568           0 :           exit (EXIT_FAILURE);
     569             :         }
     570             :       break;
     571             :     case 'W':                   /* Ignored.  */
     572             :       break;
     573          13 :     case 'z':
     574          13 :       print_decompress = true;
     575          13 :       break;
     576           4 :     case ELF_INPUT_SECTION:
     577           4 :       if (arg == NULL)
     578           4 :         elf_input_section = ".gnu_debugdata";
     579             :       else
     580           0 :         elf_input_section = arg;
     581             :       break;
     582           5 :     case DWARF_SKELETON:
     583           5 :       dwarf_skeleton = arg;
     584           5 :       break;
     585             :     default:
     586             :       return ARGP_ERR_UNKNOWN;
     587             :     }
     588             :   return 0;
     589             : }
     590             : 
     591             : 
     592             : /* Create a file descriptor to read the data from the
     593             :    elf_input_section given a file descriptor to an ELF file.  */
     594             : static int
     595           4 : open_input_section (int fd)
     596             : {
     597           4 :   size_t shnums;
     598           4 :   size_t cnt;
     599           4 :   size_t shstrndx;
     600           4 :   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
     601           4 :   if (elf == NULL)
     602             :     {
     603           0 :       error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
     604             :              elf_errmsg (-1));
     605           0 :       return -1;
     606             :     }
     607             : 
     608           4 :   if (elf_getshdrnum (elf, &shnums) < 0)
     609             :     {
     610           0 :       error (0, 0, gettext ("cannot determine number of sections: %s"),
     611             :              elf_errmsg (-1));
     612           0 :     open_error:
     613           0 :       elf_end (elf);
     614           0 :       return -1;
     615             :     }
     616             : 
     617           4 :   if (elf_getshdrstrndx (elf, &shstrndx) < 0)
     618             :     {
     619           0 :       error (0, 0, gettext ("cannot get section header string table index"));
     620           0 :       goto open_error;
     621             :     }
     622             : 
     623          91 :   for (cnt = 0; cnt < shnums; ++cnt)
     624             :     {
     625          91 :       Elf_Scn *scn = elf_getscn (elf, cnt);
     626          91 :       if (scn == NULL)
     627             :         {
     628           0 :           error (0, 0, gettext ("cannot get section: %s"),
     629             :                  elf_errmsg (-1));
     630           0 :           goto open_error;
     631             :         }
     632             : 
     633          91 :       GElf_Shdr shdr_mem;
     634          91 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
     635          91 :       if (unlikely (shdr == NULL))
     636             :         {
     637           0 :           error (0, 0, gettext ("cannot get section header: %s"),
     638             :                  elf_errmsg (-1));
     639           0 :           goto open_error;
     640             :         }
     641             : 
     642          91 :       const char *sname = elf_strptr (elf, shstrndx, shdr->sh_name);
     643          91 :       if (sname == NULL)
     644             :         {
     645           0 :           error (0, 0, gettext ("cannot get section name"));
     646           0 :           goto open_error;
     647             :         }
     648             : 
     649          91 :       if (strcmp (sname, elf_input_section) == 0)
     650             :         {
     651           4 :           Elf_Data *data = elf_rawdata (scn, NULL);
     652           4 :           if (data == NULL)
     653             :             {
     654           0 :               error (0, 0, gettext ("cannot get %s content: %s"),
     655             :                      sname, elf_errmsg (-1));
     656           0 :               goto open_error;
     657             :             }
     658             : 
     659             :           /* Create (and immediately unlink) a temporary file to store
     660             :              section data in to create a file descriptor for it.  */
     661           4 :           const char *tmpdir = getenv ("TMPDIR") ?: P_tmpdir;
     662           4 :           static const char suffix[] = "/readelfXXXXXX";
     663           4 :           int tmplen = strlen (tmpdir) + sizeof (suffix);
     664           4 :           char *tempname = alloca (tmplen);
     665           4 :           sprintf (tempname, "%s%s", tmpdir, suffix);
     666             : 
     667           4 :           int sfd = mkstemp (tempname);
     668           4 :           if (sfd == -1)
     669             :             {
     670           0 :               error (0, 0, gettext ("cannot create temp file '%s'"),
     671             :                      tempname);
     672           0 :               goto open_error;
     673             :             }
     674           4 :           unlink (tempname);
     675             : 
     676           4 :           ssize_t size = data->d_size;
     677           4 :           if (write_retry (sfd, data->d_buf, size) != size)
     678             :             {
     679           0 :               error (0, 0, gettext ("cannot write section data"));
     680           0 :               goto open_error;
     681             :             }
     682             : 
     683           4 :           if (elf_end (elf) != 0)
     684             :             {
     685           0 :               error (0, 0, gettext ("error while closing Elf descriptor: %s"),
     686             :                      elf_errmsg (-1));
     687           4 :               return -1;
     688             :             }
     689             : 
     690           4 :           if (lseek (sfd, 0, SEEK_SET) == -1)
     691             :             {
     692           0 :               error (0, 0, gettext ("error while rewinding file descriptor"));
     693           0 :               return -1;
     694             :             }
     695             : 
     696             :           return sfd;
     697             :         }
     698             :     }
     699             : 
     700             :   /* Named section not found.  */
     701           0 :   if (elf_end (elf) != 0)
     702           0 :     error (0, 0, gettext ("error while closing Elf descriptor: %s"),
     703             :            elf_errmsg (-1));
     704             :   return -1;
     705             : }
     706             : 
     707             : /* Check if the file is an archive, and if so dump its index.  */
     708             : static void
     709           2 : check_archive_index (int fd, const char *fname, bool only_one)
     710             : {
     711             :   /* Create an `Elf' descriptor.  */
     712           2 :   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
     713           2 :   if (elf == NULL)
     714           0 :     error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
     715             :            elf_errmsg (-1));
     716             :   else
     717             :     {
     718           2 :       if (elf_kind (elf) == ELF_K_AR)
     719             :         {
     720           2 :           if (!only_one)
     721           0 :             printf ("\n%s:\n\n", fname);
     722           2 :           dump_archive_index (elf, fname);
     723             :         }
     724             :       else
     725           0 :         error (0, 0,
     726           0 :                gettext ("'%s' is not an archive, cannot print archive index"),
     727             :                fname);
     728             : 
     729             :       /* Now we can close the descriptor.  */
     730           2 :       if (elf_end (elf) != 0)
     731           0 :         error (0, 0, gettext ("error while closing Elf descriptor: %s"),
     732             :                elf_errmsg (-1));
     733             :     }
     734           2 : }
     735             : 
     736             : /* Trivial callback used for checking if we opened an archive.  */
     737             : static int
     738         283 : count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
     739             :                void **userdata __attribute__ ((unused)),
     740             :                const char *name __attribute__ ((unused)),
     741             :                Dwarf_Addr base __attribute__ ((unused)),
     742             :                void *arg)
     743             : {
     744         283 :   if (*(bool *) arg)
     745             :     return DWARF_CB_ABORT;
     746         283 :   *(bool *) arg = true;
     747         283 :   return DWARF_CB_OK;
     748             : }
     749             : 
     750             : struct process_dwflmod_args
     751             : {
     752             :   int fd;
     753             :   bool only_one;
     754             : };
     755             : 
     756             : static int
     757         297 : process_dwflmod (Dwfl_Module *dwflmod,
     758             :                  void **userdata __attribute__ ((unused)),
     759             :                  const char *name __attribute__ ((unused)),
     760             :                  Dwarf_Addr base __attribute__ ((unused)),
     761             :                  void *arg)
     762             : {
     763         297 :   const struct process_dwflmod_args *a = arg;
     764             : 
     765             :   /* Print the file name.  */
     766         297 :   if (!a->only_one)
     767             :     {
     768          14 :       const char *fname;
     769          14 :       dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
     770             : 
     771          14 :       printf ("\n%s:\n\n", fname);
     772             :     }
     773             : 
     774         297 :   process_elf_file (dwflmod, a->fd);
     775             : 
     776         297 :   return DWARF_CB_OK;
     777             : }
     778             : 
     779             : /* Stub libdwfl callback, only the ELF handle already open is ever used.
     780             :    Only used for finding the alternate debug file if the Dwarf comes from
     781             :    the main file.  We are not interested in separate debuginfo.  */
     782             : static int
     783          37 : find_no_debuginfo (Dwfl_Module *mod,
     784             :                    void **userdata,
     785             :                    const char *modname,
     786             :                    Dwarf_Addr base,
     787             :                    const char *file_name,
     788             :                    const char *debuglink_file,
     789             :                    GElf_Word debuglink_crc,
     790             :                    char **debuginfo_file_name)
     791             : {
     792          37 :   Dwarf_Addr dwbias;
     793          37 :   dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
     794             : 
     795             :   /* We are only interested if the Dwarf has been setup on the main
     796             :      elf file but is only missing the alternate debug link.  If dwbias
     797             :      hasn't even been setup, this is searching for separate debuginfo
     798             :      for the main elf.  We don't care in that case.  */
     799          37 :   if (dwbias == (Dwarf_Addr) -1)
     800             :     return -1;
     801             : 
     802           5 :   return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
     803             :                                        file_name, debuglink_file,
     804             :                                        debuglink_crc, debuginfo_file_name);
     805             : }
     806             : 
     807             : static Dwfl *
     808         306 : create_dwfl (int fd, const char *fname)
     809             : {
     810             :   /* Duplicate an fd for dwfl_report_offline to swallow.  */
     811         306 :   int dwfl_fd = dup (fd);
     812         306 :   if (unlikely (dwfl_fd < 0))
     813           0 :     error (EXIT_FAILURE, errno, "dup");
     814             : 
     815             :   /* Use libdwfl in a trivial way to open the libdw handle for us.
     816             :      This takes care of applying relocations to DWARF data in ET_REL files.  */
     817         306 :   static const Dwfl_Callbacks callbacks =
     818             :     {
     819             :       .section_address = dwfl_offline_section_address,
     820             :       .find_debuginfo = find_no_debuginfo
     821             :     };
     822         306 :   Dwfl *dwfl = dwfl_begin (&callbacks);
     823         306 :   if (likely (dwfl != NULL))
     824             :     /* Let 0 be the logical address of the file (or first in archive).  */
     825         306 :     dwfl->offline_next_address = 0;
     826         306 :   if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
     827             :     {
     828           0 :       struct stat st;
     829           0 :       if (fstat (dwfl_fd, &st) != 0)
     830           0 :         error (0, errno, gettext ("cannot stat input file"));
     831           0 :       else if (unlikely (st.st_size == 0))
     832           0 :         error (0, 0, gettext ("input file is empty"));
     833             :       else
     834           0 :         error (0, 0, gettext ("failed reading '%s': %s"),
     835             :                fname, dwfl_errmsg (-1));
     836           0 :       close (dwfl_fd);          /* Consumed on success, not on failure.  */
     837           0 :       dwfl = NULL;
     838             :     }
     839             :   else
     840         306 :     dwfl_report_end (dwfl, NULL, NULL);
     841             : 
     842         306 :   return dwfl;
     843             : }
     844             : 
     845             : /* Process one input file.  */
     846             : static void
     847         299 : process_file (int fd, const char *fname, bool only_one)
     848             : {
     849         299 :   if (print_archive_index)
     850           2 :     check_archive_index (fd, fname, only_one);
     851             : 
     852         299 :   if (!any_control_option)
     853             :     return;
     854             : 
     855         297 :   if (elf_input_section != NULL)
     856             :     {
     857             :       /* Replace fname and fd with section content. */
     858           4 :       char *fnname = alloca (strlen (fname) + strlen (elf_input_section) + 2);
     859           4 :       sprintf (fnname, "%s:%s", fname, elf_input_section);
     860           4 :       fd = open_input_section (fd);
     861           4 :       if (fd == -1)
     862             :         {
     863           0 :           error (0, 0, gettext ("No such section '%s' in '%s'"),
     864             :                  elf_input_section, fname);
     865           0 :           return;
     866             :         }
     867             :       fname = fnname;
     868             :     }
     869             : 
     870         297 :   Dwfl *dwfl = create_dwfl (fd, fname);
     871         297 :   if (dwfl != NULL)
     872             :     {
     873         297 :       if (only_one)
     874             :         {
     875             :           /* Clear ONLY_ONE if we have multiple modules, from an archive.  */
     876         283 :           bool seen = false;
     877         283 :           only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
     878             :         }
     879             : 
     880             :       /* Process the one or more modules gleaned from this file.  */
     881         297 :       struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
     882         297 :       dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
     883             :     }
     884             :   /* Terrible hack for hooking unrelated skeleton/split compile units,
     885             :      see __libdw_link_skel_split in print_debug.  */
     886         297 :   if (! do_not_close_dwfl)
     887         297 :     dwfl_end (dwfl);
     888             : 
     889             :   /* Need to close the replaced fd if we created it.  Caller takes
     890             :      care of original.  */
     891         297 :   if (elf_input_section != NULL)
     892           4 :     close (fd);
     893             : }
     894             : 
     895             : /* Check whether there are any compressed sections in the ELF file.  */
     896             : static bool
     897          96 : elf_contains_chdrs (Elf *elf)
     898             : {
     899          96 :   Elf_Scn *scn = NULL;
     900      788763 :   while ((scn = elf_nextscn (elf, scn)) != NULL)
     901             :     {
     902      788673 :       GElf_Shdr shdr_mem;
     903      788673 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
     904      788673 :       if (shdr != NULL && (shdr->sh_flags & SHF_COMPRESSED) != 0)
     905           6 :         return true;
     906             :     }
     907             :   return false;
     908             : }
     909             : 
     910             : /* Process one ELF file.  */
     911             : static void
     912         297 : process_elf_file (Dwfl_Module *dwflmod, int fd)
     913             : {
     914         297 :   GElf_Addr dwflbias;
     915         297 :   Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
     916             : 
     917         297 :   GElf_Ehdr ehdr_mem;
     918         297 :   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
     919             : 
     920         297 :   if (ehdr == NULL)
     921             :     {
     922           0 :       error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
     923           0 :       return;
     924             :     }
     925             : 
     926         297 :   Ebl *ebl = ebl_openbackend (elf);
     927         297 :   if (unlikely (ebl == NULL))
     928             :     {
     929           0 :     ebl_error:
     930           0 :       error (0, errno, gettext ("cannot create EBL handle"));
     931           0 :       return;
     932             :     }
     933             : 
     934             :   /* Determine the number of sections.  */
     935         297 :   if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
     936           0 :     error (EXIT_FAILURE, 0,
     937           0 :            gettext ("cannot determine number of sections: %s"),
     938             :            elf_errmsg (-1));
     939             : 
     940             :   /* Determine the number of phdrs.  */
     941         297 :   if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
     942           0 :     error (EXIT_FAILURE, 0,
     943           0 :            gettext ("cannot determine number of program headers: %s"),
     944             :            elf_errmsg (-1));
     945             : 
     946             :   /* For an ET_REL file, libdwfl has adjusted the in-core shdrs and
     947             :      may have applied relocation to some sections.  If there are any
     948             :      compressed sections, any pass (or libdw/libdwfl) might have
     949             :      uncompressed them.  So we need to get a fresh Elf handle on the
     950             :      file to display those.  */
     951         594 :   bool print_unchanged = ((print_section_header
     952         165 :                            || print_relocations
     953         164 :                            || dump_data_sections != NULL
     954         159 :                            || print_notes)
     955         323 :                           && (ehdr->e_type == ET_REL
     956          96 :                               || elf_contains_chdrs (ebl->elf)));
     957             : 
     958         297 :   Elf *pure_elf = NULL;
     959         297 :   Ebl *pure_ebl = ebl;
     960         297 :   if (print_unchanged)
     961             :     {
     962             :       /* Read the file afresh.  */
     963          68 :       off_t aroff = elf_getaroff (elf);
     964          68 :       pure_elf = dwelf_elf_begin (fd);
     965          68 :       if (aroff > 0)
     966             :         {
     967             :           /* Archive member.  */
     968           0 :           (void) elf_rand (pure_elf, aroff);
     969           0 :           Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
     970           0 :           elf_end (pure_elf);
     971           0 :           pure_elf = armem;
     972             :         }
     973          68 :       if (pure_elf == NULL)
     974             :         {
     975           0 :           error (0, 0, gettext ("cannot read ELF: %s"), elf_errmsg (-1));
     976           0 :           return;
     977             :         }
     978          68 :       pure_ebl = ebl_openbackend (pure_elf);
     979          68 :       if (pure_ebl == NULL)
     980             :         goto ebl_error;
     981             :     }
     982             : 
     983         297 :   if (print_file_header)
     984          42 :     print_ehdr (ebl, ehdr);
     985         297 :   if (print_section_header)
     986         132 :     print_shdr (pure_ebl, ehdr);
     987         297 :   if (print_program_header)
     988          42 :     print_phdr (ebl, ehdr);
     989         297 :   if (print_section_groups)
     990          51 :     print_scngrp (ebl);
     991         297 :   if (print_dynamic_table)
     992          44 :     print_dynamic (ebl);
     993         297 :   if (print_relocations)
     994          43 :     print_relocs (pure_ebl, ehdr);
     995         297 :   if (print_histogram)
     996          42 :     handle_hash (ebl);
     997         297 :   if (print_symbol_table)
     998          56 :     print_symtab (ebl, SHT_DYNSYM);
     999         297 :   if (print_version_info)
    1000          42 :     print_verinfo (ebl);
    1001         297 :   if (print_symbol_table)
    1002          56 :     print_symtab (ebl, SHT_SYMTAB);
    1003         297 :   if (print_arch)
    1004          46 :     print_liblist (ebl);
    1005         297 :   if (print_arch)
    1006          46 :     print_attributes (ebl, ehdr);
    1007         297 :   if (dump_data_sections != NULL)
    1008           5 :     dump_data (pure_ebl);
    1009         297 :   if (string_sections != NULL)
    1010          43 :     dump_strings (ebl);
    1011         297 :   if ((print_debug_sections | implicit_debug_sections) != 0)
    1012         151 :     print_debug (dwflmod, ebl, ehdr);
    1013         297 :   if (print_notes)
    1014          62 :     handle_notes (pure_ebl, ehdr);
    1015         297 :   if (print_string_sections)
    1016           0 :     print_strings (ebl);
    1017             : 
    1018         297 :   ebl_closebackend (ebl);
    1019             : 
    1020         297 :   if (pure_ebl != ebl)
    1021             :     {
    1022          68 :       ebl_closebackend (pure_ebl);
    1023          68 :       elf_end (pure_elf);
    1024             :     }
    1025             : }
    1026             : 
    1027             : 
    1028             : /* Print file type.  */
    1029             : static void
    1030          42 : print_file_type (unsigned short int e_type)
    1031             : {
    1032          42 :   if (likely (e_type <= ET_CORE))
    1033             :     {
    1034          42 :       static const char *const knowntypes[] =
    1035             :       {
    1036             :         N_("NONE (None)"),
    1037             :         N_("REL (Relocatable file)"),
    1038             :         N_("EXEC (Executable file)"),
    1039             :         N_("DYN (Shared object file)"),
    1040             :         N_("CORE (Core file)")
    1041             :       };
    1042          42 :       puts (gettext (knowntypes[e_type]));
    1043             :     }
    1044           0 :   else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
    1045           0 :     printf (gettext ("OS Specific: (%x)\n"),  e_type);
    1046           0 :   else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
    1047           0 :     printf (gettext ("Processor Specific: (%x)\n"),  e_type);
    1048             :   else
    1049           0 :     puts ("???");
    1050          42 : }
    1051             : 
    1052             : 
    1053             : /* Print ELF header.  */
    1054             : static void
    1055          42 : print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
    1056             : {
    1057          42 :   fputs_unlocked (gettext ("ELF Header:\n  Magic:  "), stdout);
    1058         714 :   for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
    1059         672 :     printf (" %02hhx", ehdr->e_ident[cnt]);
    1060             : 
    1061          42 :   printf (gettext ("\n  Class:                             %s\n"),
    1062          42 :           ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
    1063             :           : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
    1064          34 :           : "\?\?\?");
    1065             : 
    1066          42 :   printf (gettext ("  Data:                              %s\n"),
    1067          42 :           ehdr->e_ident[EI_DATA] == ELFDATA2LSB
    1068             :           ? "2's complement, little endian"
    1069             :           : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
    1070          12 :           ? "2's complement, big endian" : "\?\?\?");
    1071             : 
    1072         168 :   printf (gettext ("  Ident Version:                     %hhd %s\n"),
    1073          42 :           ehdr->e_ident[EI_VERSION],
    1074          42 :           ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
    1075             :           : "(\?\?\?)");
    1076             : 
    1077          42 :   char buf[512];
    1078          42 :   printf (gettext ("  OS/ABI:                            %s\n"),
    1079          42 :           ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
    1080             : 
    1081         126 :   printf (gettext ("  ABI Version:                       %hhd\n"),
    1082          42 :           ehdr->e_ident[EI_ABIVERSION]);
    1083             : 
    1084          42 :   fputs_unlocked (gettext ("  Type:                              "), stdout);
    1085          42 :   print_file_type (ehdr->e_type);
    1086             : 
    1087          42 :   const char *machine = dwelf_elf_e_machine_string (ehdr->e_machine);
    1088          42 :   if (machine != NULL)
    1089          42 :     printf (gettext ("  Machine:                           %s\n"), machine);
    1090             :   else
    1091           0 :     printf (gettext ("  Machine:                           <unknown>: 0x%x\n"),
    1092           0 :             ehdr->e_machine);
    1093             : 
    1094          42 :   printf (gettext ("  Version:                           %d %s\n"),
    1095             :           ehdr->e_version,
    1096          42 :           ehdr->e_version  == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
    1097             : 
    1098          42 :   printf (gettext ("  Entry point address:               %#" PRIx64 "\n"),
    1099             :           ehdr->e_entry);
    1100             : 
    1101          42 :   printf (gettext ("  Start of program headers:          %" PRId64 " %s\n"),
    1102             :           ehdr->e_phoff, gettext ("(bytes into file)"));
    1103             : 
    1104          42 :   printf (gettext ("  Start of section headers:          %" PRId64 " %s\n"),
    1105             :           ehdr->e_shoff, gettext ("(bytes into file)"));
    1106             : 
    1107          42 :   printf (gettext ("  Flags:                             %s\n"),
    1108             :           ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
    1109             : 
    1110         126 :   printf (gettext ("  Size of this header:               %" PRId16 " %s\n"),
    1111          42 :           ehdr->e_ehsize, gettext ("(bytes)"));
    1112             : 
    1113         126 :   printf (gettext ("  Size of program header entries:    %" PRId16 " %s\n"),
    1114          42 :           ehdr->e_phentsize, gettext ("(bytes)"));
    1115             : 
    1116         126 :   printf (gettext ("  Number of program headers entries: %" PRId16),
    1117          42 :           ehdr->e_phnum);
    1118          42 :   if (ehdr->e_phnum == PN_XNUM)
    1119             :     {
    1120           0 :       GElf_Shdr shdr_mem;
    1121           0 :       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
    1122           0 :       if (shdr != NULL)
    1123           0 :         printf (gettext (" (%" PRIu32 " in [0].sh_info)"),
    1124           0 :                 (uint32_t) shdr->sh_info);
    1125             :       else
    1126           0 :         fputs_unlocked (gettext (" ([0] not available)"), stdout);
    1127             :     }
    1128          42 :   fputc_unlocked ('\n', stdout);
    1129             : 
    1130         126 :   printf (gettext ("  Size of section header entries:    %" PRId16 " %s\n"),
    1131          42 :           ehdr->e_shentsize, gettext ("(bytes)"));
    1132             : 
    1133         126 :   printf (gettext ("  Number of section headers entries: %" PRId16),
    1134          42 :           ehdr->e_shnum);
    1135          42 :   if (ehdr->e_shnum == 0)
    1136             :     {
    1137           0 :       GElf_Shdr shdr_mem;
    1138           0 :       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
    1139           0 :       if (shdr != NULL)
    1140           0 :         printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
    1141           0 :                 (uint32_t) shdr->sh_size);
    1142             :       else
    1143           0 :         fputs_unlocked (gettext (" ([0] not available)"), stdout);
    1144             :     }
    1145          42 :   fputc_unlocked ('\n', stdout);
    1146             : 
    1147          42 :   if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
    1148             :     {
    1149           0 :       GElf_Shdr shdr_mem;
    1150           0 :       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
    1151           0 :       if (shdr != NULL)
    1152             :         /* We managed to get the zeroth section.  */
    1153           0 :         snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
    1154           0 :                   (uint32_t) shdr->sh_link);
    1155             :       else
    1156             :         {
    1157           0 :           strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
    1158           0 :           buf[sizeof (buf) - 1] = '\0';
    1159             :         }
    1160             : 
    1161           0 :       printf (gettext ("  Section header string table index: XINDEX%s\n\n"),
    1162             :               buf);
    1163             :     }
    1164             :   else
    1165          42 :     printf (gettext ("  Section header string table index: %" PRId16 "\n\n"),
    1166             :             ehdr->e_shstrndx);
    1167          42 : }
    1168             : 
    1169             : 
    1170             : static const char *
    1171             : get_visibility_type (int value)
    1172             : {
    1173       14971 :   switch (value)
    1174             :     {
    1175             :     case STV_DEFAULT:
    1176             :       return "DEFAULT";
    1177           0 :     case STV_INTERNAL:
    1178           0 :       return "INTERNAL";
    1179          68 :     case STV_HIDDEN:
    1180          68 :       return "HIDDEN";
    1181           0 :     case STV_PROTECTED:
    1182           0 :       return "PROTECTED";
    1183           0 :     default:
    1184           0 :       return "???";
    1185             :     }
    1186             : }
    1187             : 
    1188             : static const char *
    1189             : elf_ch_type_name (unsigned int code)
    1190             : {
    1191           0 :   if (code == 0)
    1192             :     return "NONE";
    1193             : 
    1194           0 :   if (code == ELFCOMPRESS_ZLIB)
    1195           0 :     return "ZLIB";
    1196             : 
    1197             :   return "UNKNOWN";
    1198             : }
    1199             : 
    1200             : /* Print the section headers.  */
    1201             : static void
    1202           0 : print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
    1203             : {
    1204           0 :   size_t cnt;
    1205           0 :   size_t shstrndx;
    1206             : 
    1207           0 :   if (! print_file_header)
    1208             :     {
    1209           0 :       size_t sections;
    1210           0 :       if (unlikely (elf_getshdrnum (ebl->elf, &sections) < 0))
    1211           0 :         error (EXIT_FAILURE, 0,
    1212           0 :                gettext ("cannot get number of sections: %s"),
    1213             :                elf_errmsg (-1));
    1214             : 
    1215           0 :       printf (gettext ("\
    1216             : There are %zd section headers, starting at offset %#" PRIx64 ":\n\
    1217             : \n"),
    1218             :               sections, ehdr->e_shoff);
    1219             :     }
    1220             : 
    1221             :   /* Get the section header string table index.  */
    1222           0 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    1223           0 :     error (EXIT_FAILURE, 0,
    1224           0 :            gettext ("cannot get section header string table index: %s"),
    1225             :            elf_errmsg (-1));
    1226             : 
    1227           0 :   puts (gettext ("Section Headers:"));
    1228             : 
    1229           0 :   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
    1230           0 :     puts (gettext ("[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al"));
    1231             :   else
    1232           0 :     puts (gettext ("[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al"));
    1233             : 
    1234           0 :   if (print_decompress)
    1235             :     {
    1236           0 :       if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
    1237           0 :         puts (gettext ("     [Compression  Size   Al]"));
    1238             :       else
    1239           0 :         puts (gettext ("     [Compression  Size     Al]"));
    1240             :     }
    1241             : 
    1242           0 :   for (cnt = 0; cnt < shnum; ++cnt)
    1243             :     {
    1244           0 :       Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
    1245             : 
    1246           0 :       if (unlikely (scn == NULL))
    1247           0 :         error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
    1248             :                elf_errmsg (-1));
    1249             : 
    1250             :       /* Get the section header.  */
    1251           0 :       GElf_Shdr shdr_mem;
    1252           0 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1253           0 :       if (unlikely (shdr == NULL))
    1254           0 :         error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
    1255             :                elf_errmsg (-1));
    1256             : 
    1257           0 :       char flagbuf[20];
    1258           0 :       char *cp = flagbuf;
    1259           0 :       if (shdr->sh_flags & SHF_WRITE)
    1260           0 :         *cp++ = 'W';
    1261           0 :       if (shdr->sh_flags & SHF_ALLOC)
    1262           0 :         *cp++ = 'A';
    1263           0 :       if (shdr->sh_flags & SHF_EXECINSTR)
    1264           0 :         *cp++ = 'X';
    1265           0 :       if (shdr->sh_flags & SHF_MERGE)
    1266           0 :         *cp++ = 'M';
    1267           0 :       if (shdr->sh_flags & SHF_STRINGS)
    1268           0 :         *cp++ = 'S';
    1269           0 :       if (shdr->sh_flags & SHF_INFO_LINK)
    1270           0 :         *cp++ = 'I';
    1271           0 :       if (shdr->sh_flags & SHF_LINK_ORDER)
    1272           0 :         *cp++ = 'L';
    1273           0 :       if (shdr->sh_flags & SHF_OS_NONCONFORMING)
    1274           0 :         *cp++ = 'N';
    1275           0 :       if (shdr->sh_flags & SHF_GROUP)
    1276           0 :         *cp++ = 'G';
    1277           0 :       if (shdr->sh_flags & SHF_TLS)
    1278           0 :         *cp++ = 'T';
    1279           0 :       if (shdr->sh_flags & SHF_COMPRESSED)
    1280           0 :         *cp++ = 'C';
    1281           0 :       if (shdr->sh_flags & SHF_ORDERED)
    1282           0 :         *cp++ = 'O';
    1283           0 :       if (shdr->sh_flags & SHF_EXCLUDE)
    1284           0 :         *cp++ = 'E';
    1285           0 :       *cp = '\0';
    1286             : 
    1287           0 :       const char *sname;
    1288           0 :       char buf[128];
    1289           0 :       sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "<corrupt>";
    1290           0 :       printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
    1291             :               " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
    1292             :               " %2" PRId64 "\n",
    1293             :               cnt, sname,
    1294           0 :               ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
    1295             :               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
    1296             :               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
    1297           0 :               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
    1298             :               shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
    1299             :               shdr->sh_addralign);
    1300             : 
    1301           0 :       if (print_decompress)
    1302             :         {
    1303           0 :           if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
    1304             :             {
    1305           0 :               GElf_Chdr chdr;
    1306           0 :               if (gelf_getchdr (scn, &chdr) != NULL)
    1307           0 :                 printf ("     [ELF %s (%" PRId32 ") %0*" PRIx64
    1308             :                         " %2" PRId64 "]\n",
    1309             :                         elf_ch_type_name (chdr.ch_type),
    1310             :                         chdr.ch_type,
    1311           0 :                         ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8,
    1312             :                         chdr.ch_size, chdr.ch_addralign);
    1313             :               else
    1314           0 :                 error (0, 0,
    1315           0 :                        gettext ("bad compression header for section %zd: %s"),
    1316             :                        elf_ndxscn (scn), elf_errmsg (-1));
    1317             :             }
    1318           0 :           else if (strncmp(".zdebug", sname, strlen (".zdebug")) == 0)
    1319             :             {
    1320           0 :               ssize_t size;
    1321           0 :               if ((size = dwelf_scn_gnu_compressed_size (scn)) >= 0)
    1322           0 :                 printf ("     [GNU ZLIB     %0*zx   ]\n",
    1323           0 :                         ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, size);
    1324             :               else
    1325           0 :                 error (0, 0,
    1326           0 :                        gettext ("bad gnu compressed size for section %zd: %s"),
    1327             :                        elf_ndxscn (scn), elf_errmsg (-1));
    1328             :             }
    1329             :         }
    1330             :     }
    1331             : 
    1332           0 :   fputc_unlocked ('\n', stdout);
    1333           0 : }
    1334             : 
    1335             : 
    1336             : /* Print the program header.  */
    1337             : static void
    1338           0 : print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
    1339             : {
    1340           0 :   if (phnum == 0)
    1341             :     /* No program header, this is OK in relocatable objects.  */
    1342           0 :     return;
    1343             : 
    1344           0 :   puts (gettext ("Program Headers:"));
    1345           0 :   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
    1346           0 :     puts (gettext ("\
    1347             :   Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"));
    1348             :   else
    1349           0 :     puts (gettext ("\
    1350             :   Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align"));
    1351             : 
    1352             :   /* Process all program headers.  */
    1353             :   bool has_relro = false;
    1354             :   GElf_Addr relro_from = 0;
    1355             :   GElf_Addr relro_to = 0;
    1356           0 :   for (size_t cnt = 0; cnt < phnum; ++cnt)
    1357             :     {
    1358           0 :       char buf[128];
    1359           0 :       GElf_Phdr mem;
    1360           0 :       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
    1361             : 
    1362             :       /* If for some reason the header cannot be returned show this.  */
    1363           0 :       if (unlikely (phdr == NULL))
    1364             :         {
    1365           0 :           puts ("  ???");
    1366           0 :           continue;
    1367             :         }
    1368             : 
    1369           0 :       printf ("  %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
    1370             :               " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
    1371           0 :               ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
    1372             :               phdr->p_offset,
    1373             :               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
    1374           0 :               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
    1375             :               phdr->p_filesz,
    1376             :               phdr->p_memsz,
    1377           0 :               phdr->p_flags & PF_R ? 'R' : ' ',
    1378           0 :               phdr->p_flags & PF_W ? 'W' : ' ',
    1379           0 :               phdr->p_flags & PF_X ? 'E' : ' ',
    1380             :               phdr->p_align);
    1381             : 
    1382           0 :       if (phdr->p_type == PT_INTERP)
    1383             :         {
    1384             :           /* If we are sure the file offset is valid then we can show
    1385             :              the user the name of the interpreter.  We check whether
    1386             :              there is a section at the file offset.  Normally there
    1387             :              would be a section called ".interp".  But in separate
    1388             :              .debug files it is a NOBITS section (and so doesn't match
    1389             :              with gelf_offscn).  Which probably means the offset is
    1390             :              not valid another reason could be because the ELF file
    1391             :              just doesn't contain any section headers, in that case
    1392             :              just play it safe and don't display anything.  */
    1393             : 
    1394           0 :           Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
    1395           0 :           GElf_Shdr shdr_mem;
    1396           0 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1397             : 
    1398           0 :           size_t maxsize;
    1399           0 :           char *filedata = elf_rawfile (ebl->elf, &maxsize);
    1400             : 
    1401           0 :           if (shdr != NULL && shdr->sh_type == SHT_PROGBITS
    1402           0 :               && filedata != NULL && phdr->p_offset < maxsize
    1403           0 :               && phdr->p_filesz <= maxsize - phdr->p_offset
    1404           0 :               && memchr (filedata + phdr->p_offset, '\0',
    1405             :                          phdr->p_filesz) != NULL)
    1406           0 :             printf (gettext ("\t[Requesting program interpreter: %s]\n"),
    1407             :                     filedata + phdr->p_offset);
    1408             :         }
    1409           0 :       else if (phdr->p_type == PT_GNU_RELRO)
    1410             :         {
    1411           0 :           has_relro = true;
    1412           0 :           relro_from = phdr->p_vaddr;
    1413           0 :           relro_to = relro_from + phdr->p_memsz;
    1414             :         }
    1415             :     }
    1416             : 
    1417           0 :   size_t sections;
    1418           0 :   if (unlikely (elf_getshdrnum (ebl->elf, &sections) < 0))
    1419           0 :     error (EXIT_FAILURE, 0,
    1420           0 :            gettext ("cannot get number of sections: %s"),
    1421             :            elf_errmsg (-1));
    1422             : 
    1423           0 :   if (sections == 0)
    1424             :     /* No sections in the file.  Punt.  */
    1425           0 :     return;
    1426             : 
    1427             :   /* Get the section header string table index.  */
    1428           0 :   size_t shstrndx;
    1429           0 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    1430           0 :     error (EXIT_FAILURE, 0,
    1431           0 :            gettext ("cannot get section header string table index"));
    1432             : 
    1433           0 :   puts (gettext ("\n Section to Segment mapping:\n  Segment Sections..."));
    1434             : 
    1435           0 :   for (size_t cnt = 0; cnt < phnum; ++cnt)
    1436             :     {
    1437             :       /* Print the segment number.  */
    1438           0 :       printf ("   %2.2zu     ", cnt);
    1439             : 
    1440           0 :       GElf_Phdr phdr_mem;
    1441           0 :       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
    1442             :       /* This must not happen.  */
    1443           0 :       if (unlikely (phdr == NULL))
    1444           0 :         error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
    1445             :                elf_errmsg (-1));
    1446             : 
    1447             :       /* Iterate over the sections.  */
    1448             :       bool in_relro = false;
    1449             :       bool in_ro = false;
    1450           0 :       for (size_t inner = 1; inner < shnum; ++inner)
    1451             :         {
    1452           0 :           Elf_Scn *scn = elf_getscn (ebl->elf, inner);
    1453             :           /* This should not happen.  */
    1454           0 :           if (unlikely (scn == NULL))
    1455           0 :             error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
    1456             :                    elf_errmsg (-1));
    1457             : 
    1458             :           /* Get the section header.  */
    1459           0 :           GElf_Shdr shdr_mem;
    1460           0 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1461           0 :           if (unlikely (shdr == NULL))
    1462           0 :             error (EXIT_FAILURE, 0,
    1463           0 :                    gettext ("cannot get section header: %s"),
    1464             :                    elf_errmsg (-1));
    1465             : 
    1466           0 :           if (shdr->sh_size > 0
    1467             :               /* Compare allocated sections by VMA, unallocated
    1468             :                  sections by file offset.  */
    1469           0 :               && (shdr->sh_flags & SHF_ALLOC
    1470           0 :                   ? (shdr->sh_addr >= phdr->p_vaddr
    1471           0 :                      && (shdr->sh_addr + shdr->sh_size
    1472           0 :                          <= phdr->p_vaddr + phdr->p_memsz))
    1473           0 :                   : (shdr->sh_offset >= phdr->p_offset
    1474           0 :                      && (shdr->sh_offset + shdr->sh_size
    1475           0 :                          <= phdr->p_offset + phdr->p_filesz))))
    1476             :             {
    1477           0 :               if (has_relro && !in_relro
    1478           0 :                   && shdr->sh_addr >= relro_from
    1479           0 :                   && shdr->sh_addr + shdr->sh_size <= relro_to)
    1480             :                 {
    1481           0 :                   fputs_unlocked (" [RELRO:", stdout);
    1482           0 :                   in_relro = true;
    1483             :                 }
    1484           0 :               else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
    1485             :                 {
    1486           0 :                   fputs_unlocked ("]", stdout);
    1487           0 :                   in_relro =  false;
    1488             :                 }
    1489           0 :               else if (has_relro && in_relro
    1490           0 :                        && shdr->sh_addr + shdr->sh_size > relro_to)
    1491           0 :                 fputs_unlocked ("] <RELRO:", stdout);
    1492           0 :               else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
    1493             :                 {
    1494           0 :                   if (!in_ro)
    1495             :                     {
    1496           0 :                       fputs_unlocked (" [RO:", stdout);
    1497           0 :                       in_ro = true;
    1498             :                     }
    1499             :                 }
    1500             :               else
    1501             :                 {
    1502             :                   /* Determine the segment this section is part of.  */
    1503             :                   size_t cnt2;
    1504             :                   GElf_Phdr phdr2_mem;
    1505             :                   GElf_Phdr *phdr2 = NULL;
    1506           0 :                   for (cnt2 = 0; cnt2 < phnum; ++cnt2)
    1507             :                     {
    1508           0 :                       phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
    1509             : 
    1510           0 :                       if (phdr2 != NULL && phdr2->p_type == PT_LOAD
    1511           0 :                           && shdr->sh_addr >= phdr2->p_vaddr
    1512           0 :                           && (shdr->sh_addr + shdr->sh_size
    1513           0 :                               <= phdr2->p_vaddr + phdr2->p_memsz))
    1514             :                         break;
    1515             :                     }
    1516             : 
    1517           0 :                   if (cnt2 < phnum)
    1518             :                     {
    1519           0 :                       if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
    1520             :                         {
    1521           0 :                           fputs_unlocked (" [RO:", stdout);
    1522           0 :                           in_ro = true;
    1523             :                         }
    1524           0 :                       else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
    1525             :                         {
    1526           0 :                           fputs_unlocked ("]", stdout);
    1527           0 :                           in_ro = false;
    1528             :                         }
    1529             :                     }
    1530             :                 }
    1531             : 
    1532           0 :               printf (" %s",
    1533           0 :                       elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
    1534             : 
    1535             :               /* Signal that this sectin is only partially covered.  */
    1536           0 :               if (has_relro && in_relro
    1537           0 :                        && shdr->sh_addr + shdr->sh_size > relro_to)
    1538             :                 {
    1539           0 :                   fputs_unlocked (">", stdout);
    1540           0 :                   in_relro =  false;
    1541             :                 }
    1542             :             }
    1543             :         }
    1544           0 :       if (in_relro || in_ro)
    1545           0 :         fputs_unlocked ("]", stdout);
    1546             : 
    1547             :       /* Finish the line.  */
    1548           0 :       fputc_unlocked ('\n', stdout);
    1549             :     }
    1550             : }
    1551             : 
    1552             : 
    1553             : static const char *
    1554           0 : section_name (Ebl *ebl, GElf_Shdr *shdr)
    1555             : {
    1556           0 :   size_t shstrndx;
    1557           0 :   if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
    1558           0 :     return "???";
    1559           0 :   return elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "???";
    1560             : }
    1561             : 
    1562             : 
    1563             : static void
    1564           0 : handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
    1565             : {
    1566             :   /* Get the data of the section.  */
    1567           0 :   Elf_Data *data = elf_getdata (scn, NULL);
    1568             : 
    1569           0 :   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
    1570           0 :   GElf_Shdr symshdr_mem;
    1571           0 :   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
    1572           0 :   Elf_Data *symdata = elf_getdata (symscn, NULL);
    1573             : 
    1574           0 :   if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
    1575           0 :       || symdata == NULL)
    1576           0 :     return;
    1577             : 
    1578             :   /* Get the section header string table index.  */
    1579           0 :   size_t shstrndx;
    1580           0 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    1581           0 :     error (EXIT_FAILURE, 0,
    1582           0 :            gettext ("cannot get section header string table index"));
    1583             : 
    1584           0 :   Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
    1585             : 
    1586           0 :   GElf_Sym sym_mem;
    1587           0 :   GElf_Sym *sym = gelf_getsym (symdata, shdr->sh_info, &sym_mem);
    1588             : 
    1589           0 :   printf ((grpref[0] & GRP_COMDAT)
    1590           0 :           ? ngettext ("\
    1591             : \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
    1592             :                       "\
    1593             : \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
    1594             :                       data->d_size / sizeof (Elf32_Word) - 1)
    1595           0 :           : ngettext ("\
    1596             : \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
    1597             : \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
    1598             :                       data->d_size / sizeof (Elf32_Word) - 1),
    1599             :           elf_ndxscn (scn),
    1600           0 :           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    1601             :           (sym == NULL ? NULL
    1602           0 :            : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
    1603           0 :           ?: gettext ("<INVALID SYMBOL>"),
    1604           0 :           data->d_size / sizeof (Elf32_Word) - 1);
    1605             : 
    1606           0 :   for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
    1607             :     {
    1608           0 :       GElf_Shdr grpshdr_mem;
    1609           0 :       GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
    1610             :                                          &grpshdr_mem);
    1611             : 
    1612           0 :       const char *str;
    1613           0 :       printf ("  [%2u] %s\n",
    1614             :               grpref[cnt],
    1615             :               grpshdr != NULL
    1616           0 :               && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
    1617           0 :               ? str : gettext ("<INVALID SECTION>"));
    1618             :     }
    1619             : }
    1620             : 
    1621             : 
    1622             : static void
    1623          51 : print_scngrp (Ebl *ebl)
    1624             : {
    1625             :   /* Find all relocation sections and handle them.  */
    1626          51 :   Elf_Scn *scn = NULL;
    1627             : 
    1628        1332 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    1629             :     {
    1630             :        /* Handle the section if it is a symbol table.  */
    1631        1281 :       GElf_Shdr shdr_mem;
    1632        1281 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1633             : 
    1634        1281 :       if (shdr != NULL && shdr->sh_type == SHT_GROUP)
    1635             :         {
    1636          16 :           if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
    1637             :             {
    1638           0 :               if (elf_compress (scn, 0, 0) < 0)
    1639           0 :                 printf ("WARNING: %s [%zd]\n",
    1640             :                         gettext ("Couldn't uncompress section"),
    1641             :                         elf_ndxscn (scn));
    1642           0 :               shdr = gelf_getshdr (scn, &shdr_mem);
    1643           0 :               if (unlikely (shdr == NULL))
    1644           0 :                 error (EXIT_FAILURE, 0,
    1645           0 :                        gettext ("cannot get section [%zd] header: %s"),
    1646             :                        elf_ndxscn (scn),
    1647             :                        elf_errmsg (-1));
    1648             :             }
    1649          16 :           handle_scngrp (ebl, scn, shdr);
    1650             :         }
    1651             :     }
    1652          51 : }
    1653             : 
    1654             : 
    1655             : static const struct flags
    1656             : {
    1657             :   int mask;
    1658             :   const char *str;
    1659             : } dt_flags[] =
    1660             :   {
    1661             :     { DF_ORIGIN, "ORIGIN" },
    1662             :     { DF_SYMBOLIC, "SYMBOLIC" },
    1663             :     { DF_TEXTREL, "TEXTREL" },
    1664             :     { DF_BIND_NOW, "BIND_NOW" },
    1665             :     { DF_STATIC_TLS, "STATIC_TLS" }
    1666             :   };
    1667             : static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
    1668             : 
    1669             : static const struct flags dt_flags_1[] =
    1670             :   {
    1671             :     { DF_1_NOW, "NOW" },
    1672             :     { DF_1_GLOBAL, "GLOBAL" },
    1673             :     { DF_1_GROUP, "GROUP" },
    1674             :     { DF_1_NODELETE, "NODELETE" },
    1675             :     { DF_1_LOADFLTR, "LOADFLTR" },
    1676             :     { DF_1_INITFIRST, "INITFIRST" },
    1677             :     { DF_1_NOOPEN, "NOOPEN" },
    1678             :     { DF_1_ORIGIN, "ORIGIN" },
    1679             :     { DF_1_DIRECT, "DIRECT" },
    1680             :     { DF_1_TRANS, "TRANS" },
    1681             :     { DF_1_INTERPOSE, "INTERPOSE" },
    1682             :     { DF_1_NODEFLIB, "NODEFLIB" },
    1683             :     { DF_1_NODUMP, "NODUMP" },
    1684             :     { DF_1_CONFALT, "CONFALT" },
    1685             :     { DF_1_ENDFILTEE, "ENDFILTEE" },
    1686             :     { DF_1_DISPRELDNE, "DISPRELDNE" },
    1687             :     { DF_1_DISPRELPND, "DISPRELPND" },
    1688             :   };
    1689             : static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
    1690             : 
    1691             : static const struct flags dt_feature_1[] =
    1692             :   {
    1693             :     { DTF_1_PARINIT, "PARINIT" },
    1694             :     { DTF_1_CONFEXP, "CONFEXP" }
    1695             :   };
    1696             : static const int ndt_feature_1 = (sizeof (dt_feature_1)
    1697             :                                   / sizeof (dt_feature_1[0]));
    1698             : 
    1699             : static const struct flags dt_posflag_1[] =
    1700             :   {
    1701             :     { DF_P1_LAZYLOAD, "LAZYLOAD" },
    1702             :     { DF_P1_GROUPPERM, "GROUPPERM" }
    1703             :   };
    1704             : static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
    1705             :                                   / sizeof (dt_posflag_1[0]));
    1706             : 
    1707             : 
    1708             : static void
    1709          10 : print_flags (int class, GElf_Xword d_val, const struct flags *flags,
    1710             :                 int nflags)
    1711             : {
    1712          10 :   bool first = true;
    1713          10 :   int cnt;
    1714             : 
    1715         138 :   for (cnt = 0; cnt < nflags; ++cnt)
    1716         128 :     if (d_val & flags[cnt].mask)
    1717             :       {
    1718          22 :         if (!first)
    1719          18 :           putchar_unlocked (' ');
    1720          22 :         fputs_unlocked (flags[cnt].str, stdout);
    1721          22 :         d_val &= ~flags[cnt].mask;
    1722          22 :         first = false;
    1723             :       }
    1724             : 
    1725          10 :   if (d_val != 0)
    1726             :     {
    1727          10 :       if (!first)
    1728           4 :         putchar_unlocked (' ');
    1729          16 :       printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
    1730             :     }
    1731             : 
    1732          10 :   putchar_unlocked ('\n');
    1733          10 : }
    1734             : 
    1735             : 
    1736             : static void
    1737             : print_dt_flags (int class, GElf_Xword d_val)
    1738             : {
    1739           1 :   print_flags (class, d_val, dt_flags, ndt_flags);
    1740             : }
    1741             : 
    1742             : 
    1743             : static void
    1744             : print_dt_flags_1 (int class, GElf_Xword d_val)
    1745             : {
    1746           7 :   print_flags (class, d_val, dt_flags_1, ndt_flags_1);
    1747             : }
    1748             : 
    1749             : 
    1750             : static void
    1751             : print_dt_feature_1 (int class, GElf_Xword d_val)
    1752             : {
    1753           1 :   print_flags (class, d_val, dt_feature_1, ndt_feature_1);
    1754             : }
    1755             : 
    1756             : 
    1757             : static void
    1758             : print_dt_posflag_1 (int class, GElf_Xword d_val)
    1759             : {
    1760           1 :   print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
    1761             : }
    1762             : 
    1763             : 
    1764             : static void
    1765          12 : handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
    1766             : {
    1767          12 :   int class = gelf_getclass (ebl->elf);
    1768          12 :   GElf_Shdr glink_mem;
    1769          12 :   GElf_Shdr *glink;
    1770          12 :   Elf_Data *data;
    1771          12 :   size_t cnt;
    1772          12 :   size_t shstrndx;
    1773          12 :   size_t sh_entsize;
    1774             : 
    1775             :   /* Get the data of the section.  */
    1776          12 :   data = elf_getdata (scn, NULL);
    1777          12 :   if (data == NULL)
    1778           0 :     return;
    1779             : 
    1780             :   /* Get the section header string table index.  */
    1781          12 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    1782           0 :     error (EXIT_FAILURE, 0,
    1783           0 :            gettext ("cannot get section header string table index"));
    1784             : 
    1785          12 :   sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT);
    1786             : 
    1787          12 :   glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
    1788          12 :   if (glink == NULL)
    1789           0 :     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
    1790             :            elf_ndxscn (scn));
    1791             : 
    1792          12 :   printf (ngettext ("\
    1793             : \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
    1794             :                     "\
    1795             : \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
    1796             :                     shdr->sh_size / sh_entsize),
    1797          12 :           (unsigned long int) (shdr->sh_size / sh_entsize),
    1798             :           class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
    1799             :           shdr->sh_offset,
    1800          12 :           (int) shdr->sh_link,
    1801          12 :           elf_strptr (ebl->elf, shstrndx, glink->sh_name));
    1802          12 :   fputs_unlocked (gettext ("  Type              Value\n"), stdout);
    1803             : 
    1804         448 :   for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
    1805             :     {
    1806         436 :       GElf_Dyn dynmem;
    1807         436 :       GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
    1808         436 :       if (dyn == NULL)
    1809             :         break;
    1810             : 
    1811         436 :       char buf[64];
    1812         436 :       printf ("  %-17s ",
    1813             :               ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
    1814             : 
    1815         436 :       switch (dyn->d_tag)
    1816             :         {
    1817          66 :         case DT_NULL:
    1818             :         case DT_DEBUG:
    1819             :         case DT_BIND_NOW:
    1820             :         case DT_TEXTREL:
    1821             :           /* No further output.  */
    1822          66 :           fputc_unlocked ('\n', stdout);
    1823             :           break;
    1824             : 
    1825          52 :         case DT_NEEDED:
    1826          52 :           printf (gettext ("Shared library: [%s]\n"),
    1827          52 :                   elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
    1828             :           break;
    1829             : 
    1830           3 :         case DT_SONAME:
    1831           3 :           printf (gettext ("Library soname: [%s]\n"),
    1832           3 :                   elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
    1833             :           break;
    1834             : 
    1835           1 :         case DT_RPATH:
    1836           1 :           printf (gettext ("Library rpath: [%s]\n"),
    1837           1 :                   elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
    1838             :           break;
    1839             : 
    1840           2 :         case DT_RUNPATH:
    1841           2 :           printf (gettext ("Library runpath: [%s]\n"),
    1842           2 :                   elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
    1843             :           break;
    1844             : 
    1845          91 :         case DT_PLTRELSZ:
    1846             :         case DT_RELASZ:
    1847             :         case DT_STRSZ:
    1848             :         case DT_RELSZ:
    1849             :         case DT_RELAENT:
    1850             :         case DT_SYMENT:
    1851             :         case DT_RELENT:
    1852             :         case DT_PLTPADSZ:
    1853             :         case DT_MOVEENT:
    1854             :         case DT_MOVESZ:
    1855             :         case DT_INIT_ARRAYSZ:
    1856             :         case DT_FINI_ARRAYSZ:
    1857             :         case DT_SYMINSZ:
    1858             :         case DT_SYMINENT:
    1859             :         case DT_GNU_CONFLICTSZ:
    1860             :         case DT_GNU_LIBLISTSZ:
    1861          91 :           printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
    1862             :           break;
    1863             : 
    1864          31 :         case DT_VERDEFNUM:
    1865             :         case DT_VERNEEDNUM:
    1866             :         case DT_RELACOUNT:
    1867             :         case DT_RELCOUNT:
    1868          31 :           printf ("%" PRId64 "\n", dyn->d_un.d_val);
    1869             :           break;
    1870             : 
    1871          12 :         case DT_PLTREL:;
    1872          12 :           const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
    1873             :                                                       NULL, 0);
    1874          12 :           puts (tagname ?: "???");
    1875          12 :           break;
    1876             : 
    1877           1 :         case DT_FLAGS:
    1878           1 :           print_dt_flags (class, dyn->d_un.d_val);
    1879             :           break;
    1880             : 
    1881           7 :         case DT_FLAGS_1:
    1882           7 :           print_dt_flags_1 (class, dyn->d_un.d_val);
    1883             :           break;
    1884             : 
    1885           1 :         case DT_FEATURE_1:
    1886           1 :           print_dt_feature_1 (class, dyn->d_un.d_val);
    1887             :           break;
    1888             : 
    1889           1 :         case DT_POSFLAG_1:
    1890           1 :           print_dt_posflag_1 (class, dyn->d_un.d_val);
    1891             :           break;
    1892             : 
    1893         168 :         default:
    1894         168 :           printf ("%#0*" PRIx64 "\n",
    1895             :                   class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
    1896             :           break;
    1897             :         }
    1898             :     }
    1899             : }
    1900             : 
    1901             : 
    1902             : /* Print the dynamic segment.  */
    1903             : static void
    1904          44 : print_dynamic (Ebl *ebl)
    1905             : {
    1906         100 :   for (size_t i = 0; i < phnum; ++i)
    1907             :     {
    1908          68 :       GElf_Phdr phdr_mem;
    1909          68 :       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
    1910             : 
    1911          68 :       if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
    1912             :         {
    1913          12 :           Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
    1914          12 :           GElf_Shdr shdr_mem;
    1915          12 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1916          12 :           if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
    1917          12 :             handle_dynamic (ebl, scn, shdr);
    1918          12 :           break;
    1919             :         }
    1920             :     }
    1921          44 : }
    1922             : 
    1923             : 
    1924             : /* Print relocations.  */
    1925             : static void
    1926          43 : print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
    1927             : {
    1928             :   /* Find all relocation sections and handle them.  */
    1929          43 :   Elf_Scn *scn = NULL;
    1930             : 
    1931        1108 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    1932             :     {
    1933             :        /* Handle the section if it is a symbol table.  */
    1934        1065 :       GElf_Shdr shdr_mem;
    1935        1065 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1936             : 
    1937        1065 :       if (likely (shdr != NULL))
    1938             :         {
    1939        1065 :           if (shdr->sh_type == SHT_REL)
    1940          22 :             handle_relocs_rel (ebl, ehdr, scn, shdr);
    1941        1043 :           else if (shdr->sh_type == SHT_RELA)
    1942         172 :             handle_relocs_rela (ebl, ehdr, scn, shdr);
    1943             :         }
    1944             :     }
    1945          43 : }
    1946             : 
    1947             : 
    1948             : /* Handle a relocation section.  */
    1949             : static void
    1950           0 : handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
    1951             : {
    1952           0 :   int class = gelf_getclass (ebl->elf);
    1953           0 :   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
    1954           0 :   int nentries = shdr->sh_size / sh_entsize;
    1955             : 
    1956             :   /* Get the data of the section.  */
    1957           0 :   Elf_Data *data = elf_getdata (scn, NULL);
    1958           0 :   if (data == NULL)
    1959           0 :     return;
    1960             : 
    1961             :   /* Get the symbol table information.  */
    1962           0 :   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
    1963           0 :   GElf_Shdr symshdr_mem;
    1964           0 :   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
    1965           0 :   Elf_Data *symdata = elf_getdata (symscn, NULL);
    1966             : 
    1967             :   /* Get the section header of the section the relocations are for.  */
    1968           0 :   GElf_Shdr destshdr_mem;
    1969           0 :   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
    1970             :                                       &destshdr_mem);
    1971             : 
    1972           0 :   if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
    1973             :     {
    1974           0 :       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
    1975             :               shdr->sh_offset);
    1976           0 :       return;
    1977             :     }
    1978             : 
    1979             :   /* Search for the optional extended section index table.  */
    1980           0 :   Elf_Data *xndxdata = NULL;
    1981           0 :   int xndxscnidx = elf_scnshndx (scn);
    1982           0 :   if (unlikely (xndxscnidx > 0))
    1983           0 :     xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
    1984             : 
    1985             :   /* Get the section header string table index.  */
    1986           0 :   size_t shstrndx;
    1987           0 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    1988           0 :     error (EXIT_FAILURE, 0,
    1989           0 :            gettext ("cannot get section header string table index"));
    1990             : 
    1991           0 :   if (shdr->sh_info != 0)
    1992           0 :     printf (ngettext ("\
    1993             : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
    1994             :                     "\
    1995             : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
    1996             :                       nentries),
    1997             :             elf_ndxscn (scn),
    1998           0 :             elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    1999           0 :             (unsigned int) shdr->sh_info,
    2000           0 :             elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
    2001             :             shdr->sh_offset,
    2002             :             nentries);
    2003             :   else
    2004             :     /* The .rel.dyn section does not refer to a specific section but
    2005             :        instead of section index zero.  Do not try to print a section
    2006             :        name.  */
    2007           0 :     printf (ngettext ("\
    2008             : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
    2009             :                     "\
    2010             : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
    2011             :                       nentries),
    2012           0 :             (unsigned int) elf_ndxscn (scn),
    2013           0 :             elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    2014             :             shdr->sh_offset,
    2015             :             nentries);
    2016           0 :   fputs_unlocked (class == ELFCLASS32
    2017           0 :                   ? gettext ("\
    2018             :   Offset      Type                 Value       Name\n")
    2019           0 :                   : gettext ("\
    2020             :   Offset              Type                 Value               Name\n"),
    2021             :          stdout);
    2022             : 
    2023           0 :   int is_statically_linked = 0;
    2024           0 :   for (int cnt = 0; cnt < nentries; ++cnt)
    2025             :     {
    2026           0 :       GElf_Rel relmem;
    2027           0 :       GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
    2028           0 :       if (likely (rel != NULL))
    2029             :         {
    2030           0 :           char buf[128];
    2031           0 :           GElf_Sym symmem;
    2032           0 :           Elf32_Word xndx;
    2033           0 :           GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
    2034           0 :                                             GELF_R_SYM (rel->r_info),
    2035             :                                             &symmem, &xndx);
    2036           0 :           if (unlikely (sym == NULL))
    2037             :             {
    2038             :               /* As a special case we have to handle relocations in static
    2039             :                  executables.  This only happens for IRELATIVE relocations
    2040             :                  (so far).  There is no symbol table.  */
    2041           0 :               if (is_statically_linked == 0)
    2042             :                 {
    2043             :                   /* Find the program header and look for a PT_INTERP entry. */
    2044           0 :                   is_statically_linked = -1;
    2045           0 :                   if (ehdr->e_type == ET_EXEC)
    2046             :                     {
    2047             :                       is_statically_linked = 1;
    2048             : 
    2049           0 :                       for (size_t inner = 0; inner < phnum; ++inner)
    2050             :                         {
    2051           0 :                           GElf_Phdr phdr_mem;
    2052           0 :                           GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
    2053             :                                                           &phdr_mem);
    2054           0 :                           if (phdr != NULL && phdr->p_type == PT_INTERP)
    2055             :                             {
    2056           0 :                               is_statically_linked = -1;
    2057           0 :                               break;
    2058             :                             }
    2059             :                         }
    2060             :                     }
    2061             :                 }
    2062             : 
    2063           0 :               if (is_statically_linked > 0 && shdr->sh_link == 0)
    2064           0 :                 printf ("\
    2065             :   %#0*" PRIx64 "  %-20s %*s  %s\n",
    2066             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2067           0 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2068             :                         /* Avoid the leading R_ which isn't carrying any
    2069             :                            information.  */
    2070           0 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2071             :                                                buf, sizeof (buf)) + 2
    2072           0 :                         : gettext ("<INVALID RELOC>"),
    2073             :                         class == ELFCLASS32 ? 10 : 18, "",
    2074           0 :                         elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
    2075             :               else
    2076           0 :                 printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
    2077             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2078           0 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2079             :                         /* Avoid the leading R_ which isn't carrying any
    2080             :                            information.  */
    2081           0 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2082             :                                                buf, sizeof (buf)) + 2
    2083           0 :                         : gettext ("<INVALID RELOC>"),
    2084             :                         gettext ("INVALID SYMBOL"),
    2085           0 :                         (long int) GELF_R_SYM (rel->r_info));
    2086             :             }
    2087           0 :           else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
    2088           0 :             printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
    2089             :                     class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2090           0 :                     likely (ebl_reloc_type_check (ebl,
    2091             :                                                   GELF_R_TYPE (rel->r_info)))
    2092             :                     /* Avoid the leading R_ which isn't carrying any
    2093             :                        information.  */
    2094           0 :                     ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2095             :                                            buf, sizeof (buf)) + 2
    2096           0 :                     : gettext ("<INVALID RELOC>"),
    2097             :                     class == ELFCLASS32 ? 10 : 18, sym->st_value,
    2098           0 :                     elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
    2099             :           else
    2100             :             {
    2101             :               /* This is a relocation against a STT_SECTION symbol.  */
    2102           0 :               GElf_Shdr secshdr_mem;
    2103           0 :               GElf_Shdr *secshdr;
    2104           0 :               secshdr = gelf_getshdr (elf_getscn (ebl->elf,
    2105           0 :                                                   sym->st_shndx == SHN_XINDEX
    2106           0 :                                                   ? xndx : sym->st_shndx),
    2107             :                                       &secshdr_mem);
    2108             : 
    2109           0 :               if (unlikely (secshdr == NULL))
    2110           0 :                 printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
    2111             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2112           0 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2113             :                         /* Avoid the leading R_ which isn't carrying any
    2114             :                            information.  */
    2115           0 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2116             :                                                buf, sizeof (buf)) + 2
    2117           0 :                         : gettext ("<INVALID RELOC>"),
    2118             :                         gettext ("INVALID SECTION"),
    2119           0 :                         (long int) (sym->st_shndx == SHN_XINDEX
    2120           0 :                                     ? xndx : sym->st_shndx));
    2121             :               else
    2122           0 :                 printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
    2123             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2124           0 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2125             :                         /* Avoid the leading R_ which isn't carrying any
    2126             :                            information.  */
    2127           0 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2128             :                                                buf, sizeof (buf)) + 2
    2129           0 :                         : gettext ("<INVALID RELOC>"),
    2130             :                         class == ELFCLASS32 ? 10 : 18, sym->st_value,
    2131           0 :                         elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
    2132             :             }
    2133             :         }
    2134             :     }
    2135             : }
    2136             : 
    2137             : 
    2138             : /* Handle a relocation section.  */
    2139             : static void
    2140           0 : handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
    2141             : {
    2142           0 :   int class = gelf_getclass (ebl->elf);
    2143           0 :   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
    2144           0 :   int nentries = shdr->sh_size / sh_entsize;
    2145             : 
    2146             :   /* Get the data of the section.  */
    2147           0 :   Elf_Data *data = elf_getdata (scn, NULL);
    2148           0 :   if (data == NULL)
    2149           0 :     return;
    2150             : 
    2151             :   /* Get the symbol table information.  */
    2152           0 :   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
    2153           0 :   GElf_Shdr symshdr_mem;
    2154           0 :   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
    2155           0 :   Elf_Data *symdata = elf_getdata (symscn, NULL);
    2156             : 
    2157             :   /* Get the section header of the section the relocations are for.  */
    2158           0 :   GElf_Shdr destshdr_mem;
    2159           0 :   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
    2160             :                                       &destshdr_mem);
    2161             : 
    2162           0 :   if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
    2163             :     {
    2164           0 :       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
    2165             :               shdr->sh_offset);
    2166           0 :       return;
    2167             :     }
    2168             : 
    2169             :   /* Search for the optional extended section index table.  */
    2170           0 :   Elf_Data *xndxdata = NULL;
    2171           0 :   int xndxscnidx = elf_scnshndx (scn);
    2172           0 :   if (unlikely (xndxscnidx > 0))
    2173           0 :     xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
    2174             : 
    2175             :   /* Get the section header string table index.  */
    2176           0 :   size_t shstrndx;
    2177           0 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    2178           0 :     error (EXIT_FAILURE, 0,
    2179           0 :            gettext ("cannot get section header string table index"));
    2180             : 
    2181           0 :   if (shdr->sh_info != 0)
    2182           0 :     printf (ngettext ("\
    2183             : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
    2184             :                     "\
    2185             : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
    2186             :                     nentries),
    2187             :           elf_ndxscn (scn),
    2188           0 :           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    2189           0 :           (unsigned int) shdr->sh_info,
    2190           0 :           elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
    2191             :           shdr->sh_offset,
    2192             :           nentries);
    2193             :   else
    2194             :     /* The .rela.dyn section does not refer to a specific section but
    2195             :        instead of section index zero.  Do not try to print a section
    2196             :        name.  */
    2197           0 :     printf (ngettext ("\
    2198             : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
    2199             :                     "\
    2200             : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
    2201             :                       nentries),
    2202           0 :             (unsigned int) elf_ndxscn (scn),
    2203           0 :             elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    2204             :             shdr->sh_offset,
    2205             :             nentries);
    2206           0 :   fputs_unlocked (class == ELFCLASS32
    2207           0 :                   ? gettext ("\
    2208             :   Offset      Type            Value       Addend Name\n")
    2209           0 :                   : gettext ("\
    2210             :   Offset              Type            Value               Addend Name\n"),
    2211             :                   stdout);
    2212             : 
    2213           0 :   int is_statically_linked = 0;
    2214           0 :   for (int cnt = 0; cnt < nentries; ++cnt)
    2215             :     {
    2216           0 :       GElf_Rela relmem;
    2217           0 :       GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
    2218           0 :       if (likely (rel != NULL))
    2219             :         {
    2220           0 :           char buf[64];
    2221           0 :           GElf_Sym symmem;
    2222           0 :           Elf32_Word xndx;
    2223           0 :           GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
    2224           0 :                                             GELF_R_SYM (rel->r_info),
    2225             :                                             &symmem, &xndx);
    2226             : 
    2227           0 :           if (unlikely (sym == NULL))
    2228             :             {
    2229             :               /* As a special case we have to handle relocations in static
    2230             :                  executables.  This only happens for IRELATIVE relocations
    2231             :                  (so far).  There is no symbol table.  */
    2232           0 :               if (is_statically_linked == 0)
    2233             :                 {
    2234             :                   /* Find the program header and look for a PT_INTERP entry. */
    2235           0 :                   is_statically_linked = -1;
    2236           0 :                   if (ehdr->e_type == ET_EXEC)
    2237             :                     {
    2238             :                       is_statically_linked = 1;
    2239             : 
    2240           0 :                       for (size_t inner = 0; inner < phnum; ++inner)
    2241             :                         {
    2242           0 :                           GElf_Phdr phdr_mem;
    2243           0 :                           GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
    2244             :                                                           &phdr_mem);
    2245           0 :                           if (phdr != NULL && phdr->p_type == PT_INTERP)
    2246             :                             {
    2247           0 :                               is_statically_linked = -1;
    2248           0 :                               break;
    2249             :                             }
    2250             :                         }
    2251             :                     }
    2252             :                 }
    2253             : 
    2254           0 :               if (is_statically_linked > 0 && shdr->sh_link == 0)
    2255           0 :                 printf ("\
    2256             :   %#0*" PRIx64 "  %-15s %*s  %#6" PRIx64 " %s\n",
    2257             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2258           0 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2259             :                         /* Avoid the leading R_ which isn't carrying any
    2260             :                            information.  */
    2261           0 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2262             :                                                buf, sizeof (buf)) + 2
    2263           0 :                         : gettext ("<INVALID RELOC>"),
    2264             :                         class == ELFCLASS32 ? 10 : 18, "",
    2265             :                         rel->r_addend,
    2266           0 :                         elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
    2267             :               else
    2268           0 :                 printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
    2269             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2270           0 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2271             :                         /* Avoid the leading R_ which isn't carrying any
    2272             :                            information.  */
    2273           0 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2274             :                                                buf, sizeof (buf)) + 2
    2275           0 :                         : gettext ("<INVALID RELOC>"),
    2276             :                         gettext ("INVALID SYMBOL"),
    2277           0 :                         (long int) GELF_R_SYM (rel->r_info));
    2278             :             }
    2279           0 :           else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
    2280           0 :             printf ("\
    2281             :   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
    2282             :                     class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2283           0 :                     likely (ebl_reloc_type_check (ebl,
    2284             :                                                   GELF_R_TYPE (rel->r_info)))
    2285             :                     /* Avoid the leading R_ which isn't carrying any
    2286             :                        information.  */
    2287           0 :                     ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2288             :                                            buf, sizeof (buf)) + 2
    2289           0 :                     : gettext ("<INVALID RELOC>"),
    2290             :                     class == ELFCLASS32 ? 10 : 18, sym->st_value,
    2291             :                     rel->r_addend,
    2292           0 :                     elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
    2293             :           else
    2294             :             {
    2295             :               /* This is a relocation against a STT_SECTION symbol.  */
    2296           0 :               GElf_Shdr secshdr_mem;
    2297           0 :               GElf_Shdr *secshdr;
    2298           0 :               secshdr = gelf_getshdr (elf_getscn (ebl->elf,
    2299           0 :                                                   sym->st_shndx == SHN_XINDEX
    2300           0 :                                                   ? xndx : sym->st_shndx),
    2301             :                                       &secshdr_mem);
    2302             : 
    2303           0 :               if (unlikely (secshdr == NULL))
    2304           0 :                 printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
    2305             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2306           0 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2307             :                         /* Avoid the leading R_ which isn't carrying any
    2308             :                            information.  */
    2309           0 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2310             :                                                buf, sizeof (buf)) + 2
    2311           0 :                         : gettext ("<INVALID RELOC>"),
    2312             :                         gettext ("INVALID SECTION"),
    2313           0 :                         (long int) (sym->st_shndx == SHN_XINDEX
    2314           0 :                                     ? xndx : sym->st_shndx));
    2315             :               else
    2316           0 :                 printf ("\
    2317             :   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
    2318             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2319           0 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2320             :                         /* Avoid the leading R_ which isn't carrying any
    2321             :                            information.  */
    2322           0 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2323             :                                                buf, sizeof (buf)) + 2
    2324           0 :                         : gettext ("<INVALID RELOC>"),
    2325             :                         class == ELFCLASS32 ? 10 : 18, sym->st_value,
    2326             :                         rel->r_addend,
    2327           0 :                         elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
    2328             :             }
    2329             :         }
    2330             :     }
    2331             : }
    2332             : 
    2333             : 
    2334             : /* Print the program header.  */
    2335             : static void
    2336         112 : print_symtab (Ebl *ebl, int type)
    2337             : {
    2338             :   /* Find the symbol table(s).  For this we have to search through the
    2339             :      section table.  */
    2340         112 :   Elf_Scn *scn = NULL;
    2341             : 
    2342        2932 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    2343             :     {
    2344             :       /* Handle the section if it is a symbol table.  */
    2345        2820 :       GElf_Shdr shdr_mem;
    2346        2820 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    2347             : 
    2348        2820 :       if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
    2349             :         {
    2350          66 :           if (symbol_table_section != NULL)
    2351             :             {
    2352             :               /* Get the section header string table index.  */
    2353           4 :               size_t shstrndx;
    2354           4 :               const char *sname;
    2355           4 :               if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    2356           0 :                 error (EXIT_FAILURE, 0,
    2357           0 :                        gettext ("cannot get section header string table index"));
    2358           4 :               sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
    2359           4 :               if (sname == NULL || strcmp (sname, symbol_table_section) != 0)
    2360           2 :                 continue;
    2361             :             }
    2362             : 
    2363          64 :           if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
    2364             :             {
    2365           0 :               if (elf_compress (scn, 0, 0) < 0)
    2366           0 :                 printf ("WARNING: %s [%zd]\n",
    2367             :                         gettext ("Couldn't uncompress section"),
    2368             :                         elf_ndxscn (scn));
    2369           0 :               shdr = gelf_getshdr (scn, &shdr_mem);
    2370           0 :               if (unlikely (shdr == NULL))
    2371           0 :                 error (EXIT_FAILURE, 0,
    2372           0 :                        gettext ("cannot get section [%zd] header: %s"),
    2373             :                        elf_ndxscn (scn), elf_errmsg (-1));
    2374             :             }
    2375          64 :           handle_symtab (ebl, scn, shdr);
    2376             :         }
    2377             :     }
    2378         112 : }
    2379             : 
    2380             : 
    2381             : static void
    2382          64 : handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
    2383             : {
    2384          64 :   Elf_Data *versym_data = NULL;
    2385          64 :   Elf_Data *verneed_data = NULL;
    2386          64 :   Elf_Data *verdef_data = NULL;
    2387          64 :   Elf_Data *xndx_data = NULL;
    2388          64 :   int class = gelf_getclass (ebl->elf);
    2389          64 :   Elf32_Word verneed_stridx = 0;
    2390          64 :   Elf32_Word verdef_stridx = 0;
    2391             : 
    2392             :   /* Get the data of the section.  */
    2393          64 :   Elf_Data *data = elf_getdata (scn, NULL);
    2394          64 :   if (data == NULL)
    2395           0 :     return;
    2396             : 
    2397             :   /* Find out whether we have other sections we might need.  */
    2398             :   Elf_Scn *runscn = NULL;
    2399        1800 :   while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
    2400             :     {
    2401        1736 :       GElf_Shdr runshdr_mem;
    2402        1736 :       GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
    2403             : 
    2404        1736 :       if (likely (runshdr != NULL))
    2405             :         {
    2406        1736 :           if (runshdr->sh_type == SHT_GNU_versym
    2407          27 :               && runshdr->sh_link == elf_ndxscn (scn))
    2408             :             /* Bingo, found the version information.  Now get the data.  */
    2409          17 :             versym_data = elf_getdata (runscn, NULL);
    2410        1719 :           else if (runshdr->sh_type == SHT_GNU_verneed)
    2411             :             {
    2412             :               /* This is the information about the needed versions.  */
    2413          27 :               verneed_data = elf_getdata (runscn, NULL);
    2414          27 :               verneed_stridx = runshdr->sh_link;
    2415             :             }
    2416        1692 :           else if (runshdr->sh_type == SHT_GNU_verdef)
    2417             :             {
    2418             :               /* This is the information about the defined versions.  */
    2419           8 :               verdef_data = elf_getdata (runscn, NULL);
    2420           8 :               verdef_stridx = runshdr->sh_link;
    2421             :             }
    2422        1684 :           else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
    2423           0 :               && runshdr->sh_link == elf_ndxscn (scn))
    2424             :             /* Extended section index.  */
    2425           0 :             xndx_data = elf_getdata (runscn, NULL);
    2426             :         }
    2427             :     }
    2428             : 
    2429             :   /* Get the section header string table index.  */
    2430          64 :   size_t shstrndx;
    2431          64 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    2432           0 :     error (EXIT_FAILURE, 0,
    2433           0 :            gettext ("cannot get section header string table index"));
    2434             : 
    2435          64 :   GElf_Shdr glink_mem;
    2436          64 :   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
    2437             :                                    &glink_mem);
    2438          64 :   if (glink == NULL)
    2439           0 :     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
    2440             :            elf_ndxscn (scn));
    2441             : 
    2442             :   /* Now we can compute the number of entries in the section.  */
    2443         128 :   unsigned int nsyms = data->d_size / (class == ELFCLASS32
    2444             :                                        ? sizeof (Elf32_Sym)
    2445          64 :                                        : sizeof (Elf64_Sym));
    2446             : 
    2447          64 :   printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
    2448             :                     "\nSymbol table [%2u] '%s' contains %u entries:\n",
    2449             :                     nsyms),
    2450          64 :           (unsigned int) elf_ndxscn (scn),
    2451          64 :           elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
    2452          64 :   printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
    2453             :                     " %lu local symbols  String table: [%2u] '%s'\n",
    2454             :                     shdr->sh_info),
    2455          64 :           (unsigned long int) shdr->sh_info,
    2456          64 :           (unsigned int) shdr->sh_link,
    2457          64 :           elf_strptr (ebl->elf, shstrndx, glink->sh_name));
    2458             : 
    2459          64 :   fputs_unlocked (class == ELFCLASS32
    2460           8 :                   ? gettext ("\
    2461             :   Num:    Value   Size Type    Bind   Vis          Ndx Name\n")
    2462          56 :                   : gettext ("\
    2463             :   Num:            Value   Size Type    Bind   Vis          Ndx Name\n"),
    2464             :                   stdout);
    2465             : 
    2466       15035 :   for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
    2467             :     {
    2468       14971 :       char typebuf[64];
    2469       14971 :       char bindbuf[64];
    2470       14971 :       char scnbuf[64];
    2471       14971 :       Elf32_Word xndx;
    2472       14971 :       GElf_Sym sym_mem;
    2473       14971 :       GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
    2474             : 
    2475       14971 :       if (unlikely (sym == NULL))
    2476           0 :         continue;
    2477             : 
    2478             :       /* Determine the real section index.  */
    2479       14971 :       if (likely (sym->st_shndx != SHN_XINDEX))
    2480       14971 :         xndx = sym->st_shndx;
    2481             : 
    2482       29750 :       printf (gettext ("\
    2483             : %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
    2484             :               cnt,
    2485             :               class == ELFCLASS32 ? 8 : 16,
    2486             :               sym->st_value,
    2487             :               sym->st_size,
    2488       14971 :               ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
    2489             :                                     typebuf, sizeof (typebuf)),
    2490       14971 :               ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
    2491             :                                        bindbuf, sizeof (bindbuf)),
    2492       14971 :               get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
    2493       14971 :               ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
    2494             :                                 sizeof (scnbuf), NULL, shnum),
    2495       14971 :               elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
    2496             : 
    2497       14971 :       if (versym_data != NULL)
    2498             :         {
    2499             :           /* Get the version information.  */
    2500        1390 :           GElf_Versym versym_mem;
    2501        1390 :           GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
    2502             : 
    2503        1390 :           if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
    2504             :             {
    2505        1192 :               bool is_nobits = false;
    2506        1192 :               bool check_def = xndx != SHN_UNDEF;
    2507             : 
    2508        1192 :               if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
    2509             :                 {
    2510        1155 :                   GElf_Shdr symshdr_mem;
    2511        1155 :                   GElf_Shdr *symshdr =
    2512        1155 :                     gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
    2513             : 
    2514        1155 :                   is_nobits = (symshdr != NULL
    2515        1155 :                                && symshdr->sh_type == SHT_NOBITS);
    2516             :                 }
    2517             : 
    2518        1192 :               if (is_nobits || ! check_def)
    2519             :                 {
    2520             :                   /* We must test both.  */
    2521         813 :                   GElf_Vernaux vernaux_mem;
    2522         813 :                   GElf_Vernaux *vernaux = NULL;
    2523         813 :                   size_t vn_offset = 0;
    2524             : 
    2525         813 :                   GElf_Verneed verneed_mem;
    2526         813 :                   GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
    2527             :                                                            &verneed_mem);
    2528        3244 :                   while (verneed != NULL)
    2529             :                     {
    2530        3244 :                       size_t vna_offset = vn_offset;
    2531             : 
    2532        6488 :                       vernaux = gelf_getvernaux (verneed_data,
    2533        3244 :                                                  vna_offset += verneed->vn_aux,
    2534             :                                                  &vernaux_mem);
    2535        6605 :                       while (vernaux != NULL
    2536        6605 :                              && vernaux->vna_other != *versym
    2537        5792 :                              && vernaux->vna_next != 0)
    2538             :                         {
    2539             :                           /* Update the offset.  */
    2540        3361 :                           vna_offset += vernaux->vna_next;
    2541             : 
    2542        6722 :                           vernaux = (vernaux->vna_next == 0
    2543             :                                      ? NULL
    2544        3361 :                                      : gelf_getvernaux (verneed_data,
    2545             :                                                         vna_offset,
    2546             :                                                         &vernaux_mem));
    2547             :                         }
    2548             : 
    2549             :                       /* Check whether we found the version.  */
    2550        3244 :                       if (vernaux != NULL && vernaux->vna_other == *versym)
    2551             :                         /* Found it.  */
    2552             :                         break;
    2553             : 
    2554        2431 :                       vn_offset += verneed->vn_next;
    2555        2431 :                       verneed = (verneed->vn_next == 0
    2556             :                                  ? NULL
    2557        2431 :                                  : gelf_getverneed (verneed_data, vn_offset,
    2558             :                                                     &verneed_mem));
    2559             :                     }
    2560             : 
    2561         813 :                   if (vernaux != NULL && vernaux->vna_other == *versym)
    2562             :                     {
    2563         813 :                       printf ("@%s (%u)",
    2564             :                               elf_strptr (ebl->elf, verneed_stridx,
    2565         813 :                                           vernaux->vna_name),
    2566             :                               (unsigned int) vernaux->vna_other);
    2567         813 :                       check_def = 0;
    2568             :                     }
    2569           0 :                   else if (unlikely (! is_nobits))
    2570           0 :                     error (0, 0, gettext ("bad dynamic symbol"));
    2571             :                   else
    2572             :                     check_def = 1;
    2573             :                 }
    2574             : 
    2575        1192 :               if (check_def && *versym != 0x8001)
    2576             :                 {
    2577             :                   /* We must test both.  */
    2578         379 :                   size_t vd_offset = 0;
    2579             : 
    2580         379 :                   GElf_Verdef verdef_mem;
    2581         379 :                   GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
    2582             :                                                         &verdef_mem);
    2583        2553 :                   while (verdef != NULL)
    2584             :                     {
    2585        2553 :                       if (verdef->vd_ndx == (*versym & 0x7fff))
    2586             :                         /* Found the definition.  */
    2587             :                         break;
    2588             : 
    2589        2174 :                       vd_offset += verdef->vd_next;
    2590        2174 :                       verdef = (verdef->vd_next == 0
    2591             :                                 ? NULL
    2592        2174 :                                 : gelf_getverdef (verdef_data, vd_offset,
    2593             :                                                   &verdef_mem));
    2594             :                     }
    2595             : 
    2596         379 :                   if (verdef != NULL)
    2597             :                     {
    2598         379 :                       GElf_Verdaux verdaux_mem;
    2599         379 :                       GElf_Verdaux *verdaux
    2600         758 :                         = gelf_getverdaux (verdef_data,
    2601         379 :                                            vd_offset + verdef->vd_aux,
    2602             :                                            &verdaux_mem);
    2603             : 
    2604         379 :                       if (verdaux != NULL)
    2605         745 :                         printf ((*versym & 0x8000) ? "@%s" : "@@%s",
    2606             :                                 elf_strptr (ebl->elf, verdef_stridx,
    2607         379 :                                             verdaux->vda_name));
    2608             :                     }
    2609             :                 }
    2610             :             }
    2611             :         }
    2612             : 
    2613       29942 :       putchar_unlocked ('\n');
    2614             :     }
    2615             : }
    2616             : 
    2617             : 
    2618             : /* Print version information.  */
    2619             : static void
    2620          42 : print_verinfo (Ebl *ebl)
    2621             : {
    2622             :   /* Find the version information sections.  For this we have to
    2623             :      search through the section table.  */
    2624          42 :   Elf_Scn *scn = NULL;
    2625             : 
    2626        1073 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    2627             :     {
    2628             :       /* Handle the section if it is part of the versioning handling.  */
    2629        1031 :       GElf_Shdr shdr_mem;
    2630        1031 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    2631             : 
    2632        1031 :       if (likely (shdr != NULL))
    2633             :         {
    2634        1031 :           if (shdr->sh_type == SHT_GNU_verneed)
    2635          10 :             handle_verneed (ebl, scn, shdr);
    2636        1021 :           else if (shdr->sh_type == SHT_GNU_verdef)
    2637           4 :             handle_verdef (ebl, scn, shdr);
    2638        1017 :           else if (shdr->sh_type == SHT_GNU_versym)
    2639          10 :             handle_versym (ebl, scn, shdr);
    2640             :         }
    2641             :     }
    2642          42 : }
    2643             : 
    2644             : 
    2645             : static const char *
    2646         123 : get_ver_flags (unsigned int flags)
    2647             : {
    2648         123 :   static char buf[32];
    2649         123 :   char *endp;
    2650             : 
    2651         123 :   if (flags == 0)
    2652         118 :     return gettext ("none");
    2653             : 
    2654           5 :   if (flags & VER_FLG_BASE)
    2655           8 :     endp = stpcpy (buf, "BASE ");
    2656             :   else
    2657             :     endp = buf;
    2658             : 
    2659           5 :   if (flags & VER_FLG_WEAK)
    2660             :     {
    2661           1 :       if (endp != buf)
    2662           0 :         endp = stpcpy (endp, "| ");
    2663             : 
    2664           2 :       endp = stpcpy (endp, "WEAK ");
    2665             :     }
    2666             : 
    2667           5 :   if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
    2668             :     {
    2669           0 :       strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
    2670           0 :       buf[sizeof (buf) - 1] = '\0';
    2671             :     }
    2672             : 
    2673             :   return buf;
    2674             : }
    2675             : 
    2676             : 
    2677             : static void
    2678           0 : handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
    2679             : {
    2680           0 :   int class = gelf_getclass (ebl->elf);
    2681             : 
    2682             :   /* Get the data of the section.  */
    2683           0 :   Elf_Data *data = elf_getdata (scn, NULL);
    2684           0 :   if (data == NULL)
    2685           0 :     return;
    2686             : 
    2687             :   /* Get the section header string table index.  */
    2688           0 :   size_t shstrndx;
    2689           0 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    2690           0 :     error (EXIT_FAILURE, 0,
    2691           0 :            gettext ("cannot get section header string table index"));
    2692             : 
    2693           0 :   GElf_Shdr glink_mem;
    2694           0 :   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
    2695             :                                    &glink_mem);
    2696           0 :   if (glink == NULL)
    2697           0 :     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
    2698             :            elf_ndxscn (scn));
    2699             : 
    2700           0 :   printf (ngettext ("\
    2701             : \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
    2702             :                     "\
    2703             : \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
    2704             :                     shdr->sh_info),
    2705           0 :           (unsigned int) elf_ndxscn (scn),
    2706           0 :           elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
    2707             :           class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
    2708             :           shdr->sh_offset,
    2709           0 :           (unsigned int) shdr->sh_link,
    2710           0 :           elf_strptr (ebl->elf, shstrndx, glink->sh_name));
    2711             : 
    2712           0 :   unsigned int offset = 0;
    2713           0 :   for (int cnt = shdr->sh_info; --cnt >= 0; )
    2714             :     {
    2715             :       /* Get the data at the next offset.  */
    2716           0 :       GElf_Verneed needmem;
    2717           0 :       GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
    2718           0 :       if (unlikely (need == NULL))
    2719             :         break;
    2720             : 
    2721           0 :       printf (gettext ("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
    2722           0 :               offset, (unsigned short int) need->vn_version,
    2723           0 :               elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
    2724           0 :               (unsigned short int) need->vn_cnt);
    2725             : 
    2726           0 :       unsigned int auxoffset = offset + need->vn_aux;
    2727           0 :       for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
    2728             :         {
    2729           0 :           GElf_Vernaux auxmem;
    2730           0 :           GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
    2731           0 :           if (unlikely (aux == NULL))
    2732             :             break;
    2733             : 
    2734           0 :           printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
    2735             :                   auxoffset,
    2736           0 :                   elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
    2737           0 :                   get_ver_flags (aux->vna_flags),
    2738           0 :                   (unsigned short int) aux->vna_other);
    2739             : 
    2740           0 :           if (aux->vna_next == 0)
    2741             :             break;
    2742             : 
    2743           0 :           auxoffset += aux->vna_next;
    2744             :         }
    2745             : 
    2746             :       /* Find the next offset.  */
    2747           0 :       if (need->vn_next == 0)
    2748             :         break;
    2749             : 
    2750           0 :       offset += need->vn_next;
    2751             :     }
    2752             : }
    2753             : 
    2754             : 
    2755             : static void
    2756           0 : handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
    2757             : {
    2758             :   /* Get the data of the section.  */
    2759           0 :   Elf_Data *data = elf_getdata (scn, NULL);
    2760           0 :   if (data == NULL)
    2761           0 :     return;
    2762             : 
    2763             :   /* Get the section header string table index.  */
    2764           0 :   size_t shstrndx;
    2765           0 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    2766           0 :     error (EXIT_FAILURE, 0,
    2767           0 :            gettext ("cannot get section header string table index"));
    2768             : 
    2769           0 :   GElf_Shdr glink_mem;
    2770           0 :   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
    2771             :                                    &glink_mem);
    2772           0 :   if (glink == NULL)
    2773           0 :     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
    2774             :            elf_ndxscn (scn));
    2775             : 
    2776           0 :   int class = gelf_getclass (ebl->elf);
    2777           0 :   printf (ngettext ("\
    2778             : \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
    2779             :                     "\
    2780             : \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
    2781             :                     shdr->sh_info),
    2782           0 :           (unsigned int) elf_ndxscn (scn),
    2783           0 :           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    2784             :           shdr->sh_info,
    2785             :           class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
    2786             :           shdr->sh_offset,
    2787           0 :           (unsigned int) shdr->sh_link,
    2788           0 :           elf_strptr (ebl->elf, shstrndx, glink->sh_name));
    2789             : 
    2790           0 :   unsigned int offset = 0;
    2791           0 :   for (int cnt = shdr->sh_info; --cnt >= 0; )
    2792             :     {
    2793             :       /* Get the data at the next offset.  */
    2794           0 :       GElf_Verdef defmem;
    2795           0 :       GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
    2796           0 :       if (unlikely (def == NULL))
    2797             :         break;
    2798             : 
    2799           0 :       unsigned int auxoffset = offset + def->vd_aux;
    2800           0 :       GElf_Verdaux auxmem;
    2801           0 :       GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
    2802           0 :       if (unlikely (aux == NULL))
    2803             :         break;
    2804             : 
    2805           0 :       printf (gettext ("\
    2806             :   %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"),
    2807           0 :               offset, def->vd_version,
    2808           0 :               get_ver_flags (def->vd_flags),
    2809           0 :               def->vd_ndx,
    2810           0 :               def->vd_cnt,
    2811           0 :               elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
    2812             : 
    2813           0 :       auxoffset += aux->vda_next;
    2814           0 :       for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
    2815             :         {
    2816           0 :           aux = gelf_getverdaux (data, auxoffset, &auxmem);
    2817           0 :           if (unlikely (aux == NULL))
    2818             :             break;
    2819             : 
    2820           0 :           printf (gettext ("  %#06x: Parent %d: %s\n"),
    2821             :                   auxoffset, cnt2,
    2822           0 :                   elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
    2823             : 
    2824           0 :           if (aux->vda_next == 0)
    2825             :             break;
    2826             : 
    2827           0 :           auxoffset += aux->vda_next;
    2828             :         }
    2829             : 
    2830             :       /* Find the next offset.  */
    2831           0 :       if (def->vd_next == 0)
    2832             :         break;
    2833           0 :       offset += def->vd_next;
    2834             :     }
    2835             : }
    2836             : 
    2837             : 
    2838             : static void
    2839           0 : handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
    2840             : {
    2841           0 :   int class = gelf_getclass (ebl->elf);
    2842           0 :   const char **vername;
    2843           0 :   const char **filename;
    2844             : 
    2845             :   /* Get the data of the section.  */
    2846           0 :   Elf_Data *data = elf_getdata (scn, NULL);
    2847           0 :   if (data == NULL)
    2848           0 :     return;
    2849             : 
    2850             :   /* Get the section header string table index.  */
    2851           0 :   size_t shstrndx;
    2852           0 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    2853           0 :     error (EXIT_FAILURE, 0,
    2854           0 :            gettext ("cannot get section header string table index"));
    2855             : 
    2856             :   /* We have to find the version definition section and extract the
    2857             :      version names.  */
    2858             :   Elf_Scn *defscn = NULL;
    2859             :   Elf_Scn *needscn = NULL;
    2860             : 
    2861             :   Elf_Scn *verscn = NULL;
    2862           0 :   while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
    2863             :     {
    2864           0 :       GElf_Shdr vershdr_mem;
    2865           0 :       GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
    2866             : 
    2867           0 :       if (likely (vershdr != NULL))
    2868             :         {
    2869           0 :           if (vershdr->sh_type == SHT_GNU_verdef)
    2870             :             defscn = verscn;
    2871           0 :           else if (vershdr->sh_type == SHT_GNU_verneed)
    2872           0 :             needscn = verscn;
    2873             :         }
    2874             :     }
    2875             : 
    2876           0 :   size_t nvername;
    2877           0 :   if (defscn != NULL || needscn != NULL)
    2878             :     {
    2879             :       /* We have a version information (better should have).  Now get
    2880             :          the version names.  First find the maximum version number.  */
    2881           0 :       nvername = 0;
    2882           0 :       if (defscn != NULL)
    2883             :         {
    2884             :           /* Run through the version definitions and find the highest
    2885             :              index.  */
    2886           0 :           unsigned int offset = 0;
    2887           0 :           Elf_Data *defdata;
    2888           0 :           GElf_Shdr defshdrmem;
    2889           0 :           GElf_Shdr *defshdr;
    2890             : 
    2891           0 :           defdata = elf_getdata (defscn, NULL);
    2892           0 :           if (unlikely (defdata == NULL))
    2893           0 :             return;
    2894             : 
    2895           0 :           defshdr = gelf_getshdr (defscn, &defshdrmem);
    2896           0 :           if (unlikely (defshdr == NULL))
    2897           0 :             return;
    2898             : 
    2899           0 :           for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
    2900             :             {
    2901           0 :               GElf_Verdef defmem;
    2902           0 :               GElf_Verdef *def;
    2903             : 
    2904             :               /* Get the data at the next offset.  */
    2905           0 :               def = gelf_getverdef (defdata, offset, &defmem);
    2906           0 :               if (unlikely (def == NULL))
    2907             :                 break;
    2908             : 
    2909           0 :               nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
    2910             : 
    2911           0 :               if (def->vd_next == 0)
    2912             :                 break;
    2913           0 :               offset += def->vd_next;
    2914             :             }
    2915             :         }
    2916           0 :       if (needscn != NULL)
    2917             :         {
    2918           0 :           unsigned int offset = 0;
    2919           0 :           Elf_Data *needdata;
    2920           0 :           GElf_Shdr needshdrmem;
    2921           0 :           GElf_Shdr *needshdr;
    2922             : 
    2923           0 :           needdata = elf_getdata (needscn, NULL);
    2924           0 :           if (unlikely (needdata == NULL))
    2925           0 :             return;
    2926             : 
    2927           0 :           needshdr = gelf_getshdr (needscn, &needshdrmem);
    2928           0 :           if (unlikely (needshdr == NULL))
    2929           0 :             return;
    2930             : 
    2931           0 :           for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
    2932             :             {
    2933           0 :               GElf_Verneed needmem;
    2934           0 :               GElf_Verneed *need;
    2935           0 :               unsigned int auxoffset;
    2936           0 :               int cnt2;
    2937             : 
    2938             :               /* Get the data at the next offset.  */
    2939           0 :               need = gelf_getverneed (needdata, offset, &needmem);
    2940           0 :               if (unlikely (need == NULL))
    2941             :                 break;
    2942             : 
    2943             :               /* Run through the auxiliary entries.  */
    2944           0 :               auxoffset = offset + need->vn_aux;
    2945           0 :               for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
    2946             :                 {
    2947           0 :                   GElf_Vernaux auxmem;
    2948           0 :                   GElf_Vernaux *aux;
    2949             : 
    2950           0 :                   aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
    2951           0 :                   if (unlikely (aux == NULL))
    2952             :                     break;
    2953             : 
    2954           0 :                   nvername = MAX (nvername,
    2955             :                                   (size_t) (aux->vna_other & 0x7fff));
    2956             : 
    2957           0 :                   if (aux->vna_next == 0)
    2958             :                     break;
    2959           0 :                   auxoffset += aux->vna_next;
    2960             :                 }
    2961             : 
    2962           0 :               if (need->vn_next == 0)
    2963             :                 break;
    2964           0 :               offset += need->vn_next;
    2965             :             }
    2966             :         }
    2967             : 
    2968             :       /* This is the number of versions we know about.  */
    2969           0 :       ++nvername;
    2970             : 
    2971             :       /* Allocate the array.  */
    2972           0 :       vername = (const char **) alloca (nvername * sizeof (const char *));
    2973           0 :       memset(vername, 0, nvername * sizeof (const char *));
    2974           0 :       filename = (const char **) alloca (nvername * sizeof (const char *));
    2975           0 :       memset(filename, 0, nvername * sizeof (const char *));
    2976             : 
    2977             :       /* Run through the data structures again and collect the strings.  */
    2978           0 :       if (defscn != NULL)
    2979             :         {
    2980             :           /* Run through the version definitions and find the highest
    2981             :              index.  */
    2982           0 :           unsigned int offset = 0;
    2983           0 :           Elf_Data *defdata;
    2984           0 :           GElf_Shdr defshdrmem;
    2985           0 :           GElf_Shdr *defshdr;
    2986             : 
    2987           0 :           defdata = elf_getdata (defscn, NULL);
    2988           0 :           if (unlikely (defdata == NULL))
    2989           0 :             return;
    2990             : 
    2991           0 :           defshdr = gelf_getshdr (defscn, &defshdrmem);
    2992           0 :           if (unlikely (defshdr == NULL))
    2993           0 :             return;
    2994             : 
    2995           0 :           for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
    2996             :             {
    2997             : 
    2998             :               /* Get the data at the next offset.  */
    2999           0 :               GElf_Verdef defmem;
    3000           0 :               GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
    3001           0 :               if (unlikely (def == NULL))
    3002             :                 break;
    3003             : 
    3004           0 :               GElf_Verdaux auxmem;
    3005           0 :               GElf_Verdaux *aux = gelf_getverdaux (defdata,
    3006           0 :                                                    offset + def->vd_aux,
    3007             :                                                    &auxmem);
    3008           0 :               if (unlikely (aux == NULL))
    3009             :                 break;
    3010             : 
    3011           0 :               vername[def->vd_ndx & 0x7fff]
    3012           0 :                 = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
    3013           0 :               filename[def->vd_ndx & 0x7fff] = NULL;
    3014             : 
    3015           0 :               if (def->vd_next == 0)
    3016             :                 break;
    3017           0 :               offset += def->vd_next;
    3018             :             }
    3019             :         }
    3020           0 :       if (needscn != NULL)
    3021             :         {
    3022           0 :           unsigned int offset = 0;
    3023             : 
    3024           0 :           Elf_Data *needdata = elf_getdata (needscn, NULL);
    3025           0 :           GElf_Shdr needshdrmem;
    3026           0 :           GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
    3027           0 :           if (unlikely (needdata == NULL || needshdr == NULL))
    3028           0 :             return;
    3029             : 
    3030           0 :           for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
    3031             :             {
    3032             :               /* Get the data at the next offset.  */
    3033           0 :               GElf_Verneed needmem;
    3034           0 :               GElf_Verneed *need = gelf_getverneed (needdata, offset,
    3035             :                                                     &needmem);
    3036           0 :               if (unlikely (need == NULL))
    3037             :                 break;
    3038             : 
    3039             :               /* Run through the auxiliary entries.  */
    3040           0 :               unsigned int auxoffset = offset + need->vn_aux;
    3041           0 :               for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
    3042             :                 {
    3043           0 :                   GElf_Vernaux auxmem;
    3044           0 :                   GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
    3045             :                                                        &auxmem);
    3046           0 :                   if (unlikely (aux == NULL))
    3047             :                     break;
    3048             : 
    3049           0 :                   vername[aux->vna_other & 0x7fff]
    3050           0 :                     = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
    3051           0 :                   filename[aux->vna_other & 0x7fff]
    3052           0 :                     = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
    3053             : 
    3054           0 :                   if (aux->vna_next == 0)
    3055             :                     break;
    3056           0 :                   auxoffset += aux->vna_next;
    3057             :                 }
    3058             : 
    3059           0 :               if (need->vn_next == 0)
    3060             :                 break;
    3061           0 :               offset += need->vn_next;
    3062             :             }
    3063             :         }
    3064             :     }
    3065             :   else
    3066             :     {
    3067             :       vername = NULL;
    3068             :       nvername = 1;
    3069             :       filename = NULL;
    3070             :     }
    3071             : 
    3072           0 :   GElf_Shdr glink_mem;
    3073           0 :   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
    3074             :                                    &glink_mem);
    3075           0 :   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_HALF, 1, EV_CURRENT);
    3076           0 :   if (glink == NULL)
    3077           0 :     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
    3078             :            elf_ndxscn (scn));
    3079             : 
    3080             :   /* Print the header.  */
    3081           0 :   printf (ngettext ("\
    3082             : \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
    3083             :                     "\
    3084             : \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
    3085             :                     shdr->sh_size / sh_entsize),
    3086           0 :           (unsigned int) elf_ndxscn (scn),
    3087           0 :           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    3088           0 :           (int) (shdr->sh_size / sh_entsize),
    3089             :           class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
    3090             :           shdr->sh_offset,
    3091           0 :           (unsigned int) shdr->sh_link,
    3092           0 :           elf_strptr (ebl->elf, shstrndx, glink->sh_name));
    3093             : 
    3094             :   /* Now we can finally look at the actual contents of this section.  */
    3095           0 :   for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
    3096             :     {
    3097           0 :       if (cnt % 2 == 0)
    3098           0 :         printf ("\n %4d:", cnt);
    3099             : 
    3100           0 :       GElf_Versym symmem;
    3101           0 :       GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
    3102           0 :       if (sym == NULL)
    3103             :         break;
    3104             : 
    3105           0 :       switch (*sym)
    3106             :         {
    3107           0 :           ssize_t n;
    3108           0 :         case 0:
    3109           0 :           fputs_unlocked (gettext ("   0 *local*                     "),
    3110             :                           stdout);
    3111           0 :           break;
    3112             : 
    3113           0 :         case 1:
    3114           0 :           fputs_unlocked (gettext ("   1 *global*                    "),
    3115             :                           stdout);
    3116           0 :           break;
    3117             : 
    3118           0 :         default:
    3119           0 :           n = printf ("%4d%c%s",
    3120           0 :                       *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
    3121             :                       (vername != NULL
    3122           0 :                        && (unsigned int) (*sym & 0x7fff) < nvername)
    3123           0 :                       ? vername[*sym & 0x7fff] : "???");
    3124           0 :           if ((unsigned int) (*sym & 0x7fff) < nvername
    3125           0 :               && filename != NULL && filename[*sym & 0x7fff] != NULL)
    3126           0 :             n += printf ("(%s)", filename[*sym & 0x7fff]);
    3127           0 :           printf ("%*s", MAX (0, 33 - (int) n), " ");
    3128             :           break;
    3129             :         }
    3130             :     }
    3131           0 :   putchar_unlocked ('\n');
    3132             : }
    3133             : 
    3134             : 
    3135             : static void
    3136           0 : print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
    3137             :                  uint_fast32_t maxlength, Elf32_Word nbucket,
    3138             :                  uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
    3139             : {
    3140           0 :   uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
    3141             : 
    3142           0 :   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
    3143           0 :     ++counts[lengths[cnt]];
    3144             : 
    3145           0 :   GElf_Shdr glink_mem;
    3146           0 :   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf,
    3147           0 :                                                shdr->sh_link),
    3148             :                                    &glink_mem);
    3149           0 :   if (glink == NULL)
    3150             :     {
    3151           0 :       error (0, 0, gettext ("invalid sh_link value in section %zu"),
    3152             :              elf_ndxscn (scn));
    3153           0 :       return;
    3154             :     }
    3155             : 
    3156           0 :   printf (ngettext ("\
    3157             : \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",
    3158             :                     "\
    3159             : \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",
    3160             :                     nbucket),
    3161           0 :           (unsigned int) elf_ndxscn (scn),
    3162           0 :           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    3163             :           (int) nbucket,
    3164           0 :           gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
    3165             :           shdr->sh_addr,
    3166             :           shdr->sh_offset,
    3167           0 :           (unsigned int) shdr->sh_link,
    3168           0 :           elf_strptr (ebl->elf, shstrndx, glink->sh_name));
    3169             : 
    3170           0 :   if (extrastr != NULL)
    3171           0 :     fputs (extrastr, stdout);
    3172             : 
    3173           0 :   if (likely (nbucket > 0))
    3174             :     {
    3175           0 :       uint64_t success = 0;
    3176             : 
    3177             :       /* xgettext:no-c-format */
    3178           0 :       fputs_unlocked (gettext ("\
    3179             :  Length  Number  % of total  Coverage\n"), stdout);
    3180           0 :       printf (gettext ("      0  %6" PRIu32 "      %5.1f%%\n"),
    3181           0 :               counts[0], (counts[0] * 100.0) / nbucket);
    3182             : 
    3183           0 :       uint64_t nzero_counts = 0;
    3184           0 :       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
    3185             :         {
    3186           0 :           nzero_counts += counts[cnt] * cnt;
    3187           0 :           printf (gettext ("\
    3188             : %7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
    3189           0 :                   (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
    3190           0 :                   (nzero_counts * 100.0) / nsyms);
    3191             :         }
    3192             : 
    3193             :       Elf32_Word acc = 0;
    3194           0 :       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
    3195             :         {
    3196           0 :           acc += cnt;
    3197           0 :           success += counts[cnt] * acc;
    3198             :         }
    3199             : 
    3200           0 :       printf (gettext ("\
    3201             :  Average number of tests:   successful lookup: %f\n\
    3202             :                           unsuccessful lookup: %f\n"),
    3203           0 :               (double) success / (double) nzero_counts,
    3204           0 :               (double) nzero_counts / (double) nbucket);
    3205             :     }
    3206             : 
    3207           0 :   free (counts);
    3208             : }
    3209             : 
    3210             : 
    3211             : /* This function handles the traditional System V-style hash table format.  */
    3212             : static void
    3213           0 : handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
    3214             : {
    3215           0 :   Elf_Data *data = elf_getdata (scn, NULL);
    3216           0 :   if (unlikely (data == NULL))
    3217             :     {
    3218           0 :       error (0, 0, gettext ("cannot get data for section %d: %s"),
    3219           0 :              (int) elf_ndxscn (scn), elf_errmsg (-1));
    3220           0 :       return;
    3221             :     }
    3222             : 
    3223           0 :   if (unlikely (data->d_size < 2 * sizeof (Elf32_Word)))
    3224             :     {
    3225           0 :     invalid_data:
    3226           0 :       error (0, 0, gettext ("invalid data in sysv.hash section %d"),
    3227           0 :              (int) elf_ndxscn (scn));
    3228           0 :       return;
    3229             :     }
    3230             : 
    3231           0 :   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
    3232           0 :   Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
    3233             : 
    3234           0 :   uint64_t used_buf = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
    3235           0 :   if (used_buf > data->d_size)
    3236             :     goto invalid_data;
    3237             : 
    3238           0 :   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
    3239           0 :   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
    3240             : 
    3241           0 :   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
    3242             : 
    3243           0 :   uint_fast32_t maxlength = 0;
    3244           0 :   uint_fast32_t nsyms = 0;
    3245           0 :   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
    3246             :     {
    3247           0 :       Elf32_Word inner = bucket[cnt];
    3248           0 :       Elf32_Word chain_len = 0;
    3249           0 :       while (inner > 0 && inner < nchain)
    3250             :         {
    3251           0 :           ++nsyms;
    3252           0 :           ++chain_len;
    3253           0 :           if (chain_len > nchain)
    3254             :             {
    3255           0 :               error (0, 0, gettext ("invalid chain in sysv.hash section %d"),
    3256           0 :                      (int) elf_ndxscn (scn));
    3257           0 :               free (lengths);
    3258           0 :               return;
    3259             :             }
    3260           0 :           if (maxlength < ++lengths[cnt])
    3261           0 :             ++maxlength;
    3262             : 
    3263           0 :           inner = chain[inner];
    3264             :         }
    3265             :     }
    3266             : 
    3267           0 :   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
    3268             :                    lengths, NULL);
    3269             : 
    3270           0 :   free (lengths);
    3271             : }
    3272             : 
    3273             : 
    3274             : /* This function handles the incorrect, System V-style hash table
    3275             :    format some 64-bit architectures use.  */
    3276             : static void
    3277           0 : handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
    3278             : {
    3279           0 :   Elf_Data *data = elf_getdata (scn, NULL);
    3280           0 :   if (unlikely (data == NULL))
    3281             :     {
    3282           0 :       error (0, 0, gettext ("cannot get data for section %d: %s"),
    3283           0 :              (int) elf_ndxscn (scn), elf_errmsg (-1));
    3284           0 :       return;
    3285             :     }
    3286             : 
    3287           0 :   if (unlikely (data->d_size < 2 * sizeof (Elf64_Xword)))
    3288             :     {
    3289           0 :     invalid_data:
    3290           0 :       error (0, 0, gettext ("invalid data in sysv.hash64 section %d"),
    3291           0 :              (int) elf_ndxscn (scn));
    3292           0 :       return;
    3293             :     }
    3294             : 
    3295           0 :   Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
    3296           0 :   Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
    3297             : 
    3298           0 :   uint64_t maxwords = data->d_size / sizeof (Elf64_Xword);
    3299           0 :   if (maxwords < 2
    3300           0 :       || maxwords - 2 < nbucket
    3301           0 :       || maxwords - 2 - nbucket < nchain)
    3302             :     goto invalid_data;
    3303             : 
    3304           0 :   Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
    3305           0 :   Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
    3306             : 
    3307           0 :   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
    3308             : 
    3309           0 :   uint_fast32_t maxlength = 0;
    3310           0 :   uint_fast32_t nsyms = 0;
    3311           0 :   for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
    3312             :     {
    3313           0 :       Elf64_Xword inner = bucket[cnt];
    3314           0 :       Elf64_Xword chain_len = 0;
    3315           0 :       while (inner > 0 && inner < nchain)
    3316             :         {
    3317           0 :           ++nsyms;
    3318           0 :           ++chain_len;
    3319           0 :           if (chain_len > nchain)
    3320             :             {
    3321           0 :               error (0, 0, gettext ("invalid chain in sysv.hash64 section %d"),
    3322           0 :                      (int) elf_ndxscn (scn));
    3323           0 :               free (lengths);
    3324           0 :               return;
    3325             :             }
    3326           0 :           if (maxlength < ++lengths[cnt])
    3327           0 :             ++maxlength;
    3328             : 
    3329           0 :           inner = chain[inner];
    3330             :         }
    3331             :     }
    3332             : 
    3333           0 :   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
    3334             :                    lengths, NULL);
    3335             : 
    3336           0 :   free (lengths);
    3337             : }
    3338             : 
    3339             : 
    3340             : /* This function handles the GNU-style hash table format.  */
    3341             : static void
    3342          10 : handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
    3343             : {
    3344          10 :   uint32_t *lengths = NULL;
    3345          10 :   Elf_Data *data = elf_getdata (scn, NULL);
    3346          10 :   if (unlikely (data == NULL))
    3347             :     {
    3348           0 :       error (0, 0, gettext ("cannot get data for section %d: %s"),
    3349           0 :              (int) elf_ndxscn (scn), elf_errmsg (-1));
    3350           0 :       return;
    3351             :     }
    3352             : 
    3353          10 :   if (unlikely (data->d_size < 4 * sizeof (Elf32_Word)))
    3354             :     {
    3355           0 :     invalid_data:
    3356           0 :       free (lengths);
    3357           0 :       error (0, 0, gettext ("invalid data in gnu.hash section %d"),
    3358           0 :              (int) elf_ndxscn (scn));
    3359           0 :       return;
    3360             :     }
    3361             : 
    3362          10 :   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
    3363          10 :   Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
    3364             : 
    3365             :   /* Next comes the size of the bitmap.  It's measured in words for
    3366             :      the architecture.  It's 32 bits for 32 bit archs, and 64 bits for
    3367             :      64 bit archs.  There is always a bloom filter present, so zero is
    3368             :      an invalid value.  */
    3369          10 :   Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
    3370          10 :   if (gelf_getclass (ebl->elf) == ELFCLASS64)
    3371          10 :     bitmask_words *= 2;
    3372             : 
    3373          10 :   if (bitmask_words == 0)
    3374             :     goto invalid_data;
    3375             : 
    3376          10 :   Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
    3377             : 
    3378             :   /* Is there still room for the sym chain?
    3379             :      Use uint64_t calculation to prevent 32bit overlow.  */
    3380          10 :   uint64_t used_buf = (4ULL + bitmask_words + nbucket) * sizeof (Elf32_Word);
    3381          10 :   uint32_t max_nsyms = (data->d_size - used_buf) / sizeof (Elf32_Word);
    3382          10 :   if (used_buf > data->d_size)
    3383             :     goto invalid_data;
    3384             : 
    3385          10 :   lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
    3386             : 
    3387          10 :   Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
    3388          10 :   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
    3389          20 :   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
    3390          10 :                                                     + nbucket];
    3391             : 
    3392             :   /* Compute distribution of chain lengths.  */
    3393          10 :   uint_fast32_t maxlength = 0;
    3394          10 :   uint_fast32_t nsyms = 0;
    3395         326 :   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
    3396         316 :     if (bucket[cnt] != 0)
    3397             :       {
    3398         220 :         Elf32_Word inner = bucket[cnt] - symbias;
    3399         420 :         do
    3400             :           {
    3401         420 :             ++nsyms;
    3402         420 :             if (maxlength < ++lengths[cnt])
    3403          37 :               ++maxlength;
    3404         420 :             if (inner >= max_nsyms)
    3405             :               goto invalid_data;
    3406             :           }
    3407         420 :         while ((chain[inner++] & 1) == 0);
    3408             :       }
    3409             : 
    3410             :   /* Count bits in bitmask.  */
    3411             :   uint_fast32_t nbits = 0;
    3412         122 :   for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
    3413             :     {
    3414         112 :       uint_fast32_t word = bitmask[cnt];
    3415             : 
    3416         112 :       word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
    3417         112 :       word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
    3418         112 :       word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
    3419         112 :       word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
    3420         112 :       nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
    3421             :     }
    3422             : 
    3423          10 :   char *str;
    3424          10 :   if (unlikely (asprintf (&str, gettext ("\
    3425             :  Symbol Bias: %u\n\
    3426             :  Bitmask Size: %zu bytes  %" PRIuFAST32 "%% bits set  2nd hash shift: %u\n"),
    3427             :                           (unsigned int) symbias,
    3428             :                           bitmask_words * sizeof (Elf32_Word),
    3429             :                           ((nbits * 100 + 50)
    3430             :                            / (uint_fast32_t) (bitmask_words
    3431             :                                               * sizeof (Elf32_Word) * 8)),
    3432             :                           (unsigned int) shift) == -1))
    3433           0 :     error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
    3434             : 
    3435          10 :   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
    3436             :                    lengths, str);
    3437             : 
    3438          10 :   free (str);
    3439          10 :   free (lengths);
    3440             : }
    3441             : 
    3442             : 
    3443             : /* Find the symbol table(s).  For this we have to search through the
    3444             :    section table.  */
    3445             : static void
    3446          42 : handle_hash (Ebl *ebl)
    3447             : {
    3448             :   /* Get the section header string table index.  */
    3449          42 :   size_t shstrndx;
    3450          42 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    3451           0 :     error (EXIT_FAILURE, 0,
    3452           0 :            gettext ("cannot get section header string table index"));
    3453             : 
    3454             :   Elf_Scn *scn = NULL;
    3455        1073 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    3456             :     {
    3457             :       /* Handle the section if it is a symbol table.  */
    3458        1031 :       GElf_Shdr shdr_mem;
    3459        1031 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    3460             : 
    3461        1031 :       if (likely (shdr != NULL))
    3462             :         {
    3463        1031 :           if ((shdr->sh_type == SHT_HASH || shdr->sh_type == SHT_GNU_HASH)
    3464          10 :               && (shdr->sh_flags & SHF_COMPRESSED) != 0)
    3465             :             {
    3466           0 :               if (elf_compress (scn, 0, 0) < 0)
    3467           0 :                 printf ("WARNING: %s [%zd]\n",
    3468             :                         gettext ("Couldn't uncompress section"),
    3469             :                         elf_ndxscn (scn));
    3470           0 :               shdr = gelf_getshdr (scn, &shdr_mem);
    3471           0 :               if (unlikely (shdr == NULL))
    3472           0 :                 error (EXIT_FAILURE, 0,
    3473           0 :                        gettext ("cannot get section [%zd] header: %s"),
    3474             :                        elf_ndxscn (scn), elf_errmsg (-1));
    3475             :             }
    3476             : 
    3477        1031 :           if (shdr->sh_type == SHT_HASH)
    3478             :             {
    3479           0 :               if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
    3480           0 :                 handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
    3481             :               else
    3482           0 :                 handle_sysv_hash (ebl, scn, shdr, shstrndx);
    3483             :             }
    3484        1031 :           else if (shdr->sh_type == SHT_GNU_HASH)
    3485          10 :             handle_gnu_hash (ebl, scn, shdr, shstrndx);
    3486             :         }
    3487             :     }
    3488          42 : }
    3489             : 
    3490             : 
    3491             : static void
    3492           0 : print_liblist (Ebl *ebl)
    3493             : {
    3494             :   /* Find the library list sections.  For this we have to search
    3495             :      through the section table.  */
    3496           0 :   Elf_Scn *scn = NULL;
    3497             : 
    3498             :   /* Get the section header string table index.  */
    3499           0 :   size_t shstrndx;
    3500           0 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    3501           0 :     error (EXIT_FAILURE, 0,
    3502           0 :            gettext ("cannot get section header string table index"));
    3503             : 
    3504           0 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    3505             :     {
    3506           0 :       GElf_Shdr shdr_mem;
    3507           0 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    3508             : 
    3509           0 :       if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
    3510             :         {
    3511           0 :           size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_LIB, 1, EV_CURRENT);
    3512           0 :           int nentries = shdr->sh_size / sh_entsize;
    3513           0 :           printf (ngettext ("\
    3514             : \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
    3515             :                             "\
    3516             : \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
    3517             :                             nentries),
    3518             :                   elf_ndxscn (scn),
    3519           0 :                   elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    3520             :                   shdr->sh_offset,
    3521             :                   nentries);
    3522             : 
    3523           0 :           Elf_Data *data = elf_getdata (scn, NULL);
    3524           0 :           if (data == NULL)
    3525           0 :             return;
    3526             : 
    3527           0 :           puts (gettext ("\
    3528             :        Library                       Time Stamp          Checksum Version Flags"));
    3529             : 
    3530           0 :           for (int cnt = 0; cnt < nentries; ++cnt)
    3531             :             {
    3532           0 :               GElf_Lib lib_mem;
    3533           0 :               GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
    3534           0 :               if (unlikely (lib == NULL))
    3535           0 :                 continue;
    3536             : 
    3537           0 :               time_t t = (time_t) lib->l_time_stamp;
    3538           0 :               struct tm *tm = gmtime (&t);
    3539           0 :               if (unlikely (tm == NULL))
    3540           0 :                 continue;
    3541             : 
    3542           0 :               printf ("  [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
    3543           0 :                       cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
    3544           0 :                       tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
    3545             :                       tm->tm_hour, tm->tm_min, tm->tm_sec,
    3546           0 :                       (unsigned int) lib->l_checksum,
    3547           0 :                       (unsigned int) lib->l_version,
    3548           0 :                       (unsigned int) lib->l_flags);
    3549             :             }
    3550             :         }
    3551             :     }
    3552             : }
    3553             : 
    3554             : static void
    3555           0 : print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
    3556             : {
    3557             :   /* Find the object attributes sections.  For this we have to search
    3558             :      through the section table.  */
    3559           0 :   Elf_Scn *scn = NULL;
    3560             : 
    3561             :   /* Get the section header string table index.  */
    3562           0 :   size_t shstrndx;
    3563           0 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    3564           0 :     error (EXIT_FAILURE, 0,
    3565           0 :            gettext ("cannot get section header string table index"));
    3566             : 
    3567           0 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    3568             :     {
    3569           0 :       GElf_Shdr shdr_mem;
    3570           0 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    3571             : 
    3572           0 :       if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
    3573           0 :                            && (shdr->sh_type != SHT_ARM_ATTRIBUTES
    3574           0 :                                || ehdr->e_machine != EM_ARM)
    3575           0 :                            && (shdr->sh_type != SHT_CSKY_ATTRIBUTES
    3576           0 :                                || ehdr->e_machine != EM_CSKY)))
    3577           0 :         continue;
    3578             : 
    3579           0 :       printf (gettext ("\
    3580             : \nObject attributes section [%2zu] '%s' of %" PRIu64
    3581             :                        " bytes at offset %#0" PRIx64 ":\n"),
    3582             :               elf_ndxscn (scn),
    3583           0 :               elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    3584             :               shdr->sh_size, shdr->sh_offset);
    3585             : 
    3586           0 :       Elf_Data *data = elf_rawdata (scn, NULL);
    3587           0 :       if (unlikely (data == NULL || data->d_size == 0))
    3588           0 :         return;
    3589             : 
    3590           0 :       const unsigned char *p = data->d_buf;
    3591             : 
    3592             :       /* There is only one 'version', A.  */
    3593           0 :       if (unlikely (*p++ != 'A'))
    3594           0 :         return;
    3595             : 
    3596           0 :       fputs_unlocked (gettext ("  Owner          Size\n"), stdout);
    3597             : 
    3598           0 :       inline size_t left (void)
    3599             :       {
    3600           0 :         return (const unsigned char *) data->d_buf + data->d_size - p;
    3601             :       }
    3602             : 
    3603             :       /* Loop over the sections.  */
    3604           0 :       while (left () >= 4)
    3605             :         {
    3606             :           /* Section length.  */
    3607           0 :           uint32_t len;
    3608           0 :           memcpy (&len, p, sizeof len);
    3609             : 
    3610           0 :           if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
    3611           0 :             CONVERT (len);
    3612             : 
    3613           0 :           if (unlikely (len > left ()))
    3614             :             break;
    3615             : 
    3616             :           /* Section vendor name.  */
    3617           0 :           const unsigned char *name = p + sizeof len;
    3618           0 :           p += len;
    3619             : 
    3620           0 :           unsigned const char *q = memchr (name, '\0', len);
    3621           0 :           if (unlikely (q == NULL))
    3622             :             break;
    3623           0 :           ++q;
    3624             : 
    3625           0 :           printf (gettext ("  %-13s  %4" PRIu32 "\n"), name, len);
    3626             : 
    3627           0 :           bool gnu_vendor = (q - name == sizeof "gnu"
    3628           0 :                              && !memcmp (name, "gnu", sizeof "gnu"));
    3629             : 
    3630             :           /* Loop over subsections.  */
    3631           0 :           if (shdr->sh_type != SHT_GNU_ATTRIBUTES
    3632           0 :               || gnu_vendor)
    3633           0 :             while (q < p)
    3634             :               {
    3635           0 :                 const unsigned char *const sub = q;
    3636             : 
    3637           0 :                 unsigned int subsection_tag;
    3638           0 :                 get_uleb128 (subsection_tag, q, p);
    3639           0 :                 if (unlikely (q >= p))
    3640             :                   break;
    3641             : 
    3642           0 :                 uint32_t subsection_len;
    3643           0 :                 if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
    3644             :                   break;
    3645             : 
    3646           0 :                 memcpy (&subsection_len, q, sizeof subsection_len);
    3647             : 
    3648           0 :                 if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
    3649           0 :                   CONVERT (subsection_len);
    3650             : 
    3651             :                 /* Don't overflow, ptrdiff_t might be 32bits, but signed.  */
    3652           0 :                 if (unlikely (subsection_len == 0
    3653             :                               || subsection_len >= (uint32_t) PTRDIFF_MAX
    3654             :                               || p - sub < (ptrdiff_t) subsection_len))
    3655             :                   break;
    3656             : 
    3657           0 :                 const unsigned char *r = q + sizeof subsection_len;
    3658           0 :                 q = sub + subsection_len;
    3659             : 
    3660           0 :                 switch (subsection_tag)
    3661             :                   {
    3662           0 :                   default:
    3663             :                     /* Unknown subsection, print and skip.  */
    3664           0 :                     printf (gettext ("    %-4u %12" PRIu32 "\n"),
    3665             :                             subsection_tag, subsection_len);
    3666             :                     break;
    3667             : 
    3668           0 :                   case 1:       /* Tag_File */
    3669           0 :                     printf (gettext ("    File: %11" PRIu32 "\n"),
    3670             :                             subsection_len);
    3671             : 
    3672           0 :                     while (r < q)
    3673           0 :                       {
    3674           0 :                         unsigned int tag;
    3675           0 :                         get_uleb128 (tag, r, q);
    3676           0 :                         if (unlikely (r >= q))
    3677             :                           break;
    3678             : 
    3679             :                         /* GNU style tags have either a uleb128 value,
    3680             :                            when lowest bit is not set, or a string
    3681             :                            when the lowest bit is set.
    3682             :                            "compatibility" (32) is special.  It has
    3683             :                            both a string and a uleb128 value.  For
    3684             :                            non-gnu we assume 6 till 31 only take ints.
    3685             :                            XXX see arm backend, do we need a separate
    3686             :                            hook?  */
    3687           0 :                         uint64_t value = 0;
    3688           0 :                         const char *string = NULL;
    3689           0 :                         if (tag == 32 || (tag & 1) == 0
    3690           0 :                             || (! gnu_vendor && (tag > 5 && tag < 32)))
    3691             :                           {
    3692           0 :                             get_uleb128 (value, r, q);
    3693           0 :                             if (r > q)
    3694             :                               break;
    3695             :                           }
    3696           0 :                         if (tag == 32
    3697           0 :                             || ((tag & 1) != 0
    3698           0 :                                 && (gnu_vendor
    3699           0 :                                     || (! gnu_vendor && tag > 32)))
    3700           0 :                             || (! gnu_vendor && tag > 3 && tag < 6))
    3701             :                           {
    3702           0 :                             string = (const char *) r;
    3703           0 :                             r = memchr (r, '\0', q - r);
    3704           0 :                             if (r == NULL)
    3705             :                               break;
    3706           0 :                             ++r;
    3707             :                           }
    3708             : 
    3709           0 :                         const char *tag_name = NULL;
    3710           0 :                         const char *value_name = NULL;
    3711           0 :                         ebl_check_object_attribute (ebl, (const char *) name,
    3712             :                                                     tag, value,
    3713             :                                                     &tag_name, &value_name);
    3714             : 
    3715           0 :                         if (tag_name != NULL)
    3716             :                           {
    3717           0 :                             if (tag == 32)
    3718           0 :                               printf (gettext ("      %s: %" PRId64 ", %s\n"),
    3719             :                                       tag_name, value, string);
    3720           0 :                             else if (string == NULL && value_name == NULL)
    3721           0 :                               printf (gettext ("      %s: %" PRId64 "\n"),
    3722             :                                       tag_name, value);
    3723             :                             else
    3724           0 :                               printf (gettext ("      %s: %s\n"),
    3725             :                                       tag_name, string ?: value_name);
    3726             :                           }
    3727             :                         else
    3728             :                           {
    3729             :                             /* For "gnu" vendor 32 "compatibility" has
    3730             :                                already been handled above.  */
    3731           0 :                             assert (tag != 32
    3732             :                                     || strcmp ((const char *) name, "gnu"));
    3733           0 :                             if (string == NULL)
    3734           0 :                               printf (gettext ("      %u: %" PRId64 "\n"),
    3735             :                                       tag, value);
    3736             :                             else
    3737           0 :                               printf (gettext ("      %u: %s\n"),
    3738             :                                       tag, string);
    3739             :                           }
    3740             :                       }
    3741             :                   }
    3742             :               }
    3743             :         }
    3744             :     }
    3745             : }
    3746             : 
    3747             : 
    3748             : void
    3749      786859 : print_dwarf_addr (Dwfl_Module *dwflmod,
    3750             :                   int address_size, Dwarf_Addr address, Dwarf_Addr raw)
    3751             : {
    3752             :   /* See if there is a name we can give for this address.  */
    3753      786859 :   GElf_Sym sym;
    3754      786859 :   GElf_Off off = 0;
    3755      786831 :   const char *name = (print_address_names && ! print_unresolved_addresses)
    3756      786749 :     ? dwfl_module_addrinfo (dwflmod, address, &off, &sym, NULL, NULL, NULL)
    3757     1573608 :     : NULL;
    3758             : 
    3759      786859 :   const char *scn;
    3760      786859 :   if (print_unresolved_addresses)
    3761             :     {
    3762          82 :       address = raw;
    3763          82 :       scn = NULL;
    3764             :     }
    3765             :   else
    3766             :     {
    3767             :       /* Relativize the address.  */
    3768      786777 :       int n = dwfl_module_relocations (dwflmod);
    3769      786777 :       int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
    3770             : 
    3771             :       /* In an ET_REL file there is a section name to refer to.  */
    3772      785777 :       scn = (i < 0 ? NULL
    3773      785777 :              : dwfl_module_relocation_info (dwflmod, i, NULL));
    3774             :     }
    3775             : 
    3776      786859 :   if ((name != NULL
    3777      775450 :        ? (off != 0
    3778             :           ? (scn != NULL
    3779             :              ? (address_size == 0
    3780      249813 :                 ? printf ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">",
    3781             :                           scn, address, name, off)
    3782     1492578 :                 : printf ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">",
    3783      497526 :                           scn, 2 + address_size * 2, address,
    3784             :                           name, off))
    3785             :              : (address_size == 0
    3786         169 :                 ? printf ("%#" PRIx64 " <%s+%#" PRIx64 ">",
    3787             :                           address, name, off)
    3788        1410 :                 : printf ("%#0*" PRIx64 " <%s+%#" PRIx64 ">",
    3789         470 :                           2 + address_size * 2, address,
    3790             :                           name, off)))
    3791             :           : (scn != NULL
    3792             :              ? (address_size == 0
    3793        9189 :                 ? printf ("%s+%#" PRIx64 " <%s>", scn, address, name)
    3794       54030 :                 : printf ("%s+%#0*" PRIx64 " <%s>",
    3795       18010 :                            scn, 2 + address_size * 2, address, name))
    3796             :              : (address_size == 0
    3797          79 :                 ? printf ("%#" PRIx64 " <%s>", address, name)
    3798         582 :                 : printf ("%#0*" PRIx64 " <%s>",
    3799         194 :                           2 + address_size * 2, address, name))))
    3800             :        : (scn != NULL
    3801             :           ? (address_size == 0
    3802        5877 :              ? printf ("%s+%#" PRIx64, scn, address)
    3803        5362 :              : printf ("%s+%#0*" PRIx64, scn, 2 + address_size * 2, address))
    3804             :           : (address_size == 0
    3805          34 :              ? printf ("%#" PRIx64, address)
    3806     1573582 :              : printf ("%#0*" PRIx64, 2 + address_size * 2, address)))) < 0)
    3807           0 :     error (EXIT_FAILURE, 0, _("sprintf failure"));
    3808      786859 : }
    3809             : 
    3810             : 
    3811             : static const char *
    3812      775008 : dwarf_tag_string (unsigned int tag)
    3813             : {
    3814      775008 :   switch (tag)
    3815             :     {
    3816             : #define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
    3817      775008 :       DWARF_ALL_KNOWN_DW_TAG
    3818             : #undef DWARF_ONE_KNOWN_DW_TAG
    3819           0 :     default:
    3820           0 :       return NULL;
    3821             :     }
    3822             : }
    3823             : 
    3824             : 
    3825             : static const char *
    3826     3140967 : dwarf_attr_string (unsigned int attrnum)
    3827             : {
    3828     3140967 :   switch (attrnum)
    3829             :     {
    3830             : #define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
    3831     3140966 :       DWARF_ALL_KNOWN_DW_AT
    3832             : #undef DWARF_ONE_KNOWN_DW_AT
    3833           0 :     default:
    3834           0 :       return NULL;
    3835             :     }
    3836             : }
    3837             : 
    3838             : 
    3839             : static const char *
    3840     3140973 : dwarf_form_string (unsigned int form)
    3841             : {
    3842     3140973 :   switch (form)
    3843             :     {
    3844             : #define DWARF_ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
    3845     3140971 :       DWARF_ALL_KNOWN_DW_FORM
    3846             : #undef DWARF_ONE_KNOWN_DW_FORM
    3847           0 :     default:
    3848           0 :       return NULL;
    3849             :     }
    3850             : }
    3851             : 
    3852             : 
    3853             : static const char *
    3854        1162 : dwarf_lang_string (unsigned int lang)
    3855             : {
    3856        1162 :   switch (lang)
    3857             :     {
    3858             : #define DWARF_ONE_KNOWN_DW_LANG(NAME, CODE) case CODE: return #NAME;
    3859        1162 :       DWARF_ALL_KNOWN_DW_LANG
    3860             : #undef DWARF_ONE_KNOWN_DW_LANG
    3861           0 :     default:
    3862           0 :       return NULL;
    3863             :     }
    3864             : }
    3865             : 
    3866             : 
    3867             : static const char *
    3868             : dwarf_inline_string (unsigned int code)
    3869             : {
    3870        2934 :   static const char *const known[] =
    3871             :     {
    3872             : #define DWARF_ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME,
    3873             :       DWARF_ALL_KNOWN_DW_INL
    3874             : #undef DWARF_ONE_KNOWN_DW_INL
    3875             :     };
    3876             : 
    3877        2934 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3878        2934 :     return known[code];
    3879             : 
    3880             :   return NULL;
    3881             : }
    3882             : 
    3883             : 
    3884             : static const char *
    3885             : dwarf_encoding_string (unsigned int code)
    3886             : {
    3887       16569 :   static const char *const known[] =
    3888             :     {
    3889             : #define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
    3890             :       DWARF_ALL_KNOWN_DW_ATE
    3891             : #undef DWARF_ONE_KNOWN_DW_ATE
    3892             :     };
    3893             : 
    3894       16569 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3895       16569 :     return known[code];
    3896             : 
    3897             :   return NULL;
    3898             : }
    3899             : 
    3900             : 
    3901             : static const char *
    3902             : dwarf_access_string (unsigned int code)
    3903             : {
    3904           0 :   static const char *const known[] =
    3905             :     {
    3906             : #define DWARF_ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME,
    3907             :       DWARF_ALL_KNOWN_DW_ACCESS
    3908             : #undef DWARF_ONE_KNOWN_DW_ACCESS
    3909             :     };
    3910             : 
    3911           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3912           0 :     return known[code];
    3913             : 
    3914             :   return NULL;
    3915             : }
    3916             : 
    3917             : 
    3918             : static const char *
    3919             : dwarf_defaulted_string (unsigned int code)
    3920             : {
    3921           0 :   static const char *const known[] =
    3922             :     {
    3923             : #define DWARF_ONE_KNOWN_DW_DEFAULTED(NAME, CODE) [CODE] = #NAME,
    3924             :       DWARF_ALL_KNOWN_DW_DEFAULTED
    3925             : #undef DWARF_ONE_KNOWN_DW_DEFAULTED
    3926             :     };
    3927             : 
    3928           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3929           0 :     return known[code];
    3930             : 
    3931             :   return NULL;
    3932             : }
    3933             : 
    3934             : 
    3935             : static const char *
    3936             : dwarf_visibility_string (unsigned int code)
    3937             : {
    3938           0 :   static const char *const known[] =
    3939             :     {
    3940             : #define DWARF_ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
    3941             :       DWARF_ALL_KNOWN_DW_VIS
    3942             : #undef DWARF_ONE_KNOWN_DW_VIS
    3943             :     };
    3944             : 
    3945           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3946           0 :     return known[code];
    3947             : 
    3948             :   return NULL;
    3949             : }
    3950             : 
    3951             : 
    3952             : static const char *
    3953             : dwarf_virtuality_string (unsigned int code)
    3954             : {
    3955           0 :   static const char *const known[] =
    3956             :     {
    3957             : #define DWARF_ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
    3958             :       DWARF_ALL_KNOWN_DW_VIRTUALITY
    3959             : #undef DWARF_ONE_KNOWN_DW_VIRTUALITY
    3960             :     };
    3961             : 
    3962           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3963           0 :     return known[code];
    3964             : 
    3965             :   return NULL;
    3966             : }
    3967             : 
    3968             : 
    3969             : static const char *
    3970             : dwarf_identifier_case_string (unsigned int code)
    3971             : {
    3972           0 :   static const char *const known[] =
    3973             :     {
    3974             : #define DWARF_ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
    3975             :       DWARF_ALL_KNOWN_DW_ID
    3976             : #undef DWARF_ONE_KNOWN_DW_ID
    3977             :     };
    3978             : 
    3979           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3980           0 :     return known[code];
    3981             : 
    3982             :   return NULL;
    3983             : }
    3984             : 
    3985             : 
    3986             : static const char *
    3987             : dwarf_calling_convention_string (unsigned int code)
    3988             : {
    3989           0 :   static const char *const known[] =
    3990             :     {
    3991             : #define DWARF_ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
    3992             :       DWARF_ALL_KNOWN_DW_CC
    3993             : #undef DWARF_ONE_KNOWN_DW_CC
    3994             :     };
    3995             : 
    3996           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3997           0 :     return known[code];
    3998             : 
    3999             :   return NULL;
    4000             : }
    4001             : 
    4002             : 
    4003             : static const char *
    4004             : dwarf_ordering_string (unsigned int code)
    4005             : {
    4006           0 :   static const char *const known[] =
    4007             :     {
    4008             : #define DWARF_ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
    4009             :       DWARF_ALL_KNOWN_DW_ORD
    4010             : #undef DWARF_ONE_KNOWN_DW_ORD
    4011             :     };
    4012             : 
    4013           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    4014           0 :     return known[code];
    4015             : 
    4016             :   return NULL;
    4017             : }
    4018             : 
    4019             : 
    4020             : static const char *
    4021             : dwarf_discr_list_string (unsigned int code)
    4022             : {
    4023           8 :   static const char *const known[] =
    4024             :     {
    4025             : #define DWARF_ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
    4026             :       DWARF_ALL_KNOWN_DW_DSC
    4027             : #undef DWARF_ONE_KNOWN_DW_DSC
    4028             :     };
    4029             : 
    4030           8 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    4031           8 :     return known[code];
    4032             : 
    4033             :   return NULL;
    4034             : }
    4035             : 
    4036             : 
    4037             : static const char *
    4038             : dwarf_locexpr_opcode_string (unsigned int code)
    4039             : {
    4040      426735 :   static const char *const known[] =
    4041             :     {
    4042             :       /* Normally we can't affort building huge table of 64K entries,
    4043             :          most of them zero, just because there are a couple defined
    4044             :          values at the far end.  In case of opcodes, it's OK.  */
    4045             : #define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
    4046             :       DWARF_ALL_KNOWN_DW_OP
    4047             : #undef DWARF_ONE_KNOWN_DW_OP
    4048             :     };
    4049             : 
    4050      426735 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    4051      426735 :     return known[code];
    4052             : 
    4053             :   return NULL;
    4054             : }
    4055             : 
    4056             : 
    4057             : static const char *
    4058             : dwarf_unit_string (unsigned int type)
    4059             : {
    4060           8 :   switch (type)
    4061             :     {
    4062             : #define DWARF_ONE_KNOWN_DW_UT(NAME, CODE) case CODE: return #NAME;
    4063           7 :       DWARF_ALL_KNOWN_DW_UT
    4064             : #undef DWARF_ONE_KNOWN_DW_UT
    4065           0 :     default:
    4066           0 :       return NULL;
    4067             :     }
    4068             : }
    4069             : 
    4070             : 
    4071             : static const char *
    4072          14 : dwarf_range_list_encoding_string (unsigned int kind)
    4073             : {
    4074          14 :   switch (kind)
    4075             :     {
    4076             : #define DWARF_ONE_KNOWN_DW_RLE(NAME, CODE) case CODE: return #NAME;
    4077          12 :       DWARF_ALL_KNOWN_DW_RLE
    4078             : #undef DWARF_ONE_KNOWN_DW_RLE
    4079           0 :     default:
    4080           0 :       return NULL;
    4081             :     }
    4082             : }
    4083             : 
    4084             : 
    4085             : static const char *
    4086          89 : dwarf_loc_list_encoding_string (unsigned int kind)
    4087             : {
    4088          89 :   switch (kind)
    4089             :     {
    4090             : #define DWARF_ONE_KNOWN_DW_LLE(NAME, CODE) case CODE: return #NAME;
    4091          84 :       DWARF_ALL_KNOWN_DW_LLE
    4092             : #undef DWARF_ONE_KNOWN_DW_LLE
    4093           0 :     default:
    4094           0 :       return NULL;
    4095             :     }
    4096             : }
    4097             : 
    4098             : 
    4099             : static const char *
    4100             : dwarf_line_content_description_string (unsigned int kind)
    4101             : {
    4102           6 :   switch (kind)
    4103             :     {
    4104             : #define DWARF_ONE_KNOWN_DW_LNCT(NAME, CODE) case CODE: return #NAME;
    4105           6 :       DWARF_ALL_KNOWN_DW_LNCT
    4106             : #undef DWARF_ONE_KNOWN_DW_LNCT
    4107           0 :     default:
    4108           0 :       return NULL;
    4109             :     }
    4110             : }
    4111             : 
    4112             : 
    4113             : /* Used by all dwarf_foo_name functions.  */
    4114             : static const char *
    4115     7077738 : string_or_unknown (const char *known, unsigned int code,
    4116             :                    unsigned int lo_user, unsigned int hi_user,
    4117             :                    bool print_unknown_num)
    4118             : {
    4119     7077738 :   static char unknown_buf[20];
    4120             : 
    4121     7077738 :   if (likely (known != NULL))
    4122             :     return known;
    4123             : 
    4124           0 :   if (lo_user != 0 && code >= lo_user && code <= hi_user)
    4125             :     {
    4126           0 :       snprintf (unknown_buf, sizeof unknown_buf, "lo_user+%#x",
    4127             :                 code - lo_user);
    4128           0 :       return unknown_buf;
    4129             :     }
    4130             : 
    4131           0 :   if (print_unknown_num)
    4132             :     {
    4133           0 :       snprintf (unknown_buf, sizeof unknown_buf, "??? (%#x)", code);
    4134           0 :       return unknown_buf;
    4135             :     }
    4136             : 
    4137             :   return "???";
    4138             : }
    4139             : 
    4140             : 
    4141             : static const char *
    4142      775008 : dwarf_tag_name (unsigned int tag)
    4143             : {
    4144      775008 :   const char *ret = dwarf_tag_string (tag);
    4145      775008 :   return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true);
    4146             : }
    4147             : 
    4148             : static const char *
    4149     3140967 : dwarf_attr_name (unsigned int attr)
    4150             : {
    4151     3140967 :   const char *ret = dwarf_attr_string (attr);
    4152     3140967 :   return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true);
    4153             : }
    4154             : 
    4155             : 
    4156             : static const char *
    4157     3140973 : dwarf_form_name (unsigned int form)
    4158             : {
    4159     3140973 :   const char *ret = dwarf_form_string (form);
    4160     3140973 :   return string_or_unknown (ret, form, 0, 0, true);
    4161             : }
    4162             : 
    4163             : 
    4164             : static const char *
    4165        1162 : dwarf_lang_name (unsigned int lang)
    4166             : {
    4167        1162 :   const char *ret = dwarf_lang_string (lang);
    4168        1162 :   return string_or_unknown (ret, lang, DW_LANG_lo_user, DW_LANG_hi_user, false);
    4169             : }
    4170             : 
    4171             : 
    4172             : static const char *
    4173             : dwarf_inline_name (unsigned int code)
    4174             : {
    4175        5868 :   const char *ret = dwarf_inline_string (code);
    4176        2934 :   return string_or_unknown (ret, code, 0, 0, false);
    4177             : }
    4178             : 
    4179             : 
    4180             : static const char *
    4181             : dwarf_encoding_name (unsigned int code)
    4182             : {
    4183       33138 :   const char *ret = dwarf_encoding_string (code);
    4184       16569 :   return string_or_unknown (ret, code, DW_ATE_lo_user, DW_ATE_hi_user, false);
    4185             : }
    4186             : 
    4187             : 
    4188             : static const char *
    4189             : dwarf_access_name (unsigned int code)
    4190             : {
    4191           0 :   const char *ret = dwarf_access_string (code);
    4192           0 :   return string_or_unknown (ret, code, 0, 0, false);
    4193             : }
    4194             : 
    4195             : 
    4196             : static const char *
    4197             : dwarf_defaulted_name (unsigned int code)
    4198             : {
    4199           0 :   const char *ret = dwarf_defaulted_string (code);
    4200           0 :   return string_or_unknown (ret, code, 0, 0, false);
    4201             : }
    4202             : 
    4203             : 
    4204             : static const char *
    4205             : dwarf_visibility_name (unsigned int code)
    4206             : {
    4207           0 :   const char *ret = dwarf_visibility_string (code);
    4208           0 :   return string_or_unknown (ret, code, 0, 0, false);
    4209             : }
    4210             : 
    4211             : 
    4212             : static const char *
    4213             : dwarf_virtuality_name (unsigned int code)
    4214             : {
    4215           0 :   const char *ret = dwarf_virtuality_string (code);
    4216           0 :   return string_or_unknown (ret, code, 0, 0, false);
    4217             : }
    4218             : 
    4219             : 
    4220             : static const char *
    4221             : dwarf_identifier_case_name (unsigned int code)
    4222             : {
    4223           0 :   const char *ret = dwarf_identifier_case_string (code);
    4224           0 :   return string_or_unknown (ret, code, 0, 0, false);
    4225             : }
    4226             : 
    4227             : 
    4228             : static const char *
    4229             : dwarf_calling_convention_name (unsigned int code)
    4230             : {
    4231           0 :   const char *ret = dwarf_calling_convention_string (code);
    4232           0 :   return string_or_unknown (ret, code, DW_CC_lo_user, DW_CC_hi_user, false);
    4233             : }
    4234             : 
    4235             : 
    4236             : static const char *
    4237             : dwarf_ordering_name (unsigned int code)
    4238             : {
    4239           0 :   const char *ret = dwarf_ordering_string (code);
    4240           0 :   return string_or_unknown (ret, code, 0, 0, false);
    4241             : }
    4242             : 
    4243             : 
    4244             : static const char *
    4245             : dwarf_discr_list_name (unsigned int code)
    4246             : {
    4247          16 :   const char *ret = dwarf_discr_list_string (code);
    4248           8 :   return string_or_unknown (ret, code, 0, 0, false);
    4249             : }
    4250             : 
    4251             : 
    4252             : static const char *
    4253           8 : dwarf_unit_name (unsigned int type)
    4254             : {
    4255           8 :   const char *ret = dwarf_unit_string (type);
    4256           8 :   return string_or_unknown (ret, type, DW_UT_lo_user, DW_UT_hi_user, true);
    4257             : }
    4258             : 
    4259             : 
    4260             : static const char *
    4261          14 : dwarf_range_list_encoding_name (unsigned int kind)
    4262             : {
    4263          14 :   const char *ret = dwarf_range_list_encoding_string (kind);
    4264          14 :   return string_or_unknown (ret, kind, 0, 0, false);
    4265             : }
    4266             : 
    4267             : 
    4268             : static const char *
    4269          89 : dwarf_loc_list_encoding_name (unsigned int kind)
    4270             : {
    4271          89 :   const char *ret = dwarf_loc_list_encoding_string (kind);
    4272          89 :   return string_or_unknown (ret, kind, 0, 0, false);
    4273             : }
    4274             : 
    4275             : 
    4276             : static const char *
    4277           6 : dwarf_line_content_description_name (unsigned int kind)
    4278             : {
    4279           6 :   const char *ret = dwarf_line_content_description_string (kind);
    4280           6 :   return string_or_unknown (ret, kind, DW_LNCT_lo_user, DW_LNCT_hi_user,
    4281             :                             false);
    4282             : }
    4283             : 
    4284             : 
    4285             : static void
    4286         161 : print_block (size_t n, const void *block)
    4287             : {
    4288         161 :   if (n == 0)
    4289           0 :     puts (_("empty block"));
    4290             :   else
    4291             :     {
    4292         161 :       printf (_("%zu byte block:"), n);
    4293         161 :       const unsigned char *data = block;
    4294        2062 :       do
    4295        2062 :         printf (" %02x", *data++);
    4296        2062 :       while (--n > 0);
    4297         161 :       putchar ('\n');
    4298             :     }
    4299         161 : }
    4300             : 
    4301             : static void
    4302           0 : print_bytes (size_t n, const unsigned char *bytes)
    4303             : {
    4304           0 :   while (n-- > 0)
    4305             :     {
    4306           0 :       printf ("%02x", *bytes++);
    4307           0 :       if (n > 0)
    4308           0 :         printf (" ");
    4309             :     }
    4310           0 : }
    4311             : 
    4312             : static int
    4313          68 : get_indexed_addr (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr)
    4314             : {
    4315          68 :   if (cu == NULL)
    4316             :     return -1;
    4317             : 
    4318          68 :   Elf_Data *debug_addr = cu->dbg->sectiondata[IDX_debug_addr];
    4319          68 :   if (debug_addr == NULL)
    4320             :     return -1;
    4321             : 
    4322          68 :   Dwarf_Off base = __libdw_cu_addr_base (cu);
    4323          68 :   Dwarf_Word off = idx * cu->address_size;
    4324          68 :   if (base > debug_addr->d_size
    4325          68 :       || off > debug_addr->d_size - base
    4326          68 :       || cu->address_size > debug_addr->d_size - base - off)
    4327             :     return -1;
    4328             : 
    4329          68 :   const unsigned char *addrp = debug_addr->d_buf + base + off;
    4330          68 :   if (cu->address_size == 4)
    4331           0 :     *addr = read_4ubyte_unaligned (cu->dbg, addrp);
    4332             :   else
    4333          68 :     *addr = read_8ubyte_unaligned (cu->dbg, addrp);
    4334             : 
    4335             :   return 0;
    4336             : }
    4337             : 
    4338             : static void
    4339      294635 : print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
    4340             :            unsigned int vers, unsigned int addrsize, unsigned int offset_size,
    4341             :            struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data)
    4342             : {
    4343      294635 :   const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
    4344             : 
    4345      294635 :   if (len == 0)
    4346             :     {
    4347           0 :       printf ("%*s(empty)\n", indent, "");
    4348           0 :       return;
    4349             :     }
    4350             : 
    4351             : #define NEED(n)         if (len < (Dwarf_Word) (n)) goto invalid
    4352             : #define CONSUME(n)      NEED (n); else len -= (n)
    4353             : 
    4354             :   Dwarf_Word offset = 0;
    4355      721370 :   while (len-- > 0)
    4356             :     {
    4357      426735 :       uint_fast8_t op = *data++;
    4358             : 
    4359      426735 :       const char *op_name = dwarf_locexpr_opcode_string (op);
    4360      426735 :       if (unlikely (op_name == NULL))
    4361             :         {
    4362           0 :           static char buf[20];
    4363           0 :           if (op >= DW_OP_lo_user)
    4364           0 :             snprintf (buf, sizeof buf, "lo_user+%#x", op - DW_OP_lo_user);
    4365             :           else
    4366           0 :             snprintf (buf, sizeof buf, "??? (%#x)", op);
    4367             :           op_name = buf;
    4368             :         }
    4369             : 
    4370      426735 :       switch (op)
    4371             :         {
    4372        7420 :         case DW_OP_addr:;
    4373             :           /* Address operand.  */
    4374        7420 :           Dwarf_Word addr;
    4375        7420 :           NEED (addrsize);
    4376        7420 :           if (addrsize == 4)
    4377          24 :             addr = read_4ubyte_unaligned (dbg, data);
    4378        7396 :           else if (addrsize == 8)
    4379        7396 :             addr = read_8ubyte_unaligned (dbg, data);
    4380             :           else
    4381           0 :             goto invalid;
    4382        7420 :           data += addrsize;
    4383        7420 :           CONSUME (addrsize);
    4384             : 
    4385        7420 :           printf ("%*s[%2" PRIuMAX "] %s ",
    4386             :                   indent, "", (uintmax_t) offset, op_name);
    4387        7420 :           print_dwarf_addr (dwflmod, 0, addr, addr);
    4388        7420 :           printf ("\n");
    4389             : 
    4390        7420 :           offset += 1 + addrsize;
    4391        7420 :           break;
    4392             : 
    4393           0 :         case DW_OP_call_ref:
    4394             :         case DW_OP_GNU_variable_value:
    4395             :           /* Offset operand.  */
    4396           0 :           if (ref_size != 4 && ref_size != 8)
    4397           0 :             goto invalid; /* Cannot be used in CFA.  */
    4398           0 :           NEED (ref_size);
    4399           0 :           if (ref_size == 4)
    4400           0 :             addr = read_4ubyte_unaligned (dbg, data);
    4401             :           else
    4402           0 :             addr = read_8ubyte_unaligned (dbg, data);
    4403           0 :           data += ref_size;
    4404           0 :           CONSUME (ref_size);
    4405             :           /* addr is a DIE offset, so format it as one.  */
    4406           0 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
    4407             :                   indent, "", (uintmax_t) offset,
    4408             :                   op_name, (uintmax_t) addr);
    4409           0 :           offset += 1 + ref_size;
    4410           0 :           break;
    4411             : 
    4412       11182 :         case DW_OP_deref_size:
    4413             :         case DW_OP_xderef_size:
    4414             :         case DW_OP_pick:
    4415             :         case DW_OP_const1u:
    4416             :           // XXX value might be modified by relocation
    4417       11182 :           NEED (1);
    4418       33546 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 "\n",
    4419             :                   indent, "", (uintmax_t) offset,
    4420       11182 :                   op_name, *((uint8_t *) data));
    4421       11182 :           ++data;
    4422       11182 :           --len;
    4423       11182 :           offset += 2;
    4424       11182 :           break;
    4425             : 
    4426         971 :         case DW_OP_const2u:
    4427         971 :           NEED (2);
    4428             :           // XXX value might be modified by relocation
    4429         971 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu16 "\n",
    4430             :                   indent, "", (uintmax_t) offset,
    4431         971 :                   op_name, read_2ubyte_unaligned (dbg, data));
    4432         971 :           CONSUME (2);
    4433         971 :           data += 2;
    4434         971 :           offset += 3;
    4435         971 :           break;
    4436             : 
    4437         651 :         case DW_OP_const4u:
    4438         651 :           NEED (4);
    4439             :           // XXX value might be modified by relocation
    4440         651 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu32 "\n",
    4441             :                   indent, "", (uintmax_t) offset,
    4442         651 :                   op_name, read_4ubyte_unaligned (dbg, data));
    4443         651 :           CONSUME (4);
    4444         651 :           data += 4;
    4445         651 :           offset += 5;
    4446         651 :           break;
    4447             : 
    4448          43 :         case DW_OP_const8u:
    4449          43 :           NEED (8);
    4450             :           // XXX value might be modified by relocation
    4451          43 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
    4452             :                   indent, "", (uintmax_t) offset,
    4453          43 :                   op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
    4454          43 :           CONSUME (8);
    4455          43 :           data += 8;
    4456          43 :           offset += 9;
    4457          43 :           break;
    4458             : 
    4459        2202 :         case DW_OP_const1s:
    4460        2202 :           NEED (1);
    4461             :           // XXX value might be modified by relocation
    4462        6606 :           printf ("%*s[%2" PRIuMAX "] %s %" PRId8 "\n",
    4463             :                   indent, "", (uintmax_t) offset,
    4464        2202 :                   op_name, *((int8_t *) data));
    4465        2202 :           ++data;
    4466        2202 :           --len;
    4467        2202 :           offset += 2;
    4468        2202 :           break;
    4469             : 
    4470           3 :         case DW_OP_const2s:
    4471           3 :           NEED (2);
    4472             :           // XXX value might be modified by relocation
    4473           3 :           printf ("%*s[%2" PRIuMAX "] %s %" PRId16 "\n",
    4474             :                   indent, "", (uintmax_t) offset,
    4475           3 :                   op_name, read_2sbyte_unaligned (dbg, data));
    4476           3 :           CONSUME (2);
    4477           3 :           data += 2;
    4478           3 :           offset += 3;
    4479           3 :           break;
    4480             : 
    4481           0 :         case DW_OP_const4s:
    4482           0 :           NEED (4);
    4483             :           // XXX value might be modified by relocation
    4484           0 :           printf ("%*s[%2" PRIuMAX "] %s %" PRId32 "\n",
    4485             :                   indent, "", (uintmax_t) offset,
    4486           0 :                   op_name, read_4sbyte_unaligned (dbg, data));
    4487           0 :           CONSUME (4);
    4488           0 :           data += 4;
    4489           0 :           offset += 5;
    4490           0 :           break;
    4491             : 
    4492           0 :         case DW_OP_const8s:
    4493           0 :           NEED (8);
    4494             :           // XXX value might be modified by relocation
    4495           0 :           printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
    4496             :                   indent, "", (uintmax_t) offset,
    4497           0 :                   op_name, read_8sbyte_unaligned (dbg, data));
    4498           0 :           CONSUME (8);
    4499           0 :           data += 8;
    4500           0 :           offset += 9;
    4501           0 :           break;
    4502             : 
    4503        9514 :         case DW_OP_piece:
    4504             :         case DW_OP_regx:
    4505             :         case DW_OP_plus_uconst:
    4506        9514 :         case DW_OP_constu:;
    4507        9514 :           const unsigned char *start = data;
    4508        9514 :           uint64_t uleb;
    4509        9514 :           NEED (1);
    4510        9514 :           get_uleb128 (uleb, data, data + len);
    4511        9514 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
    4512             :                   indent, "", (uintmax_t) offset, op_name, uleb);
    4513        9514 :           CONSUME (data - start);
    4514        9514 :           offset += 1 + (data - start);
    4515        9514 :           break;
    4516             : 
    4517           2 :         case DW_OP_addrx:
    4518             :         case DW_OP_GNU_addr_index:
    4519             :         case DW_OP_constx:
    4520           2 :         case DW_OP_GNU_const_index:;
    4521           2 :           start = data;
    4522           2 :           NEED (1);
    4523           2 :           get_uleb128 (uleb, data, data + len);
    4524           2 :           printf ("%*s[%2" PRIuMAX "] %s [%" PRIu64 "] ",
    4525             :                   indent, "", (uintmax_t) offset, op_name, uleb);
    4526           2 :           CONSUME (data - start);
    4527           2 :           offset += 1 + (data - start);
    4528           2 :           if (get_indexed_addr (cu, uleb, &addr) != 0)
    4529           0 :             printf ("???\n");
    4530             :           else
    4531             :             {
    4532           2 :               print_dwarf_addr (dwflmod, 0, addr, addr);
    4533           2 :               printf ("\n");
    4534             :             }
    4535             :           break;
    4536             : 
    4537           4 :         case DW_OP_bit_piece:
    4538           4 :           start = data;
    4539           4 :           uint64_t uleb2;
    4540           4 :           NEED (1);
    4541           4 :           get_uleb128 (uleb, data, data + len);
    4542           4 :           NEED (1);
    4543           4 :           get_uleb128 (uleb2, data, data + len);
    4544           4 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
    4545             :                   indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
    4546           4 :           CONSUME (data - start);
    4547           4 :           offset += 1 + (data - start);
    4548           4 :           break;
    4549             : 
    4550       75317 :         case DW_OP_fbreg:
    4551             :         case DW_OP_breg0 ... DW_OP_breg31:
    4552             :         case DW_OP_consts:
    4553       75317 :           start = data;
    4554       75317 :           int64_t sleb;
    4555       75317 :           NEED (1);
    4556       75317 :           get_sleb128 (sleb, data, data + len);
    4557       75317 :           printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
    4558             :                   indent, "", (uintmax_t) offset, op_name, sleb);
    4559       75317 :           CONSUME (data - start);
    4560       75317 :           offset += 1 + (data - start);
    4561       75317 :           break;
    4562             : 
    4563           0 :         case DW_OP_bregx:
    4564           0 :           start = data;
    4565           0 :           NEED (1);
    4566           0 :           get_uleb128 (uleb, data, data + len);
    4567           0 :           NEED (1);
    4568           0 :           get_sleb128 (sleb, data, data + len);
    4569           0 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
    4570             :                   indent, "", (uintmax_t) offset, op_name, uleb, sleb);
    4571           0 :           CONSUME (data - start);
    4572           0 :           offset += 1 + (data - start);
    4573           0 :           break;
    4574             : 
    4575           0 :         case DW_OP_call2:
    4576           0 :           NEED (2);
    4577           0 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx16 "]\n",
    4578             :                   indent, "", (uintmax_t) offset, op_name,
    4579           0 :                   read_2ubyte_unaligned (dbg, data));
    4580           0 :           CONSUME (2);
    4581           0 :           data += 2;
    4582           0 :           offset += 3;
    4583           0 :           break;
    4584             : 
    4585           4 :         case DW_OP_call4:
    4586           4 :           NEED (4);
    4587           4 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx32 "]\n",
    4588             :                   indent, "", (uintmax_t) offset, op_name,
    4589           4 :                   read_4ubyte_unaligned (dbg, data));
    4590           4 :           CONSUME (4);
    4591           4 :           data += 4;
    4592           4 :           offset += 5;
    4593           4 :           break;
    4594             : 
    4595         421 :         case DW_OP_skip:
    4596             :         case DW_OP_bra:
    4597         421 :           NEED (2);
    4598        1263 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIuMAX "\n",
    4599             :                   indent, "", (uintmax_t) offset, op_name,
    4600         421 :                   (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
    4601         421 :           CONSUME (2);
    4602         421 :           data += 2;
    4603         421 :           offset += 3;
    4604         421 :           break;
    4605             : 
    4606         156 :         case DW_OP_implicit_value:
    4607         156 :           start = data;
    4608         156 :           NEED (1);
    4609         156 :           get_uleb128 (uleb, data, data + len);
    4610         156 :           printf ("%*s[%2" PRIuMAX "] %s: ",
    4611             :                   indent, "", (uintmax_t) offset, op_name);
    4612         156 :           NEED (uleb);
    4613         156 :           print_block (uleb, data);
    4614         156 :           data += uleb;
    4615         156 :           CONSUME (data - start);
    4616         156 :           offset += 1 + (data - start);
    4617         156 :           break;
    4618             : 
    4619        3850 :         case DW_OP_implicit_pointer:
    4620             :         case DW_OP_GNU_implicit_pointer:
    4621             :           /* DIE offset operand.  */
    4622        3850 :           start = data;
    4623        3850 :           NEED (ref_size);
    4624        3850 :           if (ref_size != 4 && ref_size != 8)
    4625           0 :             goto invalid; /* Cannot be used in CFA.  */
    4626        3850 :           if (ref_size == 4)
    4627        3850 :             addr = read_4ubyte_unaligned (dbg, data);
    4628             :           else
    4629           0 :             addr = read_8ubyte_unaligned (dbg, data);
    4630        3850 :           data += ref_size;
    4631             :           /* Byte offset operand.  */
    4632        3850 :           NEED (1);
    4633        3850 :           get_sleb128 (sleb, data, data + len);
    4634             : 
    4635        3850 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
    4636             :                   indent, "", (intmax_t) offset,
    4637             :                   op_name, (uintmax_t) addr, sleb);
    4638        3850 :           CONSUME (data - start);
    4639        3850 :           offset += 1 + (data - start);
    4640        3850 :           break;
    4641             : 
    4642       22663 :         case DW_OP_entry_value:
    4643             :         case DW_OP_GNU_entry_value:
    4644             :           /* Size plus expression block.  */
    4645       22663 :           start = data;
    4646       22663 :           NEED (1);
    4647       22663 :           get_uleb128 (uleb, data, data + len);
    4648       22663 :           printf ("%*s[%2" PRIuMAX "] %s:\n",
    4649             :                   indent, "", (uintmax_t) offset, op_name);
    4650       22663 :           NEED (uleb);
    4651       22663 :           print_ops (dwflmod, dbg, indent + 5, indent + 5, vers,
    4652             :                      addrsize, offset_size, cu, uleb, data);
    4653       22663 :           data += uleb;
    4654       22663 :           CONSUME (data - start);
    4655       22663 :           offset += 1 + (data - start);
    4656       22663 :           break;
    4657             : 
    4658           1 :         case DW_OP_const_type:
    4659             :         case DW_OP_GNU_const_type:
    4660             :           /* uleb128 CU relative DW_TAG_base_type DIE offset, 1-byte
    4661             :              unsigned size plus block.  */
    4662           1 :           start = data;
    4663           1 :           NEED (1);
    4664           1 :           get_uleb128 (uleb, data, data + len);
    4665           1 :           if (! print_unresolved_addresses && cu != NULL)
    4666           1 :             uleb += cu->start;
    4667           1 :           NEED (1);
    4668           1 :           uint8_t usize = *(uint8_t *) data++;
    4669           1 :           NEED (usize);
    4670           1 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] ",
    4671             :                   indent, "", (uintmax_t) offset, op_name, uleb);
    4672           1 :           print_block (usize, data);
    4673           1 :           data += usize;
    4674           1 :           CONSUME (data - start);
    4675           1 :           offset += 1 + (data - start);
    4676           1 :           break;
    4677             : 
    4678           0 :         case DW_OP_regval_type:
    4679             :         case DW_OP_GNU_regval_type:
    4680             :           /* uleb128 register number, uleb128 CU relative
    4681             :              DW_TAG_base_type DIE offset.  */
    4682           0 :           start = data;
    4683           0 :           NEED (1);
    4684           0 :           get_uleb128 (uleb, data, data + len);
    4685           0 :           NEED (1);
    4686           0 :           get_uleb128 (uleb2, data, data + len);
    4687           0 :           if (! print_unresolved_addresses && cu != NULL)
    4688           0 :             uleb2 += cu->start;
    4689           0 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
    4690             :                   indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
    4691           0 :           CONSUME (data - start);
    4692           0 :           offset += 1 + (data - start);
    4693           0 :           break;
    4694             : 
    4695           6 :         case DW_OP_deref_type:
    4696             :         case DW_OP_GNU_deref_type:
    4697             :           /* 1-byte unsigned size of value, uleb128 CU relative
    4698             :              DW_TAG_base_type DIE offset.  */
    4699           6 :           start = data;
    4700           6 :           NEED (1);
    4701           6 :           usize = *(uint8_t *) data++;
    4702           6 :           NEED (1);
    4703           6 :           get_uleb128 (uleb, data, data + len);
    4704           6 :           if (! print_unresolved_addresses && cu != NULL)
    4705           6 :             uleb += cu->start;
    4706           6 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
    4707             :                   indent, "", (uintmax_t) offset,
    4708             :                   op_name, usize, uleb);
    4709           6 :           CONSUME (data - start);
    4710           6 :           offset += 1 + (data - start);
    4711           6 :           break;
    4712             : 
    4713           0 :         case DW_OP_xderef_type:
    4714             :           /* 1-byte unsigned size of value, uleb128 base_type DIE offset.  */
    4715           0 :           start = data;
    4716           0 :           NEED (1);
    4717           0 :           usize = *(uint8_t *) data++;
    4718           0 :           NEED (1);
    4719           0 :           get_uleb128 (uleb, data, data + len);
    4720           0 :           printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
    4721             :                   indent, "", (uintmax_t) offset,
    4722             :                   op_name, usize, uleb);
    4723           0 :           CONSUME (data - start);
    4724           0 :           offset += 1 + (data - start);
    4725           0 :           break;
    4726             : 
    4727         342 :         case DW_OP_convert:
    4728             :         case DW_OP_GNU_convert:
    4729             :         case DW_OP_reinterpret:
    4730             :         case DW_OP_GNU_reinterpret:
    4731             :           /* uleb128 CU relative offset to DW_TAG_base_type, or zero
    4732             :              for conversion to untyped.  */
    4733         342 :           start = data;
    4734         342 :           NEED (1);
    4735         342 :           get_uleb128 (uleb, data, data + len);
    4736         342 :           if (uleb != 0 && ! print_unresolved_addresses && cu != NULL)
    4737         229 :             uleb += cu->start;
    4738         342 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
    4739             :                   indent, "", (uintmax_t) offset, op_name, uleb);
    4740         342 :           CONSUME (data - start);
    4741         342 :           offset += 1 + (data - start);
    4742         342 :           break;
    4743             : 
    4744          21 :         case DW_OP_GNU_parameter_ref:
    4745             :           /* 4 byte CU relative reference to the abstract optimized away
    4746             :              DW_TAG_formal_parameter.  */
    4747          21 :           NEED (4);
    4748          21 :           uintmax_t param_off = (uintmax_t) read_4ubyte_unaligned (dbg, data);
    4749          21 :           if (! print_unresolved_addresses && cu != NULL)
    4750          21 :             param_off += cu->start;
    4751          21 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
    4752             :                   indent, "", (uintmax_t) offset, op_name, param_off);
    4753          21 :           CONSUME (4);
    4754          21 :           data += 4;
    4755          21 :           offset += 5;
    4756          21 :           break;
    4757             : 
    4758             :         default:
    4759             :           /* No Operand.  */
    4760      291962 :           printf ("%*s[%2" PRIuMAX "] %s\n",
    4761             :                   indent, "", (uintmax_t) offset, op_name);
    4762      291962 :           ++offset;
    4763      291962 :           break;
    4764             :         }
    4765             : 
    4766      426735 :       indent = indentrest;
    4767      426735 :       continue;
    4768             : 
    4769           0 :     invalid:
    4770           0 :       printf (gettext ("%*s[%2" PRIuMAX "] %s  <TRUNCATED>\n"),
    4771             :               indent, "", (uintmax_t) offset, op_name);
    4772             :       break;
    4773             :     }
    4774             : }
    4775             : 
    4776             : 
    4777             : struct listptr
    4778             : {
    4779             :   Dwarf_Off offset:(64 - 3);
    4780             :   bool addr64:1;
    4781             :   bool dwarf64:1;
    4782             :   bool warned:1;
    4783             :   struct Dwarf_CU *cu;
    4784             :   unsigned int attr;
    4785             : };
    4786             : 
    4787             : #define listptr_offset_size(p)  ((p)->dwarf64 ? 8 : 4)
    4788             : #define listptr_address_size(p) ((p)->addr64 ? 8 : 4)
    4789             : 
    4790             : static Dwarf_Addr
    4791      104845 : cudie_base (Dwarf_Die *cudie)
    4792             : {
    4793      104845 :   Dwarf_Addr base;
    4794             :   /* Find the base address of the compilation unit.  It will normally
    4795             :      be specified by DW_AT_low_pc.  In DWARF-3 draft 4, the base
    4796             :      address could be overridden by DW_AT_entry_pc.  It's been
    4797             :      removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc for
    4798             :      compilation units with discontinuous ranges.  */
    4799      104845 :   if (unlikely (dwarf_lowpc (cudie, &base) != 0))
    4800             :     {
    4801           0 :       Dwarf_Attribute attr_mem;
    4802           0 :       if (dwarf_formaddr (dwarf_attr (cudie, DW_AT_entry_pc, &attr_mem),
    4803             :                           &base) != 0)
    4804           0 :         base = 0;
    4805             :     }
    4806      104845 :   return base;
    4807             : }
    4808             : 
    4809             : static Dwarf_Addr
    4810           0 : listptr_base (struct listptr *p)
    4811             : {
    4812           0 :   Dwarf_Die cu = CUDIE (p->cu);
    4813           0 :   return cudie_base (&cu);
    4814             : }
    4815             : 
    4816             : static int
    4817      682078 : compare_listptr (const void *a, const void *b, void *arg)
    4818             : {
    4819      682078 :   const char *name = arg;
    4820      682078 :   struct listptr *p1 = (void *) a;
    4821      682078 :   struct listptr *p2 = (void *) b;
    4822             : 
    4823      682078 :   if (p1->offset < p2->offset)
    4824             :     return -1;
    4825       68032 :   if (p1->offset > p2->offset)
    4826             :     return 1;
    4827             : 
    4828        3670 :   if (!p1->warned && !p2->warned)
    4829             :     {
    4830        3670 :       if (p1->addr64 != p2->addr64)
    4831             :         {
    4832           0 :           p1->warned = p2->warned = true;
    4833           0 :           error (0, 0,
    4834           0 :                  gettext ("%s %#" PRIx64 " used with different address sizes"),
    4835             :                  name, (uint64_t) p1->offset);
    4836             :         }
    4837        3670 :       if (p1->dwarf64 != p2->dwarf64)
    4838             :         {
    4839           0 :           p1->warned = p2->warned = true;
    4840           0 :           error (0, 0,
    4841           0 :                  gettext ("%s %#" PRIx64 " used with different offset sizes"),
    4842           0 :                  name, (uint64_t) p1->offset);
    4843             :         }
    4844        3670 :       if (listptr_base (p1) != listptr_base (p2))
    4845             :         {
    4846           0 :           p1->warned = p2->warned = true;
    4847           0 :           error (0, 0,
    4848           0 :                  gettext ("%s %#" PRIx64 " used with different base addresses"),
    4849           0 :                  name, (uint64_t) p1->offset);
    4850             :         }
    4851        3670 :       if (p1->attr != p2 ->attr)
    4852             :         {
    4853           0 :           p1->warned = p2->warned = true;
    4854           0 :           error (0, 0,
    4855           0 :                  gettext ("%s %#" PRIx64
    4856             :                           " used with different attribute %s and %s"),
    4857           0 :                  name, (uint64_t) p1->offset, dwarf_attr_name (p2->attr),
    4858             :                  dwarf_attr_name (p2->attr));
    4859             :         }
    4860             :     }
    4861             : 
    4862             :   return 0;
    4863             : }
    4864             : 
    4865             : struct listptr_table
    4866             : {
    4867             :   size_t n;
    4868             :   size_t alloc;
    4869             :   struct listptr *table;
    4870             : };
    4871             : 
    4872             : static struct listptr_table known_locsptr;
    4873             : static struct listptr_table known_loclistsptr;
    4874             : static struct listptr_table known_rangelistptr;
    4875             : static struct listptr_table known_rnglistptr;
    4876             : static struct listptr_table known_addrbases;
    4877             : static struct listptr_table known_stroffbases;
    4878             : 
    4879             : static void
    4880             : reset_listptr (struct listptr_table *table)
    4881             : {
    4882         906 :   free (table->table);
    4883         906 :   table->table = NULL;
    4884         906 :   table->n = table->alloc = 0;
    4885             : }
    4886             : 
    4887             : /* Returns false if offset doesn't fit.  See struct listptr.  */
    4888             : static bool
    4889      101211 : notice_listptr (enum section_e section, struct listptr_table *table,
    4890             :                 uint_fast8_t address_size, uint_fast8_t offset_size,
    4891             :                 struct Dwarf_CU *cu, Dwarf_Off offset, unsigned int attr)
    4892             : {
    4893      101211 :   if (print_debug_sections & section)
    4894             :     {
    4895      101110 :       if (table->n == table->alloc)
    4896             :         {
    4897         203 :           if (table->alloc == 0)
    4898          83 :             table->alloc = 128;
    4899             :           else
    4900         120 :             table->alloc *= 2;
    4901         203 :           table->table = xrealloc (table->table,
    4902         203 :                                    table->alloc * sizeof table->table[0]);
    4903             :         }
    4904             : 
    4905      101110 :       struct listptr *p = &table->table[table->n++];
    4906             : 
    4907      202220 :       *p = (struct listptr)
    4908             :         {
    4909      101110 :           .addr64 = address_size == 8,
    4910      101110 :           .dwarf64 = offset_size == 8,
    4911             :           .offset = offset,
    4912             :           .cu = cu,
    4913             :           .attr = attr
    4914             :         };
    4915             : 
    4916      101110 :       if (p->offset != offset)
    4917             :         {
    4918           0 :           table->n--;
    4919           0 :           return false;
    4920             :         }
    4921             :     }
    4922             :   return true;
    4923             : }
    4924             : 
    4925             : static void
    4926           0 : sort_listptr (struct listptr_table *table, const char *name)
    4927             : {
    4928           0 :   if (table->n > 0)
    4929          83 :     qsort_r (table->table, table->n, sizeof table->table[0],
    4930             :              &compare_listptr, (void *) name);
    4931           0 : }
    4932             : 
    4933             : static bool
    4934           0 : skip_listptr_hole (struct listptr_table *table, size_t *idxp,
    4935             :                    uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
    4936             :                    Dwarf_Addr *base, struct Dwarf_CU **cu, ptrdiff_t offset,
    4937             :                    unsigned char **readp, unsigned char *endp,
    4938             :                    unsigned int *attr)
    4939             : {
    4940           0 :   if (table->n == 0)
    4941           0 :     return false;
    4942             : 
    4943           0 :   while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
    4944           0 :     ++*idxp;
    4945             : 
    4946           0 :   struct listptr *p = &table->table[*idxp];
    4947             : 
    4948           0 :   if (*idxp == table->n
    4949           0 :       || p->offset >= (Dwarf_Off) (endp - *readp + offset))
    4950             :     {
    4951           0 :       *readp = endp;
    4952           0 :       printf (gettext (" [%6tx]  <UNUSED GARBAGE IN REST OF SECTION>\n"),
    4953             :               offset);
    4954           0 :       return true;
    4955             :     }
    4956             : 
    4957           0 :   if (p->offset != (Dwarf_Off) offset)
    4958             :     {
    4959           0 :       *readp += p->offset - offset;
    4960           0 :       printf (gettext (" [%6tx]  <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
    4961             :               offset, (Dwarf_Off) p->offset - offset);
    4962           0 :       return true;
    4963             :     }
    4964             : 
    4965           0 :   if (address_sizep != NULL)
    4966           0 :     *address_sizep = listptr_address_size (p);
    4967           0 :   if (offset_sizep != NULL)
    4968           0 :     *offset_sizep = listptr_offset_size (p);
    4969           0 :   if (base != NULL)
    4970           0 :     *base = listptr_base (p);
    4971           0 :   if (cu != NULL)
    4972           0 :     *cu = p->cu;
    4973           0 :   if (attr != NULL)
    4974           0 :     *attr = p->attr;
    4975             : 
    4976             :   return false;
    4977             : }
    4978             : 
    4979             : static Dwarf_Off
    4980           0 : next_listptr_offset (struct listptr_table *table, size_t idx)
    4981             : {
    4982             :   /* Note that multiple attributes could in theory point to the same loclist
    4983             :      offset, so make sure we pick one that is bigger than the current one.
    4984             :      The table is sorted on offset.  */
    4985       43054 :   Dwarf_Off offset = table->table[idx].offset;
    4986       43837 :   while (++idx < table->n)
    4987             :     {
    4988       43837 :       Dwarf_Off next = table->table[idx].offset;
    4989       43837 :       if (next > offset)
    4990           0 :         return next;
    4991             :     }
    4992             :   return 0;
    4993             : }
    4994             : 
    4995             : /* Returns the listptr associated with the given index, or NULL.  */
    4996             : static struct listptr *
    4997           0 : get_listptr (struct listptr_table *table, size_t idx)
    4998             : {
    4999           0 :   if (idx >= table->n)
    5000           0 :     return NULL;
    5001           0 :   return &table->table[idx];
    5002             : }
    5003             : 
    5004             : /* Returns the next index, base address and CU associated with the
    5005             :    list unit offsets.  If there is none false is returned, otherwise
    5006             :    true.  Assumes the table has been sorted.  */
    5007             : static bool
    5008           0 : listptr_cu (struct listptr_table *table, size_t *idxp,
    5009             :             Dwarf_Off start, Dwarf_Off end,
    5010             :             Dwarf_Addr *base, struct Dwarf_CU **cu)
    5011             : {
    5012           0 :   while (*idxp < table->n
    5013           0 :          && table->table[*idxp].offset < start)
    5014           0 :     ++*idxp;
    5015             : 
    5016           0 :   if (*idxp < table->n
    5017           0 :       && table->table[*idxp].offset >= start
    5018           0 :       && table->table[*idxp].offset < end)
    5019             :     {
    5020           0 :       struct listptr *p = &table->table[*idxp];
    5021           0 :       *base = listptr_base (p);
    5022           0 :       *cu = p->cu;
    5023           0 :       ++*idxp;
    5024           0 :       return true;
    5025             :     }
    5026             : 
    5027             :   return false;
    5028             : }
    5029             : 
    5030             : static void
    5031          42 : print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
    5032             :                             Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
    5033             :                             Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    5034             : {
    5035          84 :   const size_t sh_size = (dbg->sectiondata[IDX_debug_abbrev] ?
    5036          42 :                           dbg->sectiondata[IDX_debug_abbrev]->d_size : 0);
    5037             : 
    5038          42 :   printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
    5039             :                    " [ Code]\n"),
    5040             :           elf_ndxscn (scn), section_name (ebl, shdr),
    5041          42 :           (uint64_t) shdr->sh_offset);
    5042             : 
    5043          42 :   Dwarf_Off offset = 0;
    5044        1137 :   while (offset < sh_size)
    5045             :     {
    5046        1095 :       printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
    5047             :               offset);
    5048             : 
    5049       57787 :       while (1)
    5050       56692 :         {
    5051       57787 :           size_t length;
    5052       57787 :           Dwarf_Abbrev abbrev;
    5053             : 
    5054       57787 :           int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
    5055       57787 :           if (res != 0)
    5056             :             {
    5057        1095 :               if (unlikely (res < 0))
    5058             :                 {
    5059           0 :                   printf (gettext ("\
    5060             :  *** error while reading abbreviation: %s\n"),
    5061             :                           dwarf_errmsg (-1));
    5062           0 :                   return;
    5063             :                 }
    5064             : 
    5065             :               /* This is the NUL byte at the end of the section.  */
    5066        1095 :               ++offset;
    5067        1095 :               break;
    5068             :             }
    5069             : 
    5070             :           /* We know these calls can never fail.  */
    5071       56692 :           unsigned int code = dwarf_getabbrevcode (&abbrev);
    5072       56692 :           unsigned int tag = dwarf_getabbrevtag (&abbrev);
    5073       56692 :           int has_children = dwarf_abbrevhaschildren (&abbrev);
    5074             : 
    5075       56692 :           printf (gettext (" [%5u] offset: %" PRId64
    5076             :                            ", children: %s, tag: %s\n"),
    5077             :                   code, (int64_t) offset,
    5078             :                   has_children ? yes_str : no_str,
    5079             :                   dwarf_tag_name (tag));
    5080             : 
    5081       56692 :           size_t cnt = 0;
    5082       56692 :           unsigned int name;
    5083       56692 :           unsigned int form;
    5084       56692 :           Dwarf_Sword data;
    5085       56692 :           Dwarf_Off enoffset;
    5086      312292 :           while (dwarf_getabbrevattr_data (&abbrev, cnt, &name, &form,
    5087             :                                            &data, &enoffset) == 0)
    5088             :             {
    5089      255600 :               printf ("          attr: %s, form: %s",
    5090             :                       dwarf_attr_name (name), dwarf_form_name (form));
    5091      255600 :               if (form == DW_FORM_implicit_const)
    5092           0 :                 printf (" (%" PRId64 ")", data);
    5093      255600 :               printf (", offset: %#" PRIx64 "\n", (uint64_t) enoffset);
    5094      255600 :               ++cnt;
    5095             :             }
    5096             : 
    5097       56692 :           offset += length;
    5098             :         }
    5099             :     }
    5100             : }
    5101             : 
    5102             : 
    5103             : static void
    5104           2 : print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
    5105             :                           Ebl *ebl, GElf_Ehdr *ehdr,
    5106             :                           Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    5107             : {
    5108           2 :   printf (gettext ("\
    5109             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    5110             :           elf_ndxscn (scn), section_name (ebl, shdr),
    5111           2 :           (uint64_t) shdr->sh_offset);
    5112             : 
    5113           2 :   if (shdr->sh_size == 0)
    5114             :     return;
    5115             : 
    5116             :   /* We like to get the section from libdw to make sure they are relocated.  */
    5117           4 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_addr]
    5118           2 :                     ?: elf_rawdata (scn, NULL));
    5119           2 :   if (unlikely (data == NULL))
    5120             :     {
    5121           0 :       error (0, 0, gettext ("cannot get .debug_addr section data: %s"),
    5122             :              elf_errmsg (-1));
    5123           0 :       return;
    5124             :     }
    5125             : 
    5126           2 :   size_t idx = 0;
    5127           2 :   sort_listptr (&known_addrbases, "addr_base");
    5128             : 
    5129           2 :   const unsigned char *start = (const unsigned char *) data->d_buf;
    5130           2 :   const unsigned char *readp = start;
    5131           4 :   const unsigned char *readendp = ((const unsigned char *) data->d_buf
    5132           2 :                                    + data->d_size);
    5133             : 
    5134           6 :   while (readp < readendp)
    5135             :     {
    5136             :       /* We cannot really know whether or not there is an header.  The
    5137             :          DebugFission extension to DWARF4 doesn't add one.  The DWARF5
    5138             :          .debug_addr variant does.  Whether or not we have an header,
    5139             :          DW_AT_[GNU_]addr_base points at "index 0".  So if the current
    5140             :          offset equals the CU addr_base then we can just start
    5141             :          printing addresses.  If there is no CU with an exact match
    5142             :          then we'll try to parse the header first.  */
    5143           8 :       Dwarf_Off off = (Dwarf_Off) (readp
    5144           4 :                                    - (const unsigned char *) data->d_buf);
    5145             : 
    5146           4 :       printf ("Table at offset %" PRIx64 " ", off);
    5147             : 
    5148           4 :       struct listptr *listptr = get_listptr (&known_addrbases, idx++);
    5149           4 :       const unsigned char *next_unitp;
    5150             : 
    5151           4 :       uint64_t unit_length;
    5152           4 :       uint16_t version;
    5153           4 :       uint8_t address_size;
    5154           4 :       uint8_t segment_size;
    5155           4 :       if (listptr == NULL)
    5156             :         {
    5157           0 :           error (0, 0, "Warning: No CU references .debug_addr after %" PRIx64,
    5158             :                  off);
    5159             : 
    5160             :           /* We will have to assume it is just addresses to the end... */
    5161           0 :           address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    5162           0 :           next_unitp = readendp;
    5163           0 :           printf ("Unknown CU:\n");
    5164             :         }
    5165             :       else
    5166             :         {
    5167           4 :           Dwarf_Die cudie;
    5168           4 :           if (dwarf_cu_die (listptr->cu, &cudie,
    5169             :                             NULL, NULL, NULL, NULL,
    5170             :                             NULL, NULL) == NULL)
    5171           0 :             printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
    5172             :           else
    5173           4 :             printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
    5174             : 
    5175           4 :           if (listptr->offset == off)
    5176             :             {
    5177           2 :               address_size = listptr_address_size (listptr);
    5178           2 :               segment_size = 0;
    5179           2 :               version = 4;
    5180             : 
    5181             :               /* The addresses start here, but where do they end?  */
    5182           2 :               listptr = get_listptr (&known_addrbases, idx);
    5183           1 :               if (listptr == NULL)
    5184             :                 next_unitp = readendp;
    5185           1 :               else if (listptr->cu->version < 5)
    5186             :                 {
    5187           1 :                   next_unitp = start + listptr->offset;
    5188           1 :                   if (listptr->offset < off || listptr->offset > data->d_size)
    5189             :                     {
    5190           0 :                       error (0, 0,
    5191             :                              "Warning: Bad address base for next unit at %"
    5192             :                              PRIx64, off);
    5193           0 :                       next_unitp = readendp;
    5194             :                     }
    5195             :                 }
    5196             :               else
    5197             :                 {
    5198             :                   /* Tricky, we don't have a header for this unit, but
    5199             :                      there is one for the next.  We will have to
    5200             :                      "guess" how big it is and subtract it from the
    5201             :                      offset (because that points after the header).  */
    5202           0 :                   unsigned int offset_size = listptr_offset_size (listptr);
    5203           0 :                   Dwarf_Off next_off = (listptr->offset
    5204           0 :                                         - (offset_size == 4 ? 4 : 12) /* len */
    5205             :                                         - 2 /* version */
    5206             :                                         - 1 /* address size */
    5207           0 :                                         - 1); /* segment selector size */
    5208           0 :                   next_unitp = start + next_off;
    5209           0 :                   if (next_off < off || next_off > data->d_size)
    5210             :                     {
    5211           0 :                       error (0, 0,
    5212             :                              "Warning: Couldn't calculate .debug_addr "
    5213             :                              " unit lenght at %" PRIx64, off);
    5214           0 :                       next_unitp = readendp;
    5215             :                     }
    5216             :                 }
    5217           2 :               unit_length = (uint64_t) (next_unitp - readp);
    5218             : 
    5219             :               /* Pretend we have a header.  */
    5220           2 :               printf ("\n");
    5221           2 :               printf (gettext (" Length:         %8" PRIu64 "\n"),
    5222             :                       unit_length);
    5223           2 :               printf (gettext (" DWARF version:  %8" PRIu16 "\n"), version);
    5224           2 :               printf (gettext (" Address size:   %8" PRIu64 "\n"),
    5225             :                       (uint64_t) address_size);
    5226           2 :               printf (gettext (" Segment size:   %8" PRIu64 "\n"),
    5227             :                       (uint64_t) segment_size);
    5228           2 :               printf ("\n");
    5229             :             }
    5230             :           else
    5231             :             {
    5232             :               /* OK, we have to parse an header first.  */
    5233           2 :               unit_length = read_4ubyte_unaligned_inc (dbg, readp);
    5234           2 :               if (unlikely (unit_length == 0xffffffff))
    5235             :                 {
    5236           0 :                   if (unlikely (readp > readendp - 8))
    5237             :                     {
    5238           0 :                     invalid_data:
    5239           0 :                       error (0, 0, "Invalid data");
    5240           0 :                       return;
    5241             :                     }
    5242           0 :                   unit_length = read_8ubyte_unaligned_inc (dbg, readp);
    5243             :                 }
    5244           2 :               printf ("\n");
    5245           2 :               printf (gettext (" Length:         %8" PRIu64 "\n"),
    5246             :                       unit_length);
    5247             : 
    5248             :               /* We need at least 2-bytes (version) + 1-byte
    5249             :                  (addr_size) + 1-byte (segment_size) = 4 bytes to
    5250             :                  complete the header.  And this unit cannot go beyond
    5251             :                  the section data.  */
    5252           2 :               if (readp > readendp - 4
    5253           2 :                   || unit_length < 4
    5254           2 :                   || unit_length > (uint64_t) (readendp - readp))
    5255             :                 goto invalid_data;
    5256             : 
    5257           2 :               next_unitp = readp + unit_length;
    5258             : 
    5259           2 :               version = read_2ubyte_unaligned_inc (dbg, readp);
    5260           2 :               printf (gettext (" DWARF version:  %8" PRIu16 "\n"), version);
    5261             : 
    5262           2 :               if (version != 5)
    5263             :                 {
    5264           0 :                   error (0, 0, gettext ("Unknown version"));
    5265           0 :                   goto next_unit;
    5266             :                 }
    5267             : 
    5268           2 :               address_size = *readp++;
    5269           2 :               printf (gettext (" Address size:   %8" PRIu64 "\n"),
    5270             :                       (uint64_t) address_size);
    5271             : 
    5272           2 :               if (address_size != 4 && address_size != 8)
    5273             :                 {
    5274           0 :                   error (0, 0, gettext ("unsupported address size"));
    5275           0 :                   goto next_unit;
    5276             :                 }
    5277             : 
    5278           2 :               segment_size = *readp++;
    5279           2 :               printf (gettext (" Segment size:   %8" PRIu64 "\n"),
    5280             :                       (uint64_t) segment_size);
    5281           2 :               printf ("\n");
    5282             : 
    5283           2 :               if (segment_size != 0)
    5284             :                 {
    5285           0 :                   error (0, 0, gettext ("unsupported segment size"));
    5286           0 :                   goto next_unit;
    5287             :                 }
    5288             : 
    5289           2 :               if (listptr->offset != (Dwarf_Off) (readp - start))
    5290             :                 {
    5291           0 :                   error (0, 0, "Address index doesn't start after header");
    5292           0 :                   goto next_unit;
    5293             :                 }
    5294             :             }
    5295             :         }
    5296             : 
    5297           4 :       int digits = 1;
    5298           4 :       size_t addresses = (next_unitp - readp) / address_size;
    5299           8 :       while (addresses >= 10)
    5300             :         {
    5301           4 :           ++digits;
    5302           4 :           addresses /= 10;
    5303             :         }
    5304             : 
    5305           4 :       unsigned int uidx = 0;
    5306           4 :       size_t index_offset =  readp - (const unsigned char *) data->d_buf;
    5307           4 :       printf (" Addresses start at offset 0x%zx:\n", index_offset);
    5308          76 :       while (readp <= next_unitp - address_size)
    5309             :         {
    5310          72 :           Dwarf_Addr addr = read_addr_unaligned_inc (address_size, dbg,
    5311             :                                                      readp);
    5312          72 :           printf (" [%*u] ", digits, uidx++);
    5313          72 :           print_dwarf_addr (dwflmod, address_size, addr, addr);
    5314          72 :           printf ("\n");
    5315             :         }
    5316           4 :       printf ("\n");
    5317             : 
    5318           4 :       if (readp != next_unitp)
    5319           0 :         error (0, 0, "extra %zd bytes at end of unit",
    5320           0 :                (size_t) (next_unitp - readp));
    5321             : 
    5322           4 :     next_unit:
    5323             :       readp = next_unitp;
    5324             :     }
    5325             : }
    5326             : 
    5327             : /* Print content of DWARF .debug_aranges section.  We fortunately do
    5328             :    not have to know a bit about the structure of the section, libdwarf
    5329             :    takes care of it.  */
    5330             : static void
    5331           0 : print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
    5332             :                                GElf_Shdr *shdr, Dwarf *dbg)
    5333             : {
    5334           0 :   Dwarf_Aranges *aranges;
    5335           0 :   size_t cnt;
    5336           0 :   if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
    5337             :     {
    5338           0 :       error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
    5339             :              dwarf_errmsg (-1));
    5340           0 :       return;
    5341             :     }
    5342             : 
    5343           0 :   GElf_Shdr glink_mem;
    5344           0 :   GElf_Shdr *glink;
    5345           0 :   glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
    5346           0 :   if (glink == NULL)
    5347             :     {
    5348           0 :       error (0, 0, gettext ("invalid sh_link value in section %zu"),
    5349             :              elf_ndxscn (scn));
    5350           0 :       return;
    5351             :     }
    5352             : 
    5353           0 :   printf (ngettext ("\
    5354             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
    5355             :                     "\
    5356             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
    5357             :                     cnt),
    5358             :           elf_ndxscn (scn), section_name (ebl, shdr),
    5359           0 :           (uint64_t) shdr->sh_offset, cnt);
    5360             : 
    5361             :   /* Compute floor(log16(cnt)).  */
    5362           0 :   size_t tmp = cnt;
    5363           0 :   int digits = 1;
    5364           0 :   while (tmp >= 16)
    5365             :     {
    5366           0 :       ++digits;
    5367           0 :       tmp >>= 4;
    5368             :     }
    5369             : 
    5370           0 :   for (size_t n = 0; n < cnt; ++n)
    5371             :     {
    5372           0 :       Dwarf_Arange *runp = dwarf_onearange (aranges, n);
    5373           0 :       if (unlikely (runp == NULL))
    5374             :         {
    5375           0 :           printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
    5376           0 :           return;
    5377             :         }
    5378             : 
    5379           0 :       Dwarf_Addr start;
    5380           0 :       Dwarf_Word length;
    5381           0 :       Dwarf_Off offset;
    5382             : 
    5383           0 :       if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
    5384           0 :         printf (gettext (" [%*zu] ???\n"), digits, n);
    5385             :       else
    5386           0 :         printf (gettext (" [%*zu] start: %0#*" PRIx64
    5387             :                          ", length: %5" PRIu64 ", CU DIE offset: %6"
    5388             :                          PRId64 "\n"),
    5389           0 :                 digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
    5390             :                 (uint64_t) start, (uint64_t) length, (int64_t) offset);
    5391             :     }
    5392             : }
    5393             : 
    5394             : 
    5395             : /* Print content of DWARF .debug_aranges section.  */
    5396             : static void
    5397          46 : print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
    5398             :                              Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
    5399             :                              GElf_Shdr *shdr, Dwarf *dbg)
    5400             : {
    5401          46 :   if (decodedaranges)
    5402             :     {
    5403           1 :       print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg);
    5404           1 :       return;
    5405             :     }
    5406             : 
    5407          90 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_aranges]
    5408          45 :                     ?: elf_rawdata (scn, NULL));
    5409             : 
    5410          45 :   if (unlikely (data == NULL))
    5411             :     {
    5412           0 :       error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
    5413             :              elf_errmsg (-1));
    5414           0 :       return;
    5415             :     }
    5416             : 
    5417          45 :   printf (gettext ("\
    5418             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    5419             :           elf_ndxscn (scn), section_name (ebl, shdr),
    5420          45 :           (uint64_t) shdr->sh_offset);
    5421             : 
    5422          45 :   const unsigned char *readp = data->d_buf;
    5423          45 :   const unsigned char *readendp = readp + data->d_size;
    5424             : 
    5425        1137 :   while (readp < readendp)
    5426             :     {
    5427        1092 :       const unsigned char *hdrstart = readp;
    5428        1092 :       size_t start_offset = hdrstart - (const unsigned char *) data->d_buf;
    5429             : 
    5430        1092 :       printf (gettext ("\nTable at offset %zu:\n"), start_offset);
    5431        1092 :       if (readp + 4 > readendp)
    5432             :         {
    5433           0 :         invalid_data:
    5434           0 :           error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
    5435             :                  elf_ndxscn (scn), section_name (ebl, shdr));
    5436           0 :           return;
    5437             :         }
    5438             : 
    5439        1092 :       Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
    5440        1092 :       unsigned int length_bytes = 4;
    5441        1092 :       if (length == DWARF3_LENGTH_64_BIT)
    5442             :         {
    5443           0 :           if (readp + 8 > readendp)
    5444             :             goto invalid_data;
    5445           0 :           length = read_8ubyte_unaligned_inc (dbg, readp);
    5446           0 :           length_bytes = 8;
    5447             :         }
    5448             : 
    5449        1092 :       const unsigned char *nexthdr = readp + length;
    5450        1092 :       printf (gettext ("\n Length:        %6" PRIu64 "\n"),
    5451             :               (uint64_t) length);
    5452             : 
    5453        1092 :       if (unlikely (length > (size_t) (readendp - readp)))
    5454             :         goto invalid_data;
    5455             : 
    5456        1092 :       if (length == 0)
    5457             :         continue;
    5458             : 
    5459        1092 :       if (readp + 2 > readendp)
    5460             :         goto invalid_data;
    5461        1092 :       uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, readp);
    5462        1092 :       printf (gettext (" DWARF version: %6" PRIuFAST16 "\n"),
    5463             :               version);
    5464        1092 :       if (version != 2)
    5465             :         {
    5466           0 :           error (0, 0, gettext ("unsupported aranges version"));
    5467           0 :           goto next_table;
    5468             :         }
    5469             : 
    5470        1092 :       Dwarf_Word offset;
    5471        1092 :       if (readp + length_bytes > readendp)
    5472             :         goto invalid_data;
    5473        1092 :       if (length_bytes == 8)
    5474           0 :         offset = read_8ubyte_unaligned_inc (dbg, readp);
    5475             :       else
    5476        1092 :         offset = read_4ubyte_unaligned_inc (dbg, readp);
    5477        1092 :       printf (gettext (" CU offset:     %6" PRIx64 "\n"),
    5478             :               (uint64_t) offset);
    5479             : 
    5480        1092 :       if (readp + 1 > readendp)
    5481             :         goto invalid_data;
    5482        1092 :       unsigned int address_size = *readp++;
    5483        1092 :       printf (gettext (" Address size:  %6" PRIu64 "\n"),
    5484             :               (uint64_t) address_size);
    5485        1092 :       if (address_size != 4 && address_size != 8)
    5486             :         {
    5487           0 :           error (0, 0, gettext ("unsupported address size"));
    5488           0 :           goto next_table;
    5489             :         }
    5490             : 
    5491        1092 :       if (readp + 1 > readendp)
    5492             :         goto invalid_data;
    5493        1092 :       unsigned int segment_size = *readp++;
    5494        1092 :       printf (gettext (" Segment size:  %6" PRIu64 "\n\n"),
    5495             :               (uint64_t) segment_size);
    5496        1092 :       if (segment_size != 0 && segment_size != 4 && segment_size != 8)
    5497             :         {
    5498           0 :           error (0, 0, gettext ("unsupported segment size"));
    5499           0 :           goto next_table;
    5500             :         }
    5501             : 
    5502             :       /* Round the address to the next multiple of 2*address_size.  */
    5503        2184 :       readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
    5504        1092 :                 % (2 * address_size));
    5505             : 
    5506        2219 :       while (readp < nexthdr)
    5507             :         {
    5508        2219 :           Dwarf_Word range_address;
    5509        2219 :           Dwarf_Word range_length;
    5510        2219 :           Dwarf_Word segment = 0;
    5511        2219 :           if (readp + 2 * address_size + segment_size > readendp)
    5512             :             goto invalid_data;
    5513        2219 :           if (address_size == 4)
    5514             :             {
    5515          36 :               range_address = read_4ubyte_unaligned_inc (dbg, readp);
    5516          36 :               range_length = read_4ubyte_unaligned_inc (dbg, readp);
    5517             :             }
    5518             :           else
    5519             :             {
    5520        2183 :               range_address = read_8ubyte_unaligned_inc (dbg, readp);
    5521        2183 :               range_length = read_8ubyte_unaligned_inc (dbg, readp);
    5522             :             }
    5523             : 
    5524        2219 :           if (segment_size == 4)
    5525           0 :             segment = read_4ubyte_unaligned_inc (dbg, readp);
    5526        2219 :           else if (segment_size == 8)
    5527           0 :             segment = read_8ubyte_unaligned_inc (dbg, readp);
    5528             : 
    5529        2219 :           if (range_address == 0 && range_length == 0 && segment == 0)
    5530             :             break;
    5531             : 
    5532        1127 :           printf ("   ");
    5533        1127 :           print_dwarf_addr (dwflmod, address_size, range_address,
    5534             :                             range_address);
    5535        1127 :           printf ("..");
    5536        2254 :           print_dwarf_addr (dwflmod, address_size,
    5537        1127 :                             range_address + range_length - 1,
    5538             :                             range_length);
    5539        1127 :           if (segment_size != 0)
    5540           0 :             printf (" (%" PRIx64 ")\n", (uint64_t) segment);
    5541             :           else
    5542        1127 :             printf ("\n");
    5543             :         }
    5544             : 
    5545        1092 :     next_table:
    5546        1092 :       if (readp != nexthdr)
    5547             :         {
    5548           0 :           size_t padding = nexthdr - readp;
    5549           0 :           printf (gettext ("   %zu padding bytes\n"), padding);
    5550           0 :           readp = nexthdr;
    5551             :         }
    5552             :     }
    5553             : }
    5554             : 
    5555             : 
    5556             : static bool is_split_dwarf (Dwarf *dbg, uint64_t *id, Dwarf_CU **split_cu);
    5557             : 
    5558             : /* Returns true and sets cu and cu_base if the given Dwarf is a split
    5559             :    DWARF (.dwo) file.  */
    5560             : static bool
    5561           0 : split_dwarf_cu_base (Dwarf *dbg, Dwarf_CU **cu, Dwarf_Addr *cu_base)
    5562             : {
    5563           0 :   uint64_t id;
    5564           0 :   if (is_split_dwarf (dbg, &id, cu))
    5565             :     {
    5566           0 :       Dwarf_Die cudie;
    5567           0 :       if (dwarf_cu_info (*cu, NULL, NULL, &cudie, NULL, NULL, NULL, NULL) == 0)
    5568             :         {
    5569           0 :           *cu_base = cudie_base (&cudie);
    5570           0 :           return true;
    5571             :         }
    5572             :     }
    5573             :   return false;
    5574             : }
    5575             : 
    5576             : /* Print content of DWARF .debug_rnglists section.  */
    5577             : static void
    5578           2 : print_debug_rnglists_section (Dwfl_Module *dwflmod,
    5579             :                               Ebl *ebl,
    5580             :                               GElf_Ehdr *ehdr __attribute__ ((unused)),
    5581             :                               Elf_Scn *scn, GElf_Shdr *shdr,
    5582             :                               Dwarf *dbg __attribute__((unused)))
    5583             : {
    5584           2 :   printf (gettext ("\
    5585             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    5586             :           elf_ndxscn (scn), section_name (ebl, shdr),
    5587           2 :           (uint64_t) shdr->sh_offset);
    5588             : 
    5589           4 :   Elf_Data *data =(dbg->sectiondata[IDX_debug_rnglists]
    5590           2 :                    ?: elf_rawdata (scn, NULL));
    5591           2 :   if (unlikely (data == NULL))
    5592             :     {
    5593           0 :       error (0, 0, gettext ("cannot get .debug_rnglists content: %s"),
    5594             :              elf_errmsg (-1));
    5595           0 :       return;
    5596             :     }
    5597             : 
    5598             :   /* For the listptr to get the base address/CU.  */
    5599           2 :   sort_listptr (&known_rnglistptr, "rnglistptr");
    5600           2 :   size_t listptr_idx = 0;
    5601             : 
    5602           2 :   const unsigned char *readp = data->d_buf;
    5603           4 :   const unsigned char *const dataend = ((unsigned char *) data->d_buf
    5604           2 :                                         + data->d_size);
    5605           4 :   while (readp < dataend)
    5606             :     {
    5607           2 :       if (unlikely (readp > dataend - 4))
    5608             :         {
    5609           0 :         invalid_data:
    5610           0 :           error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
    5611             :                  elf_ndxscn (scn), section_name (ebl, shdr));
    5612           0 :           return;
    5613             :         }
    5614             : 
    5615           2 :       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
    5616           2 :       printf (gettext ("Table at Offset 0x%" PRIx64 ":\n\n"),
    5617             :               (uint64_t) offset);
    5618             : 
    5619           2 :       uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
    5620           2 :       unsigned int offset_size = 4;
    5621           2 :       if (unlikely (unit_length == 0xffffffff))
    5622             :         {
    5623           0 :           if (unlikely (readp > dataend - 8))
    5624             :             goto invalid_data;
    5625             : 
    5626           0 :           unit_length = read_8ubyte_unaligned_inc (dbg, readp);
    5627           0 :           offset_size = 8;
    5628             :         }
    5629           2 :       printf (gettext (" Length:         %8" PRIu64 "\n"), unit_length);
    5630             : 
    5631             :       /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
    5632             :          bytes to complete the header.  And this unit cannot go beyond
    5633             :          the section data.  */
    5634           2 :       if (readp > dataend - 8
    5635           2 :           || unit_length < 8
    5636           2 :           || unit_length > (uint64_t) (dataend - readp))
    5637             :         goto invalid_data;
    5638             : 
    5639           2 :       const unsigned char *nexthdr = readp + unit_length;
    5640             : 
    5641           2 :       uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
    5642           2 :       printf (gettext (" DWARF version:  %8" PRIu16 "\n"), version);
    5643             : 
    5644           2 :       if (version != 5)
    5645             :         {
    5646           0 :           error (0, 0, gettext ("Unknown version"));
    5647           0 :           goto next_table;
    5648             :         }
    5649             : 
    5650           2 :       uint8_t address_size = *readp++;
    5651           2 :       printf (gettext (" Address size:   %8" PRIu64 "\n"),
    5652             :               (uint64_t) address_size);
    5653             : 
    5654           2 :       if (address_size != 4 && address_size != 8)
    5655             :         {
    5656           0 :           error (0, 0, gettext ("unsupported address size"));
    5657           0 :           goto next_table;
    5658             :         }
    5659             : 
    5660           2 :       uint8_t segment_size = *readp++;
    5661           2 :       printf (gettext (" Segment size:   %8" PRIu64 "\n"),
    5662             :               (uint64_t) segment_size);
    5663             : 
    5664           2 :       if (segment_size != 0 && segment_size != 4 && segment_size != 8)
    5665             :         {
    5666           0 :           error (0, 0, gettext ("unsupported segment size"));
    5667           0 :           goto next_table;
    5668             :         }
    5669             : 
    5670           2 :       uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
    5671           2 :       printf (gettext (" Offset entries: %8" PRIu64 "\n"),
    5672             :               (uint64_t) offset_entry_count);
    5673             : 
    5674             :       /* We need the CU that uses this unit to get the initial base address. */
    5675           2 :       Dwarf_Addr cu_base = 0;
    5676           2 :       struct Dwarf_CU *cu = NULL;
    5677           2 :       if (listptr_cu (&known_rnglistptr, &listptr_idx,
    5678             :                       (Dwarf_Off) offset,
    5679           2 :                       (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
    5680             :                       &cu_base, &cu)
    5681           0 :           || split_dwarf_cu_base (dbg, &cu, &cu_base))
    5682           2 :         {
    5683           2 :           Dwarf_Die cudie;
    5684           2 :           if (dwarf_cu_die (cu, &cudie,
    5685             :                             NULL, NULL, NULL, NULL,
    5686             :                             NULL, NULL) == NULL)
    5687           0 :             printf (gettext (" Unknown CU base: "));
    5688             :           else
    5689           2 :             printf (gettext (" CU [%6" PRIx64 "] base: "),
    5690             :                     dwarf_dieoffset (&cudie));
    5691           2 :           print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
    5692           2 :           printf ("\n");
    5693             :         }
    5694             :       else
    5695           0 :         printf (gettext (" Not associated with a CU.\n"));
    5696             : 
    5697           2 :       printf ("\n");
    5698             : 
    5699           2 :       const unsigned char *offset_array_start = readp;
    5700           2 :       if (offset_entry_count > 0)
    5701             :         {
    5702           1 :           uint64_t max_entries = (unit_length - 8) / offset_size;
    5703           1 :           if (offset_entry_count > max_entries)
    5704             :             {
    5705           0 :               error (0, 0,
    5706           0 :                      gettext ("too many offset entries for unit length"));
    5707           0 :               offset_entry_count = max_entries;
    5708             :             }
    5709             : 
    5710           3 :           printf (gettext ("  Offsets starting at 0x%" PRIx64 ":\n"),
    5711             :                   (uint64_t) (offset_array_start
    5712           1 :                               - (unsigned char *) data->d_buf));
    5713           3 :           for (uint32_t idx = 0; idx < offset_entry_count; idx++)
    5714             :             {
    5715           2 :               printf ("   [%6" PRIu32 "] ", idx);
    5716           2 :               if (offset_size == 4)
    5717             :                 {
    5718           2 :                   uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
    5719           2 :                   printf ("0x%" PRIx32 "\n", off);
    5720             :                 }
    5721             :               else
    5722             :                 {
    5723           0 :                   uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
    5724           0 :                   printf ("0x%" PRIx64 "\n", off);
    5725             :                 }
    5726             :             }
    5727           1 :           printf ("\n");
    5728             :         }
    5729             : 
    5730           2 :       Dwarf_Addr base = cu_base;
    5731           2 :       bool start_of_list = true;
    5732          16 :       while (readp < nexthdr)
    5733             :         {
    5734          14 :           uint8_t kind = *readp++;
    5735          14 :           uint64_t op1, op2;
    5736             : 
    5737             :           /* Skip padding.  */
    5738          14 :           if (start_of_list && kind == DW_RLE_end_of_list)
    5739             :             continue;
    5740             : 
    5741          14 :           if (start_of_list)
    5742             :             {
    5743           4 :               base = cu_base;
    5744          16 :               printf ("  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
    5745           4 :                       (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
    5746           4 :                       (uint64_t) (readp - offset_array_start - 1));
    5747           4 :               start_of_list = false;
    5748             :             }
    5749             : 
    5750          14 :           printf ("    %s", dwarf_range_list_encoding_name (kind));
    5751          14 :           switch (kind)
    5752             :             {
    5753           4 :             case DW_RLE_end_of_list:
    5754           4 :               start_of_list = true;
    5755           4 :               printf ("\n\n");
    5756             :               break;
    5757             : 
    5758           0 :             case DW_RLE_base_addressx:
    5759           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    5760             :                 {
    5761           0 :                 invalid_range:
    5762           0 :                   error (0, 0, gettext ("invalid range list data"));
    5763           0 :                   goto next_table;
    5764             :                 }
    5765           0 :               get_uleb128 (op1, readp, nexthdr);
    5766           0 :               printf (" %" PRIx64 "\n", op1);
    5767           0 :               if (! print_unresolved_addresses)
    5768             :                 {
    5769           0 :                   Dwarf_Addr addr;
    5770           0 :                   if (get_indexed_addr (cu, op1, &addr) != 0)
    5771           0 :                     printf ("      ???\n");
    5772             :                   else
    5773             :                     {
    5774           0 :                       printf ("      ");
    5775           0 :                       print_dwarf_addr (dwflmod, address_size, addr, addr);
    5776           0 :                       printf ("\n");
    5777             :                     }
    5778             :                 }
    5779             :               break;
    5780             : 
    5781           0 :             case DW_RLE_startx_endx:
    5782           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    5783             :                 goto invalid_range;
    5784           0 :               get_uleb128 (op1, readp, nexthdr);
    5785           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    5786             :                 goto invalid_range;
    5787           0 :               get_uleb128 (op2, readp, nexthdr);
    5788           0 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    5789           0 :               if (! print_unresolved_addresses)
    5790             :                 {
    5791           0 :                   Dwarf_Addr addr1;
    5792           0 :                   Dwarf_Addr addr2;
    5793           0 :                   if (get_indexed_addr (cu, op1, &addr1) != 0
    5794           0 :                       || get_indexed_addr (cu, op2, &addr2) != 0)
    5795             :                     {
    5796           0 :                       printf ("      ???..\n");
    5797           0 :                       printf ("      ???\n");
    5798             :                     }
    5799             :                   else
    5800             :                     {
    5801           0 :                       printf ("      ");
    5802           0 :                       print_dwarf_addr (dwflmod, address_size, addr1, addr1);
    5803           0 :                       printf ("..\n      ");
    5804           0 :                       print_dwarf_addr (dwflmod, address_size,
    5805             :                                         addr2 - 1, addr2);
    5806           0 :                       printf ("\n");
    5807             :                     }
    5808             :                 }
    5809             :               break;
    5810             : 
    5811           0 :             case DW_RLE_startx_length:
    5812           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    5813             :                 goto invalid_range;
    5814           0 :               get_uleb128 (op1, readp, nexthdr);
    5815           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    5816             :                 goto invalid_range;
    5817           0 :               get_uleb128 (op2, readp, nexthdr);
    5818           0 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    5819           0 :               if (! print_unresolved_addresses)
    5820             :                 {
    5821           0 :                   Dwarf_Addr addr1;
    5822           0 :                   Dwarf_Addr addr2;
    5823           0 :                   if (get_indexed_addr (cu, op1, &addr1) != 0)
    5824             :                     {
    5825           0 :                       printf ("      ???..\n");
    5826           0 :                       printf ("      ???\n");
    5827             :                     }
    5828             :                   else
    5829             :                     {
    5830           0 :                       addr2 = addr1 + op2;
    5831           0 :                       printf ("      ");
    5832           0 :                       print_dwarf_addr (dwflmod, address_size, addr1, addr1);
    5833           0 :                       printf ("..\n      ");
    5834           0 :                       print_dwarf_addr (dwflmod, address_size,
    5835             :                                         addr2 - 1, addr2);
    5836           0 :                       printf ("\n");
    5837             :                     }
    5838             :                 }
    5839             :               break;
    5840             : 
    5841           4 :             case DW_RLE_offset_pair:
    5842           4 :               if ((uint64_t) (nexthdr - readp) < 1)
    5843             :                 goto invalid_range;
    5844           4 :               get_uleb128 (op1, readp, nexthdr);
    5845           4 :               if ((uint64_t) (nexthdr - readp) < 1)
    5846             :                 goto invalid_range;
    5847           4 :               get_uleb128 (op2, readp, nexthdr);
    5848           4 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    5849           4 :               if (! print_unresolved_addresses)
    5850             :                 {
    5851           4 :                   op1 += base;
    5852           4 :                   op2 += base;
    5853           4 :                   printf ("      ");
    5854           4 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    5855           4 :                   printf ("..\n      ");
    5856           4 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    5857           4 :                   printf ("\n");
    5858             :                 }
    5859             :               break;
    5860             : 
    5861           2 :             case DW_RLE_base_address:
    5862           2 :               if (address_size == 4)
    5863             :                 {
    5864           0 :                   if ((uint64_t) (nexthdr - readp) < 4)
    5865             :                     goto invalid_range;
    5866           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    5867             :                 }
    5868             :               else
    5869             :                 {
    5870           2 :                   if ((uint64_t) (nexthdr - readp) < 8)
    5871             :                     goto invalid_range;
    5872           2 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    5873             :                 }
    5874           2 :               base = op1;
    5875           2 :               printf (" 0x%" PRIx64 "\n", base);
    5876           2 :               if (! print_unresolved_addresses)
    5877             :                 {
    5878           2 :                   printf ("      ");
    5879           2 :                   print_dwarf_addr (dwflmod, address_size, base, base);
    5880           2 :                   printf ("\n");
    5881             :                 }
    5882             :               break;
    5883             : 
    5884           0 :             case DW_RLE_start_end:
    5885           0 :               if (address_size == 4)
    5886             :                 {
    5887           0 :                   if ((uint64_t) (nexthdr - readp) < 8)
    5888             :                     goto invalid_range;
    5889           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    5890           0 :                   op2 = read_4ubyte_unaligned_inc (dbg, readp);
    5891             :                 }
    5892             :               else
    5893             :                 {
    5894           0 :                   if ((uint64_t) (nexthdr - readp) < 16)
    5895             :                     goto invalid_range;
    5896           0 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    5897           0 :                   op2 = read_8ubyte_unaligned_inc (dbg, readp);
    5898             :                 }
    5899           0 :               printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
    5900           0 :               if (! print_unresolved_addresses)
    5901             :                 {
    5902           0 :                   printf ("      ");
    5903           0 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    5904           0 :                   printf ("..\n      ");
    5905           0 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    5906           0 :                   printf ("\n");
    5907             :                 }
    5908             :               break;
    5909             : 
    5910           4 :             case DW_RLE_start_length:
    5911           4 :               if (address_size == 4)
    5912             :                 {
    5913           0 :                   if ((uint64_t) (nexthdr - readp) < 4)
    5914             :                     goto invalid_range;
    5915           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    5916             :                 }
    5917             :               else
    5918             :                 {
    5919           4 :                   if ((uint64_t) (nexthdr - readp) < 8)
    5920             :                     goto invalid_range;
    5921           4 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    5922             :                 }
    5923           4 :               if ((uint64_t) (nexthdr - readp) < 1)
    5924             :                 goto invalid_range;
    5925           4 :               get_uleb128 (op2, readp, nexthdr);
    5926           4 :               printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
    5927           4 :               if (! print_unresolved_addresses)
    5928             :                 {
    5929           4 :                   op2 = op1 + op2;
    5930           4 :                   printf ("      ");
    5931           4 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    5932           4 :                   printf ("..\n      ");
    5933           4 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    5934           4 :                   printf ("\n");
    5935             :                 }
    5936             :               break;
    5937             : 
    5938             :             default:
    5939             :               goto invalid_range;
    5940             :             }
    5941             :         }
    5942             : 
    5943           2 :     next_table:
    5944           2 :       if (readp != nexthdr)
    5945             :         {
    5946           0 :           size_t padding = nexthdr - readp;
    5947           0 :           printf (gettext ("   %zu padding bytes\n\n"), padding);
    5948           0 :           readp = nexthdr;
    5949             :         }
    5950             :     }
    5951             : }
    5952             : 
    5953             : /* Print content of DWARF .debug_ranges section.  */
    5954             : static void
    5955          32 : print_debug_ranges_section (Dwfl_Module *dwflmod,
    5956             :                             Ebl *ebl, GElf_Ehdr *ehdr,
    5957             :                             Elf_Scn *scn, GElf_Shdr *shdr,
    5958             :                             Dwarf *dbg)
    5959             : {
    5960          64 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_ranges]
    5961          32 :                     ?: elf_rawdata (scn, NULL));
    5962          32 :   if (unlikely (data == NULL))
    5963             :     {
    5964           0 :       error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
    5965             :              elf_errmsg (-1));
    5966           0 :       return;
    5967             :     }
    5968             : 
    5969          32 :   printf (gettext ("\
    5970             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    5971             :           elf_ndxscn (scn), section_name (ebl, shdr),
    5972          32 :           (uint64_t) shdr->sh_offset);
    5973             : 
    5974          32 :   sort_listptr (&known_rangelistptr, "rangelistptr");
    5975          32 :   size_t listptr_idx = 0;
    5976             : 
    5977          32 :   uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    5978             : 
    5979          32 :   bool first = true;
    5980          32 :   Dwarf_Addr base = 0;
    5981          32 :   unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
    5982          32 :   unsigned char *readp = data->d_buf;
    5983          32 :   Dwarf_CU *last_cu = NULL;
    5984       50489 :   while (readp < endp)
    5985             :     {
    5986       50457 :       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
    5987       50457 :       Dwarf_CU *cu = last_cu;
    5988             : 
    5989       50457 :       if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
    5990             :                                       &address_size, NULL, &base, &cu,
    5991             :                                       offset, &readp, endp, NULL))
    5992           4 :         continue;
    5993             : 
    5994       50453 :       if (last_cu != cu)
    5995             :         {
    5996         643 :           Dwarf_Die cudie;
    5997         643 :           if (dwarf_cu_die (cu, &cudie,
    5998             :                             NULL, NULL, NULL, NULL,
    5999             :                             NULL, NULL) == NULL)
    6000           0 :             printf (gettext ("\n Unknown CU base: "));
    6001             :           else
    6002         643 :             printf (gettext ("\n CU [%6" PRIx64 "] base: "),
    6003             :                     dwarf_dieoffset (&cudie));
    6004         643 :           print_dwarf_addr (dwflmod, address_size, base, base);
    6005         643 :           printf ("\n");
    6006             :         }
    6007       50453 :       last_cu = cu;
    6008             : 
    6009       50453 :       if (unlikely (data->d_size - offset < (size_t) address_size * 2))
    6010             :         {
    6011           0 :           printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
    6012           0 :           break;
    6013             :         }
    6014             : 
    6015       50453 :       Dwarf_Addr begin;
    6016       50453 :       Dwarf_Addr end;
    6017       50453 :       if (address_size == 8)
    6018             :         {
    6019       50445 :           begin = read_8ubyte_unaligned_inc (dbg, readp);
    6020       50445 :           end = read_8ubyte_unaligned_inc (dbg, readp);
    6021             :         }
    6022             :       else
    6023             :         {
    6024           8 :           begin = read_4ubyte_unaligned_inc (dbg, readp);
    6025           8 :           end = read_4ubyte_unaligned_inc (dbg, readp);
    6026           8 :           if (begin == (Dwarf_Addr) (uint32_t) -1)
    6027             :             begin = (Dwarf_Addr) -1l;
    6028             :         }
    6029             : 
    6030       50453 :       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
    6031             :         {
    6032           0 :           printf (gettext (" [%6tx] base address\n          "), offset);
    6033           0 :           print_dwarf_addr (dwflmod, address_size, end, end);
    6034           0 :           printf ("\n");
    6035           0 :           base = end;
    6036             :         }
    6037       50453 :       else if (begin == 0 && end == 0) /* End of list entry.  */
    6038             :         {
    6039       11317 :           if (first)
    6040           4 :             printf (gettext (" [%6tx] empty list\n"), offset);
    6041             :           first = true;
    6042             :         }
    6043             :       else
    6044             :         {
    6045             :           /* We have an address range entry.  */
    6046       39136 :           if (first)            /* First address range entry in a list.  */
    6047       11313 :             printf (" [%6tx] ", offset);
    6048             :           else
    6049       27823 :             printf ("          ");
    6050             : 
    6051       39136 :           printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
    6052       39136 :           if (! print_unresolved_addresses)
    6053             :             {
    6054       39126 :               printf ("          ");
    6055       39126 :               print_dwarf_addr (dwflmod, address_size, base + begin,
    6056             :                                 base + begin);
    6057       39126 :               printf ("..\n          ");
    6058       39126 :               print_dwarf_addr (dwflmod, address_size,
    6059             :                                 base + end - 1, base + end);
    6060       39126 :               printf ("\n");
    6061             :             }
    6062             : 
    6063             :           first = false;
    6064             :         }
    6065             :     }
    6066             : }
    6067             : 
    6068             : #define REGNAMESZ 16
    6069             : static const char *
    6070        9478 : register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
    6071             :                char name[REGNAMESZ], int *bits, int *type)
    6072             : {
    6073        9478 :   const char *set;
    6074        9478 :   const char *pfx;
    6075        9478 :   int ignore;
    6076       26738 :   ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
    6077             :                                  bits ?: &ignore, type ?: &ignore);
    6078        9478 :   if (n <= 0)
    6079             :     {
    6080           0 :       if (loc != NULL)
    6081           0 :         snprintf (name, REGNAMESZ, "reg%u", loc->regno);
    6082             :       else
    6083           0 :         snprintf (name, REGNAMESZ, "??? 0x%x", regno);
    6084           0 :       if (bits != NULL)
    6085           0 :         *bits = loc != NULL ? loc->bits : 0;
    6086           0 :       if (type != NULL)
    6087           0 :         *type = DW_ATE_unsigned;
    6088           0 :       set = "??? unrecognized";
    6089             :     }
    6090             :   else
    6091             :     {
    6092        9478 :       if (bits != NULL && *bits <= 0)
    6093           0 :         *bits = loc != NULL ? loc->bits : 0;
    6094        9478 :       if (type != NULL && *type == DW_ATE_void)
    6095           0 :         *type = DW_ATE_unsigned;
    6096             : 
    6097             :     }
    6098        9478 :   return set;
    6099             : }
    6100             : 
    6101             : static const unsigned char *
    6102           0 : read_encoded (unsigned int encoding, const unsigned char *readp,
    6103             :               const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
    6104             : {
    6105           0 :   if ((encoding & 0xf) == DW_EH_PE_absptr)
    6106           0 :     encoding = gelf_getclass (dbg->elf) == ELFCLASS32
    6107           0 :       ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
    6108             : 
    6109           0 :   switch (encoding & 0xf)
    6110             :     {
    6111           0 :     case DW_EH_PE_uleb128:
    6112           0 :       get_uleb128 (*res, readp, endp);
    6113           0 :       break;
    6114           0 :     case DW_EH_PE_sleb128:
    6115           0 :       get_sleb128 (*res, readp, endp);
    6116           0 :       break;
    6117           0 :     case DW_EH_PE_udata2:
    6118           0 :       if (readp + 2 > endp)
    6119           0 :         goto invalid;
    6120           0 :       *res = read_2ubyte_unaligned_inc (dbg, readp);
    6121           0 :       break;
    6122           0 :     case DW_EH_PE_udata4:
    6123           0 :       if (readp + 4 > endp)
    6124           0 :         goto invalid;
    6125           0 :       *res = read_4ubyte_unaligned_inc (dbg, readp);
    6126           0 :       break;
    6127           0 :     case DW_EH_PE_udata8:
    6128           0 :       if (readp + 8 > endp)
    6129           0 :         goto invalid;
    6130           0 :       *res = read_8ubyte_unaligned_inc (dbg, readp);
    6131           0 :       break;
    6132           0 :     case DW_EH_PE_sdata2:
    6133           0 :       if (readp + 2 > endp)
    6134           0 :         goto invalid;
    6135           0 :       *res = read_2sbyte_unaligned_inc (dbg, readp);
    6136           0 :       break;
    6137           0 :     case DW_EH_PE_sdata4:
    6138           0 :       if (readp + 4 > endp)
    6139           0 :         goto invalid;
    6140           0 :       *res = read_4sbyte_unaligned_inc (dbg, readp);
    6141           0 :       break;
    6142           0 :     case DW_EH_PE_sdata8:
    6143           0 :       if (readp + 8 > endp)
    6144           0 :         goto invalid;
    6145           0 :       *res = read_8sbyte_unaligned_inc (dbg, readp);
    6146           0 :       break;
    6147             :     default:
    6148           0 :     invalid:
    6149           0 :       error (1, 0,
    6150           0 :              gettext ("invalid encoding"));
    6151             :     }
    6152             : 
    6153           0 :   return readp;
    6154             : }
    6155             : 
    6156             : 
    6157             : static void
    6158        4690 : print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
    6159             :                    Dwarf_Word vma_base, unsigned int code_align,
    6160             :                    int data_align,
    6161             :                    unsigned int version, unsigned int ptr_size,
    6162             :                    unsigned int encoding,
    6163             :                    Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
    6164             : {
    6165        4690 :   char regnamebuf[REGNAMESZ];
    6166        4690 :   const char *regname (unsigned int regno)
    6167             :   {
    6168        8630 :     register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
    6169        8630 :     return regnamebuf;
    6170             :   }
    6171             : 
    6172        4690 :   puts ("\n   Program:");
    6173        4690 :   Dwarf_Word pc = vma_base;
    6174       84030 :   while (readp < endp)
    6175             :     {
    6176       79340 :       unsigned int opcode = *readp++;
    6177             : 
    6178       79340 :       if (opcode < DW_CFA_advance_loc)
    6179             :         /* Extended opcode.  */
    6180       46036 :         switch (opcode)
    6181             :           {
    6182       13042 :             uint64_t op1;
    6183       13042 :             int64_t sop1;
    6184       13042 :             uint64_t op2;
    6185       13042 :             int64_t sop2;
    6186             : 
    6187       13042 :           case DW_CFA_nop:
    6188       13042 :             puts ("     nop");
    6189       46036 :             break;
    6190           0 :           case DW_CFA_set_loc:
    6191           0 :             if ((uint64_t) (endp - readp) < 1)
    6192             :               goto invalid;
    6193           0 :             readp = read_encoded (encoding, readp, endp, &op1, dbg);
    6194           0 :             printf ("     set_loc %#" PRIx64 " to %#" PRIx64 "\n",
    6195           0 :                     op1, pc = vma_base + op1);
    6196             :             break;
    6197        1784 :           case DW_CFA_advance_loc1:
    6198        1784 :             if ((uint64_t) (endp - readp) < 1)
    6199             :               goto invalid;
    6200        5352 :             printf ("     advance_loc1 %u to %#" PRIx64 "\n",
    6201        1784 :                     *readp, pc += *readp * code_align);
    6202        1784 :             ++readp;
    6203        1784 :             break;
    6204         705 :           case DW_CFA_advance_loc2:
    6205         705 :             if ((uint64_t) (endp - readp) < 2)
    6206             :               goto invalid;
    6207         705 :             op1 = read_2ubyte_unaligned_inc (dbg, readp);
    6208        1410 :             printf ("     advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
    6209         705 :                     op1, pc += op1 * code_align);
    6210             :             break;
    6211          24 :           case DW_CFA_advance_loc4:
    6212          24 :             if ((uint64_t) (endp - readp) < 4)
    6213             :               goto invalid;
    6214          24 :             op1 = read_4ubyte_unaligned_inc (dbg, readp);
    6215          48 :             printf ("     advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
    6216          24 :                     op1, pc += op1 * code_align);
    6217             :             break;
    6218           4 :           case DW_CFA_offset_extended:
    6219           4 :             if ((uint64_t) (endp - readp) < 1)
    6220             :               goto invalid;
    6221           4 :             get_uleb128 (op1, readp, endp);
    6222           4 :             if ((uint64_t) (endp - readp) < 1)
    6223             :               goto invalid;
    6224           4 :             get_uleb128 (op2, readp, endp);
    6225           4 :             printf ("     offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
    6226             :                     "\n",
    6227             :                     op1, regname (op1), op2 * data_align);
    6228             :             break;
    6229           0 :           case DW_CFA_restore_extended:
    6230           0 :             if ((uint64_t) (endp - readp) < 1)
    6231             :               goto invalid;
    6232           0 :             get_uleb128 (op1, readp, endp);
    6233           0 :             printf ("     restore_extended r%" PRIu64 " (%s)\n",
    6234             :                     op1, regname (op1));
    6235             :             break;
    6236           6 :           case DW_CFA_undefined:
    6237           6 :             if ((uint64_t) (endp - readp) < 1)
    6238             :               goto invalid;
    6239           6 :             get_uleb128 (op1, readp, endp);
    6240           6 :             printf ("     undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
    6241             :             break;
    6242           0 :           case DW_CFA_same_value:
    6243           0 :             if ((uint64_t) (endp - readp) < 1)
    6244             :               goto invalid;
    6245           0 :             get_uleb128 (op1, readp, endp);
    6246           0 :             printf ("     same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
    6247             :             break;
    6248           0 :           case DW_CFA_register:
    6249           0 :             if ((uint64_t) (endp - readp) < 1)
    6250             :               goto invalid;
    6251           0 :             get_uleb128 (op1, readp, endp);
    6252           0 :             if ((uint64_t) (endp - readp) < 1)
    6253             :               goto invalid;
    6254           0 :             get_uleb128 (op2, readp, endp);
    6255           0 :             printf ("     register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
    6256             :                     op1, regname (op1), op2, regname (op2));
    6257             :             break;
    6258        3110 :           case DW_CFA_remember_state:
    6259        3110 :             puts ("     remember_state");
    6260        3110 :             break;
    6261        3110 :           case DW_CFA_restore_state:
    6262        3110 :             puts ("     restore_state");
    6263        3110 :             break;
    6264         155 :           case DW_CFA_def_cfa:
    6265         155 :             if ((uint64_t) (endp - readp) < 1)
    6266             :               goto invalid;
    6267         155 :             get_uleb128 (op1, readp, endp);
    6268         155 :             if ((uint64_t) (endp - readp) < 1)
    6269             :               goto invalid;
    6270         155 :             get_uleb128 (op2, readp, endp);
    6271         155 :             printf ("     def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
    6272             :                     op1, regname (op1), op2);
    6273             :             break;
    6274          50 :           case DW_CFA_def_cfa_register:
    6275          50 :             if ((uint64_t) (endp - readp) < 1)
    6276             :               goto invalid;
    6277          50 :             get_uleb128 (op1, readp, endp);
    6278          50 :             printf ("     def_cfa_register r%" PRIu64 " (%s)\n",
    6279             :                     op1, regname (op1));
    6280             :             break;
    6281       24018 :           case DW_CFA_def_cfa_offset:
    6282       24018 :             if ((uint64_t) (endp - readp) < 1)
    6283             :               goto invalid;
    6284       24018 :             get_uleb128 (op1, readp, endp);
    6285       24018 :             printf ("     def_cfa_offset %" PRIu64 "\n", op1);
    6286             :             break;
    6287          12 :           case DW_CFA_def_cfa_expression:
    6288          12 :             if ((uint64_t) (endp - readp) < 1)
    6289             :               goto invalid;
    6290          12 :             get_uleb128 (op1, readp, endp);     /* Length of DW_FORM_block.  */
    6291          12 :             printf ("     def_cfa_expression %" PRIu64 "\n", op1);
    6292          12 :             if ((uint64_t) (endp - readp) < op1)
    6293             :               {
    6294           0 :             invalid:
    6295           0 :                 fputs (gettext ("         <INVALID DATA>\n"), stdout);
    6296           0 :                 return;
    6297             :               }
    6298          12 :             print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
    6299             :                        op1, readp);
    6300          12 :             readp += op1;
    6301          12 :             break;
    6302           0 :           case DW_CFA_expression:
    6303           0 :             if ((uint64_t) (endp - readp) < 1)
    6304             :               goto invalid;
    6305           0 :             get_uleb128 (op1, readp, endp);
    6306           0 :             if ((uint64_t) (endp - readp) < 1)
    6307             :               goto invalid;
    6308           0 :             get_uleb128 (op2, readp, endp);     /* Length of DW_FORM_block.  */
    6309           0 :             printf ("     expression r%" PRIu64 " (%s) \n",
    6310             :                     op1, regname (op1));
    6311           0 :             if ((uint64_t) (endp - readp) < op2)
    6312             :               goto invalid;
    6313           0 :             print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
    6314             :                        op2, readp);
    6315           0 :             readp += op2;
    6316           0 :             break;
    6317          16 :           case DW_CFA_offset_extended_sf:
    6318          16 :             if ((uint64_t) (endp - readp) < 1)
    6319             :               goto invalid;
    6320          16 :             get_uleb128 (op1, readp, endp);
    6321          16 :             if ((uint64_t) (endp - readp) < 1)
    6322             :               goto invalid;
    6323          16 :             get_sleb128 (sop2, readp, endp);
    6324          16 :             printf ("     offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
    6325             :                     PRId64 "\n",
    6326             :                     op1, regname (op1), sop2 * data_align);
    6327             :             break;
    6328           0 :           case DW_CFA_def_cfa_sf:
    6329           0 :             if ((uint64_t) (endp - readp) < 1)
    6330             :               goto invalid;
    6331           0 :             get_uleb128 (op1, readp, endp);
    6332           0 :             if ((uint64_t) (endp - readp) < 1)
    6333             :               goto invalid;
    6334           0 :             get_sleb128 (sop2, readp, endp);
    6335           0 :             printf ("     def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
    6336             :                     op1, regname (op1), sop2 * data_align);
    6337             :             break;
    6338           0 :           case DW_CFA_def_cfa_offset_sf:
    6339           0 :             if ((uint64_t) (endp - readp) < 1)
    6340             :               goto invalid;
    6341           0 :             get_sleb128 (sop1, readp, endp);
    6342           0 :             printf ("     def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
    6343             :             break;
    6344           0 :           case DW_CFA_val_offset:
    6345           0 :             if ((uint64_t) (endp - readp) < 1)
    6346             :               goto invalid;
    6347           0 :             get_uleb128 (op1, readp, endp);
    6348           0 :             if ((uint64_t) (endp - readp) < 1)
    6349             :               goto invalid;
    6350           0 :             get_uleb128 (op2, readp, endp);
    6351           0 :             printf ("     val_offset %" PRIu64 " at offset %" PRIu64 "\n",
    6352             :                     op1, op2 * data_align);
    6353             :             break;
    6354           0 :           case DW_CFA_val_offset_sf:
    6355           0 :             if ((uint64_t) (endp - readp) < 1)
    6356             :               goto invalid;
    6357           0 :             get_uleb128 (op1, readp, endp);
    6358           0 :             if ((uint64_t) (endp - readp) < 1)
    6359             :               goto invalid;
    6360           0 :             get_sleb128 (sop2, readp, endp);
    6361           0 :             printf ("     val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
    6362             :                     op1, sop2 * data_align);
    6363             :             break;
    6364           0 :           case DW_CFA_val_expression:
    6365           0 :             if ((uint64_t) (endp - readp) < 1)
    6366             :               goto invalid;
    6367           0 :             get_uleb128 (op1, readp, endp);
    6368           0 :             if ((uint64_t) (endp - readp) < 1)
    6369             :               goto invalid;
    6370           0 :             get_uleb128 (op2, readp, endp);     /* Length of DW_FORM_block.  */
    6371           0 :             printf ("     val_expression r%" PRIu64 " (%s)\n",
    6372             :                     op1, regname (op1));
    6373           0 :             if ((uint64_t) (endp - readp) < op2)
    6374             :               goto invalid;
    6375           0 :             print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0,
    6376             :                        NULL, op2, readp);
    6377           0 :             readp += op2;
    6378           0 :             break;
    6379           0 :           case DW_CFA_MIPS_advance_loc8:
    6380           0 :             if ((uint64_t) (endp - readp) < 8)
    6381             :               goto invalid;
    6382           0 :             op1 = read_8ubyte_unaligned_inc (dbg, readp);
    6383           0 :             printf ("     MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
    6384           0 :                     op1, pc += op1 * code_align);
    6385             :             break;
    6386           0 :           case DW_CFA_GNU_window_save:
    6387           0 :             puts ("     GNU_window_save");
    6388           0 :             break;
    6389           0 :           case DW_CFA_GNU_args_size:
    6390           0 :             if ((uint64_t) (endp - readp) < 1)
    6391             :               goto invalid;
    6392           0 :             get_uleb128 (op1, readp, endp);
    6393           0 :             printf ("     args_size %" PRIu64 "\n", op1);
    6394             :             break;
    6395             :           default:
    6396           0 :             printf ("     ??? (%u)\n", opcode);
    6397             :             break;
    6398             :           }
    6399       33304 :       else if (opcode < DW_CFA_offset)
    6400       49810 :         printf ("     advance_loc %u to %#" PRIx64 "\n",
    6401       24905 :                 opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
    6402        8399 :       else if (opcode < DW_CFA_restore)
    6403             :         {
    6404        7289 :           uint64_t offset;
    6405        7289 :           if ((uint64_t) (endp - readp) < 1)
    6406             :             goto invalid;
    6407        7289 :           get_uleb128 (offset, readp, endp);
    6408        7289 :           printf ("     offset r%u (%s) at cfa%+" PRId64 "\n",
    6409             :                   opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
    6410             :         }
    6411             :       else
    6412        1110 :         printf ("     restore r%u (%s)\n",
    6413             :                 opcode & 0x3f, regname (opcode & 0x3f));
    6414             :     }
    6415             : }
    6416             : 
    6417             : 
    6418             : static unsigned int
    6419        4587 : encoded_ptr_size (int encoding, unsigned int ptr_size)
    6420             : {
    6421        4587 :   switch (encoding & 7)
    6422             :     {
    6423             :     case DW_EH_PE_udata4:
    6424             :       return 4;
    6425           0 :     case DW_EH_PE_udata8:
    6426           0 :       return 8;
    6427          48 :     case 0:
    6428          48 :       return ptr_size;
    6429             :     }
    6430             : 
    6431           0 :   fprintf (stderr, "Unsupported pointer encoding: %#x, "
    6432             :            "assuming pointer size of %d.\n", encoding, ptr_size);
    6433           0 :   return ptr_size;
    6434             : }
    6435             : 
    6436             : 
    6437             : static unsigned int
    6438         105 : print_encoding (unsigned int val)
    6439             : {
    6440         105 :   switch (val & 0xf)
    6441             :     {
    6442           0 :     case DW_EH_PE_absptr:
    6443           0 :       fputs ("absptr", stdout);
    6444           0 :       break;
    6445           0 :     case DW_EH_PE_uleb128:
    6446           0 :       fputs ("uleb128", stdout);
    6447           0 :       break;
    6448           0 :     case DW_EH_PE_udata2:
    6449           0 :       fputs ("udata2", stdout);
    6450           0 :       break;
    6451          14 :     case DW_EH_PE_udata4:
    6452          14 :       fputs ("udata4", stdout);
    6453          14 :       break;
    6454           0 :     case DW_EH_PE_udata8:
    6455           0 :       fputs ("udata8", stdout);
    6456           0 :       break;
    6457           0 :     case DW_EH_PE_sleb128:
    6458           0 :       fputs ("sleb128", stdout);
    6459           0 :       break;
    6460           0 :     case DW_EH_PE_sdata2:
    6461           0 :       fputs ("sdata2", stdout);
    6462           0 :       break;
    6463          91 :     case DW_EH_PE_sdata4:
    6464          91 :       fputs ("sdata4", stdout);
    6465          91 :       break;
    6466           0 :     case DW_EH_PE_sdata8:
    6467           0 :       fputs ("sdata8", stdout);
    6468           0 :       break;
    6469             :     default:
    6470             :       /* We did not use any of the bits after all.  */
    6471             :       return val;
    6472             :     }
    6473             : 
    6474         105 :   return val & ~0xf;
    6475             : }
    6476             : 
    6477             : 
    6478             : static unsigned int
    6479          91 : print_relinfo (unsigned int val)
    6480             : {
    6481          91 :   switch (val & 0x70)
    6482             :     {
    6483          77 :     case DW_EH_PE_pcrel:
    6484          77 :       fputs ("pcrel", stdout);
    6485          77 :       break;
    6486           0 :     case DW_EH_PE_textrel:
    6487           0 :       fputs ("textrel", stdout);
    6488           0 :       break;
    6489          14 :     case DW_EH_PE_datarel:
    6490          14 :       fputs ("datarel", stdout);
    6491          14 :       break;
    6492           0 :     case DW_EH_PE_funcrel:
    6493           0 :       fputs ("funcrel", stdout);
    6494           0 :       break;
    6495           0 :     case DW_EH_PE_aligned:
    6496           0 :       fputs ("aligned", stdout);
    6497           0 :       break;
    6498             :     default:
    6499             :       return val;
    6500             :     }
    6501             : 
    6502          91 :   return val & ~0x70;
    6503             : }
    6504             : 
    6505             : 
    6506             : static void
    6507         105 : print_encoding_base (const char *pfx, unsigned int fde_encoding)
    6508             : {
    6509         105 :   printf ("(%s", pfx);
    6510             : 
    6511         105 :   if (fde_encoding == DW_EH_PE_omit)
    6512           0 :     puts ("omit)");
    6513             :   else
    6514             :     {
    6515         105 :       unsigned int w = fde_encoding;
    6516             : 
    6517         105 :       w = print_encoding (w);
    6518             : 
    6519         105 :       if (w & 0x70)
    6520             :         {
    6521          91 :           if (w != fde_encoding)
    6522          91 :             fputc_unlocked (' ', stdout);
    6523             : 
    6524          91 :           w = print_relinfo (w);
    6525             :         }
    6526             : 
    6527         105 :       if (w != 0)
    6528           0 :         printf ("%s%x", w != fde_encoding ? " " : "", w);
    6529             : 
    6530         105 :       puts (")");
    6531             :     }
    6532         105 : }
    6533             : 
    6534             : 
    6535             : static void
    6536          50 : print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
    6537             :                            Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    6538             : {
    6539          50 :   size_t shstrndx;
    6540             :   /* We know this call will succeed since it did in the caller.  */
    6541          50 :   (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
    6542          50 :   const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
    6543             : 
    6544             :   /* Needed if we find PC-relative addresses.  */
    6545          50 :   GElf_Addr bias;
    6546          50 :   if (dwfl_module_getelf (dwflmod, &bias) == NULL)
    6547             :     {
    6548           0 :       error (0, 0, gettext ("cannot get ELF: %s"), dwfl_errmsg (-1));
    6549           0 :       return;
    6550             :     }
    6551             : 
    6552          50 :   bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
    6553         100 :   Elf_Data *data = (is_eh_frame
    6554          26 :                     ? elf_rawdata (scn, NULL)
    6555          50 :                     : (dbg->sectiondata[IDX_debug_frame]
    6556          24 :                        ?: elf_rawdata (scn, NULL)));
    6557             : 
    6558          50 :   if (unlikely (data == NULL))
    6559             :     {
    6560           0 :       error (0, 0, gettext ("cannot get %s content: %s"),
    6561             :              scnname, elf_errmsg (-1));
    6562           0 :       return;
    6563             :     }
    6564             : 
    6565          50 :   if (is_eh_frame)
    6566          26 :     printf (gettext ("\
    6567             : \nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    6568          26 :             elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
    6569             :   else
    6570          24 :     printf (gettext ("\
    6571             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    6572          24 :             elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
    6573             : 
    6574          50 :   struct cieinfo
    6575             :   {
    6576             :     ptrdiff_t cie_offset;
    6577             :     const char *augmentation;
    6578             :     unsigned int code_alignment_factor;
    6579             :     unsigned int data_alignment_factor;
    6580             :     uint8_t address_size;
    6581             :     uint8_t fde_encoding;
    6582             :     uint8_t lsda_encoding;
    6583             :     struct cieinfo *next;
    6584          50 :   } *cies = NULL;
    6585             : 
    6586          50 :   const unsigned char *readp = data->d_buf;
    6587         100 :   const unsigned char *const dataend = ((unsigned char *) data->d_buf
    6588          50 :                                         + data->d_size);
    6589        4754 :   while (readp < dataend)
    6590             :     {
    6591        4704 :       if (unlikely (readp + 4 > dataend))
    6592             :         {
    6593           0 :         invalid_data:
    6594           0 :           error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
    6595             :                      elf_ndxscn (scn), scnname);
    6596           0 :               return;
    6597             :         }
    6598             : 
    6599             :       /* At the beginning there must be a CIE.  There can be multiple,
    6600             :          hence we test tis in a loop.  */
    6601        4704 :       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
    6602             : 
    6603        4704 :       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
    6604        4704 :       unsigned int length = 4;
    6605        4704 :       if (unlikely (unit_length == 0xffffffff))
    6606             :         {
    6607           0 :           if (unlikely (readp + 8 > dataend))
    6608             :             goto invalid_data;
    6609             : 
    6610           0 :           unit_length = read_8ubyte_unaligned_inc (dbg, readp);
    6611           0 :           length = 8;
    6612             :         }
    6613             : 
    6614        4704 :       if (unlikely (unit_length == 0))
    6615             :         {
    6616          14 :           printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
    6617          14 :           continue;
    6618             :         }
    6619             : 
    6620        4690 :       Dwarf_Word maxsize = dataend - readp;
    6621        4690 :       if (unlikely (unit_length > maxsize))
    6622             :         goto invalid_data;
    6623             : 
    6624        4690 :       unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    6625             : 
    6626        4690 :       ptrdiff_t start = readp - (unsigned char *) data->d_buf;
    6627        4690 :       const unsigned char *const cieend = readp + unit_length;
    6628        4690 :       if (unlikely (cieend > dataend))
    6629             :         goto invalid_data;
    6630             : 
    6631        4690 :       Dwarf_Off cie_id;
    6632        4690 :       if (length == 4)
    6633             :         {
    6634        4690 :           if (unlikely (cieend - readp < 4))
    6635             :             goto invalid_data;
    6636        4690 :           cie_id = read_4ubyte_unaligned_inc (dbg, readp);
    6637        4690 :           if (!is_eh_frame && cie_id == DW_CIE_ID_32)
    6638          38 :             cie_id = DW_CIE_ID_64;
    6639             :         }
    6640             :       else
    6641             :         {
    6642           0 :           if (unlikely (cieend - readp < 8))
    6643             :             goto invalid_data;
    6644           0 :           cie_id = read_8ubyte_unaligned_inc (dbg, readp);
    6645             :         }
    6646             : 
    6647        4690 :       uint_fast8_t version = 2;
    6648        4690 :       unsigned int code_alignment_factor;
    6649        4690 :       int data_alignment_factor;
    6650        4690 :       unsigned int fde_encoding = 0;
    6651        4690 :       unsigned int lsda_encoding = 0;
    6652        4690 :       Dwarf_Word initial_location = 0;
    6653        4690 :       Dwarf_Word vma_base = 0;
    6654             : 
    6655        4770 :       if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
    6656             :         {
    6657         103 :           if (unlikely (cieend - readp < 2))
    6658             :             goto invalid_data;
    6659         103 :           version = *readp++;
    6660         103 :           const char *const augmentation = (const char *) readp;
    6661         103 :           readp = memchr (readp, '\0', cieend - readp);
    6662         103 :           if (unlikely (readp == NULL))
    6663             :             goto invalid_data;
    6664         103 :           ++readp;
    6665             : 
    6666         103 :           uint_fast8_t segment_size = 0;
    6667         103 :           if (version >= 4)
    6668             :             {
    6669           0 :               if (cieend - readp < 5)
    6670             :                 goto invalid_data;
    6671           0 :               ptr_size = *readp++;
    6672           0 :               segment_size = *readp++;
    6673             :             }
    6674             : 
    6675         103 :           if (cieend - readp < 1)
    6676             :             goto invalid_data;
    6677         103 :           get_uleb128 (code_alignment_factor, readp, cieend);
    6678         103 :           if (cieend - readp < 1)
    6679             :             goto invalid_data;
    6680         103 :           get_sleb128 (data_alignment_factor, readp, cieend);
    6681             : 
    6682             :           /* In some variant for unwind data there is another field.  */
    6683         103 :           if (strcmp (augmentation, "eh") == 0)
    6684           0 :             readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    6685             : 
    6686         103 :           unsigned int return_address_register;
    6687         103 :           if (cieend - readp < 1)
    6688             :             goto invalid_data;
    6689         103 :           if (unlikely (version == 1))
    6690          91 :             return_address_register = *readp++;
    6691             :           else
    6692          12 :             get_uleb128 (return_address_register, readp, cieend);
    6693             : 
    6694         103 :           printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
    6695             :                   "   CIE_id:                   %" PRIu64 "\n"
    6696             :                   "   version:                  %u\n"
    6697             :                   "   augmentation:             \"%s\"\n",
    6698             :                   offset, (uint64_t) unit_length, (uint64_t) cie_id,
    6699             :                   version, augmentation);
    6700         103 :           if (version >= 4)
    6701           0 :             printf ("   address_size:             %u\n"
    6702             :                     "   segment_size:             %u\n",
    6703             :                     ptr_size, segment_size);
    6704         103 :           printf ("   code_alignment_factor:    %u\n"
    6705             :                   "   data_alignment_factor:    %d\n"
    6706             :                   "   return_address_register:  %u\n",
    6707             :                   code_alignment_factor,
    6708             :                   data_alignment_factor, return_address_register);
    6709             : 
    6710         103 :           if (augmentation[0] == 'z')
    6711             :             {
    6712          63 :               unsigned int augmentationlen;
    6713          63 :               get_uleb128 (augmentationlen, readp, cieend);
    6714             : 
    6715          63 :               if (augmentationlen > (size_t) (cieend - readp))
    6716             :                 {
    6717           0 :                   error (0, 0, gettext ("invalid augmentation length"));
    6718           0 :                   readp = cieend;
    6719           0 :                   continue;
    6720             :                 }
    6721             : 
    6722          63 :               const char *hdr = "Augmentation data:";
    6723          63 :               const char *cp = augmentation + 1;
    6724         126 :               while (*cp != '\0' && cp < augmentation + augmentationlen + 1)
    6725             :                 {
    6726          63 :                   printf ("   %-26s%#x ", hdr, *readp);
    6727          63 :                   hdr = "";
    6728             : 
    6729          63 :                   if (*cp == 'R')
    6730             :                     {
    6731          63 :                       fde_encoding = *readp++;
    6732          63 :                       print_encoding_base (gettext ("FDE address encoding: "),
    6733             :                                            fde_encoding);
    6734             :                     }
    6735           0 :                   else if (*cp == 'L')
    6736             :                     {
    6737           0 :                       lsda_encoding = *readp++;
    6738           0 :                       print_encoding_base (gettext ("LSDA pointer encoding: "),
    6739             :                                            lsda_encoding);
    6740             :                     }
    6741           0 :                   else if (*cp == 'P')
    6742             :                     {
    6743             :                       /* Personality.  This field usually has a relocation
    6744             :                          attached pointing to __gcc_personality_v0.  */
    6745           0 :                       const unsigned char *startp = readp;
    6746           0 :                       unsigned int encoding = *readp++;
    6747           0 :                       uint64_t val = 0;
    6748           0 :                       readp = read_encoded (encoding, readp,
    6749           0 :                                             readp - 1 + augmentationlen,
    6750             :                                             &val, dbg);
    6751             : 
    6752           0 :                       while (++startp < readp)
    6753           0 :                         printf ("%#x ", *startp);
    6754             : 
    6755           0 :                       putchar ('(');
    6756           0 :                       print_encoding (encoding);
    6757           0 :                       putchar (' ');
    6758           0 :                       switch (encoding & 0xf)
    6759             :                         {
    6760           0 :                         case DW_EH_PE_sleb128:
    6761             :                         case DW_EH_PE_sdata2:
    6762             :                         case DW_EH_PE_sdata4:
    6763           0 :                           printf ("%" PRId64 ")\n", val);
    6764             :                           break;
    6765           0 :                         default:
    6766           0 :                           printf ("%#" PRIx64 ")\n", val);
    6767             :                           break;
    6768             :                         }
    6769             :                     }
    6770             :                   else
    6771           0 :                     printf ("(%x)\n", *readp++);
    6772             : 
    6773          63 :                   ++cp;
    6774             :                 }
    6775             :             }
    6776             : 
    6777         103 :           if (likely (ptr_size == 4 || ptr_size == 8))
    6778             :             {
    6779         103 :               struct cieinfo *newp = alloca (sizeof (*newp));
    6780         103 :               newp->cie_offset = offset;
    6781         103 :               newp->augmentation = augmentation;
    6782         103 :               newp->fde_encoding = fde_encoding;
    6783         103 :               newp->lsda_encoding = lsda_encoding;
    6784         103 :               newp->address_size = ptr_size;
    6785         103 :               newp->code_alignment_factor = code_alignment_factor;
    6786         103 :               newp->data_alignment_factor = data_alignment_factor;
    6787         103 :               newp->next = cies;
    6788         103 :               cies = newp;
    6789             :             }
    6790             :         }
    6791             :       else
    6792             :         {
    6793             :           struct cieinfo *cie = cies;
    6794        9894 :           while (cie != NULL)
    6795       19788 :             if (is_eh_frame
    6796        9852 :                 ? ((Dwarf_Off) start - cie_id) == (Dwarf_Off) cie->cie_offset
    6797          42 :                 : cie_id == (Dwarf_Off) cie->cie_offset)
    6798             :               break;
    6799             :             else
    6800        5307 :               cie = cie->next;
    6801        4587 :           if (unlikely (cie == NULL))
    6802             :             {
    6803           0 :               puts ("invalid CIE reference in FDE");
    6804           0 :               return;
    6805             :             }
    6806             : 
    6807             :           /* Initialize from CIE data.  */
    6808        4587 :           fde_encoding = cie->fde_encoding;
    6809        4587 :           lsda_encoding = cie->lsda_encoding;
    6810        4587 :           ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
    6811        4587 :           code_alignment_factor = cie->code_alignment_factor;
    6812        4587 :           data_alignment_factor = cie->data_alignment_factor;
    6813             : 
    6814        4587 :           const unsigned char *base = readp;
    6815             :           // XXX There are sometimes relocations for this value
    6816        4587 :           initial_location = read_addr_unaligned_inc (ptr_size, dbg, readp);
    6817        9174 :           Dwarf_Word address_range
    6818        4587 :             = read_addr_unaligned_inc (ptr_size, dbg, readp);
    6819             : 
    6820             :           /* pcrel for an FDE address is relative to the runtime
    6821             :              address of the start_address field itself.  Sign extend
    6822             :              if necessary to make sure the calculation is done on the
    6823             :              full 64 bit address even when initial_location only holds
    6824             :              the lower 32 bits.  */
    6825        4587 :           Dwarf_Addr pc_start = initial_location;
    6826        4587 :           if (ptr_size == 4)
    6827        4547 :             pc_start = (uint64_t) (int32_t) pc_start;
    6828        4587 :           if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
    6829        9078 :             pc_start += ((uint64_t) shdr->sh_addr
    6830        4539 :                          + (base - (const unsigned char *) data->d_buf)
    6831        4539 :                          - bias);
    6832             : 
    6833        4587 :           printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
    6834             :                   "   CIE_pointer:              %" PRIu64 "\n"
    6835             :                   "   initial_location:         ",
    6836             :                   offset, (uint64_t) unit_length,
    6837             :                   cie->cie_offset, (uint64_t) cie_id);
    6838        4587 :           print_dwarf_addr (dwflmod, cie->address_size,
    6839             :                             pc_start, initial_location);
    6840        4587 :           if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
    6841             :             {
    6842        9078 :               vma_base = (((uint64_t) shdr->sh_offset
    6843        4539 :                            + (base - (const unsigned char *) data->d_buf)
    6844        4539 :                            + (uint64_t) initial_location)
    6845             :                           & (ptr_size == 4
    6846             :                              ? UINT64_C (0xffffffff)
    6847        4539 :                              : UINT64_C (0xffffffffffffffff)));
    6848        4539 :               printf (gettext (" (offset: %#" PRIx64 ")"),
    6849             :                       (uint64_t) vma_base);
    6850             :             }
    6851             : 
    6852        4587 :           printf ("\n   address_range:            %#" PRIx64,
    6853             :                   (uint64_t) address_range);
    6854        4587 :           if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
    6855        4539 :             printf (gettext (" (end offset: %#" PRIx64 ")"),
    6856        4539 :                     ((uint64_t) vma_base + (uint64_t) address_range)
    6857             :                     & (ptr_size == 4
    6858             :                        ? UINT64_C (0xffffffff)
    6859        4539 :                        : UINT64_C (0xffffffffffffffff)));
    6860        4587 :           putchar ('\n');
    6861             : 
    6862        4587 :           if (cie->augmentation[0] == 'z')
    6863             :             {
    6864        4539 :               unsigned int augmentationlen;
    6865        4539 :               if (cieend - readp < 1)
    6866             :                 goto invalid_data;
    6867        4539 :               get_uleb128 (augmentationlen, readp, cieend);
    6868             : 
    6869        4539 :               if (augmentationlen > (size_t) (cieend - readp))
    6870             :                 {
    6871           0 :                   error (0, 0, gettext ("invalid augmentation length"));
    6872           0 :                   readp = cieend;
    6873           0 :                   continue;
    6874             :                 }
    6875             : 
    6876        4539 :               if (augmentationlen > 0)
    6877             :                 {
    6878           0 :                   const char *hdr = "Augmentation data:";
    6879           0 :                   const char *cp = cie->augmentation + 1;
    6880           0 :                   unsigned int u = 0;
    6881           0 :                   while (*cp != '\0'
    6882           0 :                          && cp < cie->augmentation + augmentationlen + 1)
    6883             :                     {
    6884           0 :                       if (*cp == 'L')
    6885             :                         {
    6886           0 :                           uint64_t lsda_pointer;
    6887           0 :                           const unsigned char *p
    6888           0 :                             = read_encoded (lsda_encoding, &readp[u],
    6889             :                                             &readp[augmentationlen],
    6890             :                                             &lsda_pointer, dbg);
    6891           0 :                           u = p - readp;
    6892           0 :                           printf (gettext ("\
    6893             :    %-26sLSDA pointer: %#" PRIx64 "\n"),
    6894             :                                   hdr, lsda_pointer);
    6895           0 :                           hdr = "";
    6896             :                         }
    6897           0 :                       ++cp;
    6898             :                     }
    6899             : 
    6900           0 :                   while (u < augmentationlen)
    6901             :                     {
    6902           0 :                       printf ("   %-26s%#x\n", hdr, readp[u++]);
    6903           0 :                       hdr = "";
    6904             :                     }
    6905             :                 }
    6906             : 
    6907        4539 :               readp += augmentationlen;
    6908             :             }
    6909             :         }
    6910             : 
    6911             :       /* Handle the initialization instructions.  */
    6912        4690 :       if (ptr_size != 4 && ptr_size !=8)
    6913           0 :         printf ("invalid CIE pointer size (%u), must be 4 or 8.\n", ptr_size);
    6914             :       else
    6915        4690 :         print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
    6916             :                            data_alignment_factor, version, ptr_size,
    6917             :                            fde_encoding, dwflmod, ebl, dbg);
    6918        4690 :       readp = cieend;
    6919             :     }
    6920             : }
    6921             : 
    6922             : 
    6923             : /* Returns the signedness (or false if it cannot be determined) and
    6924             :    the byte size (or zero if it cannot be gotten) of the given DIE
    6925             :    DW_AT_type attribute.  Uses dwarf_peel_type and dwarf_aggregate_size.  */
    6926             : static void
    6927      100758 : die_type_sign_bytes (Dwarf_Die *die, bool *is_signed, int *bytes)
    6928             : {
    6929      100758 :   Dwarf_Attribute attr;
    6930      100758 :   Dwarf_Die type;
    6931             : 
    6932      100758 :   *bytes = 0;
    6933      100758 :   *is_signed = false;
    6934             : 
    6935      100758 :   if (dwarf_peel_type (dwarf_formref_die (dwarf_attr_integrate (die,
    6936             :                                                                 DW_AT_type,
    6937             :                                                                 &attr), &type),
    6938             :                        &type) == 0)
    6939             :     {
    6940         221 :       Dwarf_Word val;
    6941         221 :       *is_signed = (dwarf_formudata (dwarf_attr (&type, DW_AT_encoding,
    6942             :                                                  &attr), &val) == 0
    6943         221 :                     && (val == DW_ATE_signed || val == DW_ATE_signed_char));
    6944             : 
    6945         221 :       if (dwarf_aggregate_size (&type, &val) == 0)
    6946         221 :         *bytes = val;
    6947             :     }
    6948      100758 : }
    6949             : 
    6950             : struct attrcb_args
    6951             : {
    6952             :   Dwfl_Module *dwflmod;
    6953             :   Dwarf *dbg;
    6954             :   Dwarf_Die *dies;
    6955             :   int level;
    6956             :   bool silent;
    6957             :   bool is_split;
    6958             :   unsigned int version;
    6959             :   unsigned int addrsize;
    6960             :   unsigned int offset_size;
    6961             :   struct Dwarf_CU *cu;
    6962             : };
    6963             : 
    6964             : 
    6965             : static int
    6966     2889726 : attr_callback (Dwarf_Attribute *attrp, void *arg)
    6967             : {
    6968     2889726 :   struct attrcb_args *cbargs = (struct attrcb_args *) arg;
    6969     2889726 :   const int level = cbargs->level;
    6970     2889726 :   Dwarf_Die *die = &cbargs->dies[level];
    6971     2889726 :   bool is_split = cbargs->is_split;
    6972             : 
    6973     2889726 :   unsigned int attr = dwarf_whatattr (attrp);
    6974     2889726 :   if (unlikely (attr == 0))
    6975             :     {
    6976           0 :       if (!cbargs->silent)
    6977           0 :         error (0, 0, gettext ("DIE [%" PRIx64 "] "
    6978             :                               "cannot get attribute code: %s"),
    6979             :                dwarf_dieoffset (die), dwarf_errmsg (-1));
    6980           0 :       return DWARF_CB_ABORT;
    6981             :     }
    6982             : 
    6983     2889726 :   unsigned int form = dwarf_whatform (attrp);
    6984     2889726 :   if (unlikely (form == 0))
    6985             :     {
    6986           0 :       if (!cbargs->silent)
    6987           0 :         error (0, 0, gettext ("DIE [%" PRIx64 "] "
    6988             :                               "cannot get attribute form: %s"),
    6989             :                dwarf_dieoffset (die), dwarf_errmsg (-1));
    6990           0 :       return DWARF_CB_ABORT;
    6991             :     }
    6992             : 
    6993     2889726 :   switch (form)
    6994             :     {
    6995       44783 :     case DW_FORM_addr:
    6996             :     case DW_FORM_addrx:
    6997             :     case DW_FORM_addrx1:
    6998             :     case DW_FORM_addrx2:
    6999             :     case DW_FORM_addrx3:
    7000             :     case DW_FORM_addrx4:
    7001             :     case DW_FORM_GNU_addr_index:
    7002       44783 :       if (!cbargs->silent)
    7003             :         {
    7004       44514 :           Dwarf_Addr addr;
    7005       44514 :           if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
    7006             :             {
    7007           0 :             attrval_out:
    7008           0 :               if (!cbargs->silent)
    7009           0 :                 error (0, 0, gettext ("DIE [%" PRIx64 "] "
    7010             :                                       "cannot get attribute '%s' (%s) value: "
    7011             :                                       "%s"),
    7012             :                        dwarf_dieoffset (die),
    7013             :                        dwarf_attr_name (attr),
    7014             :                        dwarf_form_name (form),
    7015             :                        dwarf_errmsg (-1));
    7016             :               /* Don't ABORT, it might be other attributes can be resolved.  */
    7017           0 :               return DWARF_CB_OK;
    7018             :             }
    7019       44514 :           if (form != DW_FORM_addr )
    7020             :             {
    7021           8 :               Dwarf_Word word;
    7022           8 :               if (dwarf_formudata (attrp, &word) != 0)
    7023           0 :                 goto attrval_out;
    7024           8 :               printf ("           %*s%-20s (%s) [%" PRIx64 "] ",
    7025             :                       (int) (level * 2), "", dwarf_attr_name (attr),
    7026             :                       dwarf_form_name (form), word);
    7027             :             }
    7028             :           else
    7029       44506 :             printf ("           %*s%-20s (%s) ",
    7030             :                     (int) (level * 2), "", dwarf_attr_name (attr),
    7031             :                     dwarf_form_name (form));
    7032       44514 :           print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr, addr);
    7033       44514 :           printf ("\n");
    7034             :         }
    7035     2581704 :       break;
    7036             : 
    7037      465635 :     case DW_FORM_indirect:
    7038             :     case DW_FORM_strp:
    7039             :     case DW_FORM_line_strp:
    7040             :     case DW_FORM_strx:
    7041             :     case DW_FORM_strx1:
    7042             :     case DW_FORM_strx2:
    7043             :     case DW_FORM_strx3:
    7044             :     case DW_FORM_strx4:
    7045             :     case DW_FORM_string:
    7046             :     case DW_FORM_GNU_strp_alt:
    7047             :     case DW_FORM_GNU_str_index:
    7048      465635 :       if (cbargs->silent)
    7049             :         break;
    7050      464887 :       const char *str = dwarf_formstring (attrp);
    7051      464887 :       if (unlikely (str == NULL))
    7052             :         goto attrval_out;
    7053      464887 :       printf ("           %*s%-20s (%s) \"%s\"\n",
    7054             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7055             :               dwarf_form_name (form), str);
    7056             :       break;
    7057             : 
    7058      596489 :     case DW_FORM_ref_addr:
    7059             :     case DW_FORM_ref_udata:
    7060             :     case DW_FORM_ref8:
    7061             :     case DW_FORM_ref4:
    7062             :     case DW_FORM_ref2:
    7063             :     case DW_FORM_ref1:
    7064             :     case DW_FORM_GNU_ref_alt:
    7065             :     case DW_FORM_ref_sup4:
    7066             :     case DW_FORM_ref_sup8:
    7067      596489 :       if (cbargs->silent)
    7068             :         break;
    7069      595702 :       Dwarf_Die ref;
    7070      595702 :       if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
    7071             :         goto attrval_out;
    7072             : 
    7073      595702 :       printf ("           %*s%-20s (%s) ",
    7074             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7075             :               dwarf_form_name (form));
    7076      595702 :       if (is_split)
    7077          33 :         printf ("{%6" PRIxMAX "}\n", (uintmax_t) dwarf_dieoffset (&ref));
    7078             :       else
    7079      595669 :         printf ("[%6" PRIxMAX "]\n", (uintmax_t) dwarf_dieoffset (&ref));
    7080             :       break;
    7081             : 
    7082           4 :     case DW_FORM_ref_sig8:
    7083           4 :       if (cbargs->silent)
    7084             :         break;
    7085           4 :       printf ("           %*s%-20s (%s) {%6" PRIx64 "}\n",
    7086             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7087             :               dwarf_form_name (form),
    7088           4 :               (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
    7089             :       break;
    7090             : 
    7091     1627835 :     case DW_FORM_sec_offset:
    7092             :     case DW_FORM_rnglistx:
    7093             :     case DW_FORM_loclistx:
    7094             :     case DW_FORM_implicit_const:
    7095             :     case DW_FORM_udata:
    7096             :     case DW_FORM_sdata:
    7097             :     case DW_FORM_data8: /* Note no data16 here, we see that as block. */
    7098             :     case DW_FORM_data4:
    7099             :     case DW_FORM_data2:
    7100     1627835 :     case DW_FORM_data1:;
    7101     1627835 :       Dwarf_Word num;
    7102     1627835 :       if (unlikely (dwarf_formudata (attrp, &num) != 0))
    7103             :         goto attrval_out;
    7104             : 
    7105     1627835 :       const char *valuestr = NULL;
    7106     1627835 :       bool as_hex_id = false;
    7107     1627835 :       switch (attr)
    7108             :         {
    7109             :           /* This case can take either a constant or a loclistptr.  */
    7110      206746 :         case DW_AT_data_member_location:
    7111      206746 :           if (form != DW_FORM_sec_offset
    7112      206746 :               && (cbargs->version >= 4
    7113       23806 :                   || (form != DW_FORM_data4 && form != DW_FORM_data8)))
    7114             :             {
    7115      206746 :               if (!cbargs->silent)
    7116      206746 :                 printf ("           %*s%-20s (%s) %" PRIuMAX "\n",
    7117             :                         (int) (level * 2), "", dwarf_attr_name (attr),
    7118             :                         dwarf_form_name (form), (uintmax_t) num);
    7119      206746 :               return DWARF_CB_OK;
    7120             :             }
    7121       87891 :           FALLTHROUGH;
    7122             : 
    7123             :         /* These cases always take a loclist[ptr] and no constant. */
    7124             :         case DW_AT_location:
    7125             :         case DW_AT_data_location:
    7126             :         case DW_AT_vtable_elem_location:
    7127             :         case DW_AT_string_length:
    7128             :         case DW_AT_use_location:
    7129             :         case DW_AT_frame_base:
    7130             :         case DW_AT_return_addr:
    7131             :         case DW_AT_static_link:
    7132             :         case DW_AT_segment:
    7133             :         case DW_AT_GNU_call_site_value:
    7134             :         case DW_AT_GNU_call_site_data_value:
    7135             :         case DW_AT_GNU_call_site_target:
    7136             :         case DW_AT_GNU_call_site_target_clobbered:
    7137             :         case DW_AT_GNU_locviews:
    7138             :           {
    7139       87891 :             bool nlpt;
    7140       87891 :             if (cbargs->cu->version < 5)
    7141             :               {
    7142       87820 :                 if (! cbargs->is_split)
    7143             :                   {
    7144      263400 :                     nlpt = notice_listptr (section_loc, &known_locsptr,
    7145       87800 :                                            cbargs->addrsize,
    7146       87800 :                                            cbargs->offset_size,
    7147             :                                            cbargs->cu, num, attr);
    7148             :                   }
    7149             :                 else
    7150             :                   nlpt = true;
    7151             :               }
    7152             :             else
    7153             :               {
    7154             :                 /* Only register for a real section offset.  Otherwise
    7155             :                    it is a DW_FORM_loclistx which is just an index
    7156             :                    number and we should already have registered the
    7157             :                    section offset for the index when we saw the
    7158             :                    DW_AT_loclists_base CU attribute.  */
    7159          71 :                 if (form == DW_FORM_sec_offset)
    7160          96 :                   nlpt = notice_listptr (section_loc, &known_loclistsptr,
    7161          32 :                                          cbargs->addrsize, cbargs->offset_size,
    7162             :                                          cbargs->cu, num, attr);
    7163             :                 else
    7164             :                   nlpt = true;
    7165             : 
    7166             :               }
    7167             : 
    7168       87891 :             if (!cbargs->silent)
    7169             :               {
    7170       87710 :                 if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
    7171       87703 :                   printf ("           %*s%-20s (%s) location list [%6"
    7172             :                           PRIxMAX "]%s\n",
    7173             :                           (int) (level * 2), "", dwarf_attr_name (attr),
    7174             :                           dwarf_form_name (form), (uintmax_t) num,
    7175             :                           nlpt ? "" : " <WARNING offset too big>");
    7176             :                 else
    7177           7 :                   printf ("           %*s%-20s (%s) location index [%6"
    7178             :                           PRIxMAX "]\n",
    7179             :                           (int) (level * 2), "", dwarf_attr_name (attr),
    7180             :                           dwarf_form_name (form), (uintmax_t) num);
    7181             :               }
    7182             :           }
    7183             :           return DWARF_CB_OK;
    7184             : 
    7185           5 :         case DW_AT_loclists_base:
    7186           4 :           {
    7187          20 :             bool nlpt = notice_listptr (section_loc, &known_loclistsptr,
    7188           5 :                                         cbargs->addrsize, cbargs->offset_size,
    7189             :                                         cbargs->cu, num, attr);
    7190             : 
    7191           5 :             if (!cbargs->silent)
    7192           1 :               printf ("           %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n",
    7193             :                       (int) (level * 2), "", dwarf_attr_name (attr),
    7194             :                       dwarf_form_name (form), (uintmax_t) num,
    7195             :                       nlpt ? "" : " <WARNING offset too big>");
    7196             :           }
    7197             :           return DWARF_CB_OK;
    7198             : 
    7199       13363 :         case DW_AT_ranges:
    7200             :         case DW_AT_start_scope:
    7201             :           {
    7202       13363 :             bool nlpt;
    7203       13363 :             if (cbargs->cu->version < 5)
    7204       40041 :               nlpt = notice_listptr (section_ranges, &known_rangelistptr,
    7205       13347 :                                      cbargs->addrsize, cbargs->offset_size,
    7206             :                                      cbargs->cu, num, attr);
    7207             :             else
    7208             :               {
    7209             :                 /* Only register for a real section offset.  Otherwise
    7210             :                    it is a DW_FORM_rangelistx which is just an index
    7211             :                    number and we should already have registered the
    7212             :                    section offset for the index when we saw the
    7213             :                    DW_AT_rnglists_base CU attribute.  */
    7214          16 :                 if (form == DW_FORM_sec_offset)
    7215          30 :                   nlpt = notice_listptr (section_ranges, &known_rnglistptr,
    7216          10 :                                          cbargs->addrsize, cbargs->offset_size,
    7217             :                                          cbargs->cu, num, attr);
    7218             :                 else
    7219             :                   nlpt = true;
    7220             :               }
    7221             : 
    7222       13363 :             if (!cbargs->silent)
    7223             :               {
    7224       13321 :                 if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
    7225       13319 :                   printf ("           %*s%-20s (%s) range list [%6"
    7226             :                           PRIxMAX "]%s\n",
    7227             :                           (int) (level * 2), "", dwarf_attr_name (attr),
    7228             :                           dwarf_form_name (form), (uintmax_t) num,
    7229             :                           nlpt ? "" : " <WARNING offset too big>");
    7230             :                 else
    7231           2 :                   printf ("           %*s%-20s (%s) range index [%6"
    7232             :                           PRIxMAX "]\n",
    7233             :                           (int) (level * 2), "", dwarf_attr_name (attr),
    7234             :                           dwarf_form_name (form), (uintmax_t) num);
    7235             :               }
    7236             :           }
    7237             :           return DWARF_CB_OK;
    7238             : 
    7239           4 :         case DW_AT_rnglists_base:
    7240           2 :           {
    7241          16 :             bool nlpt = notice_listptr (section_ranges, &known_rnglistptr,
    7242           4 :                                         cbargs->addrsize, cbargs->offset_size,
    7243             :                                         cbargs->cu, num, attr);
    7244           4 :             if (!cbargs->silent)
    7245           2 :               printf ("           %*s%-20s (%s) range list [%6"
    7246             :                       PRIxMAX "]%s\n",
    7247             :                       (int) (level * 2), "", dwarf_attr_name (attr),
    7248             :                       dwarf_form_name (form), (uintmax_t) num,
    7249             :                       nlpt ? "" : " <WARNING offset too big>");
    7250             :           }
    7251             :           return DWARF_CB_OK;
    7252             : 
    7253          13 :         case DW_AT_addr_base:
    7254             :         case DW_AT_GNU_addr_base:
    7255           8 :           {
    7256          52 :             bool addrbase = notice_listptr (section_addr, &known_addrbases,
    7257          13 :                                             cbargs->addrsize,
    7258          13 :                                             cbargs->offset_size,
    7259             :                                             cbargs->cu, num, attr);
    7260          13 :             if (!cbargs->silent)
    7261           5 :               printf ("           %*s%-20s (%s) address base [%6"
    7262             :                       PRIxMAX "]%s\n",
    7263             :                       (int) (level * 2), "", dwarf_attr_name (attr),
    7264             :                       dwarf_form_name (form), (uintmax_t) num,
    7265             :                       addrbase ? "" : " <WARNING offset too big>");
    7266             :           }
    7267             :           return DWARF_CB_OK;
    7268             : 
    7269           0 :         case DW_AT_str_offsets_base:
    7270           0 :           {
    7271           0 :             bool stroffbase = notice_listptr (section_str, &known_stroffbases,
    7272           0 :                                               cbargs->addrsize,
    7273           0 :                                               cbargs->offset_size,
    7274             :                                               cbargs->cu, num, attr);
    7275           0 :             if (!cbargs->silent)
    7276           0 :               printf ("           %*s%-20s (%s) str offsets base [%6"
    7277             :                       PRIxMAX "]%s\n",
    7278             :                       (int) (level * 2), "", dwarf_attr_name (attr),
    7279             :                       dwarf_form_name (form), (uintmax_t) num,
    7280             :                       stroffbase ? "" : " <WARNING offset too big>");
    7281             :           }
    7282             :           return DWARF_CB_OK;
    7283             : 
    7284        1162 :         case DW_AT_language:
    7285        1162 :           valuestr = dwarf_lang_name (num);
    7286        1162 :           break;
    7287       16569 :         case DW_AT_encoding:
    7288       16569 :           valuestr = dwarf_encoding_name (num);
    7289       16569 :           break;
    7290           0 :         case DW_AT_accessibility:
    7291           0 :           valuestr = dwarf_access_name (num);
    7292           0 :           break;
    7293           0 :         case DW_AT_defaulted:
    7294           0 :           valuestr = dwarf_defaulted_name (num);
    7295           0 :           break;
    7296           0 :         case DW_AT_visibility:
    7297           0 :           valuestr = dwarf_visibility_name (num);
    7298           0 :           break;
    7299           0 :         case DW_AT_virtuality:
    7300           0 :           valuestr = dwarf_virtuality_name (num);
    7301           0 :           break;
    7302           0 :         case DW_AT_identifier_case:
    7303           0 :           valuestr = dwarf_identifier_case_name (num);
    7304           0 :           break;
    7305           0 :         case DW_AT_calling_convention:
    7306           0 :           valuestr = dwarf_calling_convention_name (num);
    7307           0 :           break;
    7308        2934 :         case DW_AT_inline:
    7309        2934 :           valuestr = dwarf_inline_name (num);
    7310        2934 :           break;
    7311           0 :         case DW_AT_ordering:
    7312           0 :           valuestr = dwarf_ordering_name (num);
    7313           0 :           break;
    7314      365501 :         case DW_AT_decl_file:
    7315             :         case DW_AT_call_file:
    7316         421 :           {
    7317      365501 :             if (cbargs->silent)
    7318             :               break;
    7319             : 
    7320             :             /* Try to get the actual file, the current interface only
    7321             :                gives us full paths, but we only want to show the file
    7322             :                name for now.  */
    7323      365080 :             Dwarf_Die cudie;
    7324      365080 :             if (dwarf_cu_die (cbargs->cu, &cudie,
    7325             :                               NULL, NULL, NULL, NULL, NULL, NULL) != NULL)
    7326             :               {
    7327      365080 :                 Dwarf_Files *files;
    7328      365080 :                 size_t nfiles;
    7329      365080 :                 if (dwarf_getsrcfiles (&cudie, &files, &nfiles) == 0)
    7330             :                   {
    7331      365080 :                     valuestr = dwarf_filesrc (files, num, NULL, NULL);
    7332      365080 :                     if (valuestr != NULL)
    7333             :                       {
    7334      365080 :                         char *filename = strrchr (valuestr, '/');
    7335      365080 :                         if (filename != NULL)
    7336      365080 :                           valuestr = filename + 1;
    7337             :                       }
    7338             :                     else
    7339           0 :                       error (0, 0, gettext ("invalid file (%" PRId64 "): %s"),
    7340             :                              num, dwarf_errmsg (-1));
    7341             :                   }
    7342             :                 else
    7343           0 :                   error (0, 0, gettext ("no srcfiles for CU [%" PRIx64 "]"),
    7344             :                          dwarf_dieoffset (&cudie));
    7345             :               }
    7346             :             else
    7347           0 :              error (0, 0, gettext ("couldn't get DWARF CU: %s"),
    7348             :                     dwarf_errmsg (-1));
    7349      365080 :             if (valuestr == NULL)
    7350             :               valuestr = "???";
    7351             :           }
    7352      365080 :           break;
    7353          13 :         case DW_AT_GNU_dwo_id:
    7354          13 :           as_hex_id = true;
    7355          13 :           break;
    7356             : 
    7357             :         default:
    7358             :           /* Nothing.  */
    7359             :           break;
    7360             :         }
    7361             : 
    7362     1319813 :       if (cbargs->silent)
    7363             :         break;
    7364             : 
    7365             :       /* When highpc is in constant form it is relative to lowpc.
    7366             :          In that case also show the address.  */
    7367     1317972 :       Dwarf_Addr highpc;
    7368     1317972 :       if (attr == DW_AT_high_pc && dwarf_highpc (die, &highpc) == 0)
    7369             :         {
    7370       11777 :           printf ("           %*s%-20s (%s) %" PRIuMAX " (",
    7371             :                   (int) (level * 2), "", dwarf_attr_name (attr),
    7372             :                   dwarf_form_name (form), (uintmax_t) num);
    7373       11777 :           print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, highpc, highpc);
    7374       11777 :           printf (")\n");
    7375             :         }
    7376             :       else
    7377             :         {
    7378     1306195 :           if (as_hex_id)
    7379             :             {
    7380           2 :               printf ("           %*s%-20s (%s) 0x%.16" PRIx64 "\n",
    7381             :                       (int) (level * 2), "", dwarf_attr_name (attr),
    7382             :                       dwarf_form_name (form), num);
    7383             :             }
    7384             :           else
    7385     1306193 :             {
    7386     1306193 :               Dwarf_Sword snum = 0;
    7387     1306193 :               bool is_signed;
    7388     1306193 :               int bytes = 0;
    7389     1306193 :               if (attr == DW_AT_const_value)
    7390      100754 :                 die_type_sign_bytes (die, &is_signed, &bytes);
    7391             :               else
    7392     2410878 :                 is_signed = (form == DW_FORM_sdata
    7393     1205439 :                              || form == DW_FORM_implicit_const);
    7394             : 
    7395     1306193 :               if (is_signed)
    7396         150 :                 if (unlikely (dwarf_formsdata (attrp, &snum) != 0))
    7397           0 :                   goto attrval_out;
    7398             : 
    7399     1306193 :               if (valuestr == NULL)
    7400             :                 {
    7401      920751 :                   printf ("           %*s%-20s (%s) ",
    7402             :                           (int) (level * 2), "", dwarf_attr_name (attr),
    7403             :                           dwarf_form_name (form));
    7404             :                 }
    7405             :               else
    7406             :                 {
    7407      385442 :                   printf ("           %*s%-20s (%s) %s (",
    7408             :                           (int) (level * 2), "", dwarf_attr_name (attr),
    7409             :                           dwarf_form_name (form), valuestr);
    7410             :                 }
    7411             : 
    7412     1306193 :               switch (bytes)
    7413             :                 {
    7414           2 :                 case 1:
    7415           2 :                   if (is_signed)
    7416           1 :                     printf ("%" PRId8, (int8_t) snum);
    7417             :                   else
    7418           1 :                     printf ("%" PRIu8, (uint8_t) num);
    7419             :                   break;
    7420             : 
    7421           2 :                 case 2:
    7422           2 :                   if (is_signed)
    7423           1 :                     printf ("%" PRId16, (int16_t) snum);
    7424             :                   else
    7425           1 :                     printf ("%" PRIu16, (uint16_t) num);
    7426             :                   break;
    7427             : 
    7428         128 :                 case 4:
    7429         128 :                   if (is_signed)
    7430         125 :                     printf ("%" PRId32, (int32_t) snum);
    7431             :                   else
    7432           3 :                     printf ("%" PRIu32, (uint32_t) num);
    7433             :                   break;
    7434             : 
    7435          85 :                 case 8:
    7436          85 :                   if (is_signed)
    7437           1 :                     printf ("%" PRId64, (int64_t) snum);
    7438             :                   else
    7439          84 :                     printf ("%" PRIu64, (uint64_t) num);
    7440             :                   break;
    7441             : 
    7442     1305976 :                 default:
    7443     1305976 :                   if (is_signed)
    7444          22 :                     printf ("%" PRIdMAX, (intmax_t) snum);
    7445             :                   else
    7446     1305954 :                     printf ("%" PRIuMAX, (uintmax_t) num);
    7447             :                   break;
    7448             :                 }
    7449             : 
    7450             :               /* Make clear if we switched from a signed encoding to
    7451             :                  an unsigned value.  */
    7452     1306193 :               if (attr == DW_AT_const_value
    7453      100754 :                   && (form == DW_FORM_sdata || form == DW_FORM_implicit_const)
    7454        1226 :                   && !is_signed)
    7455        1219 :                 printf (" (%" PRIdMAX ")", (intmax_t) num);
    7456             : 
    7457     1306193 :               if (valuestr == NULL)
    7458      920751 :                 printf ("\n");
    7459             :               else
    7460      385442 :                 printf (")\n");
    7461             :             }
    7462             :         }
    7463             :       break;
    7464             : 
    7465        9122 :     case DW_FORM_flag:
    7466        9122 :       if (cbargs->silent)
    7467             :         break;
    7468        9048 :       bool flag;
    7469        9048 :       if (unlikely (dwarf_formflag (attrp, &flag) != 0))
    7470             :         goto attrval_out;
    7471             : 
    7472        9048 :       printf ("           %*s%-20s (%s) %s\n",
    7473             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7474        9048 :               dwarf_form_name (form), flag ? yes_str : no_str);
    7475             :       break;
    7476             : 
    7477       63005 :     case DW_FORM_flag_present:
    7478       63005 :       if (cbargs->silent)
    7479             :         break;
    7480       62731 :       printf ("           %*s%-20s (%s) %s\n",
    7481             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7482             :               dwarf_form_name (form), yes_str);
    7483             :       break;
    7484             : 
    7485       82853 :     case DW_FORM_exprloc:
    7486             :     case DW_FORM_block4:
    7487             :     case DW_FORM_block2:
    7488             :     case DW_FORM_block1:
    7489             :     case DW_FORM_block:
    7490             :     case DW_FORM_data16: /* DWARF5 calls this a constant class.  */
    7491       82853 :       if (cbargs->silent)
    7492             :         break;
    7493       82724 :       Dwarf_Block block;
    7494       82724 :       if (unlikely (dwarf_formblock (attrp, &block) != 0))
    7495             :         goto attrval_out;
    7496             : 
    7497       82724 :       printf ("           %*s%-20s (%s) ",
    7498             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7499             :               dwarf_form_name (form));
    7500             : 
    7501       82724 :       switch (attr)
    7502             :         {
    7503           4 :         default:
    7504           4 :           if (form != DW_FORM_exprloc)
    7505             :             {
    7506           4 :               print_block (block.length, block.data);
    7507           4 :               break;
    7508             :             }
    7509       82716 :           FALLTHROUGH;
    7510             : 
    7511             :         case DW_AT_location:
    7512             :         case DW_AT_data_location:
    7513             :         case DW_AT_data_member_location:
    7514             :         case DW_AT_vtable_elem_location:
    7515             :         case DW_AT_string_length:
    7516             :         case DW_AT_use_location:
    7517             :         case DW_AT_frame_base:
    7518             :         case DW_AT_return_addr:
    7519             :         case DW_AT_static_link:
    7520             :         case DW_AT_allocated:
    7521             :         case DW_AT_associated:
    7522             :         case DW_AT_bit_size:
    7523             :         case DW_AT_bit_offset:
    7524             :         case DW_AT_bit_stride:
    7525             :         case DW_AT_byte_size:
    7526             :         case DW_AT_byte_stride:
    7527             :         case DW_AT_count:
    7528             :         case DW_AT_lower_bound:
    7529             :         case DW_AT_upper_bound:
    7530             :         case DW_AT_GNU_call_site_value:
    7531             :         case DW_AT_GNU_call_site_data_value:
    7532             :         case DW_AT_GNU_call_site_target:
    7533             :         case DW_AT_GNU_call_site_target_clobbered:
    7534       82716 :           if (form != DW_FORM_data16)
    7535             :             {
    7536       82716 :               putchar ('\n');
    7537      248148 :               print_ops (cbargs->dwflmod, cbargs->dbg,
    7538       82716 :                          12 + level * 2, 12 + level * 2,
    7539             :                          cbargs->version, cbargs->addrsize, cbargs->offset_size,
    7540       82716 :                          attrp->cu, block.length, block.data);
    7541             :             }
    7542             :           else
    7543           0 :             print_block (block.length, block.data);
    7544             :           break;
    7545             : 
    7546           4 :         case DW_AT_discr_list:
    7547           4 :           if (block.length == 0)
    7548           0 :             puts ("<default>");
    7549           4 :           else if (form != DW_FORM_data16)
    7550             :             {
    7551           4 :               const unsigned char *readp = block.data;
    7552           4 :               const unsigned char *readendp = readp + block.length;
    7553             : 
    7554             :               /* See if we are dealing with a signed or unsigned
    7555             :                  values.  If the parent of this variant DIE is a
    7556             :                  variant_part then it will either have a discriminant
    7557             :                  which points to the member which type is the
    7558             :                  discriminant type.  Or the variant_part itself has a
    7559             :                  type representing the discriminant.  */
    7560           4 :               bool is_signed = false;
    7561           4 :               if (level > 0)
    7562             :                 {
    7563           4 :                   Dwarf_Die *parent = &cbargs->dies[level - 1];
    7564           4 :                   if (dwarf_tag (die) == DW_TAG_variant
    7565           4 :                       && dwarf_tag (parent) == DW_TAG_variant_part)
    7566             :                     {
    7567           4 :                       Dwarf_Die member;
    7568           4 :                       Dwarf_Attribute discr_attr;
    7569           4 :                       int bytes;
    7570           4 :                       if (dwarf_formref_die (dwarf_attr (parent,
    7571             :                                                          DW_AT_discr,
    7572             :                                                          &discr_attr),
    7573             :                                              &member) != NULL)
    7574           4 :                         die_type_sign_bytes (&member, &is_signed, &bytes);
    7575             :                       else
    7576           0 :                         die_type_sign_bytes (parent, &is_signed, &bytes);
    7577             :                     }
    7578             :                 }
    7579          12 :               while (readp < readendp)
    7580             :                 {
    7581           8 :                   int d = (int) *readp++;
    7582          16 :                   printf ("%s ", dwarf_discr_list_name (d));
    7583           8 :                   if (readp >= readendp)
    7584           0 :                     goto attrval_out;
    7585             : 
    7586           8 :                   Dwarf_Word val;
    7587           8 :                   Dwarf_Sword sval;
    7588           8 :                   if (d == DW_DSC_label)
    7589             :                     {
    7590           4 :                       if (is_signed)
    7591             :                         {
    7592           2 :                           get_sleb128 (sval, readp, readendp);
    7593           2 :                           printf ("%" PRId64 "", sval);
    7594             :                         }
    7595             :                       else
    7596             :                         {
    7597           2 :                           get_uleb128 (val, readp, readendp);
    7598           2 :                           printf ("%" PRIu64 "", val);
    7599             :                         }
    7600             :                     }
    7601           4 :                   else if (d == DW_DSC_range)
    7602             :                     {
    7603           4 :                       if (is_signed)
    7604             :                         {
    7605           3 :                           get_sleb128 (sval, readp, readendp);
    7606           3 :                           printf ("%" PRId64 "..", sval);
    7607           3 :                           if (readp >= readendp)
    7608             :                             goto attrval_out;
    7609           3 :                           get_sleb128 (sval, readp, readendp);
    7610           3 :                           printf ("%" PRId64 "", sval);
    7611             :                         }
    7612             :                       else
    7613             :                         {
    7614           1 :                           get_uleb128 (val, readp, readendp);
    7615           1 :                           printf ("%" PRIu64 "..", val);
    7616           1 :                           if (readp >= readendp)
    7617             :                             goto attrval_out;
    7618           1 :                           get_uleb128 (val, readp, readendp);
    7619           1 :                           printf ("%" PRIu64 "", val);
    7620             :                         }
    7621             :                     }
    7622             :                   else
    7623             :                     {
    7624           0 :                       print_block (readendp - readp, readp);
    7625           0 :                       break;
    7626             :                     }
    7627           8 :                   if (readp < readendp)
    7628           4 :                     printf (", ");
    7629             :                 }
    7630           4 :               putchar ('\n');
    7631             :             }
    7632             :           else
    7633           0 :             print_block (block.length, block.data);
    7634             :           break;
    7635             :         }
    7636             :       break;
    7637             : 
    7638           0 :     default:
    7639           0 :       if (cbargs->silent)
    7640             :         break;
    7641           0 :       printf ("           %*s%-20s (%s) ???\n",
    7642             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7643             :               dwarf_form_name (form));
    7644             :       break;
    7645             :     }
    7646             : 
    7647     2581704 :   return DWARF_CB_OK;
    7648             : }
    7649             : 
    7650             : static void
    7651          99 : print_debug_units (Dwfl_Module *dwflmod,
    7652             :                    Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
    7653             :                    Elf_Scn *scn, GElf_Shdr *shdr,
    7654             :                    Dwarf *dbg, bool debug_types)
    7655             : {
    7656          99 :   const bool silent = !(print_debug_sections & section_info) && !debug_types;
    7657          99 :   const char *secname = section_name (ebl, shdr);
    7658             : 
    7659          99 :   if (!silent)
    7660          64 :     printf (gettext ("\
    7661             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
    7662          64 :             elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
    7663             : 
    7664             :   /* If the section is empty we don't have to do anything.  */
    7665          99 :   if (!silent && shdr->sh_size == 0)
    7666           0 :     return;
    7667             : 
    7668          99 :   int maxdies = 20;
    7669          99 :   Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
    7670             : 
    7671             :   /* New compilation unit.  */
    7672          99 :   Dwarf_Half version;
    7673             : 
    7674          99 :   Dwarf_Die result;
    7675          99 :   Dwarf_Off abbroffset;
    7676          99 :   uint8_t addrsize;
    7677          99 :   uint8_t offsize;
    7678          99 :   uint64_t unit_id;
    7679          99 :   Dwarf_Off subdie_off;
    7680             : 
    7681          99 :   int unit_res;
    7682          99 :   Dwarf_CU *cu;
    7683          99 :   Dwarf_CU cu_mem;
    7684          99 :   uint8_t unit_type;
    7685          99 :   Dwarf_Die cudie;
    7686             : 
    7687             :   /* We cheat a little because we want to see only the CUs from .debug_info
    7688             :      or .debug_types.  We know the Dwarf_CU struct layout.  Set it up at
    7689             :      the end of .debug_info if we want .debug_types only.  Check the returned
    7690             :      Dwarf_CU is still in the expected section.  */
    7691          99 :   if (debug_types)
    7692             :     {
    7693           1 :       cu_mem.dbg = dbg;
    7694           1 :       cu_mem.end = dbg->sectiondata[IDX_debug_info]->d_size;
    7695           1 :       cu_mem.sec_idx = IDX_debug_info;
    7696           1 :       cu = &cu_mem;
    7697             :     }
    7698             :   else
    7699          98 :     cu = NULL;
    7700             : 
    7701             :  next_cu:
    7702        1270 :   unit_res = dwarf_get_units (dbg, cu, &cu, &version, &unit_type,
    7703             :                               &cudie, NULL);
    7704        1270 :   if (unit_res == 1)
    7705          98 :     goto do_return;
    7706             : 
    7707        1172 :   if (unit_res == -1)
    7708             :     {
    7709           0 :       if (!silent)
    7710           0 :         error (0, 0, gettext ("cannot get next unit: %s"), dwarf_errmsg (-1));
    7711           0 :       goto do_return;
    7712             :     }
    7713             : 
    7714        2342 :   if (cu->sec_idx != (size_t) (debug_types ? IDX_debug_types : IDX_debug_info))
    7715           1 :     goto do_return;
    7716             : 
    7717        1171 :   dwarf_cu_die (cu, &result, NULL, &abbroffset, &addrsize, &offsize,
    7718             :                 &unit_id, &subdie_off);
    7719             : 
    7720        1171 :   if (!silent)
    7721             :     {
    7722        1122 :       Dwarf_Off offset = cu->start;
    7723        1122 :       if (debug_types && version < 5)
    7724           2 :         {
    7725           2 :           Dwarf_Die typedie;
    7726           2 :           Dwarf_Off dieoffset;
    7727           2 :           dieoffset = dwarf_dieoffset (dwarf_offdie_types (dbg, subdie_off,
    7728             :                                                            &typedie));
    7729           2 :           printf (gettext (" Type unit at offset %" PRIu64 ":\n"
    7730             :                            " Version: %" PRIu16
    7731             :                            ", Abbreviation section offset: %" PRIu64
    7732             :                            ", Address size: %" PRIu8
    7733             :                            ", Offset size: %" PRIu8
    7734             :                            "\n Type signature: %#" PRIx64
    7735             :                            ", Type offset: %#" PRIx64 " [%" PRIx64 "]\n"),
    7736             :                   (uint64_t) offset, version, abbroffset, addrsize, offsize,
    7737             :                   unit_id, (uint64_t) subdie_off, dieoffset);
    7738             :         }
    7739             :       else
    7740             :         {
    7741        1120 :           printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
    7742             :                            " Version: %" PRIu16
    7743             :                            ", Abbreviation section offset: %" PRIu64
    7744             :                            ", Address size: %" PRIu8
    7745             :                            ", Offset size: %" PRIu8 "\n"),
    7746             :                   (uint64_t) offset, version, abbroffset, addrsize, offsize);
    7747             : 
    7748        1120 :           if (version >= 5 || (unit_type != DW_UT_compile
    7749        1115 :                                && unit_type != DW_UT_partial))
    7750             :             {
    7751           6 :               printf (gettext (" Unit type: %s (%" PRIu8 ")"),
    7752             :                                dwarf_unit_name (unit_type), unit_type);
    7753          12 :               if (unit_type == DW_UT_type
    7754           6 :                   || unit_type == DW_UT_skeleton
    7755           1 :                   || unit_type == DW_UT_split_compile
    7756           1 :                   || unit_type == DW_UT_split_type)
    7757           5 :                 printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
    7758          12 :               if (unit_type == DW_UT_type
    7759           6 :                   || unit_type == DW_UT_split_type)
    7760             :                 {
    7761           0 :                   Dwarf_Die typedie;
    7762           0 :                   Dwarf_Off dieoffset;
    7763           0 :                   dwarf_cu_info (cu, NULL, NULL, NULL, &typedie,
    7764             :                                  NULL, NULL, NULL);
    7765           0 :                   dieoffset = dwarf_dieoffset (&typedie);
    7766           0 :                   printf (", Unit DIE off: %#" PRIx64 " [%" PRIx64 "]",
    7767             :                           subdie_off, dieoffset);
    7768             :                 }
    7769           6 :               printf ("\n");
    7770             :             }
    7771             :         }
    7772             :     }
    7773             : 
    7774        1171 :   if (version < 2 || version > 5
    7775        1171 :       || unit_type < DW_UT_compile || unit_type > DW_UT_split_type)
    7776             :     {
    7777           0 :       if (!silent)
    7778           0 :         error (0, 0, gettext ("unknown version (%d) or unit type (%d)"),
    7779             :                version, unit_type);
    7780           0 :       goto next_cu;
    7781             :     }
    7782             : 
    7783        1171 :   struct attrcb_args args =
    7784             :     {
    7785             :       .dwflmod = dwflmod,
    7786             :       .silent = silent,
    7787             :       .version = version,
    7788             :       .addrsize = addrsize,
    7789             :       .offset_size = offsize
    7790             :     };
    7791             : 
    7792        1171 :   bool is_split = false;
    7793        1171 :   int level = 0;
    7794        1171 :   dies[0] = cudie;
    7795        1171 :   args.cu = dies[0].cu;
    7796        1171 :   args.dbg = dbg;
    7797        1171 :   args.is_split = is_split;
    7798             : 
    7799             :   /* We might return here again for the split CU subdie.  */
    7800      718129 :   do_cu:
    7801      719304 :   do
    7802             :     {
    7803      719304 :       Dwarf_Off offset = dwarf_dieoffset (&dies[level]);
    7804      719304 :       if (unlikely (offset == (Dwarf_Off) -1))
    7805             :         {
    7806           0 :           if (!silent)
    7807           0 :             error (0, 0, gettext ("cannot get DIE offset: %s"),
    7808             :                    dwarf_errmsg (-1));
    7809           0 :           goto do_return;
    7810             :         }
    7811             : 
    7812      719304 :       int tag = dwarf_tag (&dies[level]);
    7813      719304 :       if (unlikely (tag == DW_TAG_invalid))
    7814             :         {
    7815           0 :           if (!silent)
    7816           0 :             error (0, 0, gettext ("cannot get tag of DIE at offset [%" PRIx64
    7817             :                                   "] in section '%s': %s"),
    7818             :                    (uint64_t) offset, secname, dwarf_errmsg (-1));
    7819           0 :           goto do_return;
    7820             :         }
    7821             : 
    7822      719304 :       if (!silent)
    7823             :         {
    7824      718316 :           unsigned int code = dwarf_getabbrevcode (dies[level].abbrev);
    7825      718316 :           if (is_split)
    7826          48 :             printf (" {%6" PRIx64 "}  ", (uint64_t) offset);
    7827             :           else
    7828      718268 :             printf (" [%6" PRIx64 "]  ", (uint64_t) offset);
    7829      718316 :           printf ("%*s%-20s abbrev: %u\n", (int) (level * 2), "",
    7830             :                   dwarf_tag_name (tag), code);
    7831             :         }
    7832             : 
    7833             :       /* Print the attribute values.  */
    7834      719304 :       args.level = level;
    7835      719304 :       args.dies = dies;
    7836      719304 :       (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
    7837             : 
    7838             :       /* Make room for the next level's DIE.  */
    7839      719304 :       if (level + 1 == maxdies)
    7840           0 :         dies = (Dwarf_Die *) xrealloc (dies,
    7841           0 :                                        (maxdies += 10)
    7842             :                                        * sizeof (Dwarf_Die));
    7843             : 
    7844      719304 :       int res = dwarf_child (&dies[level], &dies[level + 1]);
    7845      719304 :       if (res > 0)
    7846             :         {
    7847      719304 :           while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
    7848      102905 :             if (level-- == 0)
    7849             :               break;
    7850             : 
    7851      617574 :           if (unlikely (res == -1))
    7852             :             {
    7853           0 :               if (!silent)
    7854           0 :                 error (0, 0, gettext ("cannot get next DIE: %s\n"),
    7855             :                        dwarf_errmsg (-1));
    7856           0 :               goto do_return;
    7857             :             }
    7858             :         }
    7859      101730 :       else if (unlikely (res < 0))
    7860             :         {
    7861           0 :           if (!silent)
    7862           0 :             error (0, 0, gettext ("cannot get next DIE: %s"),
    7863             :                    dwarf_errmsg (-1));
    7864           0 :           goto do_return;
    7865             :         }
    7866             :       else
    7867             :         ++level;
    7868             :     }
    7869      719304 :   while (level >= 0);
    7870             : 
    7871             :   /* We might want to show the split compile unit if this was a skeleton.
    7872             :      We need to scan it if we are requesting printing .debug_ranges for
    7873             :      DWARF4 since GNU DebugFission uses "offsets" into the main ranges
    7874             :      section.  */
    7875        1175 :   if (unit_type == DW_UT_skeleton
    7876          13 :       && ((!silent && show_split_units)
    7877          10 :           || (version < 5 && (print_debug_sections & section_ranges) != 0)))
    7878             :     {
    7879           5 :       Dwarf_Die subdie;
    7880           5 :       if (dwarf_cu_info (cu, NULL, NULL, NULL, &subdie, NULL, NULL, NULL) != 0
    7881           5 :           || dwarf_tag (&subdie) == DW_TAG_invalid)
    7882             :         {
    7883           1 :           if (!silent)
    7884             :             {
    7885           1 :               Dwarf_Attribute dwo_at;
    7886           2 :               const char *dwo_name =
    7887           1 :                 (dwarf_formstring (dwarf_attr (&cudie, DW_AT_dwo_name,
    7888             :                                                &dwo_at))
    7889           1 :                  ?: (dwarf_formstring (dwarf_attr (&cudie, DW_AT_GNU_dwo_name,
    7890             :                                                    &dwo_at))
    7891           0 :                      ?: "<unknown>"));
    7892           1 :               fprintf (stderr,
    7893             :                        "Could not find split unit '%s', id: %" PRIx64 "\n",
    7894             :                        dwo_name, unit_id);
    7895             :             }
    7896             :         }
    7897             :       else
    7898             :         {
    7899           4 :           Dwarf_CU *split_cu = subdie.cu;
    7900           4 :           dwarf_cu_die (split_cu, &result, NULL, &abbroffset,
    7901             :                         &addrsize, &offsize, &unit_id, &subdie_off);
    7902           4 :           Dwarf_Off offset = cu->start;
    7903             : 
    7904           4 :           if (!silent)
    7905             :             {
    7906           2 :               printf (gettext (" Split compilation unit at offset %"
    7907             :                                PRIu64 ":\n"
    7908             :                                " Version: %" PRIu16
    7909             :                                ", Abbreviation section offset: %" PRIu64
    7910             :                                ", Address size: %" PRIu8
    7911             :                                ", Offset size: %" PRIu8 "\n"),
    7912             :                       (uint64_t) offset, version, abbroffset,
    7913             :                       addrsize, offsize);
    7914           2 :               printf (gettext (" Unit type: %s (%" PRIu8 ")"),
    7915             :                       dwarf_unit_name (unit_type), unit_type);
    7916           2 :               printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
    7917           2 :               printf ("\n");
    7918             :             }
    7919             : 
    7920           4 :           unit_type = DW_UT_split_compile;
    7921           4 :           is_split = true;
    7922           4 :           level = 0;
    7923           4 :           dies[0] = subdie;
    7924           4 :           args.cu = dies[0].cu;
    7925           4 :           args.dbg = split_cu->dbg;
    7926           4 :           args.is_split = is_split;
    7927           4 :           goto do_cu;
    7928             :         }
    7929             :     }
    7930             : 
    7931             :   /* And again... */
    7932        1171 :   goto next_cu;
    7933             : 
    7934          99 :  do_return:
    7935          99 :   free (dies);
    7936             : }
    7937             : 
    7938             : static void
    7939          19 : print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
    7940             :                           Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    7941             : {
    7942          19 :   print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
    7943          19 : }
    7944             : 
    7945             : static void
    7946           1 : print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
    7947             :                            Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    7948             : {
    7949           1 :   print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
    7950           1 : }
    7951             : 
    7952             : 
    7953             : static void
    7954           0 : print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
    7955             :                             GElf_Ehdr *ehdr __attribute__ ((unused)),
    7956             :                             Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    7957             : {
    7958           0 :   printf (gettext ("\
    7959             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n\n"),
    7960             :           elf_ndxscn (scn), section_name (ebl, shdr),
    7961           0 :           (uint64_t) shdr->sh_offset);
    7962             : 
    7963           0 :   size_t address_size
    7964           0 :     = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    7965             : 
    7966           0 :   Dwarf_Lines *lines;
    7967           0 :   size_t nlines;
    7968           0 :   Dwarf_Off off, next_off = 0;
    7969           0 :   Dwarf_CU *cu = NULL;
    7970           0 :   while (dwarf_next_lines (dbg, off = next_off, &next_off, &cu, NULL, NULL,
    7971             :                            &lines, &nlines) == 0)
    7972             :     {
    7973           0 :       Dwarf_Die cudie;
    7974           0 :       if (cu != NULL && dwarf_cu_info (cu, NULL, NULL, &cudie,
    7975             :                                        NULL, NULL, NULL, NULL) == 0)
    7976           0 :         printf (" CU [%" PRIx64 "] %s\n",
    7977             :                 dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
    7978             :       else
    7979             :         {
    7980             :           /* DWARF5 lines can be independent of any CU, but they probably
    7981             :              are used by some CU.  Determine the CU this block is for.  */
    7982           0 :           Dwarf_Off cuoffset;
    7983           0 :           Dwarf_Off ncuoffset = 0;
    7984           0 :           size_t hsize;
    7985           0 :           while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
    7986             :                                NULL, NULL, NULL) == 0)
    7987             :             {
    7988           0 :               if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
    7989           0 :                 continue;
    7990           0 :               Dwarf_Attribute stmt_list;
    7991           0 :               if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
    7992           0 :                 continue;
    7993           0 :               Dwarf_Word lineoff;
    7994           0 :               if (dwarf_formudata (&stmt_list, &lineoff) != 0)
    7995           0 :                 continue;
    7996           0 :               if (lineoff == off)
    7997             :                 {
    7998             :                   /* Found the CU.  */
    7999           0 :                   cu = cudie.cu;
    8000           0 :                   break;
    8001             :                 }
    8002             :             }
    8003             : 
    8004           0 :           if (cu != NULL)
    8005           0 :             printf (" CU [%" PRIx64 "] %s\n",
    8006             :                     dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
    8007             :           else
    8008           0 :             printf (" No CU\n");
    8009             :         }
    8010             : 
    8011           0 :       printf ("  line:col SBPE* disc isa op address"
    8012             :               " (Statement Block Prologue Epilogue *End)\n");
    8013           0 :       const char *last_file = "";
    8014           0 :       for (size_t n = 0; n < nlines; n++)
    8015             :         {
    8016           0 :           Dwarf_Line *line = dwarf_onesrcline (lines, n);
    8017           0 :           if (line == NULL)
    8018             :             {
    8019           0 :               printf ("  dwarf_onesrcline: %s\n", dwarf_errmsg (-1));
    8020           0 :               continue;
    8021             :             }
    8022           0 :           Dwarf_Word mtime, length;
    8023           0 :           const char *file = dwarf_linesrc (line, &mtime, &length);
    8024           0 :           if (file == NULL)
    8025             :             {
    8026           0 :               printf ("  <%s> (mtime: ?, length: ?)\n", dwarf_errmsg (-1));
    8027           0 :               last_file = "";
    8028             :             }
    8029           0 :           else if (strcmp (last_file, file) != 0)
    8030             :             {
    8031           0 :               printf ("  %s (mtime: %" PRIu64 ", length: %" PRIu64 ")\n",
    8032             :                       file, mtime, length);
    8033           0 :               last_file = file;
    8034             :             }
    8035             : 
    8036           0 :           int lineno, colno;
    8037           0 :           bool statement, endseq, block, prologue_end, epilogue_begin;
    8038           0 :           unsigned int lineop, isa, disc;
    8039           0 :           Dwarf_Addr address;
    8040           0 :           dwarf_lineaddr (line, &address);
    8041           0 :           dwarf_lineno (line, &lineno);
    8042           0 :           dwarf_linecol (line, &colno);
    8043           0 :           dwarf_lineop_index (line, &lineop);
    8044           0 :           dwarf_linebeginstatement (line, &statement);
    8045           0 :           dwarf_lineendsequence (line, &endseq);
    8046           0 :           dwarf_lineblock (line, &block);
    8047           0 :           dwarf_lineprologueend (line, &prologue_end);
    8048           0 :           dwarf_lineepiloguebegin (line, &epilogue_begin);
    8049           0 :           dwarf_lineisa (line, &isa);
    8050           0 :           dwarf_linediscriminator (line, &disc);
    8051             : 
    8052             :           /* End sequence is special, it is one byte past.  */
    8053           0 :           printf ("  %4d:%-3d %c%c%c%c%c %4d %3d %2d ",
    8054             :                   lineno, colno,
    8055           0 :                   (statement ? 'S' : ' '),
    8056           0 :                   (block ? 'B' : ' '),
    8057           0 :                   (prologue_end ? 'P' : ' '),
    8058           0 :                   (epilogue_begin ? 'E' : ' '),
    8059           0 :                   (endseq ? '*' : ' '),
    8060             :                   disc, isa, lineop);
    8061           0 :           print_dwarf_addr (dwflmod, address_size,
    8062           0 :                             address - (endseq ? 1 : 0), address);
    8063           0 :           printf ("\n");
    8064             : 
    8065           0 :           if (endseq)
    8066           0 :             printf("\n");
    8067             :         }
    8068             :     }
    8069           0 : }
    8070             : 
    8071             : 
    8072             : /* Print the value of a form.
    8073             :    Returns new value of readp, or readendp on failure.  */
    8074             : static const unsigned char *
    8075          20 : print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
    8076             :                  const unsigned char *readendp, unsigned int offset_len,
    8077             :                  Dwarf_Off str_offsets_base)
    8078             : {
    8079          20 :   Dwarf_Word val;
    8080          20 :   unsigned char *endp;
    8081          20 :   Elf_Data *data;
    8082          20 :   char *str;
    8083          20 :   switch (form)
    8084             :     {
    8085           8 :     case DW_FORM_data1:
    8086           8 :       if (readendp - readp < 1)
    8087             :         {
    8088           0 :         invalid_data:
    8089           0 :           error (0, 0, "invalid data");
    8090           0 :           return readendp;
    8091             :         }
    8092           8 :       val = *readp++;
    8093           8 :       printf (" %" PRIx8, (unsigned int) val);
    8094             :       break;
    8095             : 
    8096           0 :     case DW_FORM_data2:
    8097           0 :       if (readendp - readp < 2)
    8098             :         goto invalid_data;
    8099           0 :       val = read_2ubyte_unaligned_inc (dbg, readp);
    8100           0 :       printf(" %" PRIx16, (unsigned int) val);
    8101             :       break;
    8102             : 
    8103           0 :     case DW_FORM_data4:
    8104           0 :       if (readendp - readp < 4)
    8105             :         goto invalid_data;
    8106           0 :       val = read_4ubyte_unaligned_inc (dbg, readp);
    8107           0 :       printf (" %" PRIx32, (unsigned int) val);
    8108             :       break;
    8109             : 
    8110           0 :     case DW_FORM_data8:
    8111           0 :       if (readendp - readp < 8)
    8112             :         goto invalid_data;
    8113           0 :       val = read_8ubyte_unaligned_inc (dbg, readp);
    8114           0 :       printf (" %" PRIx64, val);
    8115             :       break;
    8116             : 
    8117           0 :     case DW_FORM_sdata:
    8118           0 :       if (readendp - readp < 1)
    8119             :         goto invalid_data;
    8120           0 :       get_sleb128 (val, readp, readendp);
    8121           0 :       printf (" %" PRIx64, val);
    8122             :       break;
    8123             : 
    8124           0 :     case DW_FORM_udata:
    8125           0 :       if (readendp - readp < 1)
    8126             :         goto invalid_data;
    8127           0 :       get_uleb128 (val, readp, readendp);
    8128           0 :       printf (" %" PRIx64, val);
    8129             :       break;
    8130             : 
    8131           0 :     case DW_FORM_block:
    8132           0 :       if (readendp - readp < 1)
    8133             :         goto invalid_data;
    8134           0 :       get_uleb128 (val, readp, readendp);
    8135           0 :       if ((size_t) (readendp - readp) < val)
    8136             :         goto invalid_data;
    8137           0 :       print_bytes (val, readp);
    8138           0 :       readp += val;
    8139           0 :       break;
    8140             : 
    8141           0 :     case DW_FORM_block1:
    8142           0 :       if (readendp - readp < 1)
    8143             :         goto invalid_data;
    8144           0 :       val = *readp++;
    8145           0 :       if ((size_t) (readendp - readp) < val)
    8146             :         goto invalid_data;
    8147           0 :       print_bytes (val, readp);
    8148           0 :       readp += val;
    8149           0 :       break;
    8150             : 
    8151           0 :     case DW_FORM_block2:
    8152           0 :       if (readendp - readp < 2)
    8153             :         goto invalid_data;
    8154           0 :       val = read_2ubyte_unaligned_inc (dbg, readp);
    8155           0 :       if ((size_t) (readendp - readp) < val)
    8156             :         goto invalid_data;
    8157           0 :       print_bytes (val, readp);
    8158           0 :       readp += val;
    8159           0 :       break;
    8160             : 
    8161           0 :     case DW_FORM_block4:
    8162           0 :       if (readendp - readp < 4)
    8163             :         goto invalid_data;
    8164           0 :       val = read_4ubyte_unaligned_inc (dbg, readp);
    8165           0 :       if ((size_t) (readendp - readp) < val)
    8166             :         goto invalid_data;
    8167           0 :       print_bytes (val, readp);
    8168           0 :       readp += val;
    8169           0 :       break;
    8170             : 
    8171           0 :     case DW_FORM_data16:
    8172           0 :       if (readendp - readp < 16)
    8173             :         goto invalid_data;
    8174           0 :       print_bytes (16, readp);
    8175           0 :       readp += 16;
    8176           0 :       break;
    8177             : 
    8178           0 :     case DW_FORM_flag:
    8179           0 :       if (readendp - readp < 1)
    8180             :         goto invalid_data;
    8181           0 :       val = *readp++;
    8182           0 :       printf ("%s", val != 0 ? yes_str : no_str);
    8183             :       break;
    8184             : 
    8185           0 :     case DW_FORM_string:
    8186           0 :       endp = memchr (readp, '\0', readendp - readp);
    8187           0 :       if (endp == NULL)
    8188             :         goto invalid_data;
    8189           0 :       printf ("%s", readp);
    8190           0 :       readp = endp + 1;
    8191           0 :       break;
    8192             : 
    8193          12 :     case DW_FORM_strp:
    8194             :     case DW_FORM_line_strp:
    8195             :     case DW_FORM_strp_sup:
    8196          12 :       if ((size_t) (readendp - readp) < offset_len)
    8197             :         goto invalid_data;
    8198          12 :       if (offset_len == 8)
    8199           0 :         val = read_8ubyte_unaligned_inc (dbg, readp);
    8200             :       else
    8201          12 :         val = read_4ubyte_unaligned_inc (dbg, readp);
    8202          12 :       if (form == DW_FORM_strp)
    8203           0 :         data = dbg->sectiondata[IDX_debug_str];
    8204          12 :       else if (form == DW_FORM_line_strp)
    8205          12 :         data = dbg->sectiondata[IDX_debug_line_str];
    8206             :       else /* form == DW_FORM_strp_sup */
    8207             :         {
    8208           0 :           Dwarf *alt = dwarf_getalt (dbg);
    8209           0 :           data = alt != NULL ? alt->sectiondata[IDX_debug_str] : NULL;
    8210             :         }
    8211          12 :       if (data == NULL || val >= data->d_size
    8212          12 :           || memchr (data->d_buf + val, '\0', data->d_size - val) == NULL)
    8213             :         str = "???";
    8214             :       else
    8215          12 :         str = (char *) data->d_buf + val;
    8216          12 :       printf ("%s (%" PRIu64 ")", str, val);
    8217             :       break;
    8218             : 
    8219           0 :     case DW_FORM_sec_offset:
    8220           0 :       if ((size_t) (readendp - readp) < offset_len)
    8221             :         goto invalid_data;
    8222           0 :       if (offset_len == 8)
    8223           0 :         val = read_8ubyte_unaligned_inc (dbg, readp);
    8224             :       else
    8225           0 :         val = read_4ubyte_unaligned_inc (dbg, readp);
    8226           0 :       printf ("[%" PRIx64 "]", val);
    8227             :       break;
    8228             : 
    8229           0 :     case DW_FORM_strx:
    8230             :     case DW_FORM_GNU_str_index:
    8231           0 :       if (readendp - readp < 1)
    8232             :         goto invalid_data;
    8233           0 :       get_uleb128 (val, readp, readendp);
    8234           0 :     strx_val:
    8235           0 :       data = dbg->sectiondata[IDX_debug_str_offsets];
    8236           0 :       if (data == NULL
    8237           0 :           || data->d_size - str_offsets_base < val)
    8238             :         str = "???";
    8239             :       else
    8240             :         {
    8241           0 :           const unsigned char *strreadp = data->d_buf + str_offsets_base + val;
    8242           0 :           const unsigned char *strreadendp = data->d_buf + data->d_size;
    8243           0 :           if ((size_t) (strreadendp - strreadp) < offset_len)
    8244             :             str = "???";
    8245             :           else
    8246             :             {
    8247           0 :               Dwarf_Off idx;
    8248           0 :               if (offset_len == 8)
    8249           0 :                 idx = read_8ubyte_unaligned (dbg, strreadp);
    8250             :               else
    8251           0 :                 idx = read_4ubyte_unaligned (dbg, strreadp);
    8252             : 
    8253           0 :               data = dbg->sectiondata[IDX_debug_str];
    8254           0 :               if (data == NULL || idx >= data->d_size
    8255           0 :                   || memchr (data->d_buf + idx, '\0',
    8256             :                              data->d_size - idx) == NULL)
    8257             :                 str = "???";
    8258             :               else
    8259           0 :                 str = (char *) data->d_buf + idx;
    8260             :             }
    8261             :         }
    8262           0 :       printf ("%s (%" PRIu64 ")", str, val);
    8263             :       break;
    8264             : 
    8265           0 :     case DW_FORM_strx1:
    8266           0 :       if (readendp - readp < 1)
    8267             :         goto invalid_data;
    8268           0 :       val = *readp++;
    8269           0 :       goto strx_val;
    8270             : 
    8271           0 :     case DW_FORM_strx2:
    8272           0 :       if (readendp - readp < 2)
    8273             :         goto invalid_data;
    8274           0 :       val = read_2ubyte_unaligned_inc (dbg, readp);
    8275           0 :       goto strx_val;
    8276             : 
    8277           0 :     case DW_FORM_strx3:
    8278           0 :       if (readendp - readp < 3)
    8279             :         goto invalid_data;
    8280           0 :       val = read_3ubyte_unaligned_inc (dbg, readp);
    8281           0 :       goto strx_val;
    8282             : 
    8283           0 :     case DW_FORM_strx4:
    8284           0 :       if (readendp - readp < 4)
    8285             :         goto invalid_data;
    8286           0 :       val = read_4ubyte_unaligned_inc (dbg, readp);
    8287           0 :       goto strx_val;
    8288             : 
    8289           0 :     default:
    8290           0 :       error (0, 0, gettext ("unknown form: %s"), dwarf_form_name (form));
    8291           0 :       return readendp;
    8292             :     }
    8293             : 
    8294          20 :   return readp;
    8295             : }
    8296             : 
    8297             : static void
    8298          52 : print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
    8299             :                           Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    8300             : {
    8301          52 :   if (decodedline)
    8302             :     {
    8303           4 :       print_decoded_line_section (dwflmod, ebl, ehdr, scn, shdr, dbg);
    8304           4 :       return;
    8305             :     }
    8306             : 
    8307          48 :   printf (gettext ("\
    8308             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    8309             :           elf_ndxscn (scn), section_name (ebl, shdr),
    8310          48 :           (uint64_t) shdr->sh_offset);
    8311             : 
    8312          48 :   if (shdr->sh_size == 0)
    8313             :     return;
    8314             : 
    8315             :   /* There is no functionality in libdw to read the information in the
    8316             :      way it is represented here.  Hardcode the decoder.  */
    8317          96 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_line]
    8318          48 :                     ?: elf_rawdata (scn, NULL));
    8319          48 :   if (unlikely (data == NULL))
    8320             :     {
    8321           0 :       error (0, 0, gettext ("cannot get line data section data: %s"),
    8322             :              elf_errmsg (-1));
    8323           0 :       return;
    8324             :     }
    8325             : 
    8326          48 :   const unsigned char *linep = (const unsigned char *) data->d_buf;
    8327          48 :   const unsigned char *lineendp;
    8328             : 
    8329          48 :   while (linep
    8330        1153 :          < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
    8331             :     {
    8332        1105 :       size_t start_offset = linep - (const unsigned char *) data->d_buf;
    8333             : 
    8334        1105 :       printf (gettext ("\nTable at offset %zu:\n"), start_offset);
    8335             : 
    8336        1105 :       if (unlikely (linep + 4 > lineendp))
    8337             :         goto invalid_data;
    8338        1105 :       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
    8339        1105 :       unsigned int length = 4;
    8340        1105 :       if (unlikely (unit_length == 0xffffffff))
    8341             :         {
    8342           0 :           if (unlikely (linep + 8 > lineendp))
    8343             :             {
    8344           0 :             invalid_data:
    8345           0 :               error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
    8346             :                      elf_ndxscn (scn), section_name (ebl, shdr));
    8347           0 :               return;
    8348             :             }
    8349           0 :           unit_length = read_8ubyte_unaligned_inc (dbg, linep);
    8350           0 :           length = 8;
    8351             :         }
    8352             : 
    8353             :       /* Check whether we have enough room in the section.  */
    8354        1105 :       if (unlikely (unit_length > (size_t) (lineendp - linep)))
    8355             :         goto invalid_data;
    8356        1105 :       lineendp = linep + unit_length;
    8357             : 
    8358             :       /* The next element of the header is the version identifier.  */
    8359        1105 :       if ((size_t) (lineendp - linep) < 2)
    8360             :         goto invalid_data;
    8361        1105 :       uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
    8362             : 
    8363        2210 :       size_t address_size
    8364        1105 :         = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    8365        1105 :       unsigned char segment_selector_size = 0;
    8366        1105 :       if (version > 4)
    8367             :         {
    8368           2 :           if ((size_t) (lineendp - linep) < 2)
    8369             :             goto invalid_data;
    8370           2 :           address_size = *linep++;
    8371           2 :           segment_selector_size = *linep++;
    8372             :         }
    8373             : 
    8374             :       /* Next comes the header length.  */
    8375        1105 :       Dwarf_Word header_length;
    8376        1105 :       if (length == 4)
    8377             :         {
    8378        1105 :           if ((size_t) (lineendp - linep) < 4)
    8379             :             goto invalid_data;
    8380        1105 :           header_length = read_4ubyte_unaligned_inc (dbg, linep);
    8381             :         }
    8382             :       else
    8383             :         {
    8384           0 :           if ((size_t) (lineendp - linep) < 8)
    8385             :             goto invalid_data;
    8386           0 :           header_length = read_8ubyte_unaligned_inc (dbg, linep);
    8387             :         }
    8388             : 
    8389             :       /* Next the minimum instruction length.  */
    8390        1105 :       if ((size_t) (lineendp - linep) < 1)
    8391             :         goto invalid_data;
    8392        1105 :       uint_fast8_t minimum_instr_len = *linep++;
    8393             : 
    8394             :       /* Next the maximum operations per instruction, in version 4 format.  */
    8395        1105 :       uint_fast8_t max_ops_per_instr;
    8396        1105 :       if (version < 4)
    8397             :         max_ops_per_instr = 1;
    8398             :       else
    8399             :         {
    8400          10 :           if ((size_t) (lineendp - linep) < 1)
    8401             :             goto invalid_data;
    8402          10 :           max_ops_per_instr = *linep++;
    8403             :         }
    8404             : 
    8405             :       /* We need at least 4 more bytes.  */
    8406        1105 :       if ((size_t) (lineendp - linep) < 4)
    8407             :         goto invalid_data;
    8408             : 
    8409             :       /* Then the flag determining the default value of the is_stmt
    8410             :          register.  */
    8411        1105 :       uint_fast8_t default_is_stmt = *linep++;
    8412             : 
    8413             :       /* Now the line base.  */
    8414        1105 :       int_fast8_t line_base = *linep++;
    8415             : 
    8416             :       /* And the line range.  */
    8417        1105 :       uint_fast8_t line_range = *linep++;
    8418             : 
    8419             :       /* The opcode base.  */
    8420        1105 :       uint_fast8_t opcode_base = *linep++;
    8421             : 
    8422             :       /* Print what we got so far.  */
    8423        1105 :       printf (gettext ("\n"
    8424             :                        " Length:                         %" PRIu64 "\n"
    8425             :                        " DWARF version:                  %" PRIuFAST16 "\n"
    8426             :                        " Prologue length:                %" PRIu64 "\n"
    8427             :                        " Address size:                   %zd\n"
    8428             :                        " Segment selector size:          %zd\n"
    8429             :                        " Min instruction length:         %" PRIuFAST8 "\n"
    8430             :                        " Max operations per instruction: %" PRIuFAST8 "\n"
    8431             :                        " Initial value if 'is_stmt':     %" PRIuFAST8 "\n"
    8432             :                        " Line base:                      %" PRIdFAST8 "\n"
    8433             :                        " Line range:                     %" PRIuFAST8 "\n"
    8434             :                        " Opcode base:                    %" PRIuFAST8 "\n"
    8435             :                        "\n"
    8436             :                        "Opcodes:\n"),
    8437             :               (uint64_t) unit_length, version, (uint64_t) header_length,
    8438             :               address_size, (size_t) segment_selector_size,
    8439             :               minimum_instr_len, max_ops_per_instr,
    8440             :               default_is_stmt, line_base,
    8441             :               line_range, opcode_base);
    8442             : 
    8443        1105 :       if (version < 2 || version > 5)
    8444             :         {
    8445           0 :           error (0, 0, gettext ("cannot handle .debug_line version: %u\n"),
    8446             :                  (unsigned int) version);
    8447           0 :           linep = lineendp;
    8448           0 :           continue;
    8449             :         }
    8450             : 
    8451        1105 :       if (address_size != 4 && address_size != 8)
    8452             :         {
    8453           0 :           error (0, 0, gettext ("cannot handle address size: %u\n"),
    8454             :                  (unsigned int) address_size);
    8455           0 :           linep = lineendp;
    8456           0 :           continue;
    8457             :         }
    8458             : 
    8459        1105 :       if (segment_selector_size != 0)
    8460             :         {
    8461           0 :           error (0, 0, gettext ("cannot handle segment selector size: %u\n"),
    8462             :                  (unsigned int) segment_selector_size);
    8463           0 :           linep = lineendp;
    8464           0 :           continue;
    8465             :         }
    8466             : 
    8467        1105 :       if (unlikely (linep + opcode_base - 1 >= lineendp))
    8468             :         {
    8469           0 :         invalid_unit:
    8470           0 :           error (0, 0,
    8471           0 :                  gettext ("invalid data at offset %tu in section [%zu] '%s'"),
    8472           0 :                  linep - (const unsigned char *) data->d_buf,
    8473             :                  elf_ndxscn (scn), section_name (ebl, shdr));
    8474           0 :           linep = lineendp;
    8475           0 :           continue;
    8476             :         }
    8477        1105 :       int opcode_base_l10 = 1;
    8478        1105 :       unsigned int tmp = opcode_base;
    8479        2208 :       while (tmp > 10)
    8480             :         {
    8481        1103 :           tmp /= 10;
    8482        1103 :           ++opcode_base_l10;
    8483             :         }
    8484        1105 :       const uint8_t *standard_opcode_lengths = linep - 1;
    8485       14359 :       for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
    8486       13254 :         printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
    8487             :                           "  [%*" PRIuFAST8 "]  %hhu arguments\n",
    8488             :                           (int) linep[cnt - 1]),
    8489       13254 :                 opcode_base_l10, cnt, linep[cnt - 1]);
    8490        1105 :       linep += opcode_base - 1;
    8491             : 
    8492        1105 :       if (unlikely (linep >= lineendp))
    8493             :         goto invalid_unit;
    8494             : 
    8495        1105 :       Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, NULL);
    8496             : 
    8497        1105 :       puts (gettext ("\nDirectory table:"));
    8498        1105 :       if (version > 4)
    8499             :         {
    8500           2 :           struct encpair { uint16_t desc; uint16_t form; };
    8501           2 :           struct encpair enc[256];
    8502             : 
    8503           2 :           printf (gettext ("      ["));
    8504           2 :           if ((size_t) (lineendp - linep) < 1)
    8505           0 :             goto invalid_data;
    8506           2 :           unsigned char directory_entry_format_count = *linep++;
    8507           4 :           for (int i = 0; i < directory_entry_format_count; i++)
    8508             :             {
    8509           2 :               uint16_t desc, form;
    8510           2 :               if ((size_t) (lineendp - linep) < 1)
    8511             :                 goto invalid_data;
    8512           2 :               get_uleb128 (desc, linep, lineendp);
    8513           2 :               if ((size_t) (lineendp - linep) < 1)
    8514             :                 goto invalid_data;
    8515           2 :               get_uleb128 (form, linep, lineendp);
    8516             : 
    8517           2 :               enc[i].desc = desc;
    8518           2 :               enc[i].form = form;
    8519             : 
    8520           2 :               printf ("%s(%s)",
    8521             :                       dwarf_line_content_description_name (desc),
    8522             :                       dwarf_form_name (form));
    8523           2 :               if (i + 1 < directory_entry_format_count)
    8524           0 :                 printf (", ");
    8525             :             }
    8526           2 :           printf ("]\n");
    8527             : 
    8528           2 :           uint64_t directories_count;
    8529           2 :           if ((size_t) (lineendp - linep) < 1)
    8530             :             goto invalid_data;
    8531           2 :           get_uleb128 (directories_count, linep, lineendp);
    8532             : 
    8533           4 :           if (directory_entry_format_count == 0
    8534           2 :               && directories_count != 0)
    8535             :             goto invalid_data;
    8536             : 
    8537           6 :           for (uint64_t i = 0; i < directories_count; i++)
    8538             :             {
    8539           4 :               printf (" %-5" PRIu64 " ", i);
    8540           8 :               for (int j = 0; j < directory_entry_format_count; j++)
    8541             :                 {
    8542           4 :                   linep = print_form_data (dbg, enc[j].form,
    8543             :                                            linep, lineendp, length,
    8544             :                                            str_offsets_base);
    8545           4 :                   if (j + 1 < directory_entry_format_count)
    8546           0 :                     printf (", ");
    8547             :                 }
    8548           4 :               printf ("\n");
    8549           4 :               if (linep >= lineendp)
    8550           0 :                 goto invalid_unit;
    8551             :             }
    8552             :         }
    8553             :       else
    8554             :         {
    8555        8399 :           while (linep < lineendp && *linep != 0)
    8556             :             {
    8557        7296 :               unsigned char *endp = memchr (linep, '\0', lineendp - linep);
    8558        7296 :               if (unlikely (endp == NULL))
    8559             :                 goto invalid_unit;
    8560             : 
    8561        7296 :               printf (" %s\n", (char *) linep);
    8562             : 
    8563        7296 :               linep = endp + 1;
    8564             :             }
    8565        1103 :           if (linep >= lineendp || *linep != 0)
    8566             :             goto invalid_unit;
    8567             :           /* Skip the final NUL byte.  */
    8568        1103 :           ++linep;
    8569             :         }
    8570             : 
    8571        1105 :       if (unlikely (linep >= lineendp))
    8572             :         goto invalid_unit;
    8573             : 
    8574        1105 :       puts (gettext ("\nFile name table:"));
    8575        1105 :       if (version > 4)
    8576             :         {
    8577           2 :           struct encpair { uint16_t desc; uint16_t form; };
    8578           2 :           struct encpair enc[256];
    8579             : 
    8580           2 :           printf (gettext ("      ["));
    8581           2 :           if ((size_t) (lineendp - linep) < 1)
    8582           0 :             goto invalid_data;
    8583           2 :           unsigned char file_name_format_count = *linep++;
    8584           6 :           for (int i = 0; i < file_name_format_count; i++)
    8585             :             {
    8586           4 :               uint64_t desc, form;
    8587           4 :               if ((size_t) (lineendp - linep) < 1)
    8588             :                 goto invalid_data;
    8589           4 :               get_uleb128 (desc, linep, lineendp);
    8590           4 :               if ((size_t) (lineendp - linep) < 1)
    8591             :                 goto invalid_data;
    8592           4 :               get_uleb128 (form, linep, lineendp);
    8593             : 
    8594           4 :               if (! libdw_valid_user_form (form))
    8595             :                 goto invalid_data;
    8596             : 
    8597           4 :               enc[i].desc = desc;
    8598           4 :               enc[i].form = form;
    8599             : 
    8600           4 :               printf ("%s(%s)",
    8601             :                       dwarf_line_content_description_name (desc),
    8602             :                       dwarf_form_name (form));
    8603           4 :               if (i + 1 < file_name_format_count)
    8604           2 :                 printf (", ");
    8605             :             }
    8606           2 :           printf ("]\n");
    8607             : 
    8608           2 :           uint64_t file_name_count;
    8609           2 :           if ((size_t) (lineendp - linep) < 1)
    8610             :             goto invalid_data;
    8611           2 :           get_uleb128 (file_name_count, linep, lineendp);
    8612             : 
    8613           4 :           if (file_name_format_count == 0
    8614           2 :               && file_name_count != 0)
    8615             :             goto invalid_data;
    8616             : 
    8617          10 :           for (uint64_t i = 0; i < file_name_count; i++)
    8618             :             {
    8619           8 :               printf (" %-5" PRIu64 " ", i);
    8620          24 :               for (int j = 0; j < file_name_format_count; j++)
    8621             :                 {
    8622          16 :                   linep = print_form_data (dbg, enc[j].form,
    8623             :                                            linep, lineendp, length,
    8624             :                                            str_offsets_base);
    8625          16 :                   if (j + 1 < file_name_format_count)
    8626           8 :                     printf (", ");
    8627             :                 }
    8628           8 :               printf ("\n");
    8629           8 :               if (linep >= lineendp)
    8630           0 :                 goto invalid_unit;
    8631             :             }
    8632             :         }
    8633             :       else
    8634             :         {
    8635        1103 :           puts (gettext (" Entry Dir   Time      Size      Name"));
    8636       23173 :           for (unsigned int cnt = 1; linep < lineendp && *linep != 0; ++cnt)
    8637             :             {
    8638             :               /* First comes the file name.  */
    8639       22070 :               char *fname = (char *) linep;
    8640       22070 :               unsigned char *endp = memchr (fname, '\0', lineendp - linep);
    8641       22070 :               if (unlikely (endp == NULL))
    8642             :                 goto invalid_unit;
    8643       22070 :               linep = endp + 1;
    8644             : 
    8645             :               /* Then the index.  */
    8646       22070 :               unsigned int diridx;
    8647       22070 :               if (lineendp - linep < 1)
    8648             :                 goto invalid_unit;
    8649       22070 :               get_uleb128 (diridx, linep, lineendp);
    8650             : 
    8651             :               /* Next comes the modification time.  */
    8652       22070 :               unsigned int mtime;
    8653       22070 :               if (lineendp - linep < 1)
    8654             :                 goto invalid_unit;
    8655       22070 :               get_uleb128 (mtime, linep, lineendp);
    8656             : 
    8657             :               /* Finally the length of the file.  */
    8658       22070 :               unsigned int fsize;
    8659       22070 :               if (lineendp - linep < 1)
    8660             :                 goto invalid_unit;
    8661       22070 :               get_uleb128 (fsize, linep, lineendp);
    8662             : 
    8663       22070 :               printf (" %-5u %-5u %-9u %-9u %s\n",
    8664             :                       cnt, diridx, mtime, fsize, fname);
    8665             :             }
    8666        1103 :           if (linep >= lineendp || *linep != '\0')
    8667             :             goto invalid_unit;
    8668             :           /* Skip the final NUL byte.  */
    8669        1103 :           ++linep;
    8670             :         }
    8671             : 
    8672        1105 :       puts (gettext ("\nLine number statements:"));
    8673        1105 :       Dwarf_Word address = 0;
    8674        1105 :       unsigned int op_index = 0;
    8675        1105 :       size_t line = 1;
    8676        1105 :       uint_fast8_t is_stmt = default_is_stmt;
    8677             : 
    8678             :       /* Apply the "operation advance" from a special opcode
    8679             :          or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
    8680        1105 :       unsigned int op_addr_advance;
    8681        1105 :       bool show_op_index;
    8682        1105 :       inline void advance_pc (unsigned int op_advance)
    8683             :       {
    8684      512588 :         op_addr_advance = minimum_instr_len * ((op_index + op_advance)
    8685      256294 :                                                / max_ops_per_instr);
    8686      256294 :         address += op_addr_advance;
    8687      768882 :         show_op_index = (op_index > 0 ||
    8688      256294 :                          (op_index + op_advance) % max_ops_per_instr > 0);
    8689      256294 :         op_index = (op_index + op_advance) % max_ops_per_instr;
    8690             :       }
    8691             : 
    8692        1105 :       if (max_ops_per_instr == 0)
    8693             :         {
    8694           0 :           error (0, 0,
    8695           0 :                  gettext ("invalid maximum operations per instruction is zero"));
    8696           0 :           linep = lineendp;
    8697           0 :           continue;
    8698             :         }
    8699             : 
    8700      810340 :       while (linep < lineendp)
    8701             :         {
    8702      809235 :           size_t offset = linep - (const unsigned char *) data->d_buf;
    8703      809235 :           unsigned int u128;
    8704      809235 :           int s128;
    8705             : 
    8706             :           /* Read the opcode.  */
    8707      809235 :           unsigned int opcode = *linep++;
    8708             : 
    8709      809235 :           printf (" [%6" PRIx64 "]", (uint64_t)offset);
    8710             :           /* Is this a special opcode?  */
    8711      809235 :           if (likely (opcode >= opcode_base))
    8712             :             {
    8713      234014 :               if (unlikely (line_range == 0))
    8714             :                 goto invalid_unit;
    8715             : 
    8716             :               /* Yes.  Handling this is quite easy since the opcode value
    8717             :                  is computed with
    8718             : 
    8719             :                  opcode = (desired line increment - line_base)
    8720             :                            + (line_range * address advance) + opcode_base
    8721             :               */
    8722      468028 :               int line_increment = (line_base
    8723      234014 :                                     + (opcode - opcode_base) % line_range);
    8724             : 
    8725             :               /* Perform the increments.  */
    8726      234014 :               line += line_increment;
    8727      234014 :               advance_pc ((opcode - opcode_base) / line_range);
    8728             : 
    8729      234014 :               printf (gettext (" special opcode %u: address+%u = "),
    8730             :                       opcode, op_addr_advance);
    8731      234014 :               print_dwarf_addr (dwflmod, 0, address, address);
    8732      234014 :               if (show_op_index)
    8733           0 :                 printf (gettext (", op_index = %u, line%+d = %zu\n"),
    8734             :                         op_index, line_increment, line);
    8735             :               else
    8736      234014 :                 printf (gettext (", line%+d = %zu\n"),
    8737             :                         line_increment, line);
    8738             :             }
    8739      575221 :           else if (opcode == 0)
    8740             :             {
    8741             :               /* This an extended opcode.  */
    8742       33341 :               if (unlikely (linep + 2 > lineendp))
    8743             :                 goto invalid_unit;
    8744             : 
    8745             :               /* The length.  */
    8746       33341 :               unsigned int len = *linep++;
    8747             : 
    8748       33341 :               if (unlikely (linep + len > lineendp))
    8749             :                 goto invalid_unit;
    8750             : 
    8751             :               /* The sub-opcode.  */
    8752       33341 :               opcode = *linep++;
    8753             : 
    8754       33341 :               printf (gettext (" extended opcode %u: "), opcode);
    8755             : 
    8756       33341 :               switch (opcode)
    8757             :                 {
    8758        1136 :                 case DW_LNE_end_sequence:
    8759        1136 :                   puts (gettext (" end of sequence"));
    8760             : 
    8761             :                   /* Reset the registers we care about.  */
    8762        1136 :                   address = 0;
    8763        1136 :                   op_index = 0;
    8764        1136 :                   line = 1;
    8765        1136 :                   is_stmt = default_is_stmt;
    8766        1136 :                   break;
    8767             : 
    8768        1423 :                 case DW_LNE_set_address:
    8769        1423 :                   op_index = 0;
    8770        1423 :                   if (unlikely ((size_t) (lineendp - linep) < address_size))
    8771             :                     goto invalid_unit;
    8772        1423 :                   if (address_size == 4)
    8773          17 :                     address = read_4ubyte_unaligned_inc (dbg, linep);
    8774             :                   else
    8775        1406 :                     address = read_8ubyte_unaligned_inc (dbg, linep);
    8776             :                   {
    8777        1423 :                     printf (gettext (" set address to "));
    8778        1423 :                     print_dwarf_addr (dwflmod, 0, address, address);
    8779        1423 :                     printf ("\n");
    8780             :                   }
    8781             :                   break;
    8782             : 
    8783           0 :                 case DW_LNE_define_file:
    8784             :                   {
    8785           0 :                     char *fname = (char *) linep;
    8786           0 :                     unsigned char *endp = memchr (linep, '\0',
    8787           0 :                                                   lineendp - linep);
    8788           0 :                     if (unlikely (endp == NULL))
    8789             :                       goto invalid_unit;
    8790           0 :                     linep = endp + 1;
    8791             : 
    8792           0 :                     unsigned int diridx;
    8793           0 :                     if (lineendp - linep < 1)
    8794             :                       goto invalid_unit;
    8795           0 :                     get_uleb128 (diridx, linep, lineendp);
    8796           0 :                     Dwarf_Word mtime;
    8797           0 :                     if (lineendp - linep < 1)
    8798             :                       goto invalid_unit;
    8799           0 :                     get_uleb128 (mtime, linep, lineendp);
    8800           0 :                     Dwarf_Word filelength;
    8801           0 :                     if (lineendp - linep < 1)
    8802             :                       goto invalid_unit;
    8803           0 :                     get_uleb128 (filelength, linep, lineendp);
    8804             : 
    8805           0 :                     printf (gettext ("\
    8806             :  define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
    8807             :                             diridx, (uint64_t) mtime, (uint64_t) filelength,
    8808             :                             fname);
    8809             :                   }
    8810             :                   break;
    8811             : 
    8812       30782 :                 case DW_LNE_set_discriminator:
    8813             :                   /* Takes one ULEB128 parameter, the discriminator.  */
    8814       30782 :                   if (unlikely (standard_opcode_lengths[opcode] != 1
    8815             :                                 || lineendp - linep < 1))
    8816             :                     goto invalid_unit;
    8817             : 
    8818       30782 :                   get_uleb128 (u128, linep, lineendp);
    8819       30782 :                   printf (gettext (" set discriminator to %u\n"), u128);
    8820             :                   break;
    8821             : 
    8822           0 :                 default:
    8823             :                   /* Unknown, ignore it.  */
    8824           0 :                   puts (gettext (" unknown opcode"));
    8825           0 :                   linep += len - 1;
    8826           0 :                   break;
    8827             :                 }
    8828             :             }
    8829      541880 :           else if (opcode <= DW_LNS_set_isa)
    8830             :             {
    8831             :               /* This is a known standard opcode.  */
    8832      541880 :               switch (opcode)
    8833             :                 {
    8834       85451 :                 case DW_LNS_copy:
    8835             :                   /* Takes no argument.  */
    8836       85451 :                   puts (gettext (" copy"));
    8837       85451 :                   break;
    8838             : 
    8839        3390 :                 case DW_LNS_advance_pc:
    8840             :                   /* Takes one uleb128 parameter which is added to the
    8841             :                      address.  */
    8842        3390 :                   if (lineendp - linep < 1)
    8843             :                     goto invalid_unit;
    8844        3390 :                   get_uleb128 (u128, linep, lineendp);
    8845        3390 :                   advance_pc (u128);
    8846             :                   {
    8847        3390 :                     printf (gettext (" advance address by %u to "),
    8848             :                             op_addr_advance);
    8849        3390 :                     print_dwarf_addr (dwflmod, 0, address, address);
    8850        3390 :                     if (show_op_index)
    8851           0 :                       printf (gettext (", op_index to %u"), op_index);
    8852        3390 :                     printf ("\n");
    8853             :                   }
    8854             :                   break;
    8855             : 
    8856       61929 :                 case DW_LNS_advance_line:
    8857             :                   /* Takes one sleb128 parameter which is added to the
    8858             :                      line.  */
    8859       61929 :                   if (lineendp - linep < 1)
    8860             :                     goto invalid_unit;
    8861       61929 :                   get_sleb128 (s128, linep, lineendp);
    8862       61929 :                   line += s128;
    8863       61929 :                   printf (gettext ("\
    8864             :  advance line by constant %d to %" PRId64 "\n"),
    8865             :                           s128, (int64_t) line);
    8866             :                   break;
    8867             : 
    8868       25095 :                 case DW_LNS_set_file:
    8869             :                   /* Takes one uleb128 parameter which is stored in file.  */
    8870       25095 :                   if (lineendp - linep < 1)
    8871             :                     goto invalid_unit;
    8872       25095 :                   get_uleb128 (u128, linep, lineendp);
    8873       25095 :                   printf (gettext (" set file to %" PRIu64 "\n"),
    8874             :                           (uint64_t) u128);
    8875             :                   break;
    8876             : 
    8877      205787 :                 case DW_LNS_set_column:
    8878             :                   /* Takes one uleb128 parameter which is stored in column.  */
    8879      205787 :                   if (unlikely (standard_opcode_lengths[opcode] != 1
    8880             :                                 || lineendp - linep < 1))
    8881             :                     goto invalid_unit;
    8882             : 
    8883      205787 :                   get_uleb128 (u128, linep, lineendp);
    8884      205787 :                   printf (gettext (" set column to %" PRIu64 "\n"),
    8885             :                           (uint64_t) u128);
    8886             :                   break;
    8887             : 
    8888      141315 :                 case DW_LNS_negate_stmt:
    8889             :                   /* Takes no argument.  */
    8890      141315 :                   is_stmt = 1 - is_stmt;
    8891      141315 :                   printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
    8892             :                           "is_stmt", is_stmt);
    8893             :                   break;
    8894             : 
    8895           0 :                 case DW_LNS_set_basic_block:
    8896             :                   /* Takes no argument.  */
    8897           0 :                   puts (gettext (" set basic block flag"));
    8898           0 :                   break;
    8899             : 
    8900       18890 :                 case DW_LNS_const_add_pc:
    8901             :                   /* Takes no argument.  */
    8902             : 
    8903       18890 :                   if (unlikely (line_range == 0))
    8904             :                     goto invalid_unit;
    8905             : 
    8906       18890 :                   advance_pc ((255 - opcode_base) / line_range);
    8907             :                   {
    8908       18890 :                     printf (gettext (" advance address by constant %u to "),
    8909             :                             op_addr_advance);
    8910       18890 :                     print_dwarf_addr (dwflmod, 0, address, address);
    8911       18890 :                     if (show_op_index)
    8912           0 :                       printf (gettext (", op_index to %u"), op_index);
    8913       18890 :                     printf ("\n");
    8914             :                   }
    8915             :                   break;
    8916             : 
    8917          22 :                 case DW_LNS_fixed_advance_pc:
    8918             :                   /* Takes one 16 bit parameter which is added to the
    8919             :                      address.  */
    8920          22 :                   if (unlikely (standard_opcode_lengths[opcode] != 1
    8921             :                                 || lineendp - linep < 2))
    8922             :                     goto invalid_unit;
    8923             : 
    8924          22 :                   u128 = read_2ubyte_unaligned_inc (dbg, linep);
    8925          22 :                   address += u128;
    8926          22 :                   op_index = 0;
    8927             :                   {
    8928          22 :                     printf (gettext ("\
    8929             :  advance address by fixed value %u to \n"),
    8930             :                             u128);
    8931          22 :                     print_dwarf_addr (dwflmod, 0, address, address);
    8932          22 :                     printf ("\n");
    8933             :                   }
    8934             :                   break;
    8935             : 
    8936           1 :                 case DW_LNS_set_prologue_end:
    8937             :                   /* Takes no argument.  */
    8938           1 :                   puts (gettext (" set prologue end flag"));
    8939           1 :                   break;
    8940             : 
    8941           0 :                 case DW_LNS_set_epilogue_begin:
    8942             :                   /* Takes no argument.  */
    8943           0 :                   puts (gettext (" set epilogue begin flag"));
    8944           0 :                   break;
    8945             : 
    8946           0 :                 case DW_LNS_set_isa:
    8947             :                   /* Takes one uleb128 parameter which is stored in isa.  */
    8948           0 :                   if (unlikely (standard_opcode_lengths[opcode] != 1
    8949             :                                 || lineendp - linep < 1))
    8950             :                     goto invalid_unit;
    8951             : 
    8952           0 :                   get_uleb128 (u128, linep, lineendp);
    8953           0 :                   printf (gettext (" set isa to %u\n"), u128);
    8954             :                   break;
    8955             :                 }
    8956             :             }
    8957             :           else
    8958             :             {
    8959             :               /* This is a new opcode the generator but not we know about.
    8960             :                  Read the parameters associated with it but then discard
    8961             :                  everything.  Read all the parameters for this opcode.  */
    8962           0 :               printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
    8963             :                                 " unknown opcode with %" PRIu8 " parameters:",
    8964             :                                 standard_opcode_lengths[opcode]),
    8965           0 :                       standard_opcode_lengths[opcode]);
    8966           0 :               for (int n = standard_opcode_lengths[opcode];
    8967           0 :                    n > 0 && linep < lineendp; --n)
    8968             :                 {
    8969           0 :                   get_uleb128 (u128, linep, lineendp);
    8970           0 :                   if (n != standard_opcode_lengths[opcode])
    8971           0 :                     putc_unlocked (',', stdout);
    8972           0 :                   printf (" %u", u128);
    8973             :                 }
    8974             : 
    8975             :               /* Next round, ignore this opcode.  */
    8976             :               continue;
    8977             :             }
    8978             :         }
    8979             :     }
    8980             : 
    8981             :   /* There must only be one data block.  */
    8982          48 :   assert (elf_getdata (scn, data) == NULL);
    8983             : }
    8984             : 
    8985             : 
    8986             : static void
    8987           3 : print_debug_loclists_section (Dwfl_Module *dwflmod,
    8988             :                               Ebl *ebl,
    8989             :                               GElf_Ehdr *ehdr __attribute__ ((unused)),
    8990             :                               Elf_Scn *scn, GElf_Shdr *shdr,
    8991             :                               Dwarf *dbg)
    8992             : {
    8993           3 :   printf (gettext ("\
    8994             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    8995             :           elf_ndxscn (scn), section_name (ebl, shdr),
    8996           3 :           (uint64_t) shdr->sh_offset);
    8997             : 
    8998           6 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_loclists]
    8999           3 :                     ?: elf_rawdata (scn, NULL));
    9000           3 :   if (unlikely (data == NULL))
    9001             :     {
    9002           0 :       error (0, 0, gettext ("cannot get .debug_loclists content: %s"),
    9003             :              elf_errmsg (-1));
    9004           0 :       return;
    9005             :     }
    9006             : 
    9007             :   /* For the listptr to get the base address/CU.  */
    9008           3 :   sort_listptr (&known_loclistsptr, "loclistsptr");
    9009           3 :   size_t listptr_idx = 0;
    9010             : 
    9011           3 :   const unsigned char *readp = data->d_buf;
    9012           6 :   const unsigned char *const dataend = ((unsigned char *) data->d_buf
    9013           3 :                                         + data->d_size);
    9014           7 :   while (readp < dataend)
    9015             :     {
    9016           4 :       if (unlikely (readp > dataend - 4))
    9017             :         {
    9018           0 :         invalid_data:
    9019           0 :           error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
    9020             :                  elf_ndxscn (scn), section_name (ebl, shdr));
    9021           0 :           return;
    9022             :         }
    9023             : 
    9024           4 :       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
    9025           4 :       printf (gettext ("Table at Offset 0x%" PRIx64 ":\n\n"),
    9026             :               (uint64_t) offset);
    9027             : 
    9028           4 :       uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
    9029           4 :       unsigned int offset_size = 4;
    9030           4 :       if (unlikely (unit_length == 0xffffffff))
    9031             :         {
    9032           0 :           if (unlikely (readp > dataend - 8))
    9033             :             goto invalid_data;
    9034             : 
    9035           0 :           unit_length = read_8ubyte_unaligned_inc (dbg, readp);
    9036           0 :           offset_size = 8;
    9037             :         }
    9038           4 :       printf (gettext (" Length:         %8" PRIu64 "\n"), unit_length);
    9039             : 
    9040             :       /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
    9041             :          bytes to complete the header.  And this unit cannot go beyond
    9042             :          the section data.  */
    9043           4 :       if (readp > dataend - 8
    9044           4 :           || unit_length < 8
    9045           4 :           || unit_length > (uint64_t) (dataend - readp))
    9046             :         goto invalid_data;
    9047             : 
    9048           4 :       const unsigned char *nexthdr = readp + unit_length;
    9049             : 
    9050           4 :       uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
    9051           4 :       printf (gettext (" DWARF version:  %8" PRIu16 "\n"), version);
    9052             : 
    9053           4 :       if (version != 5)
    9054             :         {
    9055           0 :           error (0, 0, gettext ("Unknown version"));
    9056           0 :           goto next_table;
    9057             :         }
    9058             : 
    9059           4 :       uint8_t address_size = *readp++;
    9060           4 :       printf (gettext (" Address size:   %8" PRIu64 "\n"),
    9061             :               (uint64_t) address_size);
    9062             : 
    9063           4 :       if (address_size != 4 && address_size != 8)
    9064             :         {
    9065           0 :           error (0, 0, gettext ("unsupported address size"));
    9066           0 :           goto next_table;
    9067             :         }
    9068             : 
    9069           4 :       uint8_t segment_size = *readp++;
    9070           4 :       printf (gettext (" Segment size:   %8" PRIu64 "\n"),
    9071             :               (uint64_t) segment_size);
    9072             : 
    9073           4 :       if (segment_size != 0)
    9074             :         {
    9075           0 :           error (0, 0, gettext ("unsupported segment size"));
    9076           0 :           goto next_table;
    9077             :         }
    9078             : 
    9079           4 :       uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
    9080           4 :       printf (gettext (" Offset entries: %8" PRIu64 "\n"),
    9081             :               (uint64_t) offset_entry_count);
    9082             : 
    9083             :       /* We need the CU that uses this unit to get the initial base address. */
    9084           4 :       Dwarf_Addr cu_base = 0;
    9085           4 :       struct Dwarf_CU *cu = NULL;
    9086           4 :       if (listptr_cu (&known_loclistsptr, &listptr_idx,
    9087             :                       (Dwarf_Off) offset,
    9088           4 :                       (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
    9089             :                       &cu_base, &cu)
    9090           0 :           || split_dwarf_cu_base (dbg, &cu, &cu_base))
    9091           4 :         {
    9092           4 :           Dwarf_Die cudie;
    9093           4 :           if (dwarf_cu_die (cu, &cudie,
    9094             :                             NULL, NULL, NULL, NULL,
    9095             :                             NULL, NULL) == NULL)
    9096           0 :             printf (gettext (" Unknown CU base: "));
    9097             :           else
    9098           4 :             printf (gettext (" CU [%6" PRIx64 "] base: "),
    9099             :                     dwarf_dieoffset (&cudie));
    9100           4 :           print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
    9101           4 :           printf ("\n");
    9102             :         }
    9103             :       else
    9104           0 :         printf (gettext (" Not associated with a CU.\n"));
    9105             : 
    9106           4 :       printf ("\n");
    9107             : 
    9108           4 :       const unsigned char *offset_array_start = readp;
    9109           4 :       if (offset_entry_count > 0)
    9110             :         {
    9111           2 :           uint64_t max_entries = (unit_length - 8) / offset_size;
    9112           2 :           if (offset_entry_count > max_entries)
    9113             :             {
    9114           0 :               error (0, 0,
    9115           0 :                      gettext ("too many offset entries for unit length"));
    9116           0 :               offset_entry_count = max_entries;
    9117             :             }
    9118             : 
    9119           6 :           printf (gettext ("  Offsets starting at 0x%" PRIx64 ":\n"),
    9120             :                   (uint64_t) (offset_array_start
    9121           2 :                               - (unsigned char *) data->d_buf));
    9122          18 :           for (uint32_t idx = 0; idx < offset_entry_count; idx++)
    9123             :             {
    9124          16 :               printf ("   [%6" PRIu32 "] ", idx);
    9125          16 :               if (offset_size == 4)
    9126             :                 {
    9127          16 :                   uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
    9128          16 :                   printf ("0x%" PRIx32 "\n", off);
    9129             :                 }
    9130             :               else
    9131             :                 {
    9132           0 :                   uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
    9133           0 :                   printf ("0x%" PRIx64 "\n", off);
    9134             :                 }
    9135             :             }
    9136           2 :           printf ("\n");
    9137             :         }
    9138             : 
    9139           4 :       Dwarf_Addr base = cu_base;
    9140           4 :       bool start_of_list = true;
    9141          93 :       while (readp < nexthdr)
    9142             :         {
    9143          89 :           uint8_t kind = *readp++;
    9144          89 :           uint64_t op1, op2, len;
    9145             : 
    9146             :           /* Skip padding.  */
    9147          89 :           if (start_of_list && kind == DW_LLE_end_of_list)
    9148             :             continue;
    9149             : 
    9150          89 :           if (start_of_list)
    9151             :             {
    9152          32 :               base = cu_base;
    9153         128 :               printf ("  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
    9154          32 :                       (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
    9155          32 :                       (uint64_t) (readp - offset_array_start - 1));
    9156          32 :               start_of_list = false;
    9157             :             }
    9158             : 
    9159          89 :           printf ("    %s", dwarf_loc_list_encoding_name (kind));
    9160          89 :           switch (kind)
    9161             :             {
    9162          32 :             case DW_LLE_end_of_list:
    9163          32 :               start_of_list = true;
    9164          32 :               printf ("\n\n");
    9165             :               break;
    9166             : 
    9167           0 :             case DW_LLE_base_addressx:
    9168           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9169             :                 {
    9170           0 :                 invalid_entry:
    9171           0 :                   error (0, 0, gettext ("invalid loclists data"));
    9172           0 :                   goto next_table;
    9173             :                 }
    9174           0 :               get_uleb128 (op1, readp, nexthdr);
    9175           0 :               printf (" %" PRIx64 "\n", op1);
    9176           0 :               if (! print_unresolved_addresses)
    9177             :                 {
    9178           0 :                   Dwarf_Addr addr;
    9179           0 :                   if (get_indexed_addr (cu, op1, &addr) != 0)
    9180           0 :                     printf ("      ???\n");
    9181             :                   else
    9182             :                     {
    9183           0 :                       printf ("      ");
    9184           0 :                       print_dwarf_addr (dwflmod, address_size, addr, addr);
    9185           0 :                       printf ("\n");
    9186             :                     }
    9187             :                 }
    9188             :               break;
    9189             : 
    9190           0 :             case DW_LLE_startx_endx:
    9191           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9192             :                 goto invalid_entry;
    9193           0 :               get_uleb128 (op1, readp, nexthdr);
    9194           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9195             :                 goto invalid_entry;
    9196           0 :               get_uleb128 (op2, readp, nexthdr);
    9197           0 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    9198           0 :               if (! print_unresolved_addresses)
    9199             :                 {
    9200           0 :                   Dwarf_Addr addr1;
    9201           0 :                   Dwarf_Addr addr2;
    9202           0 :                   if (get_indexed_addr (cu, op1, &addr1) != 0
    9203           0 :                       || get_indexed_addr (cu, op2, &addr2) != 0)
    9204             :                     {
    9205           0 :                       printf ("      ???..\n");
    9206           0 :                       printf ("      ???\n");
    9207             :                     }
    9208             :                   else
    9209             :                     {
    9210           0 :                       printf ("      ");
    9211           0 :                       print_dwarf_addr (dwflmod, address_size, addr1, addr1);
    9212           0 :                       printf ("..\n      ");
    9213           0 :                       print_dwarf_addr (dwflmod, address_size,
    9214             :                                         addr2 - 1, addr2);
    9215           0 :                       printf ("\n");
    9216             :                     }
    9217             :                 }
    9218           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9219             :                 goto invalid_entry;
    9220           0 :               get_uleb128 (len, readp, nexthdr);
    9221           0 :               if ((uint64_t) (nexthdr - readp) < len)
    9222             :                 goto invalid_entry;
    9223           0 :               print_ops (dwflmod, dbg, 8, 8, version,
    9224             :                          address_size, offset_size, cu, len, readp);
    9225           0 :               readp += len;
    9226           0 :               break;
    9227             : 
    9228          26 :             case DW_LLE_startx_length:
    9229          26 :               if ((uint64_t) (nexthdr - readp) < 1)
    9230             :                 goto invalid_entry;
    9231          26 :               get_uleb128 (op1, readp, nexthdr);
    9232          26 :               if ((uint64_t) (nexthdr - readp) < 1)
    9233             :                 goto invalid_entry;
    9234          26 :               get_uleb128 (op2, readp, nexthdr);
    9235          26 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    9236          26 :               if (! print_unresolved_addresses)
    9237             :                 {
    9238          26 :                   Dwarf_Addr addr1;
    9239          26 :                   Dwarf_Addr addr2;
    9240          26 :                   if (get_indexed_addr (cu, op1, &addr1) != 0)
    9241             :                     {
    9242           0 :                       printf ("      ???..\n");
    9243           0 :                       printf ("      ???\n");
    9244             :                     }
    9245             :                   else
    9246             :                     {
    9247          26 :                       addr2 = addr1 + op2;
    9248          26 :                       printf ("      ");
    9249          26 :                       print_dwarf_addr (dwflmod, address_size, addr1, addr1);
    9250          26 :                       printf ("..\n      ");
    9251          26 :                       print_dwarf_addr (dwflmod, address_size,
    9252             :                                         addr2 - 1, addr2);
    9253          26 :                       printf ("\n");
    9254             :                     }
    9255             :                 }
    9256          26 :               if ((uint64_t) (nexthdr - readp) < 1)
    9257             :                 goto invalid_entry;
    9258          26 :               get_uleb128 (len, readp, nexthdr);
    9259          26 :               if ((uint64_t) (nexthdr - readp) < len)
    9260             :                 goto invalid_entry;
    9261          26 :               print_ops (dwflmod, dbg, 8, 8, version,
    9262             :                          address_size, offset_size, cu, len, readp);
    9263          26 :               readp += len;
    9264          26 :               break;
    9265             : 
    9266          24 :             case DW_LLE_offset_pair:
    9267          24 :               if ((uint64_t) (nexthdr - readp) < 1)
    9268             :                 goto invalid_entry;
    9269          24 :               get_uleb128 (op1, readp, nexthdr);
    9270          24 :               if ((uint64_t) (nexthdr - readp) < 1)
    9271             :                 goto invalid_entry;
    9272          24 :               get_uleb128 (op2, readp, nexthdr);
    9273          24 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    9274          24 :               if (! print_unresolved_addresses)
    9275             :                 {
    9276          24 :                   op1 += base;
    9277          24 :                   op2 += base;
    9278          24 :                   printf ("      ");
    9279          24 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    9280          24 :                   printf ("..\n      ");
    9281          24 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    9282          24 :                   printf ("\n");
    9283             :                 }
    9284          24 :               if ((uint64_t) (nexthdr - readp) < 1)
    9285             :                 goto invalid_entry;
    9286          24 :               get_uleb128 (len, readp, nexthdr);
    9287          24 :               if ((uint64_t) (nexthdr - readp) < len)
    9288             :                 goto invalid_entry;
    9289          24 :               print_ops (dwflmod, dbg, 8, 8, version,
    9290             :                          address_size, offset_size, cu, len, readp);
    9291          24 :               readp += len;
    9292          24 :               break;
    9293             : 
    9294           0 :             case DW_LLE_default_location:
    9295           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9296             :                 goto invalid_entry;
    9297           0 :               get_uleb128 (len, readp, nexthdr);
    9298           0 :               if ((uint64_t) (nexthdr - readp) < len)
    9299             :                 goto invalid_entry;
    9300           0 :               print_ops (dwflmod, dbg, 8, 8, version,
    9301             :                          address_size, offset_size, cu, len, readp);
    9302           0 :               readp += len;
    9303           0 :               break;
    9304             : 
    9305           5 :             case DW_LLE_base_address:
    9306           5 :               if (address_size == 4)
    9307             :                 {
    9308           0 :                   if ((uint64_t) (nexthdr - readp) < 4)
    9309             :                     goto invalid_entry;
    9310           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    9311             :                 }
    9312             :               else
    9313             :                 {
    9314           5 :                   if ((uint64_t) (nexthdr - readp) < 8)
    9315             :                     goto invalid_entry;
    9316           5 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    9317             :                 }
    9318           5 :               base = op1;
    9319           5 :               printf (" 0x%" PRIx64 "\n", base);
    9320           5 :               if (! print_unresolved_addresses)
    9321             :                 {
    9322           5 :                   printf ("      ");
    9323           5 :                   print_dwarf_addr (dwflmod, address_size, base, base);
    9324           5 :                   printf ("\n");
    9325             :                 }
    9326             :               break;
    9327             : 
    9328           0 :             case DW_LLE_start_end:
    9329           0 :               if (address_size == 4)
    9330             :                 {
    9331           0 :                   if ((uint64_t) (nexthdr - readp) < 8)
    9332             :                     goto invalid_entry;
    9333           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    9334           0 :                   op2 = read_4ubyte_unaligned_inc (dbg, readp);
    9335             :                 }
    9336             :               else
    9337             :                 {
    9338           0 :                   if ((uint64_t) (nexthdr - readp) < 16)
    9339             :                     goto invalid_entry;
    9340           0 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    9341           0 :                   op2 = read_8ubyte_unaligned_inc (dbg, readp);
    9342             :                 }
    9343           0 :               printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
    9344           0 :               if (! print_unresolved_addresses)
    9345             :                 {
    9346           0 :                   printf ("      ");
    9347           0 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    9348           0 :                   printf ("..\n      ");
    9349           0 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    9350           0 :                   printf ("\n");
    9351             :                 }
    9352           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9353             :                 goto invalid_entry;
    9354           0 :               get_uleb128 (len, readp, nexthdr);
    9355           0 :               if ((uint64_t) (nexthdr - readp) < len)
    9356             :                 goto invalid_entry;
    9357           0 :               print_ops (dwflmod, dbg, 8, 8, version,
    9358             :                          address_size, offset_size, cu, len, readp);
    9359           0 :               readp += len;
    9360           0 :               break;
    9361             : 
    9362           2 :             case DW_LLE_start_length:
    9363           2 :               if (address_size == 4)
    9364             :                 {
    9365           0 :                   if ((uint64_t) (nexthdr - readp) < 4)
    9366             :                     goto invalid_entry;
    9367           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    9368             :                 }
    9369             :               else
    9370             :                 {
    9371           2 :                   if ((uint64_t) (nexthdr - readp) < 8)
    9372             :                     goto invalid_entry;
    9373           2 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    9374             :                 }
    9375           2 :               if ((uint64_t) (nexthdr - readp) < 1)
    9376             :                 goto invalid_entry;
    9377           2 :               get_uleb128 (op2, readp, nexthdr);
    9378           2 :               printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
    9379           2 :               if (! print_unresolved_addresses)
    9380             :                 {
    9381           2 :                   op2 = op1 + op2;
    9382           2 :                   printf ("      ");
    9383           2 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    9384           2 :                   printf ("..\n      ");
    9385           2 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    9386           2 :                   printf ("\n");
    9387             :                 }
    9388           2 :               if ((uint64_t) (nexthdr - readp) < 1)
    9389             :                 goto invalid_entry;
    9390           2 :               get_uleb128 (len, readp, nexthdr);
    9391           2 :               if ((uint64_t) (nexthdr - readp) < len)
    9392             :                 goto invalid_entry;
    9393           2 :               print_ops (dwflmod, dbg, 8, 8, version,
    9394             :                          address_size, offset_size, cu, len, readp);
    9395           2 :               readp += len;
    9396           2 :               break;
    9397             : 
    9398             :             default:
    9399             :               goto invalid_entry;
    9400             :             }
    9401             :         }
    9402             : 
    9403           4 :     next_table:
    9404           4 :       if (readp != nexthdr)
    9405             :         {
    9406           0 :           size_t padding = nexthdr - readp;
    9407           0 :           printf (gettext ("   %zu padding bytes\n\n"), padding);
    9408           0 :           readp = nexthdr;
    9409             :         }
    9410             :     }
    9411             : }
    9412             : 
    9413             : 
    9414             : static void
    9415          44 : print_debug_loc_section (Dwfl_Module *dwflmod,
    9416             :                          Ebl *ebl, GElf_Ehdr *ehdr,
    9417             :                          Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    9418             : {
    9419          88 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_loc]
    9420          44 :                     ?: elf_rawdata (scn, NULL));
    9421             : 
    9422          44 :   if (unlikely (data == NULL))
    9423             :     {
    9424           0 :       error (0, 0, gettext ("cannot get .debug_loc content: %s"),
    9425             :              elf_errmsg (-1));
    9426           0 :       return;
    9427             :     }
    9428             : 
    9429          44 :   printf (gettext ("\
    9430             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    9431             :           elf_ndxscn (scn), section_name (ebl, shdr),
    9432          44 :           (uint64_t) shdr->sh_offset);
    9433             : 
    9434          44 :   sort_listptr (&known_locsptr, "loclistptr");
    9435          44 :   size_t listptr_idx = 0;
    9436             : 
    9437          44 :   uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    9438          44 :   uint_fast8_t offset_size = 4;
    9439             : 
    9440          44 :   bool first = true;
    9441          44 :   Dwarf_Addr base = 0;
    9442          44 :   unsigned char *readp = data->d_buf;
    9443          44 :   unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
    9444          44 :   Dwarf_CU *last_cu = NULL;
    9445      275418 :   while (readp < endp)
    9446             :     {
    9447      275374 :       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
    9448      275374 :       Dwarf_CU *cu = last_cu;
    9449      275374 :       unsigned int attr = 0;
    9450             : 
    9451      275374 :       if (first && skip_listptr_hole (&known_locsptr, &listptr_idx,
    9452             :                                       &address_size, &offset_size, &base,
    9453             :                                       &cu, offset, &readp, endp, &attr))
    9454       43054 :         continue;
    9455             : 
    9456      275374 :       if (last_cu != cu)
    9457             :        {
    9458         974 :         Dwarf_Die cudie;
    9459         974 :         if (dwarf_cu_die (cu, &cudie,
    9460             :                           NULL, NULL, NULL, NULL,
    9461             :                           NULL, NULL) == NULL)
    9462           0 :           printf (gettext ("\n Unknown CU base: "));
    9463             :         else
    9464         974 :           printf (gettext ("\n CU [%6" PRIx64 "] base: "),
    9465             :                   dwarf_dieoffset (&cudie));
    9466         974 :         print_dwarf_addr (dwflmod, address_size, base, base);
    9467         974 :         printf ("\n");
    9468             :        }
    9469      275374 :       last_cu = cu;
    9470             : 
    9471      275374 :       if (attr == DW_AT_GNU_locviews)
    9472             :         {
    9473       43054 :           Dwarf_Off next_off = next_listptr_offset (&known_locsptr,
    9474             :                                                     listptr_idx);
    9475       43054 :           const unsigned char *locp = readp;
    9476       43054 :           const unsigned char *locendp;
    9477       43054 :           if (next_off == 0
    9478       43054 :               || next_off > (size_t) (endp
    9479       43054 :                                       - (const unsigned char *) data->d_buf))
    9480             :             locendp = endp;
    9481             :           else
    9482       43054 :             locendp = (const unsigned char *) data->d_buf + next_off;
    9483             : 
    9484      232101 :           while (locp < locendp)
    9485             :             {
    9486      189047 :               uint64_t v1, v2;
    9487      189047 :               get_uleb128 (v1, locp, locendp);
    9488      189047 :               if (locp >= locendp)
    9489             :                 {
    9490           0 :                   printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
    9491             :                   break;
    9492             :                 }
    9493      189047 :               get_uleb128 (v2, locp, locendp);
    9494      189047 :               if (first)                /* First view pair in a list.  */
    9495       43054 :                 printf (" [%6tx] ", offset);
    9496             :               else
    9497      145993 :                 printf ("          ");
    9498      189047 :               printf ("view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
    9499      189047 :               first = false;
    9500             :             }
    9501             : 
    9502       43054 :           first = true;
    9503       43054 :           readp = (unsigned char *) locendp;
    9504       43054 :           continue;
    9505             :         }
    9506             : 
    9507             :       /* GNU DebugFission encoded addresses as addrx.  */
    9508      464640 :       bool is_debugfission = ((cu != NULL
    9509           0 :                                || split_dwarf_cu_base (dbg, &cu, &base))
    9510      232320 :                               && (cu->version < 5
    9511      232320 :                                   && cu->unit_type == DW_UT_split_compile));
    9512      232320 :       if (!is_debugfission
    9513      232260 :           && unlikely (data->d_size - offset < (size_t) address_size * 2))
    9514             :         {
    9515           0 :         invalid_data:
    9516           0 :           printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
    9517           0 :           break;
    9518             :         }
    9519             : 
    9520      232320 :       Dwarf_Addr begin;
    9521      232320 :       Dwarf_Addr end;
    9522      232320 :       bool use_base = true;
    9523      232320 :       if (is_debugfission)
    9524             :         {
    9525          60 :           const unsigned char *locp = readp;
    9526          60 :           const unsigned char *locendp = readp + data->d_size;
    9527          60 :           if (locp >= locendp)
    9528           0 :             goto invalid_data;
    9529             : 
    9530          60 :           Dwarf_Word idx;
    9531          60 :           unsigned char code = *locp++;
    9532          60 :           switch (code)
    9533             :             {
    9534          20 :             case DW_LLE_GNU_end_of_list_entry:
    9535          20 :               begin = 0;
    9536          20 :               end = 0;
    9537          20 :               break;
    9538             : 
    9539           0 :             case DW_LLE_GNU_base_address_selection_entry:
    9540           0 :               if (locp >= locendp)
    9541           0 :                 goto invalid_data;
    9542           0 :               begin = (Dwarf_Addr) -1;
    9543           0 :               get_uleb128 (idx, locp, locendp);
    9544           0 :               if (get_indexed_addr (cu, idx, &end) != 0)
    9545           0 :                 end = idx; /* ... */
    9546             :               break;
    9547             : 
    9548           0 :             case DW_LLE_GNU_start_end_entry:
    9549           0 :               if (locp >= locendp)
    9550           0 :                 goto invalid_data;
    9551           0 :               get_uleb128 (idx, locp, locendp);
    9552           0 :               if (get_indexed_addr (cu, idx, &begin) != 0)
    9553           0 :                 begin = idx; /* ... */
    9554           0 :               if (locp >= locendp)
    9555           0 :                 goto invalid_data;
    9556           0 :               get_uleb128 (idx, locp, locendp);
    9557           0 :               if (get_indexed_addr (cu, idx, &end) != 0)
    9558           0 :                 end = idx; /* ... */
    9559             :               use_base = false;
    9560             :               break;
    9561             : 
    9562          40 :             case DW_LLE_GNU_start_length_entry:
    9563          40 :               if (locp >= locendp)
    9564           0 :                 goto invalid_data;
    9565          40 :               get_uleb128 (idx, locp, locendp);
    9566          40 :               if (get_indexed_addr (cu, idx, &begin) != 0)
    9567           0 :                 begin = idx; /* ... */
    9568          40 :               if (locendp - locp < 4)
    9569           0 :                 goto invalid_data;
    9570          40 :               end = read_4ubyte_unaligned_inc (dbg, locp);
    9571          40 :               end += begin;
    9572          40 :               use_base = false;
    9573          40 :               break;
    9574             : 
    9575           0 :             default:
    9576           0 :                 goto invalid_data;
    9577             :             }
    9578             : 
    9579          60 :           readp = (unsigned char *) locp;
    9580             :         }
    9581      232260 :       else if (address_size == 8)
    9582             :         {
    9583      232260 :           begin = read_8ubyte_unaligned_inc (dbg, readp);
    9584      232260 :           end = read_8ubyte_unaligned_inc (dbg, readp);
    9585             :         }
    9586             :       else
    9587             :         {
    9588           0 :           begin = read_4ubyte_unaligned_inc (dbg, readp);
    9589           0 :           end = read_4ubyte_unaligned_inc (dbg, readp);
    9590           0 :           if (begin == (Dwarf_Addr) (uint32_t) -1)
    9591           0 :             begin = (Dwarf_Addr) -1l;
    9592             :         }
    9593             : 
    9594      232320 :       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
    9595             :         {
    9596           0 :           printf (gettext (" [%6tx] base address\n          "), offset);
    9597           0 :           print_dwarf_addr (dwflmod, address_size, end, end);
    9598           0 :           printf ("\n");
    9599           0 :           base = end;
    9600             :         }
    9601      232320 :       else if (begin == 0 && end == 0) /* End of list entry.  */
    9602             :         {
    9603       43128 :           if (first)
    9604           0 :             printf (gettext (" [%6tx] empty list\n"), offset);
    9605             :           first = true;
    9606             :         }
    9607             :       else
    9608             :         {
    9609             :           /* We have a location expression entry.  */
    9610      189192 :           uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
    9611             : 
    9612      189192 :           if (first)            /* First entry in a list.  */
    9613       43128 :             printf (" [%6tx] ", offset);
    9614             :           else
    9615      146064 :             printf ("          ");
    9616             : 
    9617      189192 :           printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
    9618      189192 :           if (! print_unresolved_addresses)
    9619             :             {
    9620      189162 :               Dwarf_Addr dab = use_base ? base + begin : begin;
    9621      189162 :               Dwarf_Addr dae = use_base ? base + end : end;
    9622      189162 :               printf ("          ");
    9623      189162 :               print_dwarf_addr (dwflmod, address_size, dab, dab);
    9624      189162 :               printf ("..\n          ");
    9625      189162 :               print_dwarf_addr (dwflmod, address_size, dae - 1, dae);
    9626      189162 :               printf ("\n");
    9627             :             }
    9628             : 
    9629      189192 :           if (endp - readp <= (ptrdiff_t) len)
    9630             :             {
    9631           0 :               fputs (gettext ("   <INVALID DATA>\n"), stdout);
    9632           0 :               break;
    9633             :             }
    9634             : 
    9635      378384 :           print_ops (dwflmod, dbg, 11, 11,
    9636      189192 :                      cu != NULL ? cu->version : 3,
    9637             :                      address_size, offset_size, cu, len, readp);
    9638             : 
    9639      189192 :           first = false;
    9640      189192 :           readp += len;
    9641             :         }
    9642             :     }
    9643             : }
    9644             : 
    9645             : struct mac_culist
    9646             : {
    9647             :   Dwarf_Die die;
    9648             :   Dwarf_Off offset;
    9649             :   Dwarf_Files *files;
    9650             :   struct mac_culist *next;
    9651             : };
    9652             : 
    9653             : 
    9654             : static int
    9655           0 : mac_compare (const void *p1, const void *p2)
    9656             : {
    9657           0 :   struct mac_culist *m1 = (struct mac_culist *) p1;
    9658           0 :   struct mac_culist *m2 = (struct mac_culist *) p2;
    9659             : 
    9660           0 :   if (m1->offset < m2->offset)
    9661             :     return -1;
    9662           0 :   if (m1->offset > m2->offset)
    9663           0 :     return 1;
    9664             :   return 0;
    9665             : }
    9666             : 
    9667             : 
    9668             : static void
    9669           0 : print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
    9670             :                              Ebl *ebl,
    9671             :                              GElf_Ehdr *ehdr __attribute__ ((unused)),
    9672             :                              Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    9673             : {
    9674           0 :   printf (gettext ("\
    9675             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    9676             :           elf_ndxscn (scn), section_name (ebl, shdr),
    9677           0 :           (uint64_t) shdr->sh_offset);
    9678           0 :   putc_unlocked ('\n', stdout);
    9679             : 
    9680             :   /* There is no function in libdw to iterate over the raw content of
    9681             :      the section but it is easy enough to do.  */
    9682           0 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_macinfo]
    9683           0 :                     ?: elf_rawdata (scn, NULL));
    9684           0 :   if (unlikely (data == NULL))
    9685             :     {
    9686           0 :       error (0, 0, gettext ("cannot get macro information section data: %s"),
    9687             :              elf_errmsg (-1));
    9688           0 :       return;
    9689             :     }
    9690             : 
    9691             :   /* Get the source file information for all CUs.  */
    9692           0 :   Dwarf_Off offset;
    9693           0 :   Dwarf_Off ncu = 0;
    9694           0 :   size_t hsize;
    9695           0 :   struct mac_culist *culist = NULL;
    9696           0 :   size_t nculist = 0;
    9697           0 :   while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
    9698             :     {
    9699           0 :       Dwarf_Die cudie;
    9700           0 :       if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
    9701           0 :         continue;
    9702             : 
    9703           0 :       Dwarf_Attribute attr;
    9704           0 :       if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
    9705             :         continue;
    9706             : 
    9707           0 :       Dwarf_Word macoff;
    9708           0 :       if (dwarf_formudata (&attr, &macoff) != 0)
    9709             :         continue;
    9710             : 
    9711           0 :       struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
    9712           0 :       newp->die = cudie;
    9713           0 :       newp->offset = macoff;
    9714           0 :       newp->files = NULL;
    9715           0 :       newp->next = culist;
    9716           0 :       culist = newp;
    9717           0 :       ++nculist;
    9718             :     }
    9719             : 
    9720             :   /* Convert the list into an array for easier consumption.  */
    9721           0 :   struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
    9722             :                                                          * sizeof (*cus));
    9723             :   /* Add sentinel.  */
    9724           0 :   cus[nculist].offset = data->d_size;
    9725           0 :   cus[nculist].files = (Dwarf_Files *) -1l;
    9726           0 :   if (nculist > 0)
    9727             :     {
    9728           0 :       for (size_t cnt = nculist - 1; culist != NULL; --cnt)
    9729             :         {
    9730           0 :           assert (cnt < nculist);
    9731           0 :           cus[cnt] = *culist;
    9732           0 :           culist = culist->next;
    9733             :         }
    9734             : 
    9735             :       /* Sort the array according to the offset in the .debug_macinfo
    9736             :          section.  Note we keep the sentinel at the end.  */
    9737           0 :       qsort (cus, nculist, sizeof (*cus), mac_compare);
    9738             :     }
    9739             : 
    9740           0 :   const unsigned char *readp = (const unsigned char *) data->d_buf;
    9741           0 :   const unsigned char *readendp = readp + data->d_size;
    9742           0 :   int level = 1;
    9743             : 
    9744           0 :   while (readp < readendp)
    9745             :     {
    9746           0 :       unsigned int opcode = *readp++;
    9747           0 :       unsigned int u128;
    9748           0 :       unsigned int u128_2;
    9749           0 :       const unsigned char *endp;
    9750             : 
    9751           0 :       switch (opcode)
    9752             :         {
    9753           0 :         case DW_MACINFO_define:
    9754             :         case DW_MACINFO_undef:
    9755             :         case DW_MACINFO_vendor_ext:
    9756             :           /*  For the first two opcodes the parameters are
    9757             :                 line, string
    9758             :               For the latter
    9759             :                 number, string.
    9760             :               We can treat these cases together.  */
    9761           0 :           get_uleb128 (u128, readp, readendp);
    9762             : 
    9763           0 :           endp = memchr (readp, '\0', readendp - readp);
    9764           0 :           if (unlikely (endp == NULL))
    9765             :             {
    9766           0 :               printf (gettext ("\
    9767             : %*s*** non-terminated string at end of section"),
    9768             :                       level, "");
    9769           0 :               return;
    9770             :             }
    9771             : 
    9772           0 :           if (opcode == DW_MACINFO_define)
    9773           0 :             printf ("%*s#define %s, line %u\n",
    9774             :                     level, "", (char *) readp, u128);
    9775           0 :           else if (opcode == DW_MACINFO_undef)
    9776           0 :             printf ("%*s#undef %s, line %u\n",
    9777             :                     level, "", (char *) readp, u128);
    9778             :           else
    9779           0 :             printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
    9780             : 
    9781           0 :           readp = endp + 1;
    9782           0 :           break;
    9783             : 
    9784           0 :         case DW_MACINFO_start_file:
    9785             :           /* The two parameters are line and file index, in this order.  */
    9786           0 :           get_uleb128 (u128, readp, readendp);
    9787           0 :           if (readendp - readp < 1)
    9788             :             {
    9789           0 :               printf (gettext ("\
    9790             : %*s*** missing DW_MACINFO_start_file argument at end of section"),
    9791             :                       level, "");
    9792           0 :               return;
    9793             :             }
    9794           0 :           get_uleb128 (u128_2, readp, readendp);
    9795             : 
    9796             :           /* Find the CU DIE for this file.  */
    9797           0 :           size_t macoff = readp - (const unsigned char *) data->d_buf;
    9798           0 :           const char *fname = "???";
    9799           0 :           if (macoff >= cus[0].offset && cus[0].offset != data->d_size)
    9800             :             {
    9801           0 :               while (macoff >= cus[1].offset && cus[1].offset != data->d_size)
    9802           0 :                 ++cus;
    9803             : 
    9804           0 :               if (cus[0].files == NULL
    9805           0 :                   && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
    9806           0 :                 cus[0].files = (Dwarf_Files *) -1l;
    9807             : 
    9808           0 :               if (cus[0].files != (Dwarf_Files *) -1l)
    9809           0 :                 fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
    9810           0 :                          ?: "???");
    9811             :             }
    9812             : 
    9813           0 :           printf ("%*sstart_file %u, [%u] %s\n",
    9814             :                   level, "", u128, u128_2, fname);
    9815           0 :           ++level;
    9816           0 :           break;
    9817             : 
    9818           0 :         case DW_MACINFO_end_file:
    9819           0 :           --level;
    9820           0 :           printf ("%*send_file\n", level, "");
    9821             :           /* Nothing more to do.  */
    9822             :           break;
    9823             : 
    9824           0 :         default:
    9825             :           // XXX gcc seems to generate files with a trailing zero.
    9826           0 :           if (unlikely (opcode != 0 || readp != readendp))
    9827           0 :             printf ("%*s*** invalid opcode %u\n", level, "", opcode);
    9828             :           break;
    9829             :         }
    9830             :     }
    9831             : }
    9832             : 
    9833             : 
    9834             : static void
    9835           3 : print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
    9836             :                            Ebl *ebl,
    9837             :                            GElf_Ehdr *ehdr __attribute__ ((unused)),
    9838             :                            Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    9839             : {
    9840           3 :   printf (gettext ("\
    9841             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    9842             :           elf_ndxscn (scn), section_name (ebl, shdr),
    9843           3 :           (uint64_t) shdr->sh_offset);
    9844           3 :   putc_unlocked ('\n', stdout);
    9845             : 
    9846           3 :   Elf_Data *data =  elf_getdata (scn, NULL);
    9847           3 :   if (unlikely (data == NULL))
    9848             :     {
    9849           0 :       error (0, 0, gettext ("cannot get macro information section data: %s"),
    9850             :              elf_errmsg (-1));
    9851           0 :       return;
    9852             :     }
    9853             : 
    9854             :   /* Get the source file information for all CUs.  Uses same
    9855             :      datastructure as macinfo.  But uses offset field to directly
    9856             :      match .debug_line offset.  And just stored in a list.  */
    9857           3 :   Dwarf_Off offset;
    9858           3 :   Dwarf_Off ncu = 0;
    9859           3 :   size_t hsize;
    9860           3 :   struct mac_culist *culist = NULL;
    9861           3 :   size_t nculist = 0;
    9862           7 :   while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
    9863             :     {
    9864           4 :       Dwarf_Die cudie;
    9865           4 :       if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
    9866           0 :         continue;
    9867             : 
    9868           4 :       Dwarf_Attribute attr;
    9869           4 :       if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL)
    9870             :         continue;
    9871             : 
    9872           4 :       Dwarf_Word lineoff;
    9873           4 :       if (dwarf_formudata (&attr, &lineoff) != 0)
    9874             :         continue;
    9875             : 
    9876           4 :       struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
    9877           4 :       newp->die = cudie;
    9878           4 :       newp->offset = lineoff;
    9879           4 :       newp->files = NULL;
    9880           4 :       newp->next = culist;
    9881           4 :       culist = newp;
    9882           4 :       ++nculist;
    9883             :     }
    9884             : 
    9885           3 :   const unsigned char *readp = (const unsigned char *) data->d_buf;
    9886           3 :   const unsigned char *readendp = readp + data->d_size;
    9887             : 
    9888          11 :   while (readp < readendp)
    9889             :     {
    9890          24 :       printf (gettext (" Offset:             0x%" PRIx64 "\n"),
    9891           8 :               (uint64_t) (readp - (const unsigned char *) data->d_buf));
    9892             : 
    9893             :       // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
    9894             :       // optional vendor extension macro entry table.
    9895           8 :       if (readp + 2 > readendp)
    9896             :         {
    9897           0 :         invalid_data:
    9898           0 :           error (0, 0, gettext ("invalid data"));
    9899           0 :           return;
    9900             :         }
    9901           8 :       const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
    9902           8 :       printf (gettext (" Version:            %" PRIu16 "\n"), vers);
    9903             : 
    9904             :       // Version 4 is the GNU extension for DWARF4.  DWARF5 will use version
    9905             :       // 5 when it gets standardized.
    9906           8 :       if (vers != 4 && vers != 5)
    9907             :         {
    9908           0 :           printf (gettext ("  unknown version, cannot parse section\n"));
    9909           0 :           return;
    9910             :         }
    9911             : 
    9912           8 :       if (readp + 1 > readendp)
    9913             :         goto invalid_data;
    9914           8 :       const unsigned char flag = *readp++;
    9915           8 :       printf (gettext (" Flag:               0x%" PRIx8), flag);
    9916           8 :       if (flag != 0)
    9917             :         {
    9918           4 :           printf (" (");
    9919           4 :           if ((flag & 0x01) != 0)
    9920             :             {
    9921           0 :               printf ("offset_size");
    9922           0 :               if ((flag & 0xFE) !=  0)
    9923           0 :                 printf (", ");
    9924             :             }
    9925           4 :           if ((flag & 0x02) != 0)
    9926             :             {
    9927           4 :               printf ("debug_line_offset");
    9928           4 :               if ((flag & 0xFC) !=  0)
    9929           0 :                 printf (", ");
    9930             :             }
    9931           4 :           if ((flag & 0x04) != 0)
    9932             :             {
    9933           0 :               printf ("operands_table");
    9934           0 :               if ((flag & 0xF8) !=  0)
    9935           0 :                 printf (", ");
    9936             :             }
    9937           4 :           if ((flag & 0xF8) != 0)
    9938           0 :             printf ("unknown");
    9939           4 :           printf (")");
    9940             :         }
    9941           8 :       printf ("\n");
    9942             : 
    9943           8 :       unsigned int offset_len = (flag & 0x01) ? 8 : 4;
    9944           8 :       printf (gettext (" Offset length:      %" PRIu8 "\n"), offset_len);
    9945           8 :       Dwarf_Off line_offset = -1;
    9946           8 :       if (flag & 0x02)
    9947             :         {
    9948           4 :           if (offset_len == 8)
    9949           0 :             line_offset = read_8ubyte_unaligned_inc (dbg, readp);
    9950             :           else
    9951           4 :             line_offset = read_4ubyte_unaligned_inc (dbg, readp);
    9952           4 :           printf (gettext (" .debug_line offset: 0x%" PRIx64 "\n"),
    9953             :                   line_offset);
    9954             :         }
    9955             : 
    9956           4 :       struct mac_culist *cu = NULL;
    9957           4 :       if (line_offset != (Dwarf_Off) -1)
    9958             :         {
    9959             :           cu = culist;
    9960           5 :           while (cu != NULL && line_offset != cu->offset)
    9961           1 :             cu = cu->next;
    9962             :         }
    9963             : 
    9964           8 :       Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, (cu != NULL
    9965             :                                                                ? cu->die.cu
    9966             :                                                                : NULL));
    9967             : 
    9968           8 :       const unsigned char *vendor[DW_MACRO_hi_user - DW_MACRO_lo_user + 1];
    9969           8 :       memset (vendor, 0, sizeof vendor);
    9970           8 :       if (flag & 0x04)
    9971             :         {
    9972             :           // 1 byte length, for each item, 1 byte opcode, uleb128 number
    9973             :           // of arguments, for each argument 1 byte form code.
    9974           0 :           if (readp + 1 > readendp)
    9975             :             goto invalid_data;
    9976           0 :           unsigned int tlen = *readp++;
    9977           0 :           printf (gettext ("  extension opcode table, %" PRIu8 " items:\n"),
    9978             :                   tlen);
    9979           0 :           for (unsigned int i = 0; i < tlen; i++)
    9980             :             {
    9981           0 :               if (readp + 1 > readendp)
    9982             :                 goto invalid_data;
    9983           0 :               unsigned int opcode = *readp++;
    9984           0 :               printf (gettext ("    [%" PRIx8 "]"), opcode);
    9985           0 :               if (opcode < DW_MACRO_lo_user
    9986           0 :                   || opcode > DW_MACRO_hi_user)
    9987             :                 goto invalid_data;
    9988             :               // Record the start of description for this vendor opcode.
    9989             :               // uleb128 nr args, 1 byte per arg form.
    9990           0 :               vendor[opcode - DW_MACRO_lo_user] = readp;
    9991           0 :               if (readp + 1 > readendp)
    9992             :                 goto invalid_data;
    9993           0 :               unsigned int args = *readp++;
    9994           0 :               if (args > 0)
    9995             :                 {
    9996           0 :                   printf (gettext (" %" PRIu8 " arguments:"), args);
    9997           0 :                   while (args > 0)
    9998             :                     {
    9999           0 :                       if (readp + 1 > readendp)
   10000             :                         goto invalid_data;
   10001           0 :                       unsigned int form = *readp++;
   10002           0 :                       printf (" %s", dwarf_form_name (form));
   10003           0 :                       if (! libdw_valid_user_form (form))
   10004             :                         goto invalid_data;
   10005           0 :                       args--;
   10006           0 :                       if (args > 0)
   10007           0 :                         putchar_unlocked (',');
   10008             :                     }
   10009             :                 }
   10010             :               else
   10011           0 :                 printf (gettext (" no arguments."));
   10012           0 :               putchar_unlocked ('\n');
   10013             :             }
   10014             :         }
   10015           8 :       putchar_unlocked ('\n');
   10016             : 
   10017           8 :       int level = 1;
   10018           8 :       if (readp + 1 > readendp)
   10019             :         goto invalid_data;
   10020           8 :       unsigned int opcode = *readp++;
   10021         735 :       while (opcode != 0)
   10022             :         {
   10023         727 :           unsigned int u128;
   10024         727 :           unsigned int u128_2;
   10025         727 :           const unsigned char *endp;
   10026         727 :           uint64_t off;
   10027             : 
   10028         727 :           switch (opcode)
   10029             :             {
   10030           6 :             case DW_MACRO_start_file:
   10031           6 :               get_uleb128 (u128, readp, readendp);
   10032           6 :               if (readp >= readendp)
   10033             :                 goto invalid_data;
   10034           6 :               get_uleb128 (u128_2, readp, readendp);
   10035             : 
   10036             :               /* Find the CU DIE that matches this line offset.  */
   10037           6 :               const char *fname = "???";
   10038           6 :               if (cu != NULL)
   10039             :                 {
   10040           6 :                   if (cu->files == NULL
   10041           4 :                       && dwarf_getsrcfiles (&cu->die, &cu->files,
   10042             :                                             NULL) != 0)
   10043           0 :                     cu->files = (Dwarf_Files *) -1l;
   10044             : 
   10045           6 :                   if (cu->files != (Dwarf_Files *) -1l)
   10046           6 :                     fname = (dwarf_filesrc (cu->files, u128_2,
   10047           6 :                                             NULL, NULL) ?: "???");
   10048             :                 }
   10049           6 :               printf ("%*sstart_file %u, [%u] %s\n",
   10050             :                       level, "", u128, u128_2, fname);
   10051           6 :               ++level;
   10052           6 :               break;
   10053             : 
   10054           6 :             case DW_MACRO_end_file:
   10055           6 :               --level;
   10056           6 :               printf ("%*send_file\n", level, "");
   10057             :               break;
   10058             : 
   10059           1 :             case DW_MACRO_define:
   10060           1 :               get_uleb128 (u128, readp, readendp);
   10061           1 :               endp = memchr (readp, '\0', readendp - readp);
   10062           1 :               if (endp == NULL)
   10063             :                 goto invalid_data;
   10064           1 :               printf ("%*s#define %s, line %u\n",
   10065             :                       level, "", readp, u128);
   10066           1 :               readp = endp + 1;
   10067           1 :               break;
   10068             : 
   10069           0 :             case DW_MACRO_undef:
   10070           0 :               get_uleb128 (u128, readp, readendp);
   10071           0 :               endp = memchr (readp, '\0', readendp - readp);
   10072           0 :               if (endp == NULL)
   10073             :                 goto invalid_data;
   10074           0 :               printf ("%*s#undef %s, line %u\n",
   10075             :                       level, "", readp, u128);
   10076           0 :               readp = endp + 1;
   10077           0 :               break;
   10078             : 
   10079         707 :             case DW_MACRO_define_strp:
   10080         707 :               get_uleb128 (u128, readp, readendp);
   10081         707 :               if (readp + offset_len > readendp)
   10082             :                 goto invalid_data;
   10083         707 :               if (offset_len == 8)
   10084           0 :                 off = read_8ubyte_unaligned_inc (dbg, readp);
   10085             :               else
   10086         707 :                 off = read_4ubyte_unaligned_inc (dbg, readp);
   10087         707 :               printf ("%*s#define %s, line %u (indirect)\n",
   10088             :                       level, "", dwarf_getstring (dbg, off, NULL), u128);
   10089             :               break;
   10090             : 
   10091           1 :             case DW_MACRO_undef_strp:
   10092           1 :               get_uleb128 (u128, readp, readendp);
   10093           1 :               if (readp + offset_len > readendp)
   10094             :                 goto invalid_data;
   10095           1 :               if (offset_len == 8)
   10096           0 :                 off = read_8ubyte_unaligned_inc (dbg, readp);
   10097             :               else
   10098           1 :                 off = read_4ubyte_unaligned_inc (dbg, readp);
   10099           1 :               printf ("%*s#undef %s, line %u (indirect)\n",
   10100             :                       level, "", dwarf_getstring (dbg, off, NULL), u128);
   10101             :               break;
   10102             : 
   10103           6 :             case DW_MACRO_import:
   10104           6 :               if (readp + offset_len > readendp)
   10105             :                 goto invalid_data;
   10106           6 :               if (offset_len == 8)
   10107           0 :                 off = read_8ubyte_unaligned_inc (dbg, readp);
   10108             :               else
   10109           6 :                 off = read_4ubyte_unaligned_inc (dbg, readp);
   10110           6 :               printf ("%*s#include offset 0x%" PRIx64 "\n",
   10111             :                       level, "", off);
   10112             :               break;
   10113             : 
   10114           0 :             case DW_MACRO_define_sup:
   10115           0 :               get_uleb128 (u128, readp, readendp);
   10116           0 :               if (readp + offset_len > readendp)
   10117             :                 goto invalid_data;
   10118           0 :               printf ("%*s#define ", level, "");
   10119           0 :               readp =  print_form_data (dbg, DW_FORM_strp_sup,
   10120             :                                         readp, readendp, offset_len,
   10121             :                                         str_offsets_base);
   10122           0 :               printf (", line %u (sup)\n", u128);
   10123             :               break;
   10124             : 
   10125           0 :             case DW_MACRO_undef_sup:
   10126           0 :               get_uleb128 (u128, readp, readendp);
   10127           0 :               if (readp + offset_len > readendp)
   10128             :                 goto invalid_data;
   10129           0 :               printf ("%*s#undef ", level, "");
   10130           0 :               readp =  print_form_data (dbg, DW_FORM_strp_sup,
   10131             :                                         readp, readendp, offset_len,
   10132             :                                         str_offsets_base);
   10133           0 :               printf (", line %u (sup)\n", u128);
   10134             :               break;
   10135             : 
   10136           0 :             case DW_MACRO_import_sup:
   10137           0 :               if (readp + offset_len > readendp)
   10138             :                 goto invalid_data;
   10139           0 :               if (offset_len == 8)
   10140           0 :                 off = read_8ubyte_unaligned_inc (dbg, readp);
   10141             :               else
   10142           0 :                 off = read_4ubyte_unaligned_inc (dbg, readp);
   10143             :               // XXX Needs support for reading from supplementary object file.
   10144           0 :               printf ("%*s#include offset 0x%" PRIx64 " (sup)\n",
   10145             :                       level, "", off);
   10146             :               break;
   10147             : 
   10148           0 :             case DW_MACRO_define_strx:
   10149           0 :               get_uleb128 (u128, readp, readendp);
   10150           0 :               if (readp + offset_len > readendp)
   10151             :                 goto invalid_data;
   10152           0 :               printf ("%*s#define ", level, "");
   10153           0 :               readp =  print_form_data (dbg, DW_FORM_strx,
   10154             :                                         readp, readendp, offset_len,
   10155             :                                         str_offsets_base);
   10156           0 :               printf (", line %u (strx)\n", u128);
   10157             :               break;
   10158             : 
   10159           0 :             case DW_MACRO_undef_strx:
   10160           0 :               get_uleb128 (u128, readp, readendp);
   10161           0 :               if (readp + offset_len > readendp)
   10162             :                 goto invalid_data;
   10163           0 :               printf ("%*s#undef ", level, "");
   10164           0 :               readp =  print_form_data (dbg, DW_FORM_strx,
   10165             :                                         readp, readendp, offset_len,
   10166             :                                         str_offsets_base);
   10167           0 :               printf (", line %u (strx)\n", u128);
   10168             :               break;
   10169             : 
   10170             :             default:
   10171           0 :               printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
   10172           0 :               if (opcode < DW_MACRO_lo_user
   10173             :                   || opcode > DW_MACRO_lo_user
   10174           0 :                   || vendor[opcode - DW_MACRO_lo_user] == NULL)
   10175             :                 goto invalid_data;
   10176             : 
   10177           0 :               const unsigned char *op_desc;
   10178           0 :               op_desc = vendor[opcode - DW_MACRO_lo_user];
   10179             : 
   10180             :               // Just skip the arguments, we cannot really interpret them,
   10181             :               // but print as much as we can.
   10182           0 :               unsigned int args = *op_desc++;
   10183           0 :               while (args > 0 && readp < readendp)
   10184           0 :                 {
   10185           0 :                   unsigned int form = *op_desc++;
   10186           0 :                   readp = print_form_data (dbg, form, readp, readendp,
   10187             :                                            offset_len, str_offsets_base);
   10188           0 :                   args--;
   10189           0 :                   if (args > 0)
   10190           0 :                     printf (", ");
   10191             :                 }
   10192           0 :               putchar_unlocked ('\n');
   10193             :             }
   10194             : 
   10195         727 :           if (readp + 1 > readendp)
   10196             :             goto invalid_data;
   10197         727 :           opcode = *readp++;
   10198         727 :           if (opcode == 0)
   10199           8 :             putchar_unlocked ('\n');
   10200             :         }
   10201             :     }
   10202             : }
   10203             : 
   10204             : 
   10205             : /* Callback for printing global names.  */
   10206             : static int
   10207          34 : print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
   10208             :                 void *arg)
   10209             : {
   10210          34 :   int *np = (int *) arg;
   10211             : 
   10212         102 :   printf (gettext (" [%5d] DIE offset: %6" PRId64
   10213             :                    ", CU DIE offset: %6" PRId64 ", name: %s\n"),
   10214          34 :           (*np)++, global->die_offset, global->cu_offset, global->name);
   10215             : 
   10216          34 :   return 0;
   10217             : }
   10218             : 
   10219             : 
   10220             : /* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
   10221             : static void
   10222           8 : print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10223             :                               Ebl *ebl,
   10224             :                               GElf_Ehdr *ehdr __attribute__ ((unused)),
   10225             :                               Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   10226             : {
   10227           8 :   printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
   10228             :           elf_ndxscn (scn), section_name (ebl, shdr),
   10229           8 :           (uint64_t) shdr->sh_offset);
   10230             : 
   10231           8 :   int n = 0;
   10232           8 :   (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
   10233           8 : }
   10234             : 
   10235             : /* Print the content of the DWARF string section '.debug_str'.  */
   10236             : static void
   10237          47 : print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10238             :                          Ebl *ebl,
   10239             :                          GElf_Ehdr *ehdr __attribute__ ((unused)),
   10240             :                          Elf_Scn *scn, GElf_Shdr *shdr,
   10241             :                          Dwarf *dbg __attribute__ ((unused)))
   10242             : {
   10243          47 :   Elf_Data *data = elf_rawdata (scn, NULL);
   10244          47 :   const size_t sh_size = data ? data->d_size : 0;
   10245             : 
   10246             :   /* Compute floor(log16(shdr->sh_size)).  */
   10247          47 :   GElf_Addr tmp = sh_size;
   10248          47 :   int digits = 1;
   10249         163 :   while (tmp >= 16)
   10250             :     {
   10251         116 :       ++digits;
   10252         116 :       tmp >>= 4;
   10253             :     }
   10254          47 :   digits = MAX (4, digits);
   10255             : 
   10256          47 :   printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
   10257             :                    " %*s  String\n"),
   10258             :           elf_ndxscn (scn),
   10259          47 :           section_name (ebl, shdr), (uint64_t) shdr->sh_offset,
   10260             :           /* TRANS: the debugstr| prefix makes the string unique.  */
   10261          47 :           digits + 2, sgettext ("debugstr|Offset"));
   10262             : 
   10263          47 :   Dwarf_Off offset = 0;
   10264       64239 :   while (offset < sh_size)
   10265             :     {
   10266       64192 :       size_t len;
   10267       64192 :       const char *str = (const char *) data->d_buf + offset;
   10268       64192 :       const char *endp = memchr (str, '\0', sh_size - offset);
   10269       64192 :       if (unlikely (endp == NULL))
   10270             :         {
   10271           0 :           printf (gettext (" *** error, missing string terminator\n"));
   10272             :           break;
   10273             :         }
   10274             : 
   10275       64192 :       printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
   10276       64192 :       len = endp - str;
   10277       64192 :       offset += len + 1;
   10278             :     }
   10279          47 : }
   10280             : 
   10281             : static void
   10282           4 : print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10283             :                                  Ebl *ebl,
   10284             :                                  GElf_Ehdr *ehdr __attribute__ ((unused)),
   10285             :                                  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   10286             : {
   10287           4 :   printf (gettext ("\
   10288             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
   10289             :           elf_ndxscn (scn), section_name (ebl, shdr),
   10290           4 :           (uint64_t) shdr->sh_offset);
   10291             : 
   10292           4 :   if (shdr->sh_size == 0)
   10293             :     return;
   10294             : 
   10295             :   /* We like to get the section from libdw to make sure they are relocated.  */
   10296           8 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_str_offsets]
   10297           4 :                     ?: elf_rawdata (scn, NULL));
   10298           4 :   if (unlikely (data == NULL))
   10299             :     {
   10300           0 :       error (0, 0, gettext ("cannot get .debug_str_offsets section data: %s"),
   10301             :              elf_errmsg (-1));
   10302           0 :       return;
   10303             :     }
   10304             : 
   10305           4 :   size_t idx = 0;
   10306           4 :   sort_listptr (&known_stroffbases, "str_offsets");
   10307             : 
   10308           4 :   const unsigned char *start = (const unsigned char *) data->d_buf;
   10309           4 :   const unsigned char *readp = start;
   10310           8 :   const unsigned char *readendp = ((const unsigned char *) data->d_buf
   10311           4 :                                    + data->d_size);
   10312             : 
   10313           8 :   while (readp < readendp)
   10314             :     {
   10315             :       /* Most string offset tables will have a header.  For split
   10316             :          dwarf unit GNU DebugFission didn't add one.  But they were
   10317             :          also only defined for split units (main or skeleton units
   10318             :          didn't have indirect strings).  So if we don't have a
   10319             :          DW_AT_str_offsets_base at all and this is offset zero, then
   10320             :          just start printing offsets immediately, if this is a .dwo
   10321             :          section.  */
   10322           8 :       Dwarf_Off off = (Dwarf_Off) (readp
   10323           4 :                                    - (const unsigned char *) data->d_buf);
   10324             : 
   10325           4 :       printf ("Table at offset %" PRIx64 " ", off);
   10326             : 
   10327           4 :       struct listptr *listptr = get_listptr (&known_stroffbases, idx++);
   10328           0 :       const unsigned char *next_unitp = readendp;
   10329           0 :       uint8_t offset_size;
   10330           0 :       bool has_header;
   10331           0 :       if (listptr == NULL)
   10332             :         {
   10333             :           /* This can happen for .dwo files.  There is only an header
   10334             :              in the case this is a version 5 split DWARF file.  */
   10335           4 :           Dwarf_CU *cu;
   10336           4 :           uint8_t unit_type;
   10337           4 :           if (dwarf_get_units (dbg, NULL, &cu, NULL, &unit_type,
   10338             :                                NULL, NULL) != 0)
   10339             :             {
   10340           0 :               error (0, 0, "Warning: Cannot find any DWARF unit.");
   10341             :               /* Just guess some values.  */
   10342           0 :               has_header = false;
   10343           0 :               offset_size = 4;
   10344             :             }
   10345           4 :           else if (off == 0
   10346           4 :                    && (unit_type == DW_UT_split_type
   10347           4 :                        || unit_type == DW_UT_split_compile))
   10348             :             {
   10349           4 :               has_header = cu->version > 4;
   10350           4 :               offset_size = cu->offset_size;
   10351             :             }
   10352             :           else
   10353             :             {
   10354           0 :               error (0, 0,
   10355             :                      "Warning: No CU references .debug_str_offsets after %"
   10356             :                      PRIx64, off);
   10357           0 :               has_header = cu->version > 4;
   10358           0 :               offset_size = cu->offset_size;
   10359             :             }
   10360           4 :           printf ("\n");
   10361             :         }
   10362             :       else
   10363             :         {
   10364             :           /* This must be DWARF5, since GNU DebugFission didn't define
   10365             :              DW_AT_str_offsets_base.  */
   10366           0 :           has_header = true;
   10367             : 
   10368           0 :           Dwarf_Die cudie;
   10369           0 :           if (dwarf_cu_die (listptr->cu, &cudie,
   10370             :                             NULL, NULL, NULL, NULL,
   10371             :                             NULL, NULL) == NULL)
   10372           0 :             printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
   10373             :           else
   10374           0 :             printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
   10375             :         }
   10376             : 
   10377           4 :       if (has_header)
   10378             :         {
   10379           2 :           uint64_t unit_length;
   10380           2 :           uint16_t version;
   10381           2 :           uint16_t padding;
   10382             : 
   10383           2 :           unit_length = read_4ubyte_unaligned_inc (dbg, readp);
   10384           2 :           if (unlikely (unit_length == 0xffffffff))
   10385             :             {
   10386           0 :               if (unlikely (readp > readendp - 8))
   10387             :                 {
   10388           0 :                 invalid_data:
   10389           0 :                   error (0, 0, "Invalid data");
   10390           0 :                   return;
   10391             :                 }
   10392           0 :               unit_length = read_8ubyte_unaligned_inc (dbg, readp);
   10393           0 :               offset_size = 8;
   10394             :             }
   10395             :           else
   10396             :             offset_size = 4;
   10397             : 
   10398           2 :           printf ("\n");
   10399           2 :           printf (gettext (" Length:        %8" PRIu64 "\n"),
   10400             :                   unit_length);
   10401           2 :           printf (gettext (" Offset size:   %8" PRIu8 "\n"),
   10402             :                   offset_size);
   10403             : 
   10404             :           /* We need at least 2-bytes (version) + 2-bytes (padding) =
   10405             :              4 bytes to complete the header.  And this unit cannot go
   10406             :              beyond the section data.  */
   10407           2 :           if (readp > readendp - 4
   10408           2 :               || unit_length < 4
   10409           2 :               || unit_length > (uint64_t) (readendp - readp))
   10410             :             goto invalid_data;
   10411             : 
   10412           2 :           next_unitp = readp + unit_length;
   10413             : 
   10414           2 :           version = read_2ubyte_unaligned_inc (dbg, readp);
   10415           2 :           printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
   10416             : 
   10417           2 :           if (version != 5)
   10418             :             {
   10419           0 :               error (0, 0, gettext ("Unknown version"));
   10420           0 :               goto next_unit;
   10421             :             }
   10422             : 
   10423           2 :           padding = read_2ubyte_unaligned_inc (dbg, readp);
   10424           2 :           printf (gettext (" Padding:       %8" PRIx16 "\n"), padding);
   10425             : 
   10426           2 :           if (listptr != NULL
   10427           0 :               && listptr->offset != (Dwarf_Off) (readp - start))
   10428             :             {
   10429           0 :               error (0, 0, "String offsets index doesn't start after header");
   10430           0 :               goto next_unit;
   10431             :             }
   10432             : 
   10433           2 :           printf ("\n");
   10434             :         }
   10435             : 
   10436           4 :       int digits = 1;
   10437           4 :       size_t offsets = (next_unitp - readp) / offset_size;
   10438           8 :       while (offsets >= 10)
   10439             :         {
   10440           4 :           ++digits;
   10441           4 :           offsets /= 10;
   10442             :         }
   10443             : 
   10444           4 :       unsigned int uidx = 0;
   10445           4 :       size_t index_offset =  readp - (const unsigned char *) data->d_buf;
   10446           4 :       printf (" Offsets start at 0x%zx:\n", index_offset);
   10447          64 :       while (readp <= next_unitp - offset_size)
   10448             :         {
   10449          60 :           Dwarf_Word offset;
   10450          60 :           if (offset_size == 4)
   10451          60 :             offset = read_4ubyte_unaligned_inc (dbg, readp);
   10452             :           else
   10453           0 :             offset = read_8ubyte_unaligned_inc (dbg, readp);
   10454          60 :           const char *str = dwarf_getstring (dbg, offset, NULL);
   10455          60 :           printf (" [%*u] [%*" PRIx64 "]  \"%s\"\n",
   10456          60 :                   digits, uidx++, (int) offset_size * 2, offset, str ?: "???");
   10457             :         }
   10458           4 :       printf ("\n");
   10459             : 
   10460           4 :       if (readp != next_unitp)
   10461           0 :         error (0, 0, "extra %zd bytes at end of unit",
   10462           0 :                (size_t) (next_unitp - readp));
   10463             : 
   10464           4 :     next_unit:
   10465             :       readp = next_unitp;
   10466             :     }
   10467             : }
   10468             : 
   10469             : 
   10470             : /* Print the content of the call frame search table section
   10471             :    '.eh_frame_hdr'.  */
   10472             : static void
   10473          14 : print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10474             :                                Ebl *ebl __attribute__ ((unused)),
   10475             :                                GElf_Ehdr *ehdr __attribute__ ((unused)),
   10476             :                                Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   10477             : {
   10478          14 :   printf (gettext ("\
   10479             : \nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
   10480             :           elf_ndxscn (scn));
   10481             : 
   10482          14 :   Elf_Data *data = elf_rawdata (scn, NULL);
   10483             : 
   10484          14 :   if (unlikely (data == NULL))
   10485             :     {
   10486           0 :       error (0, 0, gettext ("cannot get %s content: %s"),
   10487             :              ".eh_frame_hdr", elf_errmsg (-1));
   10488           0 :       return;
   10489             :     }
   10490             : 
   10491          14 :   const unsigned char *readp = data->d_buf;
   10492          28 :   const unsigned char *const dataend = ((unsigned char *) data->d_buf
   10493          14 :                                         + data->d_size);
   10494             : 
   10495          14 :   if (unlikely (readp + 4 > dataend))
   10496             :     {
   10497           0 :     invalid_data:
   10498           0 :       error (0, 0, gettext ("invalid data"));
   10499           0 :       return;
   10500             :     }
   10501             : 
   10502          14 :   unsigned int version = *readp++;
   10503          14 :   unsigned int eh_frame_ptr_enc = *readp++;
   10504          14 :   unsigned int fde_count_enc = *readp++;
   10505          14 :   unsigned int table_enc = *readp++;
   10506             : 
   10507          14 :   printf (" version:          %u\n"
   10508             :           " eh_frame_ptr_enc: %#x ",
   10509             :           version, eh_frame_ptr_enc);
   10510          14 :   print_encoding_base ("", eh_frame_ptr_enc);
   10511          14 :   printf (" fde_count_enc:    %#x ", fde_count_enc);
   10512          14 :   print_encoding_base ("", fde_count_enc);
   10513          14 :   printf (" table_enc:        %#x ", table_enc);
   10514          14 :   print_encoding_base ("", table_enc);
   10515             : 
   10516          14 :   uint64_t eh_frame_ptr = 0;
   10517          14 :   if (eh_frame_ptr_enc != DW_EH_PE_omit)
   10518             :     {
   10519          14 :       readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
   10520             :                             dbg);
   10521          14 :       if (unlikely (readp == NULL))
   10522             :         goto invalid_data;
   10523             : 
   10524          14 :       printf (" eh_frame_ptr:     %#" PRIx64, eh_frame_ptr);
   10525          14 :       if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
   10526          28 :         printf (" (offset: %#" PRIx64 ")",
   10527             :                 /* +4 because of the 4 byte header of the section.  */
   10528          14 :                 (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
   10529             : 
   10530          14 :       putchar_unlocked ('\n');
   10531             :     }
   10532             : 
   10533          14 :   uint64_t fde_count = 0;
   10534          14 :   if (fde_count_enc != DW_EH_PE_omit)
   10535             :     {
   10536          14 :       readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
   10537          14 :       if (unlikely (readp == NULL))
   10538             :         goto invalid_data;
   10539             : 
   10540          14 :       printf (" fde_count:        %" PRIu64 "\n", fde_count);
   10541             :     }
   10542             : 
   10543          14 :   if (fde_count == 0 || table_enc == DW_EH_PE_omit)
   10544             :     return;
   10545             : 
   10546          14 :   puts (" Table:");
   10547             : 
   10548             :   /* Optimize for the most common case.  */
   10549          14 :   if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
   10550        4446 :     while (fde_count > 0 && readp + 8 <= dataend)
   10551             :       {
   10552        4432 :         int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
   10553        8864 :         uint64_t initial_offset = ((uint64_t) shdr->sh_offset
   10554        4432 :                                    + (int64_t) initial_location);
   10555        4432 :         int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
   10556             :         // XXX Possibly print symbol name or section offset for initial_offset
   10557        8864 :         printf ("  %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
   10558             :                 " fde=[%6" PRIx64 "]\n",
   10559             :                 initial_location, initial_offset,
   10560        4432 :                 address, address - (eh_frame_ptr + 4));
   10561             :       }
   10562             :   else
   10563             :     while (0 && readp < dataend)
   10564             :       {
   10565             : 
   10566          14 :       }
   10567             : }
   10568             : 
   10569             : 
   10570             : /* Print the content of the exception handling table section
   10571             :    '.eh_frame_hdr'.  */
   10572             : static void
   10573           0 : print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10574             :                              Ebl *ebl __attribute__ ((unused)),
   10575             :                              GElf_Ehdr *ehdr __attribute__ ((unused)),
   10576             :                              Elf_Scn *scn,
   10577             :                              GElf_Shdr *shdr __attribute__ ((unused)),
   10578             :                              Dwarf *dbg __attribute__ ((unused)))
   10579             : {
   10580           0 :   printf (gettext ("\
   10581             : \nException handling table section [%2zu] '.gcc_except_table':\n"),
   10582             :           elf_ndxscn (scn));
   10583             : 
   10584           0 :   Elf_Data *data = elf_rawdata (scn, NULL);
   10585             : 
   10586           0 :   if (unlikely (data == NULL))
   10587             :     {
   10588           0 :       error (0, 0, gettext ("cannot get %s content: %s"),
   10589             :              ".gcc_except_table", elf_errmsg (-1));
   10590           0 :       return;
   10591             :     }
   10592             : 
   10593           0 :   const unsigned char *readp = data->d_buf;
   10594           0 :   const unsigned char *const dataend = readp + data->d_size;
   10595             : 
   10596           0 :   if (unlikely (readp + 1 > dataend))
   10597             :     {
   10598           0 :     invalid_data:
   10599           0 :       error (0, 0, gettext ("invalid data"));
   10600           0 :       return;
   10601             :     }
   10602           0 :   unsigned int lpstart_encoding = *readp++;
   10603           0 :   printf (gettext (" LPStart encoding:    %#x "), lpstart_encoding);
   10604           0 :   print_encoding_base ("", lpstart_encoding);
   10605           0 :   if (lpstart_encoding != DW_EH_PE_omit)
   10606             :     {
   10607           0 :       uint64_t lpstart;
   10608           0 :       readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
   10609           0 :       printf (" LPStart:             %#" PRIx64 "\n", lpstart);
   10610             :     }
   10611             : 
   10612           0 :   if (unlikely (readp + 1 > dataend))
   10613             :     goto invalid_data;
   10614           0 :   unsigned int ttype_encoding = *readp++;
   10615           0 :   printf (gettext (" TType encoding:      %#x "), ttype_encoding);
   10616           0 :   print_encoding_base ("", ttype_encoding);
   10617           0 :   const unsigned char *ttype_base = NULL;
   10618           0 :   if (ttype_encoding != DW_EH_PE_omit)
   10619             :     {
   10620           0 :       unsigned int ttype_base_offset;
   10621           0 :       get_uleb128 (ttype_base_offset, readp, dataend);
   10622           0 :       printf (" TType base offset:   %#x\n", ttype_base_offset);
   10623           0 :       if ((size_t) (dataend - readp) > ttype_base_offset)
   10624           0 :         ttype_base = readp + ttype_base_offset;
   10625             :     }
   10626             : 
   10627           0 :   if (unlikely (readp + 1 > dataend))
   10628             :     goto invalid_data;
   10629           0 :   unsigned int call_site_encoding = *readp++;
   10630           0 :   printf (gettext (" Call site encoding:  %#x "), call_site_encoding);
   10631           0 :   print_encoding_base ("", call_site_encoding);
   10632           0 :   unsigned int call_site_table_len;
   10633           0 :   get_uleb128 (call_site_table_len, readp, dataend);
   10634             : 
   10635           0 :   const unsigned char *const action_table = readp + call_site_table_len;
   10636           0 :   if (unlikely (action_table > dataend))
   10637             :     goto invalid_data;
   10638             :   unsigned int u = 0;
   10639             :   unsigned int max_action = 0;
   10640           0 :   while (readp < action_table)
   10641             :     {
   10642           0 :       if (u == 0)
   10643           0 :         puts (gettext ("\n Call site table:"));
   10644             : 
   10645           0 :       uint64_t call_site_start;
   10646           0 :       readp = read_encoded (call_site_encoding, readp, dataend,
   10647             :                             &call_site_start, dbg);
   10648           0 :       uint64_t call_site_length;
   10649           0 :       readp = read_encoded (call_site_encoding, readp, dataend,
   10650             :                             &call_site_length, dbg);
   10651           0 :       uint64_t landing_pad;
   10652           0 :       readp = read_encoded (call_site_encoding, readp, dataend,
   10653             :                             &landing_pad, dbg);
   10654           0 :       unsigned int action;
   10655           0 :       get_uleb128 (action, readp, dataend);
   10656           0 :       max_action = MAX (action, max_action);
   10657           0 :       printf (gettext (" [%4u] Call site start:   %#" PRIx64 "\n"
   10658             :                        "        Call site length:  %" PRIu64 "\n"
   10659             :                        "        Landing pad:       %#" PRIx64 "\n"
   10660             :                        "        Action:            %u\n"),
   10661             :               u++, call_site_start, call_site_length, landing_pad, action);
   10662             :     }
   10663           0 :   if (readp != action_table)
   10664             :     goto invalid_data;
   10665             : 
   10666           0 :   unsigned int max_ar_filter = 0;
   10667           0 :   if (max_action > 0)
   10668             :     {
   10669           0 :       puts ("\n Action table:");
   10670             : 
   10671           0 :       size_t maxdata = (size_t) (dataend - action_table);
   10672           0 :       if (max_action > maxdata || maxdata - max_action < 1)
   10673             :         {
   10674           0 :         invalid_action_table:
   10675           0 :           fputs (gettext ("   <INVALID DATA>\n"), stdout);
   10676           0 :           return;
   10677             :         }
   10678             : 
   10679           0 :       const unsigned char *const action_table_end
   10680           0 :         = action_table + max_action + 1;
   10681             : 
   10682           0 :       u = 0;
   10683           0 :       do
   10684             :         {
   10685           0 :           int ar_filter;
   10686           0 :           get_sleb128 (ar_filter, readp, action_table_end);
   10687           0 :           if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
   10688           0 :             max_ar_filter = ar_filter;
   10689           0 :           int ar_disp;
   10690           0 :           if (readp >= action_table_end)
   10691             :             goto invalid_action_table;
   10692           0 :           get_sleb128 (ar_disp, readp, action_table_end);
   10693             : 
   10694           0 :           printf (" [%4u] ar_filter:  % d\n"
   10695             :                   "        ar_disp:    % -5d",
   10696             :                   u, ar_filter, ar_disp);
   10697           0 :           if (abs (ar_disp) & 1)
   10698           0 :             printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
   10699           0 :           else if (ar_disp != 0)
   10700           0 :             puts (" -> ???");
   10701             :           else
   10702           0 :             putchar_unlocked ('\n');
   10703           0 :           ++u;
   10704             :         }
   10705           0 :       while (readp < action_table_end);
   10706             :     }
   10707             : 
   10708           0 :   if (max_ar_filter > 0 && ttype_base != NULL)
   10709             :     {
   10710           0 :       unsigned char dsize;
   10711           0 :       puts ("\n TType table:");
   10712             : 
   10713             :       // XXX Not *4, size of encoding;
   10714           0 :       switch (ttype_encoding & 7)
   10715             :         {
   10716             :         case DW_EH_PE_udata2:
   10717             :         case DW_EH_PE_sdata2:
   10718             :           dsize = 2;
   10719             :           break;
   10720             :         case DW_EH_PE_udata4:
   10721             :         case DW_EH_PE_sdata4:
   10722             :           dsize = 4;
   10723             :           break;
   10724             :         case DW_EH_PE_udata8:
   10725             :         case DW_EH_PE_sdata8:
   10726             :           dsize = 8;
   10727             :           break;
   10728           0 :         default:
   10729           0 :           dsize = 0;
   10730           0 :           error (1, 0, gettext ("invalid TType encoding"));
   10731             :         }
   10732             : 
   10733           0 :       if (max_ar_filter
   10734           0 :           > (size_t) (ttype_base - (const unsigned char *) data->d_buf) / dsize)
   10735             :         goto invalid_data;
   10736             : 
   10737           0 :       readp = ttype_base - max_ar_filter * dsize;
   10738           0 :       do
   10739             :         {
   10740           0 :           uint64_t ttype;
   10741           0 :           readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
   10742             :                                 dbg);
   10743           0 :           printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
   10744             :         }
   10745           0 :       while (readp < ttype_base);
   10746             :     }
   10747             : }
   10748             : 
   10749             : /* Print the content of the '.gdb_index' section.
   10750             :    http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
   10751             : */
   10752             : static void
   10753           2 : print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
   10754             :                          GElf_Ehdr *ehdr __attribute__ ((unused)),
   10755             :                          Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   10756             : {
   10757           2 :   printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
   10758             :                    " contains %" PRId64 " bytes :\n"),
   10759             :           elf_ndxscn (scn), section_name (ebl, shdr),
   10760           2 :           (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
   10761             : 
   10762           2 :   Elf_Data *data = elf_rawdata (scn, NULL);
   10763             : 
   10764           2 :   if (unlikely (data == NULL))
   10765             :     {
   10766           0 :       error (0, 0, gettext ("cannot get %s content: %s"),
   10767             :              ".gdb_index", elf_errmsg (-1));
   10768           0 :       return;
   10769             :     }
   10770             : 
   10771             :   // .gdb_index is always in little endian.
   10772           2 :   Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
   10773           2 :   dbg = &dummy_dbg;
   10774             : 
   10775           2 :   const unsigned char *readp = data->d_buf;
   10776           2 :   const unsigned char *const dataend = readp + data->d_size;
   10777             : 
   10778           2 :   if (unlikely (readp + 4 > dataend))
   10779             :     {
   10780           0 :     invalid_data:
   10781           0 :       error (0, 0, gettext ("invalid data"));
   10782           0 :       return;
   10783             :     }
   10784             : 
   10785           2 :   int32_t vers = read_4ubyte_unaligned (dbg, readp);
   10786           2 :   printf (gettext (" Version:         %" PRId32 "\n"), vers);
   10787             : 
   10788             :   // The only difference between version 4 and version 5 is the
   10789             :   // hash used for generating the table.  Version 6 contains symbols
   10790             :   // for inlined functions, older versions didn't.  Version 7 adds
   10791             :   // symbol kinds.  Version 8 just indicates that it correctly includes
   10792             :   // TUs for symbols.
   10793           2 :   if (vers < 4 || vers > 8)
   10794             :     {
   10795           0 :       printf (gettext ("  unknown version, cannot parse section\n"));
   10796           0 :       return;
   10797             :     }
   10798             : 
   10799           2 :   readp += 4;
   10800           2 :   if (unlikely (readp + 4 > dataend))
   10801             :     goto invalid_data;
   10802             : 
   10803           2 :   uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
   10804           2 :   printf (gettext (" CU offset:       %#" PRIx32 "\n"), cu_off);
   10805             : 
   10806           2 :   readp += 4;
   10807           2 :   if (unlikely (readp + 4 > dataend))
   10808             :     goto invalid_data;
   10809             : 
   10810           2 :   uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
   10811           2 :   printf (gettext (" TU offset:       %#" PRIx32 "\n"), tu_off);
   10812             : 
   10813           2 :   readp += 4;
   10814           2 :   if (unlikely (readp + 4 > dataend))
   10815             :     goto invalid_data;
   10816             : 
   10817           2 :   uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
   10818           2 :   printf (gettext (" address offset:  %#" PRIx32 "\n"), addr_off);
   10819             : 
   10820           2 :   readp += 4;
   10821           2 :   if (unlikely (readp + 4 > dataend))
   10822             :     goto invalid_data;
   10823             : 
   10824           2 :   uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
   10825           2 :   printf (gettext (" symbol offset:   %#" PRIx32 "\n"), sym_off);
   10826             : 
   10827           2 :   readp += 4;
   10828           2 :   if (unlikely (readp + 4 > dataend))
   10829             :     goto invalid_data;
   10830             : 
   10831           2 :   uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
   10832           2 :   printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
   10833             : 
   10834           2 :   if (unlikely ((size_t) (dataend - (const unsigned char *) data->d_buf)
   10835             :                 < const_off))
   10836             :     goto invalid_data;
   10837             : 
   10838           2 :   readp = data->d_buf + cu_off;
   10839             : 
   10840           2 :   const unsigned char *nextp = data->d_buf + tu_off;
   10841           2 :   if (tu_off >= data->d_size)
   10842             :     goto invalid_data;
   10843             : 
   10844           2 :   size_t cu_nr = (nextp - readp) / 16;
   10845             : 
   10846           2 :   printf (gettext ("\n CU list at offset %#" PRIx32
   10847             :                    " contains %zu entries:\n"),
   10848             :           cu_off, cu_nr);
   10849             : 
   10850           2 :   size_t n = 0;
   10851           6 :   while (dataend - readp >= 16 && n < cu_nr)
   10852             :     {
   10853           4 :       uint64_t off = read_8ubyte_unaligned (dbg, readp);
   10854           4 :       readp += 8;
   10855             : 
   10856           4 :       uint64_t len = read_8ubyte_unaligned (dbg, readp);
   10857           4 :       readp += 8;
   10858             : 
   10859           4 :       printf (" [%4zu] start: %0#8" PRIx64
   10860             :               ", length: %5" PRIu64 "\n", n, off, len);
   10861           4 :       n++;
   10862             :     }
   10863             : 
   10864           2 :   readp = data->d_buf + tu_off;
   10865           2 :   nextp = data->d_buf + addr_off;
   10866           2 :   if (addr_off >= data->d_size)
   10867             :     goto invalid_data;
   10868             : 
   10869           2 :   size_t tu_nr = (nextp - readp) / 24;
   10870             : 
   10871           2 :   printf (gettext ("\n TU list at offset %#" PRIx32
   10872             :                    " contains %zu entries:\n"),
   10873             :           tu_off, tu_nr);
   10874             : 
   10875           2 :   n = 0;
   10876           4 :   while (dataend - readp >= 24 && n < tu_nr)
   10877             :     {
   10878           2 :       uint64_t off = read_8ubyte_unaligned (dbg, readp);
   10879           2 :       readp += 8;
   10880             : 
   10881           2 :       uint64_t type = read_8ubyte_unaligned (dbg, readp);
   10882           2 :       readp += 8;
   10883             : 
   10884           2 :       uint64_t sig = read_8ubyte_unaligned (dbg, readp);
   10885           2 :       readp += 8;
   10886             : 
   10887           2 :       printf (" [%4zu] CU offset: %5" PRId64
   10888             :               ", type offset: %5" PRId64
   10889             :               ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
   10890           2 :       n++;
   10891             :     }
   10892             : 
   10893           2 :   readp = data->d_buf + addr_off;
   10894           2 :   nextp = data->d_buf + sym_off;
   10895           2 :   if (sym_off >= data->d_size)
   10896             :     goto invalid_data;
   10897             : 
   10898           2 :   size_t addr_nr = (nextp - readp) / 20;
   10899             : 
   10900           2 :   printf (gettext ("\n Address list at offset %#" PRIx32
   10901             :                    " contains %zu entries:\n"),
   10902             :           addr_off, addr_nr);
   10903             : 
   10904           2 :   n = 0;
   10905           6 :   while (dataend - readp >= 20 && n < addr_nr)
   10906             :     {
   10907           4 :       uint64_t low = read_8ubyte_unaligned (dbg, readp);
   10908           4 :       readp += 8;
   10909             : 
   10910           4 :       uint64_t high = read_8ubyte_unaligned (dbg, readp);
   10911           4 :       readp += 8;
   10912             : 
   10913           4 :       uint32_t idx = read_4ubyte_unaligned (dbg, readp);
   10914           4 :       readp += 4;
   10915             : 
   10916           4 :       printf (" [%4zu] ", n);
   10917           4 :       print_dwarf_addr (dwflmod, 8, low, low);
   10918           4 :       printf ("..");
   10919           4 :       print_dwarf_addr (dwflmod, 8, high - 1, high);
   10920           4 :       printf (", CU index: %5" PRId32 "\n", idx);
   10921           4 :       n++;
   10922             :     }
   10923             : 
   10924           2 :   const unsigned char *const_start = data->d_buf + const_off;
   10925           2 :   if (const_off >= data->d_size)
   10926             :     goto invalid_data;
   10927             : 
   10928           2 :   readp = data->d_buf + sym_off;
   10929           2 :   nextp = const_start;
   10930           2 :   size_t sym_nr = (nextp - readp) / 8;
   10931             : 
   10932           2 :   printf (gettext ("\n Symbol table at offset %#" PRIx32
   10933             :                    " contains %zu slots:\n"),
   10934             :           addr_off, sym_nr);
   10935             : 
   10936           2 :   n = 0;
   10937        2050 :   while (dataend - readp >= 8 && n < sym_nr)
   10938             :     {
   10939        2048 :       uint32_t name = read_4ubyte_unaligned (dbg, readp);
   10940        2048 :       readp += 4;
   10941             : 
   10942        2048 :       uint32_t vector = read_4ubyte_unaligned (dbg, readp);
   10943        2048 :       readp += 4;
   10944             : 
   10945        2048 :       if (name != 0 || vector != 0)
   10946             :         {
   10947          14 :           const unsigned char *sym = const_start + name;
   10948          14 :           if (unlikely ((size_t) (dataend - const_start) < name
   10949             :                         || memchr (sym, '\0', dataend - sym) == NULL))
   10950             :             goto invalid_data;
   10951             : 
   10952          14 :           printf (" [%4zu] symbol: %s, CUs: ", n, sym);
   10953             : 
   10954          14 :           const unsigned char *readcus = const_start + vector;
   10955          14 :           if (unlikely ((size_t) (dataend - const_start) < vector))
   10956             :             goto invalid_data;
   10957          14 :           uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
   10958          30 :           while (cus--)
   10959             :             {
   10960          16 :               uint32_t cu_kind, cu, kind;
   10961          16 :               bool is_static;
   10962          16 :               readcus += 4;
   10963          16 :               if (unlikely (readcus + 4 > dataend))
   10964             :                 goto invalid_data;
   10965          16 :               cu_kind = read_4ubyte_unaligned (dbg, readcus);
   10966          16 :               cu = cu_kind & ((1 << 24) - 1);
   10967          16 :               kind = (cu_kind >> 28) & 7;
   10968          16 :               is_static = cu_kind & (1U << 31);
   10969          16 :               if (cu > cu_nr - 1)
   10970           2 :                 printf ("%" PRId32 "T", cu - (uint32_t) cu_nr);
   10971             :               else
   10972          14 :                 printf ("%" PRId32, cu);
   10973          16 :               if (kind != 0)
   10974             :                 {
   10975           8 :                   printf (" (");
   10976           8 :                   switch (kind)
   10977             :                     {
   10978             :                     case 1:
   10979           3 :                       printf ("type");
   10980             :                       break;
   10981             :                     case 2:
   10982           2 :                       printf ("var");
   10983             :                       break;
   10984             :                     case 3:
   10985           3 :                       printf ("func");
   10986             :                       break;
   10987             :                     case 4:
   10988           0 :                       printf ("other");
   10989             :                       break;
   10990             :                     default:
   10991           0 :                       printf ("unknown-0x%" PRIx32, kind);
   10992             :                       break;
   10993             :                     }
   10994          11 :                   printf (":%c)", (is_static ? 'S' : 'G'));
   10995             :                 }
   10996          16 :               if (cus > 0)
   10997           2 :                 printf (", ");
   10998             :             }
   10999          14 :           printf ("\n");
   11000             :         }
   11001        2048 :       n++;
   11002             :     }
   11003             : }
   11004             : 
   11005             : /* Returns true and sets split DWARF CU id if there is a split compile
   11006             :    unit in the given Dwarf, and no non-split units are found (before it).  */
   11007             : static bool
   11008         121 : is_split_dwarf (Dwarf *dbg, uint64_t *id, Dwarf_CU **split_cu)
   11009             : {
   11010         121 :   Dwarf_CU *cu = NULL;
   11011         121 :   while (dwarf_get_units (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
   11012             :     {
   11013         121 :       uint8_t unit_type;
   11014         121 :       if (dwarf_cu_info (cu, NULL, &unit_type, NULL, NULL,
   11015             :                          id, NULL, NULL) != 0)
   11016         121 :         return false;
   11017             : 
   11018         121 :       if (unit_type != DW_UT_split_compile && unit_type != DW_UT_split_type)
   11019             :         return false;
   11020             : 
   11021             :       /* We really only care about the split compile unit, the types
   11022             :          should be fine and self sufficient.  Also they don't have an
   11023             :          id that we can match with a skeleton unit.  */
   11024           9 :       if (unit_type == DW_UT_split_compile)
   11025             :         {
   11026           9 :           *split_cu = cu;
   11027           9 :           return true;
   11028             :         }
   11029             :     }
   11030             : 
   11031             :   return false;
   11032             : }
   11033             : 
   11034             : /* Check that there is one and only one Dwfl_Module, return in arg.  */
   11035             : static int
   11036           9 : getone_dwflmod (Dwfl_Module *dwflmod,
   11037             :                void **userdata __attribute__ ((unused)),
   11038             :                const char *name __attribute__ ((unused)),
   11039             :                Dwarf_Addr base __attribute__ ((unused)),
   11040             :                void *arg)
   11041             : {
   11042           9 :   Dwfl_Module **m = (Dwfl_Module **) arg;
   11043           9 :   if (*m != NULL)
   11044             :     return DWARF_CB_ABORT;
   11045           9 :   *m = dwflmod;
   11046           9 :   return DWARF_CB_OK;
   11047             : }
   11048             : 
   11049             : static void
   11050         151 : print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
   11051             : {
   11052             :   /* Used for skeleton file, if necessary for split DWARF.  */
   11053         151 :   Dwfl *skel_dwfl = NULL;
   11054         151 :   Dwfl_Module *skel_mod = NULL;
   11055         151 :   char *skel_name = NULL;
   11056         151 :   Dwarf *split_dbg = NULL;
   11057         151 :   Dwarf_CU *split_cu = NULL;
   11058             : 
   11059             :   /* Before we start the real work get a debug context descriptor.  */
   11060         151 :   Dwarf_Addr dwbias;
   11061         151 :   Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
   11062         453 :   Dwarf dummy_dbg =
   11063             :     {
   11064         151 :       .elf = ebl->elf,
   11065         151 :       .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
   11066             :     };
   11067         151 :   if (dbg == NULL)
   11068             :     {
   11069          30 :       if ((print_debug_sections & ~section_exception) != 0)
   11070           0 :         error (0, 0, gettext ("cannot get debug context descriptor: %s"),
   11071             :                dwfl_errmsg (-1));
   11072             :       dbg = &dummy_dbg;
   11073             :     }
   11074             :   else
   11075             :     {
   11076             :       /* If we are asked about a split dwarf (.dwo) file, use the user
   11077             :          provided, or find the corresponding skeleton file. If we got
   11078             :          a skeleton file, replace the given dwflmod and dbg, with one
   11079             :          derived from the skeleton file to provide enough context.  */
   11080         121 :       uint64_t split_id;
   11081         121 :       if (is_split_dwarf (dbg, &split_id, &split_cu))
   11082             :         {
   11083           9 :           if (dwarf_skeleton != NULL)
   11084           9 :             skel_name = strdup (dwarf_skeleton);
   11085             :           else
   11086             :             {
   11087             :               /* Replace file.dwo with file.o and see if that matches. */
   11088           0 :               const char *fname;
   11089           0 :               dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL,
   11090             :                                 &fname, NULL);
   11091           0 :               if (fname != NULL)
   11092             :                 {
   11093           0 :                   size_t flen = strlen (fname);
   11094           0 :                   if (flen > 4 && strcmp (".dwo", fname + flen - 4) == 0)
   11095             :                     {
   11096           0 :                       skel_name = strdup (fname);
   11097           0 :                       if (skel_name != NULL)
   11098             :                         {
   11099           0 :                           skel_name[flen - 3] = 'o';
   11100           0 :                           skel_name[flen - 2] = '\0';
   11101             :                         }
   11102             :                     }
   11103             :                 }
   11104             :             }
   11105             : 
   11106           9 :           if (skel_name != NULL)
   11107             :             {
   11108           9 :               int skel_fd = open (skel_name, O_RDONLY);
   11109           9 :               if (skel_fd == -1)
   11110           0 :                 fprintf (stderr, "Warning: Couldn't open DWARF skeleton file"
   11111             :                          " '%s'\n", skel_name);
   11112             :               else
   11113           9 :                 skel_dwfl = create_dwfl (skel_fd, skel_name);
   11114             : 
   11115           9 :               if (skel_dwfl != NULL)
   11116             :                 {
   11117           9 :                   if (dwfl_getmodules (skel_dwfl, &getone_dwflmod,
   11118             :                                        &skel_mod, 0) != 0)
   11119             :                     {
   11120           0 :                       fprintf (stderr, "Warning: Bad DWARF skeleton,"
   11121             :                                " multiple modules '%s'\n", skel_name);
   11122           0 :                       dwfl_end (skel_dwfl);
   11123           0 :                       skel_mod = NULL;
   11124             :                     }
   11125             :                 }
   11126           0 :               else if (skel_fd != -1)
   11127           0 :                 fprintf (stderr, "Warning: Couldn't create skeleton dwfl for"
   11128             :                          " '%s': %s\n", skel_name, dwfl_errmsg (-1));
   11129             : 
   11130           9 :               if (skel_mod != NULL)
   11131             :                 {
   11132           9 :                   Dwarf *skel_dbg = dwfl_module_getdwarf (skel_mod, &dwbias);
   11133           9 :                   if (skel_dbg != NULL)
   11134             :                     {
   11135             :                       /* First check the skeleton CU DIE, only fetch
   11136             :                          the split DIE if we know the id matches to
   11137             :                          not unnecessary search for any split DIEs we
   11138             :                          don't need. */
   11139           9 :                       Dwarf_CU *cu = NULL;
   11140          13 :                       while (dwarf_get_units (skel_dbg, cu, &cu,
   11141             :                                               NULL, NULL, NULL, NULL) == 0)
   11142             :                         {
   11143          13 :                           uint8_t unit_type;
   11144          13 :                           uint64_t skel_id;
   11145          13 :                           if (dwarf_cu_info (cu, NULL, &unit_type, NULL, NULL,
   11146             :                                              &skel_id, NULL, NULL) == 0
   11147          13 :                               && unit_type == DW_UT_skeleton
   11148          13 :                               && split_id == skel_id)
   11149             :                             {
   11150           9 :                               Dwarf_Die subdie;
   11151           9 :                               if (dwarf_cu_info (cu, NULL, NULL, NULL,
   11152             :                                                  &subdie,
   11153             :                                                  NULL, NULL, NULL) == 0
   11154           9 :                                   && dwarf_tag (&subdie) != DW_TAG_invalid)
   11155             :                                 {
   11156           9 :                                   split_dbg = dwarf_cu_getdwarf (subdie.cu);
   11157           9 :                                   if (split_dbg == NULL)
   11158           0 :                                     fprintf (stderr,
   11159             :                                              "Warning: Couldn't get split_dbg:"
   11160             :                                              " %s\n", dwarf_errmsg (-1));
   11161           9 :                                   break;
   11162             :                                 }
   11163             :                               else
   11164             :                                 {
   11165             :                                   /* Everything matches up, but not
   11166             :                                      according to libdw. Which means
   11167             :                                      the user knew better.  So...
   11168             :                                      Terrible hack... We can never
   11169             :                                      destroy the underlying dwfl
   11170             :                                      because it would free the wrong
   11171             :                                      Dwarfs... So we leak memory...*/
   11172           0 :                                   if (cu->split == NULL
   11173           0 :                                       && dwarf_skeleton != NULL)
   11174             :                                     {
   11175           0 :                                       do_not_close_dwfl = true;
   11176           0 :                                       __libdw_link_skel_split (cu, split_cu);
   11177           0 :                                       split_dbg = dwarf_cu_getdwarf (split_cu);
   11178           0 :                                       break;
   11179             :                                     }
   11180             :                                   else
   11181           0 :                                     fprintf (stderr, "Warning: Couldn't get"
   11182             :                                              " skeleton subdie: %s\n",
   11183             :                                              dwarf_errmsg (-1));
   11184             :                                 }
   11185             :                             }
   11186             :                         }
   11187           9 :                       if (split_dbg == NULL)
   11188           0 :                         fprintf (stderr, "Warning: '%s' didn't contain a skeleton for split id %" PRIx64 "\n", skel_name, split_id);
   11189             :                     }
   11190             :                   else
   11191           0 :                     fprintf (stderr, "Warning: Couldn't get skeleton DWARF:"
   11192             :                              " %s\n", dwfl_errmsg (-1));
   11193             :                 }
   11194             :             }
   11195             : 
   11196           9 :           if (split_dbg != NULL)
   11197             :             {
   11198           9 :               dbg = split_dbg;
   11199           9 :               dwflmod = skel_mod;
   11200             :             }
   11201           0 :           else if (skel_name == NULL)
   11202           0 :             fprintf (stderr,
   11203             :                      "Warning: split DWARF file, but no skeleton found.\n");
   11204             :         }
   11205         112 :       else if (dwarf_skeleton != NULL)
   11206           0 :         fprintf (stderr, "Warning: DWARF skeleton given,"
   11207             :                  " but not a split DWARF file\n");
   11208             :     }
   11209             : 
   11210             :   /* Get the section header string table index.  */
   11211         151 :   size_t shstrndx;
   11212         151 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   11213           0 :     error (EXIT_FAILURE, 0,
   11214           0 :            gettext ("cannot get section header string table index"));
   11215             : 
   11216             :   /* If the .debug_info section is listed as implicitly required then
   11217             :      we must make sure to handle it before handling any other debug
   11218             :      section.  Various other sections depend on the CU DIEs being
   11219             :      scanned (silently) first.  */
   11220         151 :   bool implicit_info = (implicit_debug_sections & section_info) != 0;
   11221         151 :   bool explicit_info = (print_debug_sections & section_info) != 0;
   11222         151 :   if (implicit_info)
   11223             :     {
   11224             :       Elf_Scn *scn = NULL;
   11225        1542 :       while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   11226             :         {
   11227        1542 :           GElf_Shdr shdr_mem;
   11228        1542 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   11229             : 
   11230        1542 :           if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
   11231             :             {
   11232        1872 :               const char *name = elf_strptr (ebl->elf, shstrndx,
   11233         624 :                                              shdr->sh_name);
   11234         624 :               if (name == NULL)
   11235           0 :                 continue;
   11236             : 
   11237         624 :               if (strcmp (name, ".debug_info") == 0
   11238         560 :                   || strcmp (name, ".debug_info.dwo") == 0
   11239         551 :                   || strcmp (name, ".zdebug_info") == 0
   11240         545 :                   || strcmp (name, ".zdebug_info.dwo") == 0)
   11241             :                 {
   11242          79 :                   print_debug_info_section (dwflmod, ebl, ehdr,
   11243             :                                             scn, shdr, dbg);
   11244          79 :                   break;
   11245             :                 }
   11246             :             }
   11247             :         }
   11248          79 :       print_debug_sections &= ~section_info;
   11249          79 :       implicit_debug_sections &= ~section_info;
   11250             :     }
   11251             : 
   11252             :   /* Look through all the sections for the debugging sections to print.  */
   11253             :   Elf_Scn *scn = NULL;
   11254        4524 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   11255             :     {
   11256        4373 :       GElf_Shdr shdr_mem;
   11257        4373 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   11258             : 
   11259        4373 :       if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
   11260             :         {
   11261        2113 :           static const struct
   11262             :           {
   11263             :             const char *name;
   11264             :             enum section_e bitmask;
   11265             :             void (*fp) (Dwfl_Module *, Ebl *,
   11266             :                         GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
   11267             :           } debug_sections[] =
   11268             :             {
   11269             : #define NEW_SECTION(name) \
   11270             :               { ".debug_" #name, section_##name, print_debug_##name##_section }
   11271             :               NEW_SECTION (abbrev),
   11272             :               NEW_SECTION (addr),
   11273             :               NEW_SECTION (aranges),
   11274             :               NEW_SECTION (frame),
   11275             :               NEW_SECTION (info),
   11276             :               NEW_SECTION (types),
   11277             :               NEW_SECTION (line),
   11278             :               NEW_SECTION (loc),
   11279             :               /* loclists is loc for DWARF5.  */
   11280             :               { ".debug_loclists", section_loc,
   11281             :                 print_debug_loclists_section },
   11282             :               NEW_SECTION (pubnames),
   11283             :               NEW_SECTION (str),
   11284             :               /* A DWARF5 specialised debug string section.  */
   11285             :               { ".debug_line_str", section_str,
   11286             :                 print_debug_str_section },
   11287             :               /* DWARF5 string offsets table.  */
   11288             :               { ".debug_str_offsets", section_str,
   11289             :                 print_debug_str_offsets_section },
   11290             :               NEW_SECTION (macinfo),
   11291             :               NEW_SECTION (macro),
   11292             :               NEW_SECTION (ranges),
   11293             :               /* rnglists is ranges for DWARF5.  */
   11294             :               { ".debug_rnglists", section_ranges,
   11295             :                 print_debug_rnglists_section },
   11296             :               { ".eh_frame", section_frame | section_exception,
   11297             :                 print_debug_frame_section },
   11298             :               { ".eh_frame_hdr", section_frame | section_exception,
   11299             :                 print_debug_frame_hdr_section },
   11300             :               { ".gcc_except_table", section_frame | section_exception,
   11301             :                 print_debug_exception_table },
   11302             :               { ".gdb_index", section_gdb_index, print_gdb_index_section }
   11303             :             };
   11304        2113 :           const int ndebug_sections = (sizeof (debug_sections)
   11305             :                                        / sizeof (debug_sections[0]));
   11306        6339 :           const char *name = elf_strptr (ebl->elf, shstrndx,
   11307        2113 :                                          shdr->sh_name);
   11308        2113 :           if (name == NULL)
   11309           0 :             continue;
   11310             : 
   11311             :           int n;
   11312       33177 :           for (n = 0; n < ndebug_sections; ++n)
   11313             :             {
   11314       32050 :               size_t dbglen = strlen (debug_sections[n].name);
   11315       32050 :               size_t scnlen = strlen (name);
   11316       32050 :               if ((strncmp (name, debug_sections[n].name, dbglen) == 0
   11317         988 :                    && (dbglen == scnlen
   11318         138 :                        || (scnlen == dbglen + 4
   11319         121 :                            && strstr (name, ".dwo") == name + dbglen)))
   11320       31146 :                   || (name[0] == '.' && name[1] == 'z'
   11321         566 :                       && debug_sections[n].name[1] == 'd'
   11322         566 :                       && strncmp (&name[2], &debug_sections[n].name[1],
   11323             :                                   dbglen - 1) == 0
   11324          82 :                       && (scnlen == dbglen + 1
   11325           0 :                           || (scnlen == dbglen + 5
   11326           0 :                               && strstr (name, ".dwo") == name + dbglen + 1))))
   11327             :                 {
   11328        1972 :                   if ((print_debug_sections | implicit_debug_sections)
   11329         986 :                       & debug_sections[n].bitmask)
   11330         371 :                     debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
   11331             :                   break;
   11332             :                 }
   11333             :             }
   11334             :         }
   11335             :     }
   11336             : 
   11337         151 :   dwfl_end (skel_dwfl);
   11338         151 :   free (skel_name);
   11339             : 
   11340             :   /* Turn implicit and/or explicit back on in case we go over another file.  */
   11341         151 :   if (implicit_info)
   11342          79 :     implicit_debug_sections |= section_info;
   11343         151 :   if (explicit_info)
   11344          63 :     print_debug_sections |= section_info;
   11345             : 
   11346         302 :   reset_listptr (&known_locsptr);
   11347         302 :   reset_listptr (&known_loclistsptr);
   11348         302 :   reset_listptr (&known_rangelistptr);
   11349         302 :   reset_listptr (&known_rnglistptr);
   11350         302 :   reset_listptr (&known_addrbases);
   11351         302 :   reset_listptr (&known_stroffbases);
   11352         151 : }
   11353             : 
   11354             : 
   11355             : #define ITEM_INDENT             4
   11356             : #define WRAP_COLUMN             75
   11357             : 
   11358             : /* Print "NAME: FORMAT", wrapping when output text would make the line
   11359             :    exceed WRAP_COLUMN.  Unpadded numbers look better for the core items
   11360             :    but this function is also used for registers which should be printed
   11361             :    aligned.  Fortunately registers output uses fixed fields width (such
   11362             :    as %11d) for the alignment.
   11363             : 
   11364             :    Line breaks should not depend on the particular values although that
   11365             :    may happen in some cases of the core items.  */
   11366             : 
   11367             : static unsigned int
   11368             : __attribute__ ((format (printf, 6, 7)))
   11369         821 : print_core_item (unsigned int colno, char sep, unsigned int wrap,
   11370             :                  size_t name_width, const char *name, const char *format, ...)
   11371             : {
   11372         821 :   size_t len = strlen (name);
   11373         821 :   if (name_width < len)
   11374         397 :     name_width = len;
   11375             : 
   11376         821 :   char *out;
   11377         821 :   va_list ap;
   11378         821 :   va_start (ap, format);
   11379         821 :   int out_len = vasprintf (&out, format, ap);
   11380         821 :   va_end (ap);
   11381         821 :   if (out_len == -1)
   11382           0 :     error (EXIT_FAILURE, 0, _("memory exhausted"));
   11383             : 
   11384         821 :   size_t n = name_width + sizeof ": " - 1 + out_len;
   11385             : 
   11386         821 :   if (colno == 0)
   11387             :     {
   11388          51 :       printf ("%*s", ITEM_INDENT, "");
   11389          51 :       colno = ITEM_INDENT + n;
   11390             :     }
   11391         770 :   else if (colno + 2 + n < wrap)
   11392             :     {
   11393         468 :       printf ("%c ", sep);
   11394         468 :       colno += 2 + n;
   11395             :     }
   11396             :   else
   11397             :     {
   11398         302 :       printf ("\n%*s", ITEM_INDENT, "");
   11399         302 :       colno = ITEM_INDENT + n;
   11400             :     }
   11401             : 
   11402         821 :   printf ("%s: %*s%s", name, (int) (name_width - len), "", out);
   11403             : 
   11404         821 :   free (out);
   11405             : 
   11406         821 :   return colno;
   11407             : }
   11408             : 
   11409             : static const void *
   11410         931 : convert (Elf *core, Elf_Type type, uint_fast16_t count,
   11411             :          void *value, const void *data, size_t size)
   11412             : {
   11413        1862 :   Elf_Data valuedata =
   11414             :     {
   11415             :       .d_type = type,
   11416             :       .d_buf = value,
   11417         931 :       .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
   11418             :       .d_version = EV_CURRENT,
   11419             :     };
   11420         931 :   Elf_Data indata =
   11421             :     {
   11422             :       .d_type = type,
   11423             :       .d_buf = (void *) data,
   11424             :       .d_size = valuedata.d_size,
   11425             :       .d_version = EV_CURRENT,
   11426             :     };
   11427             : 
   11428         931 :   Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
   11429         931 :                  ? elf32_xlatetom : elf64_xlatetom)
   11430         931 :     (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
   11431         931 :   if (d == NULL)
   11432           0 :     error (EXIT_FAILURE, 0,
   11433           0 :            gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   11434             : 
   11435         931 :   return data + indata.d_size;
   11436             : }
   11437             : 
   11438             : typedef uint8_t GElf_Byte;
   11439             : 
   11440             : static unsigned int
   11441         400 : handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
   11442             :                   unsigned int colno, size_t *repeated_size)
   11443             : {
   11444         400 :   uint_fast16_t count = item->count ?: 1;
   11445             :   /* Ebl_Core_Item count is always a small number.
   11446             :      Make sure the backend didn't put in some large bogus value.  */
   11447          62 :   assert (count < 128);
   11448             : 
   11449             : #define TYPES                                                                 \
   11450             :   DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8);                         \
   11451             :   DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16);                       \
   11452             :   DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32);                       \
   11453             :   DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32);                         \
   11454             :   DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64);                            \
   11455             :   DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64)
   11456             : 
   11457             : #define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name
   11458         400 :   typedef union { TYPES; } value_t;
   11459         400 :   void *data = alloca (count * sizeof (value_t));
   11460             : #undef DO_TYPE
   11461             : 
   11462             : #define DO_TYPE(NAME, Name, hex, dec) \
   11463             :     GElf_##Name *value_##Name __attribute__((unused)) = data
   11464         400 :   TYPES;
   11465             : #undef DO_TYPE
   11466             : 
   11467         400 :   size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
   11468         400 :   size_t convsize = size;
   11469         400 :   if (repeated_size != NULL)
   11470             :     {
   11471           1 :       if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
   11472             :         {
   11473           0 :           data = alloca (*repeated_size);
   11474           0 :           count *= *repeated_size / size;
   11475           0 :           convsize = count * size;
   11476           0 :           *repeated_size -= convsize;
   11477             :         }
   11478           1 :       else if (item->count != 0 || item->format != '\n')
   11479           0 :         *repeated_size -= size;
   11480             :     }
   11481             : 
   11482         400 :   convert (core, item->type, count, data, desc + item->offset, convsize);
   11483             : 
   11484         400 :   Elf_Type type = item->type;
   11485         400 :   if (type == ELF_T_ADDR)
   11486           1 :     type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
   11487             : 
   11488         400 :   switch (item->format)
   11489             :     {
   11490         193 :     case 'd':
   11491         193 :       assert (count == 1);
   11492         193 :       switch (type)
   11493             :         {
   11494             : #define DO_TYPE(NAME, Name, hex, dec)                                         \
   11495             :           case ELF_T_##NAME:                                                  \
   11496             :             colno = print_core_item (colno, ',', WRAP_COLUMN,                 \
   11497             :                                      0, item->name, dec, value_##Name[0]); \
   11498             :             break
   11499         193 :           TYPES;
   11500             : #undef DO_TYPE
   11501           0 :         default:
   11502           0 :           abort ();
   11503             :         }
   11504             :       break;
   11505             : 
   11506         111 :     case 'x':
   11507         111 :       assert (count == 1);
   11508         111 :       switch (type)
   11509             :         {
   11510             : #define DO_TYPE(NAME, Name, hex, dec)                                         \
   11511             :           case ELF_T_##NAME:                                                  \
   11512             :             colno = print_core_item (colno, ',', WRAP_COLUMN,                 \
   11513             :                                      0, item->name, hex, value_##Name[0]);      \
   11514             :             break
   11515         111 :           TYPES;
   11516             : #undef DO_TYPE
   11517           0 :         default:
   11518           0 :           abort ();
   11519             :         }
   11520             :       break;
   11521             : 
   11522          22 :     case 'b':
   11523             :     case 'B':
   11524          22 :       assert (size % sizeof (unsigned int) == 0);
   11525          22 :       unsigned int nbits = count * size * 8;
   11526          22 :       unsigned int pop = 0;
   11527          56 :       for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
   11528          34 :         pop += __builtin_popcount (*i);
   11529          22 :       bool negate = pop > nbits / 2;
   11530          22 :       const unsigned int bias = item->format == 'b';
   11531             : 
   11532          44 :       {
   11533          22 :         char printed[(negate ? nbits - pop : pop) * 16 + 1];
   11534          22 :         char *p = printed;
   11535          22 :         *p = '\0';
   11536             : 
   11537          22 :         if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
   11538             :           {
   11539             :             assert (size == sizeof (unsigned int) * 2);
   11540             :             for (unsigned int *i = data;
   11541             :                  (void *) i < data + count * size; i += 2)
   11542             :               {
   11543             :                 unsigned int w = i[1];
   11544             :                 i[1] = i[0];
   11545             :                 i[0] = w;
   11546             :               }
   11547             :           }
   11548             : 
   11549          22 :         unsigned int lastbit = 0;
   11550          22 :         unsigned int run = 0;
   11551          56 :         for (const unsigned int *i = data;
   11552          34 :              (void *) i < data + count * size; ++i)
   11553             :           {
   11554          34 :             unsigned int bit = ((void *) i - data) * 8;
   11555          34 :             unsigned int w = negate ? ~*i : *i;
   11556          34 :             while (w != 0)
   11557             :               {
   11558             :                 /* Note that a right shift equal to (or greater than)
   11559             :                    the number of bits of w is undefined behaviour.  In
   11560             :                    particular when the least significant bit is bit 32
   11561             :                    (w = 0x8000000) then w >>= n is undefined.  So
   11562             :                    explicitly handle that case separately.  */
   11563           0 :                 unsigned int n = ffs (w);
   11564           0 :                 if (n < sizeof (w) * 8)
   11565           0 :                   w >>= n;
   11566             :                 else
   11567             :                   w = 0;
   11568           0 :                 bit += n;
   11569             : 
   11570           0 :                 if (lastbit != 0 && lastbit + 1 == bit)
   11571           0 :                   ++run;
   11572             :                 else
   11573             :                   {
   11574           0 :                     if (lastbit == 0)
   11575           0 :                       p += sprintf (p, "%u", bit - bias);
   11576           0 :                     else if (run == 0)
   11577           0 :                       p += sprintf (p, ",%u", bit - bias);
   11578             :                     else
   11579           0 :                       p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
   11580             :                     run = 0;
   11581             :                   }
   11582             : 
   11583             :                 lastbit = bit;
   11584             :               }
   11585             :           }
   11586          22 :         if (lastbit > 0 && run > 0 && lastbit + 1 != nbits)
   11587           0 :           p += sprintf (p, "-%u", lastbit - bias);
   11588             : 
   11589          44 :         colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
   11590             :                                  negate ? "~<%s>" : "<%s>", printed);
   11591             :       }
   11592          22 :       break;
   11593             : 
   11594          44 :     case 'T':
   11595             :     case (char) ('T'|0x80):
   11596          44 :       assert (count == 2);
   11597          44 :       Dwarf_Word sec;
   11598          44 :       Dwarf_Word usec;
   11599          44 :       switch (type)
   11600             :         {
   11601             : #define DO_TYPE(NAME, Name, hex, dec)                                         \
   11602             :           case ELF_T_##NAME:                                                  \
   11603             :             sec = value_##Name[0];                                            \
   11604             :             usec = value_##Name[1];                                           \
   11605             :             break
   11606          44 :           TYPES;
   11607             : #undef DO_TYPE
   11608           0 :         default:
   11609           0 :           abort ();
   11610             :         }
   11611          44 :       if (unlikely (item->format == (char) ('T'|0x80)))
   11612             :         {
   11613             :           /* This is a hack for an ill-considered 64-bit ABI where
   11614             :              tv_usec is actually a 32-bit field with 32 bits of padding
   11615             :              rounding out struct timeval.  We've already converted it as
   11616             :              a 64-bit field.  For little-endian, this just means the
   11617             :              high half is the padding; it's presumably zero, but should
   11618             :              be ignored anyway.  For big-endian, it means the 32-bit
   11619             :              field went into the high half of USEC.  */
   11620           0 :           GElf_Ehdr ehdr_mem;
   11621           0 :           GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
   11622           0 :           if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
   11623           0 :             usec >>= 32;
   11624             :           else
   11625           0 :             usec &= UINT32_MAX;
   11626             :         }
   11627          44 :       colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
   11628             :                                "%" PRIu64 ".%.6" PRIu64, sec, usec);
   11629          44 :       break;
   11630             : 
   11631           9 :     case 'c':
   11632           9 :       assert (count == 1);
   11633          18 :       colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
   11634           9 :                                "%c", value_Byte[0]);
   11635           9 :       break;
   11636             : 
   11637          18 :     case 's':
   11638          18 :       colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
   11639             :                                "%.*s", (int) count, value_Byte);
   11640          18 :       break;
   11641             : 
   11642           1 :     case '\n':
   11643             :       /* This is a list of strings separated by '\n'.  */
   11644           1 :       assert (item->count == 0);
   11645           1 :       assert (repeated_size != NULL);
   11646           1 :       assert (item->name == NULL);
   11647           1 :       if (unlikely (item->offset >= *repeated_size))
   11648             :         break;
   11649             : 
   11650           1 :       const char *s = desc + item->offset;
   11651           1 :       size = *repeated_size - item->offset;
   11652           1 :       *repeated_size = 0;
   11653          48 :       while (size > 0)
   11654             :         {
   11655          48 :           const char *eol = memchr (s, '\n', size);
   11656          48 :           int len = size;
   11657          48 :           if (eol != NULL)
   11658          47 :             len = eol - s;
   11659          48 :           printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
   11660          48 :           if (eol == NULL)
   11661             :             break;
   11662          47 :           size -= eol + 1 - s;
   11663          47 :           s = eol + 1;
   11664             :         }
   11665             : 
   11666             :       colno = WRAP_COLUMN;
   11667             :       break;
   11668             : 
   11669             :     case 'h':
   11670             :       break;
   11671             : 
   11672           0 :     default:
   11673           0 :       error (0, 0, "XXX not handling format '%c' for %s",
   11674             :              item->format, item->name);
   11675             :       break;
   11676             :     }
   11677             : 
   11678             : #undef TYPES
   11679             : 
   11680           0 :   return colno;
   11681             : }
   11682             : 
   11683             : 
   11684             : /* Sort items by group, and by layout offset within each group.  */
   11685             : static int
   11686         895 : compare_core_items (const void *a, const void *b)
   11687             : {
   11688         895 :   const Ebl_Core_Item *const *p1 = a;
   11689         895 :   const Ebl_Core_Item *const *p2 = b;
   11690         895 :   const Ebl_Core_Item *item1 = *p1;
   11691         895 :   const Ebl_Core_Item *item2 = *p2;
   11692             : 
   11693         895 :   return ((item1->group == item2->group ? 0
   11694         895 :            : strcmp (item1->group, item2->group))
   11695         895 :           ?: (int) item1->offset - (int) item2->offset);
   11696             : }
   11697             : 
   11698             : /* Sort item groups by layout offset of the first item in the group.  */
   11699             : static int
   11700         139 : compare_core_item_groups (const void *a, const void *b)
   11701             : {
   11702         139 :   const Ebl_Core_Item *const *const *p1 = a;
   11703         139 :   const Ebl_Core_Item *const *const *p2 = b;
   11704         139 :   const Ebl_Core_Item *const *group1 = *p1;
   11705         139 :   const Ebl_Core_Item *const *group2 = *p2;
   11706         139 :   const Ebl_Core_Item *item1 = *group1;
   11707         139 :   const Ebl_Core_Item *item2 = *group2;
   11708             : 
   11709         139 :   return (int) item1->offset - (int) item2->offset;
   11710             : }
   11711             : 
   11712             : static unsigned int
   11713          37 : handle_core_items (Elf *core, const void *desc, size_t descsz,
   11714             :                    const Ebl_Core_Item *items, size_t nitems)
   11715             : {
   11716          37 :   if (nitems == 0)
   11717             :     return 0;
   11718          34 :   unsigned int colno = 0;
   11719             : 
   11720             :   /* FORMAT '\n' makes sense to be present only as a single item as it
   11721             :      processes all the data of a note.  FORMATs 'b' and 'B' have a special case
   11722             :      if present as a single item but they can be also processed with other
   11723             :      items below.  */
   11724          34 :   if (nitems == 1 && (items[0].format == '\n' || items[0].format == 'b'
   11725           8 :                       || items[0].format == 'B'))
   11726             :     {
   11727           1 :       assert (items[0].offset == 0);
   11728           1 :       size_t size = descsz;
   11729           1 :       colno = handle_core_item (core, items, desc, colno, &size);
   11730             :       /* If SIZE is not zero here there is some remaining data.  But we do not
   11731             :          know how to process it anyway.  */
   11732           1 :       return colno;
   11733             :     }
   11734         424 :   for (size_t i = 0; i < nitems; ++i)
   11735         391 :     assert (items[i].format != '\n');
   11736             : 
   11737             :   /* Sort to collect the groups together.  */
   11738          33 :   const Ebl_Core_Item *sorted_items[nitems];
   11739         424 :   for (size_t i = 0; i < nitems; ++i)
   11740         391 :     sorted_items[i] = &items[i];
   11741          33 :   qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
   11742             : 
   11743             :   /* Collect the unique groups and sort them.  */
   11744          33 :   const Ebl_Core_Item **groups[nitems];
   11745          33 :   groups[0] = &sorted_items[0];
   11746          33 :   size_t ngroups = 1;
   11747         391 :   for (size_t i = 1; i < nitems; ++i)
   11748         358 :     if (sorted_items[i]->group != sorted_items[i - 1]->group
   11749          75 :         && strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
   11750          75 :       groups[ngroups++] = &sorted_items[i];
   11751          33 :   qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
   11752             : 
   11753             :   /* Write out all the groups.  */
   11754          33 :   const void *last = desc;
   11755          35 :   do
   11756             :     {
   11757         145 :       for (size_t i = 0; i < ngroups; ++i)
   11758             :         {
   11759         110 :           for (const Ebl_Core_Item **item = groups[i];
   11760         509 :                (item < &sorted_items[nitems]
   11761         474 :                 && ((*item)->group == groups[i][0]->group
   11762          75 :                     || !strcmp ((*item)->group, groups[i][0]->group)));
   11763         399 :                ++item)
   11764         399 :             colno = handle_core_item (core, *item, desc, colno, NULL);
   11765             : 
   11766             :           /* Force a line break at the end of the group.  */
   11767         110 :           colno = WRAP_COLUMN;
   11768             :         }
   11769             : 
   11770          35 :       if (descsz == 0)
   11771             :         break;
   11772             : 
   11773             :       /* This set of items consumed a certain amount of the note's data.
   11774             :          If there is more data there, we have another unit of the same size.
   11775             :          Loop to print that out too.  */
   11776          20 :       const Ebl_Core_Item *item = &items[nitems - 1];
   11777          20 :       size_t eltsz = item->offset + gelf_fsize (core, item->type,
   11778          20 :                                                 item->count ?: 1, EV_CURRENT);
   11779             : 
   11780          20 :       int reps = -1;
   11781          20 :       do
   11782             :         {
   11783          20 :           ++reps;
   11784          20 :           desc += eltsz;
   11785          20 :           descsz -= eltsz;
   11786             :         }
   11787          20 :       while (descsz >= eltsz && !memcmp (desc, last, eltsz));
   11788             : 
   11789          20 :       if (reps == 1)
   11790             :         {
   11791             :           /* For just one repeat, print it unabridged twice.  */
   11792             :           desc -= eltsz;
   11793             :           descsz += eltsz;
   11794             :         }
   11795          20 :       else if (reps > 1)
   11796           0 :         printf (gettext ("\n%*s... <repeats %u more times> ..."),
   11797             :                 ITEM_INDENT, "", reps);
   11798             : 
   11799          20 :       last = desc;
   11800             :     }
   11801          20 :   while (descsz > 0);
   11802             : 
   11803          33 :   return colno;
   11804             : }
   11805             : 
   11806             : static unsigned int
   11807           0 : handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
   11808             :                       unsigned int colno)
   11809             : {
   11810           0 :   desc += regloc->offset;
   11811             : 
   11812           0 :   abort ();                     /* XXX */
   11813             :   return colno;
   11814             : }
   11815             : 
   11816             : 
   11817             : static unsigned int
   11818         162 : handle_core_register (Ebl *ebl, Elf *core, int maxregname,
   11819             :                       const Ebl_Register_Location *regloc, const void *desc,
   11820             :                       unsigned int colno)
   11821             : {
   11822         162 :   if (regloc->bits % 8 != 0)
   11823           0 :     return handle_bit_registers (regloc, desc, colno);
   11824             : 
   11825         162 :   desc += regloc->offset;
   11826             : 
   11827         586 :   for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
   11828             :     {
   11829         424 :       char name[REGNAMESZ];
   11830         424 :       int bits;
   11831         424 :       int type;
   11832         424 :       register_info (ebl, reg, regloc, name, &bits, &type);
   11833             : 
   11834             : #define TYPES                                                                 \
   11835             :       BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8);                          \
   11836             :       BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16);                       \
   11837             :       BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32);                             \
   11838             :       BITS (64, XWORD, "%20" PRId64, "  0x%.16" PRIx64)
   11839             : 
   11840             : #define BITS(bits, xtype, sfmt, ufmt)                           \
   11841             :       uint##bits##_t b##bits; int##bits##_t b##bits##s
   11842         424 :       union { TYPES; uint64_t b128[2]; } value;
   11843             : #undef  BITS
   11844             : 
   11845         424 :       switch (type)
   11846             :         {
   11847         336 :         case DW_ATE_unsigned:
   11848             :         case DW_ATE_signed:
   11849             :         case DW_ATE_address:
   11850         336 :           switch (bits)
   11851             :             {
   11852             : #define BITS(bits, xtype, sfmt, ufmt)                                         \
   11853             :             case bits:                                                        \
   11854             :               desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0);           \
   11855             :               if (type == DW_ATE_signed)                                      \
   11856             :                 colno = print_core_item (colno, ' ', WRAP_COLUMN,             \
   11857             :                                          maxregname, name,                    \
   11858             :                                          sfmt, value.b##bits##s);             \
   11859             :               else                                                            \
   11860             :                 colno = print_core_item (colno, ' ', WRAP_COLUMN,             \
   11861             :                                          maxregname, name,                    \
   11862             :                                          ufmt, value.b##bits);                \
   11863             :               break
   11864             : 
   11865         288 :             TYPES;
   11866             : 
   11867          48 :             case 128:
   11868          48 :               assert (type == DW_ATE_unsigned);
   11869          48 :               desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
   11870          48 :               int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
   11871          96 :               colno = print_core_item (colno, ' ', WRAP_COLUMN,
   11872             :                                        maxregname, name,
   11873             :                                        "0x%.16" PRIx64 "%.16" PRIx64,
   11874          48 :                                        value.b128[!be], value.b128[be]);
   11875          48 :               break;
   11876             : 
   11877           0 :             default:
   11878           0 :               abort ();
   11879             : #undef  BITS
   11880             :             }
   11881             :           break;
   11882             : 
   11883          88 :         default:
   11884             :           /* Print each byte in hex, the whole thing in native byte order.  */
   11885          88 :           assert (bits % 8 == 0);
   11886          88 :           const uint8_t *bytes = desc;
   11887          88 :           desc += bits / 8;
   11888          88 :           char hex[bits / 4 + 1];
   11889          88 :           hex[bits / 4] = '\0';
   11890          88 :           int incr = 1;
   11891          88 :           if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
   11892             :             {
   11893          48 :               bytes += bits / 8 - 1;
   11894          48 :               incr = -1;
   11895             :             }
   11896          88 :           size_t idx = 0;
   11897         872 :           for (char *h = hex; bits > 0; bits -= 8, idx += incr)
   11898             :             {
   11899         784 :               *h++ = "0123456789abcdef"[bytes[idx] >> 4];
   11900         784 :               *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
   11901             :             }
   11902          88 :           colno = print_core_item (colno, ' ', WRAP_COLUMN,
   11903             :                                    maxregname, name, "0x%s", hex);
   11904          88 :           break;
   11905             :         }
   11906         424 :       desc += regloc->pad;
   11907             : 
   11908             : #undef TYPES
   11909             :     }
   11910             : 
   11911         162 :   return colno;
   11912             : }
   11913             : 
   11914             : 
   11915             : struct register_info
   11916             : {
   11917             :   const Ebl_Register_Location *regloc;
   11918             :   const char *set;
   11919             :   char name[REGNAMESZ];
   11920             :   int regno;
   11921             :   int bits;
   11922             :   int type;
   11923             : };
   11924             : 
   11925             : static int
   11926           0 : register_bitpos (const struct register_info *r)
   11927             : {
   11928        2066 :   return (r->regloc->offset * 8
   11929        4132 :           + ((r->regno - r->regloc->regno)
   11930        2066 :              * (r->regloc->bits + r->regloc->pad * 8)));
   11931             : }
   11932             : 
   11933             : static int
   11934        1062 : compare_sets_by_info (const struct register_info *r1,
   11935             :                       const struct register_info *r2)
   11936             : {
   11937        1062 :   return ((int) r2->bits - (int) r1->bits
   11938        1062 :           ?: register_bitpos (r1) - register_bitpos (r2));
   11939             : }
   11940             : 
   11941             : /* Sort registers by set, and by size and layout offset within each set.  */
   11942             : static int
   11943        4595 : compare_registers (const void *a, const void *b)
   11944             : {
   11945        4595 :   const struct register_info *r1 = a;
   11946        4595 :   const struct register_info *r2 = b;
   11947             : 
   11948             :   /* Unused elements sort last.  */
   11949        4595 :   if (r1->regloc == NULL)
   11950        3309 :     return r2->regloc == NULL ? 0 : 1;
   11951        1286 :   if (r2->regloc == NULL)
   11952             :     return -1;
   11953             : 
   11954        1121 :   return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
   11955        1121 :           ?: compare_sets_by_info (r1, r2));
   11956             : }
   11957             : 
   11958             : /* Sort register sets by layout offset of the first register in the set.  */
   11959             : static int
   11960          20 : compare_register_sets (const void *a, const void *b)
   11961             : {
   11962          20 :   const struct register_info *const *p1 = a;
   11963          20 :   const struct register_info *const *p2 = b;
   11964          20 :   return compare_sets_by_info (*p1, *p2);
   11965             : }
   11966             : 
   11967             : static unsigned int
   11968          37 : handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
   11969             :                        const Ebl_Register_Location *reglocs, size_t nregloc)
   11970             : {
   11971          37 :   if (nregloc == 0)
   11972             :     return 0;
   11973             : 
   11974          18 :   ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
   11975          18 :   if (maxnreg <= 0)
   11976             :     {
   11977           0 :       for (size_t i = 0; i < nregloc; ++i)
   11978           0 :         if (maxnreg < reglocs[i].regno + reglocs[i].count)
   11979           0 :           maxnreg = reglocs[i].regno + reglocs[i].count;
   11980           0 :       assert (maxnreg > 0);
   11981             :     }
   11982             : 
   11983          18 :   struct register_info regs[maxnreg];
   11984          18 :   memset (regs, 0, sizeof regs);
   11985             : 
   11986             :   /* Sort to collect the sets together.  */
   11987          18 :   int maxreg = 0;
   11988         180 :   for (size_t i = 0; i < nregloc; ++i)
   11989         162 :     for (int reg = reglocs[i].regno;
   11990         586 :          reg < reglocs[i].regno + reglocs[i].count;
   11991         424 :          ++reg)
   11992             :       {
   11993         424 :         assert (reg < maxnreg);
   11994         424 :         if (reg > maxreg)
   11995         230 :           maxreg = reg;
   11996         424 :         struct register_info *info = &regs[reg];
   11997         424 :         info->regloc = &reglocs[i];
   11998         424 :         info->regno = reg;
   11999         424 :         info->set = register_info (ebl, reg, &reglocs[i],
   12000         424 :                                    info->name, &info->bits, &info->type);
   12001             :       }
   12002          18 :   qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
   12003             : 
   12004             :   /* Collect the unique sets and sort them.  */
   12005         882 :   inline bool same_set (const struct register_info *a,
   12006             :                         const struct register_info *b)
   12007             :   {
   12008         864 :     return (a < &regs[maxnreg] && a->regloc != NULL
   12009         864 :             && b < &regs[maxnreg] && b->regloc != NULL
   12010         846 :             && a->bits == b->bits
   12011        1692 :             && (a->set == b->set || !strcmp (a->set, b->set)));
   12012             :   }
   12013          18 :   struct register_info *sets[maxreg + 1];
   12014          18 :   sets[0] = &regs[0];
   12015          18 :   size_t nsets = 1;
   12016        1279 :   for (int i = 1; i <= maxreg; ++i)
   12017        1261 :     if (regs[i].regloc != NULL && !same_set (&regs[i], &regs[i - 1]))
   12018          16 :       sets[nsets++] = &regs[i];
   12019          18 :   qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
   12020             : 
   12021             :   /* Write out all the sets.  */
   12022          18 :   unsigned int colno = 0;
   12023          52 :   for (size_t i = 0; i < nsets; ++i)
   12024             :     {
   12025             :       /* Find the longest name of a register in this set.  */
   12026          34 :       size_t maxname = 0;
   12027          34 :       const struct register_info *end;
   12028         458 :       for (end = sets[i]; same_set (sets[i], end); ++end)
   12029             :         {
   12030         424 :           size_t len = strlen (end->name);
   12031         424 :           if (len > maxname)
   12032          52 :             maxname = len;
   12033             :         }
   12034             : 
   12035         196 :       for (const struct register_info *reg = sets[i];
   12036             :            reg < end;
   12037         162 :            reg += reg->regloc->count ?: 1)
   12038         162 :         colno = handle_core_register (ebl, core, maxname,
   12039             :                                       reg->regloc, desc, colno);
   12040             : 
   12041             :       /* Force a line break at the end of the group.  */
   12042          34 :       colno = WRAP_COLUMN;
   12043             :     }
   12044             : 
   12045          18 :   return colno;
   12046             : }
   12047             : 
   12048             : static void
   12049           9 : handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
   12050             : {
   12051           9 :   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
   12052           9 :   if (data == NULL)
   12053           0 :   elf_error:
   12054           0 :     error (EXIT_FAILURE, 0,
   12055           0 :            gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   12056             : 
   12057           9 :   const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
   12058         177 :   for (size_t i = 0; i < nauxv; ++i)
   12059             :     {
   12060         168 :       GElf_auxv_t av_mem;
   12061         168 :       GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
   12062         168 :       if (av == NULL)
   12063           0 :         goto elf_error;
   12064             : 
   12065         168 :       const char *name;
   12066         168 :       const char *fmt;
   12067         168 :       if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
   12068             :         {
   12069             :           /* Unknown type.  */
   12070           0 :           if (av->a_un.a_val == 0)
   12071           0 :             printf ("    %" PRIu64 "\n", av->a_type);
   12072             :           else
   12073           0 :             printf ("    %" PRIu64 ": %#" PRIx64 "\n",
   12074             :                     av->a_type, av->a_un.a_val);
   12075             :         }
   12076             :       else
   12077         168 :         switch (fmt[0])
   12078             :           {
   12079           9 :           case '\0':            /* Normally zero.  */
   12080           9 :             if (av->a_un.a_val == 0)
   12081             :               {
   12082           9 :                 printf ("    %s\n", name);
   12083             :                 break;
   12084             :               }
   12085          74 :             FALLTHROUGH;
   12086             :           case 'x':             /* hex */
   12087             :           case 'p':             /* address */
   12088             :           case 's':             /* address of string */
   12089          74 :             printf ("    %s: %#" PRIx64 "\n", name, av->a_un.a_val);
   12090             :             break;
   12091          81 :           case 'u':
   12092          81 :             printf ("    %s: %" PRIu64 "\n", name, av->a_un.a_val);
   12093             :             break;
   12094           0 :           case 'd':
   12095           0 :             printf ("    %s: %" PRId64 "\n", name, av->a_un.a_val);
   12096             :             break;
   12097             : 
   12098           4 :           case 'b':
   12099           4 :             printf ("    %s: %#" PRIx64 "  ", name, av->a_un.a_val);
   12100           4 :             GElf_Xword bit = 1;
   12101           4 :             const char *pfx = "<";
   12102         110 :             for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
   12103             :               {
   12104         106 :                 if (av->a_un.a_val & bit)
   12105             :                   {
   12106          77 :                     printf ("%s%s", pfx, p);
   12107          77 :                     pfx = " ";
   12108             :                   }
   12109         106 :                 bit <<= 1;
   12110             :               }
   12111           4 :             printf (">\n");
   12112             :             break;
   12113             : 
   12114           0 :           default:
   12115           0 :             abort ();
   12116             :           }
   12117             :     }
   12118           9 : }
   12119             : 
   12120             : static bool
   12121             : buf_has_data (unsigned char const *ptr, unsigned char const *end, size_t sz)
   12122             : {
   12123         195 :   return ptr < end && (size_t) (end - ptr) >= sz;
   12124             : }
   12125             : 
   12126             : static bool
   12127          18 : buf_read_int (Elf *core, unsigned char const **ptrp, unsigned char const *end,
   12128             :               int *retp)
   12129             : {
   12130          36 :   if (! buf_has_data (*ptrp, end, 4))
   12131             :     return false;
   12132             : 
   12133          18 :   *ptrp = convert (core, ELF_T_WORD, 1, retp, *ptrp, 4);
   12134          18 :   return true;
   12135             : }
   12136             : 
   12137             : static bool
   12138         177 : buf_read_ulong (Elf *core, unsigned char const **ptrp, unsigned char const *end,
   12139             :                 uint64_t *retp)
   12140             : {
   12141         177 :   size_t sz = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
   12142         354 :   if (! buf_has_data (*ptrp, end, sz))
   12143             :     return false;
   12144             : 
   12145         177 :   union
   12146             :   {
   12147             :     uint64_t u64;
   12148             :     uint32_t u32;
   12149             :   } u;
   12150             : 
   12151         177 :   *ptrp = convert (core, ELF_T_ADDR, 1, &u, *ptrp, sz);
   12152             : 
   12153         177 :   if (sz == 4)
   12154          93 :     *retp = u.u32;
   12155             :   else
   12156          84 :     *retp = u.u64;
   12157             :   return true;
   12158             : }
   12159             : 
   12160             : static void
   12161           6 : handle_siginfo_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
   12162             : {
   12163           6 :   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
   12164           6 :   if (data == NULL)
   12165           0 :     error (EXIT_FAILURE, 0,
   12166           0 :            gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   12167             : 
   12168           6 :   unsigned char const *ptr = data->d_buf;
   12169           6 :   unsigned char const *const end = data->d_buf + data->d_size;
   12170             : 
   12171             :   /* Siginfo head is three ints: signal number, error number, origin
   12172             :      code.  */
   12173           6 :   int si_signo, si_errno, si_code;
   12174           6 :   if (! buf_read_int (core, &ptr, end, &si_signo)
   12175           6 :       || ! buf_read_int (core, &ptr, end, &si_errno)
   12176           6 :       || ! buf_read_int (core, &ptr, end, &si_code))
   12177             :     {
   12178           0 :     fail:
   12179           0 :       printf ("    Not enough data in NT_SIGINFO note.\n");
   12180           0 :       return;
   12181             :     }
   12182             : 
   12183             :   /* Next is a pointer-aligned union of structures.  On 64-bit
   12184             :      machines, that implies a word of padding.  */
   12185           6 :   if (gelf_getclass (core) == ELFCLASS64)
   12186           3 :     ptr += 4;
   12187             : 
   12188           6 :   printf ("    si_signo: %d, si_errno: %d, si_code: %d\n",
   12189             :           si_signo, si_errno, si_code);
   12190             : 
   12191           6 :   if (si_code > 0)
   12192           6 :     switch (si_signo)
   12193             :       {
   12194           6 :       case CORE_SIGILL:
   12195             :       case CORE_SIGFPE:
   12196             :       case CORE_SIGSEGV:
   12197             :       case CORE_SIGBUS:
   12198             :         {
   12199           6 :           uint64_t addr;
   12200           6 :           if (! buf_read_ulong (core, &ptr, end, &addr))
   12201           0 :             goto fail;
   12202           6 :           printf ("    fault address: %#" PRIx64 "\n", addr);
   12203           6 :           break;
   12204             :         }
   12205             :       default:
   12206             :         ;
   12207             :       }
   12208           0 :   else if (si_code == CORE_SI_USER)
   12209             :     {
   12210           0 :       int pid, uid;
   12211           0 :       if (! buf_read_int (core, &ptr, end, &pid)
   12212           0 :           || ! buf_read_int (core, &ptr, end, &uid))
   12213           0 :         goto fail;
   12214           0 :       printf ("    sender PID: %d, sender UID: %d\n", pid, uid);
   12215             :     }
   12216             : }
   12217             : 
   12218             : static void
   12219           6 : handle_file_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
   12220             : {
   12221           6 :   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
   12222           6 :   if (data == NULL)
   12223           0 :     error (EXIT_FAILURE, 0,
   12224           0 :            gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   12225             : 
   12226           6 :   unsigned char const *ptr = data->d_buf;
   12227           6 :   unsigned char const *const end = data->d_buf + data->d_size;
   12228             : 
   12229           6 :   uint64_t count, page_size;
   12230           6 :   if (! buf_read_ulong (core, &ptr, end, &count)
   12231           6 :       || ! buf_read_ulong (core, &ptr, end, &page_size))
   12232             :     {
   12233           0 :     fail:
   12234           0 :       printf ("    Not enough data in NT_FILE note.\n");
   12235           0 :       return;
   12236             :     }
   12237             : 
   12238           6 :   size_t addrsize = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
   12239           6 :   uint64_t maxcount = (size_t) (end - ptr) / (3 * addrsize);
   12240           6 :   if (count > maxcount)
   12241             :     goto fail;
   12242             : 
   12243             :   /* Where file names are stored.  */
   12244           6 :   unsigned char const *const fstart = ptr + 3 * count * addrsize;
   12245           6 :   char const *fptr = (char *) fstart;
   12246             : 
   12247           6 :   printf ("    %" PRId64 " files:\n", count);
   12248          59 :   for (uint64_t i = 0; i < count; ++i)
   12249             :     {
   12250          53 :       uint64_t mstart, mend, moffset;
   12251          53 :       if (! buf_read_ulong (core, &ptr, fstart, &mstart)
   12252          53 :           || ! buf_read_ulong (core, &ptr, fstart, &mend)
   12253          53 :           || ! buf_read_ulong (core, &ptr, fstart, &moffset))
   12254           0 :         goto fail;
   12255             : 
   12256          53 :       const char *fnext = memchr (fptr, '\0', (char *) end - fptr);
   12257          53 :       if (fnext == NULL)
   12258             :         goto fail;
   12259             : 
   12260          53 :       int ct = printf ("      %08" PRIx64 "-%08" PRIx64
   12261             :                        " %08" PRIx64 " %" PRId64,
   12262             :                        mstart, mend, moffset * page_size, mend - mstart);
   12263          53 :       printf ("%*s%s\n", ct > 50 ? 3 : 53 - ct, "", fptr);
   12264             : 
   12265          53 :       fptr = fnext + 1;
   12266             :     }
   12267             : }
   12268             : 
   12269             : static void
   12270          38 : handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
   12271             :                   const char *name, const void *desc)
   12272             : {
   12273          38 :   GElf_Word regs_offset;
   12274          38 :   size_t nregloc;
   12275          38 :   const Ebl_Register_Location *reglocs;
   12276          38 :   size_t nitems;
   12277          38 :   const Ebl_Core_Item *items;
   12278             : 
   12279          38 :   if (! ebl_core_note (ebl, nhdr, name, desc,
   12280             :                        &regs_offset, &nregloc, &reglocs, &nitems, &items))
   12281           1 :     return;
   12282             : 
   12283             :   /* Pass 0 for DESCSZ when there are registers in the note,
   12284             :      so that the ITEMS array does not describe the whole thing.
   12285             :      For non-register notes, the actual descsz might be a multiple
   12286             :      of the unit size, not just exactly the unit size.  */
   12287          37 :   unsigned int colno = handle_core_items (ebl->elf, desc,
   12288          37 :                                           nregloc == 0 ? nhdr->n_descsz : 0,
   12289             :                                           items, nitems);
   12290          37 :   if (colno != 0)
   12291          34 :     putchar_unlocked ('\n');
   12292             : 
   12293          37 :   colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
   12294             :                                  reglocs, nregloc);
   12295          37 :   if (colno != 0)
   12296          18 :     putchar_unlocked ('\n');
   12297             : }
   12298             : 
   12299             : static void
   12300           0 : handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
   12301             :                    GElf_Off start, Elf_Data *data)
   12302             : {
   12303           0 :   fputs_unlocked (gettext ("  Owner          Data size  Type\n"), stdout);
   12304             : 
   12305           0 :   if (data == NULL)
   12306           0 :     goto bad_note;
   12307             : 
   12308             :   size_t offset = 0;
   12309             :   GElf_Nhdr nhdr;
   12310             :   size_t name_offset;
   12311             :   size_t desc_offset;
   12312           0 :   while (offset < data->d_size
   12313           0 :          && (offset = gelf_getnote (data, offset,
   12314             :                                     &nhdr, &name_offset, &desc_offset)) > 0)
   12315             :     {
   12316           0 :       const char *name = nhdr.n_namesz == 0 ? "" : data->d_buf + name_offset;
   12317           0 :       const char *desc = data->d_buf + desc_offset;
   12318             : 
   12319             :       /* GNU Build Attributes are weird, they store most of their data
   12320             :          into the owner name field.  Extract just the owner name
   12321             :          prefix here, then use the rest later as data.  */
   12322           0 :       bool is_gnu_build_attr
   12323           0 :         = strncmp (name, ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX,
   12324             :                    strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX)) == 0;
   12325           0 :       const char *print_name = (is_gnu_build_attr
   12326           0 :                                 ? ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX : name);
   12327           0 :       size_t print_namesz = (is_gnu_build_attr
   12328           0 :                              ? strlen (print_name) : nhdr.n_namesz);
   12329             : 
   12330           0 :       char buf[100];
   12331           0 :       char buf2[100];
   12332           0 :       printf (gettext ("  %-13.*s  %9" PRId32 "  %s\n"),
   12333             :               (int) print_namesz, print_name, nhdr.n_descsz,
   12334           0 :               ehdr->e_type == ET_CORE
   12335           0 :               ? ebl_core_note_type_name (ebl, nhdr.n_type,
   12336             :                                          buf, sizeof (buf))
   12337           0 :               : ebl_object_note_type_name (ebl, name, nhdr.n_type,
   12338             :                                            nhdr.n_descsz,
   12339             :                                            buf2, sizeof (buf2)));
   12340             : 
   12341             :       /* Filter out invalid entries.  */
   12342           0 :       if (memchr (name, '\0', nhdr.n_namesz) != NULL
   12343             :           /* XXX For now help broken Linux kernels.  */
   12344             :           || 1)
   12345             :         {
   12346           0 :           if (ehdr->e_type == ET_CORE)
   12347             :             {
   12348           0 :               if (nhdr.n_type == NT_AUXV
   12349           0 :                   && (nhdr.n_namesz == 4 /* Broken old Linux kernels.  */
   12350           0 :                       || (nhdr.n_namesz == 5 && name[4] == '\0'))
   12351           0 :                   && !memcmp (name, "CORE", 4))
   12352           0 :                 handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
   12353             :                                   start + desc_offset);
   12354           0 :               else if (nhdr.n_namesz == 5 && strcmp (name, "CORE") == 0)
   12355           0 :                 switch (nhdr.n_type)
   12356             :                   {
   12357           0 :                   case NT_SIGINFO:
   12358           0 :                     handle_siginfo_note (ebl->elf, nhdr.n_descsz,
   12359             :                                          start + desc_offset);
   12360           0 :                     break;
   12361             : 
   12362           0 :                   case NT_FILE:
   12363           0 :                     handle_file_note (ebl->elf, nhdr.n_descsz,
   12364             :                                       start + desc_offset);
   12365           0 :                     break;
   12366             : 
   12367           0 :                   default:
   12368           0 :                     handle_core_note (ebl, &nhdr, name, desc);
   12369             :                   }
   12370             :               else
   12371           0 :                 handle_core_note (ebl, &nhdr, name, desc);
   12372             :             }
   12373             :           else
   12374           0 :             ebl_object_note (ebl, nhdr.n_namesz, name, nhdr.n_type,
   12375             :                              nhdr.n_descsz, desc);
   12376             :         }
   12377             :     }
   12378             : 
   12379           0 :   if (offset == data->d_size)
   12380           0 :     return;
   12381             : 
   12382           0 :  bad_note:
   12383           0 :   error (0, 0,
   12384           0 :          gettext ("cannot get content of note: %s"),
   12385           0 :          data != NULL ? "garbage data" : elf_errmsg (-1));
   12386             : }
   12387             : 
   12388             : static void
   12389          62 : handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
   12390             : {
   12391             :   /* If we have section headers, just look for SHT_NOTE sections.
   12392             :      In a debuginfo file, the program headers are not reliable.  */
   12393          62 :   if (shnum != 0)
   12394             :     {
   12395             :       /* Get the section header string table index.  */
   12396          51 :       size_t shstrndx;
   12397          51 :       if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
   12398           0 :         error (EXIT_FAILURE, 0,
   12399           0 :                gettext ("cannot get section header string table index"));
   12400             : 
   12401             :       Elf_Scn *scn = NULL;
   12402        1213 :       while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   12403             :         {
   12404        1162 :           GElf_Shdr shdr_mem;
   12405        1162 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   12406             : 
   12407        1162 :           if (shdr == NULL || shdr->sh_type != SHT_NOTE)
   12408             :             /* Not what we are looking for.  */
   12409        1115 :             continue;
   12410             : 
   12411          47 :           printf (gettext ("\
   12412             : \nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
   12413             :                   elf_ndxscn (scn),
   12414          47 :                   elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   12415             :                   shdr->sh_size, shdr->sh_offset);
   12416             : 
   12417          47 :           handle_notes_data (ebl, ehdr, shdr->sh_offset,
   12418             :                              elf_getdata (scn, NULL));
   12419             :         }
   12420          51 :       return;
   12421             :     }
   12422             : 
   12423             :   /* We have to look through the program header to find the note
   12424             :      sections.  There can be more than one.  */
   12425         140 :   for (size_t cnt = 0; cnt < phnum; ++cnt)
   12426             :     {
   12427         129 :       GElf_Phdr mem;
   12428         129 :       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
   12429             : 
   12430         129 :       if (phdr == NULL || phdr->p_type != PT_NOTE)
   12431             :         /* Not what we are looking for.  */
   12432         117 :         continue;
   12433             : 
   12434          12 :       printf (gettext ("\
   12435             : \nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
   12436             :               phdr->p_filesz, phdr->p_offset);
   12437             : 
   12438          12 :       handle_notes_data (ebl, ehdr, phdr->p_offset,
   12439             :                          elf_getdata_rawchunk (ebl->elf,
   12440          12 :                                                phdr->p_offset, phdr->p_filesz,
   12441          12 :                                                (phdr->p_align == 8
   12442             :                                                 ? ELF_T_NHDR8 : ELF_T_NHDR)));
   12443             :     }
   12444             : }
   12445             : 
   12446             : 
   12447             : static void
   12448           5 : hex_dump (const uint8_t *data, size_t len)
   12449             : {
   12450           5 :   size_t pos = 0;
   12451          26 :   while (pos < len)
   12452             :     {
   12453          21 :       printf ("  0x%08zx ", pos);
   12454             : 
   12455          21 :       const size_t chunk = MIN (len - pos, 16);
   12456             : 
   12457         342 :       for (size_t i = 0; i < chunk; ++i)
   12458         321 :         if (i % 4 == 3)
   12459          80 :           printf ("%02x ", data[pos + i]);
   12460             :         else
   12461         241 :           printf ("%02x", data[pos + i]);
   12462             : 
   12463          21 :       if (chunk < 16)
   12464           1 :         printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
   12465             : 
   12466         342 :       for (size_t i = 0; i < chunk; ++i)
   12467             :         {
   12468         321 :           unsigned char b = data[pos + i];
   12469         321 :           printf ("%c", isprint (b) ? b : '.');
   12470             :         }
   12471             : 
   12472          21 :       putchar ('\n');
   12473          21 :       pos += chunk;
   12474             :     }
   12475           5 : }
   12476             : 
   12477             : static void
   12478           5 : dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
   12479             : {
   12480           5 :   if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
   12481           0 :     printf (gettext ("\nSection [%zu] '%s' has no data to dump.\n"),
   12482             :             elf_ndxscn (scn), name);
   12483             :   else
   12484             :     {
   12485           5 :       if (print_decompress)
   12486             :         {
   12487             :           /* We try to decompress the section, but keep the old shdr around
   12488             :              so we can show both the original shdr size and the uncompressed
   12489             :              data size.   */
   12490           4 :           if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
   12491             :             {
   12492           2 :               if (elf_compress (scn, 0, 0) < 0)
   12493           0 :                 printf ("WARNING: %s [%zd]\n",
   12494             :                         gettext ("Couldn't uncompress section"),
   12495             :                         elf_ndxscn (scn));
   12496             :             }
   12497           2 :           else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
   12498             :             {
   12499           2 :               if (elf_compress_gnu (scn, 0, 0) < 0)
   12500           0 :                 printf ("WARNING: %s [%zd]\n",
   12501             :                         gettext ("Couldn't uncompress section"),
   12502             :                         elf_ndxscn (scn));
   12503             :             }
   12504             :         }
   12505             : 
   12506           5 :       Elf_Data *data = elf_rawdata (scn, NULL);
   12507           5 :       if (data == NULL)
   12508           0 :         error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
   12509             :                elf_ndxscn (scn), name, elf_errmsg (-1));
   12510             :       else
   12511             :         {
   12512           5 :           if (data->d_size == shdr->sh_size)
   12513           1 :             printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
   12514             :                              " bytes at offset %#0" PRIx64 ":\n"),
   12515             :                     elf_ndxscn (scn), name,
   12516             :                     shdr->sh_size, shdr->sh_offset);
   12517             :           else
   12518           4 :             printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
   12519             :                              " bytes (%zd uncompressed) at offset %#0"
   12520             :                              PRIx64 ":\n"),
   12521             :                     elf_ndxscn (scn), name,
   12522             :                     shdr->sh_size, data->d_size, shdr->sh_offset);
   12523           5 :           hex_dump (data->d_buf, data->d_size);
   12524             :         }
   12525             :     }
   12526           5 : }
   12527             : 
   12528             : static void
   12529          93 : print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
   12530             : {
   12531          93 :   if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
   12532           0 :     printf (gettext ("\nSection [%zu] '%s' has no strings to dump.\n"),
   12533             :             elf_ndxscn (scn), name);
   12534             :   else
   12535             :     {
   12536          93 :       if (print_decompress)
   12537             :         {
   12538             :           /* We try to decompress the section, but keep the old shdr around
   12539             :              so we can show both the original shdr size and the uncompressed
   12540             :              data size.  */
   12541           1 :           if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
   12542             :             {
   12543           0 :               if (elf_compress (scn, 0, 0) < 0)
   12544           0 :                 printf ("WARNING: %s [%zd]\n",
   12545             :                         gettext ("Couldn't uncompress section"),
   12546             :                         elf_ndxscn (scn));
   12547             :             }
   12548           1 :           else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
   12549             :             {
   12550           1 :               if (elf_compress_gnu (scn, 0, 0) < 0)
   12551           0 :                 printf ("WARNING: %s [%zd]\n",
   12552             :                         gettext ("Couldn't uncompress section"),
   12553             :                         elf_ndxscn (scn));
   12554             :             }
   12555             :         }
   12556             : 
   12557          93 :       Elf_Data *data = elf_rawdata (scn, NULL);
   12558          93 :       if (data == NULL)
   12559           0 :         error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
   12560             :                elf_ndxscn (scn), name, elf_errmsg (-1));
   12561             :       else
   12562             :         {
   12563          93 :           if (data->d_size == shdr->sh_size)
   12564          92 :             printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
   12565             :                              " bytes at offset %#0" PRIx64 ":\n"),
   12566             :                     elf_ndxscn (scn), name,
   12567             :                     shdr->sh_size, shdr->sh_offset);
   12568             :           else
   12569           1 :             printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
   12570             :                              " bytes (%zd uncompressed) at offset %#0"
   12571             :                              PRIx64 ":\n"),
   12572             :                     elf_ndxscn (scn), name,
   12573             :                     shdr->sh_size, data->d_size, shdr->sh_offset);
   12574             : 
   12575          93 :           const char *start = data->d_buf;
   12576          93 :           const char *const limit = start + data->d_size;
   12577       16203 :           do
   12578             :             {
   12579       16203 :               const char *end = memchr (start, '\0', limit - start);
   12580       16203 :               const size_t pos = start - (const char *) data->d_buf;
   12581       16203 :               if (unlikely (end == NULL))
   12582             :                 {
   12583           0 :                   printf ("  [%6zx]- %.*s\n",
   12584             :                           pos, (int) (limit - start), start);
   12585             :                   break;
   12586             :                 }
   12587       16203 :               printf ("  [%6zx]  %s\n", pos, start);
   12588       16203 :               start = end + 1;
   12589       16203 :             } while (start < limit);
   12590             :         }
   12591             :     }
   12592          93 : }
   12593             : 
   12594             : static void
   12595          48 : for_each_section_argument (Elf *elf, const struct section_argument *list,
   12596             :                            void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
   12597             :                                          const char *name))
   12598             : {
   12599             :   /* Get the section header string table index.  */
   12600          48 :   size_t shstrndx;
   12601          48 :   if (elf_getshdrstrndx (elf, &shstrndx) < 0)
   12602           0 :     error (EXIT_FAILURE, 0,
   12603           0 :            gettext ("cannot get section header string table index"));
   12604             : 
   12605         180 :   for (const struct section_argument *a = list; a != NULL; a = a->next)
   12606             :     {
   12607         132 :       Elf_Scn *scn;
   12608         132 :       GElf_Shdr shdr_mem;
   12609         132 :       const char *name = NULL;
   12610             : 
   12611         132 :       char *endp = NULL;
   12612         132 :       unsigned long int shndx = strtoul (a->arg, &endp, 0);
   12613         132 :       if (endp != a->arg && *endp == '\0')
   12614             :         {
   12615           0 :           scn = elf_getscn (elf, shndx);
   12616           0 :           if (scn == NULL)
   12617             :             {
   12618           0 :               error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
   12619           0 :               continue;
   12620             :             }
   12621             : 
   12622           0 :           if (gelf_getshdr (scn, &shdr_mem) == NULL)
   12623           0 :             error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
   12624             :                    elf_errmsg (-1));
   12625           0 :           name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
   12626             :         }
   12627             :       else
   12628             :         {
   12629             :           /* Need to look up the section by name.  */
   12630             :           scn = NULL;
   12631             :           bool found = false;
   12632        3303 :           while ((scn = elf_nextscn (elf, scn)) != NULL)
   12633             :             {
   12634        3171 :               if (gelf_getshdr (scn, &shdr_mem) == NULL)
   12635             :                 continue;
   12636        3171 :               name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
   12637        3171 :               if (name == NULL)
   12638             :                 continue;
   12639        3171 :               if (!strcmp (name, a->arg))
   12640             :                 {
   12641          98 :                   found = true;
   12642          98 :                   (*dump) (scn, &shdr_mem, name);
   12643             :                 }
   12644             :             }
   12645             : 
   12646         132 :           if (unlikely (!found) && !a->implicit)
   12647           0 :             error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
   12648             :         }
   12649             :     }
   12650          48 : }
   12651             : 
   12652             : static void
   12653           0 : dump_data (Ebl *ebl)
   12654             : {
   12655           5 :   for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
   12656           0 : }
   12657             : 
   12658             : static void
   12659           0 : dump_strings (Ebl *ebl)
   12660             : {
   12661          43 :   for_each_section_argument (ebl->elf, string_sections, &print_string_section);
   12662           0 : }
   12663             : 
   12664             : static void
   12665           0 : print_strings (Ebl *ebl)
   12666             : {
   12667             :   /* Get the section header string table index.  */
   12668           0 :   size_t shstrndx;
   12669           0 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   12670           0 :     error (EXIT_FAILURE, 0,
   12671           0 :            gettext ("cannot get section header string table index"));
   12672             : 
   12673             :   Elf_Scn *scn;
   12674             :   GElf_Shdr shdr_mem;
   12675             :   const char *name;
   12676             :   scn = NULL;
   12677           0 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   12678             :     {
   12679           0 :       if (gelf_getshdr (scn, &shdr_mem) == NULL)
   12680           0 :         continue;
   12681             : 
   12682           0 :       if (shdr_mem.sh_type != SHT_PROGBITS
   12683           0 :           || !(shdr_mem.sh_flags & SHF_STRINGS))
   12684           0 :         continue;
   12685             : 
   12686           0 :       name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
   12687           0 :       if (name == NULL)
   12688           0 :         continue;
   12689             : 
   12690           0 :       print_string_section (scn, &shdr_mem, name);
   12691             :     }
   12692           0 : }
   12693             : 
   12694             : static void
   12695           2 : dump_archive_index (Elf *elf, const char *fname)
   12696             : {
   12697           2 :   size_t narsym;
   12698           2 :   const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
   12699           2 :   if (arsym == NULL)
   12700             :     {
   12701           0 :       int result = elf_errno ();
   12702           0 :       if (unlikely (result != ELF_E_NO_INDEX))
   12703           0 :         error (EXIT_FAILURE, 0,
   12704           0 :                gettext ("cannot get symbol index of archive '%s': %s"),
   12705             :                fname, elf_errmsg (result));
   12706             :       else
   12707           0 :         printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
   12708           0 :       return;
   12709             :     }
   12710             : 
   12711           2 :   printf (gettext ("\nIndex of archive '%s' has %zu entries:\n"),
   12712             :           fname, narsym);
   12713             : 
   12714           2 :   size_t as_off = 0;
   12715          11 :   for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
   12716             :     {
   12717           9 :       if (s->as_off != as_off)
   12718             :         {
   12719           6 :           as_off = s->as_off;
   12720             : 
   12721           6 :           Elf *subelf = NULL;
   12722           6 :           if (unlikely (elf_rand (elf, as_off) == 0)
   12723           6 :               || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
   12724             :                            == NULL))
   12725             : #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
   12726             :             while (1)
   12727             : #endif
   12728           0 :               error (EXIT_FAILURE, 0,
   12729           0 :                      gettext ("cannot extract member at offset %zu in '%s': %s"),
   12730             :                      as_off, fname, elf_errmsg (-1));
   12731             : 
   12732           6 :           const Elf_Arhdr *h = elf_getarhdr (subelf);
   12733             : 
   12734           6 :           printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
   12735             : 
   12736           6 :           elf_end (subelf);
   12737             :         }
   12738             : 
   12739           9 :       printf ("\t%s\n", s->as_name);
   12740             :     }
   12741             : }
   12742             : 
   12743             : #include "debugpred.h"

Generated by: LCOV version 1.13