LCOV - code coverage report
Current view: top level - src - readelf.c (source / functions) Hit Total Coverage
Test: elfutils-0.176 Lines: 3813 5505 69.3 %
Date: 2019-02-15 17:57:54 Functions: 121 129 93.8 %
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             : int
     316         285 : main (int argc, char *argv[])
     317             : {
     318             :   /* We use no threads here which can interfere with handling a stream.  */
     319         285 :   (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
     320             : 
     321             :   /* Set locale.  */
     322         285 :   setlocale (LC_ALL, "");
     323             : 
     324             :   /* Initialize the message catalog.  */
     325         285 :   textdomain (PACKAGE_TARNAME);
     326             : 
     327             :   /* Look up once.  */
     328         285 :   yes_str = gettext ("yes");
     329         285 :   no_str = gettext ("no");
     330             : 
     331             :   /* Parse and process arguments.  */
     332             :   int remaining;
     333         285 :   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
     334             : 
     335             :   /* Before we start tell the ELF library which version we are using.  */
     336         285 :   elf_version (EV_CURRENT);
     337             : 
     338             :   /* Now process all the files given at the command line.  */
     339         285 :   bool only_one = remaining + 1 == argc;
     340             :   do
     341             :     {
     342             :       /* Open the file.  */
     343         582 :       int fd = open (argv[remaining], O_RDONLY);
     344         291 :       if (fd == -1)
     345             :         {
     346           0 :           error (0, errno, gettext ("cannot open input file"));
     347           0 :           continue;
     348             :         }
     349             : 
     350         291 :       process_file (fd, argv[remaining], only_one);
     351             : 
     352         291 :       close (fd);
     353             :     }
     354         291 :   while (++remaining < argc);
     355             : 
     356         285 :   return error_message_count != 0;
     357             : }
     358             : 
     359             : 
     360             : /* Handle program arguments.  */
     361             : static error_t
     362        1775 : parse_opt (int key, char *arg,
     363             :            struct argp_state *state __attribute__ ((unused)))
     364             : {
     365         126 :   void add_dump_section (const char *name, bool implicit)
     366             :   {
     367         126 :     struct section_argument *a = xmalloc (sizeof *a);
     368         126 :     a->arg = name;
     369         126 :     a->next = NULL;
     370         126 :     a->implicit = implicit;
     371         126 :     struct section_argument ***tailp
     372         126 :       = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
     373         126 :     **tailp = a;
     374         126 :     *tailp = &a->next;
     375         126 :   }
     376             : 
     377        1775 :   switch (key)
     378             :     {
     379          40 :     case 'a':
     380          40 :       print_file_header = true;
     381          40 :       print_program_header = true;
     382          40 :       print_relocations = true;
     383          40 :       print_section_header = true;
     384          40 :       print_symbol_table = true;
     385          40 :       print_version_info = true;
     386          40 :       print_dynamic_table = true;
     387          40 :       print_section_groups = true;
     388          40 :       print_histogram = true;
     389          40 :       print_arch = true;
     390          40 :       print_notes = true;
     391          40 :       implicit_debug_sections |= section_exception;
     392          40 :       add_dump_section (".strtab", true);
     393          40 :       add_dump_section (".dynstr", true);
     394          40 :       add_dump_section (".comment", true);
     395          40 :       any_control_option = true;
     396          40 :       break;
     397           4 :     case 'A':
     398           4 :       print_arch = true;
     399           4 :       any_control_option = true;
     400           4 :       break;
     401           2 :     case 'd':
     402           2 :       print_dynamic_table = true;
     403           2 :       any_control_option = true;
     404           2 :       break;
     405           0 :     case 'e':
     406           0 :       print_debug_sections |= section_exception;
     407           0 :       any_control_option = true;
     408           0 :       break;
     409           9 :     case 'g':
     410           9 :       print_section_groups = true;
     411           9 :       any_control_option = true;
     412           9 :       break;
     413           0 :     case 'h':
     414           0 :       print_file_header = true;
     415           0 :       any_control_option = true;
     416           0 :       break;
     417           0 :     case 'I':
     418           0 :       print_histogram = true;
     419           0 :       any_control_option = true;
     420           0 :       break;
     421           0 :     case 'l':
     422           0 :       print_program_header = true;
     423           0 :       any_control_option = true;
     424           0 :       break;
     425          20 :     case 'n':
     426          20 :       print_notes = true;
     427          20 :       any_control_option = true;
     428          20 :       break;
     429           1 :     case 'r':
     430           1 :       print_relocations = true;
     431           1 :       any_control_option = true;
     432           1 :      break;
     433          88 :     case 'S':
     434          88 :       print_section_header = true;
     435          88 :       any_control_option = true;
     436          88 :       break;
     437          14 :     case 's':
     438          14 :       print_symbol_table = true;
     439          14 :       any_control_option = true;
     440          14 :       symbol_table_section = arg;
     441          14 :       break;
     442           0 :     case 'V':
     443           0 :       print_version_info = true;
     444           0 :       any_control_option = true;
     445           0 :       break;
     446           2 :     case 'c':
     447           2 :       print_archive_index = true;
     448           2 :       break;
     449         114 :     case 'w':
     450         114 :       if (arg == NULL)
     451             :         {
     452          39 :           print_debug_sections = section_all;
     453          39 :           implicit_debug_sections = section_info;
     454          39 :           show_split_units = true;
     455             :         }
     456          75 :       else if (strcmp (arg, "abbrev") == 0)
     457           0 :         print_debug_sections |= section_abbrev;
     458          75 :       else if (strcmp (arg, "addr") == 0)
     459             :         {
     460           2 :           print_debug_sections |= section_addr;
     461           2 :           implicit_debug_sections |= section_info;
     462             :         }
     463          73 :       else if (strcmp (arg, "aranges") == 0)
     464           3 :         print_debug_sections |= section_aranges;
     465          70 :       else if (strcmp (arg, "decodedaranges") == 0)
     466             :         {
     467           1 :           print_debug_sections |= section_aranges;
     468           1 :           decodedaranges = true;
     469             :         }
     470          69 :       else if (strcmp (arg, "ranges") == 0)
     471             :         {
     472          12 :           print_debug_sections |= section_ranges;
     473          12 :           implicit_debug_sections |= section_info;
     474             :         }
     475          57 :       else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
     476           2 :         print_debug_sections |= section_frame;
     477          55 :       else if (strcmp (arg, "info") == 0)
     478             :         {
     479          17 :           print_debug_sections |= section_info;
     480          17 :           print_debug_sections |= section_types;
     481             :         }
     482          38 :       else if (strcmp (arg, "info+") == 0)
     483             :         {
     484           2 :           print_debug_sections |= section_info;
     485           2 :           print_debug_sections |= section_types;
     486           2 :           show_split_units = true;
     487             :         }
     488          36 :       else if (strcmp (arg, "loc") == 0)
     489             :         {
     490          18 :           print_debug_sections |= section_loc;
     491          18 :           implicit_debug_sections |= section_info;
     492             :         }
     493          18 :       else if (strcmp (arg, "line") == 0)
     494           6 :         print_debug_sections |= section_line;
     495          12 :       else if (strcmp (arg, "decodedline") == 0)
     496             :         {
     497           4 :           print_debug_sections |= section_line;
     498           4 :           decodedline = true;
     499             :         }
     500           8 :       else if (strcmp (arg, "pubnames") == 0)
     501           0 :         print_debug_sections |= section_pubnames;
     502           8 :       else if (strcmp (arg, "str") == 0)
     503             :         {
     504           3 :           print_debug_sections |= section_str;
     505             :           /* For mapping string offset tables to CUs.  */
     506           3 :           implicit_debug_sections |= section_info;
     507             :         }
     508           5 :       else if (strcmp (arg, "macinfo") == 0)
     509           0 :         print_debug_sections |= section_macinfo;
     510           5 :       else if (strcmp (arg, "macro") == 0)
     511           3 :         print_debug_sections |= section_macro;
     512           2 :       else if (strcmp (arg, "exception") == 0)
     513           0 :         print_debug_sections |= section_exception;
     514           2 :       else if (strcmp (arg, "gdb_index") == 0)
     515           2 :         print_debug_sections |= section_gdb_index;
     516             :       else
     517             :         {
     518           0 :           fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
     519             :                    arg);
     520           0 :           argp_help (&argp, stderr, ARGP_HELP_SEE,
     521             :                      program_invocation_short_name);
     522           0 :           exit (1);
     523             :         }
     524         114 :       any_control_option = true;
     525         114 :       break;
     526           1 :     case 'p':
     527           1 :       any_control_option = true;
     528           1 :       if (arg == NULL)
     529             :         {
     530           0 :           print_string_sections = true;
     531           0 :           break;
     532             :         }
     533             :       FALLTHROUGH;
     534             :     case 'x':
     535           6 :       add_dump_section (arg, false);
     536           6 :       any_control_option = true;
     537           6 :       break;
     538           2 :     case 'N':
     539           2 :       print_address_names = false;
     540           2 :       break;
     541          26 :     case 'U':
     542          26 :       print_unresolved_addresses = true;
     543          26 :       break;
     544           0 :     case ARGP_KEY_NO_ARGS:
     545           0 :       fputs (gettext ("Missing file name.\n"), stderr);
     546           0 :       goto do_argp_help;
     547         285 :     case ARGP_KEY_FINI:
     548         285 :       if (! any_control_option && ! print_archive_index)
     549             :         {
     550           0 :           fputs (gettext ("No operation specified.\n"), stderr);
     551           0 :         do_argp_help:
     552           0 :           argp_help (&argp, stderr, ARGP_HELP_SEE,
     553             :                      program_invocation_short_name);
     554           0 :           exit (EXIT_FAILURE);
     555             :         }
     556             :       break;
     557             :     case 'W':                   /* Ignored.  */
     558             :       break;
     559          13 :     case 'z':
     560          13 :       print_decompress = true;
     561          13 :       break;
     562           4 :     case ELF_INPUT_SECTION:
     563           4 :       if (arg == NULL)
     564           4 :         elf_input_section = ".gnu_debugdata";
     565             :       else
     566           0 :         elf_input_section = arg;
     567             :       break;
     568           5 :     case DWARF_SKELETON:
     569           5 :       dwarf_skeleton = arg;
     570           5 :       break;
     571             :     default:
     572             :       return ARGP_ERR_UNKNOWN;
     573             :     }
     574             :   return 0;
     575             : }
     576             : 
     577             : 
     578             : /* Create a file descriptor to read the data from the
     579             :    elf_input_section given a file descriptor to an ELF file.  */
     580             : static int
     581           4 : open_input_section (int fd)
     582             : {
     583             :   size_t shnums;
     584             :   size_t cnt;
     585             :   size_t shstrndx;
     586           4 :   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
     587           4 :   if (elf == NULL)
     588             :     {
     589           0 :       error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
     590             :              elf_errmsg (-1));
     591           0 :       return -1;
     592             :     }
     593             : 
     594           4 :   if (elf_getshdrnum (elf, &shnums) < 0)
     595             :     {
     596           0 :       error (0, 0, gettext ("cannot determine number of sections: %s"),
     597             :              elf_errmsg (-1));
     598           0 :     open_error:
     599           0 :       elf_end (elf);
     600           0 :       return -1;
     601             :     }
     602             : 
     603           4 :   if (elf_getshdrstrndx (elf, &shstrndx) < 0)
     604             :     {
     605           0 :       error (0, 0, gettext ("cannot get section header string table index"));
     606             :       goto open_error;
     607             :     }
     608             : 
     609         178 :   for (cnt = 0; cnt < shnums; ++cnt)
     610             :     {
     611          91 :       Elf_Scn *scn = elf_getscn (elf, cnt);
     612          91 :       if (scn == NULL)
     613             :         {
     614           0 :           error (0, 0, gettext ("cannot get section: %s"),
     615             :                  elf_errmsg (-1));
     616           0 :           goto open_error;
     617             :         }
     618             : 
     619             :       GElf_Shdr shdr_mem;
     620          91 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
     621          91 :       if (unlikely (shdr == NULL))
     622             :         {
     623           0 :           error (0, 0, gettext ("cannot get section header: %s"),
     624             :                  elf_errmsg (-1));
     625             :           goto open_error;
     626             :         }
     627             : 
     628          91 :       const char *sname = elf_strptr (elf, shstrndx, shdr->sh_name);
     629          91 :       if (sname == NULL)
     630             :         {
     631           0 :           error (0, 0, gettext ("cannot get section name"));
     632             :           goto open_error;
     633             :         }
     634             : 
     635          91 :       if (strcmp (sname, elf_input_section) == 0)
     636             :         {
     637           4 :           Elf_Data *data = elf_rawdata (scn, NULL);
     638           4 :           if (data == NULL)
     639             :             {
     640           0 :               error (0, 0, gettext ("cannot get %s content: %s"),
     641             :                      sname, elf_errmsg (-1));
     642             :               goto open_error;
     643             :             }
     644             : 
     645             :           /* Create (and immediately unlink) a temporary file to store
     646             :              section data in to create a file descriptor for it.  */
     647           4 :           const char *tmpdir = getenv ("TMPDIR") ?: P_tmpdir;
     648             :           static const char suffix[] = "/readelfXXXXXX";
     649           4 :           int tmplen = strlen (tmpdir) + sizeof (suffix);
     650           4 :           char *tempname = alloca (tmplen);
     651           4 :           sprintf (tempname, "%s%s", tmpdir, suffix);
     652             : 
     653           4 :           int sfd = mkstemp (tempname);
     654           4 :           if (sfd == -1)
     655             :             {
     656           0 :               error (0, 0, gettext ("cannot create temp file '%s'"),
     657             :                      tempname);
     658             :               goto open_error;
     659             :             }
     660           4 :           unlink (tempname);
     661             : 
     662           4 :           ssize_t size = data->d_size;
     663           4 :           if (write_retry (sfd, data->d_buf, size) != size)
     664             :             {
     665           0 :               error (0, 0, gettext ("cannot write section data"));
     666             :               goto open_error;
     667             :             }
     668             : 
     669           4 :           if (elf_end (elf) != 0)
     670             :             {
     671           0 :               error (0, 0, gettext ("error while closing Elf descriptor: %s"),
     672             :                      elf_errmsg (-1));
     673           0 :               return -1;
     674             :             }
     675             : 
     676           4 :           if (lseek (sfd, 0, SEEK_SET) == -1)
     677             :             {
     678           0 :               error (0, 0, gettext ("error while rewinding file descriptor"));
     679           0 :               return -1;
     680             :             }
     681             : 
     682             :           return sfd;
     683             :         }
     684             :     }
     685             : 
     686             :   /* Named section not found.  */
     687           0 :   if (elf_end (elf) != 0)
     688           0 :     error (0, 0, gettext ("error while closing Elf descriptor: %s"),
     689             :            elf_errmsg (-1));
     690             :   return -1;
     691             : }
     692             : 
     693             : /* Check if the file is an archive, and if so dump its index.  */
     694             : static void
     695           2 : check_archive_index (int fd, const char *fname, bool only_one)
     696             : {
     697             :   /* Create an `Elf' descriptor.  */
     698           2 :   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
     699           2 :   if (elf == NULL)
     700           0 :     error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
     701             :            elf_errmsg (-1));
     702             :   else
     703             :     {
     704           2 :       if (elf_kind (elf) == ELF_K_AR)
     705             :         {
     706           2 :           if (!only_one)
     707             :             printf ("\n%s:\n\n", fname);
     708           2 :           dump_archive_index (elf, fname);
     709             :         }
     710             :       else
     711             :         error (0, 0,
     712           0 :                gettext ("'%s' is not an archive, cannot print archive index"),
     713             :                fname);
     714             : 
     715             :       /* Now we can close the descriptor.  */
     716           2 :       if (elf_end (elf) != 0)
     717           0 :         error (0, 0, gettext ("error while closing Elf descriptor: %s"),
     718             :                elf_errmsg (-1));
     719             :     }
     720           2 : }
     721             : 
     722             : /* Trivial callback used for checking if we opened an archive.  */
     723             : static int
     724         277 : count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
     725             :                void **userdata __attribute__ ((unused)),
     726             :                const char *name __attribute__ ((unused)),
     727             :                Dwarf_Addr base __attribute__ ((unused)),
     728             :                void *arg)
     729             : {
     730         277 :   if (*(bool *) arg)
     731             :     return DWARF_CB_ABORT;
     732         277 :   *(bool *) arg = true;
     733         277 :   return DWARF_CB_OK;
     734             : }
     735             : 
     736             : struct process_dwflmod_args
     737             : {
     738             :   int fd;
     739             :   bool only_one;
     740             : };
     741             : 
     742             : static int
     743         289 : process_dwflmod (Dwfl_Module *dwflmod,
     744             :                  void **userdata __attribute__ ((unused)),
     745             :                  const char *name __attribute__ ((unused)),
     746             :                  Dwarf_Addr base __attribute__ ((unused)),
     747             :                  void *arg)
     748             : {
     749         289 :   const struct process_dwflmod_args *a = arg;
     750             : 
     751             :   /* Print the file name.  */
     752         289 :   if (!a->only_one)
     753             :     {
     754             :       const char *fname;
     755          12 :       dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
     756             : 
     757          24 :       printf ("\n%s:\n\n", fname);
     758             :     }
     759             : 
     760         289 :   process_elf_file (dwflmod, a->fd);
     761             : 
     762         289 :   return DWARF_CB_OK;
     763             : }
     764             : 
     765             : /* Stub libdwfl callback, only the ELF handle already open is ever used.
     766             :    Only used for finding the alternate debug file if the Dwarf comes from
     767             :    the main file.  We are not interested in separate debuginfo.  */
     768             : static int
     769          35 : find_no_debuginfo (Dwfl_Module *mod,
     770             :                    void **userdata,
     771             :                    const char *modname,
     772             :                    Dwarf_Addr base,
     773             :                    const char *file_name,
     774             :                    const char *debuglink_file,
     775             :                    GElf_Word debuglink_crc,
     776             :                    char **debuginfo_file_name)
     777             : {
     778             :   Dwarf_Addr dwbias;
     779          35 :   dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
     780             : 
     781             :   /* We are only interested if the Dwarf has been setup on the main
     782             :      elf file but is only missing the alternate debug link.  If dwbias
     783             :      hasn't even been setup, this is searching for separate debuginfo
     784             :      for the main elf.  We don't care in that case.  */
     785          35 :   if (dwbias == (Dwarf_Addr) -1)
     786             :     return -1;
     787             : 
     788           5 :   return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
     789             :                                        file_name, debuglink_file,
     790             :                                        debuglink_crc, debuginfo_file_name);
     791             : }
     792             : 
     793             : static Dwfl *
     794         298 : create_dwfl (int fd, const char *fname)
     795             : {
     796             :   /* Duplicate an fd for dwfl_report_offline to swallow.  */
     797         298 :   int dwfl_fd = dup (fd);
     798         298 :   if (unlikely (dwfl_fd < 0))
     799           0 :     error (EXIT_FAILURE, errno, "dup");
     800             : 
     801             :   /* Use libdwfl in a trivial way to open the libdw handle for us.
     802             :      This takes care of applying relocations to DWARF data in ET_REL files.  */
     803             :   static const Dwfl_Callbacks callbacks =
     804             :     {
     805             :       .section_address = dwfl_offline_section_address,
     806             :       .find_debuginfo = find_no_debuginfo
     807             :     };
     808         298 :   Dwfl *dwfl = dwfl_begin (&callbacks);
     809         298 :   if (likely (dwfl != NULL))
     810             :     /* Let 0 be the logical address of the file (or first in archive).  */
     811         298 :     dwfl->offline_next_address = 0;
     812         298 :   if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
     813             :     {
     814             :       struct stat st;
     815           0 :       if (fstat (dwfl_fd, &st) != 0)
     816           0 :         error (0, errno, gettext ("cannot stat input file"));
     817           0 :       else if (unlikely (st.st_size == 0))
     818           0 :         error (0, 0, gettext ("input file is empty"));
     819             :       else
     820           0 :         error (0, 0, gettext ("failed reading '%s': %s"),
     821             :                fname, dwfl_errmsg (-1));
     822           0 :       close (dwfl_fd);          /* Consumed on success, not on failure.  */
     823           0 :       dwfl = NULL;
     824             :     }
     825             :   else
     826         298 :     dwfl_report_end (dwfl, NULL, NULL);
     827             : 
     828         298 :   return dwfl;
     829             : }
     830             : 
     831             : /* Process one input file.  */
     832             : static void
     833         291 : process_file (int fd, const char *fname, bool only_one)
     834             : {
     835         291 :   if (print_archive_index)
     836           2 :     check_archive_index (fd, fname, only_one);
     837             : 
     838         291 :   if (!any_control_option)
     839             :     return;
     840             : 
     841         289 :   if (elf_input_section != NULL)
     842             :     {
     843             :       /* Replace fname and fd with section content. */
     844           4 :       char *fnname = alloca (strlen (fname) + strlen (elf_input_section) + 2);
     845           8 :       sprintf (fnname, "%s:%s", fname, elf_input_section);
     846           4 :       fd = open_input_section (fd);
     847           4 :       if (fd == -1)
     848             :         {
     849           0 :           error (0, 0, gettext ("No such section '%s' in '%s'"),
     850             :                  elf_input_section, fname);
     851             :           return;
     852             :         }
     853             :       fname = fnname;
     854             :     }
     855             : 
     856         289 :   Dwfl *dwfl = create_dwfl (fd, fname);
     857         289 :   if (dwfl != NULL)
     858             :     {
     859         289 :       if (only_one)
     860             :         {
     861             :           /* Clear ONLY_ONE if we have multiple modules, from an archive.  */
     862         277 :           bool seen = false;
     863         277 :           only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
     864             :         }
     865             : 
     866             :       /* Process the one or more modules gleaned from this file.  */
     867         289 :       struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
     868         289 :       dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
     869             :     }
     870             :   /* Terrible hack for hooking unrelated skeleton/split compile units,
     871             :      see __libdw_link_skel_split in print_debug.  */
     872         289 :   if (! do_not_close_dwfl)
     873         289 :     dwfl_end (dwfl);
     874             : 
     875             :   /* Need to close the replaced fd if we created it.  Caller takes
     876             :      care of original.  */
     877         289 :   if (elf_input_section != NULL)
     878           4 :     close (fd);
     879             : }
     880             : 
     881             : /* Check whether there are any compressed sections in the ELF file.  */
     882             : static bool
     883          95 : elf_contains_chdrs (Elf *elf)
     884             : {
     885          95 :   Elf_Scn *scn = NULL;
     886      788827 :   while ((scn = elf_nextscn (elf, scn)) != NULL)
     887             :     {
     888             :       GElf_Shdr shdr_mem;
     889      788643 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
     890      788643 :       if (shdr != NULL && (shdr->sh_flags & SHF_COMPRESSED) != 0)
     891           6 :         return true;
     892             :     }
     893             :   return false;
     894             : }
     895             : 
     896             : /* Process one ELF file.  */
     897             : static void
     898         289 : process_elf_file (Dwfl_Module *dwflmod, int fd)
     899             : {
     900             :   GElf_Addr dwflbias;
     901         289 :   Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
     902             : 
     903             :   GElf_Ehdr ehdr_mem;
     904         289 :   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
     905             : 
     906         289 :   if (ehdr == NULL)
     907             :     {
     908           0 :       error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
     909           0 :       return;
     910             :     }
     911             : 
     912         289 :   Ebl *ebl = ebl_openbackend (elf);
     913         289 :   if (unlikely (ebl == NULL))
     914             :     {
     915           0 :     ebl_error:
     916           0 :       error (0, errno, gettext ("cannot create EBL handle"));
     917             :       return;
     918             :     }
     919             : 
     920             :   /* Determine the number of sections.  */
     921         289 :   if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
     922           0 :     error (EXIT_FAILURE, 0,
     923           0 :            gettext ("cannot determine number of sections: %s"),
     924             :            elf_errmsg (-1));
     925             : 
     926             :   /* Determine the number of phdrs.  */
     927         289 :   if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
     928           0 :     error (EXIT_FAILURE, 0,
     929           0 :            gettext ("cannot determine number of program headers: %s"),
     930             :            elf_errmsg (-1));
     931             : 
     932             :   /* For an ET_REL file, libdwfl has adjusted the in-core shdrs and
     933             :      may have applied relocation to some sections.  If there are any
     934             :      compressed sections, any pass (or libdw/libdwfl) might have
     935             :      uncompressed them.  So we need to get a fresh Elf handle on the
     936             :      file to display those.  */
     937         578 :   bool print_unchanged = ((print_section_header
     938         161 :                            || print_relocations
     939         160 :                            || dump_data_sections != NULL
     940         155 :                            || print_notes)
     941         443 :                           && (ehdr->e_type == ET_REL
     942          95 :                               || elf_contains_chdrs (ebl->elf)));
     943             : 
     944         289 :   Elf *pure_elf = NULL;
     945         289 :   Ebl *pure_ebl = ebl;
     946         289 :   if (print_unchanged)
     947             :     {
     948             :       /* Read the file afresh.  */
     949          65 :       off_t aroff = elf_getaroff (elf);
     950          65 :       pure_elf = dwelf_elf_begin (fd);
     951          65 :       if (aroff > 0)
     952             :         {
     953             :           /* Archive member.  */
     954           0 :           (void) elf_rand (pure_elf, aroff);
     955           0 :           Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
     956           0 :           elf_end (pure_elf);
     957           0 :           pure_elf = armem;
     958             :         }
     959          65 :       if (pure_elf == NULL)
     960             :         {
     961           0 :           error (0, 0, gettext ("cannot read ELF: %s"), elf_errmsg (-1));
     962             :           return;
     963             :         }
     964          65 :       pure_ebl = ebl_openbackend (pure_elf);
     965          65 :       if (pure_ebl == NULL)
     966             :         goto ebl_error;
     967             :     }
     968             : 
     969         289 :   if (print_file_header)
     970          40 :     print_ehdr (ebl, ehdr);
     971         289 :   if (print_section_header)
     972         128 :     print_shdr (pure_ebl, ehdr);
     973         289 :   if (print_program_header)
     974          40 :     print_phdr (ebl, ehdr);
     975         289 :   if (print_section_groups)
     976          49 :     print_scngrp (ebl);
     977         289 :   if (print_dynamic_table)
     978          42 :     print_dynamic (ebl);
     979         289 :   if (print_relocations)
     980          41 :     print_relocs (pure_ebl, ehdr);
     981         289 :   if (print_histogram)
     982          40 :     handle_hash (ebl);
     983         289 :   if (print_symbol_table)
     984          54 :     print_symtab (ebl, SHT_DYNSYM);
     985         289 :   if (print_version_info)
     986          40 :     print_verinfo (ebl);
     987         289 :   if (print_symbol_table)
     988          54 :     print_symtab (ebl, SHT_SYMTAB);
     989         289 :   if (print_arch)
     990          44 :     print_liblist (ebl);
     991         289 :   if (print_arch)
     992          44 :     print_attributes (ebl, ehdr);
     993         289 :   if (dump_data_sections != NULL)
     994           5 :     dump_data (pure_ebl);
     995         289 :   if (string_sections != NULL)
     996          41 :     dump_strings (ebl);
     997         289 :   if ((print_debug_sections | implicit_debug_sections) != 0)
     998         145 :     print_debug (dwflmod, ebl, ehdr);
     999         289 :   if (print_notes)
    1000          60 :     handle_notes (pure_ebl, ehdr);
    1001         289 :   if (print_string_sections)
    1002           0 :     print_strings (ebl);
    1003             : 
    1004         289 :   ebl_closebackend (ebl);
    1005             : 
    1006         289 :   if (pure_ebl != ebl)
    1007             :     {
    1008          65 :       ebl_closebackend (pure_ebl);
    1009          65 :       elf_end (pure_elf);
    1010             :     }
    1011             : }
    1012             : 
    1013             : 
    1014             : /* Print file type.  */
    1015             : static void
    1016          40 : print_file_type (unsigned short int e_type)
    1017             : {
    1018          40 :   if (likely (e_type <= ET_CORE))
    1019             :     {
    1020             :       static const char *const knowntypes[] =
    1021             :       {
    1022             :         N_("NONE (None)"),
    1023             :         N_("REL (Relocatable file)"),
    1024             :         N_("EXEC (Executable file)"),
    1025             :         N_("DYN (Shared object file)"),
    1026             :         N_("CORE (Core file)")
    1027             :       };
    1028          40 :       puts (gettext (knowntypes[e_type]));
    1029             :     }
    1030           0 :   else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
    1031           0 :     printf (gettext ("OS Specific: (%x)\n"),  e_type);
    1032           0 :   else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
    1033           0 :     printf (gettext ("Processor Specific: (%x)\n"),  e_type);
    1034             :   else
    1035           0 :     puts ("???");
    1036          40 : }
    1037             : 
    1038             : 
    1039             : /* Print ELF header.  */
    1040             : static void
    1041          40 : print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
    1042             : {
    1043          40 :   fputs_unlocked (gettext ("ELF Header:\n  Magic:  "), stdout);
    1044         680 :   for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
    1045        1280 :     printf (" %02hhx", ehdr->e_ident[cnt]);
    1046             : 
    1047         120 :   printf (gettext ("\n  Class:                             %s\n"),
    1048          40 :           ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
    1049             :           : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
    1050          34 :           : "\?\?\?");
    1051             : 
    1052         120 :   printf (gettext ("  Data:                              %s\n"),
    1053          40 :           ehdr->e_ident[EI_DATA] == ELFDATA2LSB
    1054             :           ? "2's complement, little endian"
    1055             :           : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
    1056          12 :           ? "2's complement, big endian" : "\?\?\?");
    1057             : 
    1058         120 :   printf (gettext ("  Ident Version:                     %hhd %s\n"),
    1059          40 :           ehdr->e_ident[EI_VERSION],
    1060          40 :           ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
    1061             :           : "(\?\?\?)");
    1062             : 
    1063             :   char buf[512];
    1064          80 :   printf (gettext ("  OS/ABI:                            %s\n"),
    1065          40 :           ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
    1066             : 
    1067          80 :   printf (gettext ("  ABI Version:                       %hhd\n"),
    1068          40 :           ehdr->e_ident[EI_ABIVERSION]);
    1069             : 
    1070          40 :   fputs_unlocked (gettext ("  Type:                              "), stdout);
    1071          40 :   print_file_type (ehdr->e_type);
    1072             : 
    1073          80 :   printf (gettext ("  Machine:                           %s\n"), ebl->name);
    1074             : 
    1075          80 :   printf (gettext ("  Version:                           %d %s\n"),
    1076             :           ehdr->e_version,
    1077          40 :           ehdr->e_version  == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
    1078             : 
    1079          80 :   printf (gettext ("  Entry point address:               %#" PRIx64 "\n"),
    1080             :           ehdr->e_entry);
    1081             : 
    1082          80 :   printf (gettext ("  Start of program headers:          %" PRId64 " %s\n"),
    1083             :           ehdr->e_phoff, gettext ("(bytes into file)"));
    1084             : 
    1085          80 :   printf (gettext ("  Start of section headers:          %" PRId64 " %s\n"),
    1086             :           ehdr->e_shoff, gettext ("(bytes into file)"));
    1087             : 
    1088          80 :   printf (gettext ("  Flags:                             %s\n"),
    1089             :           ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
    1090             : 
    1091         120 :   printf (gettext ("  Size of this header:               %" PRId16 " %s\n"),
    1092          40 :           ehdr->e_ehsize, gettext ("(bytes)"));
    1093             : 
    1094         120 :   printf (gettext ("  Size of program header entries:    %" PRId16 " %s\n"),
    1095          40 :           ehdr->e_phentsize, gettext ("(bytes)"));
    1096             : 
    1097          80 :   printf (gettext ("  Number of program headers entries: %" PRId16),
    1098          40 :           ehdr->e_phnum);
    1099          40 :   if (ehdr->e_phnum == PN_XNUM)
    1100             :     {
    1101             :       GElf_Shdr shdr_mem;
    1102           0 :       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
    1103           0 :       if (shdr != NULL)
    1104           0 :         printf (gettext (" (%" PRIu32 " in [0].sh_info)"),
    1105           0 :                 (uint32_t) shdr->sh_info);
    1106             :       else
    1107           0 :         fputs_unlocked (gettext (" ([0] not available)"), stdout);
    1108             :     }
    1109          80 :   fputc_unlocked ('\n', stdout);
    1110             : 
    1111         120 :   printf (gettext ("  Size of section header entries:    %" PRId16 " %s\n"),
    1112          40 :           ehdr->e_shentsize, gettext ("(bytes)"));
    1113             : 
    1114          80 :   printf (gettext ("  Number of section headers entries: %" PRId16),
    1115          40 :           ehdr->e_shnum);
    1116          40 :   if (ehdr->e_shnum == 0)
    1117             :     {
    1118             :       GElf_Shdr shdr_mem;
    1119           0 :       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
    1120           0 :       if (shdr != NULL)
    1121           0 :         printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
    1122           0 :                 (uint32_t) shdr->sh_size);
    1123             :       else
    1124           0 :         fputs_unlocked (gettext (" ([0] not available)"), stdout);
    1125             :     }
    1126          80 :   fputc_unlocked ('\n', stdout);
    1127             : 
    1128          40 :   if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
    1129             :     {
    1130             :       GElf_Shdr shdr_mem;
    1131           0 :       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
    1132           0 :       if (shdr != NULL)
    1133             :         /* We managed to get the zeroth section.  */
    1134           0 :         snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
    1135           0 :                   (uint32_t) shdr->sh_link);
    1136             :       else
    1137             :         {
    1138           0 :           strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
    1139           0 :           buf[sizeof (buf) - 1] = '\0';
    1140             :         }
    1141             : 
    1142           0 :       printf (gettext ("  Section header string table index: XINDEX%s\n\n"),
    1143             :               buf);
    1144             :     }
    1145             :   else
    1146          40 :     printf (gettext ("  Section header string table index: %" PRId16 "\n\n"),
    1147             :             ehdr->e_shstrndx);
    1148          40 : }
    1149             : 
    1150             : 
    1151             : static const char *
    1152             : get_visibility_type (int value)
    1153             : {
    1154       14879 :   switch (value)
    1155             :     {
    1156             :     case STV_DEFAULT:
    1157             :       return "DEFAULT";
    1158           0 :     case STV_INTERNAL:
    1159             :       return "INTERNAL";
    1160          76 :     case STV_HIDDEN:
    1161             :       return "HIDDEN";
    1162           0 :     case STV_PROTECTED:
    1163             :       return "PROTECTED";
    1164           0 :     default:
    1165             :       return "???";
    1166             :     }
    1167             : }
    1168             : 
    1169             : static const char *
    1170             : elf_ch_type_name (unsigned int code)
    1171             : {
    1172          12 :   if (code == 0)
    1173             :     return "NONE";
    1174             : 
    1175          12 :   if (code == ELFCOMPRESS_ZLIB)
    1176             :     return "ZLIB";
    1177             : 
    1178             :   return "UNKNOWN";
    1179             : }
    1180             : 
    1181             : /* Print the section headers.  */
    1182             : static void
    1183         128 : print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
    1184             : {
    1185             :   size_t cnt;
    1186             :   size_t shstrndx;
    1187             : 
    1188         128 :   if (! print_file_header)
    1189             :     {
    1190             :       size_t sections;
    1191          88 :       if (unlikely (elf_getshdrnum (ebl->elf, &sections) < 0))
    1192           0 :         error (EXIT_FAILURE, 0,
    1193           0 :                gettext ("cannot get number of sections: %s"),
    1194             :                elf_errmsg (-1));
    1195             : 
    1196         176 :       printf (gettext ("\
    1197             : There are %zd section headers, starting at offset %#" PRIx64 ":\n\
    1198             : \n"),
    1199             :               sections, ehdr->e_shoff);
    1200             :     }
    1201             : 
    1202             :   /* Get the section header string table index.  */
    1203         128 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    1204           0 :     error (EXIT_FAILURE, 0,
    1205           0 :            gettext ("cannot get section header string table index: %s"),
    1206             :            elf_errmsg (-1));
    1207             : 
    1208         128 :   puts (gettext ("Section Headers:"));
    1209             : 
    1210         128 :   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
    1211          52 :     puts (gettext ("[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al"));
    1212             :   else
    1213          76 :     puts (gettext ("[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al"));
    1214             : 
    1215         128 :   if (print_decompress)
    1216             :     {
    1217           8 :       if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
    1218           4 :         puts (gettext ("     [Compression  Size   Al]"));
    1219             :       else
    1220           4 :         puts (gettext ("     [Compression  Size     Al]"));
    1221             :     }
    1222             : 
    1223     1576044 :   for (cnt = 0; cnt < shnum; ++cnt)
    1224             :     {
    1225     1576044 :       Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
    1226             : 
    1227     1576044 :       if (unlikely (scn == NULL))
    1228           0 :         error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
    1229             :                elf_errmsg (-1));
    1230             : 
    1231             :       /* Get the section header.  */
    1232             :       GElf_Shdr shdr_mem;
    1233     1576044 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1234     1576044 :       if (unlikely (shdr == NULL))
    1235           0 :         error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
    1236             :                elf_errmsg (-1));
    1237             : 
    1238             :       char flagbuf[20];
    1239     1576044 :       char *cp = flagbuf;
    1240     1576044 :       if (shdr->sh_flags & SHF_WRITE)
    1241         724 :         *cp++ = 'W';
    1242     1576044 :       if (shdr->sh_flags & SHF_ALLOC)
    1243        1975 :         *cp++ = 'A';
    1244     1576044 :       if (shdr->sh_flags & SHF_EXECINSTR)
    1245         371 :         *cp++ = 'X';
    1246     1576044 :       if (shdr->sh_flags & SHF_MERGE)
    1247         132 :         *cp++ = 'M';
    1248     1576044 :       if (shdr->sh_flags & SHF_STRINGS)
    1249         128 :         *cp++ = 'S';
    1250     1576044 :       if (shdr->sh_flags & SHF_INFO_LINK)
    1251         138 :         *cp++ = 'I';
    1252     1576044 :       if (shdr->sh_flags & SHF_LINK_ORDER)
    1253           2 :         *cp++ = 'L';
    1254     1576044 :       if (shdr->sh_flags & SHF_OS_NONCONFORMING)
    1255           0 :         *cp++ = 'N';
    1256     1576044 :       if (shdr->sh_flags & SHF_GROUP)
    1257           0 :         *cp++ = 'G';
    1258     1576044 :       if (shdr->sh_flags & SHF_TLS)
    1259           8 :         *cp++ = 'T';
    1260     1576044 :       if (shdr->sh_flags & SHF_COMPRESSED)
    1261          12 :         *cp++ = 'C';
    1262     1576044 :       if (shdr->sh_flags & SHF_ORDERED)
    1263           0 :         *cp++ = 'O';
    1264     1576044 :       if (shdr->sh_flags & SHF_EXCLUDE)
    1265           0 :         *cp++ = 'E';
    1266     1576044 :       *cp = '\0';
    1267             : 
    1268             :       const char *sname;
    1269             :       char buf[128];
    1270     1576044 :       sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "<corrupt>";
    1271     6304176 :       printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
    1272             :               " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
    1273             :               " %2" PRId64 "\n",
    1274             :               cnt, sname,
    1275     1576044 :               ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
    1276             :               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
    1277             :               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
    1278     1576044 :               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
    1279             :               shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
    1280             :               shdr->sh_addralign);
    1281             : 
    1282     1576044 :       if (print_decompress)
    1283             :         {
    1284          76 :           if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
    1285             :             {
    1286             :               GElf_Chdr chdr;
    1287          12 :               if (gelf_getchdr (scn, &chdr) != NULL)
    1288          36 :                 printf ("     [ELF %s (%" PRId32 ") %0*" PRIx64
    1289             :                         " %2" PRId64 "]\n",
    1290             :                         elf_ch_type_name (chdr.ch_type),
    1291             :                         chdr.ch_type,
    1292          12 :                         ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8,
    1293             :                         chdr.ch_size, chdr.ch_addralign);
    1294             :               else
    1295           0 :                 error (0, 0,
    1296           0 :                        gettext ("bad compression header for section %zd: %s"),
    1297             :                        elf_ndxscn (scn), elf_errmsg (-1));
    1298             :             }
    1299          64 :           else if (strncmp(".zdebug", sname, strlen (".zdebug")) == 0)
    1300             :             {
    1301             :               ssize_t size;
    1302          12 :               if ((size = dwelf_scn_gnu_compressed_size (scn)) >= 0)
    1303          12 :                 printf ("     [GNU ZLIB     %0*zx   ]\n",
    1304          12 :                         ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, size);
    1305             :               else
    1306           0 :                 error (0, 0,
    1307           0 :                        gettext ("bad gnu compressed size for section %zd: %s"),
    1308             :                        elf_ndxscn (scn), elf_errmsg (-1));
    1309             :             }
    1310             :         }
    1311             :     }
    1312             : 
    1313         256 :   fputc_unlocked ('\n', stdout);
    1314         128 : }
    1315             : 
    1316             : 
    1317             : /* Print the program header.  */
    1318             : static void
    1319          40 : print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
    1320             : {
    1321          40 :   if (phnum == 0)
    1322             :     /* No program header, this is OK in relocatable objects.  */
    1323          30 :     return;
    1324             : 
    1325          10 :   puts (gettext ("Program Headers:"));
    1326          10 :   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
    1327           0 :     puts (gettext ("\
    1328             :   Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"));
    1329             :   else
    1330          10 :     puts (gettext ("\
    1331             :   Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align"));
    1332             : 
    1333             :   /* Process all program headers.  */
    1334             :   bool has_relro = false;
    1335             :   GElf_Addr relro_from = 0;
    1336             :   GElf_Addr relro_to = 0;
    1337         110 :   for (size_t cnt = 0; cnt < phnum; ++cnt)
    1338             :     {
    1339             :       char buf[128];
    1340             :       GElf_Phdr mem;
    1341         110 :       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
    1342             : 
    1343             :       /* If for some reason the header cannot be returned show this.  */
    1344         110 :       if (unlikely (phdr == NULL))
    1345             :         {
    1346           0 :           puts ("  ???");
    1347           0 :           continue;
    1348             :         }
    1349             : 
    1350         770 :       printf ("  %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
    1351             :               " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
    1352         110 :               ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
    1353             :               phdr->p_offset,
    1354             :               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
    1355         110 :               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
    1356             :               phdr->p_filesz,
    1357             :               phdr->p_memsz,
    1358         110 :               phdr->p_flags & PF_R ? 'R' : ' ',
    1359         110 :               phdr->p_flags & PF_W ? 'W' : ' ',
    1360         110 :               phdr->p_flags & PF_X ? 'E' : ' ',
    1361             :               phdr->p_align);
    1362             : 
    1363         110 :       if (phdr->p_type == PT_INTERP)
    1364             :         {
    1365             :           /* If we are sure the file offset is valid then we can show
    1366             :              the user the name of the interpreter.  We check whether
    1367             :              there is a section at the file offset.  Normally there
    1368             :              would be a section called ".interp".  But in separate
    1369             :              .debug files it is a NOBITS section (and so doesn't match
    1370             :              with gelf_offscn).  Which probably means the offset is
    1371             :              not valid another reason could be because the ELF file
    1372             :              just doesn't contain any section headers, in that case
    1373             :              just play it safe and don't display anything.  */
    1374             : 
    1375           6 :           Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
    1376             :           GElf_Shdr shdr_mem;
    1377           6 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1378             : 
    1379             :           size_t maxsize;
    1380           6 :           char *filedata = elf_rawfile (ebl->elf, &maxsize);
    1381             : 
    1382           6 :           if (shdr != NULL && shdr->sh_type == SHT_PROGBITS
    1383           6 :               && filedata != NULL && phdr->p_offset < maxsize
    1384           6 :               && phdr->p_filesz <= maxsize - phdr->p_offset
    1385           6 :               && memchr (filedata + phdr->p_offset, '\0',
    1386             :                          phdr->p_filesz) != NULL)
    1387           6 :             printf (gettext ("\t[Requesting program interpreter: %s]\n"),
    1388             :                     filedata + phdr->p_offset);
    1389             :         }
    1390         104 :       else if (phdr->p_type == PT_GNU_RELRO)
    1391             :         {
    1392          10 :           has_relro = true;
    1393          10 :           relro_from = phdr->p_vaddr;
    1394          10 :           relro_to = relro_from + phdr->p_memsz;
    1395             :         }
    1396             :     }
    1397             : 
    1398             :   size_t sections;
    1399          10 :   if (unlikely (elf_getshdrnum (ebl->elf, &sections) < 0))
    1400           0 :     error (EXIT_FAILURE, 0,
    1401           0 :            gettext ("cannot get number of sections: %s"),
    1402             :            elf_errmsg (-1));
    1403             : 
    1404          10 :   if (sections == 0)
    1405             :     /* No sections in the file.  Punt.  */
    1406             :     return;
    1407             : 
    1408             :   /* Get the section header string table index.  */
    1409             :   size_t shstrndx;
    1410          10 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    1411             :     error (EXIT_FAILURE, 0,
    1412           0 :            gettext ("cannot get section header string table index"));
    1413             : 
    1414          10 :   puts (gettext ("\n Section to Segment mapping:\n  Segment Sections..."));
    1415             : 
    1416         120 :   for (size_t cnt = 0; cnt < phnum; ++cnt)
    1417             :     {
    1418             :       /* Print the segment number.  */
    1419         110 :       printf ("   %2.2zu     ", cnt);
    1420             : 
    1421             :       GElf_Phdr phdr_mem;
    1422         110 :       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
    1423             :       /* This must not happen.  */
    1424         110 :       if (unlikely (phdr == NULL))
    1425           0 :         error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
    1426             :                elf_errmsg (-1));
    1427             : 
    1428             :       /* Iterate over the sections.  */
    1429             :       bool in_relro = false;
    1430             :       bool in_ro = false;
    1431        3932 :       for (size_t inner = 1; inner < shnum; ++inner)
    1432             :         {
    1433        3932 :           Elf_Scn *scn = elf_getscn (ebl->elf, inner);
    1434             :           /* This should not happen.  */
    1435        3932 :           if (unlikely (scn == NULL))
    1436           0 :             error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
    1437             :                    elf_errmsg (-1));
    1438             : 
    1439             :           /* Get the section header.  */
    1440             :           GElf_Shdr shdr_mem;
    1441        3932 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1442        3932 :           if (unlikely (shdr == NULL))
    1443           0 :             error (EXIT_FAILURE, 0,
    1444           0 :                    gettext ("cannot get section header: %s"),
    1445             :                    elf_errmsg (-1));
    1446             : 
    1447        3932 :           if (shdr->sh_size > 0
    1448             :               /* Compare allocated sections by VMA, unallocated
    1449             :                  sections by file offset.  */
    1450        7864 :               && (shdr->sh_flags & SHF_ALLOC
    1451        2914 :                   ? (shdr->sh_addr >= phdr->p_vaddr
    1452        4716 :                      && (shdr->sh_addr + shdr->sh_size
    1453        1802 :                          <= phdr->p_vaddr + phdr->p_memsz))
    1454        1018 :                   : (shdr->sh_offset >= phdr->p_offset
    1455        2036 :                      && (shdr->sh_offset + shdr->sh_size
    1456        1018 :                          <= phdr->p_offset + phdr->p_filesz))))
    1457             :             {
    1458         372 :               if (has_relro && !in_relro
    1459         266 :                   && shdr->sh_addr >= relro_from
    1460          58 :                   && shdr->sh_addr + shdr->sh_size <= relro_to)
    1461             :                 {
    1462          38 :                   fputs_unlocked (" [RELRO:", stdout);
    1463          38 :                   in_relro = true;
    1464             :                 }
    1465         334 :               else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
    1466             :                 {
    1467          10 :                   fputs_unlocked ("]", stdout);
    1468          10 :                   in_relro =  false;
    1469             :                 }
    1470         324 :               else if (has_relro && in_relro
    1471          96 :                        && shdr->sh_addr + shdr->sh_size > relro_to)
    1472           0 :                 fputs_unlocked ("] <RELRO:", stdout);
    1473         324 :               else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
    1474             :                 {
    1475         176 :                   if (!in_ro)
    1476             :                     {
    1477          30 :                       fputs_unlocked (" [RO:", stdout);
    1478          30 :                       in_ro = true;
    1479             :                     }
    1480             :                 }
    1481             :               else
    1482             :                 {
    1483             :                   /* Determine the segment this section is part of.  */
    1484             :                   size_t cnt2;
    1485             :                   GElf_Phdr phdr2_mem;
    1486             :                   GElf_Phdr *phdr2 = NULL;
    1487         560 :                   for (cnt2 = 0; cnt2 < phnum; ++cnt2)
    1488             :                     {
    1489         708 :                       phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
    1490             : 
    1491         708 :                       if (phdr2 != NULL && phdr2->p_type == PT_LOAD
    1492         516 :                           && shdr->sh_addr >= phdr2->p_vaddr
    1493        1032 :                           && (shdr->sh_addr + shdr->sh_size
    1494         516 :                               <= phdr2->p_vaddr + phdr2->p_memsz))
    1495             :                         break;
    1496             :                     }
    1497             : 
    1498         148 :                   if (cnt2 < phnum)
    1499             :                     {
    1500         148 :                       if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
    1501             :                         {
    1502          26 :                           fputs_unlocked (" [RO:", stdout);
    1503          26 :                           in_ro = true;
    1504             :                         }
    1505         122 :                       else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
    1506             :                         {
    1507           0 :                           fputs_unlocked ("]", stdout);
    1508           0 :                           in_ro = false;
    1509             :                         }
    1510             :                     }
    1511             :                 }
    1512             : 
    1513         744 :               printf (" %s",
    1514         372 :                       elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
    1515             : 
    1516             :               /* Signal that this sectin is only partially covered.  */
    1517         372 :               if (has_relro && in_relro
    1518         134 :                        && shdr->sh_addr + shdr->sh_size > relro_to)
    1519             :                 {
    1520           0 :                   fputs_unlocked (">", stdout);
    1521           0 :                   in_relro =  false;
    1522             :                 }
    1523             :             }
    1524             :         }
    1525         110 :       if (in_relro || in_ro)
    1526          84 :         fputs_unlocked ("]", stdout);
    1527             : 
    1528             :       /* Finish the line.  */
    1529         220 :       fputc_unlocked ('\n', stdout);
    1530             :     }
    1531             : }
    1532             : 
    1533             : 
    1534             : static const char *
    1535         372 : section_name (Ebl *ebl, GElf_Shdr *shdr)
    1536             : {
    1537             :   size_t shstrndx;
    1538         372 :   if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
    1539             :     return "???";
    1540         372 :   return elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "???";
    1541             : }
    1542             : 
    1543             : 
    1544             : static void
    1545          16 : handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
    1546             : {
    1547             :   /* Get the data of the section.  */
    1548          16 :   Elf_Data *data = elf_getdata (scn, NULL);
    1549             : 
    1550          16 :   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
    1551             :   GElf_Shdr symshdr_mem;
    1552          16 :   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
    1553          16 :   Elf_Data *symdata = elf_getdata (symscn, NULL);
    1554             : 
    1555          16 :   if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
    1556          16 :       || symdata == NULL)
    1557           0 :     return;
    1558             : 
    1559             :   /* Get the section header string table index.  */
    1560             :   size_t shstrndx;
    1561          16 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    1562             :     error (EXIT_FAILURE, 0,
    1563           0 :            gettext ("cannot get section header string table index"));
    1564             : 
    1565          16 :   Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
    1566             : 
    1567             :   GElf_Sym sym_mem;
    1568          16 :   GElf_Sym *sym = gelf_getsym (symdata, shdr->sh_info, &sym_mem);
    1569             : 
    1570          80 :   printf ((grpref[0] & GRP_COMDAT)
    1571           4 :           ? ngettext ("\
    1572             : \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
    1573             :                       "\
    1574             : \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
    1575             :                       data->d_size / sizeof (Elf32_Word) - 1)
    1576          12 :           : ngettext ("\
    1577             : \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
    1578             : \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
    1579             :                       data->d_size / sizeof (Elf32_Word) - 1),
    1580             :           elf_ndxscn (scn),
    1581          16 :           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    1582             :           (sym == NULL ? NULL
    1583          16 :            : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
    1584             :           ?: gettext ("<INVALID SYMBOL>"),
    1585          16 :           data->d_size / sizeof (Elf32_Word) - 1);
    1586             : 
    1587          52 :   for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
    1588             :     {
    1589             :       GElf_Shdr grpshdr_mem;
    1590          36 :       GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
    1591             :                                          &grpshdr_mem);
    1592             : 
    1593             :       const char *str;
    1594          72 :       printf ("  [%2u] %s\n",
    1595             :               grpref[cnt],
    1596             :               grpshdr != NULL
    1597          36 :               && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
    1598             :               ? str : gettext ("<INVALID SECTION>"));
    1599             :     }
    1600             : }
    1601             : 
    1602             : 
    1603             : static void
    1604          49 : print_scngrp (Ebl *ebl)
    1605             : {
    1606             :   /* Find all relocation sections and handle them.  */
    1607          49 :   Elf_Scn *scn = NULL;
    1608             : 
    1609        1349 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    1610             :     {
    1611             :        /* Handle the section if it is a symbol table.  */
    1612             :       GElf_Shdr shdr_mem;
    1613        1251 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1614             : 
    1615        1251 :       if (shdr != NULL && shdr->sh_type == SHT_GROUP)
    1616             :         {
    1617          16 :           if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
    1618             :             {
    1619           0 :               if (elf_compress (scn, 0, 0) < 0)
    1620           0 :                 printf ("WARNING: %s [%zd]\n",
    1621             :                         gettext ("Couldn't uncompress section"),
    1622             :                         elf_ndxscn (scn));
    1623           0 :               shdr = gelf_getshdr (scn, &shdr_mem);
    1624           0 :               if (unlikely (shdr == NULL))
    1625           0 :                 error (EXIT_FAILURE, 0,
    1626           0 :                        gettext ("cannot get section [%zd] header: %s"),
    1627             :                        elf_ndxscn (scn),
    1628             :                        elf_errmsg (-1));
    1629             :             }
    1630          16 :           handle_scngrp (ebl, scn, shdr);
    1631             :         }
    1632             :     }
    1633          49 : }
    1634             : 
    1635             : 
    1636             : static const struct flags
    1637             : {
    1638             :   int mask;
    1639             :   const char *str;
    1640             : } dt_flags[] =
    1641             :   {
    1642             :     { DF_ORIGIN, "ORIGIN" },
    1643             :     { DF_SYMBOLIC, "SYMBOLIC" },
    1644             :     { DF_TEXTREL, "TEXTREL" },
    1645             :     { DF_BIND_NOW, "BIND_NOW" },
    1646             :     { DF_STATIC_TLS, "STATIC_TLS" }
    1647             :   };
    1648             : static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
    1649             : 
    1650             : static const struct flags dt_flags_1[] =
    1651             :   {
    1652             :     { DF_1_NOW, "NOW" },
    1653             :     { DF_1_GLOBAL, "GLOBAL" },
    1654             :     { DF_1_GROUP, "GROUP" },
    1655             :     { DF_1_NODELETE, "NODELETE" },
    1656             :     { DF_1_LOADFLTR, "LOADFLTR" },
    1657             :     { DF_1_INITFIRST, "INITFIRST" },
    1658             :     { DF_1_NOOPEN, "NOOPEN" },
    1659             :     { DF_1_ORIGIN, "ORIGIN" },
    1660             :     { DF_1_DIRECT, "DIRECT" },
    1661             :     { DF_1_TRANS, "TRANS" },
    1662             :     { DF_1_INTERPOSE, "INTERPOSE" },
    1663             :     { DF_1_NODEFLIB, "NODEFLIB" },
    1664             :     { DF_1_NODUMP, "NODUMP" },
    1665             :     { DF_1_CONFALT, "CONFALT" },
    1666             :     { DF_1_ENDFILTEE, "ENDFILTEE" },
    1667             :     { DF_1_DISPRELDNE, "DISPRELDNE" },
    1668             :     { DF_1_DISPRELPND, "DISPRELPND" },
    1669             :   };
    1670             : static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
    1671             : 
    1672             : static const struct flags dt_feature_1[] =
    1673             :   {
    1674             :     { DTF_1_PARINIT, "PARINIT" },
    1675             :     { DTF_1_CONFEXP, "CONFEXP" }
    1676             :   };
    1677             : static const int ndt_feature_1 = (sizeof (dt_feature_1)
    1678             :                                   / sizeof (dt_feature_1[0]));
    1679             : 
    1680             : static const struct flags dt_posflag_1[] =
    1681             :   {
    1682             :     { DF_P1_LAZYLOAD, "LAZYLOAD" },
    1683             :     { DF_P1_GROUPPERM, "GROUPPERM" }
    1684             :   };
    1685             : static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
    1686             :                                   / sizeof (dt_posflag_1[0]));
    1687             : 
    1688             : 
    1689             : static void
    1690          10 : print_flags (int class, GElf_Xword d_val, const struct flags *flags,
    1691             :                 int nflags)
    1692             : {
    1693          10 :   bool first = true;
    1694             :   int cnt;
    1695             : 
    1696         138 :   for (cnt = 0; cnt < nflags; ++cnt)
    1697         128 :     if (d_val & flags[cnt].mask)
    1698             :       {
    1699          22 :         if (!first)
    1700             :           putchar_unlocked (' ');
    1701          22 :         fputs_unlocked (flags[cnt].str, stdout);
    1702          22 :         d_val &= ~flags[cnt].mask;
    1703          22 :         first = false;
    1704             :       }
    1705             : 
    1706          10 :   if (d_val != 0)
    1707             :     {
    1708          10 :       if (!first)
    1709             :         putchar_unlocked (' ');
    1710          10 :       printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
    1711             :     }
    1712             : 
    1713          10 :   putchar_unlocked ('\n');
    1714          10 : }
    1715             : 
    1716             : 
    1717             : static void
    1718             : print_dt_flags (int class, GElf_Xword d_val)
    1719             : {
    1720           1 :   print_flags (class, d_val, dt_flags, ndt_flags);
    1721             : }
    1722             : 
    1723             : 
    1724             : static void
    1725             : print_dt_flags_1 (int class, GElf_Xword d_val)
    1726             : {
    1727           7 :   print_flags (class, d_val, dt_flags_1, ndt_flags_1);
    1728             : }
    1729             : 
    1730             : 
    1731             : static void
    1732             : print_dt_feature_1 (int class, GElf_Xword d_val)
    1733             : {
    1734           1 :   print_flags (class, d_val, dt_feature_1, ndt_feature_1);
    1735             : }
    1736             : 
    1737             : 
    1738             : static void
    1739             : print_dt_posflag_1 (int class, GElf_Xword d_val)
    1740             : {
    1741           1 :   print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
    1742             : }
    1743             : 
    1744             : 
    1745             : static void
    1746          12 : handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
    1747             : {
    1748          12 :   int class = gelf_getclass (ebl->elf);
    1749             :   GElf_Shdr glink_mem;
    1750             :   GElf_Shdr *glink;
    1751             :   Elf_Data *data;
    1752             :   size_t cnt;
    1753             :   size_t shstrndx;
    1754             :   size_t sh_entsize;
    1755             : 
    1756             :   /* Get the data of the section.  */
    1757          12 :   data = elf_getdata (scn, NULL);
    1758          12 :   if (data == NULL)
    1759           0 :     return;
    1760             : 
    1761             :   /* Get the section header string table index.  */
    1762          12 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    1763             :     error (EXIT_FAILURE, 0,
    1764           0 :            gettext ("cannot get section header string table index"));
    1765             : 
    1766          12 :   sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT);
    1767             : 
    1768          12 :   glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
    1769          12 :   if (glink == NULL)
    1770           0 :     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
    1771             :            elf_ndxscn (scn));
    1772             : 
    1773          48 :   printf (ngettext ("\
    1774             : \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
    1775             :                     "\
    1776             : \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
    1777             :                     shdr->sh_size / sh_entsize),
    1778          12 :           (unsigned long int) (shdr->sh_size / sh_entsize),
    1779             :           class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
    1780             :           shdr->sh_offset,
    1781          12 :           (int) shdr->sh_link,
    1782          12 :           elf_strptr (ebl->elf, shstrndx, glink->sh_name));
    1783          12 :   fputs_unlocked (gettext ("  Type              Value\n"), stdout);
    1784             : 
    1785         448 :   for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
    1786             :     {
    1787             :       GElf_Dyn dynmem;
    1788         436 :       GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
    1789         436 :       if (dyn == NULL)
    1790             :         break;
    1791             : 
    1792             :       char buf[64];
    1793         872 :       printf ("  %-17s ",
    1794             :               ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
    1795             : 
    1796         436 :       switch (dyn->d_tag)
    1797             :         {
    1798          66 :         case DT_NULL:
    1799             :         case DT_DEBUG:
    1800             :         case DT_BIND_NOW:
    1801             :         case DT_TEXTREL:
    1802             :           /* No further output.  */
    1803          66 :           fputc_unlocked ('\n', stdout);
    1804             :           break;
    1805             : 
    1806          52 :         case DT_NEEDED:
    1807         104 :           printf (gettext ("Shared library: [%s]\n"),
    1808          52 :                   elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
    1809             :           break;
    1810             : 
    1811           3 :         case DT_SONAME:
    1812           6 :           printf (gettext ("Library soname: [%s]\n"),
    1813           3 :                   elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
    1814             :           break;
    1815             : 
    1816           1 :         case DT_RPATH:
    1817           2 :           printf (gettext ("Library rpath: [%s]\n"),
    1818           1 :                   elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
    1819             :           break;
    1820             : 
    1821           2 :         case DT_RUNPATH:
    1822           4 :           printf (gettext ("Library runpath: [%s]\n"),
    1823           2 :                   elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
    1824             :           break;
    1825             : 
    1826          91 :         case DT_PLTRELSZ:
    1827             :         case DT_RELASZ:
    1828             :         case DT_STRSZ:
    1829             :         case DT_RELSZ:
    1830             :         case DT_RELAENT:
    1831             :         case DT_SYMENT:
    1832             :         case DT_RELENT:
    1833             :         case DT_PLTPADSZ:
    1834             :         case DT_MOVEENT:
    1835             :         case DT_MOVESZ:
    1836             :         case DT_INIT_ARRAYSZ:
    1837             :         case DT_FINI_ARRAYSZ:
    1838             :         case DT_SYMINSZ:
    1839             :         case DT_SYMINENT:
    1840             :         case DT_GNU_CONFLICTSZ:
    1841             :         case DT_GNU_LIBLISTSZ:
    1842          91 :           printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
    1843             :           break;
    1844             : 
    1845          31 :         case DT_VERDEFNUM:
    1846             :         case DT_VERNEEDNUM:
    1847             :         case DT_RELACOUNT:
    1848             :         case DT_RELCOUNT:
    1849          31 :           printf ("%" PRId64 "\n", dyn->d_un.d_val);
    1850             :           break;
    1851             : 
    1852          12 :         case DT_PLTREL:;
    1853          12 :           const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
    1854             :                                                       NULL, 0);
    1855          12 :           puts (tagname ?: "???");
    1856          12 :           break;
    1857             : 
    1858           1 :         case DT_FLAGS:
    1859           1 :           print_dt_flags (class, dyn->d_un.d_val);
    1860             :           break;
    1861             : 
    1862           7 :         case DT_FLAGS_1:
    1863           7 :           print_dt_flags_1 (class, dyn->d_un.d_val);
    1864             :           break;
    1865             : 
    1866           1 :         case DT_FEATURE_1:
    1867           1 :           print_dt_feature_1 (class, dyn->d_un.d_val);
    1868             :           break;
    1869             : 
    1870           1 :         case DT_POSFLAG_1:
    1871           1 :           print_dt_posflag_1 (class, dyn->d_un.d_val);
    1872             :           break;
    1873             : 
    1874         168 :         default:
    1875         168 :           printf ("%#0*" PRIx64 "\n",
    1876             :                   class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
    1877             :           break;
    1878             :         }
    1879             :     }
    1880             : }
    1881             : 
    1882             : 
    1883             : /* Print the dynamic segment.  */
    1884             : static void
    1885          42 : print_dynamic (Ebl *ebl)
    1886             : {
    1887          98 :   for (size_t i = 0; i < phnum; ++i)
    1888             :     {
    1889             :       GElf_Phdr phdr_mem;
    1890          68 :       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
    1891             : 
    1892          68 :       if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
    1893             :         {
    1894          12 :           Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
    1895             :           GElf_Shdr shdr_mem;
    1896          12 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1897          12 :           if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
    1898          12 :             handle_dynamic (ebl, scn, shdr);
    1899             :           break;
    1900             :         }
    1901             :     }
    1902          42 : }
    1903             : 
    1904             : 
    1905             : /* Print relocations.  */
    1906             : static void
    1907          41 : print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
    1908             : {
    1909             :   /* Find all relocation sections and handle them.  */
    1910          41 :   Elf_Scn *scn = NULL;
    1911             : 
    1912        1117 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    1913             :     {
    1914             :        /* Handle the section if it is a symbol table.  */
    1915             :       GElf_Shdr shdr_mem;
    1916        1035 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1917             : 
    1918        1035 :       if (likely (shdr != NULL))
    1919             :         {
    1920        1035 :           if (shdr->sh_type == SHT_REL)
    1921          22 :             handle_relocs_rel (ebl, ehdr, scn, shdr);
    1922        1013 :           else if (shdr->sh_type == SHT_RELA)
    1923         168 :             handle_relocs_rela (ebl, ehdr, scn, shdr);
    1924             :         }
    1925             :     }
    1926          41 : }
    1927             : 
    1928             : 
    1929             : /* Handle a relocation section.  */
    1930             : static void
    1931          22 : handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
    1932             : {
    1933          22 :   int class = gelf_getclass (ebl->elf);
    1934          22 :   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
    1935          22 :   int nentries = shdr->sh_size / sh_entsize;
    1936             : 
    1937             :   /* Get the data of the section.  */
    1938          22 :   Elf_Data *data = elf_getdata (scn, NULL);
    1939          22 :   if (data == NULL)
    1940           0 :     return;
    1941             : 
    1942             :   /* Get the symbol table information.  */
    1943          22 :   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
    1944             :   GElf_Shdr symshdr_mem;
    1945          22 :   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
    1946          22 :   Elf_Data *symdata = elf_getdata (symscn, NULL);
    1947             : 
    1948             :   /* Get the section header of the section the relocations are for.  */
    1949             :   GElf_Shdr destshdr_mem;
    1950          22 :   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
    1951             :                                       &destshdr_mem);
    1952             : 
    1953          22 :   if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
    1954             :     {
    1955           0 :       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
    1956             :               shdr->sh_offset);
    1957             :       return;
    1958             :     }
    1959             : 
    1960             :   /* Search for the optional extended section index table.  */
    1961          22 :   Elf_Data *xndxdata = NULL;
    1962          22 :   int xndxscnidx = elf_scnshndx (scn);
    1963          22 :   if (unlikely (xndxscnidx > 0))
    1964           0 :     xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
    1965             : 
    1966             :   /* Get the section header string table index.  */
    1967             :   size_t shstrndx;
    1968          22 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    1969             :     error (EXIT_FAILURE, 0,
    1970           0 :            gettext ("cannot get section header string table index"));
    1971             : 
    1972          22 :   if (shdr->sh_info != 0)
    1973          66 :     printf (ngettext ("\
    1974             : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
    1975             :                     "\
    1976             : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
    1977             :                       nentries),
    1978             :             elf_ndxscn (scn),
    1979          22 :             elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    1980          22 :             (unsigned int) shdr->sh_info,
    1981          22 :             elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
    1982             :             shdr->sh_offset,
    1983             :             nentries);
    1984             :   else
    1985             :     /* The .rel.dyn section does not refer to a specific section but
    1986             :        instead of section index zero.  Do not try to print a section
    1987             :        name.  */
    1988           0 :     printf (ngettext ("\
    1989             : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
    1990             :                     "\
    1991             : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
    1992             :                       nentries),
    1993           0 :             (unsigned int) elf_ndxscn (scn),
    1994           0 :             elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    1995             :             shdr->sh_offset,
    1996             :             nentries);
    1997          22 :   fputs_unlocked (class == ELFCLASS32
    1998             :                   ? gettext ("\
    1999             :   Offset      Type                 Value       Name\n")
    2000             :                   : gettext ("\
    2001             :   Offset              Type                 Value               Name\n"),
    2002             :          stdout);
    2003             : 
    2004          22 :   int is_statically_linked = 0;
    2005        6491 :   for (int cnt = 0; cnt < nentries; ++cnt)
    2006             :     {
    2007             :       GElf_Rel relmem;
    2008        6469 :       GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
    2009        6469 :       if (likely (rel != NULL))
    2010             :         {
    2011             :           char buf[128];
    2012             :           GElf_Sym symmem;
    2013             :           Elf32_Word xndx;
    2014        6469 :           GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
    2015        6469 :                                             GELF_R_SYM (rel->r_info),
    2016             :                                             &symmem, &xndx);
    2017        6469 :           if (unlikely (sym == NULL))
    2018             :             {
    2019             :               /* As a special case we have to handle relocations in static
    2020             :                  executables.  This only happens for IRELATIVE relocations
    2021             :                  (so far).  There is no symbol table.  */
    2022           0 :               if (is_statically_linked == 0)
    2023             :                 {
    2024             :                   /* Find the program header and look for a PT_INTERP entry. */
    2025           0 :                   is_statically_linked = -1;
    2026           0 :                   if (ehdr->e_type == ET_EXEC)
    2027             :                     {
    2028             :                       is_statically_linked = 1;
    2029             : 
    2030           0 :                       for (size_t inner = 0; inner < phnum; ++inner)
    2031             :                         {
    2032             :                           GElf_Phdr phdr_mem;
    2033           0 :                           GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
    2034             :                                                           &phdr_mem);
    2035           0 :                           if (phdr != NULL && phdr->p_type == PT_INTERP)
    2036             :                             {
    2037           0 :                               is_statically_linked = -1;
    2038           0 :                               break;
    2039             :                             }
    2040             :                         }
    2041             :                     }
    2042             :                 }
    2043             : 
    2044           0 :               if (is_statically_linked > 0 && shdr->sh_link == 0)
    2045           0 :                 printf ("\
    2046             :   %#0*" PRIx64 "  %-20s %*s  %s\n",
    2047             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2048           0 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2049             :                         /* Avoid the leading R_ which isn't carrying any
    2050             :                            information.  */
    2051           0 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2052             :                                                buf, sizeof (buf)) + 2
    2053             :                         : gettext ("<INVALID RELOC>"),
    2054             :                         class == ELFCLASS32 ? 10 : 18, "",
    2055           0 :                         elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
    2056             :               else
    2057           0 :                 printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
    2058             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2059           0 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2060             :                         /* Avoid the leading R_ which isn't carrying any
    2061             :                            information.  */
    2062           0 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2063             :                                                buf, sizeof (buf)) + 2
    2064             :                         : gettext ("<INVALID RELOC>"),
    2065             :                         gettext ("INVALID SYMBOL"),
    2066           0 :                         (long int) GELF_R_SYM (rel->r_info));
    2067             :             }
    2068        6469 :           else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
    2069         124 :             printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
    2070             :                     class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2071          31 :                     likely (ebl_reloc_type_check (ebl,
    2072             :                                                   GELF_R_TYPE (rel->r_info)))
    2073             :                     /* Avoid the leading R_ which isn't carrying any
    2074             :                        information.  */
    2075          31 :                     ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2076             :                                            buf, sizeof (buf)) + 2
    2077             :                     : gettext ("<INVALID RELOC>"),
    2078             :                     class == ELFCLASS32 ? 10 : 18, sym->st_value,
    2079          62 :                     elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
    2080             :           else
    2081             :             {
    2082             :               /* This is a relocation against a STT_SECTION symbol.  */
    2083             :               GElf_Shdr secshdr_mem;
    2084             :               GElf_Shdr *secshdr;
    2085        6438 :               secshdr = gelf_getshdr (elf_getscn (ebl->elf,
    2086        6438 :                                                   sym->st_shndx == SHN_XINDEX
    2087           0 :                                                   ? xndx : sym->st_shndx),
    2088             :                                       &secshdr_mem);
    2089             : 
    2090        6438 :               if (unlikely (secshdr == NULL))
    2091           0 :                 printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
    2092             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2093           0 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2094             :                         /* Avoid the leading R_ which isn't carrying any
    2095             :                            information.  */
    2096           0 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2097             :                                                buf, sizeof (buf)) + 2
    2098             :                         : gettext ("<INVALID RELOC>"),
    2099             :                         gettext ("INVALID SECTION"),
    2100           0 :                         (long int) (sym->st_shndx == SHN_XINDEX
    2101           0 :                                     ? xndx : sym->st_shndx));
    2102             :               else
    2103       19314 :                 printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
    2104             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2105        6438 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2106             :                         /* Avoid the leading R_ which isn't carrying any
    2107             :                            information.  */
    2108        6438 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2109             :                                                buf, sizeof (buf)) + 2
    2110             :                         : gettext ("<INVALID RELOC>"),
    2111             :                         class == ELFCLASS32 ? 10 : 18, sym->st_value,
    2112        6438 :                         elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
    2113             :             }
    2114             :         }
    2115             :     }
    2116             : }
    2117             : 
    2118             : 
    2119             : /* Handle a relocation section.  */
    2120             : static void
    2121         168 : handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
    2122             : {
    2123         168 :   int class = gelf_getclass (ebl->elf);
    2124         168 :   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
    2125         168 :   int nentries = shdr->sh_size / sh_entsize;
    2126             : 
    2127             :   /* Get the data of the section.  */
    2128         168 :   Elf_Data *data = elf_getdata (scn, NULL);
    2129         168 :   if (data == NULL)
    2130           0 :     return;
    2131             : 
    2132             :   /* Get the symbol table information.  */
    2133         168 :   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
    2134             :   GElf_Shdr symshdr_mem;
    2135         168 :   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
    2136         168 :   Elf_Data *symdata = elf_getdata (symscn, NULL);
    2137             : 
    2138             :   /* Get the section header of the section the relocations are for.  */
    2139             :   GElf_Shdr destshdr_mem;
    2140         168 :   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
    2141             :                                       &destshdr_mem);
    2142             : 
    2143         168 :   if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
    2144             :     {
    2145           0 :       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
    2146             :               shdr->sh_offset);
    2147             :       return;
    2148             :     }
    2149             : 
    2150             :   /* Search for the optional extended section index table.  */
    2151         168 :   Elf_Data *xndxdata = NULL;
    2152         168 :   int xndxscnidx = elf_scnshndx (scn);
    2153         168 :   if (unlikely (xndxscnidx > 0))
    2154           0 :     xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
    2155             : 
    2156             :   /* Get the section header string table index.  */
    2157             :   size_t shstrndx;
    2158         168 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    2159             :     error (EXIT_FAILURE, 0,
    2160           0 :            gettext ("cannot get section header string table index"));
    2161             : 
    2162         168 :   if (shdr->sh_info != 0)
    2163         474 :     printf (ngettext ("\
    2164             : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
    2165             :                     "\
    2166             : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
    2167             :                     nentries),
    2168             :           elf_ndxscn (scn),
    2169         158 :           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    2170         158 :           (unsigned int) shdr->sh_info,
    2171         158 :           elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
    2172             :           shdr->sh_offset,
    2173             :           nentries);
    2174             :   else
    2175             :     /* The .rela.dyn section does not refer to a specific section but
    2176             :        instead of section index zero.  Do not try to print a section
    2177             :        name.  */
    2178          30 :     printf (ngettext ("\
    2179             : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
    2180             :                     "\
    2181             : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
    2182             :                       nentries),
    2183          10 :             (unsigned int) elf_ndxscn (scn),
    2184          10 :             elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    2185             :             shdr->sh_offset,
    2186             :             nentries);
    2187         168 :   fputs_unlocked (class == ELFCLASS32
    2188             :                   ? gettext ("\
    2189             :   Offset      Type            Value       Addend Name\n")
    2190             :                   : gettext ("\
    2191             :   Offset              Type            Value               Addend Name\n"),
    2192             :                   stdout);
    2193             : 
    2194         168 :   int is_statically_linked = 0;
    2195       38696 :   for (int cnt = 0; cnt < nentries; ++cnt)
    2196             :     {
    2197             :       GElf_Rela relmem;
    2198       38528 :       GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
    2199       38528 :       if (likely (rel != NULL))
    2200             :         {
    2201             :           char buf[64];
    2202             :           GElf_Sym symmem;
    2203             :           Elf32_Word xndx;
    2204       38528 :           GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
    2205       38528 :                                             GELF_R_SYM (rel->r_info),
    2206             :                                             &symmem, &xndx);
    2207             : 
    2208       38528 :           if (unlikely (sym == NULL))
    2209             :             {
    2210             :               /* As a special case we have to handle relocations in static
    2211             :                  executables.  This only happens for IRELATIVE relocations
    2212             :                  (so far).  There is no symbol table.  */
    2213           0 :               if (is_statically_linked == 0)
    2214             :                 {
    2215             :                   /* Find the program header and look for a PT_INTERP entry. */
    2216           0 :                   is_statically_linked = -1;
    2217           0 :                   if (ehdr->e_type == ET_EXEC)
    2218             :                     {
    2219             :                       is_statically_linked = 1;
    2220             : 
    2221           0 :                       for (size_t inner = 0; inner < phnum; ++inner)
    2222             :                         {
    2223             :                           GElf_Phdr phdr_mem;
    2224           0 :                           GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
    2225             :                                                           &phdr_mem);
    2226           0 :                           if (phdr != NULL && phdr->p_type == PT_INTERP)
    2227             :                             {
    2228           0 :                               is_statically_linked = -1;
    2229           0 :                               break;
    2230             :                             }
    2231             :                         }
    2232             :                     }
    2233             :                 }
    2234             : 
    2235           0 :               if (is_statically_linked > 0 && shdr->sh_link == 0)
    2236           0 :                 printf ("\
    2237             :   %#0*" PRIx64 "  %-15s %*s  %#6" PRIx64 " %s\n",
    2238             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2239           0 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2240             :                         /* Avoid the leading R_ which isn't carrying any
    2241             :                            information.  */
    2242           0 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2243             :                                                buf, sizeof (buf)) + 2
    2244             :                         : gettext ("<INVALID RELOC>"),
    2245             :                         class == ELFCLASS32 ? 10 : 18, "",
    2246             :                         rel->r_addend,
    2247           0 :                         elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
    2248             :               else
    2249           0 :                 printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
    2250             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2251           0 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2252             :                         /* Avoid the leading R_ which isn't carrying any
    2253             :                            information.  */
    2254           0 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2255             :                                                buf, sizeof (buf)) + 2
    2256             :                         : gettext ("<INVALID RELOC>"),
    2257             :                         gettext ("INVALID SYMBOL"),
    2258           0 :                         (long int) GELF_R_SYM (rel->r_info));
    2259             :             }
    2260       38528 :           else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
    2261       82784 :             printf ("\
    2262             :   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
    2263             :                     class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2264       20696 :                     likely (ebl_reloc_type_check (ebl,
    2265             :                                                   GELF_R_TYPE (rel->r_info)))
    2266             :                     /* Avoid the leading R_ which isn't carrying any
    2267             :                        information.  */
    2268       20696 :                     ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2269             :                                            buf, sizeof (buf)) + 2
    2270             :                     : gettext ("<INVALID RELOC>"),
    2271             :                     class == ELFCLASS32 ? 10 : 18, sym->st_value,
    2272             :                     rel->r_addend,
    2273       41392 :                     elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
    2274             :           else
    2275             :             {
    2276             :               /* This is a relocation against a STT_SECTION symbol.  */
    2277             :               GElf_Shdr secshdr_mem;
    2278             :               GElf_Shdr *secshdr;
    2279       17832 :               secshdr = gelf_getshdr (elf_getscn (ebl->elf,
    2280       17832 :                                                   sym->st_shndx == SHN_XINDEX
    2281           0 :                                                   ? xndx : sym->st_shndx),
    2282             :                                       &secshdr_mem);
    2283             : 
    2284       17832 :               if (unlikely (secshdr == NULL))
    2285           0 :                 printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
    2286             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2287           0 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2288             :                         /* Avoid the leading R_ which isn't carrying any
    2289             :                            information.  */
    2290           0 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2291             :                                                buf, sizeof (buf)) + 2
    2292             :                         : gettext ("<INVALID RELOC>"),
    2293             :                         gettext ("INVALID SECTION"),
    2294           0 :                         (long int) (sym->st_shndx == SHN_XINDEX
    2295           0 :                                     ? xndx : sym->st_shndx));
    2296             :               else
    2297       53496 :                 printf ("\
    2298             :   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
    2299             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2300       17832 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2301             :                         /* Avoid the leading R_ which isn't carrying any
    2302             :                            information.  */
    2303       17832 :                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
    2304             :                                                buf, sizeof (buf)) + 2
    2305             :                         : gettext ("<INVALID RELOC>"),
    2306             :                         class == ELFCLASS32 ? 10 : 18, sym->st_value,
    2307             :                         rel->r_addend,
    2308       17832 :                         elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
    2309             :             }
    2310             :         }
    2311             :     }
    2312             : }
    2313             : 
    2314             : 
    2315             : /* Print the program header.  */
    2316             : static void
    2317         108 : print_symtab (Ebl *ebl, int type)
    2318             : {
    2319             :   /* Find the symbol table(s).  For this we have to search through the
    2320             :      section table.  */
    2321         108 :   Elf_Scn *scn = NULL;
    2322             : 
    2323        2976 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    2324             :     {
    2325             :       /* Handle the section if it is a symbol table.  */
    2326             :       GElf_Shdr shdr_mem;
    2327        2760 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    2328             : 
    2329        2760 :       if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
    2330             :         {
    2331          64 :           if (symbol_table_section != NULL)
    2332             :             {
    2333             :               /* Get the section header string table index.  */
    2334             :               size_t shstrndx;
    2335             :               const char *sname;
    2336           4 :               if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    2337             :                 error (EXIT_FAILURE, 0,
    2338           0 :                        gettext ("cannot get section header string table index"));
    2339           4 :               sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
    2340           4 :               if (sname == NULL || strcmp (sname, symbol_table_section) != 0)
    2341           2 :                 continue;
    2342             :             }
    2343             : 
    2344          62 :           if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
    2345             :             {
    2346           0 :               if (elf_compress (scn, 0, 0) < 0)
    2347           0 :                 printf ("WARNING: %s [%zd]\n",
    2348             :                         gettext ("Couldn't uncompress section"),
    2349             :                         elf_ndxscn (scn));
    2350           0 :               shdr = gelf_getshdr (scn, &shdr_mem);
    2351           0 :               if (unlikely (shdr == NULL))
    2352           0 :                 error (EXIT_FAILURE, 0,
    2353           0 :                        gettext ("cannot get section [%zd] header: %s"),
    2354             :                        elf_ndxscn (scn), elf_errmsg (-1));
    2355             :             }
    2356          62 :           handle_symtab (ebl, scn, shdr);
    2357             :         }
    2358             :     }
    2359         108 : }
    2360             : 
    2361             : 
    2362             : static void
    2363          62 : handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
    2364             : {
    2365          62 :   Elf_Data *versym_data = NULL;
    2366          62 :   Elf_Data *verneed_data = NULL;
    2367          62 :   Elf_Data *verdef_data = NULL;
    2368          62 :   Elf_Data *xndx_data = NULL;
    2369          62 :   int class = gelf_getclass (ebl->elf);
    2370          62 :   Elf32_Word verneed_stridx = 0;
    2371          62 :   Elf32_Word verdef_stridx = 0;
    2372             : 
    2373             :   /* Get the data of the section.  */
    2374          62 :   Elf_Data *data = elf_getdata (scn, NULL);
    2375          62 :   if (data == NULL)
    2376           0 :     return;
    2377             : 
    2378             :   /* Find out whether we have other sections we might need.  */
    2379             :   Elf_Scn *runscn = NULL;
    2380        1768 :   while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
    2381             :     {
    2382             :       GElf_Shdr runshdr_mem;
    2383        1706 :       GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
    2384             : 
    2385        1706 :       if (likely (runshdr != NULL))
    2386             :         {
    2387        1706 :           if (runshdr->sh_type == SHT_GNU_versym
    2388          27 :               && runshdr->sh_link == elf_ndxscn (scn))
    2389             :             /* Bingo, found the version information.  Now get the data.  */
    2390          17 :             versym_data = elf_getdata (runscn, NULL);
    2391        1689 :           else if (runshdr->sh_type == SHT_GNU_verneed)
    2392             :             {
    2393             :               /* This is the information about the needed versions.  */
    2394          27 :               verneed_data = elf_getdata (runscn, NULL);
    2395          27 :               verneed_stridx = runshdr->sh_link;
    2396             :             }
    2397        1662 :           else if (runshdr->sh_type == SHT_GNU_verdef)
    2398             :             {
    2399             :               /* This is the information about the defined versions.  */
    2400           8 :               verdef_data = elf_getdata (runscn, NULL);
    2401           8 :               verdef_stridx = runshdr->sh_link;
    2402             :             }
    2403        1654 :           else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
    2404           0 :               && runshdr->sh_link == elf_ndxscn (scn))
    2405             :             /* Extended section index.  */
    2406           0 :             xndx_data = elf_getdata (runscn, NULL);
    2407             :         }
    2408             :     }
    2409             : 
    2410             :   /* Get the section header string table index.  */
    2411             :   size_t shstrndx;
    2412          62 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    2413             :     error (EXIT_FAILURE, 0,
    2414           0 :            gettext ("cannot get section header string table index"));
    2415             : 
    2416             :   GElf_Shdr glink_mem;
    2417          62 :   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
    2418             :                                    &glink_mem);
    2419          62 :   if (glink == NULL)
    2420           0 :     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
    2421             :            elf_ndxscn (scn));
    2422             : 
    2423             :   /* Now we can compute the number of entries in the section.  */
    2424         124 :   unsigned int nsyms = data->d_size / (class == ELFCLASS32
    2425             :                                        ? sizeof (Elf32_Sym)
    2426          62 :                                        : sizeof (Elf64_Sym));
    2427             : 
    2428         186 :   printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
    2429             :                     "\nSymbol table [%2u] '%s' contains %u entries:\n",
    2430             :                     nsyms),
    2431          62 :           (unsigned int) elf_ndxscn (scn),
    2432          62 :           elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
    2433         186 :   printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
    2434             :                     " %lu local symbols  String table: [%2u] '%s'\n",
    2435             :                     shdr->sh_info),
    2436          62 :           (unsigned long int) shdr->sh_info,
    2437          62 :           (unsigned int) shdr->sh_link,
    2438          62 :           elf_strptr (ebl->elf, shstrndx, glink->sh_name));
    2439             : 
    2440          62 :   fputs_unlocked (class == ELFCLASS32
    2441             :                   ? gettext ("\
    2442             :   Num:    Value   Size Type    Bind   Vis          Ndx Name\n")
    2443             :                   : gettext ("\
    2444             :   Num:            Value   Size Type    Bind   Vis          Ndx Name\n"),
    2445             :                   stdout);
    2446             : 
    2447       14941 :   for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
    2448             :     {
    2449             :       char typebuf[64];
    2450             :       char bindbuf[64];
    2451             :       char scnbuf[64];
    2452             :       Elf32_Word xndx;
    2453             :       GElf_Sym sym_mem;
    2454       14879 :       GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
    2455             : 
    2456       14879 :       if (unlikely (sym == NULL))
    2457           0 :         continue;
    2458             : 
    2459             :       /* Determine the real section index.  */
    2460       14879 :       if (likely (sym->st_shndx != SHN_XINDEX))
    2461       14879 :         xndx = sym->st_shndx;
    2462             : 
    2463      119032 :       printf (gettext ("\
    2464             : %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
    2465             :               cnt,
    2466             :               class == ELFCLASS32 ? 8 : 16,
    2467             :               sym->st_value,
    2468             :               sym->st_size,
    2469       14879 :               ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
    2470             :                                     typebuf, sizeof (typebuf)),
    2471       14879 :               ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
    2472             :                                        bindbuf, sizeof (bindbuf)),
    2473       14879 :               get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
    2474       14879 :               ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
    2475             :                                 sizeof (scnbuf), NULL, shnum),
    2476       29758 :               elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
    2477             : 
    2478       14879 :       if (versym_data != NULL)
    2479             :         {
    2480             :           /* Get the version information.  */
    2481             :           GElf_Versym versym_mem;
    2482        1387 :           GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
    2483             : 
    2484        1387 :           if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
    2485             :             {
    2486        1189 :               bool is_nobits = false;
    2487        1189 :               bool check_def = xndx != SHN_UNDEF;
    2488             : 
    2489        1189 :               if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
    2490             :                 {
    2491             :                   GElf_Shdr symshdr_mem;
    2492        1153 :                   GElf_Shdr *symshdr =
    2493        1153 :                     gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
    2494             : 
    2495        1153 :                   is_nobits = (symshdr != NULL
    2496        1153 :                                && symshdr->sh_type == SHT_NOBITS);
    2497             :                 }
    2498             : 
    2499        1189 :               if (is_nobits || ! check_def)
    2500             :                 {
    2501             :                   /* We must test both.  */
    2502             :                   GElf_Vernaux vernaux_mem;
    2503         813 :                   GElf_Vernaux *vernaux = NULL;
    2504         813 :                   size_t vn_offset = 0;
    2505             : 
    2506             :                   GElf_Verneed verneed_mem;
    2507         813 :                   GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
    2508             :                                                            &verneed_mem);
    2509        4057 :                   while (verneed != NULL)
    2510             :                     {
    2511        3244 :                       size_t vna_offset = vn_offset;
    2512             : 
    2513        3244 :                       vernaux = gelf_getvernaux (verneed_data,
    2514        3244 :                                                  vna_offset += verneed->vn_aux,
    2515             :                                                  &vernaux_mem);
    2516       10018 :                       while (vernaux != NULL
    2517        6774 :                              && vernaux->vna_other != *versym
    2518        5961 :                              && vernaux->vna_next != 0)
    2519             :                         {
    2520             :                           /* Update the offset.  */
    2521        3530 :                           vna_offset += vernaux->vna_next;
    2522             : 
    2523        3530 :                           vernaux = (vernaux->vna_next == 0
    2524             :                                      ? NULL
    2525        3530 :                                      : gelf_getvernaux (verneed_data,
    2526             :                                                         vna_offset,
    2527             :                                                         &vernaux_mem));
    2528             :                         }
    2529             : 
    2530             :                       /* Check whether we found the version.  */
    2531        3244 :                       if (vernaux != NULL && vernaux->vna_other == *versym)
    2532             :                         /* Found it.  */
    2533             :                         break;
    2534             : 
    2535        2431 :                       vn_offset += verneed->vn_next;
    2536             :                       verneed = (verneed->vn_next == 0
    2537             :                                  ? NULL
    2538        2431 :                                  : gelf_getverneed (verneed_data, vn_offset,
    2539             :                                                     &verneed_mem));
    2540             :                     }
    2541             : 
    2542         813 :                   if (vernaux != NULL && vernaux->vna_other == *versym)
    2543             :                     {
    2544        2439 :                       printf ("@%s (%u)",
    2545             :                               elf_strptr (ebl->elf, verneed_stridx,
    2546         813 :                                           vernaux->vna_name),
    2547             :                               (unsigned int) vernaux->vna_other);
    2548         813 :                       check_def = 0;
    2549             :                     }
    2550           0 :                   else if (unlikely (! is_nobits))
    2551           0 :                     error (0, 0, gettext ("bad dynamic symbol"));
    2552             :                   else
    2553             :                     check_def = 1;
    2554             :                 }
    2555             : 
    2556         376 :               if (check_def && *versym != 0x8001)
    2557             :                 {
    2558             :                   /* We must test both.  */
    2559         376 :                   size_t vd_offset = 0;
    2560             : 
    2561             :                   GElf_Verdef verdef_mem;
    2562         376 :                   GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
    2563             :                                                         &verdef_mem);
    2564        2848 :                   while (verdef != NULL)
    2565             :                     {
    2566        2472 :                       if (verdef->vd_ndx == (*versym & 0x7fff))
    2567             :                         /* Found the definition.  */
    2568             :                         break;
    2569             : 
    2570        2096 :                       vd_offset += verdef->vd_next;
    2571             :                       verdef = (verdef->vd_next == 0
    2572             :                                 ? NULL
    2573        2096 :                                 : gelf_getverdef (verdef_data, vd_offset,
    2574             :                                                   &verdef_mem));
    2575             :                     }
    2576             : 
    2577         376 :                   if (verdef != NULL)
    2578             :                     {
    2579             :                       GElf_Verdaux verdaux_mem;
    2580         376 :                       GElf_Verdaux *verdaux
    2581         376 :                         = gelf_getverdaux (verdef_data,
    2582         376 :                                            vd_offset + verdef->vd_aux,
    2583             :                                            &verdaux_mem);
    2584             : 
    2585         376 :                       if (verdaux != NULL)
    2586         376 :                         printf ((*versym & 0x8000) ? "@%s" : "@@%s",
    2587             :                                 elf_strptr (ebl->elf, verdef_stridx,
    2588         376 :                                             verdaux->vda_name));
    2589             :                     }
    2590             :                 }
    2591             :             }
    2592             :         }
    2593             : 
    2594       14879 :       putchar_unlocked ('\n');
    2595             :     }
    2596             : }
    2597             : 
    2598             : 
    2599             : /* Print version information.  */
    2600             : static void
    2601          40 : print_verinfo (Ebl *ebl)
    2602             : {
    2603             :   /* Find the version information sections.  For this we have to
    2604             :      search through the section table.  */
    2605          40 :   Elf_Scn *scn = NULL;
    2606             : 
    2607        1081 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    2608             :     {
    2609             :       /* Handle the section if it is part of the versioning handling.  */
    2610             :       GElf_Shdr shdr_mem;
    2611        1001 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    2612             : 
    2613        1001 :       if (likely (shdr != NULL))
    2614             :         {
    2615        1001 :           if (shdr->sh_type == SHT_GNU_verneed)
    2616          10 :             handle_verneed (ebl, scn, shdr);
    2617         991 :           else if (shdr->sh_type == SHT_GNU_verdef)
    2618           4 :             handle_verdef (ebl, scn, shdr);
    2619         987 :           else if (shdr->sh_type == SHT_GNU_versym)
    2620          10 :             handle_versym (ebl, scn, shdr);
    2621             :         }
    2622             :     }
    2623          40 : }
    2624             : 
    2625             : 
    2626             : static const char *
    2627         125 : get_ver_flags (unsigned int flags)
    2628             : {
    2629             :   static char buf[32];
    2630             :   char *endp;
    2631             : 
    2632         125 :   if (flags == 0)
    2633         120 :     return gettext ("none");
    2634             : 
    2635           5 :   if (flags & VER_FLG_BASE)
    2636           4 :     endp = stpcpy (buf, "BASE ");
    2637             :   else
    2638             :     endp = buf;
    2639             : 
    2640           5 :   if (flags & VER_FLG_WEAK)
    2641             :     {
    2642           1 :       if (endp != buf)
    2643           0 :         endp = stpcpy (endp, "| ");
    2644             : 
    2645           1 :       endp = stpcpy (endp, "WEAK ");
    2646             :     }
    2647             : 
    2648           5 :   if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
    2649             :     {
    2650           0 :       strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
    2651           0 :       buf[sizeof (buf) - 1] = '\0';
    2652             :     }
    2653             : 
    2654             :   return buf;
    2655             : }
    2656             : 
    2657             : 
    2658             : static void
    2659          10 : handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
    2660             : {
    2661          10 :   int class = gelf_getclass (ebl->elf);
    2662             : 
    2663             :   /* Get the data of the section.  */
    2664          10 :   Elf_Data *data = elf_getdata (scn, NULL);
    2665          10 :   if (data == NULL)
    2666           0 :     return;
    2667             : 
    2668             :   /* Get the section header string table index.  */
    2669             :   size_t shstrndx;
    2670          10 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    2671             :     error (EXIT_FAILURE, 0,
    2672           0 :            gettext ("cannot get section header string table index"));
    2673             : 
    2674             :   GElf_Shdr glink_mem;
    2675          10 :   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
    2676             :                                    &glink_mem);
    2677          10 :   if (glink == NULL)
    2678           0 :     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
    2679             :            elf_ndxscn (scn));
    2680             : 
    2681          50 :   printf (ngettext ("\
    2682             : \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
    2683             :                     "\
    2684             : \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
    2685             :                     shdr->sh_info),
    2686          10 :           (unsigned int) elf_ndxscn (scn),
    2687          10 :           elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
    2688             :           class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
    2689             :           shdr->sh_offset,
    2690          10 :           (unsigned int) shdr->sh_link,
    2691          10 :           elf_strptr (ebl->elf, shstrndx, glink->sh_name));
    2692             : 
    2693          10 :   unsigned int offset = 0;
    2694          47 :   for (int cnt = shdr->sh_info; --cnt >= 0; )
    2695             :     {
    2696             :       /* Get the data at the next offset.  */
    2697             :       GElf_Verneed needmem;
    2698          37 :       GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
    2699          37 :       if (unlikely (need == NULL))
    2700             :         break;
    2701             : 
    2702         185 :       printf (gettext ("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
    2703          37 :               offset, (unsigned short int) need->vn_version,
    2704          74 :               elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
    2705          37 :               (unsigned short int) need->vn_cnt);
    2706             : 
    2707          37 :       unsigned int auxoffset = offset + need->vn_aux;
    2708         122 :       for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
    2709             :         {
    2710             :           GElf_Vernaux auxmem;
    2711          85 :           GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
    2712          85 :           if (unlikely (aux == NULL))
    2713             :             break;
    2714             : 
    2715         425 :           printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
    2716             :                   auxoffset,
    2717         170 :                   elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
    2718          85 :                   get_ver_flags (aux->vna_flags),
    2719          85 :                   (unsigned short int) aux->vna_other);
    2720             : 
    2721          85 :           if (aux->vna_next == 0)
    2722             :             break;
    2723             : 
    2724          48 :           auxoffset += aux->vna_next;
    2725             :         }
    2726             : 
    2727             :       /* Find the next offset.  */
    2728          37 :       if (need->vn_next == 0)
    2729             :         break;
    2730             : 
    2731          27 :       offset += need->vn_next;
    2732             :     }
    2733             : }
    2734             : 
    2735             : 
    2736             : static void
    2737           4 : handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
    2738             : {
    2739             :   /* Get the data of the section.  */
    2740           4 :   Elf_Data *data = elf_getdata (scn, NULL);
    2741           4 :   if (data == NULL)
    2742           0 :     return;
    2743             : 
    2744             :   /* Get the section header string table index.  */
    2745             :   size_t shstrndx;
    2746           4 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    2747             :     error (EXIT_FAILURE, 0,
    2748           0 :            gettext ("cannot get section header string table index"));
    2749             : 
    2750             :   GElf_Shdr glink_mem;
    2751           4 :   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
    2752             :                                    &glink_mem);
    2753           4 :   if (glink == NULL)
    2754           0 :     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
    2755             :            elf_ndxscn (scn));
    2756             : 
    2757           4 :   int class = gelf_getclass (ebl->elf);
    2758          20 :   printf (ngettext ("\
    2759             : \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
    2760             :                     "\
    2761             : \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
    2762             :                     shdr->sh_info),
    2763           4 :           (unsigned int) elf_ndxscn (scn),
    2764           4 :           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    2765             :           shdr->sh_info,
    2766             :           class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
    2767             :           shdr->sh_offset,
    2768           4 :           (unsigned int) shdr->sh_link,
    2769           4 :           elf_strptr (ebl->elf, shstrndx, glink->sh_name));
    2770             : 
    2771           4 :   unsigned int offset = 0;
    2772          44 :   for (int cnt = shdr->sh_info; --cnt >= 0; )
    2773             :     {
    2774             :       /* Get the data at the next offset.  */
    2775             :       GElf_Verdef defmem;
    2776          40 :       GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
    2777          40 :       if (unlikely (def == NULL))
    2778             :         break;
    2779             : 
    2780          40 :       unsigned int auxoffset = offset + def->vd_aux;
    2781             :       GElf_Verdaux auxmem;
    2782          40 :       GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
    2783          40 :       if (unlikely (aux == NULL))
    2784             :         break;
    2785             : 
    2786         280 :       printf (gettext ("\
    2787             :   %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"),
    2788          40 :               offset, def->vd_version,
    2789          40 :               get_ver_flags (def->vd_flags),
    2790          40 :               def->vd_ndx,
    2791          40 :               def->vd_cnt,
    2792          80 :               elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
    2793             : 
    2794          40 :       auxoffset += aux->vda_next;
    2795          40 :       for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
    2796             :         {
    2797          32 :           aux = gelf_getverdaux (data, auxoffset, &auxmem);
    2798          32 :           if (unlikely (aux == NULL))
    2799             :             break;
    2800             : 
    2801          96 :           printf (gettext ("  %#06x: Parent %d: %s\n"),
    2802             :                   auxoffset, cnt2,
    2803          64 :                   elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
    2804             : 
    2805          32 :           if (aux->vda_next == 0)
    2806             :             break;
    2807             : 
    2808           0 :           auxoffset += aux->vda_next;
    2809             :         }
    2810             : 
    2811             :       /* Find the next offset.  */
    2812          40 :       if (def->vd_next == 0)
    2813             :         break;
    2814          36 :       offset += def->vd_next;
    2815             :     }
    2816             : }
    2817             : 
    2818             : 
    2819             : static void
    2820          10 : handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
    2821             : {
    2822          10 :   int class = gelf_getclass (ebl->elf);
    2823             :   const char **vername;
    2824             :   const char **filename;
    2825             : 
    2826             :   /* Get the data of the section.  */
    2827          10 :   Elf_Data *data = elf_getdata (scn, NULL);
    2828          10 :   if (data == NULL)
    2829           0 :     return;
    2830             : 
    2831             :   /* Get the section header string table index.  */
    2832             :   size_t shstrndx;
    2833          10 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    2834             :     error (EXIT_FAILURE, 0,
    2835           0 :            gettext ("cannot get section header string table index"));
    2836             : 
    2837             :   /* We have to find the version definition section and extract the
    2838             :      version names.  */
    2839             :   Elf_Scn *defscn = NULL;
    2840             :   Elf_Scn *needscn = NULL;
    2841             : 
    2842             :   Elf_Scn *verscn = NULL;
    2843         368 :   while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
    2844             :     {
    2845             :       GElf_Shdr vershdr_mem;
    2846         358 :       GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
    2847             : 
    2848         358 :       if (likely (vershdr != NULL))
    2849             :         {
    2850         358 :           if (vershdr->sh_type == SHT_GNU_verdef)
    2851             :             defscn = verscn;
    2852         354 :           else if (vershdr->sh_type == SHT_GNU_verneed)
    2853          10 :             needscn = verscn;
    2854             :         }
    2855             :     }
    2856             : 
    2857             :   size_t nvername;
    2858          10 :   if (defscn != NULL || needscn != NULL)
    2859             :     {
    2860             :       /* We have a version information (better should have).  Now get
    2861             :          the version names.  First find the maximum version number.  */
    2862          10 :       nvername = 0;
    2863          10 :       if (defscn != NULL)
    2864             :         {
    2865             :           /* Run through the version definitions and find the highest
    2866             :              index.  */
    2867           4 :           unsigned int offset = 0;
    2868             :           Elf_Data *defdata;
    2869             :           GElf_Shdr defshdrmem;
    2870             :           GElf_Shdr *defshdr;
    2871             : 
    2872           4 :           defdata = elf_getdata (defscn, NULL);
    2873           4 :           if (unlikely (defdata == NULL))
    2874           0 :             return;
    2875             : 
    2876           4 :           defshdr = gelf_getshdr (defscn, &defshdrmem);
    2877           4 :           if (unlikely (defshdr == NULL))
    2878             :             return;
    2879             : 
    2880          36 :           for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
    2881             :             {
    2882             :               GElf_Verdef defmem;
    2883             :               GElf_Verdef *def;
    2884             : 
    2885             :               /* Get the data at the next offset.  */
    2886          40 :               def = gelf_getverdef (defdata, offset, &defmem);
    2887          40 :               if (unlikely (def == NULL))
    2888             :                 break;
    2889             : 
    2890          40 :               nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
    2891             : 
    2892          40 :               if (def->vd_next == 0)
    2893             :                 break;
    2894          36 :               offset += def->vd_next;
    2895             :             }
    2896             :         }
    2897          10 :       if (needscn != NULL)
    2898             :         {
    2899          10 :           unsigned int offset = 0;
    2900             :           Elf_Data *needdata;
    2901             :           GElf_Shdr needshdrmem;
    2902             :           GElf_Shdr *needshdr;
    2903             : 
    2904          10 :           needdata = elf_getdata (needscn, NULL);
    2905          10 :           if (unlikely (needdata == NULL))
    2906           0 :             return;
    2907             : 
    2908          10 :           needshdr = gelf_getshdr (needscn, &needshdrmem);
    2909          10 :           if (unlikely (needshdr == NULL))
    2910             :             return;
    2911             : 
    2912          27 :           for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
    2913             :             {
    2914             :               GElf_Verneed needmem;
    2915             :               GElf_Verneed *need;
    2916             :               unsigned int auxoffset;
    2917             :               int cnt2;
    2918             : 
    2919             :               /* Get the data at the next offset.  */
    2920          37 :               need = gelf_getverneed (needdata, offset, &needmem);
    2921          37 :               if (unlikely (need == NULL))
    2922             :                 break;
    2923             : 
    2924             :               /* Run through the auxiliary entries.  */
    2925          37 :               auxoffset = offset + need->vn_aux;
    2926         122 :               for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
    2927             :                 {
    2928             :                   GElf_Vernaux auxmem;
    2929             :                   GElf_Vernaux *aux;
    2930             : 
    2931          85 :                   aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
    2932          85 :                   if (unlikely (aux == NULL))
    2933             :                     break;
    2934             : 
    2935          85 :                   nvername = MAX (nvername,
    2936             :                                   (size_t) (aux->vna_other & 0x7fff));
    2937             : 
    2938          85 :                   if (aux->vna_next == 0)
    2939             :                     break;
    2940          48 :                   auxoffset += aux->vna_next;
    2941             :                 }
    2942             : 
    2943          37 :               if (need->vn_next == 0)
    2944             :                 break;
    2945          27 :               offset += need->vn_next;
    2946             :             }
    2947             :         }
    2948             : 
    2949             :       /* This is the number of versions we know about.  */
    2950          10 :       ++nvername;
    2951             : 
    2952             :       /* Allocate the array.  */
    2953          10 :       vername = (const char **) alloca (nvername * sizeof (const char *));
    2954          20 :       memset(vername, 0, nvername * sizeof (const char *));
    2955          10 :       filename = (const char **) alloca (nvername * sizeof (const char *));
    2956          20 :       memset(filename, 0, nvername * sizeof (const char *));
    2957             : 
    2958             :       /* Run through the data structures again and collect the strings.  */
    2959          10 :       if (defscn != NULL)
    2960             :         {
    2961             :           /* Run through the version definitions and find the highest
    2962             :              index.  */
    2963           4 :           unsigned int offset = 0;
    2964             :           Elf_Data *defdata;
    2965             :           GElf_Shdr defshdrmem;
    2966             :           GElf_Shdr *defshdr;
    2967             : 
    2968           4 :           defdata = elf_getdata (defscn, NULL);
    2969           4 :           if (unlikely (defdata == NULL))
    2970           0 :             return;
    2971             : 
    2972           4 :           defshdr = gelf_getshdr (defscn, &defshdrmem);
    2973           4 :           if (unlikely (defshdr == NULL))
    2974             :             return;
    2975             : 
    2976          36 :           for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
    2977             :             {
    2978             : 
    2979             :               /* Get the data at the next offset.  */
    2980             :               GElf_Verdef defmem;
    2981          40 :               GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
    2982          40 :               if (unlikely (def == NULL))
    2983             :                 break;
    2984             : 
    2985             :               GElf_Verdaux auxmem;
    2986          40 :               GElf_Verdaux *aux = gelf_getverdaux (defdata,
    2987          40 :                                                    offset + def->vd_aux,
    2988             :                                                    &auxmem);
    2989          40 :               if (unlikely (aux == NULL))
    2990             :                 break;
    2991             : 
    2992          40 :               vername[def->vd_ndx & 0x7fff]
    2993          80 :                 = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
    2994          40 :               filename[def->vd_ndx & 0x7fff] = NULL;
    2995             : 
    2996          40 :               if (def->vd_next == 0)
    2997             :                 break;
    2998          36 :               offset += def->vd_next;
    2999             :             }
    3000             :         }
    3001          10 :       if (needscn != NULL)
    3002             :         {
    3003          10 :           unsigned int offset = 0;
    3004             : 
    3005          10 :           Elf_Data *needdata = elf_getdata (needscn, NULL);
    3006             :           GElf_Shdr needshdrmem;
    3007          10 :           GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
    3008          10 :           if (unlikely (needdata == NULL || needshdr == NULL))
    3009           0 :             return;
    3010             : 
    3011          27 :           for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
    3012             :             {
    3013             :               /* Get the data at the next offset.  */
    3014             :               GElf_Verneed needmem;
    3015          37 :               GElf_Verneed *need = gelf_getverneed (needdata, offset,
    3016             :                                                     &needmem);
    3017          37 :               if (unlikely (need == NULL))
    3018             :                 break;
    3019             : 
    3020             :               /* Run through the auxiliary entries.  */
    3021          37 :               unsigned int auxoffset = offset + need->vn_aux;
    3022         122 :               for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
    3023             :                 {
    3024             :                   GElf_Vernaux auxmem;
    3025          85 :                   GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
    3026             :                                                        &auxmem);
    3027          85 :                   if (unlikely (aux == NULL))
    3028             :                     break;
    3029             : 
    3030          85 :                   vername[aux->vna_other & 0x7fff]
    3031         170 :                     = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
    3032          85 :                   filename[aux->vna_other & 0x7fff]
    3033         170 :                     = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
    3034             : 
    3035          85 :                   if (aux->vna_next == 0)
    3036             :                     break;
    3037          48 :                   auxoffset += aux->vna_next;
    3038             :                 }
    3039             : 
    3040          37 :               if (need->vn_next == 0)
    3041             :                 break;
    3042          27 :               offset += need->vn_next;
    3043             :             }
    3044             :         }
    3045             :     }
    3046             :   else
    3047             :     {
    3048             :       vername = NULL;
    3049             :       nvername = 1;
    3050             :       filename = NULL;
    3051             :     }
    3052             : 
    3053             :   GElf_Shdr glink_mem;
    3054          10 :   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
    3055             :                                    &glink_mem);
    3056          10 :   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_HALF, 1, EV_CURRENT);
    3057          10 :   if (glink == NULL)
    3058           0 :     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
    3059             :            elf_ndxscn (scn));
    3060             : 
    3061             :   /* Print the header.  */
    3062          60 :   printf (ngettext ("\
    3063             : \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
    3064             :                     "\
    3065             : \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
    3066             :                     shdr->sh_size / sh_entsize),
    3067          10 :           (unsigned int) elf_ndxscn (scn),
    3068          10 :           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    3069          10 :           (int) (shdr->sh_size / sh_entsize),
    3070             :           class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
    3071             :           shdr->sh_offset,
    3072          10 :           (unsigned int) shdr->sh_link,
    3073          10 :           elf_strptr (ebl->elf, shstrndx, glink->sh_name));
    3074             : 
    3075             :   /* Now we can finally look at the actual contents of this section.  */
    3076        1310 :   for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
    3077             :     {
    3078        1300 :       if (cnt % 2 == 0)
    3079             :         printf ("\n %4d:", cnt);
    3080             : 
    3081             :       GElf_Versym symmem;
    3082        1300 :       GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
    3083        1300 :       if (sym == NULL)
    3084             :         break;
    3085             : 
    3086        1300 :       switch (*sym)
    3087             :         {
    3088             :           ssize_t n;
    3089         112 :         case 0:
    3090         112 :           fputs_unlocked (gettext ("   0 *local*                     "),
    3091             :                           stdout);
    3092             :           break;
    3093             : 
    3094          12 :         case 1:
    3095          12 :           fputs_unlocked (gettext ("   1 *global*                    "),
    3096             :                           stdout);
    3097             :           break;
    3098             : 
    3099        1176 :         default:
    3100        4704 :           n = printf ("%4d%c%s",
    3101        1176 :                       *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
    3102             :                       (vername != NULL
    3103        1176 :                        && (unsigned int) (*sym & 0x7fff) < nvername)
    3104        1176 :                       ? vername[*sym & 0x7fff] : "???");
    3105        1176 :           if ((unsigned int) (*sym & 0x7fff) < nvername
    3106        1176 :               && filename != NULL && filename[*sym & 0x7fff] != NULL)
    3107        1600 :             n += printf ("(%s)", filename[*sym & 0x7fff]);
    3108        1176 :           printf ("%*s", MAX (0, 33 - (int) n), " ");
    3109             :           break;
    3110             :         }
    3111             :     }
    3112          10 :   putchar_unlocked ('\n');
    3113             : }
    3114             : 
    3115             : 
    3116             : static void
    3117          10 : print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
    3118             :                  uint_fast32_t maxlength, Elf32_Word nbucket,
    3119             :                  uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
    3120             : {
    3121          10 :   uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
    3122             : 
    3123         326 :   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
    3124         316 :     ++counts[lengths[cnt]];
    3125             : 
    3126             :   GElf_Shdr glink_mem;
    3127          10 :   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf,
    3128          10 :                                                shdr->sh_link),
    3129             :                                    &glink_mem);
    3130          10 :   if (glink == NULL)
    3131             :     {
    3132           0 :       error (0, 0, gettext ("invalid sh_link value in section %zu"),
    3133             :              elf_ndxscn (scn));
    3134           0 :       return;
    3135             :     }
    3136             : 
    3137          60 :   printf (ngettext ("\
    3138             : \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",
    3139             :                     "\
    3140             : \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",
    3141             :                     nbucket),
    3142          10 :           (unsigned int) elf_ndxscn (scn),
    3143          10 :           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    3144             :           (int) nbucket,
    3145          10 :           gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
    3146             :           shdr->sh_addr,
    3147             :           shdr->sh_offset,
    3148          10 :           (unsigned int) shdr->sh_link,
    3149          10 :           elf_strptr (ebl->elf, shstrndx, glink->sh_name));
    3150             : 
    3151          10 :   if (extrastr != NULL)
    3152          10 :     fputs (extrastr, stdout);
    3153             : 
    3154          10 :   if (likely (nbucket > 0))
    3155             :     {
    3156          10 :       uint64_t success = 0;
    3157             : 
    3158             :       /* xgettext:no-c-format */
    3159          10 :       fputs_unlocked (gettext ("\
    3160             :  Length  Number  % of total  Coverage\n"), stdout);
    3161          20 :       printf (gettext ("      0  %6" PRIu32 "      %5.1f%%\n"),
    3162          10 :               counts[0], (counts[0] * 100.0) / nbucket);
    3163             : 
    3164          10 :       uint64_t nzero_counts = 0;
    3165          47 :       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
    3166             :         {
    3167          37 :           nzero_counts += counts[cnt] * cnt;
    3168         111 :           printf (gettext ("\
    3169             : %7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
    3170          37 :                   (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
    3171          37 :                   (nzero_counts * 100.0) / nsyms);
    3172             :         }
    3173             : 
    3174             :       Elf32_Word acc = 0;
    3175          37 :       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
    3176             :         {
    3177          37 :           acc += cnt;
    3178          37 :           success += counts[cnt] * acc;
    3179             :         }
    3180             : 
    3181          20 :       printf (gettext ("\
    3182             :  Average number of tests:   successful lookup: %f\n\
    3183             :                           unsuccessful lookup: %f\n"),
    3184          10 :               (double) success / (double) nzero_counts,
    3185          10 :               (double) nzero_counts / (double) nbucket);
    3186             :     }
    3187             : 
    3188          10 :   free (counts);
    3189             : }
    3190             : 
    3191             : 
    3192             : /* This function handles the traditional System V-style hash table format.  */
    3193             : static void
    3194           0 : handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
    3195             : {
    3196           0 :   Elf_Data *data = elf_getdata (scn, NULL);
    3197           0 :   if (unlikely (data == NULL))
    3198             :     {
    3199           0 :       error (0, 0, gettext ("cannot get data for section %d: %s"),
    3200           0 :              (int) elf_ndxscn (scn), elf_errmsg (-1));
    3201             :       return;
    3202             :     }
    3203             : 
    3204           0 :   if (unlikely (data->d_size < 2 * sizeof (Elf32_Word)))
    3205             :     {
    3206           0 :     invalid_data:
    3207           0 :       error (0, 0, gettext ("invalid data in sysv.hash section %d"),
    3208           0 :              (int) elf_ndxscn (scn));
    3209             :       return;
    3210             :     }
    3211             : 
    3212           0 :   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
    3213           0 :   Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
    3214             : 
    3215           0 :   uint64_t used_buf = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
    3216           0 :   if (used_buf > data->d_size)
    3217             :     goto invalid_data;
    3218             : 
    3219           0 :   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
    3220           0 :   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
    3221             : 
    3222           0 :   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
    3223             : 
    3224           0 :   uint_fast32_t maxlength = 0;
    3225           0 :   uint_fast32_t nsyms = 0;
    3226           0 :   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
    3227             :     {
    3228           0 :       Elf32_Word inner = bucket[cnt];
    3229           0 :       Elf32_Word chain_len = 0;
    3230           0 :       while (inner > 0 && inner < nchain)
    3231             :         {
    3232           0 :           ++nsyms;
    3233           0 :           ++chain_len;
    3234           0 :           if (chain_len > nchain)
    3235             :             {
    3236           0 :               error (0, 0, gettext ("invalid chain in sysv.hash section %d"),
    3237           0 :                      (int) elf_ndxscn (scn));
    3238           0 :               free (lengths);
    3239           0 :               return;
    3240             :             }
    3241           0 :           if (maxlength < ++lengths[cnt])
    3242           0 :             ++maxlength;
    3243             : 
    3244           0 :           inner = chain[inner];
    3245             :         }
    3246             :     }
    3247             : 
    3248           0 :   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
    3249             :                    lengths, NULL);
    3250             : 
    3251           0 :   free (lengths);
    3252             : }
    3253             : 
    3254             : 
    3255             : /* This function handles the incorrect, System V-style hash table
    3256             :    format some 64-bit architectures use.  */
    3257             : static void
    3258           0 : handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
    3259             : {
    3260           0 :   Elf_Data *data = elf_getdata (scn, NULL);
    3261           0 :   if (unlikely (data == NULL))
    3262             :     {
    3263           0 :       error (0, 0, gettext ("cannot get data for section %d: %s"),
    3264           0 :              (int) elf_ndxscn (scn), elf_errmsg (-1));
    3265             :       return;
    3266             :     }
    3267             : 
    3268           0 :   if (unlikely (data->d_size < 2 * sizeof (Elf64_Xword)))
    3269             :     {
    3270           0 :     invalid_data:
    3271           0 :       error (0, 0, gettext ("invalid data in sysv.hash64 section %d"),
    3272           0 :              (int) elf_ndxscn (scn));
    3273             :       return;
    3274             :     }
    3275             : 
    3276           0 :   Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
    3277           0 :   Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
    3278             : 
    3279           0 :   uint64_t maxwords = data->d_size / sizeof (Elf64_Xword);
    3280           0 :   if (maxwords < 2
    3281           0 :       || maxwords - 2 < nbucket
    3282           0 :       || maxwords - 2 - nbucket < nchain)
    3283             :     goto invalid_data;
    3284             : 
    3285           0 :   Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
    3286           0 :   Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
    3287             : 
    3288           0 :   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
    3289             : 
    3290           0 :   uint_fast32_t maxlength = 0;
    3291           0 :   uint_fast32_t nsyms = 0;
    3292           0 :   for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
    3293             :     {
    3294           0 :       Elf64_Xword inner = bucket[cnt];
    3295           0 :       Elf64_Xword chain_len = 0;
    3296           0 :       while (inner > 0 && inner < nchain)
    3297             :         {
    3298           0 :           ++nsyms;
    3299           0 :           ++chain_len;
    3300           0 :           if (chain_len > nchain)
    3301             :             {
    3302           0 :               error (0, 0, gettext ("invalid chain in sysv.hash64 section %d"),
    3303           0 :                      (int) elf_ndxscn (scn));
    3304           0 :               free (lengths);
    3305           0 :               return;
    3306             :             }
    3307           0 :           if (maxlength < ++lengths[cnt])
    3308           0 :             ++maxlength;
    3309             : 
    3310           0 :           inner = chain[inner];
    3311             :         }
    3312             :     }
    3313             : 
    3314           0 :   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
    3315             :                    lengths, NULL);
    3316             : 
    3317           0 :   free (lengths);
    3318             : }
    3319             : 
    3320             : 
    3321             : /* This function handles the GNU-style hash table format.  */
    3322             : static void
    3323          10 : handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
    3324             : {
    3325          10 :   uint32_t *lengths = NULL;
    3326          10 :   Elf_Data *data = elf_getdata (scn, NULL);
    3327          10 :   if (unlikely (data == NULL))
    3328             :     {
    3329           0 :       error (0, 0, gettext ("cannot get data for section %d: %s"),
    3330           0 :              (int) elf_ndxscn (scn), elf_errmsg (-1));
    3331           0 :       return;
    3332             :     }
    3333             : 
    3334          10 :   if (unlikely (data->d_size < 4 * sizeof (Elf32_Word)))
    3335             :     {
    3336           0 :     invalid_data:
    3337           0 :       free (lengths);
    3338           0 :       error (0, 0, gettext ("invalid data in gnu.hash section %d"),
    3339           0 :              (int) elf_ndxscn (scn));
    3340             :       return;
    3341             :     }
    3342             : 
    3343          10 :   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
    3344          10 :   Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
    3345             : 
    3346             :   /* Next comes the size of the bitmap.  It's measured in words for
    3347             :      the architecture.  It's 32 bits for 32 bit archs, and 64 bits for
    3348             :      64 bit archs.  There is always a bloom filter present, so zero is
    3349             :      an invalid value.  */
    3350          10 :   Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
    3351          10 :   if (gelf_getclass (ebl->elf) == ELFCLASS64)
    3352          10 :     bitmask_words *= 2;
    3353             : 
    3354          10 :   if (bitmask_words == 0)
    3355             :     goto invalid_data;
    3356             : 
    3357          10 :   Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
    3358             : 
    3359             :   /* Is there still room for the sym chain?
    3360             :      Use uint64_t calculation to prevent 32bit overlow.  */
    3361          10 :   uint64_t used_buf = (4ULL + bitmask_words + nbucket) * sizeof (Elf32_Word);
    3362          10 :   uint32_t max_nsyms = (data->d_size - used_buf) / sizeof (Elf32_Word);
    3363          10 :   if (used_buf > data->d_size)
    3364             :     goto invalid_data;
    3365             : 
    3366          10 :   lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
    3367             : 
    3368          10 :   Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
    3369          10 :   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
    3370          10 :   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
    3371          10 :                                                     + nbucket];
    3372             : 
    3373             :   /* Compute distribution of chain lengths.  */
    3374          10 :   uint_fast32_t maxlength = 0;
    3375          10 :   uint_fast32_t nsyms = 0;
    3376         326 :   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
    3377         316 :     if (bucket[cnt] != 0)
    3378             :       {
    3379         218 :         Elf32_Word inner = bucket[cnt] - symbias;
    3380             :         do
    3381             :           {
    3382         417 :             ++nsyms;
    3383         417 :             if (maxlength < ++lengths[cnt])
    3384          37 :               ++maxlength;
    3385         417 :             if (inner >= max_nsyms)
    3386             :               goto invalid_data;
    3387             :           }
    3388         417 :         while ((chain[inner++] & 1) == 0);
    3389             :       }
    3390             : 
    3391             :   /* Count bits in bitmask.  */
    3392             :   uint_fast32_t nbits = 0;
    3393         112 :   for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
    3394             :     {
    3395         112 :       uint_fast32_t word = bitmask[cnt];
    3396             : 
    3397         112 :       word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
    3398         112 :       word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
    3399         112 :       word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
    3400         112 :       word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
    3401         112 :       nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
    3402             :     }
    3403             : 
    3404             :   char *str;
    3405          20 :   if (unlikely (asprintf (&str, gettext ("\
    3406             :  Symbol Bias: %u\n\
    3407             :  Bitmask Size: %zu bytes  %" PRIuFAST32 "%% bits set  2nd hash shift: %u\n"),
    3408             :                           (unsigned int) symbias,
    3409             :                           bitmask_words * sizeof (Elf32_Word),
    3410             :                           ((nbits * 100 + 50)
    3411             :                            / (uint_fast32_t) (bitmask_words
    3412             :                                               * sizeof (Elf32_Word) * 8)),
    3413             :                           (unsigned int) shift) == -1))
    3414           0 :     error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
    3415             : 
    3416          10 :   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
    3417             :                    lengths, str);
    3418             : 
    3419          10 :   free (str);
    3420          10 :   free (lengths);
    3421             : }
    3422             : 
    3423             : 
    3424             : /* Find the symbol table(s).  For this we have to search through the
    3425             :    section table.  */
    3426             : static void
    3427          40 : handle_hash (Ebl *ebl)
    3428             : {
    3429             :   /* Get the section header string table index.  */
    3430             :   size_t shstrndx;
    3431          40 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    3432             :     error (EXIT_FAILURE, 0,
    3433           0 :            gettext ("cannot get section header string table index"));
    3434             : 
    3435             :   Elf_Scn *scn = NULL;
    3436        1041 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    3437             :     {
    3438             :       /* Handle the section if it is a symbol table.  */
    3439             :       GElf_Shdr shdr_mem;
    3440        1001 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    3441             : 
    3442        1001 :       if (likely (shdr != NULL))
    3443             :         {
    3444        1001 :           if ((shdr->sh_type == SHT_HASH || shdr->sh_type == SHT_GNU_HASH)
    3445          10 :               && (shdr->sh_flags & SHF_COMPRESSED) != 0)
    3446             :             {
    3447           0 :               if (elf_compress (scn, 0, 0) < 0)
    3448           0 :                 printf ("WARNING: %s [%zd]\n",
    3449             :                         gettext ("Couldn't uncompress section"),
    3450             :                         elf_ndxscn (scn));
    3451           0 :               shdr = gelf_getshdr (scn, &shdr_mem);
    3452           0 :               if (unlikely (shdr == NULL))
    3453           0 :                 error (EXIT_FAILURE, 0,
    3454           0 :                        gettext ("cannot get section [%zd] header: %s"),
    3455             :                        elf_ndxscn (scn), elf_errmsg (-1));
    3456             :             }
    3457             : 
    3458        1001 :           if (shdr->sh_type == SHT_HASH)
    3459             :             {
    3460           0 :               if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
    3461           0 :                 handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
    3462             :               else
    3463           0 :                 handle_sysv_hash (ebl, scn, shdr, shstrndx);
    3464             :             }
    3465        1001 :           else if (shdr->sh_type == SHT_GNU_HASH)
    3466          10 :             handle_gnu_hash (ebl, scn, shdr, shstrndx);
    3467             :         }
    3468             :     }
    3469          40 : }
    3470             : 
    3471             : 
    3472             : static void
    3473          44 : print_liblist (Ebl *ebl)
    3474             : {
    3475             :   /* Find the library list sections.  For this we have to search
    3476             :      through the section table.  */
    3477          44 :   Elf_Scn *scn = NULL;
    3478             : 
    3479             :   /* Get the section header string table index.  */
    3480             :   size_t shstrndx;
    3481          44 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    3482             :     error (EXIT_FAILURE, 0,
    3483           0 :            gettext ("cannot get section header string table index"));
    3484             : 
    3485        1104 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    3486             :     {
    3487             :       GElf_Shdr shdr_mem;
    3488        1060 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    3489             : 
    3490        1060 :       if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
    3491             :         {
    3492           0 :           size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_LIB, 1, EV_CURRENT);
    3493           0 :           int nentries = shdr->sh_size / sh_entsize;
    3494           0 :           printf (ngettext ("\
    3495             : \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
    3496             :                             "\
    3497             : \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
    3498             :                             nentries),
    3499             :                   elf_ndxscn (scn),
    3500           0 :                   elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    3501             :                   shdr->sh_offset,
    3502             :                   nentries);
    3503             : 
    3504           0 :           Elf_Data *data = elf_getdata (scn, NULL);
    3505           0 :           if (data == NULL)
    3506           0 :             return;
    3507             : 
    3508           0 :           puts (gettext ("\
    3509             :        Library                       Time Stamp          Checksum Version Flags"));
    3510             : 
    3511           0 :           for (int cnt = 0; cnt < nentries; ++cnt)
    3512             :             {
    3513             :               GElf_Lib lib_mem;
    3514           0 :               GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
    3515           0 :               if (unlikely (lib == NULL))
    3516           0 :                 continue;
    3517             : 
    3518           0 :               time_t t = (time_t) lib->l_time_stamp;
    3519           0 :               struct tm *tm = gmtime (&t);
    3520           0 :               if (unlikely (tm == NULL))
    3521           0 :                 continue;
    3522             : 
    3523           0 :               printf ("  [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
    3524           0 :                       cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
    3525           0 :                       tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
    3526             :                       tm->tm_hour, tm->tm_min, tm->tm_sec,
    3527           0 :                       (unsigned int) lib->l_checksum,
    3528           0 :                       (unsigned int) lib->l_version,
    3529           0 :                       (unsigned int) lib->l_flags);
    3530             :             }
    3531             :         }
    3532             :     }
    3533             : }
    3534             : 
    3535             : static void
    3536          44 : print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
    3537             : {
    3538             :   /* Find the object attributes sections.  For this we have to search
    3539             :      through the section table.  */
    3540          44 :   Elf_Scn *scn = NULL;
    3541             : 
    3542             :   /* Get the section header string table index.  */
    3543             :   size_t shstrndx;
    3544          44 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
    3545             :     error (EXIT_FAILURE, 0,
    3546           0 :            gettext ("cannot get section header string table index"));
    3547             : 
    3548        1104 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    3549             :     {
    3550             :       GElf_Shdr shdr_mem;
    3551        1060 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    3552             : 
    3553        1060 :       if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
    3554        1057 :                            && (shdr->sh_type != SHT_ARM_ATTRIBUTES
    3555           1 :                                || ehdr->e_machine != EM_ARM)))
    3556        1056 :         continue;
    3557             : 
    3558          12 :       printf (gettext ("\
    3559             : \nObject attributes section [%2zu] '%s' of %" PRIu64
    3560             :                        " bytes at offset %#0" PRIx64 ":\n"),
    3561             :               elf_ndxscn (scn),
    3562           4 :               elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    3563             :               shdr->sh_size, shdr->sh_offset);
    3564             : 
    3565           4 :       Elf_Data *data = elf_rawdata (scn, NULL);
    3566           4 :       if (unlikely (data == NULL || data->d_size == 0))
    3567           0 :         return;
    3568             : 
    3569           4 :       const unsigned char *p = data->d_buf;
    3570             : 
    3571             :       /* There is only one 'version', A.  */
    3572           4 :       if (unlikely (*p++ != 'A'))
    3573             :         return;
    3574             : 
    3575           4 :       fputs_unlocked (gettext ("  Owner          Size\n"), stdout);
    3576             : 
    3577             :       inline size_t left (void)
    3578             :       {
    3579           8 :         return (const unsigned char *) data->d_buf + data->d_size - p;
    3580             :       }
    3581             : 
    3582             :       /* Loop over the sections.  */
    3583           8 :       while (left () >= 4)
    3584             :         {
    3585             :           /* Section length.  */
    3586             :           uint32_t len;
    3587           4 :           memcpy (&len, p, sizeof len);
    3588             : 
    3589           4 :           if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
    3590           4 :             CONVERT (len);
    3591             : 
    3592           4 :           if (unlikely (len > left ()))
    3593             :             break;
    3594             : 
    3595             :           /* Section vendor name.  */
    3596           4 :           const unsigned char *name = p + sizeof len;
    3597           4 :           p += len;
    3598             : 
    3599           4 :           unsigned const char *q = memchr (name, '\0', len);
    3600           4 :           if (unlikely (q == NULL))
    3601             :             break;
    3602           4 :           ++q;
    3603             : 
    3604           8 :           printf (gettext ("  %-13s  %4" PRIu32 "\n"), name, len);
    3605             : 
    3606           8 :           bool gnu_vendor = (q - name == sizeof "gnu"
    3607           4 :                              && !memcmp (name, "gnu", sizeof "gnu"));
    3608             : 
    3609             :           /* Loop over subsections.  */
    3610           4 :           if (shdr->sh_type != SHT_GNU_ATTRIBUTES
    3611           3 :               || gnu_vendor)
    3612           8 :             while (q < p)
    3613             :               {
    3614           4 :                 const unsigned char *const sub = q;
    3615             : 
    3616             :                 unsigned int subsection_tag;
    3617           4 :                 get_uleb128 (subsection_tag, q, p);
    3618           4 :                 if (unlikely (q >= p))
    3619             :                   break;
    3620             : 
    3621             :                 uint32_t subsection_len;
    3622           4 :                 if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
    3623             :                   break;
    3624             : 
    3625           4 :                 memcpy (&subsection_len, q, sizeof subsection_len);
    3626             : 
    3627           4 :                 if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
    3628           4 :                   CONVERT (subsection_len);
    3629             : 
    3630             :                 /* Don't overflow, ptrdiff_t might be 32bits, but signed.  */
    3631           4 :                 if (unlikely (subsection_len == 0
    3632             :                               || subsection_len >= (uint32_t) PTRDIFF_MAX
    3633             :                               || p - sub < (ptrdiff_t) subsection_len))
    3634             :                   break;
    3635             : 
    3636           4 :                 const unsigned char *r = q + sizeof subsection_len;
    3637           4 :                 q = sub + subsection_len;
    3638             : 
    3639           4 :                 switch (subsection_tag)
    3640             :                   {
    3641           0 :                   default:
    3642             :                     /* Unknown subsection, print and skip.  */
    3643           0 :                     printf (gettext ("    %-4u %12" PRIu32 "\n"),
    3644             :                             subsection_tag, subsection_len);
    3645             :                     break;
    3646             : 
    3647           4 :                   case 1:       /* Tag_File */
    3648           4 :                     printf (gettext ("    File: %11" PRIu32 "\n"),
    3649             :                             subsection_len);
    3650             : 
    3651          26 :                     while (r < q)
    3652          22 :                       {
    3653             :                         unsigned int tag;
    3654          22 :                         get_uleb128 (tag, r, q);
    3655          22 :                         if (unlikely (r >= q))
    3656             :                           break;
    3657             : 
    3658             :                         /* GNU style tags have either a uleb128 value,
    3659             :                            when lowest bit is not set, or a string
    3660             :                            when the lowest bit is set.
    3661             :                            "compatibility" (32) is special.  It has
    3662             :                            both a string and a uleb128 value.  For
    3663             :                            non-gnu we assume 6 till 31 only take ints.
    3664             :                            XXX see arm backend, do we need a separate
    3665             :                            hook?  */
    3666          22 :                         uint64_t value = 0;
    3667          22 :                         const char *string = NULL;
    3668          22 :                         if (tag == 32 || (tag & 1) == 0
    3669           8 :                             || (! gnu_vendor && (tag > 5 && tag < 32)))
    3670             :                           {
    3671          21 :                             get_uleb128 (value, r, q);
    3672          21 :                             if (r > q)
    3673             :                               break;
    3674             :                           }
    3675          22 :                         if (tag == 32
    3676          22 :                             || ((tag & 1) != 0
    3677           8 :                                 && (gnu_vendor
    3678           8 :                                     || (! gnu_vendor && tag > 32)))
    3679          22 :                             || (! gnu_vendor && tag > 3 && tag < 6))
    3680             :                           {
    3681           1 :                             string = (const char *) r;
    3682           1 :                             r = memchr (r, '\0', q - r);
    3683           1 :                             if (r == NULL)
    3684             :                               break;
    3685           1 :                             ++r;
    3686             :                           }
    3687             : 
    3688          22 :                         const char *tag_name = NULL;
    3689          22 :                         const char *value_name = NULL;
    3690          22 :                         ebl_check_object_attribute (ebl, (const char *) name,
    3691             :                                                     tag, value,
    3692             :                                                     &tag_name, &value_name);
    3693             : 
    3694          22 :                         if (tag_name != NULL)
    3695             :                           {
    3696          22 :                             if (tag == 32)
    3697           0 :                               printf (gettext ("      %s: %" PRId64 ", %s\n"),
    3698             :                                       tag_name, value, string);
    3699          22 :                             else if (string == NULL && value_name == NULL)
    3700           1 :                               printf (gettext ("      %s: %" PRId64 "\n"),
    3701             :                                       tag_name, value);
    3702             :                             else
    3703          21 :                               printf (gettext ("      %s: %s\n"),
    3704             :                                       tag_name, string ?: value_name);
    3705             :                           }
    3706             :                         else
    3707             :                           {
    3708             :                             /* For "gnu" vendor 32 "compatibility" has
    3709             :                                already been handled above.  */
    3710           0 :                             assert (tag != 32
    3711             :                                     || strcmp ((const char *) name, "gnu"));
    3712           0 :                             if (string == NULL)
    3713           0 :                               printf (gettext ("      %u: %" PRId64 "\n"),
    3714             :                                       tag, value);
    3715             :                             else
    3716           0 :                               printf (gettext ("      %u: %s\n"),
    3717             :                                       tag, string);
    3718             :                           }
    3719             :                       }
    3720             :                   }
    3721             :               }
    3722             :         }
    3723             :     }
    3724             : }
    3725             : 
    3726             : 
    3727             : void
    3728      606854 : print_dwarf_addr (Dwfl_Module *dwflmod,
    3729             :                   int address_size, Dwarf_Addr address, Dwarf_Addr raw)
    3730             : {
    3731             :   /* See if there is a name we can give for this address.  */
    3732             :   GElf_Sym sym;
    3733      606854 :   GElf_Off off = 0;
    3734     1820534 :   const char *name = (print_address_names && ! print_unresolved_addresses)
    3735      606754 :     ? dwfl_module_addrinfo (dwflmod, address, &off, &sym, NULL, NULL, NULL)
    3736     1213608 :     : NULL;
    3737             : 
    3738             :   const char *scn;
    3739      606854 :   if (print_unresolved_addresses)
    3740             :     {
    3741          72 :       address = raw;
    3742          72 :       scn = NULL;
    3743             :     }
    3744             :   else
    3745             :     {
    3746             :       /* Relativize the address.  */
    3747      606782 :       int n = dwfl_module_relocations (dwflmod);
    3748      606782 :       int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
    3749             : 
    3750             :       /* In an ET_REL file there is a section name to refer to.  */
    3751             :       scn = (i < 0 ? NULL
    3752      605782 :              : dwfl_module_relocation_info (dwflmod, i, NULL));
    3753             :     }
    3754             : 
    3755      606854 :   if ((name != NULL
    3756      595739 :        ? (off != 0
    3757             :           ? (scn != NULL
    3758             :              ? (address_size == 0
    3759      294852 :                 ? printf ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">",
    3760             :                           scn, address, name, off)
    3761     1270143 :                 : printf ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">",
    3762      423381 :                           scn, 2 + address_size * 2, address,
    3763             :                           name, off))
    3764             :              : (address_size == 0
    3765         338 :                 ? printf ("%#" PRIx64 " <%s+%#" PRIx64 ">",
    3766             :                           address, name, off)
    3767        1410 :                 : printf ("%#0*" PRIx64 " <%s+%#" PRIx64 ">",
    3768         470 :                           2 + address_size * 2, address,
    3769             :                           name, off)))
    3770             :           : (scn != NULL
    3771             :              ? (address_size == 0
    3772       12612 :                 ? printf ("%s+%#" PRIx64 " <%s>", scn, address, name)
    3773       53142 :                 : printf ("%s+%#0*" PRIx64 " <%s>",
    3774       17714 :                            scn, 2 + address_size * 2, address, name))
    3775             :              : (address_size == 0
    3776         158 :                 ? printf ("%#" PRIx64 " <%s>", address, name)
    3777         582 :                 : printf ("%#0*" PRIx64 " <%s>",
    3778         194 :                           2 + address_size * 2, address, name))))
    3779             :        : (scn != NULL
    3780             :           ? (address_size == 0
    3781       11244 :              ? printf ("%s+%#" PRIx64, scn, address)
    3782       10666 :              : printf ("%s+%#0*" PRIx64, scn, 2 + address_size * 2, address))
    3783             :           : (address_size == 0
    3784          64 :              ? printf ("%#" PRIx64, address)
    3785     1809447 :              : printf ("%#0*" PRIx64, 2 + address_size * 2, address)))) < 0)
    3786           0 :     error (EXIT_FAILURE, 0, _("sprintf failure"));
    3787      606854 : }
    3788             : 
    3789             : 
    3790             : static const char *
    3791      771589 : dwarf_tag_string (unsigned int tag)
    3792             : {
    3793      771589 :   switch (tag)
    3794             :     {
    3795             : #define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
    3796           0 :       DWARF_ALL_KNOWN_DW_TAG
    3797             : #undef DWARF_ONE_KNOWN_DW_TAG
    3798           0 :     default:
    3799           0 :       return NULL;
    3800             :     }
    3801             : }
    3802             : 
    3803             : 
    3804             : static const char *
    3805     2705738 : dwarf_attr_string (unsigned int attrnum)
    3806             : {
    3807     2705738 :   switch (attrnum)
    3808             :     {
    3809             : #define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
    3810        4379 :       DWARF_ALL_KNOWN_DW_AT
    3811             : #undef DWARF_ONE_KNOWN_DW_AT
    3812           0 :     default:
    3813           0 :       return NULL;
    3814             :     }
    3815             : }
    3816             : 
    3817             : 
    3818             : static const char *
    3819     2705744 : dwarf_form_string (unsigned int form)
    3820             : {
    3821     2705744 :   switch (form)
    3822             :     {
    3823             : #define DWARF_ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
    3824          21 :       DWARF_ALL_KNOWN_DW_FORM
    3825             : #undef DWARF_ONE_KNOWN_DW_FORM
    3826           0 :     default:
    3827           0 :       return NULL;
    3828             :     }
    3829             : }
    3830             : 
    3831             : 
    3832             : static const char *
    3833        1152 : dwarf_lang_string (unsigned int lang)
    3834             : {
    3835        1152 :   switch (lang)
    3836             :     {
    3837             : #define DWARF_ONE_KNOWN_DW_LANG(NAME, CODE) case CODE: return #NAME;
    3838           1 :       DWARF_ALL_KNOWN_DW_LANG
    3839             : #undef DWARF_ONE_KNOWN_DW_LANG
    3840           0 :     default:
    3841           0 :       return NULL;
    3842             :     }
    3843             : }
    3844             : 
    3845             : 
    3846             : static const char *
    3847             : dwarf_inline_string (unsigned int code)
    3848             : {
    3849             :   static const char *const known[] =
    3850             :     {
    3851             : #define DWARF_ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME,
    3852             :       DWARF_ALL_KNOWN_DW_INL
    3853             : #undef DWARF_ONE_KNOWN_DW_INL
    3854             :     };
    3855             : 
    3856        2927 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3857        2927 :     return known[code];
    3858             : 
    3859             :   return NULL;
    3860             : }
    3861             : 
    3862             : 
    3863             : static const char *
    3864             : dwarf_encoding_string (unsigned int code)
    3865             : {
    3866             :   static const char *const known[] =
    3867             :     {
    3868             : #define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
    3869             :       DWARF_ALL_KNOWN_DW_ATE
    3870             : #undef DWARF_ONE_KNOWN_DW_ATE
    3871             :     };
    3872             : 
    3873       16426 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3874       16426 :     return known[code];
    3875             : 
    3876             :   return NULL;
    3877             : }
    3878             : 
    3879             : 
    3880             : static const char *
    3881             : dwarf_access_string (unsigned int code)
    3882             : {
    3883             :   static const char *const known[] =
    3884             :     {
    3885             : #define DWARF_ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME,
    3886             :       DWARF_ALL_KNOWN_DW_ACCESS
    3887             : #undef DWARF_ONE_KNOWN_DW_ACCESS
    3888             :     };
    3889             : 
    3890           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3891           0 :     return known[code];
    3892             : 
    3893             :   return NULL;
    3894             : }
    3895             : 
    3896             : 
    3897             : static const char *
    3898             : dwarf_defaulted_string (unsigned int code)
    3899             : {
    3900             :   static const char *const known[] =
    3901             :     {
    3902             : #define DWARF_ONE_KNOWN_DW_DEFAULTED(NAME, CODE) [CODE] = #NAME,
    3903             :       DWARF_ALL_KNOWN_DW_DEFAULTED
    3904             : #undef DWARF_ONE_KNOWN_DW_DEFAULTED
    3905             :     };
    3906             : 
    3907           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3908           0 :     return known[code];
    3909             : 
    3910             :   return NULL;
    3911             : }
    3912             : 
    3913             : 
    3914             : static const char *
    3915             : dwarf_visibility_string (unsigned int code)
    3916             : {
    3917             :   static const char *const known[] =
    3918             :     {
    3919             : #define DWARF_ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
    3920             :       DWARF_ALL_KNOWN_DW_VIS
    3921             : #undef DWARF_ONE_KNOWN_DW_VIS
    3922             :     };
    3923             : 
    3924           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3925           0 :     return known[code];
    3926             : 
    3927             :   return NULL;
    3928             : }
    3929             : 
    3930             : 
    3931             : static const char *
    3932             : dwarf_virtuality_string (unsigned int code)
    3933             : {
    3934             :   static const char *const known[] =
    3935             :     {
    3936             : #define DWARF_ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
    3937             :       DWARF_ALL_KNOWN_DW_VIRTUALITY
    3938             : #undef DWARF_ONE_KNOWN_DW_VIRTUALITY
    3939             :     };
    3940             : 
    3941           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3942           0 :     return known[code];
    3943             : 
    3944             :   return NULL;
    3945             : }
    3946             : 
    3947             : 
    3948             : static const char *
    3949             : dwarf_identifier_case_string (unsigned int code)
    3950             : {
    3951             :   static const char *const known[] =
    3952             :     {
    3953             : #define DWARF_ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
    3954             :       DWARF_ALL_KNOWN_DW_ID
    3955             : #undef DWARF_ONE_KNOWN_DW_ID
    3956             :     };
    3957             : 
    3958           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3959           0 :     return known[code];
    3960             : 
    3961             :   return NULL;
    3962             : }
    3963             : 
    3964             : 
    3965             : static const char *
    3966             : dwarf_calling_convention_string (unsigned int code)
    3967             : {
    3968             :   static const char *const known[] =
    3969             :     {
    3970             : #define DWARF_ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
    3971             :       DWARF_ALL_KNOWN_DW_CC
    3972             : #undef DWARF_ONE_KNOWN_DW_CC
    3973             :     };
    3974             : 
    3975           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3976           0 :     return known[code];
    3977             : 
    3978             :   return NULL;
    3979             : }
    3980             : 
    3981             : 
    3982             : static const char *
    3983             : dwarf_ordering_string (unsigned int code)
    3984             : {
    3985             :   static const char *const known[] =
    3986             :     {
    3987             : #define DWARF_ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
    3988             :       DWARF_ALL_KNOWN_DW_ORD
    3989             : #undef DWARF_ONE_KNOWN_DW_ORD
    3990             :     };
    3991             : 
    3992           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3993           0 :     return known[code];
    3994             : 
    3995             :   return NULL;
    3996             : }
    3997             : 
    3998             : 
    3999             : static const char *
    4000             : dwarf_discr_list_string (unsigned int code)
    4001             : {
    4002             :   static const char *const known[] =
    4003             :     {
    4004             : #define DWARF_ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
    4005             :       DWARF_ALL_KNOWN_DW_DSC
    4006             : #undef DWARF_ONE_KNOWN_DW_DSC
    4007             :     };
    4008             : 
    4009           0 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    4010           0 :     return known[code];
    4011             : 
    4012             :   return NULL;
    4013             : }
    4014             : 
    4015             : 
    4016             : static const char *
    4017             : dwarf_locexpr_opcode_string (unsigned int code)
    4018             : {
    4019             :   static const char *const known[] =
    4020             :     {
    4021             :       /* Normally we can't affort building huge table of 64K entries,
    4022             :          most of them zero, just because there are a couple defined
    4023             :          values at the far end.  In case of opcodes, it's OK.  */
    4024             : #define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
    4025             :       DWARF_ALL_KNOWN_DW_OP
    4026             : #undef DWARF_ONE_KNOWN_DW_OP
    4027             :     };
    4028             : 
    4029      381451 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    4030      381451 :     return known[code];
    4031             : 
    4032             :   return NULL;
    4033             : }
    4034             : 
    4035             : 
    4036             : static const char *
    4037             : dwarf_unit_string (unsigned int type)
    4038             : {
    4039           8 :   switch (type)
    4040             :     {
    4041             : #define DWARF_ONE_KNOWN_DW_UT(NAME, CODE) case CODE: return #NAME;
    4042           0 :       DWARF_ALL_KNOWN_DW_UT
    4043             : #undef DWARF_ONE_KNOWN_DW_UT
    4044           0 :     default:
    4045             :       return NULL;
    4046             :     }
    4047             : }
    4048             : 
    4049             : 
    4050             : static const char *
    4051          14 : dwarf_range_list_encoding_string (unsigned int kind)
    4052             : {
    4053          14 :   switch (kind)
    4054             :     {
    4055             : #define DWARF_ONE_KNOWN_DW_RLE(NAME, CODE) case CODE: return #NAME;
    4056           0 :       DWARF_ALL_KNOWN_DW_RLE
    4057             : #undef DWARF_ONE_KNOWN_DW_RLE
    4058           0 :     default:
    4059           0 :       return NULL;
    4060             :     }
    4061             : }
    4062             : 
    4063             : 
    4064             : static const char *
    4065          89 : dwarf_loc_list_encoding_string (unsigned int kind)
    4066             : {
    4067          89 :   switch (kind)
    4068             :     {
    4069             : #define DWARF_ONE_KNOWN_DW_LLE(NAME, CODE) case CODE: return #NAME;
    4070           0 :       DWARF_ALL_KNOWN_DW_LLE
    4071             : #undef DWARF_ONE_KNOWN_DW_LLE
    4072           0 :     default:
    4073           0 :       return NULL;
    4074             :     }
    4075             : }
    4076             : 
    4077             : 
    4078             : static const char *
    4079             : dwarf_line_content_description_string (unsigned int kind)
    4080             : {
    4081           6 :   switch (kind)
    4082             :     {
    4083             : #define DWARF_ONE_KNOWN_DW_LNCT(NAME, CODE) case CODE: return #NAME;
    4084           2 :       DWARF_ALL_KNOWN_DW_LNCT
    4085             : #undef DWARF_ONE_KNOWN_DW_LNCT
    4086           0 :     default:
    4087             :       return NULL;
    4088             :     }
    4089             : }
    4090             : 
    4091             : 
    4092             : /* Used by all dwarf_foo_name functions.  */
    4093             : static const char *
    4094     6203693 : string_or_unknown (const char *known, unsigned int code,
    4095             :                    unsigned int lo_user, unsigned int hi_user,
    4096             :                    bool print_unknown_num)
    4097             : {
    4098             :   static char unknown_buf[20];
    4099             : 
    4100     6203693 :   if (likely (known != NULL))
    4101             :     return known;
    4102             : 
    4103           0 :   if (lo_user != 0 && code >= lo_user && code <= hi_user)
    4104             :     {
    4105           0 :       snprintf (unknown_buf, sizeof unknown_buf, "lo_user+%#x",
    4106             :                 code - lo_user);
    4107           0 :       return unknown_buf;
    4108             :     }
    4109             : 
    4110           0 :   if (print_unknown_num)
    4111             :     {
    4112           0 :       snprintf (unknown_buf, sizeof unknown_buf, "??? (%#x)", code);
    4113           0 :       return unknown_buf;
    4114             :     }
    4115             : 
    4116             :   return "???";
    4117             : }
    4118             : 
    4119             : 
    4120             : static const char *
    4121      771589 : dwarf_tag_name (unsigned int tag)
    4122             : {
    4123      771589 :   const char *ret = dwarf_tag_string (tag);
    4124      771589 :   return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true);
    4125             : }
    4126             : 
    4127             : static const char *
    4128     2705738 : dwarf_attr_name (unsigned int attr)
    4129             : {
    4130     2705738 :   const char *ret = dwarf_attr_string (attr);
    4131     2705738 :   return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true);
    4132             : }
    4133             : 
    4134             : 
    4135             : static const char *
    4136     2705744 : dwarf_form_name (unsigned int form)
    4137             : {
    4138     2705744 :   const char *ret = dwarf_form_string (form);
    4139     2705744 :   return string_or_unknown (ret, form, 0, 0, true);
    4140             : }
    4141             : 
    4142             : 
    4143             : static const char *
    4144        1152 : dwarf_lang_name (unsigned int lang)
    4145             : {
    4146        1152 :   const char *ret = dwarf_lang_string (lang);
    4147        1152 :   return string_or_unknown (ret, lang, DW_LANG_lo_user, DW_LANG_hi_user, false);
    4148             : }
    4149             : 
    4150             : 
    4151             : static const char *
    4152             : dwarf_inline_name (unsigned int code)
    4153             : {
    4154        2927 :   const char *ret = dwarf_inline_string (code);
    4155        2927 :   return string_or_unknown (ret, code, 0, 0, false);
    4156             : }
    4157             : 
    4158             : 
    4159             : static const char *
    4160             : dwarf_encoding_name (unsigned int code)
    4161             : {
    4162       16426 :   const char *ret = dwarf_encoding_string (code);
    4163       16426 :   return string_or_unknown (ret, code, DW_ATE_lo_user, DW_ATE_hi_user, false);
    4164             : }
    4165             : 
    4166             : 
    4167             : static const char *
    4168             : dwarf_access_name (unsigned int code)
    4169             : {
    4170           0 :   const char *ret = dwarf_access_string (code);
    4171           0 :   return string_or_unknown (ret, code, 0, 0, false);
    4172             : }
    4173             : 
    4174             : 
    4175             : static const char *
    4176             : dwarf_defaulted_name (unsigned int code)
    4177             : {
    4178           0 :   const char *ret = dwarf_defaulted_string (code);
    4179           0 :   return string_or_unknown (ret, code, 0, 0, false);
    4180             : }
    4181             : 
    4182             : 
    4183             : static const char *
    4184             : dwarf_visibility_name (unsigned int code)
    4185             : {
    4186           0 :   const char *ret = dwarf_visibility_string (code);
    4187           0 :   return string_or_unknown (ret, code, 0, 0, false);
    4188             : }
    4189             : 
    4190             : 
    4191             : static const char *
    4192             : dwarf_virtuality_name (unsigned int code)
    4193             : {
    4194           0 :   const char *ret = dwarf_virtuality_string (code);
    4195           0 :   return string_or_unknown (ret, code, 0, 0, false);
    4196             : }
    4197             : 
    4198             : 
    4199             : static const char *
    4200             : dwarf_identifier_case_name (unsigned int code)
    4201             : {
    4202           0 :   const char *ret = dwarf_identifier_case_string (code);
    4203           0 :   return string_or_unknown (ret, code, 0, 0, false);
    4204             : }
    4205             : 
    4206             : 
    4207             : static const char *
    4208             : dwarf_calling_convention_name (unsigned int code)
    4209             : {
    4210           0 :   const char *ret = dwarf_calling_convention_string (code);
    4211           0 :   return string_or_unknown (ret, code, DW_CC_lo_user, DW_CC_hi_user, false);
    4212             : }
    4213             : 
    4214             : 
    4215             : static const char *
    4216             : dwarf_ordering_name (unsigned int code)
    4217             : {
    4218           0 :   const char *ret = dwarf_ordering_string (code);
    4219           0 :   return string_or_unknown (ret, code, 0, 0, false);
    4220             : }
    4221             : 
    4222             : 
    4223             : static const char *
    4224             : dwarf_discr_list_name (unsigned int code)
    4225             : {
    4226           0 :   const char *ret = dwarf_discr_list_string (code);
    4227           0 :   return string_or_unknown (ret, code, 0, 0, false);
    4228             : }
    4229             : 
    4230             : 
    4231             : static const char *
    4232           8 : dwarf_unit_name (unsigned int type)
    4233             : {
    4234           8 :   const char *ret = dwarf_unit_string (type);
    4235           8 :   return string_or_unknown (ret, type, DW_UT_lo_user, DW_UT_hi_user, true);
    4236             : }
    4237             : 
    4238             : 
    4239             : static const char *
    4240          14 : dwarf_range_list_encoding_name (unsigned int kind)
    4241             : {
    4242          14 :   const char *ret = dwarf_range_list_encoding_string (kind);
    4243          14 :   return string_or_unknown (ret, kind, 0, 0, false);
    4244             : }
    4245             : 
    4246             : 
    4247             : static const char *
    4248          89 : dwarf_loc_list_encoding_name (unsigned int kind)
    4249             : {
    4250          89 :   const char *ret = dwarf_loc_list_encoding_string (kind);
    4251          89 :   return string_or_unknown (ret, kind, 0, 0, false);
    4252             : }
    4253             : 
    4254             : 
    4255             : static const char *
    4256           6 : dwarf_line_content_description_name (unsigned int kind)
    4257             : {
    4258           6 :   const char *ret = dwarf_line_content_description_string (kind);
    4259           6 :   return string_or_unknown (ret, kind, DW_LNCT_lo_user, DW_LNCT_hi_user,
    4260             :                             false);
    4261             : }
    4262             : 
    4263             : 
    4264             : static void
    4265         145 : print_block (size_t n, const void *block)
    4266             : {
    4267         145 :   if (n == 0)
    4268           0 :     puts (_("empty block"));
    4269             :   else
    4270             :     {
    4271         290 :       printf (_("%zu byte block:"), n);
    4272         145 :       const unsigned char *data = block;
    4273             :       do
    4274        4202 :         printf (" %02x", *data++);
    4275        2101 :       while (--n > 0);
    4276             :       putchar ('\n');
    4277             :     }
    4278         145 : }
    4279             : 
    4280             : static void
    4281           0 : print_bytes (size_t n, const unsigned char *bytes)
    4282             : {
    4283           0 :   while (n-- > 0)
    4284             :     {
    4285           0 :       printf ("%02x", *bytes++);
    4286           0 :       if (n > 0)
    4287             :         printf (" ");
    4288             :     }
    4289           0 : }
    4290             : 
    4291             : static int
    4292          68 : get_indexed_addr (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr)
    4293             : {
    4294          68 :   if (cu == NULL)
    4295             :     return -1;
    4296             : 
    4297          68 :   Elf_Data *debug_addr = cu->dbg->sectiondata[IDX_debug_addr];
    4298          68 :   if (debug_addr == NULL)
    4299             :     return -1;
    4300             : 
    4301          68 :   Dwarf_Off base = __libdw_cu_addr_base (cu);
    4302          68 :   Dwarf_Word off = idx * cu->address_size;
    4303          68 :   if (base > debug_addr->d_size
    4304          68 :       || off > debug_addr->d_size - base
    4305          68 :       || cu->address_size > debug_addr->d_size - base - off)
    4306             :     return -1;
    4307             : 
    4308          68 :   const unsigned char *addrp = debug_addr->d_buf + base + off;
    4309          68 :   if (cu->address_size == 4)
    4310           0 :     *addr = read_4ubyte_unaligned (cu->dbg, addrp);
    4311             :   else
    4312          68 :     *addr = read_8ubyte_unaligned (cu->dbg, addrp);
    4313             : 
    4314             :   return 0;
    4315             : }
    4316             : 
    4317             : static void
    4318      267230 : print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
    4319             :            unsigned int vers, unsigned int addrsize, unsigned int offset_size,
    4320             :            struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data)
    4321             : {
    4322      267230 :   const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
    4323             : 
    4324      267230 :   if (len == 0)
    4325             :     {
    4326             :       printf ("%*s(empty)\n", indent, "");
    4327             :       return;
    4328             :     }
    4329             : 
    4330             : #define NEED(n)         if (len < (Dwarf_Word) (n)) goto invalid
    4331             : #define CONSUME(n)      NEED (n); else len -= (n)
    4332             : 
    4333             :   Dwarf_Word offset = 0;
    4334      648681 :   while (len-- > 0)
    4335             :     {
    4336      381451 :       uint_fast8_t op = *data++;
    4337             : 
    4338      762902 :       const char *op_name = dwarf_locexpr_opcode_string (op);
    4339      381451 :       if (unlikely (op_name == NULL))
    4340             :         {
    4341             :           static char buf[20];
    4342           0 :           if (op >= DW_OP_lo_user)
    4343           0 :             snprintf (buf, sizeof buf, "lo_user+%#x", op - DW_OP_lo_user);
    4344             :           else
    4345           0 :             snprintf (buf, sizeof buf, "??? (%#x)", op);
    4346             :           op_name = buf;
    4347             :         }
    4348             : 
    4349      381451 :       switch (op)
    4350             :         {
    4351        7534 :         case DW_OP_addr:;
    4352             :           /* Address operand.  */
    4353             :           Dwarf_Word addr;
    4354        7534 :           NEED (addrsize);
    4355        7534 :           if (addrsize == 4)
    4356          28 :             addr = read_4ubyte_unaligned (dbg, data);
    4357        7516 :           else if (addrsize == 8)
    4358        7534 :             addr = read_8ubyte_unaligned (dbg, data);
    4359             :           else
    4360             :             goto invalid;
    4361        7534 :           data += addrsize;
    4362        7534 :           CONSUME (addrsize);
    4363             : 
    4364        7534 :           printf ("%*s[%2" PRIuMAX "] %s ",
    4365             :                   indent, "", (uintmax_t) offset, op_name);
    4366        7534 :           print_dwarf_addr (dwflmod, 0, addr, addr);
    4367        7534 :           printf ("\n");
    4368             : 
    4369        7534 :           offset += 1 + addrsize;
    4370      388985 :           break;
    4371             : 
    4372           0 :         case DW_OP_call_ref:
    4373             :         case DW_OP_GNU_variable_value:
    4374             :           /* Offset operand.  */
    4375           0 :           if (ref_size != 4 && ref_size != 8)
    4376             :             goto invalid; /* Cannot be used in CFA.  */
    4377           0 :           NEED (ref_size);
    4378           0 :           if (ref_size == 4)
    4379           0 :             addr = read_4ubyte_unaligned (dbg, data);
    4380             :           else
    4381           0 :             addr = read_8ubyte_unaligned (dbg, data);
    4382           0 :           data += ref_size;
    4383           0 :           CONSUME (ref_size);
    4384             :           /* addr is a DIE offset, so format it as one.  */
    4385           0 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
    4386             :                   indent, "", (uintmax_t) offset,
    4387             :                   op_name, (uintmax_t) addr);
    4388           0 :           offset += 1 + ref_size;
    4389           0 :           break;
    4390             : 
    4391        9477 :         case DW_OP_deref_size:
    4392             :         case DW_OP_xderef_size:
    4393             :         case DW_OP_pick:
    4394             :         case DW_OP_const1u:
    4395             :           // XXX value might be modified by relocation
    4396        9477 :           NEED (1);
    4397       18954 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 "\n",
    4398             :                   indent, "", (uintmax_t) offset,
    4399        9477 :                   op_name, *((uint8_t *) data));
    4400        9477 :           ++data;
    4401        9477 :           --len;
    4402        9477 :           offset += 2;
    4403        9477 :           break;
    4404             : 
    4405         945 :         case DW_OP_const2u:
    4406         945 :           NEED (2);
    4407             :           // XXX value might be modified by relocation
    4408        2835 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu16 "\n",
    4409             :                   indent, "", (uintmax_t) offset,
    4410        1890 :                   op_name, read_2ubyte_unaligned (dbg, data));
    4411         945 :           CONSUME (2);
    4412         945 :           data += 2;
    4413         945 :           offset += 3;
    4414         945 :           break;
    4415             : 
    4416         575 :         case DW_OP_const4u:
    4417         575 :           NEED (4);
    4418             :           // XXX value might be modified by relocation
    4419        1725 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu32 "\n",
    4420             :                   indent, "", (uintmax_t) offset,
    4421        1150 :                   op_name, read_4ubyte_unaligned (dbg, data));
    4422         575 :           CONSUME (4);
    4423         575 :           data += 4;
    4424         575 :           offset += 5;
    4425         575 :           break;
    4426             : 
    4427          46 :         case DW_OP_const8u:
    4428          46 :           NEED (8);
    4429             :           // XXX value might be modified by relocation
    4430         138 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
    4431             :                   indent, "", (uintmax_t) offset,
    4432          92 :                   op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
    4433          46 :           CONSUME (8);
    4434          46 :           data += 8;
    4435          46 :           offset += 9;
    4436          46 :           break;
    4437             : 
    4438        2105 :         case DW_OP_const1s:
    4439        2105 :           NEED (1);
    4440             :           // XXX value might be modified by relocation
    4441        4210 :           printf ("%*s[%2" PRIuMAX "] %s %" PRId8 "\n",
    4442             :                   indent, "", (uintmax_t) offset,
    4443        2105 :                   op_name, *((int8_t *) data));
    4444        2105 :           ++data;
    4445        2105 :           --len;
    4446        2105 :           offset += 2;
    4447        2105 :           break;
    4448             : 
    4449           3 :         case DW_OP_const2s:
    4450           3 :           NEED (2);
    4451             :           // XXX value might be modified by relocation
    4452           9 :           printf ("%*s[%2" PRIuMAX "] %s %" PRId16 "\n",
    4453             :                   indent, "", (uintmax_t) offset,
    4454           6 :                   op_name, read_2sbyte_unaligned (dbg, data));
    4455           3 :           CONSUME (2);
    4456           3 :           data += 2;
    4457           3 :           offset += 3;
    4458           3 :           break;
    4459             : 
    4460           0 :         case DW_OP_const4s:
    4461           0 :           NEED (4);
    4462             :           // XXX value might be modified by relocation
    4463           0 :           printf ("%*s[%2" PRIuMAX "] %s %" PRId32 "\n",
    4464             :                   indent, "", (uintmax_t) offset,
    4465           0 :                   op_name, read_4sbyte_unaligned (dbg, data));
    4466           0 :           CONSUME (4);
    4467           0 :           data += 4;
    4468           0 :           offset += 5;
    4469           0 :           break;
    4470             : 
    4471           0 :         case DW_OP_const8s:
    4472           0 :           NEED (8);
    4473             :           // XXX value might be modified by relocation
    4474           0 :           printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
    4475             :                   indent, "", (uintmax_t) offset,
    4476           0 :                   op_name, read_8sbyte_unaligned (dbg, data));
    4477           0 :           CONSUME (8);
    4478           0 :           data += 8;
    4479           0 :           offset += 9;
    4480           0 :           break;
    4481             : 
    4482        8030 :         case DW_OP_piece:
    4483             :         case DW_OP_regx:
    4484             :         case DW_OP_plus_uconst:
    4485             :         case DW_OP_constu:;
    4486        8030 :           const unsigned char *start = data;
    4487             :           uint64_t uleb;
    4488        8030 :           NEED (1);
    4489        8030 :           get_uleb128 (uleb, data, data + len);
    4490        8030 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
    4491             :                   indent, "", (uintmax_t) offset, op_name, uleb);
    4492        8030 :           CONSUME (data - start);
    4493        8030 :           offset += 1 + (data - start);
    4494        8030 :           break;
    4495             : 
    4496           2 :         case DW_OP_addrx:
    4497             :         case DW_OP_GNU_addr_index:
    4498             :         case DW_OP_constx:
    4499             :         case DW_OP_GNU_const_index:;
    4500           2 :           start = data;
    4501           2 :           NEED (1);
    4502           2 :           get_uleb128 (uleb, data, data + len);
    4503           2 :           printf ("%*s[%2" PRIuMAX "] %s [%" PRIu64 "] ",
    4504             :                   indent, "", (uintmax_t) offset, op_name, uleb);
    4505           2 :           CONSUME (data - start);
    4506           2 :           offset += 1 + (data - start);
    4507           2 :           if (get_indexed_addr (cu, uleb, &addr) != 0)
    4508             :             printf ("???\n");
    4509             :           else
    4510             :             {
    4511           2 :               print_dwarf_addr (dwflmod, 0, addr, addr);
    4512             :               printf ("\n");
    4513             :             }
    4514             :           break;
    4515             : 
    4516           0 :         case DW_OP_bit_piece:
    4517           0 :           start = data;
    4518             :           uint64_t uleb2;
    4519           0 :           NEED (1);
    4520           0 :           get_uleb128 (uleb, data, data + len);
    4521             :           NEED (1);
    4522           0 :           get_uleb128 (uleb2, data, data + len);
    4523           0 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
    4524             :                   indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
    4525           0 :           CONSUME (data - start);
    4526           0 :           offset += 1 + (data - start);
    4527           0 :           break;
    4528             : 
    4529       68137 :         case DW_OP_fbreg:
    4530             :         case DW_OP_breg0 ... DW_OP_breg31:
    4531             :         case DW_OP_consts:
    4532       68137 :           start = data;
    4533             :           int64_t sleb;
    4534       68137 :           NEED (1);
    4535       68137 :           get_sleb128 (sleb, data, data + len);
    4536       68137 :           printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
    4537             :                   indent, "", (uintmax_t) offset, op_name, sleb);
    4538       68137 :           CONSUME (data - start);
    4539       68137 :           offset += 1 + (data - start);
    4540       68137 :           break;
    4541             : 
    4542           0 :         case DW_OP_bregx:
    4543           0 :           start = data;
    4544           0 :           NEED (1);
    4545           0 :           get_uleb128 (uleb, data, data + len);
    4546             :           NEED (1);
    4547           0 :           get_sleb128 (sleb, data, data + len);
    4548           0 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
    4549             :                   indent, "", (uintmax_t) offset, op_name, uleb, sleb);
    4550           0 :           CONSUME (data - start);
    4551           0 :           offset += 1 + (data - start);
    4552           0 :           break;
    4553             : 
    4554           0 :         case DW_OP_call2:
    4555           0 :           NEED (2);
    4556           0 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx16 "]\n",
    4557             :                   indent, "", (uintmax_t) offset, op_name,
    4558           0 :                   read_2ubyte_unaligned (dbg, data));
    4559           0 :           CONSUME (2);
    4560           0 :           data += 2;
    4561           0 :           offset += 3;
    4562           0 :           break;
    4563             : 
    4564           1 :         case DW_OP_call4:
    4565           1 :           NEED (4);
    4566           3 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx32 "]\n",
    4567             :                   indent, "", (uintmax_t) offset, op_name,
    4568           2 :                   read_4ubyte_unaligned (dbg, data));
    4569           1 :           CONSUME (4);
    4570           1 :           data += 4;
    4571           1 :           offset += 5;
    4572           1 :           break;
    4573             : 
    4574         274 :         case DW_OP_skip:
    4575             :         case DW_OP_bra:
    4576         274 :           NEED (2);
    4577         274 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIuMAX "\n",
    4578             :                   indent, "", (uintmax_t) offset, op_name,
    4579         274 :                   (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
    4580         274 :           CONSUME (2);
    4581         274 :           data += 2;
    4582         274 :           offset += 3;
    4583         274 :           break;
    4584             : 
    4585         128 :         case DW_OP_implicit_value:
    4586         128 :           start = data;
    4587         128 :           NEED (1);
    4588         128 :           get_uleb128 (uleb, data, data + len);
    4589         128 :           printf ("%*s[%2" PRIuMAX "] %s: ",
    4590             :                   indent, "", (uintmax_t) offset, op_name);
    4591         128 :           NEED (uleb);
    4592         128 :           print_block (uleb, data);
    4593         128 :           data += uleb;
    4594         128 :           CONSUME (data - start);
    4595         128 :           offset += 1 + (data - start);
    4596         128 :           break;
    4597             : 
    4598        3538 :         case DW_OP_implicit_pointer:
    4599             :         case DW_OP_GNU_implicit_pointer:
    4600             :           /* DIE offset operand.  */
    4601        3538 :           start = data;
    4602        3538 :           NEED (ref_size);
    4603        3538 :           if (ref_size != 4 && ref_size != 8)
    4604             :             goto invalid; /* Cannot be used in CFA.  */
    4605        3538 :           if (ref_size == 4)
    4606        3538 :             addr = read_4ubyte_unaligned (dbg, data);
    4607             :           else
    4608           0 :             addr = read_8ubyte_unaligned (dbg, data);
    4609        3538 :           data += ref_size;
    4610             :           /* Byte offset operand.  */
    4611        3538 :           NEED (1);
    4612        3538 :           get_sleb128 (sleb, data, data + len);
    4613             : 
    4614        7076 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
    4615             :                   indent, "", (intmax_t) offset,
    4616             :                   op_name, (uintmax_t) addr, sleb);
    4617        3538 :           CONSUME (data - start);
    4618        3538 :           offset += 1 + (data - start);
    4619        3538 :           break;
    4620             : 
    4621       20865 :         case DW_OP_entry_value:
    4622             :         case DW_OP_GNU_entry_value:
    4623             :           /* Size plus expression block.  */
    4624       20865 :           start = data;
    4625       20865 :           NEED (1);
    4626       20865 :           get_uleb128 (uleb, data, data + len);
    4627       20865 :           printf ("%*s[%2" PRIuMAX "] %s:\n",
    4628             :                   indent, "", (uintmax_t) offset, op_name);
    4629       20865 :           NEED (uleb);
    4630       20865 :           print_ops (dwflmod, dbg, indent + 5, indent + 5, vers,
    4631             :                      addrsize, offset_size, cu, uleb, data);
    4632       20865 :           data += uleb;
    4633       20865 :           CONSUME (data - start);
    4634       20865 :           offset += 1 + (data - start);
    4635       20865 :           break;
    4636             : 
    4637           1 :         case DW_OP_const_type:
    4638             :         case DW_OP_GNU_const_type:
    4639             :           /* uleb128 CU relative DW_TAG_base_type DIE offset, 1-byte
    4640             :              unsigned size plus block.  */
    4641           1 :           start = data;
    4642           1 :           NEED (1);
    4643           1 :           get_uleb128 (uleb, data, data + len);
    4644           1 :           if (! print_unresolved_addresses && cu != NULL)
    4645           1 :             uleb += cu->start;
    4646             :           NEED (1);
    4647           1 :           uint8_t usize = *(uint8_t *) data++;
    4648           1 :           NEED (usize);
    4649           1 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] ",
    4650             :                   indent, "", (uintmax_t) offset, op_name, uleb);
    4651           1 :           print_block (usize, data);
    4652           1 :           data += usize;
    4653           1 :           CONSUME (data - start);
    4654           1 :           offset += 1 + (data - start);
    4655           1 :           break;
    4656             : 
    4657           0 :         case DW_OP_regval_type:
    4658             :         case DW_OP_GNU_regval_type:
    4659             :           /* uleb128 register number, uleb128 CU relative
    4660             :              DW_TAG_base_type DIE offset.  */
    4661           0 :           start = data;
    4662           0 :           NEED (1);
    4663           0 :           get_uleb128 (uleb, data, data + len);
    4664             :           NEED (1);
    4665           0 :           get_uleb128 (uleb2, data, data + len);
    4666           0 :           if (! print_unresolved_addresses && cu != NULL)
    4667           0 :             uleb2 += cu->start;
    4668           0 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
    4669             :                   indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
    4670           0 :           CONSUME (data - start);
    4671           0 :           offset += 1 + (data - start);
    4672           0 :           break;
    4673             : 
    4674           6 :         case DW_OP_deref_type:
    4675             :         case DW_OP_GNU_deref_type:
    4676             :           /* 1-byte unsigned size of value, uleb128 CU relative
    4677             :              DW_TAG_base_type DIE offset.  */
    4678           6 :           start = data;
    4679           6 :           NEED (1);
    4680           6 :           usize = *(uint8_t *) data++;
    4681             :           NEED (1);
    4682           6 :           get_uleb128 (uleb, data, data + len);
    4683           6 :           if (! print_unresolved_addresses && cu != NULL)
    4684           6 :             uleb += cu->start;
    4685          12 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
    4686             :                   indent, "", (uintmax_t) offset,
    4687             :                   op_name, usize, uleb);
    4688           6 :           CONSUME (data - start);
    4689           6 :           offset += 1 + (data - start);
    4690           6 :           break;
    4691             : 
    4692           0 :         case DW_OP_xderef_type:
    4693             :           /* 1-byte unsigned size of value, uleb128 base_type DIE offset.  */
    4694           0 :           start = data;
    4695           0 :           NEED (1);
    4696           0 :           usize = *(uint8_t *) data++;
    4697             :           NEED (1);
    4698           0 :           get_uleb128 (uleb, data, data + len);
    4699           0 :           printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
    4700             :                   indent, "", (uintmax_t) offset,
    4701             :                   op_name, usize, uleb);
    4702           0 :           CONSUME (data - start);
    4703           0 :           offset += 1 + (data - start);
    4704           0 :           break;
    4705             : 
    4706         306 :         case DW_OP_convert:
    4707             :         case DW_OP_GNU_convert:
    4708             :         case DW_OP_reinterpret:
    4709             :         case DW_OP_GNU_reinterpret:
    4710             :           /* uleb128 CU relative offset to DW_TAG_base_type, or zero
    4711             :              for conversion to untyped.  */
    4712         306 :           start = data;
    4713         306 :           NEED (1);
    4714         306 :           get_uleb128 (uleb, data, data + len);
    4715         306 :           if (uleb != 0 && ! print_unresolved_addresses && cu != NULL)
    4716         205 :             uleb += cu->start;
    4717         306 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
    4718             :                   indent, "", (uintmax_t) offset, op_name, uleb);
    4719         306 :           CONSUME (data - start);
    4720         306 :           offset += 1 + (data - start);
    4721         306 :           break;
    4722             : 
    4723          22 :         case DW_OP_GNU_parameter_ref:
    4724             :           /* 4 byte CU relative reference to the abstract optimized away
    4725             :              DW_TAG_formal_parameter.  */
    4726          22 :           NEED (4);
    4727          22 :           uintmax_t param_off = (uintmax_t) read_4ubyte_unaligned (dbg, data);
    4728          22 :           if (! print_unresolved_addresses && cu != NULL)
    4729          22 :             param_off += cu->start;
    4730          22 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
    4731             :                   indent, "", (uintmax_t) offset, op_name, param_off);
    4732          22 :           CONSUME (4);
    4733          22 :           data += 4;
    4734          22 :           offset += 5;
    4735          22 :           break;
    4736             : 
    4737      259456 :         default:
    4738             :           /* No Operand.  */
    4739      259456 :           printf ("%*s[%2" PRIuMAX "] %s\n",
    4740             :                   indent, "", (uintmax_t) offset, op_name);
    4741      259456 :           ++offset;
    4742      259456 :           break;
    4743             :         }
    4744             : 
    4745      381451 :       indent = indentrest;
    4746      381451 :       continue;
    4747             : 
    4748           0 :     invalid:
    4749           0 :       printf (gettext ("%*s[%2" PRIuMAX "] %s  <TRUNCATED>\n"),
    4750             :               indent, "", (uintmax_t) offset, op_name);
    4751             :       break;
    4752             :     }
    4753             : }
    4754             : 
    4755             : 
    4756             : struct listptr
    4757             : {
    4758             :   Dwarf_Off offset:(64 - 3);
    4759             :   bool addr64:1;
    4760             :   bool dwarf64:1;
    4761             :   bool warned:1;
    4762             :   struct Dwarf_CU *cu;
    4763             :   unsigned int attr;
    4764             : };
    4765             : 
    4766             : #define listptr_offset_size(p)  ((p)->dwarf64 ? 8 : 4)
    4767             : #define listptr_address_size(p) ((p)->addr64 ? 8 : 4)
    4768             : 
    4769             : static Dwarf_Addr
    4770       56961 : cudie_base (Dwarf_Die *cudie)
    4771             : {
    4772             :   Dwarf_Addr base;
    4773             :   /* Find the base address of the compilation unit.  It will normally
    4774             :      be specified by DW_AT_low_pc.  In DWARF-3 draft 4, the base
    4775             :      address could be overridden by DW_AT_entry_pc.  It's been
    4776             :      removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc for
    4777             :      compilation units with discontinuous ranges.  */
    4778       56961 :   if (unlikely (dwarf_lowpc (cudie, &base) != 0))
    4779             :     {
    4780             :       Dwarf_Attribute attr_mem;
    4781           0 :       if (dwarf_formaddr (dwarf_attr (cudie, DW_AT_entry_pc, &attr_mem),
    4782             :                           &base) != 0)
    4783           0 :         base = 0;
    4784             :     }
    4785       56961 :   return base;
    4786             : }
    4787             : 
    4788             : static Dwarf_Addr
    4789       56961 : listptr_base (struct listptr *p)
    4790             : {
    4791      113922 :   Dwarf_Die cu = CUDIE (p->cu);
    4792       56961 :   return cudie_base (&cu);
    4793             : }
    4794             : 
    4795             : static int
    4796      315410 : compare_listptr (const void *a, const void *b, void *arg)
    4797             : {
    4798      315410 :   const char *name = arg;
    4799      315410 :   struct listptr *p1 = (void *) a;
    4800      315410 :   struct listptr *p2 = (void *) b;
    4801             : 
    4802      315410 :   if (p1->offset < p2->offset)
    4803             :     return -1;
    4804       21297 :   if (p1->offset > p2->offset)
    4805             :     return 1;
    4806             : 
    4807        4268 :   if (!p1->warned && !p2->warned)
    4808             :     {
    4809        4268 :       if (p1->addr64 != p2->addr64)
    4810             :         {
    4811           0 :           p1->warned = p2->warned = true;
    4812           0 :           error (0, 0,
    4813           0 :                  gettext ("%s %#" PRIx64 " used with different address sizes"),
    4814             :                  name, (uint64_t) p1->offset);
    4815             :         }
    4816        4268 :       if (p1->dwarf64 != p2->dwarf64)
    4817             :         {
    4818           0 :           p1->warned = p2->warned = true;
    4819           0 :           error (0, 0,
    4820           0 :                  gettext ("%s %#" PRIx64 " used with different offset sizes"),
    4821           0 :                  name, (uint64_t) p1->offset);
    4822             :         }
    4823        4268 :       if (listptr_base (p1) != listptr_base (p2))
    4824             :         {
    4825           0 :           p1->warned = p2->warned = true;
    4826           0 :           error (0, 0,
    4827           0 :                  gettext ("%s %#" PRIx64 " used with different base addresses"),
    4828           0 :                  name, (uint64_t) p1->offset);
    4829             :         }
    4830        4268 :       if (p1->attr != p2 ->attr)
    4831             :         {
    4832           0 :           p1->warned = p2->warned = true;
    4833           0 :           error (0, 0,
    4834           0 :                  gettext ("%s %#" PRIx64
    4835             :                           " used with different attribute %s and %s"),
    4836           0 :                  name, (uint64_t) p1->offset, dwarf_attr_name (p2->attr),
    4837             :                  dwarf_attr_name (p2->attr));
    4838             :         }
    4839             :     }
    4840             : 
    4841             :   return 0;
    4842             : }
    4843             : 
    4844             : struct listptr_table
    4845             : {
    4846             :   size_t n;
    4847             :   size_t alloc;
    4848             :   struct listptr *table;
    4849             : };
    4850             : 
    4851             : static struct listptr_table known_locsptr;
    4852             : static struct listptr_table known_loclistsptr;
    4853             : static struct listptr_table known_rangelistptr;
    4854             : static struct listptr_table known_rnglistptr;
    4855             : static struct listptr_table known_addrbases;
    4856             : static struct listptr_table known_stroffbases;
    4857             : 
    4858             : static void
    4859             : reset_listptr (struct listptr_table *table)
    4860             : {
    4861         870 :   free (table->table);
    4862         870 :   table->table = NULL;
    4863         870 :   table->n = table->alloc = 0;
    4864             : }
    4865             : 
    4866             : /* Returns false if offset doesn't fit.  See struct listptr.  */
    4867             : static bool
    4868       52605 : notice_listptr (enum section_e section, struct listptr_table *table,
    4869             :                 uint_fast8_t address_size, uint_fast8_t offset_size,
    4870             :                 struct Dwarf_CU *cu, Dwarf_Off offset, unsigned int attr)
    4871             : {
    4872       52605 :   if (print_debug_sections & section)
    4873             :     {
    4874       52504 :       if (table->n == table->alloc)
    4875             :         {
    4876         175 :           if (table->alloc == 0)
    4877          81 :             table->alloc = 128;
    4878             :           else
    4879          94 :             table->alloc *= 2;
    4880         175 :           table->table = xrealloc (table->table,
    4881         175 :                                    table->alloc * sizeof table->table[0]);
    4882             :         }
    4883             : 
    4884       52504 :       struct listptr *p = &table->table[table->n++];
    4885             : 
    4886      105008 :       *p = (struct listptr)
    4887             :         {
    4888       52504 :           .addr64 = address_size == 8,
    4889       52504 :           .dwarf64 = offset_size == 8,
    4890             :           .offset = offset,
    4891             :           .cu = cu,
    4892             :           .attr = attr
    4893             :         };
    4894             : 
    4895       52504 :       if (p->offset != offset)
    4896             :         {
    4897           0 :           table->n--;
    4898           0 :           return false;
    4899             :         }
    4900             :     }
    4901             :   return true;
    4902             : }
    4903             : 
    4904             : static void
    4905             : sort_listptr (struct listptr_table *table, const char *name)
    4906             : {
    4907          85 :   if (table->n > 0)
    4908          81 :     qsort_r (table->table, table->n, sizeof table->table[0],
    4909             :              &compare_listptr, (void *) name);
    4910             : }
    4911             : 
    4912             : static bool
    4913       48419 : skip_listptr_hole (struct listptr_table *table, size_t *idxp,
    4914             :                    uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
    4915             :                    Dwarf_Addr *base, struct Dwarf_CU **cu, ptrdiff_t offset,
    4916             :                    unsigned char **readp, unsigned char *endp,
    4917             :                    unsigned int *attr)
    4918             : {
    4919       48419 :   if (table->n == 0)
    4920             :     return false;
    4921             : 
    4922      100822 :   while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
    4923       52403 :     ++*idxp;
    4924             : 
    4925       48419 :   struct listptr *p = &table->table[*idxp];
    4926             : 
    4927       48419 :   if (*idxp == table->n
    4928       48419 :       || p->offset >= (Dwarf_Off) (endp - *readp + offset))
    4929             :     {
    4930           0 :       *readp = endp;
    4931           0 :       printf (gettext (" [%6tx]  <UNUSED GARBAGE IN REST OF SECTION>\n"),
    4932             :               offset);
    4933             :       return true;
    4934             :     }
    4935             : 
    4936       48419 :   if (p->offset != (Dwarf_Off) offset)
    4937             :     {
    4938           0 :       *readp += p->offset - offset;
    4939           0 :       printf (gettext (" [%6tx]  <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
    4940             :               offset, (Dwarf_Off) p->offset - offset);
    4941             :       return true;
    4942             :     }
    4943             : 
    4944       48419 :   if (address_sizep != NULL)
    4945       48419 :     *address_sizep = listptr_address_size (p);
    4946       48419 :   if (offset_sizep != NULL)
    4947       39494 :     *offset_sizep = listptr_offset_size (p);
    4948       48419 :   if (base != NULL)
    4949       48419 :     *base = listptr_base (p);
    4950       48419 :   if (cu != NULL)
    4951       48419 :     *cu = p->cu;
    4952       48419 :   if (attr != NULL)
    4953       39494 :     *attr = p->attr;
    4954             : 
    4955             :   return false;
    4956             : }
    4957             : 
    4958             : static Dwarf_Off
    4959             : next_listptr_offset (struct listptr_table *table, size_t idx)
    4960             : {
    4961             :   /* Note that multiple attributes could in theory point to the same loclist
    4962             :      offset, so make sure we pick one that is bigger than the current one.
    4963             :      The table is sorted on offset.  */
    4964           0 :   Dwarf_Off offset = table->table[idx].offset;
    4965           0 :   while (++idx < table->n)
    4966             :     {
    4967           0 :       Dwarf_Off next = table->table[idx].offset;
    4968           0 :       if (next > offset)
    4969             :         return next;
    4970             :     }
    4971             :   return 0;
    4972             : }
    4973             : 
    4974             : /* Returns the listptr associated with the given index, or NULL.  */
    4975             : static struct listptr *
    4976             : get_listptr (struct listptr_table *table, size_t idx)
    4977             : {
    4978          10 :   if (idx >= table->n)
    4979             :     return NULL;
    4980           5 :   return &table->table[idx];
    4981             : }
    4982             : 
    4983             : /* Returns the next index, base address and CU associated with the
    4984             :    list unit offsets.  If there is none false is returned, otherwise
    4985             :    true.  Assumes the table has been sorted.  */
    4986             : static bool
    4987           6 : listptr_cu (struct listptr_table *table, size_t *idxp,
    4988             :             Dwarf_Off start, Dwarf_Off end,
    4989             :             Dwarf_Addr *base, struct Dwarf_CU **cu)
    4990             : {
    4991          14 :   while (*idxp < table->n
    4992          14 :          && table->table[*idxp].offset < start)
    4993           8 :     ++*idxp;
    4994             : 
    4995           6 :   if (*idxp < table->n
    4996           6 :       && table->table[*idxp].offset >= start
    4997           6 :       && table->table[*idxp].offset < end)
    4998             :     {
    4999           6 :       struct listptr *p = &table->table[*idxp];
    5000           6 :       *base = listptr_base (p);
    5001           6 :       *cu = p->cu;
    5002           6 :       ++*idxp;
    5003             :       return true;
    5004             :     }
    5005             : 
    5006             :   return false;
    5007             : }
    5008             : 
    5009             : static void
    5010          40 : print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
    5011             :                             Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
    5012             :                             Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    5013             : {
    5014          80 :   const size_t sh_size = (dbg->sectiondata[IDX_debug_abbrev] ?
    5015          40 :                           dbg->sectiondata[IDX_debug_abbrev]->d_size : 0);
    5016             : 
    5017          80 :   printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
    5018             :                    " [ Code]\n"),
    5019             :           elf_ndxscn (scn), section_name (ebl, shdr),
    5020          40 :           (uint64_t) shdr->sh_offset);
    5021             : 
    5022          40 :   Dwarf_Off offset = 0;
    5023          40 :   while (offset < sh_size)
    5024             :     {
    5025        1087 :       printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
    5026             :               offset);
    5027             : 
    5028             :       while (1)
    5029       56639 :         {
    5030             :           size_t length;
    5031             :           Dwarf_Abbrev abbrev;
    5032             : 
    5033       57726 :           int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
    5034       57726 :           if (res != 0)
    5035             :             {
    5036        1087 :               if (unlikely (res < 0))
    5037             :                 {
    5038           0 :                   printf (gettext ("\
    5039             :  *** error while reading abbreviation: %s\n"),
    5040             :                           dwarf_errmsg (-1));
    5041           0 :                   return;
    5042             :                 }
    5043             : 
    5044             :               /* This is the NUL byte at the end of the section.  */
    5045        1087 :               ++offset;
    5046        1087 :               break;
    5047             :             }
    5048             : 
    5049             :           /* We know these calls can never fail.  */
    5050       56639 :           unsigned int code = dwarf_getabbrevcode (&abbrev);
    5051       56639 :           unsigned int tag = dwarf_getabbrevtag (&abbrev);
    5052       56639 :           int has_children = dwarf_abbrevhaschildren (&abbrev);
    5053             : 
    5054      113278 :           printf (gettext (" [%5u] offset: %" PRId64
    5055             :                            ", children: %s, tag: %s\n"),
    5056             :                   code, (int64_t) offset,
    5057             :                   has_children ? yes_str : no_str,
    5058             :                   dwarf_tag_name (tag));
    5059             : 
    5060       56639 :           size_t cnt = 0;
    5061             :           unsigned int name;
    5062             :           unsigned int form;
    5063             :           Dwarf_Sword data;
    5064             :           Dwarf_Off enoffset;
    5065      332133 :           while (dwarf_getabbrevattr_data (&abbrev, cnt, &name, &form,
    5066             :                                            &data, &enoffset) == 0)
    5067             :             {
    5068      437710 :               printf ("          attr: %s, form: %s",
    5069             :                       dwarf_attr_name (name), dwarf_form_name (form));
    5070      218855 :               if (form == DW_FORM_implicit_const)
    5071           0 :                 printf (" (%" PRId64 ")", data);
    5072      437710 :               printf (", offset: %#" PRIx64 "\n", (uint64_t) enoffset);
    5073      218855 :               ++cnt;
    5074             :             }
    5075             : 
    5076       56639 :           offset += length;
    5077             :         }
    5078             :     }
    5079             : }
    5080             : 
    5081             : 
    5082             : static void
    5083           2 : print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
    5084             :                           Ebl *ebl, GElf_Ehdr *ehdr,
    5085             :                           Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    5086             : {
    5087           4 :   printf (gettext ("\
    5088             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    5089             :           elf_ndxscn (scn), section_name (ebl, shdr),
    5090           2 :           (uint64_t) shdr->sh_offset);
    5091             : 
    5092           2 :   if (shdr->sh_size == 0)
    5093             :     return;
    5094             : 
    5095             :   /* We like to get the section from libdw to make sure they are relocated.  */
    5096           4 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_addr]
    5097           2 :                     ?: elf_rawdata (scn, NULL));
    5098           2 :   if (unlikely (data == NULL))
    5099             :     {
    5100           0 :       error (0, 0, gettext ("cannot get .debug_addr section data: %s"),
    5101             :              elf_errmsg (-1));
    5102             :       return;
    5103             :     }
    5104             : 
    5105           2 :   size_t idx = 0;
    5106           4 :   sort_listptr (&known_addrbases, "addr_base");
    5107             : 
    5108           2 :   const unsigned char *start = (const unsigned char *) data->d_buf;
    5109           2 :   const unsigned char *readp = start;
    5110           2 :   const unsigned char *readendp = ((const unsigned char *) data->d_buf
    5111           2 :                                    + data->d_size);
    5112             : 
    5113           8 :   while (readp < readendp)
    5114             :     {
    5115             :       /* We cannot really know whether or not there is an header.  The
    5116             :          DebugFission extension to DWARF4 doesn't add one.  The DWARF5
    5117             :          .debug_addr variant does.  Whether or not we have an header,
    5118             :          DW_AT_[GNU_]addr_base points at "index 0".  So if the current
    5119             :          offset equals the CU addr_base then we can just start
    5120             :          printing addresses.  If there is no CU with an exact match
    5121             :          then we'll try to parse the header first.  */
    5122           4 :       Dwarf_Off off = (Dwarf_Off) (readp
    5123           4 :                                    - (const unsigned char *) data->d_buf);
    5124             : 
    5125           4 :       printf ("Table at offset %" PRIx64 " ", off);
    5126             : 
    5127           8 :       struct listptr *listptr = get_listptr (&known_addrbases, idx++);
    5128             :       const unsigned char *next_unitp;
    5129             : 
    5130             :       uint64_t unit_length;
    5131             :       uint16_t version;
    5132             :       uint8_t address_size;
    5133             :       uint8_t segment_size;
    5134           4 :       if (listptr == NULL)
    5135             :         {
    5136           0 :           error (0, 0, "Warning: No CU references .debug_addr after %" PRIx64,
    5137             :                  off);
    5138             : 
    5139             :           /* We will have to assume it is just addresses to the end... */
    5140           0 :           address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    5141           0 :           next_unitp = readendp;
    5142             :           printf ("Unknown CU:\n");
    5143             :         }
    5144             :       else
    5145             :         {
    5146             :           Dwarf_Die cudie;
    5147           4 :           if (dwarf_cu_die (listptr->cu, &cudie,
    5148             :                             NULL, NULL, NULL, NULL,
    5149             :                             NULL, NULL) == NULL)
    5150           0 :             printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
    5151             :           else
    5152           4 :             printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
    5153             : 
    5154           4 :           if (listptr->offset == off)
    5155             :             {
    5156           2 :               address_size = listptr_address_size (listptr);
    5157           2 :               segment_size = 0;
    5158           2 :               version = 4;
    5159             : 
    5160             :               /* The addresses start here, but where do they end?  */
    5161           3 :               listptr = get_listptr (&known_addrbases, idx);
    5162           1 :               if (listptr == NULL)
    5163             :                 next_unitp = readendp;
    5164           1 :               else if (listptr->cu->version < 5)
    5165             :                 {
    5166           1 :                   next_unitp = start + listptr->offset;
    5167           1 :                   if (listptr->offset < off || listptr->offset > data->d_size)
    5168             :                     {
    5169           0 :                       error (0, 0,
    5170             :                              "Warning: Bad address base for next unit at %"
    5171             :                              PRIx64, off);
    5172           0 :                       next_unitp = readendp;
    5173             :                     }
    5174             :                 }
    5175             :               else
    5176             :                 {
    5177             :                   /* Tricky, we don't have a header for this unit, but
    5178             :                      there is one for the next.  We will have to
    5179             :                      "guess" how big it is and subtract it from the
    5180             :                      offset (because that points after the header).  */
    5181           0 :                   unsigned int offset_size = listptr_offset_size (listptr);
    5182           0 :                   Dwarf_Off next_off = (listptr->offset
    5183           0 :                                         - (offset_size == 4 ? 4 : 12) /* len */
    5184             :                                         - 2 /* version */
    5185             :                                         - 1 /* address size */
    5186           0 :                                         - 1); /* segment selector size */
    5187           0 :                   next_unitp = start + next_off;
    5188           0 :                   if (next_off < off || next_off > data->d_size)
    5189             :                     {
    5190           0 :                       error (0, 0,
    5191             :                              "Warning: Couldn't calculate .debug_addr "
    5192             :                              " unit lenght at %" PRIx64, off);
    5193           0 :                       next_unitp = readendp;
    5194             :                     }
    5195             :                 }
    5196           2 :               unit_length = (uint64_t) (next_unitp - readp);
    5197             : 
    5198             :               /* Pretend we have a header.  */
    5199           2 :               printf ("\n");
    5200           4 :               printf (gettext (" Length:         %8" PRIu64 "\n"),
    5201             :                       unit_length);
    5202           4 :               printf (gettext (" DWARF version:  %8" PRIu16 "\n"), version);
    5203           4 :               printf (gettext (" Address size:   %8" PRIu64 "\n"),
    5204             :                       (uint64_t) address_size);
    5205           4 :               printf (gettext (" Segment size:   %8" PRIu64 "\n"),
    5206             :                       (uint64_t) segment_size);
    5207             :               printf ("\n");
    5208             :             }
    5209             :           else
    5210             :             {
    5211             :               /* OK, we have to parse an header first.  */
    5212           2 :               unit_length = read_4ubyte_unaligned_inc (dbg, readp);
    5213           2 :               if (unlikely (unit_length == 0xffffffff))
    5214             :                 {
    5215           0 :                   if (unlikely (readp > readendp - 8))
    5216             :                     {
    5217           0 :                     invalid_data:
    5218           0 :                       error (0, 0, "Invalid data");
    5219           0 :                       return;
    5220             :                     }
    5221           0 :                   unit_length = read_8ubyte_unaligned_inc (dbg, readp);
    5222             :                 }
    5223           2 :               printf ("\n");
    5224           4 :               printf (gettext (" Length:         %8" PRIu64 "\n"),
    5225             :                       unit_length);
    5226             : 
    5227             :               /* We need at least 2-bytes (version) + 1-byte
    5228             :                  (addr_size) + 1-byte (segment_size) = 4 bytes to
    5229             :                  complete the header.  And this unit cannot go beyond
    5230             :                  the section data.  */
    5231           2 :               if (readp > readendp - 4
    5232           2 :                   || unit_length < 4
    5233           2 :                   || unit_length > (uint64_t) (readendp - readp))
    5234             :                 goto invalid_data;
    5235             : 
    5236           2 :               next_unitp = readp + unit_length;
    5237             : 
    5238           2 :               version = read_2ubyte_unaligned_inc (dbg, readp);
    5239           4 :               printf (gettext (" DWARF version:  %8" PRIu16 "\n"), version);
    5240             : 
    5241           2 :               if (version != 5)
    5242             :                 {
    5243           0 :                   error (0, 0, gettext ("Unknown version"));
    5244           0 :                   goto next_unit;
    5245             :                 }
    5246             : 
    5247           2 :               address_size = *readp++;
    5248           4 :               printf (gettext (" Address size:   %8" PRIu64 "\n"),
    5249             :                       (uint64_t) address_size);
    5250             : 
    5251           2 :               if (address_size != 4 && address_size != 8)
    5252             :                 {
    5253           0 :                   error (0, 0, gettext ("unsupported address size"));
    5254             :                   goto next_unit;
    5255             :                 }
    5256             : 
    5257           2 :               segment_size = *readp++;
    5258           4 :               printf (gettext (" Segment size:   %8" PRIu64 "\n"),
    5259             :                       (uint64_t) segment_size);
    5260           2 :               printf ("\n");
    5261             : 
    5262           2 :               if (segment_size != 0)
    5263             :                 {
    5264           0 :                   error (0, 0, gettext ("unsupported segment size"));
    5265             :                   goto next_unit;
    5266             :                 }
    5267             : 
    5268           2 :               if (listptr->offset != (Dwarf_Off) (readp - start))
    5269             :                 {
    5270             :                   error (0, 0, "Address index doesn't start after header");
    5271             :                   goto next_unit;
    5272             :                 }
    5273             :             }
    5274             :         }
    5275             : 
    5276           4 :       int digits = 1;
    5277           4 :       size_t addresses = (next_unitp - readp) / address_size;
    5278          12 :       while (addresses >= 10)
    5279             :         {
    5280           4 :           ++digits;
    5281           4 :           addresses /= 10;
    5282             :         }
    5283             : 
    5284           4 :       unsigned int uidx = 0;
    5285           4 :       size_t index_offset =  readp - (const unsigned char *) data->d_buf;
    5286             :       printf (" Addresses start at offset 0x%zx:\n", index_offset);
    5287          76 :       while (readp <= next_unitp - address_size)
    5288             :         {
    5289          72 :           Dwarf_Addr addr = read_addr_unaligned_inc (address_size, dbg,
    5290             :                                                      readp);
    5291         144 :           printf (" [%*u] ", digits, uidx++);
    5292          72 :           print_dwarf_addr (dwflmod, address_size, addr, addr);
    5293             :           printf ("\n");
    5294             :         }
    5295           4 :       printf ("\n");
    5296             : 
    5297           4 :       if (readp != next_unitp)
    5298           0 :         error (0, 0, "extra %zd bytes at end of unit",
    5299           0 :                (size_t) (next_unitp - readp));
    5300             : 
    5301           4 :     next_unit:
    5302             :       readp = next_unitp;
    5303             :     }
    5304             : }
    5305             : 
    5306             : /* Print content of DWARF .debug_aranges section.  We fortunately do
    5307             :    not have to know a bit about the structure of the section, libdwarf
    5308             :    takes care of it.  */
    5309             : static void
    5310           1 : print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
    5311             :                                GElf_Shdr *shdr, Dwarf *dbg)
    5312             : {
    5313             :   Dwarf_Aranges *aranges;
    5314             :   size_t cnt;
    5315           1 :   if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
    5316             :     {
    5317           0 :       error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
    5318             :              dwarf_errmsg (-1));
    5319           0 :       return;
    5320             :     }
    5321             : 
    5322             :   GElf_Shdr glink_mem;
    5323             :   GElf_Shdr *glink;
    5324           1 :   glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
    5325           1 :   if (glink == NULL)
    5326             :     {
    5327           0 :       error (0, 0, gettext ("invalid sh_link value in section %zu"),
    5328             :              elf_ndxscn (scn));
    5329             :       return;
    5330             :     }
    5331             : 
    5332           3 :   printf (ngettext ("\
    5333             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
    5334             :                     "\
    5335             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
    5336             :                     cnt),
    5337             :           elf_ndxscn (scn), section_name (ebl, shdr),
    5338           1 :           (uint64_t) shdr->sh_offset, cnt);
    5339             : 
    5340             :   /* Compute floor(log16(cnt)).  */
    5341           1 :   size_t tmp = cnt;
    5342           1 :   int digits = 1;
    5343           1 :   while (tmp >= 16)
    5344             :     {
    5345           0 :       ++digits;
    5346           0 :       tmp >>= 4;
    5347             :     }
    5348             : 
    5349           5 :   for (size_t n = 0; n < cnt; ++n)
    5350             :     {
    5351           5 :       Dwarf_Arange *runp = dwarf_onearange (aranges, n);
    5352           5 :       if (unlikely (runp == NULL))
    5353             :         {
    5354           0 :           printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
    5355           0 :           return;
    5356             :         }
    5357             : 
    5358             :       Dwarf_Addr start;
    5359             :       Dwarf_Word length;
    5360             :       Dwarf_Off offset;
    5361             : 
    5362           5 :       if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
    5363           0 :         printf (gettext (" [%*zu] ???\n"), digits, n);
    5364             :       else
    5365          10 :         printf (gettext (" [%*zu] start: %0#*" PRIx64
    5366             :                          ", length: %5" PRIu64 ", CU DIE offset: %6"
    5367             :                          PRId64 "\n"),
    5368           5 :                 digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
    5369             :                 (uint64_t) start, (uint64_t) length, (int64_t) offset);
    5370             :     }
    5371             : }
    5372             : 
    5373             : 
    5374             : /* Print content of DWARF .debug_aranges section.  */
    5375             : static void
    5376          44 : print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
    5377             :                              Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
    5378             :                              GElf_Shdr *shdr, Dwarf *dbg)
    5379             : {
    5380          44 :   if (decodedaranges)
    5381             :     {
    5382           1 :       print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg);
    5383           1 :       return;
    5384             :     }
    5385             : 
    5386          86 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_aranges]
    5387          43 :                     ?: elf_rawdata (scn, NULL));
    5388             : 
    5389          43 :   if (unlikely (data == NULL))
    5390             :     {
    5391           0 :       error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
    5392             :              elf_errmsg (-1));
    5393             :       return;
    5394             :     }
    5395             : 
    5396          86 :   printf (gettext ("\
    5397             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    5398             :           elf_ndxscn (scn), section_name (ebl, shdr),
    5399          43 :           (uint64_t) shdr->sh_offset);
    5400             : 
    5401          43 :   const unsigned char *readp = data->d_buf;
    5402          43 :   const unsigned char *readendp = readp + data->d_size;
    5403             : 
    5404        1170 :   while (readp < readendp)
    5405             :     {
    5406        1084 :       const unsigned char *hdrstart = readp;
    5407        1084 :       size_t start_offset = hdrstart - (const unsigned char *) data->d_buf;
    5408             : 
    5409        2168 :       printf (gettext ("\nTable at offset %zu:\n"), start_offset);
    5410        1084 :       if (readp + 4 > readendp)
    5411             :         {
    5412           0 :         invalid_data:
    5413           0 :           error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
    5414             :                  elf_ndxscn (scn), section_name (ebl, shdr));
    5415             :           return;
    5416             :         }
    5417             : 
    5418        1104 :       Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
    5419        1084 :       unsigned int length_bytes = 4;
    5420        1084 :       if (length == DWARF3_LENGTH_64_BIT)
    5421             :         {
    5422           0 :           if (readp + 8 > readendp)
    5423             :             goto invalid_data;
    5424           0 :           length = read_8ubyte_unaligned_inc (dbg, readp);
    5425           0 :           length_bytes = 8;
    5426             :         }
    5427             : 
    5428        1084 :       const unsigned char *nexthdr = readp + length;
    5429        2168 :       printf (gettext ("\n Length:        %6" PRIu64 "\n"),
    5430             :               (uint64_t) length);
    5431             : 
    5432        1084 :       if (unlikely (length > (size_t) (readendp - readp)))
    5433             :         goto invalid_data;
    5434             : 
    5435        1084 :       if (length == 0)
    5436           0 :         continue;
    5437             : 
    5438        1084 :       if (readp + 2 > readendp)
    5439             :         goto invalid_data;
    5440        1104 :       uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, readp);
    5441        2168 :       printf (gettext (" DWARF version: %6" PRIuFAST16 "\n"),
    5442             :               version);
    5443        1084 :       if (version != 2)
    5444             :         {
    5445           0 :           error (0, 0, gettext ("unsupported aranges version"));
    5446             :           goto next_table;
    5447             :         }
    5448             : 
    5449             :       Dwarf_Word offset;
    5450        1084 :       if (readp + length_bytes > readendp)
    5451             :         goto invalid_data;
    5452        1084 :       if (length_bytes == 8)
    5453           0 :         offset = read_8ubyte_unaligned_inc (dbg, readp);
    5454             :       else
    5455        1104 :         offset = read_4ubyte_unaligned_inc (dbg, readp);
    5456        2168 :       printf (gettext (" CU offset:     %6" PRIx64 "\n"),
    5457             :               (uint64_t) offset);
    5458             : 
    5459        1084 :       if (readp + 1 > readendp)
    5460             :         goto invalid_data;
    5461        1084 :       unsigned int address_size = *readp++;
    5462        2168 :       printf (gettext (" Address size:  %6" PRIu64 "\n"),
    5463             :               (uint64_t) address_size);
    5464        1084 :       if (address_size != 4 && address_size != 8)
    5465             :         {
    5466           0 :           error (0, 0, gettext ("unsupported address size"));
    5467             :           goto next_table;
    5468             :         }
    5469             : 
    5470        1084 :       if (readp + 1 > readendp)
    5471             :         goto invalid_data;
    5472        1084 :       unsigned int segment_size = *readp++;
    5473        2168 :       printf (gettext (" Segment size:  %6" PRIu64 "\n\n"),
    5474             :               (uint64_t) segment_size);
    5475        1084 :       if (segment_size != 0 && segment_size != 4 && segment_size != 8)
    5476             :         {
    5477           0 :           error (0, 0, gettext ("unsupported segment size"));
    5478             :           goto next_table;
    5479             :         }
    5480             : 
    5481             :       /* Round the address to the next multiple of 2*address_size.  */
    5482        2168 :       readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
    5483        1084 :                 % (2 * address_size));
    5484             : 
    5485        3285 :       while (readp < nexthdr)
    5486             :         {
    5487             :           Dwarf_Word range_address;
    5488             :           Dwarf_Word range_length;
    5489        2201 :           Dwarf_Word segment = 0;
    5490        2201 :           if (readp + 2 * address_size + segment_size > readendp)
    5491             :             goto invalid_data;
    5492        2201 :           if (address_size == 4)
    5493             :             {
    5494          36 :               range_address = read_4ubyte_unaligned_inc (dbg, readp);
    5495          36 :               range_length = read_4ubyte_unaligned_inc (dbg, readp);
    5496             :             }
    5497             :           else
    5498             :             {
    5499        2203 :               range_address = read_8ubyte_unaligned_inc (dbg, readp);
    5500        2203 :               range_length = read_8ubyte_unaligned_inc (dbg, readp);
    5501             :             }
    5502             : 
    5503        2201 :           if (segment_size == 4)
    5504           0 :             segment = read_4ubyte_unaligned_inc (dbg, readp);
    5505        2201 :           else if (segment_size == 8)
    5506           0 :             segment = read_8ubyte_unaligned_inc (dbg, readp);
    5507             : 
    5508        2201 :           if (range_address == 0 && range_length == 0 && segment == 0)
    5509             :             break;
    5510             : 
    5511        1117 :           printf ("   ");
    5512        1117 :           print_dwarf_addr (dwflmod, address_size, range_address,
    5513             :                             range_address);
    5514        1117 :           printf ("..");
    5515        1117 :           print_dwarf_addr (dwflmod, address_size,
    5516        1117 :                             range_address + range_length - 1,
    5517             :                             range_length);
    5518        1117 :           if (segment_size != 0)
    5519             :             printf (" (%" PRIx64 ")\n", (uint64_t) segment);
    5520             :           else
    5521             :             printf ("\n");
    5522             :         }
    5523             : 
    5524        1084 :     next_table:
    5525        1084 :       if (readp != nexthdr)
    5526             :         {
    5527           0 :           size_t padding = nexthdr - readp;
    5528           0 :           printf (gettext ("   %zu padding bytes\n"), padding);
    5529           0 :           readp = nexthdr;
    5530             :         }
    5531             :     }
    5532             : }
    5533             : 
    5534             : 
    5535             : static bool is_split_dwarf (Dwarf *dbg, uint64_t *id, Dwarf_CU **split_cu);
    5536             : 
    5537             : /* Returns true and sets cu and cu_base if the given Dwarf is a split
    5538             :    DWARF (.dwo) file.  */
    5539             : static bool
    5540           0 : split_dwarf_cu_base (Dwarf *dbg, Dwarf_CU **cu, Dwarf_Addr *cu_base)
    5541             : {
    5542             :   uint64_t id;
    5543           0 :   if (is_split_dwarf (dbg, &id, cu))
    5544             :     {
    5545             :       Dwarf_Die cudie;
    5546           0 :       if (dwarf_cu_info (*cu, NULL, NULL, &cudie, NULL, NULL, NULL, NULL) == 0)
    5547             :         {
    5548           0 :           *cu_base = cudie_base (&cudie);
    5549           0 :           return true;
    5550             :         }
    5551             :     }
    5552             :   return false;
    5553             : }
    5554             : 
    5555             : /* Print content of DWARF .debug_rnglists section.  */
    5556             : static void
    5557           2 : print_debug_rnglists_section (Dwfl_Module *dwflmod,
    5558             :                               Ebl *ebl,
    5559             :                               GElf_Ehdr *ehdr __attribute__ ((unused)),
    5560             :                               Elf_Scn *scn, GElf_Shdr *shdr,
    5561             :                               Dwarf *dbg __attribute__((unused)))
    5562             : {
    5563           4 :   printf (gettext ("\
    5564             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    5565             :           elf_ndxscn (scn), section_name (ebl, shdr),
    5566           2 :           (uint64_t) shdr->sh_offset);
    5567             : 
    5568           4 :   Elf_Data *data =(dbg->sectiondata[IDX_debug_rnglists]
    5569           2 :                    ?: elf_rawdata (scn, NULL));
    5570           2 :   if (unlikely (data == NULL))
    5571             :     {
    5572           0 :       error (0, 0, gettext ("cannot get .debug_rnglists content: %s"),
    5573             :              elf_errmsg (-1));
    5574           0 :       return;
    5575             :     }
    5576             : 
    5577             :   /* For the listptr to get the base address/CU.  */
    5578           4 :   sort_listptr (&known_rnglistptr, "rnglistptr");
    5579           2 :   size_t listptr_idx = 0;
    5580             : 
    5581           2 :   const unsigned char *readp = data->d_buf;
    5582           2 :   const unsigned char *const dataend = ((unsigned char *) data->d_buf
    5583           2 :                                         + data->d_size);
    5584           6 :   while (readp < dataend)
    5585             :     {
    5586           2 :       if (unlikely (readp > dataend - 4))
    5587             :         {
    5588           0 :         invalid_data:
    5589           0 :           error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
    5590             :                  elf_ndxscn (scn), section_name (ebl, shdr));
    5591           0 :           return;
    5592             :         }
    5593             : 
    5594           2 :       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
    5595           4 :       printf (gettext ("Table at Offset 0x%" PRIx64 ":\n\n"),
    5596             :               (uint64_t) offset);
    5597             : 
    5598           2 :       uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
    5599           2 :       unsigned int offset_size = 4;
    5600           2 :       if (unlikely (unit_length == 0xffffffff))
    5601             :         {
    5602           0 :           if (unlikely (readp > dataend - 8))
    5603             :             goto invalid_data;
    5604             : 
    5605           0 :           unit_length = read_8ubyte_unaligned_inc (dbg, readp);
    5606           0 :           offset_size = 8;
    5607             :         }
    5608           4 :       printf (gettext (" Length:         %8" PRIu64 "\n"), unit_length);
    5609             : 
    5610             :       /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
    5611             :          bytes to complete the header.  And this unit cannot go beyond
    5612             :          the section data.  */
    5613           2 :       if (readp > dataend - 8
    5614           2 :           || unit_length < 8
    5615           2 :           || unit_length > (uint64_t) (dataend - readp))
    5616             :         goto invalid_data;
    5617             : 
    5618           2 :       const unsigned char *nexthdr = readp + unit_length;
    5619             : 
    5620           2 :       uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
    5621           4 :       printf (gettext (" DWARF version:  %8" PRIu16 "\n"), version);
    5622             : 
    5623           2 :       if (version != 5)
    5624             :         {
    5625           0 :           error (0, 0, gettext ("Unknown version"));
    5626             :           goto next_table;
    5627             :         }
    5628             : 
    5629           2 :       uint8_t address_size = *readp++;
    5630           4 :       printf (gettext (" Address size:   %8" PRIu64 "\n"),
    5631             :               (uint64_t) address_size);
    5632             : 
    5633           2 :       if (address_size != 4 && address_size != 8)
    5634             :         {
    5635           0 :           error (0, 0, gettext ("unsupported address size"));
    5636             :           goto next_table;
    5637             :         }
    5638             : 
    5639           2 :       uint8_t segment_size = *readp++;
    5640           4 :       printf (gettext (" Segment size:   %8" PRIu64 "\n"),
    5641             :               (uint64_t) segment_size);
    5642             : 
    5643           2 :       if (segment_size != 0 && segment_size != 4 && segment_size != 8)
    5644             :         {
    5645           0 :           error (0, 0, gettext ("unsupported segment size"));
    5646             :           goto next_table;
    5647             :         }
    5648             : 
    5649           2 :       uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
    5650           4 :       printf (gettext (" Offset entries: %8" PRIu64 "\n"),
    5651             :               (uint64_t) offset_entry_count);
    5652             : 
    5653             :       /* We need the CU that uses this unit to get the initial base address. */
    5654           2 :       Dwarf_Addr cu_base = 0;
    5655           2 :       struct Dwarf_CU *cu = NULL;
    5656           2 :       if (listptr_cu (&known_rnglistptr, &listptr_idx,
    5657             :                       (Dwarf_Off) offset,
    5658           2 :                       (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
    5659             :                       &cu_base, &cu)
    5660           0 :           || split_dwarf_cu_base (dbg, &cu, &cu_base))
    5661           2 :         {
    5662             :           Dwarf_Die cudie;
    5663           2 :           if (dwarf_cu_die (cu, &cudie,
    5664             :                             NULL, NULL, NULL, NULL,
    5665             :                             NULL, NULL) == NULL)
    5666           0 :             printf (gettext (" Unknown CU base: "));
    5667             :           else
    5668           2 :             printf (gettext (" CU [%6" PRIx64 "] base: "),
    5669             :                     dwarf_dieoffset (&cudie));
    5670           2 :           print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
    5671           2 :           printf ("\n");
    5672             :         }
    5673             :       else
    5674           0 :         printf (gettext (" Not associated with a CU.\n"));
    5675             : 
    5676           2 :       printf ("\n");
    5677             : 
    5678           2 :       const unsigned char *offset_array_start = readp;
    5679           2 :       if (offset_entry_count > 0)
    5680             :         {
    5681           1 :           uint64_t max_entries = (unit_length - 8) / offset_size;
    5682           1 :           if (offset_entry_count > max_entries)
    5683             :             {
    5684           0 :               error (0, 0,
    5685           0 :                      gettext ("too many offset entries for unit length"));
    5686           0 :               offset_entry_count = max_entries;
    5687             :             }
    5688             : 
    5689           2 :           printf (gettext ("  Offsets starting at 0x%" PRIx64 ":\n"),
    5690             :                   (uint64_t) (offset_array_start
    5691           1 :                               - (unsigned char *) data->d_buf));
    5692           3 :           for (uint32_t idx = 0; idx < offset_entry_count; idx++)
    5693             :             {
    5694           2 :               printf ("   [%6" PRIu32 "] ", idx);
    5695           2 :               if (offset_size == 4)
    5696             :                 {
    5697           2 :                   uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
    5698             :                   printf ("0x%" PRIx32 "\n", off);
    5699             :                 }
    5700             :               else
    5701             :                 {
    5702           0 :                   uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
    5703             :                   printf ("0x%" PRIx64 "\n", off);
    5704             :                 }
    5705             :             }
    5706             :           printf ("\n");
    5707             :         }
    5708             : 
    5709           2 :       Dwarf_Addr base = cu_base;
    5710           2 :       bool start_of_list = true;
    5711          18 :       while (readp < nexthdr)
    5712             :         {
    5713          14 :           uint8_t kind = *readp++;
    5714             :           uint64_t op1, op2;
    5715             : 
    5716             :           /* Skip padding.  */
    5717          14 :           if (start_of_list && kind == DW_RLE_end_of_list)
    5718           0 :             continue;
    5719             : 
    5720          14 :           if (start_of_list)
    5721             :             {
    5722           4 :               base = cu_base;
    5723          12 :               printf ("  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
    5724           4 :                       (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
    5725           4 :                       (uint64_t) (readp - offset_array_start - 1));
    5726           4 :               start_of_list = false;
    5727             :             }
    5728             : 
    5729          28 :           printf ("    %s", dwarf_range_list_encoding_name (kind));
    5730          14 :           switch (kind)
    5731             :             {
    5732           4 :             case DW_RLE_end_of_list:
    5733           4 :               start_of_list = true;
    5734             :               printf ("\n\n");
    5735             :               break;
    5736             : 
    5737           0 :             case DW_RLE_base_addressx:
    5738           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    5739             :                 {
    5740           0 :                 invalid_range:
    5741           0 :                   error (0, 0, gettext ("invalid range list data"));
    5742             :                   goto next_table;
    5743             :                 }
    5744           0 :               get_uleb128 (op1, readp, nexthdr);
    5745           0 :               printf (" %" PRIx64 "\n", op1);
    5746           0 :               if (! print_unresolved_addresses)
    5747             :                 {
    5748             :                   Dwarf_Addr addr;
    5749           0 :                   if (get_indexed_addr (cu, op1, &addr) != 0)
    5750             :                     printf ("      ???\n");
    5751             :                   else
    5752             :                     {
    5753           0 :                       printf ("      ");
    5754           0 :                       print_dwarf_addr (dwflmod, address_size, addr, addr);
    5755             :                       printf ("\n");
    5756             :                     }
    5757             :                 }
    5758             :               break;
    5759             : 
    5760           0 :             case DW_RLE_startx_endx:
    5761           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    5762             :                 goto invalid_range;
    5763           0 :               get_uleb128 (op1, readp, nexthdr);
    5764           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    5765             :                 goto invalid_range;
    5766           0 :               get_uleb128 (op2, readp, nexthdr);
    5767           0 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    5768           0 :               if (! print_unresolved_addresses)
    5769             :                 {
    5770             :                   Dwarf_Addr addr1;
    5771             :                   Dwarf_Addr addr2;
    5772           0 :                   if (get_indexed_addr (cu, op1, &addr1) != 0
    5773           0 :                       || get_indexed_addr (cu, op2, &addr2) != 0)
    5774             :                     {
    5775           0 :                       printf ("      ???..\n");
    5776             :                       printf ("      ???\n");
    5777             :                     }
    5778             :                   else
    5779             :                     {
    5780           0 :                       printf ("      ");
    5781           0 :                       print_dwarf_addr (dwflmod, address_size, addr1, addr1);
    5782           0 :                       printf ("..\n      ");
    5783           0 :                       print_dwarf_addr (dwflmod, address_size,
    5784             :                                         addr2 - 1, addr2);
    5785             :                       printf ("\n");
    5786             :                     }
    5787             :                 }
    5788             :               break;
    5789             : 
    5790           0 :             case DW_RLE_startx_length:
    5791           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    5792             :                 goto invalid_range;
    5793           0 :               get_uleb128 (op1, readp, nexthdr);
    5794           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    5795             :                 goto invalid_range;
    5796           0 :               get_uleb128 (op2, readp, nexthdr);
    5797           0 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    5798           0 :               if (! print_unresolved_addresses)
    5799             :                 {
    5800             :                   Dwarf_Addr addr1;
    5801             :                   Dwarf_Addr addr2;
    5802           0 :                   if (get_indexed_addr (cu, op1, &addr1) != 0)
    5803             :                     {
    5804           0 :                       printf ("      ???..\n");
    5805             :                       printf ("      ???\n");
    5806             :                     }
    5807             :                   else
    5808             :                     {
    5809           0 :                       addr2 = addr1 + op2;
    5810           0 :                       printf ("      ");
    5811           0 :                       print_dwarf_addr (dwflmod, address_size, addr1, addr1);
    5812           0 :                       printf ("..\n      ");
    5813           0 :                       print_dwarf_addr (dwflmod, address_size,
    5814             :                                         addr2 - 1, addr2);
    5815             :                       printf ("\n");
    5816             :                     }
    5817             :                 }
    5818             :               break;
    5819             : 
    5820           4 :             case DW_RLE_offset_pair:
    5821           4 :               if ((uint64_t) (nexthdr - readp) < 1)
    5822             :                 goto invalid_range;
    5823           4 :               get_uleb128 (op1, readp, nexthdr);
    5824           4 :               if ((uint64_t) (nexthdr - readp) < 1)
    5825             :                 goto invalid_range;
    5826           4 :               get_uleb128 (op2, readp, nexthdr);
    5827           4 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    5828           4 :               if (! print_unresolved_addresses)
    5829             :                 {
    5830           4 :                   op1 += base;
    5831           4 :                   op2 += base;
    5832           4 :                   printf ("      ");
    5833           4 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    5834           4 :                   printf ("..\n      ");
    5835           4 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    5836             :                   printf ("\n");
    5837             :                 }
    5838             :               break;
    5839             : 
    5840           2 :             case DW_RLE_base_address:
    5841           2 :               if (address_size == 4)
    5842             :                 {
    5843           0 :                   if ((uint64_t) (nexthdr - readp) < 4)
    5844             :                     goto invalid_range;
    5845           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    5846             :                 }
    5847             :               else
    5848             :                 {
    5849           2 :                   if ((uint64_t) (nexthdr - readp) < 8)
    5850             :                     goto invalid_range;
    5851           2 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    5852             :                 }
    5853           2 :               base = op1;
    5854           2 :               printf (" 0x%" PRIx64 "\n", base);
    5855           2 :               if (! print_unresolved_addresses)
    5856             :                 {
    5857           2 :                   printf ("      ");
    5858           2 :                   print_dwarf_addr (dwflmod, address_size, base, base);
    5859             :                   printf ("\n");
    5860             :                 }
    5861             :               break;
    5862             : 
    5863           0 :             case DW_RLE_start_end:
    5864           0 :               if (address_size == 4)
    5865             :                 {
    5866           0 :                   if ((uint64_t) (nexthdr - readp) < 8)
    5867             :                     goto invalid_range;
    5868           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    5869           0 :                   op2 = read_4ubyte_unaligned_inc (dbg, readp);
    5870             :                 }
    5871             :               else
    5872             :                 {
    5873           0 :                   if ((uint64_t) (nexthdr - readp) < 16)
    5874             :                     goto invalid_range;
    5875           0 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    5876           0 :                   op2 = read_8ubyte_unaligned_inc (dbg, readp);
    5877             :                 }
    5878           0 :               printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
    5879           0 :               if (! print_unresolved_addresses)
    5880             :                 {
    5881           0 :                   printf ("      ");
    5882           0 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    5883           0 :                   printf ("..\n      ");
    5884           0 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    5885             :                   printf ("\n");
    5886             :                 }
    5887             :               break;
    5888             : 
    5889           4 :             case DW_RLE_start_length:
    5890           4 :               if (address_size == 4)
    5891             :                 {
    5892           0 :                   if ((uint64_t) (nexthdr - readp) < 4)
    5893             :                     goto invalid_range;
    5894           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    5895             :                 }
    5896             :               else
    5897             :                 {
    5898           4 :                   if ((uint64_t) (nexthdr - readp) < 8)
    5899             :                     goto invalid_range;
    5900           4 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    5901             :                 }
    5902           4 :               if ((uint64_t) (nexthdr - readp) < 1)
    5903             :                 goto invalid_range;
    5904           4 :               get_uleb128 (op2, readp, nexthdr);
    5905           4 :               printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
    5906           4 :               if (! print_unresolved_addresses)
    5907             :                 {
    5908           4 :                   op2 = op1 + op2;
    5909           4 :                   printf ("      ");
    5910           4 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    5911           4 :                   printf ("..\n      ");
    5912           4 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    5913             :                   printf ("\n");
    5914             :                 }
    5915             :               break;
    5916             : 
    5917             :             default:
    5918             :               goto invalid_range;
    5919             :             }
    5920             :         }
    5921             : 
    5922           2 :     next_table:
    5923           2 :       if (readp != nexthdr)
    5924             :         {
    5925           0 :           size_t padding = nexthdr - readp;
    5926           0 :           printf (gettext ("   %zu padding bytes\n\n"), padding);
    5927           0 :           readp = nexthdr;
    5928             :         }
    5929             :     }
    5930             : }
    5931             : 
    5932             : /* Print content of DWARF .debug_ranges section.  */
    5933             : static void
    5934          30 : print_debug_ranges_section (Dwfl_Module *dwflmod,
    5935             :                             Ebl *ebl, GElf_Ehdr *ehdr,
    5936             :                             Elf_Scn *scn, GElf_Shdr *shdr,
    5937             :                             Dwarf *dbg)
    5938             : {
    5939          60 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_ranges]
    5940          30 :                     ?: elf_rawdata (scn, NULL));
    5941          30 :   if (unlikely (data == NULL))
    5942             :     {
    5943           0 :       error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
    5944             :              elf_errmsg (-1));
    5945           0 :       return;
    5946             :     }
    5947             : 
    5948          60 :   printf (gettext ("\
    5949             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    5950             :           elf_ndxscn (scn), section_name (ebl, shdr),
    5951          30 :           (uint64_t) shdr->sh_offset);
    5952             : 
    5953          60 :   sort_listptr (&known_rangelistptr, "rangelistptr");
    5954          30 :   size_t listptr_idx = 0;
    5955             : 
    5956          30 :   uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    5957             : 
    5958          30 :   bool first = true;
    5959          30 :   Dwarf_Addr base = 0;
    5960          30 :   unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
    5961          30 :   unsigned char *readp = data->d_buf;
    5962          30 :   Dwarf_CU *last_cu = NULL;
    5963       38305 :   while (readp < endp)
    5964             :     {
    5965       38245 :       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
    5966       38245 :       Dwarf_CU *cu = last_cu;
    5967             : 
    5968       38245 :       if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
    5969             :                                       &address_size, NULL, &base, &cu,
    5970             :                                       offset, &readp, endp, NULL))
    5971           0 :         continue;
    5972             : 
    5973       38245 :       if (last_cu != cu)
    5974             :         {
    5975             :           Dwarf_Die cudie;
    5976         588 :           if (dwarf_cu_die (cu, &cudie,
    5977             :                             NULL, NULL, NULL, NULL,
    5978             :                             NULL, NULL) == NULL)
    5979           0 :             printf (gettext ("\n Unknown CU base: "));
    5980             :           else
    5981         588 :             printf (gettext ("\n CU [%6" PRIx64 "] base: "),
    5982             :                     dwarf_dieoffset (&cudie));
    5983         588 :           print_dwarf_addr (dwflmod, address_size, base, base);
    5984         588 :           printf ("\n");
    5985             :         }
    5986       38245 :       last_cu = cu;
    5987             : 
    5988       38245 :       if (unlikely (data->d_size - offset < (size_t) address_size * 2))
    5989             :         {
    5990           0 :           printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
    5991           0 :           break;
    5992             :         }
    5993             : 
    5994             :       Dwarf_Addr begin;
    5995             :       Dwarf_Addr end;
    5996       38245 :       if (address_size == 8)
    5997             :         {
    5998       38245 :           begin = read_8ubyte_unaligned_inc (dbg, readp);
    5999       38245 :           end = read_8ubyte_unaligned_inc (dbg, readp);
    6000             :         }
    6001             :       else
    6002             :         {
    6003           0 :           begin = read_4ubyte_unaligned_inc (dbg, readp);
    6004           0 :           end = read_4ubyte_unaligned_inc (dbg, readp);
    6005           0 :           if (begin == (Dwarf_Addr) (uint32_t) -1)
    6006             :             begin = (Dwarf_Addr) -1l;
    6007             :         }
    6008             : 
    6009       38245 :       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
    6010             :         {
    6011           0 :           printf (gettext (" [%6tx] base address\n          "), offset);
    6012           0 :           print_dwarf_addr (dwflmod, address_size, end, end);
    6013           0 :           printf ("\n");
    6014           0 :           base = end;
    6015             :         }
    6016       38245 :       else if (begin == 0 && end == 0) /* End of list entry.  */
    6017             :         {
    6018        8925 :           if (first)
    6019           0 :             printf (gettext (" [%6tx] empty list\n"), offset);
    6020             :           first = true;
    6021             :         }
    6022             :       else
    6023             :         {
    6024             :           /* We have an address range entry.  */
    6025       29320 :           if (first)            /* First address range entry in a list.  */
    6026             :             printf (" [%6tx] ", offset);
    6027             :           else
    6028             :             printf ("          ");
    6029             : 
    6030       29320 :           printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
    6031       29320 :           if (! print_unresolved_addresses)
    6032             :             {
    6033       29310 :               printf ("          ");
    6034       29310 :               print_dwarf_addr (dwflmod, address_size, base + begin,
    6035             :                                 base + begin);
    6036       29310 :               printf ("..\n          ");
    6037       29310 :               print_dwarf_addr (dwflmod, address_size,
    6038             :                                 base + end - 1, base + end);
    6039             :               printf ("\n");
    6040             :             }
    6041             : 
    6042             :           first = false;
    6043             :         }
    6044             :     }
    6045             : }
    6046             : 
    6047             : #define REGNAMESZ 16
    6048             : static const char *
    6049        9583 : register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
    6050             :                char name[REGNAMESZ], int *bits, int *type)
    6051             : {
    6052             :   const char *set;
    6053             :   const char *pfx;
    6054             :   int ignore;
    6055        9583 :   ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
    6056             :                                  bits ?: &ignore, type ?: &ignore);
    6057        9583 :   if (n <= 0)
    6058             :     {
    6059           0 :       if (loc != NULL)
    6060           0 :         snprintf (name, REGNAMESZ, "reg%u", loc->regno);
    6061             :       else
    6062             :         snprintf (name, REGNAMESZ, "??? 0x%x", regno);
    6063           0 :       if (bits != NULL)
    6064           0 :         *bits = loc != NULL ? loc->bits : 0;
    6065           0 :       if (type != NULL)
    6066           0 :         *type = DW_ATE_unsigned;
    6067           0 :       set = "??? unrecognized";
    6068             :     }
    6069             :   else
    6070             :     {
    6071        9583 :       if (bits != NULL && *bits <= 0)
    6072           0 :         *bits = loc != NULL ? loc->bits : 0;
    6073        9583 :       if (type != NULL && *type == DW_ATE_void)
    6074           0 :         *type = DW_ATE_unsigned;
    6075             : 
    6076             :     }
    6077        9583 :   return set;
    6078             : }
    6079             : 
    6080             : static const unsigned char *
    6081          28 : read_encoded (unsigned int encoding, const unsigned char *readp,
    6082             :               const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
    6083             : {
    6084          28 :   if ((encoding & 0xf) == DW_EH_PE_absptr)
    6085           0 :     encoding = gelf_getclass (dbg->elf) == ELFCLASS32
    6086           0 :       ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
    6087             : 
    6088          28 :   switch (encoding & 0xf)
    6089             :     {
    6090           0 :     case DW_EH_PE_uleb128:
    6091           0 :       get_uleb128 (*res, readp, endp);
    6092             :       break;
    6093           0 :     case DW_EH_PE_sleb128:
    6094           0 :       get_sleb128 (*res, readp, endp);
    6095             :       break;
    6096           0 :     case DW_EH_PE_udata2:
    6097           0 :       if (readp + 2 > endp)
    6098             :         goto invalid;
    6099           0 :       *res = read_2ubyte_unaligned_inc (dbg, readp);
    6100             :       break;
    6101          14 :     case DW_EH_PE_udata4:
    6102          14 :       if (readp + 4 > endp)
    6103             :         goto invalid;
    6104          14 :       *res = read_4ubyte_unaligned_inc (dbg, readp);
    6105             :       break;
    6106           0 :     case DW_EH_PE_udata8:
    6107           0 :       if (readp + 8 > endp)
    6108             :         goto invalid;
    6109           0 :       *res = read_8ubyte_unaligned_inc (dbg, readp);
    6110             :       break;
    6111           0 :     case DW_EH_PE_sdata2:
    6112           0 :       if (readp + 2 > endp)
    6113             :         goto invalid;
    6114           0 :       *res = read_2sbyte_unaligned_inc (dbg, readp);
    6115             :       break;
    6116          14 :     case DW_EH_PE_sdata4:
    6117          14 :       if (readp + 4 > endp)
    6118             :         goto invalid;
    6119          14 :       *res = read_4sbyte_unaligned_inc (dbg, readp);
    6120             :       break;
    6121           0 :     case DW_EH_PE_sdata8:
    6122           0 :       if (readp + 8 > endp)
    6123             :         goto invalid;
    6124           0 :       *res = read_8sbyte_unaligned_inc (dbg, readp);
    6125             :       break;
    6126             :     default:
    6127           0 :     invalid:
    6128             :       error (1, 0,
    6129           0 :              gettext ("invalid encoding"));
    6130             :     }
    6131             : 
    6132          28 :   return readp;
    6133             : }
    6134             : 
    6135             : 
    6136             : static void
    6137        4629 : print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
    6138             :                    Dwarf_Word vma_base, unsigned int code_align,
    6139             :                    int data_align,
    6140             :                    unsigned int version, unsigned int ptr_size,
    6141             :                    unsigned int encoding,
    6142             :                    Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
    6143             : {
    6144             :   char regnamebuf[REGNAMESZ];
    6145             :   const char *regname (unsigned int regno)
    6146             :   {
    6147        8735 :     register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
    6148             :     return regnamebuf;
    6149             :   }
    6150             : 
    6151        4629 :   puts ("\n   Program:");
    6152        4629 :   Dwarf_Word pc = vma_base;
    6153       85168 :   while (readp < endp)
    6154             :     {
    6155       75910 :       unsigned int opcode = *readp++;
    6156             : 
    6157       75910 :       if (opcode < DW_CFA_advance_loc)
    6158             :         /* Extended opcode.  */
    6159       43824 :         switch (opcode)
    6160             :           {
    6161             :             uint64_t op1;
    6162             :             int64_t sop1;
    6163             :             uint64_t op2;
    6164             :             int64_t sop2;
    6165             : 
    6166       12882 :           case DW_CFA_nop:
    6167       12882 :             puts ("     nop");
    6168       56706 :             break;
    6169           0 :           case DW_CFA_set_loc:
    6170           0 :             if ((uint64_t) (endp - readp) < 1)
    6171             :               goto invalid;
    6172           0 :             readp = read_encoded (encoding, readp, endp, &op1, dbg);
    6173           0 :             printf ("     set_loc %#" PRIx64 " to %#" PRIx64 "\n",
    6174           0 :                     op1, pc = vma_base + op1);
    6175             :             break;
    6176        1658 :           case DW_CFA_advance_loc1:
    6177        1658 :             if ((uint64_t) (endp - readp) < 1)
    6178             :               goto invalid;
    6179        3316 :             printf ("     advance_loc1 %u to %#" PRIx64 "\n",
    6180        1658 :                     *readp, pc += *readp * code_align);
    6181        1658 :             ++readp;
    6182        1658 :             break;
    6183         749 :           case DW_CFA_advance_loc2:
    6184         749 :             if ((uint64_t) (endp - readp) < 2)
    6185             :               goto invalid;
    6186         749 :             op1 = read_2ubyte_unaligned_inc (dbg, readp);
    6187         749 :             printf ("     advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
    6188         749 :                     op1, pc += op1 * code_align);
    6189             :             break;
    6190          24 :           case DW_CFA_advance_loc4:
    6191          24 :             if ((uint64_t) (endp - readp) < 4)
    6192             :               goto invalid;
    6193          48 :             op1 = read_4ubyte_unaligned_inc (dbg, readp);
    6194          24 :             printf ("     advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
    6195          24 :                     op1, pc += op1 * code_align);
    6196             :             break;
    6197           4 :           case DW_CFA_offset_extended:
    6198           4 :             if ((uint64_t) (endp - readp) < 1)
    6199             :               goto invalid;
    6200           4 :             get_uleb128 (op1, readp, endp);
    6201           4 :             if ((uint64_t) (endp - readp) < 1)
    6202             :               goto invalid;
    6203           4 :             get_uleb128 (op2, readp, endp);
    6204           8 :             printf ("     offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
    6205             :                     "\n",
    6206             :                     op1, regname (op1), op2 * data_align);
    6207             :             break;
    6208           0 :           case DW_CFA_restore_extended:
    6209           0 :             if ((uint64_t) (endp - readp) < 1)
    6210             :               goto invalid;
    6211           0 :             get_uleb128 (op1, readp, endp);
    6212           0 :             printf ("     restore_extended r%" PRIu64 " (%s)\n",
    6213             :                     op1, regname (op1));
    6214             :             break;
    6215           6 :           case DW_CFA_undefined:
    6216           6 :             if ((uint64_t) (endp - readp) < 1)
    6217             :               goto invalid;
    6218           6 :             get_uleb128 (op1, readp, endp);
    6219          12 :             printf ("     undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
    6220             :             break;
    6221           0 :           case DW_CFA_same_value:
    6222           0 :             if ((uint64_t) (endp - readp) < 1)
    6223             :               goto invalid;
    6224           0 :             get_uleb128 (op1, readp, endp);
    6225           0 :             printf ("     same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
    6226             :             break;
    6227           0 :           case DW_CFA_register:
    6228           0 :             if ((uint64_t) (endp - readp) < 1)
    6229             :               goto invalid;
    6230           0 :             get_uleb128 (op1, readp, endp);
    6231           0 :             if ((uint64_t) (endp - readp) < 1)
    6232             :               goto invalid;
    6233           0 :             get_uleb128 (op2, readp, endp);
    6234           0 :             printf ("     register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
    6235             :                     op1, regname (op1), op2, regname (op2));
    6236             :             break;
    6237        2619 :           case DW_CFA_remember_state:
    6238        2619 :             puts ("     remember_state");
    6239        2619 :             break;
    6240        2619 :           case DW_CFA_restore_state:
    6241        2619 :             puts ("     restore_state");
    6242        2619 :             break;
    6243         124 :           case DW_CFA_def_cfa:
    6244         124 :             if ((uint64_t) (endp - readp) < 1)
    6245             :               goto invalid;
    6246         124 :             get_uleb128 (op1, readp, endp);
    6247         124 :             if ((uint64_t) (endp - readp) < 1)
    6248             :               goto invalid;
    6249         124 :             get_uleb128 (op2, readp, endp);
    6250         248 :             printf ("     def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
    6251             :                     op1, regname (op1), op2);
    6252             :             break;
    6253          46 :           case DW_CFA_def_cfa_register:
    6254          46 :             if ((uint64_t) (endp - readp) < 1)
    6255             :               goto invalid;
    6256          46 :             get_uleb128 (op1, readp, endp);
    6257          92 :             printf ("     def_cfa_register r%" PRIu64 " (%s)\n",
    6258             :                     op1, regname (op1));
    6259             :             break;
    6260       23065 :           case DW_CFA_def_cfa_offset:
    6261       23065 :             if ((uint64_t) (endp - readp) < 1)
    6262             :               goto invalid;
    6263       23065 :             get_uleb128 (op1, readp, endp);
    6264       23065 :             printf ("     def_cfa_offset %" PRIu64 "\n", op1);
    6265             :             break;
    6266          12 :           case DW_CFA_def_cfa_expression:
    6267          12 :             if ((uint64_t) (endp - readp) < 1)
    6268             :               goto invalid;
    6269          12 :             get_uleb128 (op1, readp, endp);     /* Length of DW_FORM_block.  */
    6270          24 :             printf ("     def_cfa_expression %" PRIu64 "\n", op1);
    6271          12 :             if ((uint64_t) (endp - readp) < op1)
    6272             :               {
    6273           0 :             invalid:
    6274           0 :                 fputs (gettext ("         <INVALID DATA>\n"), stdout);
    6275           0 :                 return;
    6276             :               }
    6277          12 :             print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
    6278             :                        op1, readp);
    6279          12 :             readp += op1;
    6280          12 :             break;
    6281           0 :           case DW_CFA_expression:
    6282           0 :             if ((uint64_t) (endp - readp) < 1)
    6283             :               goto invalid;
    6284           0 :             get_uleb128 (op1, readp, endp);
    6285           0 :             if ((uint64_t) (endp - readp) < 1)
    6286             :               goto invalid;
    6287           0 :             get_uleb128 (op2, readp, endp);     /* Length of DW_FORM_block.  */
    6288           0 :             printf ("     expression r%" PRIu64 " (%s) \n",
    6289             :                     op1, regname (op1));
    6290           0 :             if ((uint64_t) (endp - readp) < op2)
    6291             :               goto invalid;
    6292           0 :             print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
    6293             :                        op2, readp);
    6294           0 :             readp += op2;
    6295           0 :             break;
    6296          16 :           case DW_CFA_offset_extended_sf:
    6297          16 :             if ((uint64_t) (endp - readp) < 1)
    6298             :               goto invalid;
    6299          16 :             get_uleb128 (op1, readp, endp);
    6300          16 :             if ((uint64_t) (endp - readp) < 1)
    6301             :               goto invalid;
    6302          16 :             get_sleb128 (sop2, readp, endp);
    6303          32 :             printf ("     offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
    6304             :                     PRId64 "\n",
    6305             :                     op1, regname (op1), sop2 * data_align);
    6306             :             break;
    6307           0 :           case DW_CFA_def_cfa_sf:
    6308           0 :             if ((uint64_t) (endp - readp) < 1)
    6309             :               goto invalid;
    6310           0 :             get_uleb128 (op1, readp, endp);
    6311           0 :             if ((uint64_t) (endp - readp) < 1)
    6312             :               goto invalid;
    6313           0 :             get_sleb128 (sop2, readp, endp);
    6314           0 :             printf ("     def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
    6315             :                     op1, regname (op1), sop2 * data_align);
    6316             :             break;
    6317           0 :           case DW_CFA_def_cfa_offset_sf:
    6318           0 :             if ((uint64_t) (endp - readp) < 1)
    6319             :               goto invalid;
    6320           0 :             get_sleb128 (sop1, readp, endp);
    6321           0 :             printf ("     def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
    6322             :             break;
    6323           0 :           case DW_CFA_val_offset:
    6324           0 :             if ((uint64_t) (endp - readp) < 1)
    6325             :               goto invalid;
    6326           0 :             get_uleb128 (op1, readp, endp);
    6327           0 :             if ((uint64_t) (endp - readp) < 1)
    6328             :               goto invalid;
    6329           0 :             get_uleb128 (op2, readp, endp);
    6330           0 :             printf ("     val_offset %" PRIu64 " at offset %" PRIu64 "\n",
    6331             :                     op1, op2 * data_align);
    6332             :             break;
    6333           0 :           case DW_CFA_val_offset_sf:
    6334           0 :             if ((uint64_t) (endp - readp) < 1)
    6335             :               goto invalid;
    6336           0 :             get_uleb128 (op1, readp, endp);
    6337           0 :             if ((uint64_t) (endp - readp) < 1)
    6338             :               goto invalid;
    6339           0 :             get_sleb128 (sop2, readp, endp);
    6340           0 :             printf ("     val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
    6341             :                     op1, sop2 * data_align);
    6342             :             break;
    6343           0 :           case DW_CFA_val_expression:
    6344           0 :             if ((uint64_t) (endp - readp) < 1)
    6345             :               goto invalid;
    6346           0 :             get_uleb128 (op1, readp, endp);
    6347           0 :             if ((uint64_t) (endp - readp) < 1)
    6348             :               goto invalid;
    6349           0 :             get_uleb128 (op2, readp, endp);     /* Length of DW_FORM_block.  */
    6350           0 :             printf ("     val_expression r%" PRIu64 " (%s)\n",
    6351             :                     op1, regname (op1));
    6352           0 :             if ((uint64_t) (endp - readp) < op2)
    6353             :               goto invalid;
    6354           0 :             print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0,
    6355             :                        NULL, op2, readp);
    6356           0 :             readp += op2;
    6357           0 :             break;
    6358           0 :           case DW_CFA_MIPS_advance_loc8:
    6359           0 :             if ((uint64_t) (endp - readp) < 8)
    6360             :               goto invalid;
    6361           0 :             op1 = read_8ubyte_unaligned_inc (dbg, readp);
    6362           0 :             printf ("     MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
    6363           0 :                     op1, pc += op1 * code_align);
    6364             :             break;
    6365           0 :           case DW_CFA_GNU_window_save:
    6366           0 :             puts ("     GNU_window_save");
    6367           0 :             break;
    6368           0 :           case DW_CFA_GNU_args_size:
    6369           0 :             if ((uint64_t) (endp - readp) < 1)
    6370             :               goto invalid;
    6371           0 :             get_uleb128 (op1, readp, endp);
    6372           0 :             printf ("     args_size %" PRIu64 "\n", op1);
    6373             :             break;
    6374           0 :           default:
    6375             :             printf ("     ??? (%u)\n", opcode);
    6376             :             break;
    6377             :           }
    6378       32086 :       else if (opcode < DW_CFA_offset)
    6379       23547 :         printf ("     advance_loc %u to %#" PRIx64 "\n",
    6380       23547 :                 opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
    6381        8539 :       else if (opcode < DW_CFA_restore)
    6382             :         {
    6383             :           uint64_t offset;
    6384        7281 :           if ((uint64_t) (endp - readp) < 1)
    6385             :             goto invalid;
    6386        7281 :           get_uleb128 (offset, readp, endp);
    6387       14562 :           printf ("     offset r%u (%s) at cfa%+" PRId64 "\n",
    6388             :                   opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
    6389             :         }
    6390             :       else
    6391        2516 :         printf ("     restore r%u (%s)\n",
    6392             :                 opcode & 0x3f, regname (opcode & 0x3f));
    6393             :     }
    6394             : }
    6395             : 
    6396             : 
    6397             : static unsigned int
    6398        4557 : encoded_ptr_size (int encoding, unsigned int ptr_size)
    6399             : {
    6400        4557 :   switch (encoding & 7)
    6401             :     {
    6402             :     case DW_EH_PE_udata4:
    6403             :       return 4;
    6404           0 :     case DW_EH_PE_udata8:
    6405           0 :       return 8;
    6406          44 :     case 0:
    6407          44 :       return ptr_size;
    6408             :     }
    6409             : 
    6410           0 :   fprintf (stderr, "Unsupported pointer encoding: %#x, "
    6411             :            "assuming pointer size of %d.\n", encoding, ptr_size);
    6412           0 :   return ptr_size;
    6413             : }
    6414             : 
    6415             : 
    6416             : static unsigned int
    6417          78 : print_encoding (unsigned int val)
    6418             : {
    6419          78 :   switch (val & 0xf)
    6420             :     {
    6421           0 :     case DW_EH_PE_absptr:
    6422           0 :       fputs ("absptr", stdout);
    6423           0 :       break;
    6424           0 :     case DW_EH_PE_uleb128:
    6425           0 :       fputs ("uleb128", stdout);
    6426           0 :       break;
    6427           0 :     case DW_EH_PE_udata2:
    6428           0 :       fputs ("udata2", stdout);
    6429           0 :       break;
    6430          14 :     case DW_EH_PE_udata4:
    6431          14 :       fputs ("udata4", stdout);
    6432          14 :       break;
    6433           0 :     case DW_EH_PE_udata8:
    6434           0 :       fputs ("udata8", stdout);
    6435           0 :       break;
    6436           0 :     case DW_EH_PE_sleb128:
    6437           0 :       fputs ("sleb128", stdout);
    6438           0 :       break;
    6439           0 :     case DW_EH_PE_sdata2:
    6440           0 :       fputs ("sdata2", stdout);
    6441           0 :       break;
    6442          64 :     case DW_EH_PE_sdata4:
    6443          64 :       fputs ("sdata4", stdout);
    6444          64 :       break;
    6445           0 :     case DW_EH_PE_sdata8:
    6446           0 :       fputs ("sdata8", stdout);
    6447           0 :       break;
    6448             :     default:
    6449             :       /* We did not use any of the bits after all.  */
    6450             :       return val;
    6451             :     }
    6452             : 
    6453          78 :   return val & ~0xf;
    6454             : }
    6455             : 
    6456             : 
    6457             : static unsigned int
    6458          64 : print_relinfo (unsigned int val)
    6459             : {
    6460          64 :   switch (val & 0x70)
    6461             :     {
    6462          50 :     case DW_EH_PE_pcrel:
    6463          50 :       fputs ("pcrel", stdout);
    6464          50 :       break;
    6465           0 :     case DW_EH_PE_textrel:
    6466           0 :       fputs ("textrel", stdout);
    6467           0 :       break;
    6468          14 :     case DW_EH_PE_datarel:
    6469          14 :       fputs ("datarel", stdout);
    6470          14 :       break;
    6471           0 :     case DW_EH_PE_funcrel:
    6472           0 :       fputs ("funcrel", stdout);
    6473           0 :       break;
    6474           0 :     case DW_EH_PE_aligned:
    6475           0 :       fputs ("aligned", stdout);
    6476           0 :       break;
    6477             :     default:
    6478             :       return val;
    6479             :     }
    6480             : 
    6481          64 :   return val & ~0x70;
    6482             : }
    6483             : 
    6484             : 
    6485             : static void
    6486          78 : print_encoding_base (const char *pfx, unsigned int fde_encoding)
    6487             : {
    6488          78 :   printf ("(%s", pfx);
    6489             : 
    6490          78 :   if (fde_encoding == DW_EH_PE_omit)
    6491           0 :     puts ("omit)");
    6492             :   else
    6493             :     {
    6494          78 :       unsigned int w = fde_encoding;
    6495             : 
    6496          78 :       w = print_encoding (w);
    6497             : 
    6498          78 :       if (w & 0x70)
    6499             :         {
    6500          64 :           if (w != fde_encoding)
    6501          64 :             fputc_unlocked (' ', stdout);
    6502             : 
    6503          64 :           w = print_relinfo (w);
    6504             :         }
    6505             : 
    6506          78 :       if (w != 0)
    6507           0 :         printf ("%s%x", w != fde_encoding ? " " : "", w);
    6508             : 
    6509          78 :       puts (")");
    6510             :     }
    6511          78 : }
    6512             : 
    6513             : 
    6514             : static void
    6515          48 : print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
    6516             :                            Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    6517             : {
    6518             :   size_t shstrndx;
    6519             :   /* We know this call will succeed since it did in the caller.  */
    6520          48 :   (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
    6521          48 :   const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
    6522             : 
    6523             :   /* Needed if we find PC-relative addresses.  */
    6524             :   GElf_Addr bias;
    6525          48 :   if (dwfl_module_getelf (dwflmod, &bias) == NULL)
    6526             :     {
    6527           0 :       error (0, 0, gettext ("cannot get ELF: %s"), dwfl_errmsg (-1));
    6528           0 :       return;
    6529             :     }
    6530             : 
    6531          48 :   bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
    6532          48 :   Elf_Data *data = (is_eh_frame
    6533             :                     ? elf_rawdata (scn, NULL)
    6534          48 :                     : (dbg->sectiondata[IDX_debug_frame]
    6535          22 :                        ?: elf_rawdata (scn, NULL)));
    6536             : 
    6537          48 :   if (unlikely (data == NULL))
    6538             :     {
    6539           0 :       error (0, 0, gettext ("cannot get %s content: %s"),
    6540             :              scnname, elf_errmsg (-1));
    6541             :       return;
    6542             :     }
    6543             : 
    6544          48 :   if (is_eh_frame)
    6545          26 :     printf (gettext ("\
    6546             : \nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    6547          26 :             elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
    6548             :   else
    6549          22 :     printf (gettext ("\
    6550             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    6551          22 :             elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
    6552             : 
    6553             :   struct cieinfo
    6554             :   {
    6555             :     ptrdiff_t cie_offset;
    6556             :     const char *augmentation;
    6557             :     unsigned int code_alignment_factor;
    6558             :     unsigned int data_alignment_factor;
    6559             :     uint8_t address_size;
    6560             :     uint8_t fde_encoding;
    6561             :     uint8_t lsda_encoding;
    6562             :     struct cieinfo *next;
    6563          48 :   } *cies = NULL;
    6564             : 
    6565          48 :   const unsigned char *readp = data->d_buf;
    6566          48 :   const unsigned char *const dataend = ((unsigned char *) data->d_buf
    6567          48 :                                         + data->d_size);
    6568        4739 :   while (readp < dataend)
    6569             :     {
    6570        4643 :       if (unlikely (readp + 4 > dataend))
    6571             :         {
    6572           0 :         invalid_data:
    6573           0 :           error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
    6574             :                      elf_ndxscn (scn), scnname);
    6575             :               return;
    6576             :         }
    6577             : 
    6578             :       /* At the beginning there must be a CIE.  There can be multiple,
    6579             :          hence we test tis in a loop.  */
    6580        4643 :       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
    6581             : 
    6582        4687 :       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
    6583        4643 :       unsigned int length = 4;
    6584        4643 :       if (unlikely (unit_length == 0xffffffff))
    6585             :         {
    6586           0 :           if (unlikely (readp + 8 > dataend))
    6587             :             goto invalid_data;
    6588             : 
    6589           0 :           unit_length = read_8ubyte_unaligned_inc (dbg, readp);
    6590           0 :           length = 8;
    6591             :         }
    6592             : 
    6593        4643 :       if (unlikely (unit_length == 0))
    6594             :         {
    6595          28 :           printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
    6596          14 :           continue;
    6597             :         }
    6598             : 
    6599        4629 :       Dwarf_Word maxsize = dataend - readp;
    6600        4629 :       if (unlikely (unit_length > maxsize))
    6601             :         goto invalid_data;
    6602             : 
    6603        4629 :       unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    6604             : 
    6605        4629 :       ptrdiff_t start = readp - (unsigned char *) data->d_buf;
    6606        4629 :       const unsigned char *const cieend = readp + unit_length;
    6607        4629 :       if (unlikely (cieend > dataend))
    6608             :         goto invalid_data;
    6609             : 
    6610             :       Dwarf_Off cie_id;
    6611        4629 :       if (length == 4)
    6612             :         {
    6613        4629 :           if (unlikely (cieend - readp < 4))
    6614             :             goto invalid_data;
    6615        4673 :           cie_id = read_4ubyte_unaligned_inc (dbg, readp);
    6616        4629 :           if (!is_eh_frame && cie_id == DW_CIE_ID_32)
    6617          34 :             cie_id = DW_CIE_ID_64;
    6618             :         }
    6619             :       else
    6620             :         {
    6621           0 :           if (unlikely (cieend - readp < 8))
    6622             :             goto invalid_data;
    6623           0 :           cie_id = read_8ubyte_unaligned_inc (dbg, readp);
    6624             :         }
    6625             : 
    6626        4629 :       uint_fast8_t version = 2;
    6627             :       unsigned int code_alignment_factor;
    6628             :       int data_alignment_factor;
    6629        4629 :       unsigned int fde_encoding = 0;
    6630        4629 :       unsigned int lsda_encoding = 0;
    6631        4629 :       Dwarf_Word initial_location = 0;
    6632        4629 :       Dwarf_Word vma_base = 0;
    6633             : 
    6634        4629 :       if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
    6635             :         {
    6636          72 :           if (unlikely (cieend - readp < 2))
    6637             :             goto invalid_data;
    6638          72 :           version = *readp++;
    6639          72 :           const char *const augmentation = (const char *) readp;
    6640          72 :           readp = memchr (readp, '\0', cieend - readp);
    6641          72 :           if (unlikely (readp == NULL))
    6642             :             goto invalid_data;
    6643          72 :           ++readp;
    6644             : 
    6645          72 :           uint_fast8_t segment_size = 0;
    6646          72 :           if (version >= 4)
    6647             :             {
    6648           0 :               if (cieend - readp < 5)
    6649             :                 goto invalid_data;
    6650           0 :               ptr_size = *readp++;
    6651           0 :               segment_size = *readp++;
    6652             :             }
    6653             : 
    6654          72 :           if (cieend - readp < 1)
    6655             :             goto invalid_data;
    6656          72 :           get_uleb128 (code_alignment_factor, readp, cieend);
    6657          72 :           if (cieend - readp < 1)
    6658             :             goto invalid_data;
    6659          72 :           get_sleb128 (data_alignment_factor, readp, cieend);
    6660             : 
    6661             :           /* In some variant for unwind data there is another field.  */
    6662          72 :           if (strcmp (augmentation, "eh") == 0)
    6663           0 :             readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    6664             : 
    6665             :           unsigned int return_address_register;
    6666          72 :           if (cieend - readp < 1)
    6667             :             goto invalid_data;
    6668          72 :           if (unlikely (version == 1))
    6669          60 :             return_address_register = *readp++;
    6670             :           else
    6671          12 :             get_uleb128 (return_address_register, readp, cieend);
    6672             : 
    6673         144 :           printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
    6674             :                   "   CIE_id:                   %" PRIu64 "\n"
    6675             :                   "   version:                  %u\n"
    6676             :                   "   augmentation:             \"%s\"\n",
    6677             :                   offset, (uint64_t) unit_length, (uint64_t) cie_id,
    6678             :                   version, augmentation);
    6679          72 :           if (version >= 4)
    6680           0 :             printf ("   address_size:             %u\n"
    6681             :                     "   segment_size:             %u\n",
    6682             :                     ptr_size, segment_size);
    6683          72 :           printf ("   code_alignment_factor:    %u\n"
    6684             :                   "   data_alignment_factor:    %d\n"
    6685             :                   "   return_address_register:  %u\n",
    6686             :                   code_alignment_factor,
    6687             :                   data_alignment_factor, return_address_register);
    6688             : 
    6689          72 :           if (augmentation[0] == 'z')
    6690             :             {
    6691             :               unsigned int augmentationlen;
    6692          36 :               get_uleb128 (augmentationlen, readp, cieend);
    6693             : 
    6694          36 :               if (augmentationlen > (size_t) (cieend - readp))
    6695             :                 {
    6696           0 :                   error (0, 0, gettext ("invalid augmentation length"));
    6697           0 :                   readp = cieend;
    6698           0 :                   continue;
    6699             :                 }
    6700             : 
    6701          36 :               const char *hdr = "Augmentation data:";
    6702          36 :               const char *cp = augmentation + 1;
    6703         108 :               while (*cp != '\0' && cp < augmentation + augmentationlen + 1)
    6704             :                 {
    6705          72 :                   printf ("   %-26s%#x ", hdr, *readp);
    6706          36 :                   hdr = "";
    6707             : 
    6708          36 :                   if (*cp == 'R')
    6709             :                     {
    6710          36 :                       fde_encoding = *readp++;
    6711          36 :                       print_encoding_base (gettext ("FDE address encoding: "),
    6712             :                                            fde_encoding);
    6713             :                     }
    6714           0 :                   else if (*cp == 'L')
    6715             :                     {
    6716           0 :                       lsda_encoding = *readp++;
    6717           0 :                       print_encoding_base (gettext ("LSDA pointer encoding: "),
    6718             :                                            lsda_encoding);
    6719             :                     }
    6720           0 :                   else if (*cp == 'P')
    6721             :                     {
    6722             :                       /* Personality.  This field usually has a relocation
    6723             :                          attached pointing to __gcc_personality_v0.  */
    6724           0 :                       const unsigned char *startp = readp;
    6725           0 :                       unsigned int encoding = *readp++;
    6726           0 :                       uint64_t val = 0;
    6727           0 :                       readp = read_encoded (encoding, readp,
    6728           0 :                                             readp - 1 + augmentationlen,
    6729             :                                             &val, dbg);
    6730             : 
    6731           0 :                       while (++startp < readp)
    6732           0 :                         printf ("%#x ", *startp);
    6733             : 
    6734           0 :                       putchar ('(');
    6735           0 :                       print_encoding (encoding);
    6736           0 :                       putchar (' ');
    6737           0 :                       switch (encoding & 0xf)
    6738             :                         {
    6739           0 :                         case DW_EH_PE_sleb128:
    6740             :                         case DW_EH_PE_sdata2:
    6741             :                         case DW_EH_PE_sdata4:
    6742           0 :                           printf ("%" PRId64 ")\n", val);
    6743             :                           break;
    6744           0 :                         default:
    6745           0 :                           printf ("%#" PRIx64 ")\n", val);
    6746             :                           break;
    6747             :                         }
    6748             :                     }
    6749             :                   else
    6750           0 :                     printf ("(%x)\n", *readp++);
    6751             : 
    6752          36 :                   ++cp;
    6753             :                 }
    6754             :             }
    6755             : 
    6756          72 :           if (likely (ptr_size == 4 || ptr_size == 8))
    6757             :             {
    6758          72 :               struct cieinfo *newp = alloca (sizeof (*newp));
    6759          72 :               newp->cie_offset = offset;
    6760          72 :               newp->augmentation = augmentation;
    6761          72 :               newp->fde_encoding = fde_encoding;
    6762          72 :               newp->lsda_encoding = lsda_encoding;
    6763          72 :               newp->address_size = ptr_size;
    6764          72 :               newp->code_alignment_factor = code_alignment_factor;
    6765          72 :               newp->data_alignment_factor = data_alignment_factor;
    6766          72 :               newp->next = cies;
    6767          72 :               cies = newp;
    6768             :             }
    6769             :         }
    6770             :       else
    6771             :         {
    6772             :           struct cieinfo *cie = cies;
    6773        4557 :           while (cie != NULL)
    6774        9114 :             if (is_eh_frame
    6775        4519 :                 ? ((Dwarf_Off) start - cie_id) == (Dwarf_Off) cie->cie_offset
    6776          38 :                 : cie_id == (Dwarf_Off) cie->cie_offset)
    6777             :               break;
    6778             :             else
    6779           0 :               cie = cie->next;
    6780        4557 :           if (unlikely (cie == NULL))
    6781             :             {
    6782           0 :               puts ("invalid CIE reference in FDE");
    6783           0 :               return;
    6784             :             }
    6785             : 
    6786             :           /* Initialize from CIE data.  */
    6787        4557 :           fde_encoding = cie->fde_encoding;
    6788        4557 :           lsda_encoding = cie->lsda_encoding;
    6789        4557 :           ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
    6790        4557 :           code_alignment_factor = cie->code_alignment_factor;
    6791        4557 :           data_alignment_factor = cie->data_alignment_factor;
    6792             : 
    6793        4557 :           const unsigned char *base = readp;
    6794             :           // XXX There are sometimes relocations for this value
    6795        4579 :           initial_location = read_addr_unaligned_inc (ptr_size, dbg, readp);
    6796        4557 :           Dwarf_Word address_range
    6797        4579 :             = read_addr_unaligned_inc (ptr_size, dbg, readp);
    6798             : 
    6799             :           /* pcrel for an FDE address is relative to the runtime
    6800             :              address of the start_address field itself.  Sign extend
    6801             :              if necessary to make sure the calculation is done on the
    6802             :              full 64 bit address even when initial_location only holds
    6803             :              the lower 32 bits.  */
    6804        4557 :           Dwarf_Addr pc_start = initial_location;
    6805        4557 :           if (ptr_size == 4)
    6806        4517 :             pc_start = (uint64_t) (int32_t) pc_start;
    6807        4557 :           if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
    6808        9026 :             pc_start += ((uint64_t) shdr->sh_addr
    6809        4513 :                          + (base - (const unsigned char *) data->d_buf)
    6810        4513 :                          - bias);
    6811             : 
    6812        9114 :           printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
    6813             :                   "   CIE_pointer:              %" PRIu64 "\n"
    6814             :                   "   initial_location:         ",
    6815             :                   offset, (uint64_t) unit_length,
    6816             :                   cie->cie_offset, (uint64_t) cie_id);
    6817        4557 :           print_dwarf_addr (dwflmod, cie->address_size,
    6818             :                             pc_start, initial_location);
    6819        4557 :           if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
    6820             :             {
    6821        9026 :               vma_base = (((uint64_t) shdr->sh_offset
    6822        4513 :                            + (base - (const unsigned char *) data->d_buf)
    6823        4513 :                            + (uint64_t) initial_location)
    6824             :                           & (ptr_size == 4
    6825             :                              ? UINT64_C (0xffffffff)
    6826        4513 :                              : UINT64_C (0xffffffffffffffff)));
    6827        4513 :               printf (gettext (" (offset: %#" PRIx64 ")"),
    6828             :                       (uint64_t) vma_base);
    6829             :             }
    6830             : 
    6831        4557 :           printf ("\n   address_range:            %#" PRIx64,
    6832             :                   (uint64_t) address_range);
    6833        4557 :           if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
    6834        4513 :             printf (gettext (" (end offset: %#" PRIx64 ")"),
    6835        4513 :                     ((uint64_t) vma_base + (uint64_t) address_range)
    6836             :                     & (ptr_size == 4
    6837             :                        ? UINT64_C (0xffffffff)
    6838        4513 :                        : UINT64_C (0xffffffffffffffff)));
    6839        4557 :           putchar ('\n');
    6840             : 
    6841        4557 :           if (cie->augmentation[0] == 'z')
    6842             :             {
    6843             :               unsigned int augmentationlen;
    6844        4513 :               if (cieend - readp < 1)
    6845             :                 goto invalid_data;
    6846        4513 :               get_uleb128 (augmentationlen, readp, cieend);
    6847             : 
    6848        4513 :               if (augmentationlen > (size_t) (cieend - readp))
    6849             :                 {
    6850           0 :                   error (0, 0, gettext ("invalid augmentation length"));
    6851           0 :                   readp = cieend;
    6852           0 :                   continue;
    6853             :                 }
    6854             : 
    6855        4513 :               if (augmentationlen > 0)
    6856             :                 {
    6857           0 :                   const char *hdr = "Augmentation data:";
    6858           0 :                   const char *cp = cie->augmentation + 1;
    6859           0 :                   unsigned int u = 0;
    6860           0 :                   while (*cp != '\0'
    6861           0 :                          && cp < cie->augmentation + augmentationlen + 1)
    6862             :                     {
    6863           0 :                       if (*cp == 'L')
    6864             :                         {
    6865             :                           uint64_t lsda_pointer;
    6866           0 :                           const unsigned char *p
    6867           0 :                             = read_encoded (lsda_encoding, &readp[u],
    6868             :                                             &readp[augmentationlen],
    6869             :                                             &lsda_pointer, dbg);
    6870           0 :                           u = p - readp;
    6871           0 :                           printf (gettext ("\
    6872             :    %-26sLSDA pointer: %#" PRIx64 "\n"),
    6873             :                                   hdr, lsda_pointer);
    6874           0 :                           hdr = "";
    6875             :                         }
    6876           0 :                       ++cp;
    6877             :                     }
    6878             : 
    6879           0 :                   while (u < augmentationlen)
    6880             :                     {
    6881           0 :                       printf ("   %-26s%#x\n", hdr, readp[u++]);
    6882           0 :                       hdr = "";
    6883             :                     }
    6884             :                 }
    6885             : 
    6886        4513 :               readp += augmentationlen;
    6887             :             }
    6888             :         }
    6889             : 
    6890             :       /* Handle the initialization instructions.  */
    6891        4629 :       if (ptr_size != 4 && ptr_size !=8)
    6892             :         printf ("invalid CIE pointer size (%u), must be 4 or 8.\n", ptr_size);
    6893             :       else
    6894        4629 :         print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
    6895             :                            data_alignment_factor, version, ptr_size,
    6896             :                            fde_encoding, dwflmod, ebl, dbg);
    6897        4629 :       readp = cieend;
    6898             :     }
    6899             : }
    6900             : 
    6901             : 
    6902             : /* Returns the signedness (or false if it cannot be determined) and
    6903             :    the byte size (or zero if it cannot be gotten) of the given DIE
    6904             :    DW_AT_type attribute.  Uses dwarf_peel_type and dwarf_aggregate_size.  */
    6905             : static void
    6906      100273 : die_type_sign_bytes (Dwarf_Die *die, bool *is_signed, int *bytes)
    6907             : {
    6908             :   Dwarf_Attribute attr;
    6909             :   Dwarf_Die type;
    6910             : 
    6911      100273 :   *bytes = 0;
    6912      100273 :   *is_signed = false;
    6913             : 
    6914      100273 :   if (dwarf_peel_type (dwarf_formref_die (dwarf_attr_integrate (die,
    6915             :                                                                 DW_AT_type,
    6916             :                                                                 &attr), &type),
    6917             :                        &type) == 0)
    6918             :     {
    6919             :       Dwarf_Word val;
    6920         414 :       *is_signed = (dwarf_formudata (dwarf_attr (&type, DW_AT_encoding,
    6921             :                                                  &attr), &val) == 0
    6922         207 :                     && (val == DW_ATE_signed || val == DW_ATE_signed_char));
    6923             : 
    6924         207 :       if (dwarf_aggregate_size (&type, &val) == 0)
    6925         207 :         *bytes = val;
    6926             :     }
    6927      100273 : }
    6928             : 
    6929             : struct attrcb_args
    6930             : {
    6931             :   Dwfl_Module *dwflmod;
    6932             :   Dwarf *dbg;
    6933             :   Dwarf_Die *die;
    6934             :   int level;
    6935             :   bool silent;
    6936             :   bool is_split;
    6937             :   unsigned int version;
    6938             :   unsigned int addrsize;
    6939             :   unsigned int offset_size;
    6940             :   struct Dwarf_CU *cu;
    6941             : };
    6942             : 
    6943             : 
    6944             : static int
    6945     2491242 : attr_callback (Dwarf_Attribute *attrp, void *arg)
    6946             : {
    6947     2491242 :   struct attrcb_args *cbargs = (struct attrcb_args *) arg;
    6948     2491242 :   const int level = cbargs->level;
    6949     2491242 :   Dwarf_Die *die = cbargs->die;
    6950     2491242 :   bool is_split = cbargs->is_split;
    6951             : 
    6952     2491242 :   unsigned int attr = dwarf_whatattr (attrp);
    6953     2491242 :   if (unlikely (attr == 0))
    6954             :     {
    6955           0 :       if (!cbargs->silent)
    6956           0 :         error (0, 0, gettext ("DIE [%" PRIx64 "] "
    6957             :                               "cannot get attribute code: %s"),
    6958             :                dwarf_dieoffset (die), dwarf_errmsg (-1));
    6959             :       return DWARF_CB_ABORT;
    6960             :     }
    6961             : 
    6962     2491242 :   unsigned int form = dwarf_whatform (attrp);
    6963     2491242 :   if (unlikely (form == 0))
    6964             :     {
    6965           0 :       if (!cbargs->silent)
    6966           0 :         error (0, 0, gettext ("DIE [%" PRIx64 "] "
    6967             :                               "cannot get attribute form: %s"),
    6968             :                dwarf_dieoffset (die), dwarf_errmsg (-1));
    6969             :       return DWARF_CB_ABORT;
    6970             :     }
    6971             : 
    6972     2491242 :   switch (form)
    6973             :     {
    6974       39520 :     case DW_FORM_addr:
    6975             :     case DW_FORM_addrx:
    6976             :     case DW_FORM_addrx1:
    6977             :     case DW_FORM_addrx2:
    6978             :     case DW_FORM_addrx3:
    6979             :     case DW_FORM_addrx4:
    6980             :     case DW_FORM_GNU_addr_index:
    6981       39520 :       if (!cbargs->silent)
    6982             :         {
    6983             :           Dwarf_Addr addr;
    6984       39251 :           if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
    6985             :             {
    6986           0 :             attrval_out:
    6987           0 :               if (!cbargs->silent)
    6988           0 :                 error (0, 0, gettext ("DIE [%" PRIx64 "] "
    6989             :                                       "cannot get attribute '%s' (%s) value: "
    6990             :                                       "%s"),
    6991             :                        dwarf_dieoffset (die),
    6992             :                        dwarf_attr_name (attr),
    6993             :                        dwarf_form_name (form),
    6994             :                        dwarf_errmsg (-1));
    6995             :               /* Don't ABORT, it might be other attributes can be resolved.  */
    6996           0 :               return DWARF_CB_OK;
    6997             :             }
    6998       39251 :           if (form != DW_FORM_addr )
    6999             :             {
    7000             :               Dwarf_Word word;
    7001           8 :               if (dwarf_formudata (attrp, &word) != 0)
    7002             :                 goto attrval_out;
    7003          16 :               printf ("           %*s%-20s (%s) [%" PRIx64 "] ",
    7004             :                       (int) (level * 2), "", dwarf_attr_name (attr),
    7005             :                       dwarf_form_name (form), word);
    7006             :             }
    7007             :           else
    7008       39243 :             printf ("           %*s%-20s (%s) ",
    7009             :                     (int) (level * 2), "", dwarf_attr_name (attr),
    7010             :                     dwarf_form_name (form));
    7011       39251 :           print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr, addr);
    7012       39251 :           printf ("\n");
    7013             :         }
    7014     2233489 :       break;
    7015             : 
    7016      463440 :     case DW_FORM_indirect:
    7017             :     case DW_FORM_strp:
    7018             :     case DW_FORM_line_strp:
    7019             :     case DW_FORM_strx:
    7020             :     case DW_FORM_strx1:
    7021             :     case DW_FORM_strx2:
    7022             :     case DW_FORM_strx3:
    7023             :     case DW_FORM_strx4:
    7024             :     case DW_FORM_string:
    7025             :     case DW_FORM_GNU_strp_alt:
    7026             :     case DW_FORM_GNU_str_index:
    7027      463440 :       if (cbargs->silent)
    7028             :         break;
    7029      462692 :       const char *str = dwarf_formstring (attrp);
    7030      462692 :       if (unlikely (str == NULL))
    7031             :         goto attrval_out;
    7032      462692 :       printf ("           %*s%-20s (%s) \"%s\"\n",
    7033             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7034             :               dwarf_form_name (form), str);
    7035             :       break;
    7036             : 
    7037      593335 :     case DW_FORM_ref_addr:
    7038             :     case DW_FORM_ref_udata:
    7039             :     case DW_FORM_ref8:
    7040             :     case DW_FORM_ref4:
    7041             :     case DW_FORM_ref2:
    7042             :     case DW_FORM_ref1:
    7043             :     case DW_FORM_GNU_ref_alt:
    7044             :     case DW_FORM_ref_sup4:
    7045             :     case DW_FORM_ref_sup8:
    7046      593335 :       if (cbargs->silent)
    7047             :         break;
    7048             :       Dwarf_Die ref;
    7049      592548 :       if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
    7050             :         goto attrval_out;
    7051             : 
    7052     1185096 :       printf ("           %*s%-20s (%s) ",
    7053             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7054             :               dwarf_form_name (form));
    7055      592548 :       if (is_split)
    7056          33 :         printf ("{%6" PRIxMAX "}\n", (uintmax_t) dwarf_dieoffset (&ref));
    7057             :       else
    7058      592515 :         printf ("[%6" PRIxMAX "]\n", (uintmax_t) dwarf_dieoffset (&ref));
    7059             :       break;
    7060             : 
    7061           4 :     case DW_FORM_ref_sig8:
    7062           4 :       if (cbargs->silent)
    7063             :         break;
    7064           8 :       printf ("           %*s%-20s (%s) {%6" PRIx64 "}\n",
    7065             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7066             :               dwarf_form_name (form),
    7067           8 :               (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
    7068             :       break;
    7069             : 
    7070     1239637 :     case DW_FORM_sec_offset:
    7071             :     case DW_FORM_rnglistx:
    7072             :     case DW_FORM_loclistx:
    7073             :     case DW_FORM_implicit_const:
    7074             :     case DW_FORM_udata:
    7075             :     case DW_FORM_sdata:
    7076             :     case DW_FORM_data8: /* Note no data16 here, we see that as block. */
    7077             :     case DW_FORM_data4:
    7078             :     case DW_FORM_data2:
    7079             :     case DW_FORM_data1:;
    7080             :       Dwarf_Word num;
    7081     1239637 :       if (unlikely (dwarf_formudata (attrp, &num) != 0))
    7082             :         goto attrval_out;
    7083             : 
    7084     1239637 :       const char *valuestr = NULL;
    7085     1239637 :       bool as_hex_id = false;
    7086     1239637 :       switch (attr)
    7087             :         {
    7088             :           /* This case can take either a constant or a loclistptr.  */
    7089      205083 :         case DW_AT_data_member_location:
    7090      205083 :           if (form != DW_FORM_sec_offset
    7091      205083 :               && (cbargs->version >= 4
    7092       23806 :                   || (form != DW_FORM_data4 && form != DW_FORM_data8)))
    7093             :             {
    7094      205083 :               if (!cbargs->silent)
    7095      205083 :                 printf ("           %*s%-20s (%s) %" PRIxMAX "\n",
    7096             :                         (int) (level * 2), "", dwarf_attr_name (attr),
    7097             :                         dwarf_form_name (form), (uintmax_t) num);
    7098             :               return DWARF_CB_OK;
    7099             :             }
    7100             :           FALLTHROUGH;
    7101             : 
    7102             :         /* These cases always take a loclist[ptr] and no constant. */
    7103             :         case DW_AT_location:
    7104             :         case DW_AT_data_location:
    7105             :         case DW_AT_vtable_elem_location:
    7106             :         case DW_AT_string_length:
    7107             :         case DW_AT_use_location:
    7108             :         case DW_AT_frame_base:
    7109             :         case DW_AT_return_addr:
    7110             :         case DW_AT_static_link:
    7111             :         case DW_AT_segment:
    7112             :         case DW_AT_GNU_call_site_value:
    7113             :         case DW_AT_GNU_call_site_data_value:
    7114             :         case DW_AT_GNU_call_site_target:
    7115             :         case DW_AT_GNU_call_site_target_clobbered:
    7116             :         case DW_AT_GNU_locviews:
    7117             :           {
    7118             :             bool nlpt;
    7119       41625 :             if (cbargs->cu->version < 5)
    7120             :               {
    7121       41554 :                 if (! cbargs->is_split)
    7122             :                   {
    7123      124602 :                     nlpt = notice_listptr (section_loc, &known_locsptr,
    7124       41534 :                                            cbargs->addrsize,
    7125       41534 :                                            cbargs->offset_size,
    7126             :                                            cbargs->cu, num, attr);
    7127             :                   }
    7128             :                 else
    7129             :                   nlpt = true;
    7130             :               }
    7131             :             else
    7132             :               {
    7133             :                 /* Only register for a real section offset.  Otherwise
    7134             :                    it is a DW_FORM_loclistx which is just an index
    7135             :                    number and we should already have registered the
    7136             :                    section offset for the index when we saw the
    7137             :                    DW_AT_loclists_base CU attribute.  */
    7138          71 :                 if (form == DW_FORM_sec_offset)
    7139          96 :                   nlpt = notice_listptr (section_loc, &known_loclistsptr,
    7140          64 :                                          cbargs->addrsize, cbargs->offset_size,
    7141             :                                          cbargs->cu, num, attr);
    7142             :                 else
    7143             :                   nlpt = true;
    7144             : 
    7145             :               }
    7146             : 
    7147       41625 :             if (!cbargs->silent)
    7148             :               {
    7149       41444 :                 if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
    7150       41437 :                   printf ("           %*s%-20s (%s) location list [%6"
    7151             :                           PRIxMAX "]%s\n",
    7152             :                           (int) (level * 2), "", dwarf_attr_name (attr),
    7153             :                           dwarf_form_name (form), (uintmax_t) num,
    7154             :                           nlpt ? "" : " <WARNING offset too big>");
    7155             :                 else
    7156           7 :                   printf ("           %*s%-20s (%s) location index [%6"
    7157             :                           PRIxMAX "]\n",
    7158             :                           (int) (level * 2), "", dwarf_attr_name (attr),
    7159             :                           dwarf_form_name (form), (uintmax_t) num);
    7160             :               }
    7161             :           }
    7162             :           return DWARF_CB_OK;
    7163             : 
    7164           5 :         case DW_AT_loclists_base:
    7165           4 :           {
    7166          15 :             bool nlpt = notice_listptr (section_loc, &known_loclistsptr,
    7167          10 :                                         cbargs->addrsize, cbargs->offset_size,
    7168             :                                         cbargs->cu, num, attr);
    7169             : 
    7170           5 :             if (!cbargs->silent)
    7171           1 :               printf ("           %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n",
    7172             :                       (int) (level * 2), "", dwarf_attr_name (attr),
    7173             :                       dwarf_form_name (form), (uintmax_t) num,
    7174             :                       nlpt ? "" : " <WARNING offset too big>");
    7175             :           }
    7176             :           return DWARF_CB_OK;
    7177             : 
    7178       11023 :         case DW_AT_ranges:
    7179             :         case DW_AT_start_scope:
    7180             :           {
    7181             :             bool nlpt;
    7182       11023 :             if (cbargs->cu->version < 5)
    7183       33021 :               nlpt = notice_listptr (section_ranges, &known_rangelistptr,
    7184       22014 :                                      cbargs->addrsize, cbargs->offset_size,
    7185             :                                      cbargs->cu, num, attr);
    7186             :             else
    7187             :               {
    7188             :                 /* Only register for a real section offset.  Otherwise
    7189             :                    it is a DW_FORM_rangelistx which is just an index
    7190             :                    number and we should already have registered the
    7191             :                    section offset for the index when we saw the
    7192             :                    DW_AT_rnglists_base CU attribute.  */
    7193          16 :                 if (form == DW_FORM_sec_offset)
    7194          30 :                   nlpt = notice_listptr (section_ranges, &known_rnglistptr,
    7195          20 :                                          cbargs->addrsize, cbargs->offset_size,
    7196             :                                          cbargs->cu, num, attr);
    7197             :                 else
    7198             :                   nlpt = true;
    7199             :               }
    7200             : 
    7201       11023 :             if (!cbargs->silent)
    7202             :               {
    7203       10981 :                 if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
    7204       10979 :                   printf ("           %*s%-20s (%s) range list [%6"
    7205             :                           PRIxMAX "]%s\n",
    7206             :                           (int) (level * 2), "", dwarf_attr_name (attr),
    7207             :                           dwarf_form_name (form), (uintmax_t) num,
    7208             :                           nlpt ? "" : " <WARNING offset too big>");
    7209             :                 else
    7210           2 :                   printf ("           %*s%-20s (%s) range index [%6"
    7211             :                           PRIxMAX "]\n",
    7212             :                           (int) (level * 2), "", dwarf_attr_name (attr),
    7213             :                           dwarf_form_name (form), (uintmax_t) num);
    7214             :               }
    7215             :           }
    7216             :           return DWARF_CB_OK;
    7217             : 
    7218           4 :         case DW_AT_rnglists_base:
    7219           2 :           {
    7220          12 :             bool nlpt = notice_listptr (section_ranges, &known_rnglistptr,
    7221           8 :                                         cbargs->addrsize, cbargs->offset_size,
    7222             :                                         cbargs->cu, num, attr);
    7223           4 :             if (!cbargs->silent)
    7224           2 :               printf ("           %*s%-20s (%s) range list [%6"
    7225             :                       PRIxMAX "]%s\n",
    7226             :                       (int) (level * 2), "", dwarf_attr_name (attr),
    7227             :                       dwarf_form_name (form), (uintmax_t) num,
    7228             :                       nlpt ? "" : " <WARNING offset too big>");
    7229             :           }
    7230             :           return DWARF_CB_OK;
    7231             : 
    7232          13 :         case DW_AT_addr_base:
    7233             :         case DW_AT_GNU_addr_base:
    7234           8 :           {
    7235          39 :             bool addrbase = notice_listptr (section_addr, &known_addrbases,
    7236          13 :                                             cbargs->addrsize,
    7237          13 :                                             cbargs->offset_size,
    7238             :                                             cbargs->cu, num, attr);
    7239          13 :             if (!cbargs->silent)
    7240           5 :               printf ("           %*s%-20s (%s) address base [%6"
    7241             :                       PRIxMAX "]%s\n",
    7242             :                       (int) (level * 2), "", dwarf_attr_name (attr),
    7243             :                       dwarf_form_name (form), (uintmax_t) num,
    7244             :                       addrbase ? "" : " <WARNING offset too big>");
    7245             :           }
    7246             :           return DWARF_CB_OK;
    7247             : 
    7248           0 :         case DW_AT_str_offsets_base:
    7249           0 :           {
    7250           0 :             bool stroffbase = notice_listptr (section_str, &known_stroffbases,
    7251           0 :                                               cbargs->addrsize,
    7252           0 :                                               cbargs->offset_size,
    7253             :                                               cbargs->cu, num, attr);
    7254           0 :             if (!cbargs->silent)
    7255           0 :               printf ("           %*s%-20s (%s) str offsets base [%6"
    7256             :                       PRIxMAX "]%s\n",
    7257             :                       (int) (level * 2), "", dwarf_attr_name (attr),
    7258             :                       dwarf_form_name (form), (uintmax_t) num,
    7259             :                       stroffbase ? "" : " <WARNING offset too big>");
    7260             :           }
    7261             :           return DWARF_CB_OK;
    7262             : 
    7263        1152 :         case DW_AT_language:
    7264        1152 :           valuestr = dwarf_lang_name (num);
    7265        1152 :           break;
    7266       16426 :         case DW_AT_encoding:
    7267       32852 :           valuestr = dwarf_encoding_name (num);
    7268       16426 :           break;
    7269           0 :         case DW_AT_accessibility:
    7270           0 :           valuestr = dwarf_access_name (num);
    7271           0 :           break;
    7272           0 :         case DW_AT_defaulted:
    7273           0 :           valuestr = dwarf_defaulted_name (num);
    7274           0 :           break;
    7275           0 :         case DW_AT_visibility:
    7276           0 :           valuestr = dwarf_visibility_name (num);
    7277           0 :           break;
    7278           0 :         case DW_AT_virtuality:
    7279           0 :           valuestr = dwarf_virtuality_name (num);
    7280           0 :           break;
    7281           0 :         case DW_AT_identifier_case:
    7282           0 :           valuestr = dwarf_identifier_case_name (num);
    7283           0 :           break;
    7284           0 :         case DW_AT_calling_convention:
    7285           0 :           valuestr = dwarf_calling_convention_name (num);
    7286           0 :           break;
    7287        2927 :         case DW_AT_inline:
    7288        5854 :           valuestr = dwarf_inline_name (num);
    7289        2927 :           break;
    7290           0 :         case DW_AT_ordering:
    7291           0 :           valuestr = dwarf_ordering_name (num);
    7292           0 :           break;
    7293           0 :         case DW_AT_discr_list:
    7294           0 :           valuestr = dwarf_discr_list_name (num);
    7295           0 :           break;
    7296      363012 :         case DW_AT_decl_file:
    7297             :         case DW_AT_call_file:
    7298      363012 :           {
    7299      363012 :             if (cbargs->silent)
    7300             :               break;
    7301             : 
    7302             :             /* Try to get the actual file, the current interface only
    7303             :                gives us full paths, but we only want to show the file
    7304             :                name for now.  */
    7305             :             Dwarf_Die cudie;
    7306      362591 :             if (dwarf_cu_die (cbargs->cu, &cudie,
    7307             :                               NULL, NULL, NULL, NULL, NULL, NULL) != NULL)
    7308             :               {
    7309             :                 Dwarf_Files *files;
    7310             :                 size_t nfiles;
    7311      362591 :                 if (dwarf_getsrcfiles (&cudie, &files, &nfiles) == 0)
    7312             :                   {
    7313      362591 :                     valuestr = dwarf_filesrc (files, num, NULL, NULL);
    7314      362591 :                     if (valuestr != NULL)
    7315             :                       {
    7316      362591 :                         char *filename = strrchr (valuestr, '/');
    7317      362591 :                         if (filename != NULL)
    7318      362591 :                           valuestr = filename + 1;
    7319             :                       }
    7320             :                     else
    7321           0 :                       error (0, 0, gettext ("invalid file (%" PRId64 "): %s"),
    7322             :                              num, dwarf_errmsg (-1));
    7323             :                   }
    7324             :                 else
    7325           0 :                   error (0, 0, gettext ("no srcfiles for CU [%" PRIx64 "]"),
    7326             :                          dwarf_dieoffset (&cudie));
    7327             :               }
    7328             :             else
    7329           0 :              error (0, 0, gettext ("couldn't get DWARF CU: %s"),
    7330             :                     dwarf_errmsg (-1));
    7331      362591 :             if (valuestr == NULL)
    7332             :               valuestr = "???";
    7333             :           }
    7334      362591 :           break;
    7335          13 :         case DW_AT_GNU_dwo_id:
    7336          13 :           as_hex_id = true;
    7337          13 :           break;
    7338             : 
    7339             :         default:
    7340             :           /* Nothing.  */
    7341             :           break;
    7342             :         }
    7343             : 
    7344      981884 :       if (cbargs->silent)
    7345             :         break;
    7346             : 
    7347             :       /* When highpc is in constant form it is relative to lowpc.
    7348             :          In that case also show the address.  */
    7349             :       Dwarf_Addr highpc;
    7350      980043 :       if (attr == DW_AT_high_pc && dwarf_highpc (cbargs->die, &highpc) == 0)
    7351             :         {
    7352       27334 :           printf ("           %*s%-20s (%s) %" PRIuMAX " (",
    7353             :                   (int) (level * 2), "", dwarf_attr_name (attr),
    7354             :                   dwarf_form_name (form), (uintmax_t) num);
    7355       13667 :           print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, highpc, highpc);
    7356             :           printf (")\n");
    7357             :         }
    7358             :       else
    7359             :         {
    7360      966376 :           if (as_hex_id)
    7361             :             {
    7362           2 :               printf ("           %*s%-20s (%s) 0x%.16" PRIx64 "\n",
    7363             :                       (int) (level * 2), "", dwarf_attr_name (attr),
    7364             :                       dwarf_form_name (form), num);
    7365             :             }
    7366             :           else
    7367      966374 :             {
    7368      966374 :               Dwarf_Sword snum = 0;
    7369             :               bool is_signed;
    7370      966374 :               int bytes = 0;
    7371      966374 :               if (attr == DW_AT_const_value)
    7372      100273 :                 die_type_sign_bytes (cbargs->die, &is_signed, &bytes);
    7373             :               else
    7374     1732202 :                 is_signed = (form == DW_FORM_sdata
    7375      866101 :                              || form == DW_FORM_implicit_const);
    7376             : 
    7377      966374 :               if (is_signed)
    7378         144 :                 if (unlikely (dwarf_formsdata (attrp, &snum) != 0))
    7379             :                   goto attrval_out;
    7380             : 
    7381      966374 :               if (valuestr == NULL)
    7382             :                 {
    7383      583581 :                   printf ("           %*s%-20s (%s) ",
    7384             :                           (int) (level * 2), "", dwarf_attr_name (attr),
    7385             :                           dwarf_form_name (form));
    7386             :                 }
    7387             :               else
    7388             :                 {
    7389      382793 :                   printf ("           %*s%-20s (%s) %s (",
    7390             :                           (int) (level * 2), "", dwarf_attr_name (attr),
    7391             :                           dwarf_form_name (form), valuestr);
    7392             :                 }
    7393             : 
    7394      966374 :               switch (bytes)
    7395             :                 {
    7396           2 :                 case 1:
    7397           2 :                   if (is_signed)
    7398           1 :                     printf ("%" PRId8, (int8_t) snum);
    7399             :                   else
    7400           1 :                     printf ("%" PRIu8, (uint8_t) num);
    7401             :                   break;
    7402             : 
    7403           2 :                 case 2:
    7404           2 :                   if (is_signed)
    7405           1 :                     printf ("%" PRId16, (int16_t) snum);
    7406             :                   else
    7407           1 :                     printf ("%" PRIu16, (uint16_t) num);
    7408             :                   break;
    7409             : 
    7410         123 :                 case 4:
    7411         123 :                   if (is_signed)
    7412         120 :                     printf ("%" PRId32, (int32_t) snum);
    7413             :                   else
    7414           3 :                     printf ("%" PRIu32, (uint32_t) num);
    7415             :                   break;
    7416             : 
    7417          80 :                 case 8:
    7418          80 :                   if (is_signed)
    7419           1 :                     printf ("%" PRId64, (int64_t) snum);
    7420             :                   else
    7421          79 :                     printf ("%" PRIu64, (uint64_t) num);
    7422             :                   break;
    7423             : 
    7424      966167 :                 default:
    7425      966167 :                   if (is_signed)
    7426          21 :                     printf ("%" PRIdMAX, (intmax_t) snum);
    7427             :                   else
    7428      966146 :                     printf ("%" PRIuMAX, (uintmax_t) num);
    7429             :                   break;
    7430             :                 }
    7431             : 
    7432             :               /* Make clear if we switched from a signed encoding to
    7433             :                  an unsigned value.  */
    7434      966374 :               if (attr == DW_AT_const_value
    7435      100273 :                   && (form == DW_FORM_sdata || form == DW_FORM_implicit_const)
    7436        1227 :                   && !is_signed)
    7437        1219 :                 printf (" (%" PRIdMAX ")", (intmax_t) num);
    7438             : 
    7439      966374 :               if (valuestr == NULL)
    7440             :                 printf ("\n");
    7441             :               else
    7442             :                 printf (")\n");
    7443             :             }
    7444             :         }
    7445             :       break;
    7446             : 
    7447        9122 :     case DW_FORM_flag:
    7448        9122 :       if (cbargs->silent)
    7449             :         break;
    7450             :       bool flag;
    7451        9048 :       if (unlikely (dwarf_formflag (attrp, &flag) != 0))
    7452             :         goto attrval_out;
    7453             : 
    7454        9048 :       printf ("           %*s%-20s (%s) %s\n",
    7455             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7456        9048 :               dwarf_form_name (form), flag ? yes_str : no_str);
    7457             :       break;
    7458             : 
    7459       63246 :     case DW_FORM_flag_present:
    7460       63246 :       if (cbargs->silent)
    7461             :         break;
    7462       62972 :       printf ("           %*s%-20s (%s) %s\n",
    7463             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7464             :               dwarf_form_name (form), yes_str);
    7465             :       break;
    7466             : 
    7467       82938 :     case DW_FORM_exprloc:
    7468             :     case DW_FORM_block4:
    7469             :     case DW_FORM_block2:
    7470             :     case DW_FORM_block1:
    7471             :     case DW_FORM_block:
    7472             :     case DW_FORM_data16: /* DWARF5 calls this a constant class.  */
    7473       82938 :       if (cbargs->silent)
    7474             :         break;
    7475             :       Dwarf_Block block;
    7476       82809 :       if (unlikely (dwarf_formblock (attrp, &block) != 0))
    7477             :         goto attrval_out;
    7478             : 
    7479      165618 :       printf ("           %*s%-20s (%s) ",
    7480             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7481             :               dwarf_form_name (form));
    7482             : 
    7483       82809 :       switch (attr)
    7484             :         {
    7485          16 :         default:
    7486          16 :           if (form != DW_FORM_exprloc)
    7487             :             {
    7488          16 :               print_block (block.length, block.data);
    7489          16 :               break;
    7490             :             }
    7491             :           FALLTHROUGH;
    7492             : 
    7493             :         case DW_AT_location:
    7494             :         case DW_AT_data_location:
    7495             :         case DW_AT_data_member_location:
    7496             :         case DW_AT_vtable_elem_location:
    7497             :         case DW_AT_string_length:
    7498             :         case DW_AT_use_location:
    7499             :         case DW_AT_frame_base:
    7500             :         case DW_AT_return_addr:
    7501             :         case DW_AT_static_link:
    7502             :         case DW_AT_allocated:
    7503             :         case DW_AT_associated:
    7504             :         case DW_AT_bit_size:
    7505             :         case DW_AT_bit_offset:
    7506             :         case DW_AT_bit_stride:
    7507             :         case DW_AT_byte_size:
    7508             :         case DW_AT_byte_stride:
    7509             :         case DW_AT_count:
    7510             :         case DW_AT_lower_bound:
    7511             :         case DW_AT_upper_bound:
    7512             :         case DW_AT_GNU_call_site_value:
    7513             :         case DW_AT_GNU_call_site_data_value:
    7514             :         case DW_AT_GNU_call_site_target:
    7515             :         case DW_AT_GNU_call_site_target_clobbered:
    7516       82793 :           if (form != DW_FORM_data16)
    7517             :             {
    7518       82793 :               putchar ('\n');
    7519      165586 :               print_ops (cbargs->dwflmod, cbargs->dbg,
    7520       82793 :                          12 + level * 2, 12 + level * 2,
    7521             :                          cbargs->version, cbargs->addrsize, cbargs->offset_size,
    7522       82793 :                          attrp->cu, block.length, block.data);
    7523             :             }
    7524             :           else
    7525           0 :             print_block (block.length, block.data);
    7526             :           break;
    7527             :         }
    7528             :       break;
    7529             : 
    7530           0 :     default:
    7531           0 :       if (cbargs->silent)
    7532             :         break;
    7533           0 :       printf ("           %*s%-20s (%s) ???\n",
    7534             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7535             :               dwarf_form_name (form));
    7536             :       break;
    7537             :     }
    7538             : 
    7539     2233489 :   return DWARF_CB_OK;
    7540             : }
    7541             : 
    7542             : static void
    7543          95 : print_debug_units (Dwfl_Module *dwflmod,
    7544             :                    Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
    7545             :                    Elf_Scn *scn, GElf_Shdr *shdr,
    7546             :                    Dwarf *dbg, bool debug_types)
    7547             : {
    7548          95 :   const bool silent = !(print_debug_sections & section_info) && !debug_types;
    7549          95 :   const char *secname = section_name (ebl, shdr);
    7550             : 
    7551          95 :   if (!silent)
    7552          60 :     printf (gettext ("\
    7553             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
    7554          60 :             elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
    7555             : 
    7556             :   /* If the section is empty we don't have to do anything.  */
    7557          95 :   if (!silent && shdr->sh_size == 0)
    7558           0 :     return;
    7559             : 
    7560          95 :   int maxdies = 20;
    7561          95 :   Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
    7562             : 
    7563             :   /* New compilation unit.  */
    7564             :   Dwarf_Half version;
    7565             : 
    7566             :   Dwarf_Die result;
    7567             :   Dwarf_Off abbroffset;
    7568             :   uint8_t addrsize;
    7569             :   uint8_t offsize;
    7570             :   uint64_t unit_id;
    7571             :   Dwarf_Off subdie_off;
    7572             : 
    7573             :   int unit_res;
    7574             :   Dwarf_CU *cu;
    7575             :   Dwarf_CU cu_mem;
    7576             :   uint8_t unit_type;
    7577             :   Dwarf_Die cudie;
    7578             : 
    7579             :   /* We cheat a little because we want to see only the CUs from .debug_info
    7580             :      or .debug_types.  We know the Dwarf_CU struct layout.  Set it up at
    7581             :      the end of .debug_info if we want .debug_types only.  Check the returned
    7582             :      Dwarf_CU is still in the expected section.  */
    7583          95 :   if (debug_types)
    7584             :     {
    7585           1 :       cu_mem.dbg = dbg;
    7586           1 :       cu_mem.end = dbg->sectiondata[IDX_debug_info]->d_size;
    7587           1 :       cu_mem.sec_idx = IDX_debug_info;
    7588           1 :       cu = &cu_mem;
    7589             :     }
    7590             :   else
    7591          94 :     cu = NULL;
    7592             : 
    7593             :  next_cu:
    7594        1256 :   unit_res = dwarf_get_units (dbg, cu, &cu, &version, &unit_type,
    7595             :                               &cudie, NULL);
    7596        1256 :   if (unit_res == 1)
    7597             :     goto do_return;
    7598             : 
    7599        1162 :   if (unit_res == -1)
    7600             :     {
    7601           0 :       if (!silent)
    7602           0 :         error (0, 0, gettext ("cannot get next unit: %s"), dwarf_errmsg (-1));
    7603             :       goto do_return;
    7604             :     }
    7605             : 
    7606        1162 :   if (cu->sec_idx != (size_t) (debug_types ? IDX_debug_types : IDX_debug_info))
    7607             :     goto do_return;
    7608             : 
    7609        1161 :   dwarf_cu_die (cu, &result, NULL, &abbroffset, &addrsize, &offsize,
    7610             :                 &unit_id, &subdie_off);
    7611             : 
    7612        1161 :   if (!silent)
    7613             :     {
    7614        1112 :       Dwarf_Off offset = cu->start;
    7615        1112 :       if (debug_types && version < 5)
    7616           2 :         {
    7617             :           Dwarf_Die typedie;
    7618             :           Dwarf_Off dieoffset;
    7619           2 :           dieoffset = dwarf_dieoffset (dwarf_offdie_types (dbg, subdie_off,
    7620             :                                                            &typedie));
    7621           4 :           printf (gettext (" Type unit at offset %" PRIu64 ":\n"
    7622             :                            " Version: %" PRIu16
    7623             :                            ", Abbreviation section offset: %" PRIu64
    7624             :                            ", Address size: %" PRIu8
    7625             :                            ", Offset size: %" PRIu8
    7626             :                            "\n Type signature: %#" PRIx64
    7627             :                            ", Type offset: %#" PRIx64 " [%" PRIx64 "]\n"),
    7628             :                   (uint64_t) offset, version, abbroffset, addrsize, offsize,
    7629             :                   unit_id, (uint64_t) subdie_off, dieoffset);
    7630             :         }
    7631             :       else
    7632             :         {
    7633        2220 :           printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
    7634             :                            " Version: %" PRIu16
    7635             :                            ", Abbreviation section offset: %" PRIu64
    7636             :                            ", Address size: %" PRIu8
    7637             :                            ", Offset size: %" PRIu8 "\n"),
    7638             :                   (uint64_t) offset, version, abbroffset, addrsize, offsize);
    7639             : 
    7640        2215 :           if (version >= 5 || (unit_type != DW_UT_compile
    7641        1105 :                                && unit_type != DW_UT_partial))
    7642             :             {
    7643          12 :               printf (gettext (" Unit type: %s (%" PRIu8 ")"),
    7644             :                                dwarf_unit_name (unit_type), unit_type);
    7645           6 :               if (unit_type == DW_UT_type
    7646           6 :                   || unit_type == DW_UT_skeleton
    7647           1 :                   || unit_type == DW_UT_split_compile
    7648           1 :                   || unit_type == DW_UT_split_type)
    7649           5 :                 printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
    7650           6 :               if (unit_type == DW_UT_type
    7651           6 :                   || unit_type == DW_UT_split_type)
    7652             :                 {
    7653             :                   Dwarf_Die typedie;
    7654             :                   Dwarf_Off dieoffset;
    7655           0 :                   dwarf_cu_info (cu, NULL, NULL, NULL, &typedie,
    7656             :                                  NULL, NULL, NULL);
    7657           0 :                   dieoffset = dwarf_dieoffset (&typedie);
    7658           0 :                   printf (", Unit DIE off: %#" PRIx64 " [%" PRIx64 "]",
    7659             :                           subdie_off, dieoffset);
    7660             :                 }
    7661             :               printf ("\n");
    7662             :             }
    7663             :         }
    7664             :     }
    7665             : 
    7666        1161 :   if (version < 2 || version > 5
    7667        1161 :       || unit_type < DW_UT_compile || unit_type > DW_UT_split_type)
    7668             :     {
    7669           0 :       if (!silent)
    7670           0 :         error (0, 0, gettext ("unknown version (%d) or unit type (%d)"),
    7671             :                version, unit_type);
    7672             :       goto next_cu;
    7673             :     }
    7674             : 
    7675        1161 :   struct attrcb_args args =
    7676             :     {
    7677             :       .dwflmod = dwflmod,
    7678             :       .silent = silent,
    7679             :       .version = version,
    7680             :       .addrsize = addrsize,
    7681             :       .offset_size = offsize
    7682             :     };
    7683             : 
    7684        1161 :   bool is_split = false;
    7685        1161 :   int level = 0;
    7686        1161 :   dies[0] = cudie;
    7687        1161 :   args.cu = dies[0].cu;
    7688        1161 :   args.dbg = dbg;
    7689             :   args.is_split = is_split;
    7690             : 
    7691             :   /* We might return here again for the split CU subdie.  */
    7692      714773 :   do_cu:
    7693             :   do
    7694             :     {
    7695      715938 :       Dwarf_Off offset = dwarf_dieoffset (&dies[level]);
    7696      715938 :       if (unlikely (offset == (Dwarf_Off) -1))
    7697             :         {
    7698           0 :           if (!silent)
    7699           0 :             error (0, 0, gettext ("cannot get DIE offset: %s"),
    7700             :                    dwarf_errmsg (-1));
    7701             :           goto do_return;
    7702             :         }
    7703             : 
    7704      715938 :       int tag = dwarf_tag (&dies[level]);
    7705      715938 :       if (unlikely (tag == DW_TAG_invalid))
    7706             :         {
    7707           0 :           if (!silent)
    7708           0 :             error (0, 0, gettext ("cannot get tag of DIE at offset [%" PRIx64
    7709             :                                   "] in section '%s': %s"),
    7710             :                    (uint64_t) offset, secname, dwarf_errmsg (-1));
    7711             :           goto do_return;
    7712             :         }
    7713             : 
    7714      715938 :       if (!silent)
    7715             :         {
    7716      714950 :           unsigned int code = dwarf_getabbrevcode (dies[level].abbrev);
    7717      714950 :           if (is_split)
    7718             :             printf (" {%6" PRIx64 "}  ", (uint64_t) offset);
    7719             :           else
    7720             :             printf (" [%6" PRIx64 "]  ", (uint64_t) offset);
    7721      714950 :           printf ("%*s%-20s abbrev: %u\n", (int) (level * 2), "",
    7722             :                   dwarf_tag_name (tag), code);
    7723             :         }
    7724             : 
    7725             :       /* Print the attribute values.  */
    7726      715938 :       args.level = level;
    7727      715938 :       args.die = &dies[level];
    7728      715938 :       (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
    7729             : 
    7730             :       /* Make room for the next level's DIE.  */
    7731      715938 :       if (level + 1 == maxdies)
    7732           0 :         dies = (Dwarf_Die *) xrealloc (dies,
    7733           0 :                                        (maxdies += 10)
    7734             :                                        * sizeof (Dwarf_Die));
    7735             : 
    7736      715938 :       int res = dwarf_child (&dies[level], &dies[level + 1]);
    7737      715938 :       if (res > 0)
    7738             :         {
    7739      715938 :           while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
    7740      101554 :             if (level-- == 0)
    7741             :               break;
    7742             : 
    7743      615549 :           if (unlikely (res == -1))
    7744             :             {
    7745           0 :               if (!silent)
    7746           0 :                 error (0, 0, gettext ("cannot get next DIE: %s\n"),
    7747             :                        dwarf_errmsg (-1));
    7748             :               goto do_return;
    7749             :             }
    7750             :         }
    7751      100389 :       else if (unlikely (res < 0))
    7752             :         {
    7753           0 :           if (!silent)
    7754           0 :             error (0, 0, gettext ("cannot get next DIE: %s"),
    7755             :                    dwarf_errmsg (-1));
    7756             :           goto do_return;
    7757             :         }
    7758             :       else
    7759             :         ++level;
    7760             :     }
    7761      715938 :   while (level >= 0);
    7762             : 
    7763             :   /* We might want to show the split compile unit if this was a skeleton.
    7764             :      We need to scan it if we are requesting printing .debug_ranges for
    7765             :      DWARF4 since GNU DebugFission uses "offsets" into the main ranges
    7766             :      section.  */
    7767        1165 :   if (unit_type == DW_UT_skeleton
    7768          13 :       && ((!silent && show_split_units)
    7769          10 :           || (version < 5 && (print_debug_sections & section_ranges) != 0)))
    7770             :     {
    7771             :       Dwarf_Die subdie;
    7772           5 :       if (dwarf_cu_info (cu, NULL, NULL, NULL, &subdie, NULL, NULL, NULL) != 0
    7773           5 :           || dwarf_tag (&subdie) == DW_TAG_invalid)
    7774             :         {
    7775           1 :           if (!silent)
    7776             :             {
    7777             :               Dwarf_Attribute dwo_at;
    7778           1 :               const char *dwo_name =
    7779           1 :                 (dwarf_formstring (dwarf_attr (&cudie, DW_AT_dwo_name,
    7780             :                                                &dwo_at))
    7781           1 :                  ?: (dwarf_formstring (dwarf_attr (&cudie, DW_AT_GNU_dwo_name,
    7782             :                                                    &dwo_at))
    7783           0 :                      ?: "<unknown>"));
    7784           2 :               fprintf (stderr,
    7785             :                        "Could not find split unit '%s', id: %" PRIx64 "\n",
    7786             :                        dwo_name, unit_id);
    7787             :             }
    7788             :         }
    7789             :       else
    7790             :         {
    7791           4 :           Dwarf_CU *split_cu = subdie.cu;
    7792           4 :           dwarf_cu_die (split_cu, &result, NULL, &abbroffset,
    7793             :                         &addrsize, &offsize, &unit_id, &subdie_off);
    7794           4 :           Dwarf_Off offset = cu->start;
    7795             : 
    7796           4 :           if (!silent)
    7797             :             {
    7798           4 :               printf (gettext (" Split compilation unit at offset %"
    7799             :                                PRIu64 ":\n"
    7800             :                                " Version: %" PRIu16
    7801             :                                ", Abbreviation section offset: %" PRIu64
    7802             :                                ", Address size: %" PRIu8
    7803             :                                ", Offset size: %" PRIu8 "\n"),
    7804             :                       (uint64_t) offset, version, abbroffset,
    7805             :                       addrsize, offsize);
    7806           4 :               printf (gettext (" Unit type: %s (%" PRIu8 ")"),
    7807             :                       dwarf_unit_name (unit_type), unit_type);
    7808           4 :               printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
    7809             :               printf ("\n");
    7810             :             }
    7811             : 
    7812           4 :           unit_type = DW_UT_split_compile;
    7813           4 :           is_split = true;
    7814           4 :           level = 0;
    7815           4 :           dies[0] = subdie;
    7816           4 :           args.cu = dies[0].cu;
    7817           4 :           args.dbg = split_cu->dbg;
    7818           4 :           args.is_split = is_split;
    7819           4 :           goto do_cu;
    7820             :         }
    7821             :     }
    7822             : 
    7823             :   /* And again... */
    7824             :   goto next_cu;
    7825             : 
    7826          95 :  do_return:
    7827          95 :   free (dies);
    7828             : }
    7829             : 
    7830             : static void
    7831          17 : print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
    7832             :                           Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    7833             : {
    7834          94 :   print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
    7835          17 : }
    7836             : 
    7837             : static void
    7838           1 : print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
    7839             :                            Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    7840             : {
    7841           1 :   print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
    7842           1 : }
    7843             : 
    7844             : 
    7845             : static void
    7846           4 : print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
    7847             :                             GElf_Ehdr *ehdr __attribute__ ((unused)),
    7848             :                             Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    7849             : {
    7850           8 :   printf (gettext ("\
    7851             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n\n"),
    7852             :           elf_ndxscn (scn), section_name (ebl, shdr),
    7853           4 :           (uint64_t) shdr->sh_offset);
    7854             : 
    7855           4 :   size_t address_size
    7856           4 :     = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    7857             : 
    7858             :   Dwarf_Lines *lines;
    7859             :   size_t nlines;
    7860           4 :   Dwarf_Off off, next_off = 0;
    7861           4 :   Dwarf_CU *cu = NULL;
    7862          12 :   while (dwarf_next_lines (dbg, off = next_off, &next_off, &cu, NULL, NULL,
    7863             :                            &lines, &nlines) == 0)
    7864             :     {
    7865             :       Dwarf_Die cudie;
    7866           8 :       if (cu != NULL && dwarf_cu_info (cu, NULL, NULL, &cudie,
    7867             :                                        NULL, NULL, NULL, NULL) == 0)
    7868           6 :         printf (" CU [%" PRIx64 "] %s\n",
    7869             :                 dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
    7870             :       else
    7871             :         {
    7872             :           /* DWARF5 lines can be independent of any CU, but they probably
    7873             :              are used by some CU.  Determine the CU this block is for.  */
    7874             :           Dwarf_Off cuoffset;
    7875           2 :           Dwarf_Off ncuoffset = 0;
    7876             :           size_t hsize;
    7877           3 :           while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
    7878             :                                NULL, NULL, NULL) == 0)
    7879             :             {
    7880           3 :               if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
    7881           0 :                 continue;
    7882             :               Dwarf_Attribute stmt_list;
    7883           3 :               if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
    7884           0 :                 continue;
    7885             :               Dwarf_Word lineoff;
    7886           3 :               if (dwarf_formudata (&stmt_list, &lineoff) != 0)
    7887           0 :                 continue;
    7888           3 :               if (lineoff == off)
    7889             :                 {
    7890             :                   /* Found the CU.  */
    7891           2 :                   cu = cudie.cu;
    7892           2 :                   break;
    7893             :                 }
    7894             :             }
    7895             : 
    7896           2 :           if (cu != NULL)
    7897           2 :             printf (" CU [%" PRIx64 "] %s\n",
    7898             :                     dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
    7899             :           else
    7900             :             printf (" No CU\n");
    7901             :         }
    7902             : 
    7903           8 :       printf ("  line:col SBPE* disc isa op address"
    7904             :               " (Statement Block Prologue Epilogue *End)\n");
    7905           8 :       const char *last_file = "";
    7906         168 :       for (size_t n = 0; n < nlines; n++)
    7907             :         {
    7908         160 :           Dwarf_Line *line = dwarf_onesrcline (lines, n);
    7909         160 :           if (line == NULL)
    7910             :             {
    7911           0 :               printf ("  dwarf_onesrcline: %s\n", dwarf_errmsg (-1));
    7912           0 :               continue;
    7913             :             }
    7914             :           Dwarf_Word mtime, length;
    7915         160 :           const char *file = dwarf_linesrc (line, &mtime, &length);
    7916         160 :           if (file == NULL)
    7917             :             {
    7918           0 :               printf ("  <%s> (mtime: ?, length: ?)\n", dwarf_errmsg (-1));
    7919           0 :               last_file = "";
    7920             :             }
    7921         160 :           else if (strcmp (last_file, file) != 0)
    7922             :             {
    7923          40 :               printf ("  %s (mtime: %" PRIu64 ", length: %" PRIu64 ")\n",
    7924             :                       file, mtime, length);
    7925          20 :               last_file = file;
    7926             :             }
    7927             : 
    7928             :           int lineno, colno;
    7929             :           bool statement, endseq, block, prologue_end, epilogue_begin;
    7930             :           unsigned int lineop, isa, disc;
    7931             :           Dwarf_Addr address;
    7932         160 :           dwarf_lineaddr (line, &address);
    7933         160 :           dwarf_lineno (line, &lineno);
    7934         160 :           dwarf_linecol (line, &colno);
    7935         160 :           dwarf_lineop_index (line, &lineop);
    7936         160 :           dwarf_linebeginstatement (line, &statement);
    7937         160 :           dwarf_lineendsequence (line, &endseq);
    7938         160 :           dwarf_lineblock (line, &block);
    7939         160 :           dwarf_lineprologueend (line, &prologue_end);
    7940         160 :           dwarf_lineepiloguebegin (line, &epilogue_begin);
    7941         160 :           dwarf_lineisa (line, &isa);
    7942         160 :           dwarf_linediscriminator (line, &disc);
    7943             : 
    7944             :           /* End sequence is special, it is one byte past.  */
    7945        1120 :           printf ("  %4d:%-3d %c%c%c%c%c %4d %3d %2d ",
    7946             :                   lineno, colno,
    7947         160 :                   (statement ? 'S' : ' '),
    7948         160 :                   (block ? 'B' : ' '),
    7949         160 :                   (prologue_end ? 'P' : ' '),
    7950         160 :                   (epilogue_begin ? 'E' : ' '),
    7951         160 :                   (endseq ? '*' : ' '),
    7952             :                   disc, isa, lineop);
    7953         320 :           print_dwarf_addr (dwflmod, address_size,
    7954         160 :                             address - (endseq ? 1 : 0), address);
    7955         160 :           printf ("\n");
    7956             : 
    7957         160 :           if (endseq)
    7958             :             printf("\n");
    7959             :         }
    7960             :     }
    7961           4 : }
    7962             : 
    7963             : 
    7964             : /* Print the value of a form.
    7965             :    Returns new value of readp, or readendp on failure.  */
    7966             : static const unsigned char *
    7967          20 : print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
    7968             :                  const unsigned char *readendp, unsigned int offset_len,
    7969             :                  Dwarf_Off str_offsets_base)
    7970             : {
    7971             :   Dwarf_Word val;
    7972             :   unsigned char *endp;
    7973             :   Elf_Data *data;
    7974             :   char *str;
    7975          20 :   switch (form)
    7976             :     {
    7977           8 :     case DW_FORM_data1:
    7978           8 :       if (readendp - readp < 1)
    7979             :         {
    7980           0 :         invalid_data:
    7981           0 :           error (0, 0, "invalid data");
    7982           0 :           return readendp;
    7983             :         }
    7984           8 :       val = *readp++;
    7985           8 :       printf (" %" PRIx8, (unsigned int) val);
    7986             :       break;
    7987             : 
    7988           0 :     case DW_FORM_data2:
    7989           0 :       if (readendp - readp < 2)
    7990             :         goto invalid_data;
    7991           0 :       val = read_2ubyte_unaligned_inc (dbg, readp);
    7992           0 :       printf(" %" PRIx16, (unsigned int) val);
    7993             :       break;
    7994             : 
    7995           0 :     case DW_FORM_data4:
    7996           0 :       if (readendp - readp < 4)
    7997             :         goto invalid_data;
    7998           0 :       val = read_4ubyte_unaligned_inc (dbg, readp);
    7999           0 :       printf (" %" PRIx32, (unsigned int) val);
    8000             :       break;
    8001             : 
    8002           0 :     case DW_FORM_data8:
    8003           0 :       if (readendp - readp < 8)
    8004             :         goto invalid_data;
    8005           0 :       val = read_8ubyte_unaligned_inc (dbg, readp);
    8006             :       printf (" %" PRIx64, val);
    8007             :       break;
    8008             : 
    8009           0 :     case DW_FORM_sdata:
    8010           0 :       if (readendp - readp < 1)
    8011             :         goto invalid_data;
    8012           0 :       get_sleb128 (val, readp, readendp);
    8013             :       printf (" %" PRIx64, val);
    8014             :       break;
    8015             : 
    8016           0 :     case DW_FORM_udata:
    8017           0 :       if (readendp - readp < 1)
    8018             :         goto invalid_data;
    8019           0 :       get_uleb128 (val, readp, readendp);
    8020             :       printf (" %" PRIx64, val);
    8021             :       break;
    8022             : 
    8023           0 :     case DW_FORM_block:
    8024           0 :       if (readendp - readp < 1)
    8025             :         goto invalid_data;
    8026           0 :       get_uleb128 (val, readp, readendp);
    8027           0 :       if ((size_t) (readendp - readp) < val)
    8028             :         goto invalid_data;
    8029           0 :       print_bytes (val, readp);
    8030           0 :       readp += val;
    8031           0 :       break;
    8032             : 
    8033           0 :     case DW_FORM_block1:
    8034           0 :       if (readendp - readp < 1)
    8035             :         goto invalid_data;
    8036           0 :       val = *readp++;
    8037           0 :       if ((size_t) (readendp - readp) < val)
    8038             :         goto invalid_data;
    8039           0 :       print_bytes (val, readp);
    8040           0 :       readp += val;
    8041           0 :       break;
    8042             : 
    8043           0 :     case DW_FORM_block2:
    8044           0 :       if (readendp - readp < 2)
    8045             :         goto invalid_data;
    8046           0 :       val = read_2ubyte_unaligned_inc (dbg, readp);
    8047           0 :       if ((size_t) (readendp - readp) < val)
    8048             :         goto invalid_data;
    8049           0 :       print_bytes (val, readp);
    8050           0 :       readp += val;
    8051           0 :       break;
    8052             : 
    8053           0 :     case DW_FORM_block4:
    8054           0 :       if (readendp - readp < 4)
    8055             :         goto invalid_data;
    8056           0 :       val = read_4ubyte_unaligned_inc (dbg, readp);
    8057           0 :       if ((size_t) (readendp - readp) < val)
    8058             :         goto invalid_data;
    8059           0 :       print_bytes (val, readp);
    8060           0 :       readp += val;
    8061           0 :       break;
    8062             : 
    8063           0 :     case DW_FORM_data16:
    8064           0 :       if (readendp - readp < 16)
    8065             :         goto invalid_data;
    8066           0 :       print_bytes (16, readp);
    8067           0 :       readp += 16;
    8068           0 :       break;
    8069             : 
    8070           0 :     case DW_FORM_flag:
    8071           0 :       if (readendp - readp < 1)
    8072             :         goto invalid_data;
    8073           0 :       val = *readp++;
    8074           0 :       printf ("%s", val != 0 ? yes_str : no_str);
    8075             :       break;
    8076             : 
    8077           0 :     case DW_FORM_string:
    8078           0 :       endp = memchr (readp, '\0', readendp - readp);
    8079           0 :       if (endp == NULL)
    8080             :         goto invalid_data;
    8081           0 :       printf ("%s", readp);
    8082           0 :       readp = endp + 1;
    8083           0 :       break;
    8084             : 
    8085          12 :     case DW_FORM_strp:
    8086             :     case DW_FORM_line_strp:
    8087             :     case DW_FORM_strp_sup:
    8088          12 :       if ((size_t) (readendp - readp) < offset_len)
    8089             :         goto invalid_data;
    8090          12 :       if (offset_len == 8)
    8091           0 :         val = read_8ubyte_unaligned_inc (dbg, readp);
    8092             :       else
    8093          12 :         val = read_4ubyte_unaligned_inc (dbg, readp);
    8094          12 :       if (form == DW_FORM_strp)
    8095           0 :         data = dbg->sectiondata[IDX_debug_str];
    8096          12 :       else if (form == DW_FORM_line_strp)
    8097          12 :         data = dbg->sectiondata[IDX_debug_line_str];
    8098             :       else /* form == DW_FORM_strp_sup */
    8099             :         {
    8100           0 :           Dwarf *alt = dwarf_getalt (dbg);
    8101           0 :           data = alt != NULL ? alt->sectiondata[IDX_debug_str] : NULL;
    8102             :         }
    8103          12 :       if (data == NULL || val >= data->d_size
    8104          12 :           || memchr (data->d_buf + val, '\0', data->d_size - val) == NULL)
    8105             :         str = "???";
    8106             :       else
    8107          12 :         str = (char *) data->d_buf + val;
    8108             :       printf ("%s (%" PRIu64 ")", str, val);
    8109             :       break;
    8110             : 
    8111           0 :     case DW_FORM_sec_offset:
    8112           0 :       if ((size_t) (readendp - readp) < offset_len)
    8113             :         goto invalid_data;
    8114           0 :       if (offset_len == 8)
    8115           0 :         val = read_8ubyte_unaligned_inc (dbg, readp);
    8116             :       else
    8117           0 :         val = read_4ubyte_unaligned_inc (dbg, readp);
    8118             :       printf ("[%" PRIx64 "]", val);
    8119             :       break;
    8120             : 
    8121           0 :     case DW_FORM_strx:
    8122             :     case DW_FORM_GNU_str_index:
    8123           0 :       if (readendp - readp < 1)
    8124             :         goto invalid_data;
    8125           0 :       get_uleb128 (val, readp, readendp);
    8126           0 :     strx_val:
    8127           0 :       data = dbg->sectiondata[IDX_debug_str_offsets];
    8128           0 :       if (data == NULL
    8129           0 :           || data->d_size - str_offsets_base < val)
    8130             :         str = "???";
    8131             :       else
    8132             :         {
    8133           0 :           const unsigned char *strreadp = data->d_buf + str_offsets_base + val;
    8134           0 :           const unsigned char *strreadendp = data->d_buf + data->d_size;
    8135           0 :           if ((size_t) (strreadendp - strreadp) < offset_len)
    8136             :             str = "???";
    8137             :           else
    8138             :             {
    8139             :               Dwarf_Off idx;
    8140           0 :               if (offset_len == 8)
    8141           0 :                 idx = read_8ubyte_unaligned (dbg, strreadp);
    8142             :               else
    8143           0 :                 idx = read_4ubyte_unaligned (dbg, strreadp);
    8144             : 
    8145           0 :               data = dbg->sectiondata[IDX_debug_str];
    8146           0 :               if (data == NULL || idx >= data->d_size
    8147           0 :                   || memchr (data->d_buf + idx, '\0',
    8148             :                              data->d_size - idx) == NULL)
    8149             :                 str = "???";
    8150             :               else
    8151           0 :                 str = (char *) data->d_buf + idx;
    8152             :             }
    8153             :         }
    8154             :       printf ("%s (%" PRIu64 ")", str, val);
    8155             :       break;
    8156             : 
    8157           0 :     case DW_FORM_strx1:
    8158           0 :       if (readendp - readp < 1)
    8159             :         goto invalid_data;
    8160           0 :       val = *readp++;
    8161           0 :       goto strx_val;
    8162             : 
    8163           0 :     case DW_FORM_strx2:
    8164           0 :       if (readendp - readp < 2)
    8165             :         goto invalid_data;
    8166           0 :       val = read_2ubyte_unaligned_inc (dbg, readp);
    8167           0 :       goto strx_val;
    8168             : 
    8169           0 :     case DW_FORM_strx3:
    8170           0 :       if (readendp - readp < 3)
    8171             :         goto invalid_data;
    8172           0 :       val = read_3ubyte_unaligned_inc (dbg, readp);
    8173           0 :       goto strx_val;
    8174             : 
    8175           0 :     case DW_FORM_strx4:
    8176           0 :       if (readendp - readp < 4)
    8177             :         goto invalid_data;
    8178           0 :       val = read_4ubyte_unaligned_inc (dbg, readp);
    8179           0 :       goto strx_val;
    8180             : 
    8181           0 :     default:
    8182           0 :       error (0, 0, gettext ("unknown form: %s"), dwarf_form_name (form));
    8183           0 :       return readendp;
    8184             :     }
    8185             : 
    8186          20 :   return readp;
    8187             : }
    8188             : 
    8189             : static void
    8190          50 : print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
    8191             :                           Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    8192             : {
    8193          50 :   if (decodedline)
    8194             :     {
    8195           4 :       print_decoded_line_section (dwflmod, ebl, ehdr, scn, shdr, dbg);
    8196           4 :       return;
    8197             :     }
    8198             : 
    8199          92 :   printf (gettext ("\
    8200             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    8201             :           elf_ndxscn (scn), section_name (ebl, shdr),
    8202          46 :           (uint64_t) shdr->sh_offset);
    8203             : 
    8204          46 :   if (shdr->sh_size == 0)
    8205             :     return;
    8206             : 
    8207             :   /* There is no functionality in libdw to read the information in the
    8208             :      way it is represented here.  Hardcode the decoder.  */
    8209          92 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_line]
    8210          46 :                     ?: elf_rawdata (scn, NULL));
    8211          46 :   if (unlikely (data == NULL))
    8212             :     {
    8213           0 :       error (0, 0, gettext ("cannot get line data section data: %s"),
    8214             :              elf_errmsg (-1));
    8215             :       return;
    8216             :     }
    8217             : 
    8218          46 :   const unsigned char *linep = (const unsigned char *) data->d_buf;
    8219             :   const unsigned char *lineendp;
    8220             : 
    8221        1189 :   while (linep
    8222        1143 :          < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
    8223             :     {
    8224        1097 :       size_t start_offset = linep - (const unsigned char *) data->d_buf;
    8225             : 
    8226        2194 :       printf (gettext ("\nTable at offset %zu:\n"), start_offset);
    8227             : 
    8228        1097 :       if (unlikely (linep + 4 > lineendp))
    8229             :         goto invalid_data;
    8230        1122 :       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
    8231        1097 :       unsigned int length = 4;
    8232        1097 :       if (unlikely (unit_length == 0xffffffff))
    8233             :         {
    8234           0 :           if (unlikely (linep + 8 > lineendp))
    8235             :             {
    8236           0 :             invalid_data:
    8237           0 :               error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
    8238             :                      elf_ndxscn (scn), section_name (ebl, shdr));
    8239             :               return;
    8240             :             }
    8241           0 :           unit_length = read_8ubyte_unaligned_inc (dbg, linep);
    8242           0 :           length = 8;
    8243             :         }
    8244             : 
    8245             :       /* Check whether we have enough room in the section.  */
    8246        1097 :       if (unlikely (unit_length > (size_t) (lineendp - linep)))
    8247             :         goto invalid_data;
    8248        1097 :       lineendp = linep + unit_length;
    8249             : 
    8250             :       /* The next element of the header is the version identifier.  */
    8251        1097 :       if ((size_t) (lineendp - linep) < 2)
    8252             :         goto invalid_data;
    8253        1122 :       uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
    8254             : 
    8255        1097 :       size_t address_size
    8256        1097 :         = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    8257        1097 :       unsigned char segment_selector_size = 0;
    8258        1097 :       if (version > 4)
    8259             :         {
    8260           2 :           if ((size_t) (lineendp - linep) < 2)
    8261             :             goto invalid_data;
    8262           2 :           address_size = *linep++;
    8263           2 :           segment_selector_size = *linep++;
    8264             :         }
    8265             : 
    8266             :       /* Next comes the header length.  */
    8267             :       Dwarf_Word header_length;
    8268        1097 :       if (length == 4)
    8269             :         {
    8270        1097 :           if ((size_t) (lineendp - linep) < 4)
    8271             :             goto invalid_data;
    8272        1122 :           header_length = read_4ubyte_unaligned_inc (dbg, linep);
    8273             :         }
    8274             :       else
    8275             :         {
    8276           0 :           if ((size_t) (lineendp - linep) < 8)
    8277             :             goto invalid_data;
    8278           0 :           header_length = read_8ubyte_unaligned_inc (dbg, linep);
    8279             :         }
    8280             : 
    8281             :       /* Next the minimum instruction length.  */
    8282        1097 :       if ((size_t) (lineendp - linep) < 1)
    8283             :         goto invalid_data;
    8284        1097 :       uint_fast8_t minimum_instr_len = *linep++;
    8285             : 
    8286             :       /* Next the maximum operations per instruction, in version 4 format.  */
    8287             :       uint_fast8_t max_ops_per_instr;
    8288        1097 :       if (version < 4)
    8289             :         max_ops_per_instr = 1;
    8290             :       else
    8291             :         {
    8292          10 :           if ((size_t) (lineendp - linep) < 1)
    8293             :             goto invalid_data;
    8294          10 :           max_ops_per_instr = *linep++;
    8295             :         }
    8296             : 
    8297             :       /* We need at least 4 more bytes.  */
    8298        1097 :       if ((size_t) (lineendp - linep) < 4)
    8299             :         goto invalid_data;
    8300             : 
    8301             :       /* Then the flag determining the default value of the is_stmt
    8302             :          register.  */
    8303        1097 :       uint_fast8_t default_is_stmt = *linep++;
    8304             : 
    8305             :       /* Now the line base.  */
    8306        1097 :       int_fast8_t line_base = *linep++;
    8307             : 
    8308             :       /* And the line range.  */
    8309        1097 :       uint_fast8_t line_range = *linep++;
    8310             : 
    8311             :       /* The opcode base.  */
    8312        1097 :       uint_fast8_t opcode_base = *linep++;
    8313             : 
    8314             :       /* Print what we got so far.  */
    8315        2194 :       printf (gettext ("\n"
    8316             :                        " Length:                         %" PRIu64 "\n"
    8317             :                        " DWARF version:                  %" PRIuFAST16 "\n"
    8318             :                        " Prologue length:                %" PRIu64 "\n"
    8319             :                        " Address size:                   %zd\n"
    8320             :                        " Segment selector size:          %zd\n"
    8321             :                        " Min instruction length:         %" PRIuFAST8 "\n"
    8322             :                        " Max operations per instruction: %" PRIuFAST8 "\n"
    8323             :                        " Initial value if 'is_stmt':     %" PRIuFAST8 "\n"
    8324             :                        " Line base:                      %" PRIdFAST8 "\n"
    8325             :                        " Line range:                     %" PRIuFAST8 "\n"
    8326             :                        " Opcode base:                    %" PRIuFAST8 "\n"
    8327             :                        "\n"
    8328             :                        "Opcodes:\n"),
    8329             :               (uint64_t) unit_length, version, (uint64_t) header_length,
    8330             :               address_size, (size_t) segment_selector_size,
    8331             :               minimum_instr_len, max_ops_per_instr,
    8332             :               default_is_stmt, line_base,
    8333             :               line_range, opcode_base);
    8334             : 
    8335        1097 :       if (version < 2 || version > 5)
    8336             :         {
    8337           0 :           error (0, 0, gettext ("cannot handle .debug_line version: %u\n"),
    8338             :                  (unsigned int) version);
    8339           0 :           linep = lineendp;
    8340           0 :           continue;
    8341             :         }
    8342             : 
    8343        1097 :       if (address_size != 4 && address_size != 8)
    8344             :         {
    8345           0 :           error (0, 0, gettext ("cannot handle address size: %u\n"),
    8346             :                  (unsigned int) address_size);
    8347           0 :           linep = lineendp;
    8348           0 :           continue;
    8349             :         }
    8350             : 
    8351        1097 :       if (segment_selector_size != 0)
    8352             :         {
    8353           0 :           error (0, 0, gettext ("cannot handle segment selector size: %u\n"),
    8354             :                  (unsigned int) segment_selector_size);
    8355           0 :           linep = lineendp;
    8356           0 :           continue;
    8357             :         }
    8358             : 
    8359        1097 :       if (unlikely (linep + opcode_base - 1 >= lineendp))
    8360             :         {
    8361           0 :         invalid_unit:
    8362           0 :           error (0, 0,
    8363           0 :                  gettext ("invalid data at offset %tu in section [%zu] '%s'"),
    8364           0 :                  linep - (const unsigned char *) data->d_buf,
    8365             :                  elf_ndxscn (scn), section_name (ebl, shdr));
    8366           0 :           linep = lineendp;
    8367           0 :           continue;
    8368             :         }
    8369        1097 :       int opcode_base_l10 = 1;
    8370        1097 :       unsigned int tmp = opcode_base;
    8371        3289 :       while (tmp > 10)
    8372             :         {
    8373        1095 :           tmp /= 10;
    8374        1095 :           ++opcode_base_l10;
    8375             :         }
    8376        1097 :       const uint8_t *standard_opcode_lengths = linep - 1;
    8377       14255 :       for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
    8378       26316 :         printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
    8379             :                           "  [%*" PRIuFAST8 "]  %hhu arguments\n",
    8380             :                           (int) linep[cnt - 1]),
    8381       13158 :                 opcode_base_l10, cnt, linep[cnt - 1]);
    8382        1097 :       linep += opcode_base - 1;
    8383             : 
    8384        1097 :       if (unlikely (linep >= lineendp))
    8385             :         goto invalid_unit;
    8386             : 
    8387        1097 :       Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, NULL);
    8388             : 
    8389        1097 :       puts (gettext ("\nDirectory table:"));
    8390        1097 :       if (version > 4)
    8391             :         {
    8392             :           struct encpair { uint16_t desc; uint16_t form; };
    8393             :           struct encpair enc[256];
    8394             : 
    8395           4 :           printf (gettext ("      ["));
    8396           2 :           if ((size_t) (lineendp - linep) < 1)
    8397             :             goto invalid_data;
    8398           2 :           unsigned char directory_entry_format_count = *linep++;
    8399           6 :           for (int i = 0; i < directory_entry_format_count; i++)
    8400             :             {
    8401             :               uint16_t desc, form;
    8402           2 :               if ((size_t) (lineendp - linep) < 1)
    8403             :                 goto invalid_data;
    8404           2 :               get_uleb128 (desc, linep, lineendp);
    8405           2 :               if ((size_t) (lineendp - linep) < 1)
    8406             :                 goto invalid_data;
    8407           2 :               get_uleb128 (form, linep, lineendp);
    8408             : 
    8409             :               enc[i].desc = desc;
    8410           2 :               enc[i].form = form;
    8411             : 
    8412           4 :               printf ("%s(%s)",
    8413             :                       dwarf_line_content_description_name (desc),
    8414             :                       dwarf_form_name (form));
    8415           2 :               if (i + 1 < directory_entry_format_count)
    8416             :                 printf (", ");
    8417             :             }
    8418           2 :           printf ("]\n");
    8419             : 
    8420             :           uint64_t directories_count;
    8421           2 :           if ((size_t) (lineendp - linep) < 1)
    8422             :             goto invalid_data;
    8423           2 :           get_uleb128 (directories_count, linep, lineendp);
    8424             : 
    8425           4 :           if (directory_entry_format_count == 0
    8426           2 :               && directories_count != 0)
    8427             :             goto invalid_data;
    8428             : 
    8429           4 :           for (uint64_t i = 0; i < directories_count; i++)
    8430             :             {
    8431           4 :               printf (" %-5" PRIu64 " ", i);
    8432          12 :               for (int j = 0; j < directory_entry_format_count; j++)
    8433             :                 {
    8434           4 :                   linep = print_form_data (dbg, enc[j].form,
    8435             :                                            linep, lineendp, length,
    8436             :                                            str_offsets_base);
    8437           4 :                   if (j + 1 < directory_entry_format_count)
    8438             :                     printf (", ");
    8439             :                 }
    8440           4 :               printf ("\n");
    8441           4 :               if (linep >= lineendp)
    8442             :                 goto invalid_unit;
    8443             :             }
    8444             :         }
    8445             :       else
    8446             :         {
    8447        8355 :           while (linep < lineendp && *linep != 0)
    8448             :             {
    8449        7260 :               unsigned char *endp = memchr (linep, '\0', lineendp - linep);
    8450        7260 :               if (unlikely (endp == NULL))
    8451             :                 goto invalid_unit;
    8452             : 
    8453       14520 :               printf (" %s\n", (char *) linep);
    8454             : 
    8455        7260 :               linep = endp + 1;
    8456             :             }
    8457        2190 :           if (linep >= lineendp || *linep != 0)
    8458             :             goto invalid_unit;
    8459             :           /* Skip the final NUL byte.  */
    8460        1095 :           ++linep;
    8461             :         }
    8462             : 
    8463        1097 :       if (unlikely (linep >= lineendp))
    8464             :         goto invalid_unit;
    8465             : 
    8466        1097 :       puts (gettext ("\nFile name table:"));
    8467        1097 :       if (version > 4)
    8468             :         {
    8469             :           struct encpair { uint16_t desc; uint16_t form; };
    8470             :           struct encpair enc[256];
    8471             : 
    8472           4 :           printf (gettext ("      ["));
    8473           2 :           if ((size_t) (lineendp - linep) < 1)
    8474             :             goto invalid_data;
    8475           2 :           unsigned char file_name_format_count = *linep++;
    8476           8 :           for (int i = 0; i < file_name_format_count; i++)
    8477             :             {
    8478             :               uint64_t desc, form;
    8479           4 :               if ((size_t) (lineendp - linep) < 1)
    8480             :                 goto invalid_data;
    8481           4 :               get_uleb128 (desc, linep, lineendp);
    8482           4 :               if ((size_t) (lineendp - linep) < 1)
    8483             :                 goto invalid_data;
    8484           4 :               get_uleb128 (form, linep, lineendp);
    8485             : 
    8486           4 :               if (! libdw_valid_user_form (form))
    8487             :                 goto invalid_data;
    8488             : 
    8489             :               enc[i].desc = desc;
    8490           4 :               enc[i].form = form;
    8491             : 
    8492           8 :               printf ("%s(%s)",
    8493             :                       dwarf_line_content_description_name (desc),
    8494             :                       dwarf_form_name (form));
    8495           4 :               if (i + 1 < file_name_format_count)
    8496             :                 printf (", ");
    8497             :             }
    8498           2 :           printf ("]\n");
    8499             : 
    8500             :           uint64_t file_name_count;
    8501           2 :           if ((size_t) (lineendp - linep) < 1)
    8502             :             goto invalid_data;
    8503           2 :           get_uleb128 (file_name_count, linep, lineendp);
    8504             : 
    8505           4 :           if (file_name_format_count == 0
    8506           2 :               && file_name_count != 0)
    8507             :             goto invalid_data;
    8508             : 
    8509           8 :           for (uint64_t i = 0; i < file_name_count; i++)
    8510             :             {
    8511           8 :               printf (" %-5" PRIu64 " ", i);
    8512          32 :               for (int j = 0; j < file_name_format_count; j++)
    8513             :                 {
    8514          16 :                   linep = print_form_data (dbg, enc[j].form,
    8515             :                                            linep, lineendp, length,
    8516             :                                            str_offsets_base);
    8517          16 :                   if (j + 1 < file_name_format_count)
    8518             :                     printf (", ");
    8519             :                 }
    8520           8 :               printf ("\n");
    8521           8 :               if (linep >= lineendp)
    8522             :                 goto invalid_unit;
    8523             :             }
    8524             :         }
    8525             :       else
    8526             :         {
    8527        1095 :           puts (gettext (" Entry Dir   Time      Size      Name"));
    8528       22867 :           for (unsigned int cnt = 1; linep < lineendp && *linep != 0; ++cnt)
    8529             :             {
    8530             :               /* First comes the file name.  */
    8531       21772 :               char *fname = (char *) linep;
    8532       21772 :               unsigned char *endp = memchr (fname, '\0', lineendp - linep);
    8533       21772 :               if (unlikely (endp == NULL))
    8534             :                 goto invalid_unit;
    8535       21772 :               linep = endp + 1;
    8536             : 
    8537             :               /* Then the index.  */
    8538             :               unsigned int diridx;
    8539       21772 :               if (lineendp - linep < 1)
    8540             :                 goto invalid_unit;
    8541       21772 :               get_uleb128 (diridx, linep, lineendp);
    8542             : 
    8543             :               /* Next comes the modification time.  */
    8544             :               unsigned int mtime;
    8545       21772 :               if (lineendp - linep < 1)
    8546             :                 goto invalid_unit;
    8547       21772 :               get_uleb128 (mtime, linep, lineendp);
    8548             : 
    8549             :               /* Finally the length of the file.  */
    8550             :               unsigned int fsize;
    8551       21772 :               if (lineendp - linep < 1)
    8552             :                 goto invalid_unit;
    8553       21772 :               get_uleb128 (fsize, linep, lineendp);
    8554             : 
    8555       21772 :               printf (" %-5u %-5u %-9u %-9u %s\n",
    8556             :                       cnt, diridx, mtime, fsize, fname);
    8557             :             }
    8558        2190 :           if (linep >= lineendp || *linep != '\0')
    8559             :             goto invalid_unit;
    8560             :           /* Skip the final NUL byte.  */
    8561        1095 :           ++linep;
    8562             :         }
    8563             : 
    8564        1097 :       puts (gettext ("\nLine number statements:"));
    8565             :       Dwarf_Word address = 0;
    8566             :       unsigned int op_index = 0;
    8567        1097 :       size_t line = 1;
    8568        1097 :       uint_fast8_t is_stmt = default_is_stmt;
    8569             : 
    8570             :       /* Apply the "operation advance" from a special opcode
    8571             :          or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
    8572             :       unsigned int op_addr_advance;
    8573             :       bool show_op_index;
    8574             :       inline void advance_pc (unsigned int op_advance)
    8575             :       {
    8576      301644 :         op_addr_advance = minimum_instr_len * ((op_index + op_advance)
    8577      150822 :                                                / max_ops_per_instr);
    8578      150822 :         address += op_addr_advance;
    8579      301644 :         show_op_index = (op_index > 0 ||
    8580      150822 :                          (op_index + op_advance) % max_ops_per_instr > 0);
    8581      150822 :         op_index = (op_index + op_advance) % max_ops_per_instr;
    8582             :       }
    8583             : 
    8584        1097 :       if (max_ops_per_instr == 0)
    8585             :         {
    8586           0 :           error (0, 0,
    8587           0 :                  gettext ("invalid maximum operations per instruction is zero"));
    8588           0 :           linep = lineendp;
    8589           0 :           continue;
    8590             :         }
    8591             : 
    8592      246103 :       while (linep < lineendp)
    8593             :         {
    8594      245006 :           size_t offset = linep - (const unsigned char *) data->d_buf;
    8595             :           unsigned int u128;
    8596             :           int s128;
    8597             : 
    8598             :           /* Read the opcode.  */
    8599      245006 :           unsigned int opcode = *linep++;
    8600             : 
    8601      245006 :           printf (" [%6" PRIx64 "]", (uint64_t)offset);
    8602             :           /* Is this a special opcode?  */
    8603      245006 :           if (likely (opcode >= opcode_base))
    8604             :             {
    8605      112220 :               if (unlikely (line_range == 0))
    8606             :                 goto invalid_unit;
    8607             : 
    8608             :               /* Yes.  Handling this is quite easy since the opcode value
    8609             :                  is computed with
    8610             : 
    8611             :                  opcode = (desired line increment - line_base)
    8612             :                            + (line_range * address advance) + opcode_base
    8613             :               */
    8614      112220 :               int line_increment = (line_base
    8615      112220 :                                     + (opcode - opcode_base) % line_range);
    8616             : 
    8617             :               /* Perform the increments.  */
    8618      112220 :               line += line_increment;
    8619      224440 :               advance_pc ((opcode - opcode_base) / line_range);
    8620             : 
    8621      224440 :               printf (gettext (" special opcode %u: address+%u = "),
    8622             :                       opcode, op_addr_advance);
    8623      112220 :               print_dwarf_addr (dwflmod, 0, address, address);
    8624      112220 :               if (show_op_index)
    8625           0 :                 printf (gettext (", op_index = %u, line%+d = %zu\n"),
    8626             :                         op_index, line_increment, line);
    8627             :               else
    8628      112220 :                 printf (gettext (", line%+d = %zu\n"),
    8629             :                         line_increment, line);
    8630             :             }
    8631      132786 :           else if (opcode == 0)
    8632             :             {
    8633             :               /* This an extended opcode.  */
    8634       13274 :               if (unlikely (linep + 2 > lineendp))
    8635             :                 goto invalid_unit;
    8636             : 
    8637             :               /* The length.  */
    8638       13274 :               unsigned int len = *linep++;
    8639             : 
    8640       13274 :               if (unlikely (linep + len > lineendp))
    8641             :                 goto invalid_unit;
    8642             : 
    8643             :               /* The sub-opcode.  */
    8644       13274 :               opcode = *linep++;
    8645             : 
    8646       26548 :               printf (gettext (" extended opcode %u: "), opcode);
    8647             : 
    8648       13274 :               switch (opcode)
    8649             :                 {
    8650        1126 :                 case DW_LNE_end_sequence:
    8651        1126 :                   puts (gettext (" end of sequence"));
    8652             : 
    8653             :                   /* Reset the registers we care about.  */
    8654             :                   address = 0;
    8655             :                   op_index = 0;
    8656        1126 :                   line = 1;
    8657        1126 :                   is_stmt = default_is_stmt;
    8658        1126 :                   break;
    8659             : 
    8660        1254 :                 case DW_LNE_set_address:
    8661             :                   op_index = 0;
    8662        1254 :                   if (unlikely ((size_t) (lineendp - linep) < address_size))
    8663             :                     goto invalid_unit;
    8664        1254 :                   if (address_size == 4)
    8665          17 :                     address = read_4ubyte_unaligned_inc (dbg, linep);
    8666             :                   else
    8667        1256 :                     address = read_8ubyte_unaligned_inc (dbg, linep);
    8668             :                   {
    8669        2508 :                     printf (gettext (" set address to "));
    8670        1254 :                     print_dwarf_addr (dwflmod, 0, address, address);
    8671             :                     printf ("\n");
    8672             :                   }
    8673             :                   break;
    8674             : 
    8675           0 :                 case DW_LNE_define_file:
    8676             :                   {
    8677           0 :                     char *fname = (char *) linep;
    8678           0 :                     unsigned char *endp = memchr (linep, '\0',
    8679           0 :                                                   lineendp - linep);
    8680           0 :                     if (unlikely (endp == NULL))
    8681             :                       goto invalid_unit;
    8682           0 :                     linep = endp + 1;
    8683             : 
    8684             :                     unsigned int diridx;
    8685           0 :                     if (lineendp - linep < 1)
    8686             :                       goto invalid_unit;
    8687           0 :                     get_uleb128 (diridx, linep, lineendp);
    8688             :                     Dwarf_Word mtime;
    8689           0 :                     if (lineendp - linep < 1)
    8690             :                       goto invalid_unit;
    8691           0 :                     get_uleb128 (mtime, linep, lineendp);
    8692             :                     Dwarf_Word filelength;
    8693           0 :                     if (lineendp - linep < 1)
    8694             :                       goto invalid_unit;
    8695           0 :                     get_uleb128 (filelength, linep, lineendp);
    8696             : 
    8697           0 :                     printf (gettext ("\
    8698             :  define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
    8699             :                             diridx, (uint64_t) mtime, (uint64_t) filelength,
    8700             :                             fname);
    8701             :                   }
    8702             :                   break;
    8703             : 
    8704       10894 :                 case DW_LNE_set_discriminator:
    8705             :                   /* Takes one ULEB128 parameter, the discriminator.  */
    8706       21788 :                   if (unlikely (standard_opcode_lengths[opcode] != 1
    8707             :                                 || lineendp - linep < 1))
    8708             :                     goto invalid_unit;
    8709             : 
    8710       10894 :                   get_uleb128 (u128, linep, lineendp);
    8711       10894 :                   printf (gettext (" set discriminator to %u\n"), u128);
    8712             :                   break;
    8713             : 
    8714           0 :                 default:
    8715             :                   /* Unknown, ignore it.  */
    8716           0 :                   puts (gettext (" unknown opcode"));
    8717           0 :                   linep += len - 1;
    8718           0 :                   break;
    8719             :                 }
    8720             :             }
    8721      119512 :           else if (opcode <= DW_LNS_set_isa)
    8722             :             {
    8723             :               /* This is a known standard opcode.  */
    8724      119512 :               switch (opcode)
    8725             :                 {
    8726        8383 :                 case DW_LNS_copy:
    8727             :                   /* Takes no argument.  */
    8728        8383 :                   puts (gettext (" copy"));
    8729        8383 :                   break;
    8730             : 
    8731       12109 :                 case DW_LNS_advance_pc:
    8732             :                   /* Takes one uleb128 parameter which is added to the
    8733             :                      address.  */
    8734       12109 :                   if (lineendp - linep < 1)
    8735             :                     goto invalid_unit;
    8736       12109 :                   get_uleb128 (u128, linep, lineendp);
    8737       12109 :                   advance_pc (u128);
    8738             :                   {
    8739       24218 :                     printf (gettext (" advance address by %u to "),
    8740             :                             op_addr_advance);
    8741       12109 :                     print_dwarf_addr (dwflmod, 0, address, address);
    8742       12109 :                     if (show_op_index)
    8743           0 :                       printf (gettext (", op_index to %u"), op_index);
    8744             :                     printf ("\n");
    8745             :                   }
    8746             :                   break;
    8747             : 
    8748       48704 :                 case DW_LNS_advance_line:
    8749             :                   /* Takes one sleb128 parameter which is added to the
    8750             :                      line.  */
    8751       48704 :                   if (lineendp - linep < 1)
    8752             :                     goto invalid_unit;
    8753       48704 :                   get_sleb128 (s128, linep, lineendp);
    8754       48704 :                   line += s128;
    8755       48704 :                   printf (gettext ("\
    8756             :  advance line by constant %d to %" PRId64 "\n"),
    8757             :                           s128, (int64_t) line);
    8758             :                   break;
    8759             : 
    8760       19159 :                 case DW_LNS_set_file:
    8761             :                   /* Takes one uleb128 parameter which is stored in file.  */
    8762       19159 :                   if (lineendp - linep < 1)
    8763             :                     goto invalid_unit;
    8764       19159 :                   get_uleb128 (u128, linep, lineendp);
    8765       19159 :                   printf (gettext (" set file to %" PRIu64 "\n"),
    8766             :                           (uint64_t) u128);
    8767             :                   break;
    8768             : 
    8769         131 :                 case DW_LNS_set_column:
    8770             :                   /* Takes one uleb128 parameter which is stored in column.  */
    8771         262 :                   if (unlikely (standard_opcode_lengths[opcode] != 1
    8772             :                                 || lineendp - linep < 1))
    8773             :                     goto invalid_unit;
    8774             : 
    8775         131 :                   get_uleb128 (u128, linep, lineendp);
    8776         131 :                   printf (gettext (" set column to %" PRIu64 "\n"),
    8777             :                           (uint64_t) u128);
    8778             :                   break;
    8779             : 
    8780        4510 :                 case DW_LNS_negate_stmt:
    8781             :                   /* Takes no argument.  */
    8782        4510 :                   is_stmt = 1 - is_stmt;
    8783        4510 :                   printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
    8784             :                           "is_stmt", is_stmt);
    8785             :                   break;
    8786             : 
    8787           0 :                 case DW_LNS_set_basic_block:
    8788             :                   /* Takes no argument.  */
    8789           0 :                   puts (gettext (" set basic block flag"));
    8790           0 :                   break;
    8791             : 
    8792       26493 :                 case DW_LNS_const_add_pc:
    8793             :                   /* Takes no argument.  */
    8794             : 
    8795       26493 :                   if (unlikely (line_range == 0))
    8796             :                     goto invalid_unit;
    8797             : 
    8798       52986 :                   advance_pc ((255 - opcode_base) / line_range);
    8799             :                   {
    8800       52986 :                     printf (gettext (" advance address by constant %u to "),
    8801             :                             op_addr_advance);
    8802       26493 :                     print_dwarf_addr (dwflmod, 0, address, address);
    8803       26493 :                     if (show_op_index)
    8804           0 :                       printf (gettext (", op_index to %u"), op_index);
    8805             :                     printf ("\n");
    8806             :                   }
    8807             :                   break;
    8808             : 
    8809          22 :                 case DW_LNS_fixed_advance_pc:
    8810             :                   /* Takes one 16 bit parameter which is added to the
    8811             :                      address.  */
    8812          44 :                   if (unlikely (standard_opcode_lengths[opcode] != 1
    8813             :                                 || lineendp - linep < 2))
    8814             :                     goto invalid_unit;
    8815             : 
    8816          22 :                   u128 = read_2ubyte_unaligned_inc (dbg, linep);
    8817          22 :                   address += u128;
    8818             :                   op_index = 0;
    8819             :                   {
    8820          44 :                     printf (gettext ("\
    8821             :  advance address by fixed value %u to \n"),
    8822             :                             u128);
    8823          22 :                     print_dwarf_addr (dwflmod, 0, address, address);
    8824             :                     printf ("\n");
    8825             :                   }
    8826             :                   break;
    8827             : 
    8828           1 :                 case DW_LNS_set_prologue_end:
    8829             :                   /* Takes no argument.  */
    8830           1 :                   puts (gettext (" set prologue end flag"));
    8831           1 :                   break;
    8832             : 
    8833           0 :                 case DW_LNS_set_epilogue_begin:
    8834             :                   /* Takes no argument.  */
    8835           0 :                   puts (gettext (" set epilogue begin flag"));
    8836           0 :                   break;
    8837             : 
    8838           0 :                 case DW_LNS_set_isa:
    8839             :                   /* Takes one uleb128 parameter which is stored in isa.  */
    8840           0 :                   if (unlikely (standard_opcode_lengths[opcode] != 1
    8841             :                                 || lineendp - linep < 1))
    8842             :                     goto invalid_unit;
    8843             : 
    8844           0 :                   get_uleb128 (u128, linep, lineendp);
    8845           0 :                   printf (gettext (" set isa to %u\n"), u128);
    8846             :                   break;
    8847             :                 }
    8848             :             }
    8849             :           else
    8850             :             {
    8851             :               /* This is a new opcode the generator but not we know about.
    8852             :                  Read the parameters associated with it but then discard
    8853             :                  everything.  Read all the parameters for this opcode.  */
    8854           0 :               printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
    8855             :                                 " unknown opcode with %" PRIu8 " parameters:",
    8856             :                                 standard_opcode_lengths[opcode]),
    8857           0 :                       standard_opcode_lengths[opcode]);
    8858           0 :               for (int n = standard_opcode_lengths[opcode];
    8859           0 :                    n > 0 && linep < lineendp; --n)
    8860             :                 {
    8861           0 :                   get_uleb128 (u128, linep, lineendp);
    8862           0 :                   if (n != standard_opcode_lengths[opcode])
    8863           0 :                     putc_unlocked (',', stdout);
    8864           0 :                   printf (" %u", u128);
    8865             :                 }
    8866             : 
    8867             :               /* Next round, ignore this opcode.  */
    8868           0 :               continue;
    8869             :             }
    8870             :         }
    8871             :     }
    8872             : 
    8873             :   /* There must only be one data block.  */
    8874          46 :   assert (elf_getdata (scn, data) == NULL);
    8875             : }
    8876             : 
    8877             : 
    8878             : static void
    8879           3 : print_debug_loclists_section (Dwfl_Module *dwflmod,
    8880             :                               Ebl *ebl,
    8881             :                               GElf_Ehdr *ehdr __attribute__ ((unused)),
    8882             :                               Elf_Scn *scn, GElf_Shdr *shdr,
    8883             :                               Dwarf *dbg)
    8884             : {
    8885           6 :   printf (gettext ("\
    8886             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    8887             :           elf_ndxscn (scn), section_name (ebl, shdr),
    8888           3 :           (uint64_t) shdr->sh_offset);
    8889             : 
    8890           6 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_loclists]
    8891           3 :                     ?: elf_rawdata (scn, NULL));
    8892           3 :   if (unlikely (data == NULL))
    8893             :     {
    8894           0 :       error (0, 0, gettext ("cannot get .debug_loclists content: %s"),
    8895             :              elf_errmsg (-1));
    8896           0 :       return;
    8897             :     }
    8898             : 
    8899             :   /* For the listptr to get the base address/CU.  */
    8900           6 :   sort_listptr (&known_loclistsptr, "loclistsptr");
    8901           3 :   size_t listptr_idx = 0;
    8902             : 
    8903           3 :   const unsigned char *readp = data->d_buf;
    8904           3 :   const unsigned char *const dataend = ((unsigned char *) data->d_buf
    8905           3 :                                         + data->d_size);
    8906          10 :   while (readp < dataend)
    8907             :     {
    8908           4 :       if (unlikely (readp > dataend - 4))
    8909             :         {
    8910           0 :         invalid_data:
    8911           0 :           error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
    8912             :                  elf_ndxscn (scn), section_name (ebl, shdr));
    8913           0 :           return;
    8914             :         }
    8915             : 
    8916           4 :       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
    8917           8 :       printf (gettext ("Table at Offset 0x%" PRIx64 ":\n\n"),
    8918             :               (uint64_t) offset);
    8919             : 
    8920           4 :       uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
    8921           4 :       unsigned int offset_size = 4;
    8922           4 :       if (unlikely (unit_length == 0xffffffff))
    8923             :         {
    8924           0 :           if (unlikely (readp > dataend - 8))
    8925             :             goto invalid_data;
    8926             : 
    8927           0 :           unit_length = read_8ubyte_unaligned_inc (dbg, readp);
    8928           0 :           offset_size = 8;
    8929             :         }
    8930           8 :       printf (gettext (" Length:         %8" PRIu64 "\n"), unit_length);
    8931             : 
    8932             :       /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
    8933             :          bytes to complete the header.  And this unit cannot go beyond
    8934             :          the section data.  */
    8935           4 :       if (readp > dataend - 8
    8936           4 :           || unit_length < 8
    8937           4 :           || unit_length > (uint64_t) (dataend - readp))
    8938             :         goto invalid_data;
    8939             : 
    8940           4 :       const unsigned char *nexthdr = readp + unit_length;
    8941             : 
    8942           4 :       uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
    8943           8 :       printf (gettext (" DWARF version:  %8" PRIu16 "\n"), version);
    8944             : 
    8945           4 :       if (version != 5)
    8946             :         {
    8947           0 :           error (0, 0, gettext ("Unknown version"));
    8948             :           goto next_table;
    8949             :         }
    8950             : 
    8951           4 :       uint8_t address_size = *readp++;
    8952           8 :       printf (gettext (" Address size:   %8" PRIu64 "\n"),
    8953             :               (uint64_t) address_size);
    8954             : 
    8955           4 :       if (address_size != 4 && address_size != 8)
    8956             :         {
    8957           0 :           error (0, 0, gettext ("unsupported address size"));
    8958             :           goto next_table;
    8959             :         }
    8960             : 
    8961           4 :       uint8_t segment_size = *readp++;
    8962           8 :       printf (gettext (" Segment size:   %8" PRIu64 "\n"),
    8963             :               (uint64_t) segment_size);
    8964             : 
    8965           4 :       if (segment_size != 0)
    8966             :         {
    8967           0 :           error (0, 0, gettext ("unsupported segment size"));
    8968             :           goto next_table;
    8969             :         }
    8970             : 
    8971           4 :       uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
    8972           8 :       printf (gettext (" Offset entries: %8" PRIu64 "\n"),
    8973             :               (uint64_t) offset_entry_count);
    8974             : 
    8975             :       /* We need the CU that uses this unit to get the initial base address. */
    8976           4 :       Dwarf_Addr cu_base = 0;
    8977           4 :       struct Dwarf_CU *cu = NULL;
    8978           4 :       if (listptr_cu (&known_loclistsptr, &listptr_idx,
    8979             :                       (Dwarf_Off) offset,
    8980           4 :                       (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
    8981             :                       &cu_base, &cu)
    8982           0 :           || split_dwarf_cu_base (dbg, &cu, &cu_base))
    8983           4 :         {
    8984             :           Dwarf_Die cudie;
    8985           4 :           if (dwarf_cu_die (cu, &cudie,
    8986             :                             NULL, NULL, NULL, NULL,
    8987             :                             NULL, NULL) == NULL)
    8988           0 :             printf (gettext (" Unknown CU base: "));
    8989             :           else
    8990           4 :             printf (gettext (" CU [%6" PRIx64 "] base: "),
    8991             :                     dwarf_dieoffset (&cudie));
    8992           4 :           print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
    8993           4 :           printf ("\n");
    8994             :         }
    8995             :       else
    8996           0 :         printf (gettext (" Not associated with a CU.\n"));
    8997             : 
    8998           4 :       printf ("\n");
    8999             : 
    9000           4 :       const unsigned char *offset_array_start = readp;
    9001           4 :       if (offset_entry_count > 0)
    9002             :         {
    9003           2 :           uint64_t max_entries = (unit_length - 8) / offset_size;
    9004           2 :           if (offset_entry_count > max_entries)
    9005             :             {
    9006           0 :               error (0, 0,
    9007           0 :                      gettext ("too many offset entries for unit length"));
    9008           0 :               offset_entry_count = max_entries;
    9009             :             }
    9010             : 
    9011           4 :           printf (gettext ("  Offsets starting at 0x%" PRIx64 ":\n"),
    9012             :                   (uint64_t) (offset_array_start
    9013           2 :                               - (unsigned char *) data->d_buf));
    9014          18 :           for (uint32_t idx = 0; idx < offset_entry_count; idx++)
    9015             :             {
    9016          16 :               printf ("   [%6" PRIu32 "] ", idx);
    9017          16 :               if (offset_size == 4)
    9018             :                 {
    9019          16 :                   uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
    9020             :                   printf ("0x%" PRIx32 "\n", off);
    9021             :                 }
    9022             :               else
    9023             :                 {
    9024           0 :                   uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
    9025             :                   printf ("0x%" PRIx64 "\n", off);
    9026             :                 }
    9027             :             }
    9028             :           printf ("\n");
    9029             :         }
    9030             : 
    9031           4 :       Dwarf_Addr base = cu_base;
    9032           4 :       bool start_of_list = true;
    9033          97 :       while (readp < nexthdr)
    9034             :         {
    9035          89 :           uint8_t kind = *readp++;
    9036             :           uint64_t op1, op2, len;
    9037             : 
    9038             :           /* Skip padding.  */
    9039          89 :           if (start_of_list && kind == DW_LLE_end_of_list)
    9040           0 :             continue;
    9041             : 
    9042          89 :           if (start_of_list)
    9043             :             {
    9044          32 :               base = cu_base;
    9045          96 :               printf ("  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
    9046          32 :                       (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
    9047          32 :                       (uint64_t) (readp - offset_array_start - 1));
    9048          32 :               start_of_list = false;
    9049             :             }
    9050             : 
    9051         178 :           printf ("    %s", dwarf_loc_list_encoding_name (kind));
    9052          89 :           switch (kind)
    9053             :             {
    9054          32 :             case DW_LLE_end_of_list:
    9055          32 :               start_of_list = true;
    9056             :               printf ("\n\n");
    9057             :               break;
    9058             : 
    9059           0 :             case DW_LLE_base_addressx:
    9060           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9061             :                 {
    9062           0 :                 invalid_entry:
    9063           0 :                   error (0, 0, gettext ("invalid loclists data"));
    9064             :                   goto next_table;
    9065             :                 }
    9066           0 :               get_uleb128 (op1, readp, nexthdr);
    9067           0 :               printf (" %" PRIx64 "\n", op1);
    9068           0 :               if (! print_unresolved_addresses)
    9069             :                 {
    9070             :                   Dwarf_Addr addr;
    9071           0 :                   if (get_indexed_addr (cu, op1, &addr) != 0)
    9072             :                     printf ("      ???\n");
    9073             :                   else
    9074             :                     {
    9075           0 :                       printf ("      ");
    9076           0 :                       print_dwarf_addr (dwflmod, address_size, addr, addr);
    9077             :                       printf ("\n");
    9078             :                     }
    9079             :                 }
    9080             :               break;
    9081             : 
    9082           0 :             case DW_LLE_startx_endx:
    9083           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9084             :                 goto invalid_entry;
    9085           0 :               get_uleb128 (op1, readp, nexthdr);
    9086           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9087             :                 goto invalid_entry;
    9088           0 :               get_uleb128 (op2, readp, nexthdr);
    9089           0 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    9090           0 :               if (! print_unresolved_addresses)
    9091             :                 {
    9092             :                   Dwarf_Addr addr1;
    9093             :                   Dwarf_Addr addr2;
    9094           0 :                   if (get_indexed_addr (cu, op1, &addr1) != 0
    9095           0 :                       || get_indexed_addr (cu, op2, &addr2) != 0)
    9096             :                     {
    9097           0 :                       printf ("      ???..\n");
    9098             :                       printf ("      ???\n");
    9099             :                     }
    9100             :                   else
    9101             :                     {
    9102           0 :                       printf ("      ");
    9103           0 :                       print_dwarf_addr (dwflmod, address_size, addr1, addr1);
    9104           0 :                       printf ("..\n      ");
    9105           0 :                       print_dwarf_addr (dwflmod, address_size,
    9106             :                                         addr2 - 1, addr2);
    9107             :                       printf ("\n");
    9108             :                     }
    9109             :                 }
    9110           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9111             :                 goto invalid_entry;
    9112           0 :               get_uleb128 (len, readp, nexthdr);
    9113           0 :               if ((uint64_t) (nexthdr - readp) < len)
    9114             :                 goto invalid_entry;
    9115           0 :               print_ops (dwflmod, dbg, 8, 8, version,
    9116             :                          address_size, offset_size, cu, len, readp);
    9117           0 :               readp += len;
    9118           0 :               break;
    9119             : 
    9120          26 :             case DW_LLE_startx_length:
    9121          26 :               if ((uint64_t) (nexthdr - readp) < 1)
    9122             :                 goto invalid_entry;
    9123          26 :               get_uleb128 (op1, readp, nexthdr);
    9124          26 :               if ((uint64_t) (nexthdr - readp) < 1)
    9125             :                 goto invalid_entry;
    9126          26 :               get_uleb128 (op2, readp, nexthdr);
    9127          26 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    9128          26 :               if (! print_unresolved_addresses)
    9129             :                 {
    9130             :                   Dwarf_Addr addr1;
    9131             :                   Dwarf_Addr addr2;
    9132          26 :                   if (get_indexed_addr (cu, op1, &addr1) != 0)
    9133             :                     {
    9134           0 :                       printf ("      ???..\n");
    9135             :                       printf ("      ???\n");
    9136             :                     }
    9137             :                   else
    9138             :                     {
    9139          26 :                       addr2 = addr1 + op2;
    9140          26 :                       printf ("      ");
    9141          26 :                       print_dwarf_addr (dwflmod, address_size, addr1, addr1);
    9142          26 :                       printf ("..\n      ");
    9143          26 :                       print_dwarf_addr (dwflmod, address_size,
    9144             :                                         addr2 - 1, addr2);
    9145             :                       printf ("\n");
    9146             :                     }
    9147             :                 }
    9148          26 :               if ((uint64_t) (nexthdr - readp) < 1)
    9149             :                 goto invalid_entry;
    9150          26 :               get_uleb128 (len, readp, nexthdr);
    9151          26 :               if ((uint64_t) (nexthdr - readp) < len)
    9152             :                 goto invalid_entry;
    9153          26 :               print_ops (dwflmod, dbg, 8, 8, version,
    9154             :                          address_size, offset_size, cu, len, readp);
    9155          26 :               readp += len;
    9156          26 :               break;
    9157             : 
    9158          24 :             case DW_LLE_offset_pair:
    9159          24 :               if ((uint64_t) (nexthdr - readp) < 1)
    9160             :                 goto invalid_entry;
    9161          24 :               get_uleb128 (op1, readp, nexthdr);
    9162          24 :               if ((uint64_t) (nexthdr - readp) < 1)
    9163             :                 goto invalid_entry;
    9164          24 :               get_uleb128 (op2, readp, nexthdr);
    9165          24 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    9166          24 :               if (! print_unresolved_addresses)
    9167             :                 {
    9168          24 :                   op1 += base;
    9169          24 :                   op2 += base;
    9170          24 :                   printf ("      ");
    9171          24 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    9172          24 :                   printf ("..\n      ");
    9173          24 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    9174             :                   printf ("\n");
    9175             :                 }
    9176          24 :               if ((uint64_t) (nexthdr - readp) < 1)
    9177             :                 goto invalid_entry;
    9178          24 :               get_uleb128 (len, readp, nexthdr);
    9179          24 :               if ((uint64_t) (nexthdr - readp) < len)
    9180             :                 goto invalid_entry;
    9181          24 :               print_ops (dwflmod, dbg, 8, 8, version,
    9182             :                          address_size, offset_size, cu, len, readp);
    9183          24 :               readp += len;
    9184          24 :               break;
    9185             : 
    9186           0 :             case DW_LLE_default_location:
    9187           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9188             :                 goto invalid_entry;
    9189           0 :               get_uleb128 (len, readp, nexthdr);
    9190           0 :               if ((uint64_t) (nexthdr - readp) < len)
    9191             :                 goto invalid_entry;
    9192           0 :               print_ops (dwflmod, dbg, 8, 8, version,
    9193             :                          address_size, offset_size, cu, len, readp);
    9194           0 :               readp += len;
    9195           0 :               break;
    9196             : 
    9197           5 :             case DW_LLE_base_address:
    9198           5 :               if (address_size == 4)
    9199             :                 {
    9200           0 :                   if ((uint64_t) (nexthdr - readp) < 4)
    9201             :                     goto invalid_entry;
    9202           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    9203             :                 }
    9204             :               else
    9205             :                 {
    9206           5 :                   if ((uint64_t) (nexthdr - readp) < 8)
    9207             :                     goto invalid_entry;
    9208           5 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    9209             :                 }
    9210           5 :               base = op1;
    9211           5 :               printf (" 0x%" PRIx64 "\n", base);
    9212           5 :               if (! print_unresolved_addresses)
    9213             :                 {
    9214           5 :                   printf ("      ");
    9215           5 :                   print_dwarf_addr (dwflmod, address_size, base, base);
    9216             :                   printf ("\n");
    9217             :                 }
    9218             :               break;
    9219             : 
    9220           0 :             case DW_LLE_start_end:
    9221           0 :               if (address_size == 4)
    9222             :                 {
    9223           0 :                   if ((uint64_t) (nexthdr - readp) < 8)
    9224             :                     goto invalid_entry;
    9225           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    9226           0 :                   op2 = read_4ubyte_unaligned_inc (dbg, readp);
    9227             :                 }
    9228             :               else
    9229             :                 {
    9230           0 :                   if ((uint64_t) (nexthdr - readp) < 16)
    9231             :                     goto invalid_entry;
    9232           0 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    9233           0 :                   op2 = read_8ubyte_unaligned_inc (dbg, readp);
    9234             :                 }
    9235           0 :               printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
    9236           0 :               if (! print_unresolved_addresses)
    9237             :                 {
    9238           0 :                   printf ("      ");
    9239           0 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    9240           0 :                   printf ("..\n      ");
    9241           0 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    9242             :                   printf ("\n");
    9243             :                 }
    9244           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9245             :                 goto invalid_entry;
    9246           0 :               get_uleb128 (len, readp, nexthdr);
    9247           0 :               if ((uint64_t) (nexthdr - readp) < len)
    9248             :                 goto invalid_entry;
    9249           0 :               print_ops (dwflmod, dbg, 8, 8, version,
    9250             :                          address_size, offset_size, cu, len, readp);
    9251           0 :               readp += len;
    9252           0 :               break;
    9253             : 
    9254           2 :             case DW_LLE_start_length:
    9255           2 :               if (address_size == 4)
    9256             :                 {
    9257           0 :                   if ((uint64_t) (nexthdr - readp) < 4)
    9258             :                     goto invalid_entry;
    9259           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    9260             :                 }
    9261             :               else
    9262             :                 {
    9263           2 :                   if ((uint64_t) (nexthdr - readp) < 8)
    9264             :                     goto invalid_entry;
    9265           2 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    9266             :                 }
    9267           2 :               if ((uint64_t) (nexthdr - readp) < 1)
    9268             :                 goto invalid_entry;
    9269           2 :               get_uleb128 (op2, readp, nexthdr);
    9270           2 :               printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
    9271           2 :               if (! print_unresolved_addresses)
    9272             :                 {
    9273           2 :                   op2 = op1 + op2;
    9274           2 :                   printf ("      ");
    9275           2 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    9276           2 :                   printf ("..\n      ");
    9277           2 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    9278             :                   printf ("\n");
    9279             :                 }
    9280           2 :               if ((uint64_t) (nexthdr - readp) < 1)
    9281             :                 goto invalid_entry;
    9282           2 :               get_uleb128 (len, readp, nexthdr);
    9283           2 :               if ((uint64_t) (nexthdr - readp) < len)
    9284             :                 goto invalid_entry;
    9285           2 :               print_ops (dwflmod, dbg, 8, 8, version,
    9286             :                          address_size, offset_size, cu, len, readp);
    9287           2 :               readp += len;
    9288           2 :               break;
    9289             : 
    9290             :             default:
    9291             :               goto invalid_entry;
    9292             :             }
    9293             :         }
    9294             : 
    9295           4 :     next_table:
    9296           4 :       if (readp != nexthdr)
    9297             :         {
    9298           0 :           size_t padding = nexthdr - readp;
    9299           0 :           printf (gettext ("   %zu padding bytes\n\n"), padding);
    9300           0 :           readp = nexthdr;
    9301             :         }
    9302             :     }
    9303             : }
    9304             : 
    9305             : 
    9306             : static void
    9307          44 : print_debug_loc_section (Dwfl_Module *dwflmod,
    9308             :                          Ebl *ebl, GElf_Ehdr *ehdr,
    9309             :                          Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    9310             : {
    9311          88 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_loc]
    9312          44 :                     ?: elf_rawdata (scn, NULL));
    9313             : 
    9314          44 :   if (unlikely (data == NULL))
    9315             :     {
    9316           0 :       error (0, 0, gettext ("cannot get .debug_loc content: %s"),
    9317             :              elf_errmsg (-1));
    9318           0 :       return;
    9319             :     }
    9320             : 
    9321          88 :   printf (gettext ("\
    9322             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    9323             :           elf_ndxscn (scn), section_name (ebl, shdr),
    9324          44 :           (uint64_t) shdr->sh_offset);
    9325             : 
    9326          88 :   sort_listptr (&known_locsptr, "loclistptr");
    9327          44 :   size_t listptr_idx = 0;
    9328             : 
    9329          44 :   uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    9330          44 :   uint_fast8_t offset_size = 4;
    9331             : 
    9332          44 :   bool first = true;
    9333          44 :   Dwarf_Addr base = 0;
    9334          44 :   unsigned char *readp = data->d_buf;
    9335          44 :   unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
    9336          44 :   Dwarf_CU *last_cu = NULL;
    9337      203090 :   while (readp < endp)
    9338             :     {
    9339      203002 :       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
    9340      203002 :       Dwarf_CU *cu = last_cu;
    9341      203002 :       unsigned int attr = 0;
    9342             : 
    9343      203002 :       if (first && skip_listptr_hole (&known_locsptr, &listptr_idx,
    9344             :                                       &address_size, &offset_size, &base,
    9345             :                                       &cu, offset, &readp, endp, &attr))
    9346           0 :         continue;
    9347             : 
    9348      203002 :       if (last_cu != cu)
    9349             :        {
    9350             :         Dwarf_Die cudie;
    9351         974 :         if (dwarf_cu_die (cu, &cudie,
    9352             :                           NULL, NULL, NULL, NULL,
    9353             :                           NULL, NULL) == NULL)
    9354           0 :           printf (gettext ("\n Unknown CU base: "));
    9355             :         else
    9356         974 :           printf (gettext ("\n CU [%6" PRIx64 "] base: "),
    9357             :                   dwarf_dieoffset (&cudie));
    9358         974 :         print_dwarf_addr (dwflmod, address_size, base, base);
    9359         974 :         printf ("\n");
    9360             :        }
    9361      203002 :       last_cu = cu;
    9362             : 
    9363      203002 :       if (attr == DW_AT_GNU_locviews)
    9364             :         {
    9365           0 :           Dwarf_Off next_off = next_listptr_offset (&known_locsptr,
    9366             :                                                     listptr_idx);
    9367           0 :           const unsigned char *locp = readp;
    9368             :           const unsigned char *locendp;
    9369           0 :           if (next_off == 0
    9370           0 :               || next_off > (size_t) (endp
    9371           0 :                                       - (const unsigned char *) data->d_buf))
    9372             :             locendp = endp;
    9373             :           else
    9374           0 :             locendp = (const unsigned char *) data->d_buf + next_off;
    9375             : 
    9376           0 :           while (locp < locendp)
    9377             :             {
    9378             :               uint64_t v1, v2;
    9379           0 :               get_uleb128 (v1, locp, locendp);
    9380           0 :               if (locp >= locendp)
    9381             :                 {
    9382           0 :                   printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
    9383             :                   break;
    9384             :                 }
    9385           0 :               get_uleb128 (v2, locp, locendp);
    9386           0 :               if (first)                /* First view pair in a list.  */
    9387             :                 printf (" [%6tx] ", offset);
    9388             :               else
    9389             :                 printf ("          ");
    9390           0 :               printf ("view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
    9391           0 :               first = false;
    9392             :             }
    9393             : 
    9394           0 :           first = true;
    9395           0 :           readp = (unsigned char *) locendp;
    9396           0 :           continue;
    9397             :         }
    9398             : 
    9399             :       /* GNU DebugFission encoded addresses as addrx.  */
    9400      203002 :       bool is_debugfission = ((cu != NULL
    9401           0 :                                || split_dwarf_cu_base (dbg, &cu, &base))
    9402      406004 :                               && (cu->version < 5
    9403      203002 :                                   && cu->unit_type == DW_UT_split_compile));
    9404      203002 :       if (!is_debugfission
    9405      202942 :           && unlikely (data->d_size - offset < (size_t) address_size * 2))
    9406             :         {
    9407           0 :         invalid_data:
    9408           0 :           printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
    9409           0 :           break;
    9410             :         }
    9411             : 
    9412             :       Dwarf_Addr begin;
    9413             :       Dwarf_Addr end;
    9414      203002 :       bool use_base = true;
    9415      203002 :       if (is_debugfission)
    9416             :         {
    9417          60 :           const unsigned char *locp = readp;
    9418          60 :           const unsigned char *locendp = readp + data->d_size;
    9419          60 :           if (locp >= locendp)
    9420             :             goto invalid_data;
    9421             : 
    9422             :           Dwarf_Word idx;
    9423          60 :           unsigned char code = *locp++;
    9424          60 :           switch (code)
    9425             :             {
    9426          20 :             case DW_LLE_GNU_end_of_list_entry:
    9427          20 :               begin = 0;
    9428          20 :               end = 0;
    9429          20 :               break;
    9430             : 
    9431           0 :             case DW_LLE_GNU_base_address_selection_entry:
    9432           0 :               if (locp >= locendp)
    9433             :                 goto invalid_data;
    9434           0 :               begin = (Dwarf_Addr) -1;
    9435           0 :               get_uleb128 (idx, locp, locendp);
    9436           0 :               if (get_indexed_addr (cu, idx, &end) != 0)
    9437           0 :                 end = idx; /* ... */
    9438             :               break;
    9439             : 
    9440           0 :             case DW_LLE_GNU_start_end_entry:
    9441           0 :               if (locp >= locendp)
    9442             :                 goto invalid_data;
    9443           0 :               get_uleb128 (idx, locp, locendp);
    9444           0 :               if (get_indexed_addr (cu, idx, &begin) != 0)
    9445           0 :                 begin = idx; /* ... */
    9446           0 :               if (locp >= locendp)
    9447             :                 goto invalid_data;
    9448           0 :               get_uleb128 (idx, locp, locendp);
    9449           0 :               if (get_indexed_addr (cu, idx, &end) != 0)
    9450           0 :                 end = idx; /* ... */
    9451             :               use_base = false;
    9452             :               break;
    9453             : 
    9454          40 :             case DW_LLE_GNU_start_length_entry:
    9455          40 :               if (locp >= locendp)
    9456             :                 goto invalid_data;
    9457          40 :               get_uleb128 (idx, locp, locendp);
    9458          40 :               if (get_indexed_addr (cu, idx, &begin) != 0)
    9459           0 :                 begin = idx; /* ... */
    9460          40 :               if (locendp - locp < 4)
    9461             :                 goto invalid_data;
    9462          40 :               end = read_4ubyte_unaligned_inc (dbg, locp);
    9463          40 :               end += begin;
    9464          40 :               use_base = false;
    9465          40 :               break;
    9466             : 
    9467             :             default:
    9468             :                 goto invalid_data;
    9469             :             }
    9470             : 
    9471          60 :           readp = (unsigned char *) locp;
    9472             :         }
    9473      202942 :       else if (address_size == 8)
    9474             :         {
    9475      202996 :           begin = read_8ubyte_unaligned_inc (dbg, readp);
    9476      202996 :           end = read_8ubyte_unaligned_inc (dbg, readp);
    9477             :         }
    9478             :       else
    9479             :         {
    9480           0 :           begin = read_4ubyte_unaligned_inc (dbg, readp);
    9481           0 :           end = read_4ubyte_unaligned_inc (dbg, readp);
    9482           0 :           if (begin == (Dwarf_Addr) (uint32_t) -1)
    9483           0 :             begin = (Dwarf_Addr) -1l;
    9484             :         }
    9485             : 
    9486      203002 :       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
    9487             :         {
    9488           0 :           printf (gettext (" [%6tx] base address\n          "), offset);
    9489           0 :           print_dwarf_addr (dwflmod, address_size, end, end);
    9490           0 :           printf ("\n");
    9491           0 :           base = end;
    9492             :         }
    9493      203002 :       else if (begin == 0 && end == 0) /* End of list entry.  */
    9494             :         {
    9495       39494 :           if (first)
    9496           0 :             printf (gettext (" [%6tx] empty list\n"), offset);
    9497             :           first = true;
    9498             :         }
    9499             :       else
    9500             :         {
    9501             :           /* We have a location expression entry.  */
    9502      163544 :           uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
    9503             : 
    9504      163508 :           if (first)            /* First entry in a list.  */
    9505             :             printf (" [%6tx] ", offset);
    9506             :           else
    9507             :             printf ("          ");
    9508             : 
    9509      327016 :           printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
    9510      163508 :           if (! print_unresolved_addresses)
    9511             :             {
    9512      163478 :               Dwarf_Addr dab = use_base ? base + begin : begin;
    9513      163478 :               Dwarf_Addr dae = use_base ? base + end : end;
    9514      163478 :               printf ("          ");
    9515      163478 :               print_dwarf_addr (dwflmod, address_size, dab, dab);
    9516      163478 :               printf ("..\n          ");
    9517      163478 :               print_dwarf_addr (dwflmod, address_size, dae - 1, dae);
    9518             :               printf ("\n");
    9519             :             }
    9520             : 
    9521      163508 :           if (endp - readp <= (ptrdiff_t) len)
    9522             :             {
    9523           0 :               fputs (gettext ("   <INVALID DATA>\n"), stdout);
    9524           0 :               break;
    9525             :             }
    9526             : 
    9527      327016 :           print_ops (dwflmod, dbg, 11, 11,
    9528      163508 :                      cu != NULL ? cu->version : 3,
    9529             :                      address_size, offset_size, cu, len, readp);
    9530             : 
    9531      163508 :           first = false;
    9532      163508 :           readp += len;
    9533             :         }
    9534             :     }
    9535             : }
    9536             : 
    9537             : struct mac_culist
    9538             : {
    9539             :   Dwarf_Die die;
    9540             :   Dwarf_Off offset;
    9541             :   Dwarf_Files *files;
    9542             :   struct mac_culist *next;
    9543             : };
    9544             : 
    9545             : 
    9546             : static int
    9547           0 : mac_compare (const void *p1, const void *p2)
    9548             : {
    9549           0 :   struct mac_culist *m1 = (struct mac_culist *) p1;
    9550           0 :   struct mac_culist *m2 = (struct mac_culist *) p2;
    9551             : 
    9552           0 :   if (m1->offset < m2->offset)
    9553             :     return -1;
    9554           0 :   if (m1->offset > m2->offset)
    9555             :     return 1;
    9556           0 :   return 0;
    9557             : }
    9558             : 
    9559             : 
    9560             : static void
    9561           0 : print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
    9562             :                              Ebl *ebl,
    9563             :                              GElf_Ehdr *ehdr __attribute__ ((unused)),
    9564             :                              Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    9565             : {
    9566           0 :   printf (gettext ("\
    9567             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    9568             :           elf_ndxscn (scn), section_name (ebl, shdr),
    9569           0 :           (uint64_t) shdr->sh_offset);
    9570           0 :   putc_unlocked ('\n', stdout);
    9571             : 
    9572             :   /* There is no function in libdw to iterate over the raw content of
    9573             :      the section but it is easy enough to do.  */
    9574           0 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_macinfo]
    9575           0 :                     ?: elf_rawdata (scn, NULL));
    9576           0 :   if (unlikely (data == NULL))
    9577             :     {
    9578           0 :       error (0, 0, gettext ("cannot get macro information section data: %s"),
    9579             :              elf_errmsg (-1));
    9580           0 :       return;
    9581             :     }
    9582             : 
    9583             :   /* Get the source file information for all CUs.  */
    9584             :   Dwarf_Off offset;
    9585           0 :   Dwarf_Off ncu = 0;
    9586             :   size_t hsize;
    9587           0 :   struct mac_culist *culist = NULL;
    9588           0 :   size_t nculist = 0;
    9589           0 :   while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
    9590             :     {
    9591             :       Dwarf_Die cudie;
    9592           0 :       if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
    9593           0 :         continue;
    9594             : 
    9595             :       Dwarf_Attribute attr;
    9596           0 :       if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
    9597           0 :         continue;
    9598             : 
    9599             :       Dwarf_Word macoff;
    9600           0 :       if (dwarf_formudata (&attr, &macoff) != 0)
    9601           0 :         continue;
    9602             : 
    9603           0 :       struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
    9604           0 :       newp->die = cudie;
    9605           0 :       newp->offset = macoff;
    9606           0 :       newp->files = NULL;
    9607           0 :       newp->next = culist;
    9608           0 :       culist = newp;
    9609           0 :       ++nculist;
    9610             :     }
    9611             : 
    9612             :   /* Convert the list into an array for easier consumption.  */
    9613           0 :   struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
    9614             :                                                          * sizeof (*cus));
    9615             :   /* Add sentinel.  */
    9616           0 :   cus[nculist].offset = data->d_size;
    9617           0 :   cus[nculist].files = (Dwarf_Files *) -1l;
    9618           0 :   if (nculist > 0)
    9619             :     {
    9620           0 :       for (size_t cnt = nculist - 1; culist != NULL; --cnt)
    9621             :         {
    9622           0 :           assert (cnt < nculist);
    9623           0 :           cus[cnt] = *culist;
    9624           0 :           culist = culist->next;
    9625             :         }
    9626             : 
    9627             :       /* Sort the array according to the offset in the .debug_macinfo
    9628             :          section.  Note we keep the sentinel at the end.  */
    9629           0 :       qsort (cus, nculist, sizeof (*cus), mac_compare);
    9630             :     }
    9631             : 
    9632           0 :   const unsigned char *readp = (const unsigned char *) data->d_buf;
    9633           0 :   const unsigned char *readendp = readp + data->d_size;
    9634           0 :   int level = 1;
    9635             : 
    9636           0 :   while (readp < readendp)
    9637             :     {
    9638           0 :       unsigned int opcode = *readp++;
    9639             :       unsigned int u128;
    9640             :       unsigned int u128_2;
    9641             :       const unsigned char *endp;
    9642             : 
    9643           0 :       switch (opcode)
    9644             :         {
    9645           0 :         case DW_MACINFO_define:
    9646             :         case DW_MACINFO_undef:
    9647             :         case DW_MACINFO_vendor_ext:
    9648             :           /*  For the first two opcodes the parameters are
    9649             :                 line, string
    9650             :               For the latter
    9651             :                 number, string.
    9652             :               We can treat these cases together.  */
    9653           0 :           get_uleb128 (u128, readp, readendp);
    9654             : 
    9655           0 :           endp = memchr (readp, '\0', readendp - readp);
    9656           0 :           if (unlikely (endp == NULL))
    9657             :             {
    9658           0 :               printf (gettext ("\
    9659             : %*s*** non-terminated string at end of section"),
    9660             :                       level, "");
    9661             :               return;
    9662             :             }
    9663             : 
    9664           0 :           if (opcode == DW_MACINFO_define)
    9665           0 :             printf ("%*s#define %s, line %u\n",
    9666             :                     level, "", (char *) readp, u128);
    9667           0 :           else if (opcode == DW_MACINFO_undef)
    9668           0 :             printf ("%*s#undef %s, line %u\n",
    9669             :                     level, "", (char *) readp, u128);
    9670             :           else
    9671           0 :             printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
    9672             : 
    9673           0 :           readp = endp + 1;
    9674           0 :           break;
    9675             : 
    9676           0 :         case DW_MACINFO_start_file:
    9677             :           /* The two parameters are line and file index, in this order.  */
    9678           0 :           get_uleb128 (u128, readp, readendp);
    9679           0 :           if (readendp - readp < 1)
    9680             :             {
    9681           0 :               printf (gettext ("\
    9682             : %*s*** missing DW_MACINFO_start_file argument at end of section"),
    9683             :                       level, "");
    9684             :               return;
    9685             :             }
    9686           0 :           get_uleb128 (u128_2, readp, readendp);
    9687             : 
    9688             :           /* Find the CU DIE for this file.  */
    9689           0 :           size_t macoff = readp - (const unsigned char *) data->d_buf;
    9690           0 :           const char *fname = "???";
    9691           0 :           if (macoff >= cus[0].offset)
    9692             :             {
    9693           0 :               while (macoff >= cus[1].offset && cus[1].offset != data->d_size)
    9694           0 :                 ++cus;
    9695             : 
    9696           0 :               if (cus[0].files == NULL
    9697           0 :                 && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
    9698           0 :                 cus[0].files = (Dwarf_Files *) -1l;
    9699             : 
    9700           0 :               if (cus[0].files != (Dwarf_Files *) -1l)
    9701           0 :                 fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
    9702           0 :                          ?: "???");
    9703             :             }
    9704             : 
    9705           0 :           printf ("%*sstart_file %u, [%u] %s\n",
    9706             :                   level, "", u128, u128_2, fname);
    9707           0 :           ++level;
    9708           0 :           break;
    9709             : 
    9710           0 :         case DW_MACINFO_end_file:
    9711           0 :           --level;
    9712             :           printf ("%*send_file\n", level, "");
    9713             :           /* Nothing more to do.  */
    9714             :           break;
    9715             : 
    9716           0 :         default:
    9717             :           // XXX gcc seems to generate files with a trailing zero.
    9718           0 :           if (unlikely (opcode != 0 || readp != readendp))
    9719             :             printf ("%*s*** invalid opcode %u\n", level, "", opcode);
    9720             :           break;
    9721             :         }
    9722             :     }
    9723             : }
    9724             : 
    9725             : 
    9726             : static void
    9727           3 : print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
    9728             :                            Ebl *ebl,
    9729             :                            GElf_Ehdr *ehdr __attribute__ ((unused)),
    9730             :                            Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    9731             : {
    9732           6 :   printf (gettext ("\
    9733             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    9734             :           elf_ndxscn (scn), section_name (ebl, shdr),
    9735           3 :           (uint64_t) shdr->sh_offset);
    9736           6 :   putc_unlocked ('\n', stdout);
    9737             : 
    9738           3 :   Elf_Data *data =  elf_getdata (scn, NULL);
    9739           3 :   if (unlikely (data == NULL))
    9740             :     {
    9741           0 :       error (0, 0, gettext ("cannot get macro information section data: %s"),
    9742             :              elf_errmsg (-1));
    9743           0 :       return;
    9744             :     }
    9745             : 
    9746             :   /* Get the source file information for all CUs.  Uses same
    9747             :      datastructure as macinfo.  But uses offset field to directly
    9748             :      match .debug_line offset.  And just stored in a list.  */
    9749             :   Dwarf_Off offset;
    9750           3 :   Dwarf_Off ncu = 0;
    9751             :   size_t hsize;
    9752           3 :   struct mac_culist *culist = NULL;
    9753           3 :   size_t nculist = 0;
    9754          10 :   while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
    9755             :     {
    9756             :       Dwarf_Die cudie;
    9757           4 :       if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
    9758           0 :         continue;
    9759             : 
    9760             :       Dwarf_Attribute attr;
    9761           4 :       if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL)
    9762           0 :         continue;
    9763             : 
    9764             :       Dwarf_Word lineoff;
    9765           4 :       if (dwarf_formudata (&attr, &lineoff) != 0)
    9766           0 :         continue;
    9767             : 
    9768           4 :       struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
    9769           4 :       newp->die = cudie;
    9770           4 :       newp->offset = lineoff;
    9771           4 :       newp->files = NULL;
    9772           4 :       newp->next = culist;
    9773           4 :       culist = newp;
    9774           4 :       ++nculist;
    9775             :     }
    9776             : 
    9777           3 :   const unsigned char *readp = (const unsigned char *) data->d_buf;
    9778           3 :   const unsigned char *readendp = readp + data->d_size;
    9779             : 
    9780          14 :   while (readp < readendp)
    9781             :     {
    9782          16 :       printf (gettext (" Offset:             0x%" PRIx64 "\n"),
    9783           8 :               (uint64_t) (readp - (const unsigned char *) data->d_buf));
    9784             : 
    9785             :       // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
    9786             :       // optional vendor extension macro entry table.
    9787           8 :       if (readp + 2 > readendp)
    9788             :         {
    9789           0 :         invalid_data:
    9790           0 :           error (0, 0, gettext ("invalid data"));
    9791           0 :           return;
    9792             :         }
    9793           8 :       const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
    9794          16 :       printf (gettext (" Version:            %" PRIu16 "\n"), vers);
    9795             : 
    9796             :       // Version 4 is the GNU extension for DWARF4.  DWARF5 will use version
    9797             :       // 5 when it gets standardized.
    9798           8 :       if (vers != 4 && vers != 5)
    9799             :         {
    9800           0 :           printf (gettext ("  unknown version, cannot parse section\n"));
    9801             :           return;
    9802             :         }
    9803             : 
    9804           8 :       if (readp + 1 > readendp)
    9805             :         goto invalid_data;
    9806           8 :       const unsigned char flag = *readp++;
    9807          16 :       printf (gettext (" Flag:               0x%" PRIx8), flag);
    9808           8 :       if (flag != 0)
    9809             :         {
    9810           4 :           printf (" (");
    9811           4 :           if ((flag & 0x01) != 0)
    9812             :             {
    9813           0 :               printf ("offset_size");
    9814           0 :               if ((flag & 0xFE) !=  0)
    9815             :                 printf (", ");
    9816             :             }
    9817           4 :           if ((flag & 0x02) != 0)
    9818             :             {
    9819           4 :               printf ("debug_line_offset");
    9820           4 :               if ((flag & 0xFC) !=  0)
    9821             :                 printf (", ");
    9822             :             }
    9823           4 :           if ((flag & 0x04) != 0)
    9824             :             {
    9825           0 :               printf ("operands_table");
    9826           0 :               if ((flag & 0xF8) !=  0)
    9827             :                 printf (", ");
    9828             :             }
    9829           4 :           if ((flag & 0xF8) != 0)
    9830             :             printf ("unknown");
    9831             :           printf (")");
    9832             :         }
    9833           8 :       printf ("\n");
    9834             : 
    9835           8 :       unsigned int offset_len = (flag & 0x01) ? 8 : 4;
    9836          16 :       printf (gettext (" Offset length:      %" PRIu8 "\n"), offset_len);
    9837           8 :       Dwarf_Off line_offset = -1;
    9838           8 :       if (flag & 0x02)
    9839             :         {
    9840           4 :           if (offset_len == 8)
    9841           0 :             line_offset = read_8ubyte_unaligned_inc (dbg, readp);
    9842             :           else
    9843           4 :             line_offset = read_4ubyte_unaligned_inc (dbg, readp);
    9844           4 :           printf (gettext (" .debug_line offset: 0x%" PRIx64 "\n"),
    9845             :                   line_offset);
    9846             :         }
    9847             : 
    9848           4 :       struct mac_culist *cu = NULL;
    9849           4 :       if (line_offset != (Dwarf_Off) -1)
    9850             :         {
    9851             :           cu = culist;
    9852           5 :           while (cu != NULL && line_offset != cu->offset)
    9853           1 :             cu = cu->next;
    9854             :         }
    9855             : 
    9856           8 :       Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, (cu != NULL
    9857             :                                                                ? cu->die.cu
    9858             :                                                                : NULL));
    9859             : 
    9860             :       const unsigned char *vendor[DW_MACRO_hi_user - DW_MACRO_lo_user + 1];
    9861           8 :       memset (vendor, 0, sizeof vendor);
    9862           8 :       if (flag & 0x04)
    9863             :         {
    9864             :           // 1 byte length, for each item, 1 byte opcode, uleb128 number
    9865             :           // of arguments, for each argument 1 byte form code.
    9866           0 :           if (readp + 1 > readendp)
    9867             :             goto invalid_data;
    9868           0 :           unsigned int tlen = *readp++;
    9869           0 :           printf (gettext ("  extension opcode table, %" PRIu8 " items:\n"),
    9870             :                   tlen);
    9871           0 :           for (unsigned int i = 0; i < tlen; i++)
    9872             :             {
    9873           0 :               if (readp + 1 > readendp)
    9874             :                 goto invalid_data;
    9875           0 :               unsigned int opcode = *readp++;
    9876           0 :               printf (gettext ("    [%" PRIx8 "]"), opcode);
    9877           0 :               if (opcode < DW_MACRO_lo_user
    9878           0 :                   || opcode > DW_MACRO_hi_user)
    9879             :                 goto invalid_data;
    9880             :               // Record the start of description for this vendor opcode.
    9881             :               // uleb128 nr args, 1 byte per arg form.
    9882           0 :               vendor[opcode - DW_MACRO_lo_user] = readp;
    9883           0 :               if (readp + 1 > readendp)
    9884             :                 goto invalid_data;
    9885           0 :               unsigned int args = *readp++;
    9886           0 :               if (args > 0)
    9887             :                 {
    9888           0 :                   printf (gettext (" %" PRIu8 " arguments:"), args);
    9889           0 :                   while (args > 0)
    9890             :                     {
    9891           0 :                       if (readp + 1 > readendp)
    9892             :                         goto invalid_data;
    9893           0 :                       unsigned int form = *readp++;
    9894           0 :                       printf (" %s", dwarf_form_name (form));
    9895           0 :                       if (! libdw_valid_user_form (form))
    9896             :                         goto invalid_data;
    9897           0 :                       args--;
    9898           0 :                       if (args > 0)
    9899             :                         putchar_unlocked (',');
    9900             :                     }
    9901             :                 }
    9902             :               else
    9903           0 :                 printf (gettext (" no arguments."));
    9904           0 :               putchar_unlocked ('\n');
    9905             :             }
    9906             :         }
    9907           8 :       putchar_unlocked ('\n');
    9908             : 
    9909           8 :       int level = 1;
    9910           8 :       if (readp + 1 > readendp)
    9911             :         goto invalid_data;
    9912           8 :       unsigned int opcode = *readp++;
    9913         743 :       while (opcode != 0)
    9914             :         {
    9915             :           unsigned int u128;
    9916             :           unsigned int u128_2;
    9917             :           const unsigned char *endp;
    9918             :           uint64_t off;
    9919             : 
    9920         727 :           switch (opcode)
    9921             :             {
    9922           6 :             case DW_MACRO_start_file:
    9923           6 :               get_uleb128 (u128, readp, readendp);
    9924           6 :               if (readp >= readendp)
    9925             :                 goto invalid_data;
    9926           6 :               get_uleb128 (u128_2, readp, readendp);
    9927             : 
    9928             :               /* Find the CU DIE that matches this line offset.  */
    9929           6 :               const char *fname = "???";
    9930           6 :               if (cu != NULL)
    9931             :                 {
    9932           6 :                   if (cu->files == NULL
    9933           4 :                       && dwarf_getsrcfiles (&cu->die, &cu->files,
    9934             :                                             NULL) != 0)
    9935           0 :                     cu->files = (Dwarf_Files *) -1l;
    9936             : 
    9937           6 :                   if (cu->files != (Dwarf_Files *) -1l)
    9938           6 :                     fname = (dwarf_filesrc (cu->files, u128_2,
    9939           6 :                                             NULL, NULL) ?: "???");
    9940             :                 }
    9941           6 :               printf ("%*sstart_file %u, [%u] %s\n",
    9942             :                       level, "", u128, u128_2, fname);
    9943           6 :               ++level;
    9944           6 :               break;
    9945             : 
    9946           6 :             case DW_MACRO_end_file:
    9947           6 :               --level;
    9948             :               printf ("%*send_file\n", level, "");
    9949             :               break;
    9950             : 
    9951           1 :             case DW_MACRO_define:
    9952           1 :               get_uleb128 (u128, readp, readendp);
    9953           1 :               endp = memchr (readp, '\0', readendp - readp);
    9954           1 :               if (endp == NULL)
    9955             :                 goto invalid_data;
    9956           2 :               printf ("%*s#define %s, line %u\n",
    9957             :                       level, "", readp, u128);
    9958           1 :               readp = endp + 1;
    9959           1 :               break;
    9960             : 
    9961           0 :             case DW_MACRO_undef:
    9962           0 :               get_uleb128 (u128, readp, readendp);
    9963           0 :               endp = memchr (readp, '\0', readendp - readp);
    9964           0 :               if (endp == NULL)
    9965             :                 goto invalid_data;
    9966           0 :               printf ("%*s#undef %s, line %u\n",
    9967             :                       level, "", readp, u128);
    9968           0 :               readp = endp + 1;
    9969           0 :               break;
    9970             : 
    9971         707 :             case DW_MACRO_define_strp:
    9972         707 :               get_uleb128 (u128, readp, readendp);
    9973         707 :               if (readp + offset_len > readendp)
    9974             :                 goto invalid_data;
    9975         707 :               if (offset_len == 8)
    9976           0 :                 off = read_8ubyte_unaligned_inc (dbg, readp);
    9977             :               else
    9978         707 :                 off = read_4ubyte_unaligned_inc (dbg, readp);
    9979         707 :               printf ("%*s#define %s, line %u (indirect)\n",
    9980             :                       level, "", dwarf_getstring (dbg, off, NULL), u128);
    9981             :               break;
    9982             : 
    9983           1 :             case DW_MACRO_undef_strp:
    9984           1 :               get_uleb128 (u128, readp, readendp);
    9985           1 :               if (readp + offset_len > readendp)
    9986             :                 goto invalid_data;
    9987           1 :               if (offset_len == 8)
    9988           0 :                 off = read_8ubyte_unaligned_inc (dbg, readp);
    9989             :               else
    9990           1 :                 off = read_4ubyte_unaligned_inc (dbg, readp);
    9991           1 :               printf ("%*s#undef %s, line %u (indirect)\n",
    9992             :                       level, "", dwarf_getstring (dbg, off, NULL), u128);
    9993             :               break;
    9994             : 
    9995           6 :             case DW_MACRO_import:
    9996           6 :               if (readp + offset_len > readendp)
    9997             :                 goto invalid_data;
    9998           6 :               if (offset_len == 8)
    9999           0 :                 off = read_8ubyte_unaligned_inc (dbg, readp);
   10000             :               else
   10001           6 :                 off = read_4ubyte_unaligned_inc (dbg, readp);
   10002             :               printf ("%*s#include offset 0x%" PRIx64 "\n",
   10003             :                       level, "", off);
   10004             :               break;
   10005             : 
   10006           0 :             case DW_MACRO_define_sup:
   10007           0 :               get_uleb128 (u128, readp, readendp);
   10008           0 :               if (readp + offset_len > readendp)
   10009             :                 goto invalid_data;
   10010           0 :               printf ("%*s#define ", level, "");
   10011           0 :               readp =  print_form_data (dbg, DW_FORM_strp_sup,
   10012             :                                         readp, readendp, offset_len,
   10013             :                                         str_offsets_base);
   10014             :               printf (", line %u (sup)\n", u128);
   10015             :               break;
   10016             : 
   10017           0 :             case DW_MACRO_undef_sup:
   10018           0 :               get_uleb128 (u128, readp, readendp);
   10019           0 :               if (readp + offset_len > readendp)
   10020             :                 goto invalid_data;
   10021           0 :               printf ("%*s#undef ", level, "");
   10022           0 :               readp =  print_form_data (dbg, DW_FORM_strp_sup,
   10023             :                                         readp, readendp, offset_len,
   10024             :                                         str_offsets_base);
   10025             :               printf (", line %u (sup)\n", u128);
   10026             :               break;
   10027             : 
   10028           0 :             case DW_MACRO_import_sup:
   10029           0 :               if (readp + offset_len > readendp)
   10030             :                 goto invalid_data;
   10031           0 :               if (offset_len == 8)
   10032           0 :                 off = read_8ubyte_unaligned_inc (dbg, readp);
   10033             :               else
   10034           0 :                 off = read_4ubyte_unaligned_inc (dbg, readp);
   10035             :               // XXX Needs support for reading from supplementary object file.
   10036             :               printf ("%*s#include offset 0x%" PRIx64 " (sup)\n",
   10037             :                       level, "", off);
   10038             :               break;
   10039             : 
   10040           0 :             case DW_MACRO_define_strx:
   10041           0 :               get_uleb128 (u128, readp, readendp);
   10042           0 :               if (readp + offset_len > readendp)
   10043             :                 goto invalid_data;
   10044           0 :               printf ("%*s#define ", level, "");
   10045           0 :               readp =  print_form_data (dbg, DW_FORM_strx,
   10046             :                                         readp, readendp, offset_len,
   10047             :                                         str_offsets_base);
   10048             :               printf (", line %u (strx)\n", u128);
   10049             :               break;
   10050             : 
   10051           0 :             case DW_MACRO_undef_strx:
   10052           0 :               get_uleb128 (u128, readp, readendp);
   10053           0 :               if (readp + offset_len > readendp)
   10054             :                 goto invalid_data;
   10055           0 :               printf ("%*s#undef ", level, "");
   10056           0 :               readp =  print_form_data (dbg, DW_FORM_strx,
   10057             :                                         readp, readendp, offset_len,
   10058             :                                         str_offsets_base);
   10059             :               printf (", line %u (strx)\n", u128);
   10060             :               break;
   10061             : 
   10062           0 :             default:
   10063           0 :               printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
   10064           0 :               if (opcode < DW_MACRO_lo_user
   10065             :                   || opcode > DW_MACRO_lo_user
   10066           0 :                   || vendor[opcode - DW_MACRO_lo_user] == NULL)
   10067             :                 goto invalid_data;
   10068             : 
   10069             :               const unsigned char *op_desc;
   10070           0 :               op_desc = vendor[opcode - DW_MACRO_lo_user];
   10071             : 
   10072             :               // Just skip the arguments, we cannot really interpret them,
   10073             :               // but print as much as we can.
   10074           0 :               unsigned int args = *op_desc++;
   10075           0 :               while (args > 0 && readp < readendp)
   10076           0 :                 {
   10077           0 :                   unsigned int form = *op_desc++;
   10078           0 :                   readp = print_form_data (dbg, form, readp, readendp,
   10079             :                                            offset_len, str_offsets_base);
   10080           0 :                   args--;
   10081           0 :                   if (args > 0)
   10082             :                     printf (", ");
   10083             :                 }
   10084             :               putchar_unlocked ('\n');
   10085             :             }
   10086             : 
   10087         727 :           if (readp + 1 > readendp)
   10088             :             goto invalid_data;
   10089         727 :           opcode = *readp++;
   10090         727 :           if (opcode == 0)
   10091             :             putchar_unlocked ('\n');
   10092             :         }
   10093             :     }
   10094             : }
   10095             : 
   10096             : 
   10097             : /* Callback for printing global names.  */
   10098             : static int
   10099          34 : print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
   10100             :                 void *arg)
   10101             : {
   10102          34 :   int *np = (int *) arg;
   10103             : 
   10104         102 :   printf (gettext (" [%5d] DIE offset: %6" PRId64
   10105             :                    ", CU DIE offset: %6" PRId64 ", name: %s\n"),
   10106          34 :           (*np)++, global->die_offset, global->cu_offset, global->name);
   10107             : 
   10108          34 :   return 0;
   10109             : }
   10110             : 
   10111             : 
   10112             : /* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
   10113             : static void
   10114           8 : print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10115             :                               Ebl *ebl,
   10116             :                               GElf_Ehdr *ehdr __attribute__ ((unused)),
   10117             :                               Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   10118             : {
   10119          16 :   printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
   10120             :           elf_ndxscn (scn), section_name (ebl, shdr),
   10121           8 :           (uint64_t) shdr->sh_offset);
   10122             : 
   10123           8 :   int n = 0;
   10124           8 :   (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
   10125           8 : }
   10126             : 
   10127             : /* Print the content of the DWARF string section '.debug_str'.  */
   10128             : static void
   10129          45 : print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10130             :                          Ebl *ebl,
   10131             :                          GElf_Ehdr *ehdr __attribute__ ((unused)),
   10132             :                          Elf_Scn *scn, GElf_Shdr *shdr,
   10133             :                          Dwarf *dbg __attribute__ ((unused)))
   10134             : {
   10135          45 :   Elf_Data *data = elf_rawdata (scn, NULL);
   10136          45 :   const size_t sh_size = data ? data->d_size : 0;
   10137             : 
   10138             :   /* Compute floor(log16(shdr->sh_size)).  */
   10139          45 :   GElf_Addr tmp = sh_size;
   10140          45 :   int digits = 1;
   10141         200 :   while (tmp >= 16)
   10142             :     {
   10143         110 :       ++digits;
   10144         110 :       tmp >>= 4;
   10145             :     }
   10146          45 :   digits = MAX (4, digits);
   10147             : 
   10148         135 :   printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
   10149             :                    " %*s  String\n"),
   10150             :           elf_ndxscn (scn),
   10151          45 :           section_name (ebl, shdr), (uint64_t) shdr->sh_offset,
   10152             :           /* TRANS: the debugstr| prefix makes the string unique.  */
   10153          45 :           digits + 2, sgettext ("debugstr|Offset"));
   10154             : 
   10155          45 :   Dwarf_Off offset = 0;
   10156       61203 :   while (offset < sh_size)
   10157             :     {
   10158             :       size_t len;
   10159       61113 :       const char *str = (const char *) data->d_buf + offset;
   10160       61113 :       const char *endp = memchr (str, '\0', sh_size - offset);
   10161       61113 :       if (unlikely (endp == NULL))
   10162             :         {
   10163           0 :           printf (gettext (" *** error, missing string terminator\n"));
   10164             :           break;
   10165             :         }
   10166             : 
   10167       61113 :       printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
   10168       61113 :       len = endp - str;
   10169       61113 :       offset += len + 1;
   10170             :     }
   10171          45 : }
   10172             : 
   10173             : static void
   10174           4 : print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10175             :                                  Ebl *ebl,
   10176             :                                  GElf_Ehdr *ehdr __attribute__ ((unused)),
   10177             :                                  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   10178             : {
   10179           8 :   printf (gettext ("\
   10180             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
   10181             :           elf_ndxscn (scn), section_name (ebl, shdr),
   10182           4 :           (uint64_t) shdr->sh_offset);
   10183             : 
   10184           4 :   if (shdr->sh_size == 0)
   10185             :     return;
   10186             : 
   10187             :   /* We like to get the section from libdw to make sure they are relocated.  */
   10188           8 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_str_offsets]
   10189           4 :                     ?: elf_rawdata (scn, NULL));
   10190           4 :   if (unlikely (data == NULL))
   10191             :     {
   10192           0 :       error (0, 0, gettext ("cannot get .debug_str_offsets section data: %s"),
   10193             :              elf_errmsg (-1));
   10194             :       return;
   10195             :     }
   10196             : 
   10197           4 :   size_t idx = 0;
   10198           8 :   sort_listptr (&known_stroffbases, "str_offsets");
   10199             : 
   10200           4 :   const unsigned char *start = (const unsigned char *) data->d_buf;
   10201           4 :   const unsigned char *readp = start;
   10202           4 :   const unsigned char *readendp = ((const unsigned char *) data->d_buf
   10203           4 :                                    + data->d_size);
   10204             : 
   10205          12 :   while (readp < readendp)
   10206             :     {
   10207             :       /* Most string offset tables will have a header.  For split
   10208             :          dwarf unit GNU DebugFission didn't add one.  But they were
   10209             :          also only defined for split units (main or skeleton units
   10210             :          didn't have indirect strings).  So if we don't have a
   10211             :          DW_AT_str_offsets_base at all and this is offset zero, then
   10212             :          just start printing offsets immediately, if this is a .dwo
   10213             :          section.  */
   10214           4 :       Dwarf_Off off = (Dwarf_Off) (readp
   10215           4 :                                    - (const unsigned char *) data->d_buf);
   10216             : 
   10217           4 :       printf ("Table at offset %" PRIx64 " ", off);
   10218             : 
   10219           4 :       struct listptr *listptr = get_listptr (&known_stroffbases, idx++);
   10220           0 :       const unsigned char *next_unitp = readendp;
   10221             :       uint8_t offset_size;
   10222             :       bool has_header;
   10223           0 :       if (listptr == NULL)
   10224             :         {
   10225             :           /* This can happen for .dwo files.  There is only an header
   10226             :              in the case this is a version 5 split DWARF file.  */
   10227             :           Dwarf_CU *cu;
   10228             :           uint8_t unit_type;
   10229           4 :           if (dwarf_get_units (dbg, NULL, &cu, NULL, &unit_type,
   10230             :                                NULL, NULL) != 0)
   10231             :             {
   10232           0 :               error (0, 0, "Warning: Cannot find any DWARF unit.");
   10233             :               /* Just guess some values.  */
   10234           0 :               has_header = false;
   10235           0 :               offset_size = 4;
   10236             :             }
   10237           4 :           else if (off == 0
   10238           4 :                    && (unit_type == DW_UT_split_type
   10239           4 :                        || unit_type == DW_UT_split_compile))
   10240             :             {
   10241           4 :               has_header = cu->version > 4;
   10242           4 :               offset_size = cu->offset_size;
   10243             :             }
   10244             :           else
   10245             :             {
   10246           0 :               error (0, 0,
   10247             :                      "Warning: No CU references .debug_str_offsets after %"
   10248             :                      PRIx64, off);
   10249           0 :               has_header = cu->version > 4;
   10250           0 :               offset_size = cu->offset_size;
   10251             :             }
   10252           4 :           printf ("\n");
   10253             :         }
   10254             :       else
   10255             :         {
   10256             :           /* This must be DWARF5, since GNU DebugFission didn't define
   10257             :              DW_AT_str_offsets_base.  */
   10258           0 :           has_header = true;
   10259             : 
   10260             :           Dwarf_Die cudie;
   10261           0 :           if (dwarf_cu_die (listptr->cu, &cudie,
   10262             :                             NULL, NULL, NULL, NULL,
   10263             :                             NULL, NULL) == NULL)
   10264           0 :             printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
   10265             :           else
   10266           0 :             printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
   10267             :         }
   10268             : 
   10269           4 :       if (has_header)
   10270             :         {
   10271             :           uint64_t unit_length;
   10272             :           uint16_t version;
   10273             :           uint16_t padding;
   10274             : 
   10275           2 :           unit_length = read_4ubyte_unaligned_inc (dbg, readp);
   10276           2 :           if (unlikely (unit_length == 0xffffffff))
   10277             :             {
   10278           0 :               if (unlikely (readp > readendp - 8))
   10279             :                 {
   10280           0 :                 invalid_data:
   10281             :                   error (0, 0, "Invalid data");
   10282             :                   return;
   10283             :                 }
   10284           0 :               unit_length = read_8ubyte_unaligned_inc (dbg, readp);
   10285           0 :               offset_size = 8;
   10286             :             }
   10287             :           else
   10288             :             offset_size = 4;
   10289             : 
   10290           2 :           printf ("\n");
   10291           4 :           printf (gettext (" Length:        %8" PRIu64 "\n"),
   10292             :                   unit_length);
   10293           4 :           printf (gettext (" Offset size:   %8" PRIu8 "\n"),
   10294             :                   offset_size);
   10295             : 
   10296             :           /* We need at least 2-bytes (version) + 2-bytes (padding) =
   10297             :              4 bytes to complete the header.  And this unit cannot go
   10298             :              beyond the section data.  */
   10299           2 :           if (readp > readendp - 4
   10300           2 :               || unit_length < 4
   10301           2 :               || unit_length > (uint64_t) (readendp - readp))
   10302             :             goto invalid_data;
   10303             : 
   10304           2 :           next_unitp = readp + unit_length;
   10305             : 
   10306           2 :           version = read_2ubyte_unaligned_inc (dbg, readp);
   10307           4 :           printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
   10308             : 
   10309           2 :           if (version != 5)
   10310             :             {
   10311           0 :               error (0, 0, gettext ("Unknown version"));
   10312             :               goto next_unit;
   10313             :             }
   10314             : 
   10315           2 :           padding = read_2ubyte_unaligned_inc (dbg, readp);
   10316           4 :           printf (gettext (" Padding:       %8" PRIx16 "\n"), padding);
   10317             : 
   10318           2 :           if (listptr != NULL
   10319           0 :               && listptr->offset != (Dwarf_Off) (readp - start))
   10320             :             {
   10321             :               error (0, 0, "String offsets index doesn't start after header");
   10322             :               goto next_unit;
   10323             :             }
   10324             : 
   10325             :           printf ("\n");
   10326             :         }
   10327             : 
   10328           4 :       int digits = 1;
   10329           4 :       size_t offsets = (next_unitp - readp) / offset_size;
   10330          12 :       while (offsets >= 10)
   10331             :         {
   10332           4 :           ++digits;
   10333           4 :           offsets /= 10;
   10334             :         }
   10335             : 
   10336           4 :       unsigned int uidx = 0;
   10337           4 :       size_t index_offset =  readp - (const unsigned char *) data->d_buf;
   10338             :       printf (" Offsets start at 0x%zx:\n", index_offset);
   10339          64 :       while (readp <= next_unitp - offset_size)
   10340             :         {
   10341             :           Dwarf_Word offset;
   10342          60 :           if (offset_size == 4)
   10343          60 :             offset = read_4ubyte_unaligned_inc (dbg, readp);
   10344             :           else
   10345           0 :             offset = read_8ubyte_unaligned_inc (dbg, readp);
   10346          60 :           const char *str = dwarf_getstring (dbg, offset, NULL);
   10347         120 :           printf (" [%*u] [%*" PRIx64 "]  \"%s\"\n",
   10348          60 :                   digits, uidx++, (int) offset_size * 2, offset, str ?: "???");
   10349             :         }
   10350           4 :       printf ("\n");
   10351             : 
   10352           4 :       if (readp != next_unitp)
   10353           0 :         error (0, 0, "extra %zd bytes at end of unit",
   10354           0 :                (size_t) (next_unitp - readp));
   10355             : 
   10356           4 :     next_unit:
   10357             :       readp = next_unitp;
   10358             :     }
   10359             : }
   10360             : 
   10361             : 
   10362             : /* Print the content of the call frame search table section
   10363             :    '.eh_frame_hdr'.  */
   10364             : static void
   10365          14 : print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10366             :                                Ebl *ebl __attribute__ ((unused)),
   10367             :                                GElf_Ehdr *ehdr __attribute__ ((unused)),
   10368             :                                Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   10369             : {
   10370          28 :   printf (gettext ("\
   10371             : \nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
   10372             :           elf_ndxscn (scn));
   10373             : 
   10374          14 :   Elf_Data *data = elf_rawdata (scn, NULL);
   10375             : 
   10376          14 :   if (unlikely (data == NULL))
   10377             :     {
   10378           0 :       error (0, 0, gettext ("cannot get %s content: %s"),
   10379             :              ".eh_frame_hdr", elf_errmsg (-1));
   10380           0 :       return;
   10381             :     }
   10382             : 
   10383          14 :   const unsigned char *readp = data->d_buf;
   10384          14 :   const unsigned char *const dataend = ((unsigned char *) data->d_buf
   10385          14 :                                         + data->d_size);
   10386             : 
   10387          14 :   if (unlikely (readp + 4 > dataend))
   10388             :     {
   10389           0 :     invalid_data:
   10390           0 :       error (0, 0, gettext ("invalid data"));
   10391             :       return;
   10392             :     }
   10393             : 
   10394          14 :   unsigned int version = *readp++;
   10395          14 :   unsigned int eh_frame_ptr_enc = *readp++;
   10396          14 :   unsigned int fde_count_enc = *readp++;
   10397          14 :   unsigned int table_enc = *readp++;
   10398             : 
   10399          14 :   printf (" version:          %u\n"
   10400             :           " eh_frame_ptr_enc: %#x ",
   10401             :           version, eh_frame_ptr_enc);
   10402          14 :   print_encoding_base ("", eh_frame_ptr_enc);
   10403          14 :   printf (" fde_count_enc:    %#x ", fde_count_enc);
   10404          14 :   print_encoding_base ("", fde_count_enc);
   10405          14 :   printf (" table_enc:        %#x ", table_enc);
   10406          14 :   print_encoding_base ("", table_enc);
   10407             : 
   10408          14 :   uint64_t eh_frame_ptr = 0;
   10409          14 :   if (eh_frame_ptr_enc != DW_EH_PE_omit)
   10410             :     {
   10411          14 :       readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
   10412             :                             dbg);
   10413          14 :       if (unlikely (readp == NULL))
   10414             :         goto invalid_data;
   10415             : 
   10416          28 :       printf (" eh_frame_ptr:     %#" PRIx64, eh_frame_ptr);
   10417          14 :       if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
   10418          14 :         printf (" (offset: %#" PRIx64 ")",
   10419             :                 /* +4 because of the 4 byte header of the section.  */
   10420          14 :                 (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
   10421             : 
   10422             :       putchar_unlocked ('\n');
   10423             :     }
   10424             : 
   10425          14 :   uint64_t fde_count = 0;
   10426          14 :   if (fde_count_enc != DW_EH_PE_omit)
   10427             :     {
   10428          14 :       readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
   10429          14 :       if (unlikely (readp == NULL))
   10430             :         goto invalid_data;
   10431             : 
   10432          14 :       printf (" fde_count:        %" PRIu64 "\n", fde_count);
   10433             :     }
   10434             : 
   10435          14 :   if (fde_count == 0 || table_enc == DW_EH_PE_omit)
   10436             :     return;
   10437             : 
   10438          14 :   puts (" Table:");
   10439             : 
   10440             :   /* Optimize for the most common case.  */
   10441          14 :   if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
   10442        4420 :     while (fde_count > 0 && readp + 8 <= dataend)
   10443             :       {
   10444        4406 :         int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
   10445        8812 :         uint64_t initial_offset = ((uint64_t) shdr->sh_offset
   10446        4406 :                                    + (int64_t) initial_location);
   10447        4406 :         int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
   10448             :         // XXX Possibly print symbol name or section offset for initial_offset
   10449        4406 :         printf ("  %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
   10450             :                 " fde=[%6" PRIx64 "]\n",
   10451             :                 initial_location, initial_offset,
   10452        4406 :                 address, address - (eh_frame_ptr + 4));
   10453             :       }
   10454             :   else
   10455             :     while (0 && readp < dataend)
   10456             :       {
   10457             : 
   10458             :       }
   10459             : }
   10460             : 
   10461             : 
   10462             : /* Print the content of the exception handling table section
   10463             :    '.eh_frame_hdr'.  */
   10464             : static void
   10465           0 : print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10466             :                              Ebl *ebl __attribute__ ((unused)),
   10467             :                              GElf_Ehdr *ehdr __attribute__ ((unused)),
   10468             :                              Elf_Scn *scn,
   10469             :                              GElf_Shdr *shdr __attribute__ ((unused)),
   10470             :                              Dwarf *dbg __attribute__ ((unused)))
   10471             : {
   10472           0 :   printf (gettext ("\
   10473             : \nException handling table section [%2zu] '.gcc_except_table':\n"),
   10474             :           elf_ndxscn (scn));
   10475             : 
   10476           0 :   Elf_Data *data = elf_rawdata (scn, NULL);
   10477             : 
   10478           0 :   if (unlikely (data == NULL))
   10479             :     {
   10480           0 :       error (0, 0, gettext ("cannot get %s content: %s"),
   10481             :              ".gcc_except_table", elf_errmsg (-1));
   10482           0 :       return;
   10483             :     }
   10484             : 
   10485           0 :   const unsigned char *readp = data->d_buf;
   10486           0 :   const unsigned char *const dataend = readp + data->d_size;
   10487             : 
   10488           0 :   if (unlikely (readp + 1 > dataend))
   10489             :     {
   10490           0 :     invalid_data:
   10491           0 :       error (0, 0, gettext ("invalid data"));
   10492             :       return;
   10493             :     }
   10494           0 :   unsigned int lpstart_encoding = *readp++;
   10495           0 :   printf (gettext (" LPStart encoding:    %#x "), lpstart_encoding);
   10496           0 :   print_encoding_base ("", lpstart_encoding);
   10497           0 :   if (lpstart_encoding != DW_EH_PE_omit)
   10498             :     {
   10499             :       uint64_t lpstart;
   10500           0 :       readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
   10501           0 :       printf (" LPStart:             %#" PRIx64 "\n", lpstart);
   10502             :     }
   10503             : 
   10504           0 :   if (unlikely (readp + 1 > dataend))
   10505             :     goto invalid_data;
   10506           0 :   unsigned int ttype_encoding = *readp++;
   10507           0 :   printf (gettext (" TType encoding:      %#x "), ttype_encoding);
   10508           0 :   print_encoding_base ("", ttype_encoding);
   10509           0 :   const unsigned char *ttype_base = NULL;
   10510           0 :   if (ttype_encoding != DW_EH_PE_omit)
   10511             :     {
   10512             :       unsigned int ttype_base_offset;
   10513           0 :       get_uleb128 (ttype_base_offset, readp, dataend);
   10514           0 :       printf (" TType base offset:   %#x\n", ttype_base_offset);
   10515           0 :       if ((size_t) (dataend - readp) > ttype_base_offset)
   10516           0 :         ttype_base = readp + ttype_base_offset;
   10517             :     }
   10518             : 
   10519           0 :   if (unlikely (readp + 1 > dataend))
   10520             :     goto invalid_data;
   10521           0 :   unsigned int call_site_encoding = *readp++;
   10522           0 :   printf (gettext (" Call site encoding:  %#x "), call_site_encoding);
   10523           0 :   print_encoding_base ("", call_site_encoding);
   10524             :   unsigned int call_site_table_len;
   10525           0 :   get_uleb128 (call_site_table_len, readp, dataend);
   10526             : 
   10527           0 :   const unsigned char *const action_table = readp + call_site_table_len;
   10528           0 :   if (unlikely (action_table > dataend))
   10529             :     goto invalid_data;
   10530             :   unsigned int u = 0;
   10531             :   unsigned int max_action = 0;
   10532           0 :   while (readp < action_table)
   10533             :     {
   10534           0 :       if (u == 0)
   10535           0 :         puts (gettext ("\n Call site table:"));
   10536             : 
   10537             :       uint64_t call_site_start;
   10538           0 :       readp = read_encoded (call_site_encoding, readp, dataend,
   10539             :                             &call_site_start, dbg);
   10540             :       uint64_t call_site_length;
   10541           0 :       readp = read_encoded (call_site_encoding, readp, dataend,
   10542             :                             &call_site_length, dbg);
   10543             :       uint64_t landing_pad;
   10544           0 :       readp = read_encoded (call_site_encoding, readp, dataend,
   10545             :                             &landing_pad, dbg);
   10546             :       unsigned int action;
   10547           0 :       get_uleb128 (action, readp, dataend);
   10548           0 :       max_action = MAX (action, max_action);
   10549           0 :       printf (gettext (" [%4u] Call site start:   %#" PRIx64 "\n"
   10550             :                        "        Call site length:  %" PRIu64 "\n"
   10551             :                        "        Landing pad:       %#" PRIx64 "\n"
   10552             :                        "        Action:            %u\n"),
   10553             :               u++, call_site_start, call_site_length, landing_pad, action);
   10554             :     }
   10555           0 :   if (readp != action_table)
   10556             :     goto invalid_data;
   10557             : 
   10558           0 :   unsigned int max_ar_filter = 0;
   10559           0 :   if (max_action > 0)
   10560             :     {
   10561           0 :       puts ("\n Action table:");
   10562             : 
   10563           0 :       size_t maxdata = (size_t) (dataend - action_table);
   10564           0 :       if (max_action > maxdata || maxdata - max_action < 1)
   10565             :         {
   10566           0 :         invalid_action_table:
   10567           0 :           fputs (gettext ("   <INVALID DATA>\n"), stdout);
   10568           0 :           return;
   10569             :         }
   10570             : 
   10571           0 :       const unsigned char *const action_table_end
   10572           0 :         = action_table + max_action + 1;
   10573             : 
   10574           0 :       u = 0;
   10575             :       do
   10576             :         {
   10577             :           int ar_filter;
   10578           0 :           get_sleb128 (ar_filter, readp, action_table_end);
   10579           0 :           if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
   10580           0 :             max_ar_filter = ar_filter;
   10581             :           int ar_disp;
   10582           0 :           if (readp >= action_table_end)
   10583             :             goto invalid_action_table;
   10584           0 :           get_sleb128 (ar_disp, readp, action_table_end);
   10585             : 
   10586           0 :           printf (" [%4u] ar_filter:  % d\n"
   10587             :                   "        ar_disp:    % -5d",
   10588             :                   u, ar_filter, ar_disp);
   10589           0 :           if (abs (ar_disp) & 1)
   10590           0 :             printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
   10591           0 :           else if (ar_disp != 0)
   10592           0 :             puts (" -> ???");
   10593             :           else
   10594             :             putchar_unlocked ('\n');
   10595           0 :           ++u;
   10596             :         }
   10597           0 :       while (readp < action_table_end);
   10598             :     }
   10599             : 
   10600           0 :   if (max_ar_filter > 0 && ttype_base != NULL)
   10601             :     {
   10602             :       unsigned char dsize;
   10603           0 :       puts ("\n TType table:");
   10604             : 
   10605             :       // XXX Not *4, size of encoding;
   10606             :       switch (ttype_encoding & 7)
   10607             :         {
   10608             :         case DW_EH_PE_udata2:
   10609             :         case DW_EH_PE_sdata2:
   10610             :           dsize = 2;
   10611             :           break;
   10612             :         case DW_EH_PE_udata4:
   10613             :         case DW_EH_PE_sdata4:
   10614             :           dsize = 4;
   10615             :           break;
   10616             :         case DW_EH_PE_udata8:
   10617             :         case DW_EH_PE_sdata8:
   10618             :           dsize = 8;
   10619             :           break;
   10620           0 :         default:
   10621           0 :           dsize = 0;
   10622           0 :           error (1, 0, gettext ("invalid TType encoding"));
   10623             :         }
   10624             : 
   10625           0 :       if (max_ar_filter
   10626           0 :           > (size_t) (ttype_base - (const unsigned char *) data->d_buf) / dsize)
   10627             :         goto invalid_data;
   10628             : 
   10629           0 :       readp = ttype_base - max_ar_filter * dsize;
   10630             :       do
   10631             :         {
   10632             :           uint64_t ttype;
   10633           0 :           readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
   10634             :                                 dbg);
   10635           0 :           printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
   10636             :         }
   10637           0 :       while (readp < ttype_base);
   10638             :     }
   10639             : }
   10640             : 
   10641             : /* Print the content of the '.gdb_index' section.
   10642             :    http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
   10643             : */
   10644             : static void
   10645           2 : print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
   10646             :                          GElf_Ehdr *ehdr __attribute__ ((unused)),
   10647             :                          Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   10648             : {
   10649           4 :   printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
   10650             :                    " contains %" PRId64 " bytes :\n"),
   10651             :           elf_ndxscn (scn), section_name (ebl, shdr),
   10652           2 :           (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
   10653             : 
   10654           2 :   Elf_Data *data = elf_rawdata (scn, NULL);
   10655             : 
   10656           2 :   if (unlikely (data == NULL))
   10657             :     {
   10658           0 :       error (0, 0, gettext ("cannot get %s content: %s"),
   10659             :              ".gdb_index", elf_errmsg (-1));
   10660           0 :       return;
   10661             :     }
   10662             : 
   10663             :   // .gdb_index is always in little endian.
   10664           2 :   Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
   10665           2 :   dbg = &dummy_dbg;
   10666             : 
   10667           2 :   const unsigned char *readp = data->d_buf;
   10668           2 :   const unsigned char *const dataend = readp + data->d_size;
   10669             : 
   10670           2 :   if (unlikely (readp + 4 > dataend))
   10671             :     {
   10672           0 :     invalid_data:
   10673           0 :       error (0, 0, gettext ("invalid data"));
   10674             :       return;
   10675             :     }
   10676             : 
   10677           2 :   int32_t vers = read_4ubyte_unaligned (dbg, readp);
   10678           4 :   printf (gettext (" Version:         %" PRId32 "\n"), vers);
   10679             : 
   10680             :   // The only difference between version 4 and version 5 is the
   10681             :   // hash used for generating the table.  Version 6 contains symbols
   10682             :   // for inlined functions, older versions didn't.  Version 7 adds
   10683             :   // symbol kinds.  Version 8 just indicates that it correctly includes
   10684             :   // TUs for symbols.
   10685           2 :   if (vers < 4 || vers > 8)
   10686             :     {
   10687           0 :       printf (gettext ("  unknown version, cannot parse section\n"));
   10688             :       return;
   10689             :     }
   10690             : 
   10691           2 :   readp += 4;
   10692           2 :   if (unlikely (readp + 4 > dataend))
   10693             :     goto invalid_data;
   10694             : 
   10695           2 :   uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
   10696           4 :   printf (gettext (" CU offset:       %#" PRIx32 "\n"), cu_off);
   10697             : 
   10698           2 :   readp += 4;
   10699           2 :   if (unlikely (readp + 4 > dataend))
   10700             :     goto invalid_data;
   10701             : 
   10702           2 :   uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
   10703           4 :   printf (gettext (" TU offset:       %#" PRIx32 "\n"), tu_off);
   10704             : 
   10705           2 :   readp += 4;
   10706           2 :   if (unlikely (readp + 4 > dataend))
   10707             :     goto invalid_data;
   10708             : 
   10709           2 :   uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
   10710           4 :   printf (gettext (" address offset:  %#" PRIx32 "\n"), addr_off);
   10711             : 
   10712           2 :   readp += 4;
   10713           2 :   if (unlikely (readp + 4 > dataend))
   10714             :     goto invalid_data;
   10715             : 
   10716           2 :   uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
   10717           4 :   printf (gettext (" symbol offset:   %#" PRIx32 "\n"), sym_off);
   10718             : 
   10719           2 :   readp += 4;
   10720           2 :   if (unlikely (readp + 4 > dataend))
   10721             :     goto invalid_data;
   10722             : 
   10723           2 :   uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
   10724           4 :   printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
   10725             : 
   10726           2 :   if (unlikely ((size_t) (dataend - (const unsigned char *) data->d_buf)
   10727             :                 < const_off))
   10728             :     goto invalid_data;
   10729             : 
   10730           2 :   readp = data->d_buf + cu_off;
   10731             : 
   10732           2 :   const unsigned char *nextp = data->d_buf + tu_off;
   10733           2 :   if (tu_off >= data->d_size)
   10734             :     goto invalid_data;
   10735             : 
   10736           2 :   size_t cu_nr = (nextp - readp) / 16;
   10737             : 
   10738           4 :   printf (gettext ("\n CU list at offset %#" PRIx32
   10739             :                    " contains %zu entries:\n"),
   10740             :           cu_off, cu_nr);
   10741             : 
   10742           2 :   size_t n = 0;
   10743           8 :   while (dataend - readp >= 16 && n < cu_nr)
   10744             :     {
   10745           4 :       uint64_t off = read_8ubyte_unaligned (dbg, readp);
   10746           4 :       readp += 8;
   10747             : 
   10748           4 :       uint64_t len = read_8ubyte_unaligned (dbg, readp);
   10749           4 :       readp += 8;
   10750             : 
   10751           4 :       printf (" [%4zu] start: %0#8" PRIx64
   10752             :               ", length: %5" PRIu64 "\n", n, off, len);
   10753           4 :       n++;
   10754             :     }
   10755             : 
   10756           2 :   readp = data->d_buf + tu_off;
   10757           2 :   nextp = data->d_buf + addr_off;
   10758           2 :   if (addr_off >= data->d_size)
   10759             :     goto invalid_data;
   10760             : 
   10761           2 :   size_t tu_nr = (nextp - readp) / 24;
   10762             : 
   10763           4 :   printf (gettext ("\n TU list at offset %#" PRIx32
   10764             :                    " contains %zu entries:\n"),
   10765             :           tu_off, tu_nr);
   10766             : 
   10767           2 :   n = 0;
   10768           6 :   while (dataend - readp >= 24 && n < tu_nr)
   10769             :     {
   10770           2 :       uint64_t off = read_8ubyte_unaligned (dbg, readp);
   10771           2 :       readp += 8;
   10772             : 
   10773           2 :       uint64_t type = read_8ubyte_unaligned (dbg, readp);
   10774           2 :       readp += 8;
   10775             : 
   10776           2 :       uint64_t sig = read_8ubyte_unaligned (dbg, readp);
   10777           2 :       readp += 8;
   10778             : 
   10779           2 :       printf (" [%4zu] CU offset: %5" PRId64
   10780             :               ", type offset: %5" PRId64
   10781             :               ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
   10782           2 :       n++;
   10783             :     }
   10784             : 
   10785           2 :   readp = data->d_buf + addr_off;
   10786           2 :   nextp = data->d_buf + sym_off;
   10787           2 :   if (sym_off >= data->d_size)
   10788             :     goto invalid_data;
   10789             : 
   10790           2 :   size_t addr_nr = (nextp - readp) / 20;
   10791             : 
   10792           4 :   printf (gettext ("\n Address list at offset %#" PRIx32
   10793             :                    " contains %zu entries:\n"),
   10794             :           addr_off, addr_nr);
   10795             : 
   10796           2 :   n = 0;
   10797           8 :   while (dataend - readp >= 20 && n < addr_nr)
   10798             :     {
   10799           4 :       uint64_t low = read_8ubyte_unaligned (dbg, readp);
   10800           4 :       readp += 8;
   10801             : 
   10802           4 :       uint64_t high = read_8ubyte_unaligned (dbg, readp);
   10803           4 :       readp += 8;
   10804             : 
   10805           4 :       uint32_t idx = read_4ubyte_unaligned (dbg, readp);
   10806           4 :       readp += 4;
   10807             : 
   10808           4 :       printf (" [%4zu] ", n);
   10809           4 :       print_dwarf_addr (dwflmod, 8, low, low);
   10810           4 :       printf ("..");
   10811           4 :       print_dwarf_addr (dwflmod, 8, high - 1, high);
   10812           4 :       printf (", CU index: %5" PRId32 "\n", idx);
   10813           4 :       n++;
   10814             :     }
   10815             : 
   10816           2 :   const unsigned char *const_start = data->d_buf + const_off;
   10817           2 :   if (const_off >= data->d_size)
   10818             :     goto invalid_data;
   10819             : 
   10820           2 :   readp = data->d_buf + sym_off;
   10821           2 :   nextp = const_start;
   10822           2 :   size_t sym_nr = (nextp - readp) / 8;
   10823             : 
   10824           4 :   printf (gettext ("\n Symbol table at offset %#" PRIx32
   10825             :                    " contains %zu slots:\n"),
   10826             :           addr_off, sym_nr);
   10827             : 
   10828           2 :   n = 0;
   10829        2052 :   while (dataend - readp >= 8 && n < sym_nr)
   10830             :     {
   10831        2048 :       uint32_t name = read_4ubyte_unaligned (dbg, readp);
   10832        2048 :       readp += 4;
   10833             : 
   10834        2048 :       uint32_t vector = read_4ubyte_unaligned (dbg, readp);
   10835        2048 :       readp += 4;
   10836             : 
   10837        2048 :       if (name != 0 || vector != 0)
   10838             :         {
   10839          14 :           const unsigned char *sym = const_start + name;
   10840          28 :           if (unlikely ((size_t) (dataend - const_start) < name
   10841             :                         || memchr (sym, '\0', dataend - sym) == NULL))
   10842             :             goto invalid_data;
   10843             : 
   10844          14 :           printf (" [%4zu] symbol: %s, CUs: ", n, sym);
   10845             : 
   10846          14 :           const unsigned char *readcus = const_start + vector;
   10847          14 :           if (unlikely ((size_t) (dataend - const_start) < vector))
   10848             :             goto invalid_data;
   10849          14 :           uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
   10850          44 :           while (cus--)
   10851             :             {
   10852             :               uint32_t cu_kind, cu, kind;
   10853             :               bool is_static;
   10854          16 :               readcus += 4;
   10855          16 :               if (unlikely (readcus + 4 > dataend))
   10856             :                 goto invalid_data;
   10857          16 :               cu_kind = read_4ubyte_unaligned (dbg, readcus);
   10858          16 :               cu = cu_kind & ((1 << 24) - 1);
   10859          16 :               kind = (cu_kind >> 28) & 7;
   10860          16 :               is_static = cu_kind & (1U << 31);
   10861          16 :               if (cu > cu_nr - 1)
   10862           2 :                 printf ("%" PRId32 "T", cu - (uint32_t) cu_nr);
   10863             :               else
   10864             :                 printf ("%" PRId32, cu);
   10865          16 :               if (kind != 0)
   10866             :                 {
   10867           8 :                   printf (" (");
   10868           8 :                   switch (kind)
   10869             :                     {
   10870           3 :                     case 1:
   10871             :                       printf ("type");
   10872             :                       break;
   10873           2 :                     case 2:
   10874             :                       printf ("var");
   10875             :                       break;
   10876           3 :                     case 3:
   10877             :                       printf ("func");
   10878             :                       break;
   10879           0 :                     case 4:
   10880             :                       printf ("other");
   10881             :                       break;
   10882           0 :                     default:
   10883             :                       printf ("unknown-0x%" PRIx32, kind);
   10884             :                       break;
   10885             :                     }
   10886           8 :                   printf (":%c)", (is_static ? 'S' : 'G'));
   10887             :                 }
   10888          16 :               if (cus > 0)
   10889             :                 printf (", ");
   10890             :             }
   10891             :           printf ("\n");
   10892             :         }
   10893        2048 :       n++;
   10894             :     }
   10895             : }
   10896             : 
   10897             : /* Returns true and sets split DWARF CU id if there is a split compile
   10898             :    unit in the given Dwarf, and no non-split units are found (before it).  */
   10899             : static bool
   10900         117 : is_split_dwarf (Dwarf *dbg, uint64_t *id, Dwarf_CU **split_cu)
   10901             : {
   10902         117 :   Dwarf_CU *cu = NULL;
   10903         234 :   while (dwarf_get_units (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
   10904             :     {
   10905             :       uint8_t unit_type;
   10906         117 :       if (dwarf_cu_info (cu, NULL, &unit_type, NULL, NULL,
   10907             :                          id, NULL, NULL) != 0)
   10908         117 :         return false;
   10909             : 
   10910         117 :       if (unit_type != DW_UT_split_compile && unit_type != DW_UT_split_type)
   10911             :         return false;
   10912             : 
   10913             :       /* We really only care about the split compile unit, the types
   10914             :          should be fine and self sufficient.  Also they don't have an
   10915             :          id that we can match with a skeleton unit.  */
   10916           9 :       if (unit_type == DW_UT_split_compile)
   10917             :         {
   10918           9 :           *split_cu = cu;
   10919           9 :           return true;
   10920             :         }
   10921             :     }
   10922             : 
   10923             :   return false;
   10924             : }
   10925             : 
   10926             : /* Check that there is one and only one Dwfl_Module, return in arg.  */
   10927             : static int
   10928           9 : getone_dwflmod (Dwfl_Module *dwflmod,
   10929             :                void **userdata __attribute__ ((unused)),
   10930             :                const char *name __attribute__ ((unused)),
   10931             :                Dwarf_Addr base __attribute__ ((unused)),
   10932             :                void *arg)
   10933             : {
   10934           9 :   Dwfl_Module **m = (Dwfl_Module **) arg;
   10935           9 :   if (*m != NULL)
   10936             :     return DWARF_CB_ABORT;
   10937           9 :   *m = dwflmod;
   10938           9 :   return DWARF_CB_OK;
   10939             : }
   10940             : 
   10941             : static void
   10942         145 : print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
   10943             : {
   10944             :   /* Used for skeleton file, if necessary for split DWARF.  */
   10945         145 :   Dwfl *skel_dwfl = NULL;
   10946         145 :   Dwfl_Module *skel_mod = NULL;
   10947         145 :   char *skel_name = NULL;
   10948         145 :   Dwarf *split_dbg = NULL;
   10949         145 :   Dwarf_CU *split_cu = NULL;
   10950             : 
   10951             :   /* Before we start the real work get a debug context descriptor.  */
   10952             :   Dwarf_Addr dwbias;
   10953         145 :   Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
   10954         435 :   Dwarf dummy_dbg =
   10955             :     {
   10956         145 :       .elf = ebl->elf,
   10957         145 :       .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
   10958             :     };
   10959         145 :   if (dbg == NULL)
   10960             :     {
   10961          28 :       if ((print_debug_sections & ~section_exception) != 0)
   10962           0 :         error (0, 0, gettext ("cannot get debug context descriptor: %s"),
   10963             :                dwfl_errmsg (-1));
   10964             :       dbg = &dummy_dbg;
   10965             :     }
   10966             :   else
   10967             :     {
   10968             :       /* If we are asked about a split dwarf (.dwo) file, use the user
   10969             :          provided, or find the corresponding skeleton file. If we got
   10970             :          a skeleton file, replace the given dwflmod and dbg, with one
   10971             :          derived from the skeleton file to provide enough context.  */
   10972             :       uint64_t split_id;
   10973         117 :       if (is_split_dwarf (dbg, &split_id, &split_cu))
   10974             :         {
   10975           9 :           if (dwarf_skeleton != NULL)
   10976           9 :             skel_name = strdup (dwarf_skeleton);
   10977             :           else
   10978             :             {
   10979             :               /* Replace file.dwo with file.o and see if that matches. */
   10980             :               const char *fname;
   10981           0 :               dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL,
   10982             :                                 &fname, NULL);
   10983           0 :               if (fname != NULL)
   10984             :                 {
   10985           0 :                   size_t flen = strlen (fname);
   10986           0 :                   if (flen > 4 && strcmp (".dwo", fname + flen - 4) == 0)
   10987             :                     {
   10988           0 :                       skel_name = strdup (fname);
   10989           0 :                       if (skel_name != NULL)
   10990             :                         {
   10991           0 :                           skel_name[flen - 3] = 'o';
   10992           0 :                           skel_name[flen - 2] = '\0';
   10993             :                         }
   10994             :                     }
   10995             :                 }
   10996             :             }
   10997             : 
   10998           9 :           if (skel_name != NULL)
   10999             :             {
   11000           9 :               int skel_fd = open (skel_name, O_RDONLY);
   11001           9 :               if (skel_fd == -1)
   11002           0 :                 fprintf (stderr, "Warning: Couldn't open DWARF skeleton file"
   11003             :                          " '%s'\n", skel_name);
   11004             :               else
   11005           9 :                 skel_dwfl = create_dwfl (skel_fd, skel_name);
   11006             : 
   11007           9 :               if (skel_dwfl != NULL)
   11008             :                 {
   11009           9 :                   if (dwfl_getmodules (skel_dwfl, &getone_dwflmod,
   11010             :                                        &skel_mod, 0) != 0)
   11011             :                     {
   11012           0 :                       fprintf (stderr, "Warning: Bad DWARF skeleton,"
   11013             :                                " multiple modules '%s'\n", skel_name);
   11014           0 :                       dwfl_end (skel_dwfl);
   11015           0 :                       skel_mod = NULL;
   11016             :                     }
   11017             :                 }
   11018           0 :               else if (skel_fd != -1)
   11019           0 :                 fprintf (stderr, "Warning: Couldn't create skeleton dwfl for"
   11020             :                          " '%s': %s\n", skel_name, dwfl_errmsg (-1));
   11021             : 
   11022           9 :               if (skel_mod != NULL)
   11023             :                 {
   11024           9 :                   Dwarf *skel_dbg = dwfl_module_getdwarf (skel_mod, &dwbias);
   11025           9 :                   if (skel_dbg != NULL)
   11026             :                     {
   11027             :                       /* First check the skeleton CU DIE, only fetch
   11028             :                          the split DIE if we know the id matches to
   11029             :                          not unnecessary search for any split DIEs we
   11030             :                          don't need. */
   11031           9 :                       Dwarf_CU *cu = NULL;
   11032          22 :                       while (dwarf_get_units (skel_dbg, cu, &cu,
   11033             :                                               NULL, NULL, NULL, NULL) == 0)
   11034             :                         {
   11035             :                           uint8_t unit_type;
   11036             :                           uint64_t skel_id;
   11037          13 :                           if (dwarf_cu_info (cu, NULL, &unit_type, NULL, NULL,
   11038             :                                              &skel_id, NULL, NULL) == 0
   11039          13 :                               && unit_type == DW_UT_skeleton
   11040          13 :                               && split_id == skel_id)
   11041             :                             {
   11042             :                               Dwarf_Die subdie;
   11043           9 :                               if (dwarf_cu_info (cu, NULL, NULL, NULL,
   11044             :                                                  &subdie,
   11045             :                                                  NULL, NULL, NULL) == 0
   11046           9 :                                   && dwarf_tag (&subdie) != DW_TAG_invalid)
   11047             :                                 {
   11048           9 :                                   split_dbg = dwarf_cu_getdwarf (subdie.cu);
   11049           9 :                                   if (split_dbg == NULL)
   11050           0 :                                     fprintf (stderr,
   11051             :                                              "Warning: Couldn't get split_dbg:"
   11052             :                                              " %s\n", dwarf_errmsg (-1));
   11053           9 :                                   break;
   11054             :                                 }
   11055             :                               else
   11056             :                                 {
   11057             :                                   /* Everything matches up, but not
   11058             :                                      according to libdw. Which means
   11059             :                                      the user knew better.  So...
   11060             :                                      Terrible hack... We can never
   11061             :                                      destroy the underlying dwfl
   11062             :                                      because it would free the wrong
   11063             :                                      Dwarfs... So we leak memory...*/
   11064           0 :                                   if (cu->split == NULL
   11065           0 :                                       && dwarf_skeleton != NULL)
   11066             :                                     {
   11067           0 :                                       do_not_close_dwfl = true;
   11068           0 :                                       __libdw_link_skel_split (cu, split_cu);
   11069           0 :                                       split_dbg = dwarf_cu_getdwarf (split_cu);
   11070           0 :                                       break;
   11071             :                                     }
   11072             :                                   else
   11073           0 :                                     fprintf (stderr, "Warning: Couldn't get"
   11074             :                                              " skeleton subdie: %s\n",
   11075             :                                              dwarf_errmsg (-1));
   11076             :                                 }
   11077             :                             }
   11078             :                         }
   11079           9 :                       if (split_dbg == NULL)
   11080           0 :                         fprintf (stderr, "Warning: '%s' didn't contain a skeleton for split id %" PRIx64 "\n", skel_name, split_id);
   11081             :                     }
   11082             :                   else
   11083           0 :                     fprintf (stderr, "Warning: Couldn't get skeleton DWARF:"
   11084             :                              " %s\n", dwfl_errmsg (-1));
   11085             :                 }
   11086             :             }
   11087             : 
   11088           9 :           if (split_dbg != NULL)
   11089             :             {
   11090           9 :               dbg = split_dbg;
   11091           9 :               dwflmod = skel_mod;
   11092             :             }
   11093           0 :           else if (skel_name == NULL)
   11094           0 :             fprintf (stderr,
   11095             :                      "Warning: split DWARF file, but no skeleton found.\n");
   11096             :         }
   11097         108 :       else if (dwarf_skeleton != NULL)
   11098           0 :         fprintf (stderr, "Warning: DWARF skeleton given,"
   11099             :                  " but not a split DWARF file\n");
   11100             :     }
   11101             : 
   11102             :   /* Get the section header string table index.  */
   11103             :   size_t shstrndx;
   11104         145 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   11105             :     error (EXIT_FAILURE, 0,
   11106           0 :            gettext ("cannot get section header string table index"));
   11107             : 
   11108             :   /* If the .debug_info section is listed as implicitly required then
   11109             :      we must make sure to handle it before handling any other debug
   11110             :      section.  Various other sections depend on the CU DIEs being
   11111             :      scanned (silently) first.  */
   11112         145 :   bool implicit_info = (implicit_debug_sections & section_info) != 0;
   11113         145 :   bool explicit_info = (print_debug_sections & section_info) != 0;
   11114         145 :   if (implicit_info)
   11115             :     {
   11116             :       Elf_Scn *scn = NULL;
   11117        1514 :       while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   11118             :         {
   11119             :           GElf_Shdr shdr_mem;
   11120        1514 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   11121             : 
   11122        1514 :           if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
   11123             :             {
   11124         620 :               const char *name = elf_strptr (ebl->elf, shstrndx,
   11125         620 :                                              shdr->sh_name);
   11126         620 :               if (name == NULL)
   11127           0 :                 continue;
   11128             : 
   11129         620 :               if (strcmp (name, ".debug_info") == 0
   11130         558 :                   || strcmp (name, ".debug_info.dwo") == 0
   11131         549 :                   || strcmp (name, ".zdebug_info") == 0
   11132         543 :                   || strcmp (name, ".zdebug_info.dwo") == 0)
   11133             :                 {
   11134          77 :                   print_debug_info_section (dwflmod, ebl, ehdr,
   11135             :                                             scn, shdr, dbg);
   11136          77 :                   break;
   11137             :                 }
   11138             :             }
   11139             :         }
   11140          77 :       print_debug_sections &= ~section_info;
   11141          77 :       implicit_debug_sections &= ~section_info;
   11142             :     }
   11143             : 
   11144             :   /* Look through all the sections for the debugging sections to print.  */
   11145             :   Elf_Scn *scn = NULL;
   11146        4398 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   11147             :     {
   11148             :       GElf_Shdr shdr_mem;
   11149        4253 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   11150             : 
   11151        4253 :       if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
   11152             :         {
   11153             :           static const struct
   11154             :           {
   11155             :             const char *name;
   11156             :             enum section_e bitmask;
   11157             :             void (*fp) (Dwfl_Module *, Ebl *,
   11158             :                         GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
   11159             :           } debug_sections[] =
   11160             :             {
   11161             : #define NEW_SECTION(name) \
   11162             :               { ".debug_" #name, section_##name, print_debug_##name##_section }
   11163             :               NEW_SECTION (abbrev),
   11164             :               NEW_SECTION (addr),
   11165             :               NEW_SECTION (aranges),
   11166             :               NEW_SECTION (frame),
   11167             :               NEW_SECTION (info),
   11168             :               NEW_SECTION (types),
   11169             :               NEW_SECTION (line),
   11170             :               NEW_SECTION (loc),
   11171             :               /* loclists is loc for DWARF5.  */
   11172             :               { ".debug_loclists", section_loc,
   11173             :                 print_debug_loclists_section },
   11174             :               NEW_SECTION (pubnames),
   11175             :               NEW_SECTION (str),
   11176             :               /* A DWARF5 specialised debug string section.  */
   11177             :               { ".debug_line_str", section_str,
   11178             :                 print_debug_str_section },
   11179             :               /* DWARF5 string offsets table.  */
   11180             :               { ".debug_str_offsets", section_str,
   11181             :                 print_debug_str_offsets_section },
   11182             :               NEW_SECTION (macinfo),
   11183             :               NEW_SECTION (macro),
   11184             :               NEW_SECTION (ranges),
   11185             :               /* rnglists is ranges for DWARF5.  */
   11186             :               { ".debug_rnglists", section_ranges,
   11187             :                 print_debug_rnglists_section },
   11188             :               { ".eh_frame", section_frame | section_exception,
   11189             :                 print_debug_frame_section },
   11190             :               { ".eh_frame_hdr", section_frame | section_exception,
   11191             :                 print_debug_frame_hdr_section },
   11192             :               { ".gcc_except_table", section_frame | section_exception,
   11193             :                 print_debug_exception_table },
   11194             :               { ".gdb_index", section_gdb_index, print_gdb_index_section }
   11195             :             };
   11196        2073 :           const int ndebug_sections = (sizeof (debug_sections)
   11197             :                                        / sizeof (debug_sections[0]));
   11198        2073 :           const char *name = elf_strptr (ebl->elf, shstrndx,
   11199        2073 :                                          shdr->sh_name);
   11200        2073 :           if (name == NULL)
   11201           0 :             continue;
   11202             : 
   11203             :           int n;
   11204       30604 :           for (n = 0; n < ndebug_sections; ++n)
   11205             :             {
   11206       31566 :               size_t dbglen = strlen (debug_sections[n].name);
   11207       31566 :               size_t scnlen = strlen (name);
   11208       31566 :               if ((strncmp (name, debug_sections[n].name, dbglen) == 0
   11209         964 :                    && (dbglen == scnlen
   11210         138 :                        || (scnlen == dbglen + 4
   11211         121 :                            && strstr (name, ".dwo") == name + dbglen)))
   11212       30686 :                   || (name[0] == '.' && name[1] == 'z'
   11213         566 :                       && debug_sections[n].name[1] == 'd'
   11214         566 :                       && strncmp (&name[2], &debug_sections[n].name[1],
   11215             :                                   dbglen - 1) == 0
   11216          82 :                       && (scnlen == dbglen + 1
   11217           0 :                           || (scnlen == dbglen + 5
   11218           0 :                               && strstr (name, ".dwo") == name + dbglen + 1))))
   11219             :                 {
   11220        1924 :                   if ((print_debug_sections | implicit_debug_sections)
   11221         962 :                       & debug_sections[n].bitmask)
   11222         357 :                     debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
   11223             :                   break;
   11224             :                 }
   11225             :             }
   11226             :         }
   11227             :     }
   11228             : 
   11229         145 :   dwfl_end (skel_dwfl);
   11230         145 :   free (skel_name);
   11231             : 
   11232             :   /* Turn implicit and/or explicit back on in case we go over another file.  */
   11233         145 :   if (implicit_info)
   11234          77 :     implicit_debug_sections |= section_info;
   11235         145 :   if (explicit_info)
   11236          59 :     print_debug_sections |= section_info;
   11237             : 
   11238         145 :   reset_listptr (&known_locsptr);
   11239         145 :   reset_listptr (&known_loclistsptr);
   11240         145 :   reset_listptr (&known_rangelistptr);
   11241         145 :   reset_listptr (&known_rnglistptr);
   11242         145 :   reset_listptr (&known_addrbases);
   11243         145 :   reset_listptr (&known_stroffbases);
   11244         145 : }
   11245             : 
   11246             : 
   11247             : #define ITEM_INDENT             4
   11248             : #define WRAP_COLUMN             75
   11249             : 
   11250             : /* Print "NAME: FORMAT", wrapping when output text would make the line
   11251             :    exceed WRAP_COLUMN.  Unpadded numbers look better for the core items
   11252             :    but this function is also used for registers which should be printed
   11253             :    aligned.  Fortunately registers output uses fixed fields width (such
   11254             :    as %11d) for the alignment.
   11255             : 
   11256             :    Line breaks should not depend on the particular values although that
   11257             :    may happen in some cases of the core items.  */
   11258             : 
   11259             : static unsigned int
   11260             : __attribute__ ((format (printf, 6, 7)))
   11261         821 : print_core_item (unsigned int colno, char sep, unsigned int wrap,
   11262             :                  size_t name_width, const char *name, const char *format, ...)
   11263             : {
   11264         821 :   size_t len = strlen (name);
   11265         821 :   if (name_width < len)
   11266         397 :     name_width = len;
   11267             : 
   11268             :   char *out;
   11269             :   va_list ap;
   11270         821 :   va_start (ap, format);
   11271         821 :   int out_len = vasprintf (&out, format, ap);
   11272         821 :   va_end (ap);
   11273         821 :   if (out_len == -1)
   11274           0 :     error (EXIT_FAILURE, 0, _("memory exhausted"));
   11275             : 
   11276         821 :   size_t n = name_width + sizeof ": " - 1 + out_len;
   11277             : 
   11278         821 :   if (colno == 0)
   11279             :     {
   11280          51 :       printf ("%*s", ITEM_INDENT, "");
   11281          51 :       colno = ITEM_INDENT + n;
   11282             :     }
   11283         770 :   else if (colno + 2 + n < wrap)
   11284             :     {
   11285         936 :       printf ("%c ", sep);
   11286         468 :       colno += 2 + n;
   11287             :     }
   11288             :   else
   11289             :     {
   11290         302 :       printf ("\n%*s", ITEM_INDENT, "");
   11291         302 :       colno = ITEM_INDENT + n;
   11292             :     }
   11293             : 
   11294        1642 :   printf ("%s: %*s%s", name, (int) (name_width - len), "", out);
   11295             : 
   11296         821 :   free (out);
   11297             : 
   11298         821 :   return colno;
   11299             : }
   11300             : 
   11301             : static const void *
   11302         931 : convert (Elf *core, Elf_Type type, uint_fast16_t count,
   11303             :          void *value, const void *data, size_t size)
   11304             : {
   11305        1862 :   Elf_Data valuedata =
   11306             :     {
   11307             :       .d_type = type,
   11308             :       .d_buf = value,
   11309         931 :       .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
   11310             :       .d_version = EV_CURRENT,
   11311             :     };
   11312         931 :   Elf_Data indata =
   11313             :     {
   11314             :       .d_type = type,
   11315             :       .d_buf = (void *) data,
   11316             :       .d_size = valuedata.d_size,
   11317             :       .d_version = EV_CURRENT,
   11318             :     };
   11319             : 
   11320        1862 :   Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
   11321        1862 :                  ? elf32_xlatetom : elf64_xlatetom)
   11322         931 :     (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
   11323         931 :   if (d == NULL)
   11324           0 :     error (EXIT_FAILURE, 0,
   11325           0 :            gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   11326             : 
   11327         931 :   return data + indata.d_size;
   11328             : }
   11329             : 
   11330             : typedef uint8_t GElf_Byte;
   11331             : 
   11332             : static unsigned int
   11333         400 : handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
   11334             :                   unsigned int colno, size_t *repeated_size)
   11335             : {
   11336         400 :   uint_fast16_t count = item->count ?: 1;
   11337             :   /* Ebl_Core_Item count is always a small number.
   11338             :      Make sure the backend didn't put in some large bogus value.  */
   11339          62 :   assert (count < 128);
   11340             : 
   11341             : #define TYPES                                                                 \
   11342             :   DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8);                         \
   11343             :   DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16);                       \
   11344             :   DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32);                       \
   11345             :   DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32);                         \
   11346             :   DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64);                            \
   11347             :   DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64)
   11348             : 
   11349             : #define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name
   11350             :   typedef union { TYPES; } value_t;
   11351         400 :   void *data = alloca (count * sizeof (value_t));
   11352             : #undef DO_TYPE
   11353             : 
   11354             : #define DO_TYPE(NAME, Name, hex, dec) \
   11355             :     GElf_##Name *value_##Name __attribute__((unused)) = data
   11356         400 :   TYPES;
   11357             : #undef DO_TYPE
   11358             : 
   11359         400 :   size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
   11360         400 :   size_t convsize = size;
   11361         400 :   if (repeated_size != NULL)
   11362             :     {
   11363           1 :       if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
   11364             :         {
   11365           0 :           data = alloca (*repeated_size);
   11366           0 :           count *= *repeated_size / size;
   11367           0 :           convsize = count * size;
   11368           0 :           *repeated_size -= convsize;
   11369             :         }
   11370           1 :       else if (item->count != 0 || item->format != '\n')
   11371           0 :         *repeated_size -= size;
   11372             :     }
   11373             : 
   11374         400 :   convert (core, item->type, count, data, desc + item->offset, convsize);
   11375             : 
   11376         400 :   Elf_Type type = item->type;
   11377         400 :   if (type == ELF_T_ADDR)
   11378           1 :     type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
   11379             : 
   11380         400 :   switch (item->format)
   11381             :     {
   11382         193 :     case 'd':
   11383         193 :       assert (count == 1);
   11384         193 :       switch (type)
   11385             :         {
   11386             : #define DO_TYPE(NAME, Name, hex, dec)                                         \
   11387             :           case ELF_T_##NAME:                                                  \
   11388             :             colno = print_core_item (colno, ',', WRAP_COLUMN,                 \
   11389             :                                      0, item->name, dec, value_##Name[0]); \
   11390             :             break
   11391          27 :           TYPES;
   11392             : #undef DO_TYPE
   11393           0 :         default:
   11394           0 :           abort ();
   11395             :         }
   11396             :       break;
   11397             : 
   11398         111 :     case 'x':
   11399         111 :       assert (count == 1);
   11400         111 :       switch (type)
   11401             :         {
   11402             : #define DO_TYPE(NAME, Name, hex, dec)                                         \
   11403             :           case ELF_T_##NAME:                                                  \
   11404             :             colno = print_core_item (colno, ',', WRAP_COLUMN,                 \
   11405             :                                      0, item->name, hex, value_##Name[0]);      \
   11406             :             break
   11407           0 :           TYPES;
   11408             : #undef DO_TYPE
   11409           0 :         default:
   11410           0 :           abort ();
   11411             :         }
   11412             :       break;
   11413             : 
   11414          22 :     case 'b':
   11415             :     case 'B':
   11416          22 :       assert (size % sizeof (unsigned int) == 0);
   11417          22 :       unsigned int nbits = count * size * 8;
   11418          22 :       unsigned int pop = 0;
   11419          56 :       for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
   11420          34 :         pop += __builtin_popcount (*i);
   11421          22 :       bool negate = pop > nbits / 2;
   11422          22 :       const unsigned int bias = item->format == 'b';
   11423             : 
   11424          44 :       {
   11425          22 :         char printed[(negate ? nbits - pop : pop) * 16 + 1];
   11426          22 :         char *p = printed;
   11427          22 :         *p = '\0';
   11428             : 
   11429             :         if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
   11430             :           {
   11431             :             assert (size == sizeof (unsigned int) * 2);
   11432             :             for (unsigned int *i = data;
   11433             :                  (void *) i < data + count * size; i += 2)
   11434             :               {
   11435             :                 unsigned int w = i[1];
   11436             :                 i[1] = i[0];
   11437             :                 i[0] = w;
   11438             :               }
   11439             :           }
   11440             : 
   11441          22 :         unsigned int lastbit = 0;
   11442          22 :         unsigned int run = 0;
   11443          78 :         for (const unsigned int *i = data;
   11444          34 :              (void *) i < data + count * size; ++i)
   11445             :           {
   11446          34 :             unsigned int bit = ((void *) i - data) * 8;
   11447          34 :             unsigned int w = negate ? ~*i : *i;
   11448          34 :             while (w != 0)
   11449             :               {
   11450             :                 /* Note that a right shift equal to (or greater than)
   11451             :                    the number of bits of w is undefined behaviour.  In
   11452             :                    particular when the least significant bit is bit 32
   11453             :                    (w = 0x8000000) then w >>= n is undefined.  So
   11454             :                    explicitly handle that case separately.  */
   11455           0 :                 unsigned int n = ffs (w);
   11456           0 :                 if (n < sizeof (w) * 8)
   11457           0 :                   w >>= n;
   11458             :                 else
   11459             :                   w = 0;
   11460           0 :                 bit += n;
   11461             : 
   11462           0 :                 if (lastbit != 0 && lastbit + 1 == bit)
   11463           0 :                   ++run;
   11464             :                 else
   11465             :                   {
   11466           0 :                     if (lastbit == 0)
   11467           0 :                       p += sprintf (p, "%u", bit - bias);
   11468           0 :                     else if (run == 0)
   11469           0 :                       p += sprintf (p, ",%u", bit - bias);
   11470             :                     else
   11471           0 :                       p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
   11472             :                     run = 0;
   11473             :                   }
   11474             : 
   11475             :                 lastbit = bit;
   11476             :               }
   11477             :           }
   11478          22 :         if (lastbit > 0 && run > 0 && lastbit + 1 != nbits)
   11479           0 :           p += sprintf (p, "-%u", lastbit - bias);
   11480             : 
   11481          22 :         colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
   11482             :                                  negate ? "~<%s>" : "<%s>", printed);
   11483             :       }
   11484          22 :       break;
   11485             : 
   11486          44 :     case 'T':
   11487             :     case (char) ('T'|0x80):
   11488          44 :       assert (count == 2);
   11489             :       Dwarf_Word sec;
   11490             :       Dwarf_Word usec;
   11491          44 :       switch (type)
   11492             :         {
   11493             : #define DO_TYPE(NAME, Name, hex, dec)                                         \
   11494             :           case ELF_T_##NAME:                                                  \
   11495             :             sec = value_##Name[0];                                            \
   11496             :             usec = value_##Name[1];                                           \
   11497             :             break
   11498           0 :           TYPES;
   11499             : #undef DO_TYPE
   11500           0 :         default:
   11501           0 :           abort ();
   11502             :         }
   11503          44 :       if (unlikely (item->format == (char) ('T'|0x80)))
   11504             :         {
   11505             :           /* This is a hack for an ill-considered 64-bit ABI where
   11506             :              tv_usec is actually a 32-bit field with 32 bits of padding
   11507             :              rounding out struct timeval.  We've already converted it as
   11508             :              a 64-bit field.  For little-endian, this just means the
   11509             :              high half is the padding; it's presumably zero, but should
   11510             :              be ignored anyway.  For big-endian, it means the 32-bit
   11511             :              field went into the high half of USEC.  */
   11512             :           GElf_Ehdr ehdr_mem;
   11513           0 :           GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
   11514           0 :           if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
   11515           0 :             usec >>= 32;
   11516             :           else
   11517           0 :             usec &= UINT32_MAX;
   11518             :         }
   11519          44 :       colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
   11520             :                                "%" PRIu64 ".%.6" PRIu64, sec, usec);
   11521          44 :       break;
   11522             : 
   11523           9 :     case 'c':
   11524           9 :       assert (count == 1);
   11525           9 :       colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
   11526           9 :                                "%c", value_Byte[0]);
   11527           9 :       break;
   11528             : 
   11529          18 :     case 's':
   11530          18 :       colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
   11531             :                                "%.*s", (int) count, value_Byte);
   11532          18 :       break;
   11533             : 
   11534           1 :     case '\n':
   11535             :       /* This is a list of strings separated by '\n'.  */
   11536           1 :       assert (item->count == 0);
   11537           1 :       assert (repeated_size != NULL);
   11538           1 :       assert (item->name == NULL);
   11539           1 :       if (unlikely (item->offset >= *repeated_size))
   11540             :         break;
   11541             : 
   11542           1 :       const char *s = desc + item->offset;
   11543           1 :       size = *repeated_size - item->offset;
   11544           1 :       *repeated_size = 0;
   11545          49 :       while (size > 0)
   11546             :         {
   11547          48 :           const char *eol = memchr (s, '\n', size);
   11548          48 :           int len = size;
   11549          48 :           if (eol != NULL)
   11550          47 :             len = eol - s;
   11551          48 :           printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
   11552          48 :           if (eol == NULL)
   11553             :             break;
   11554          47 :           size -= eol + 1 - s;
   11555          47 :           s = eol + 1;
   11556             :         }
   11557             : 
   11558             :       colno = WRAP_COLUMN;
   11559             :       break;
   11560             : 
   11561             :     case 'h':
   11562             :       break;
   11563             : 
   11564           0 :     default:
   11565           0 :       error (0, 0, "XXX not handling format '%c' for %s",
   11566             :              item->format, item->name);
   11567             :       break;
   11568             :     }
   11569             : 
   11570             : #undef TYPES
   11571             : 
   11572         400 :   return colno;
   11573             : }
   11574             : 
   11575             : 
   11576             : /* Sort items by group, and by layout offset within each group.  */
   11577             : static int
   11578         895 : compare_core_items (const void *a, const void *b)
   11579             : {
   11580         895 :   const Ebl_Core_Item *const *p1 = a;
   11581         895 :   const Ebl_Core_Item *const *p2 = b;
   11582         895 :   const Ebl_Core_Item *item1 = *p1;
   11583         895 :   const Ebl_Core_Item *item2 = *p2;
   11584             : 
   11585         895 :   return ((item1->group == item2->group ? 0
   11586         895 :            : strcmp (item1->group, item2->group))
   11587         432 :           ?: (int) item1->offset - (int) item2->offset);
   11588             : }
   11589             : 
   11590             : /* Sort item groups by layout offset of the first item in the group.  */
   11591             : static int
   11592         139 : compare_core_item_groups (const void *a, const void *b)
   11593             : {
   11594         139 :   const Ebl_Core_Item *const *const *p1 = a;
   11595         139 :   const Ebl_Core_Item *const *const *p2 = b;
   11596         139 :   const Ebl_Core_Item *const *group1 = *p1;
   11597         139 :   const Ebl_Core_Item *const *group2 = *p2;
   11598         139 :   const Ebl_Core_Item *item1 = *group1;
   11599         139 :   const Ebl_Core_Item *item2 = *group2;
   11600             : 
   11601         139 :   return (int) item1->offset - (int) item2->offset;
   11602             : }
   11603             : 
   11604             : static unsigned int
   11605          37 : handle_core_items (Elf *core, const void *desc, size_t descsz,
   11606             :                    const Ebl_Core_Item *items, size_t nitems)
   11607             : {
   11608          37 :   if (nitems == 0)
   11609             :     return 0;
   11610          34 :   unsigned int colno = 0;
   11611             : 
   11612             :   /* FORMAT '\n' makes sense to be present only as a single item as it
   11613             :      processes all the data of a note.  FORMATs 'b' and 'B' have a special case
   11614             :      if present as a single item but they can be also processed with other
   11615             :      items below.  */
   11616          34 :   if (nitems == 1 && (items[0].format == '\n' || items[0].format == 'b'
   11617           8 :                       || items[0].format == 'B'))
   11618             :     {
   11619           1 :       assert (items[0].offset == 0);
   11620           1 :       size_t size = descsz;
   11621           1 :       colno = handle_core_item (core, items, desc, colno, &size);
   11622             :       /* If SIZE is not zero here there is some remaining data.  But we do not
   11623             :          know how to process it anyway.  */
   11624             :       return colno;
   11625             :     }
   11626         391 :   for (size_t i = 0; i < nitems; ++i)
   11627         391 :     assert (items[i].format != '\n');
   11628             : 
   11629             :   /* Sort to collect the groups together.  */
   11630          33 :   const Ebl_Core_Item *sorted_items[nitems];
   11631         424 :   for (size_t i = 0; i < nitems; ++i)
   11632         391 :     sorted_items[i] = &items[i];
   11633          33 :   qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
   11634             : 
   11635             :   /* Collect the unique groups and sort them.  */
   11636          33 :   const Ebl_Core_Item **groups[nitems];
   11637          33 :   groups[0] = &sorted_items[0];
   11638          33 :   size_t ngroups = 1;
   11639         391 :   for (size_t i = 1; i < nitems; ++i)
   11640         358 :     if (sorted_items[i]->group != sorted_items[i - 1]->group
   11641          75 :         && strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
   11642          75 :       groups[ngroups++] = &sorted_items[i];
   11643          33 :   qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
   11644             : 
   11645             :   /* Write out all the groups.  */
   11646          33 :   const void *last = desc;
   11647             :   do
   11648             :     {
   11649         145 :       for (size_t i = 0; i < ngroups; ++i)
   11650             :         {
   11651         619 :           for (const Ebl_Core_Item **item = groups[i];
   11652         509 :                (item < &sorted_items[nitems]
   11653         474 :                 && ((*item)->group == groups[i][0]->group
   11654          75 :                     || !strcmp ((*item)->group, groups[i][0]->group)));
   11655         399 :                ++item)
   11656         399 :             colno = handle_core_item (core, *item, desc, colno, NULL);
   11657             : 
   11658             :           /* Force a line break at the end of the group.  */
   11659         110 :           colno = WRAP_COLUMN;
   11660             :         }
   11661             : 
   11662          35 :       if (descsz == 0)
   11663             :         break;
   11664             : 
   11665             :       /* This set of items consumed a certain amount of the note's data.
   11666             :          If there is more data there, we have another unit of the same size.
   11667             :          Loop to print that out too.  */
   11668          20 :       const Ebl_Core_Item *item = &items[nitems - 1];
   11669          40 :       size_t eltsz = item->offset + gelf_fsize (core, item->type,
   11670          20 :                                                 item->count ?: 1, EV_CURRENT);
   11671             : 
   11672          20 :       int reps = -1;
   11673             :       do
   11674             :         {
   11675          20 :           ++reps;
   11676          20 :           desc += eltsz;
   11677          20 :           descsz -= eltsz;
   11678             :         }
   11679          20 :       while (descsz >= eltsz && !memcmp (desc, last, eltsz));
   11680             : 
   11681          20 :       if (reps == 1)
   11682             :         {
   11683             :           /* For just one repeat, print it unabridged twice.  */
   11684             :           desc -= eltsz;
   11685             :           descsz += eltsz;
   11686             :         }
   11687          20 :       else if (reps > 1)
   11688           0 :         printf (gettext ("\n%*s... <repeats %u more times> ..."),
   11689             :                 ITEM_INDENT, "", reps);
   11690             : 
   11691          20 :       last = desc;
   11692             :     }
   11693          20 :   while (descsz > 0);
   11694             : 
   11695             :   return colno;
   11696             : }
   11697             : 
   11698             : static unsigned int
   11699             : handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
   11700             :                       unsigned int colno)
   11701             : {
   11702           0 :   desc += regloc->offset;
   11703             : 
   11704           0 :   abort ();                     /* XXX */
   11705             :   return colno;
   11706             : }
   11707             : 
   11708             : 
   11709             : static unsigned int
   11710         162 : handle_core_register (Ebl *ebl, Elf *core, int maxregname,
   11711             :                       const Ebl_Register_Location *regloc, const void *desc,
   11712             :                       unsigned int colno)
   11713             : {
   11714         162 :   if (regloc->bits % 8 != 0)
   11715           0 :     return handle_bit_registers (regloc, desc, colno);
   11716             : 
   11717         162 :   desc += regloc->offset;
   11718             : 
   11719         586 :   for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
   11720             :     {
   11721             :       char name[REGNAMESZ];
   11722             :       int bits;
   11723             :       int type;
   11724         424 :       register_info (ebl, reg, regloc, name, &bits, &type);
   11725             : 
   11726             : #define TYPES                                                                 \
   11727             :       BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8);                          \
   11728             :       BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16);                       \
   11729             :       BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32);                             \
   11730             :       BITS (64, XWORD, "%20" PRId64, "  0x%.16" PRIx64)
   11731             : 
   11732             : #define BITS(bits, xtype, sfmt, ufmt)                           \
   11733             :       uint##bits##_t b##bits; int##bits##_t b##bits##s
   11734             :       union { TYPES; uint64_t b128[2]; } value;
   11735             : #undef  BITS
   11736             : 
   11737         424 :       switch (type)
   11738             :         {
   11739         336 :         case DW_ATE_unsigned:
   11740             :         case DW_ATE_signed:
   11741             :         case DW_ATE_address:
   11742         336 :           switch (bits)
   11743             :             {
   11744             : #define BITS(bits, xtype, sfmt, ufmt)                                         \
   11745             :             case bits:                                                        \
   11746             :               desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0);           \
   11747             :               if (type == DW_ATE_signed)                                      \
   11748             :                 colno = print_core_item (colno, ' ', WRAP_COLUMN,             \
   11749             :                                          maxregname, name,                    \
   11750             :                                          sfmt, value.b##bits##s);             \
   11751             :               else                                                            \
   11752             :                 colno = print_core_item (colno, ' ', WRAP_COLUMN,             \
   11753             :                                          maxregname, name,                    \
   11754             :                                          ufmt, value.b##bits);                \
   11755             :               break
   11756             : 
   11757           0 :             TYPES;
   11758             : 
   11759          48 :             case 128:
   11760          48 :               assert (type == DW_ATE_unsigned);
   11761          48 :               desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
   11762          48 :               int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
   11763          96 :               colno = print_core_item (colno, ' ', WRAP_COLUMN,
   11764             :                                        maxregname, name,
   11765             :                                        "0x%.16" PRIx64 "%.16" PRIx64,
   11766          48 :                                        value.b128[!be], value.b128[be]);
   11767          48 :               break;
   11768             : 
   11769           0 :             default:
   11770           0 :               abort ();
   11771             : #undef  BITS
   11772             :             }
   11773             :           break;
   11774             : 
   11775          88 :         default:
   11776             :           /* Print each byte in hex, the whole thing in native byte order.  */
   11777          88 :           assert (bits % 8 == 0);
   11778          88 :           const uint8_t *bytes = desc;
   11779          88 :           desc += bits / 8;
   11780          88 :           char hex[bits / 4 + 1];
   11781          88 :           hex[bits / 4] = '\0';
   11782          88 :           int incr = 1;
   11783          88 :           if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
   11784             :             {
   11785          48 :               bytes += bits / 8 - 1;
   11786          48 :               incr = -1;
   11787             :             }
   11788          88 :           size_t idx = 0;
   11789         872 :           for (char *h = hex; bits > 0; bits -= 8, idx += incr)
   11790             :             {
   11791         784 :               *h++ = "0123456789abcdef"[bytes[idx] >> 4];
   11792         784 :               *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
   11793             :             }
   11794          88 :           colno = print_core_item (colno, ' ', WRAP_COLUMN,
   11795             :                                    maxregname, name, "0x%s", hex);
   11796             :           break;
   11797             :         }
   11798         424 :       desc += regloc->pad;
   11799             : 
   11800             : #undef TYPES
   11801             :     }
   11802             : 
   11803             :   return colno;
   11804             : }
   11805             : 
   11806             : 
   11807             : struct register_info
   11808             : {
   11809             :   const Ebl_Register_Location *regloc;
   11810             :   const char *set;
   11811             :   char name[REGNAMESZ];
   11812             :   int regno;
   11813             :   int bits;
   11814             :   int type;
   11815             : };
   11816             : 
   11817             : static int
   11818             : register_bitpos (const struct register_info *r)
   11819             : {
   11820        2066 :   return (r->regloc->offset * 8
   11821        4132 :           + ((r->regno - r->regloc->regno)
   11822        2066 :              * (r->regloc->bits + r->regloc->pad * 8)));
   11823             : }
   11824             : 
   11825             : static int
   11826        1062 : compare_sets_by_info (const struct register_info *r1,
   11827             :                       const struct register_info *r2)
   11828             : {
   11829        1062 :   return ((int) r2->bits - (int) r1->bits
   11830        3128 :           ?: register_bitpos (r1) - register_bitpos (r2));
   11831             : }
   11832             : 
   11833             : /* Sort registers by set, and by size and layout offset within each set.  */
   11834             : static int
   11835        4595 : compare_registers (const void *a, const void *b)
   11836             : {
   11837        4595 :   const struct register_info *r1 = a;
   11838        4595 :   const struct register_info *r2 = b;
   11839             : 
   11840             :   /* Unused elements sort last.  */
   11841        4595 :   if (r1->regloc == NULL)
   11842        3309 :     return r2->regloc == NULL ? 0 : 1;
   11843        1286 :   if (r2->regloc == NULL)
   11844             :     return -1;
   11845             : 
   11846        1121 :   return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
   11847          79 :           ?: compare_sets_by_info (r1, r2));
   11848             : }
   11849             : 
   11850             : /* Sort register sets by layout offset of the first register in the set.  */
   11851             : static int
   11852          20 : compare_register_sets (const void *a, const void *b)
   11853             : {
   11854          20 :   const struct register_info *const *p1 = a;
   11855          20 :   const struct register_info *const *p2 = b;
   11856          20 :   return compare_sets_by_info (*p1, *p2);
   11857             : }
   11858             : 
   11859             : static unsigned int
   11860          37 : handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
   11861             :                        const Ebl_Register_Location *reglocs, size_t nregloc)
   11862             : {
   11863          37 :   if (nregloc == 0)
   11864             :     return 0;
   11865             : 
   11866          18 :   ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
   11867          18 :   if (maxnreg <= 0)
   11868             :     {
   11869           0 :       for (size_t i = 0; i < nregloc; ++i)
   11870           0 :         if (maxnreg < reglocs[i].regno + reglocs[i].count)
   11871           0 :           maxnreg = reglocs[i].regno + reglocs[i].count;
   11872           0 :       assert (maxnreg > 0);
   11873             :     }
   11874             : 
   11875          18 :   struct register_info regs[maxnreg];
   11876          36 :   memset (regs, 0, sizeof regs);
   11877             : 
   11878             :   /* Sort to collect the sets together.  */
   11879          18 :   int maxreg = 0;
   11880         180 :   for (size_t i = 0; i < nregloc; ++i)
   11881         748 :     for (int reg = reglocs[i].regno;
   11882         586 :          reg < reglocs[i].regno + reglocs[i].count;
   11883         424 :          ++reg)
   11884             :       {
   11885         424 :         assert (reg < maxnreg);
   11886         424 :         if (reg > maxreg)
   11887         230 :           maxreg = reg;
   11888         424 :         struct register_info *info = &regs[reg];
   11889         424 :         info->regloc = &reglocs[i];
   11890         424 :         info->regno = reg;
   11891         848 :         info->set = register_info (ebl, reg, &reglocs[i],
   11892         424 :                                    info->name, &info->bits, &info->type);
   11893             :       }
   11894          18 :   qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
   11895             : 
   11896             :   /* Collect the unique sets and sort them.  */
   11897         864 :   inline bool same_set (const struct register_info *a,
   11898             :                         const struct register_info *b)
   11899             :   {
   11900        1728 :     return (a < &regs[maxnreg] && a->regloc != NULL
   11901         864 :             && b < &regs[maxnreg] && b->regloc != NULL
   11902         846 :             && a->bits == b->bits
   11903        1692 :             && (a->set == b->set || !strcmp (a->set, b->set)));
   11904             :   }
   11905          18 :   struct register_info *sets[maxreg + 1];
   11906          18 :   sets[0] = &regs[0];
   11907          18 :   size_t nsets = 1;
   11908        1279 :   for (int i = 1; i <= maxreg; ++i)
   11909        1261 :     if (regs[i].regloc != NULL && !same_set (&regs[i], &regs[i - 1]))
   11910          16 :       sets[nsets++] = &regs[i];
   11911          18 :   qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
   11912             : 
   11913             :   /* Write out all the sets.  */
   11914          18 :   unsigned int colno = 0;
   11915          52 :   for (size_t i = 0; i < nsets; ++i)
   11916             :     {
   11917             :       /* Find the longest name of a register in this set.  */
   11918          34 :       size_t maxname = 0;
   11919             :       const struct register_info *end;
   11920         458 :       for (end = sets[i]; same_set (sets[i], end); ++end)
   11921             :         {
   11922         424 :           size_t len = strlen (end->name);
   11923         424 :           if (len > maxname)
   11924          52 :             maxname = len;
   11925             :         }
   11926             : 
   11927         196 :       for (const struct register_info *reg = sets[i];
   11928             :            reg < end;
   11929         162 :            reg += reg->regloc->count ?: 1)
   11930         162 :         colno = handle_core_register (ebl, core, maxname,
   11931             :                                       reg->regloc, desc, colno);
   11932             : 
   11933             :       /* Force a line break at the end of the group.  */
   11934          34 :       colno = WRAP_COLUMN;
   11935             :     }
   11936             : 
   11937             :   return colno;
   11938             : }
   11939             : 
   11940             : static void
   11941           9 : handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
   11942             : {
   11943           9 :   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
   11944           9 :   if (data == NULL)
   11945           0 :   elf_error:
   11946           0 :     error (EXIT_FAILURE, 0,
   11947           0 :            gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   11948             : 
   11949           9 :   const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
   11950         177 :   for (size_t i = 0; i < nauxv; ++i)
   11951             :     {
   11952             :       GElf_auxv_t av_mem;
   11953         168 :       GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
   11954         168 :       if (av == NULL)
   11955             :         goto elf_error;
   11956             : 
   11957             :       const char *name;
   11958             :       const char *fmt;
   11959         168 :       if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
   11960             :         {
   11961             :           /* Unknown type.  */
   11962           0 :           if (av->a_un.a_val == 0)
   11963           0 :             printf ("    %" PRIu64 "\n", av->a_type);
   11964             :           else
   11965           0 :             printf ("    %" PRIu64 ": %#" PRIx64 "\n",
   11966             :                     av->a_type, av->a_un.a_val);
   11967             :         }
   11968             :       else
   11969         168 :         switch (fmt[0])
   11970             :           {
   11971           9 :           case '\0':            /* Normally zero.  */
   11972           9 :             if (av->a_un.a_val == 0)
   11973             :               {
   11974           9 :                 printf ("    %s\n", name);
   11975             :                 break;
   11976             :               }
   11977             :             FALLTHROUGH;
   11978             :           case 'x':             /* hex */
   11979             :           case 'p':             /* address */
   11980             :           case 's':             /* address of string */
   11981          74 :             printf ("    %s: %#" PRIx64 "\n", name, av->a_un.a_val);
   11982             :             break;
   11983          81 :           case 'u':
   11984          81 :             printf ("    %s: %" PRIu64 "\n", name, av->a_un.a_val);
   11985             :             break;
   11986           0 :           case 'd':
   11987           0 :             printf ("    %s: %" PRId64 "\n", name, av->a_un.a_val);
   11988             :             break;
   11989             : 
   11990           4 :           case 'b':
   11991           8 :             printf ("    %s: %#" PRIx64 "  ", name, av->a_un.a_val);
   11992           4 :             GElf_Xword bit = 1;
   11993           4 :             const char *pfx = "<";
   11994         110 :             for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
   11995             :               {
   11996         106 :                 if (av->a_un.a_val & bit)
   11997             :                   {
   11998          77 :                     printf ("%s%s", pfx, p);
   11999          77 :                     pfx = " ";
   12000             :                   }
   12001         106 :                 bit <<= 1;
   12002             :               }
   12003             :             printf (">\n");
   12004             :             break;
   12005             : 
   12006           0 :           default:
   12007           0 :             abort ();
   12008             :           }
   12009             :     }
   12010           9 : }
   12011             : 
   12012             : static bool
   12013             : buf_has_data (unsigned char const *ptr, unsigned char const *end, size_t sz)
   12014             : {
   12015         195 :   return ptr < end && (size_t) (end - ptr) >= sz;
   12016             : }
   12017             : 
   12018             : static bool
   12019          18 : buf_read_int (Elf *core, unsigned char const **ptrp, unsigned char const *end,
   12020             :               int *retp)
   12021             : {
   12022          36 :   if (! buf_has_data (*ptrp, end, 4))
   12023             :     return false;
   12024             : 
   12025          18 :   *ptrp = convert (core, ELF_T_WORD, 1, retp, *ptrp, 4);
   12026          18 :   return true;
   12027             : }
   12028             : 
   12029             : static bool
   12030         177 : buf_read_ulong (Elf *core, unsigned char const **ptrp, unsigned char const *end,
   12031             :                 uint64_t *retp)
   12032             : {
   12033         177 :   size_t sz = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
   12034         354 :   if (! buf_has_data (*ptrp, end, sz))
   12035             :     return false;
   12036             : 
   12037             :   union
   12038             :   {
   12039             :     uint64_t u64;
   12040             :     uint32_t u32;
   12041             :   } u;
   12042             : 
   12043         177 :   *ptrp = convert (core, ELF_T_ADDR, 1, &u, *ptrp, sz);
   12044             : 
   12045         177 :   if (sz == 4)
   12046          93 :     *retp = u.u32;
   12047             :   else
   12048          84 :     *retp = u.u64;
   12049             :   return true;
   12050             : }
   12051             : 
   12052             : static void
   12053           6 : handle_siginfo_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
   12054             : {
   12055           6 :   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
   12056           6 :   if (data == NULL)
   12057           0 :     error (EXIT_FAILURE, 0,
   12058           0 :            gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   12059             : 
   12060           6 :   unsigned char const *ptr = data->d_buf;
   12061           6 :   unsigned char const *const end = data->d_buf + data->d_size;
   12062             : 
   12063             :   /* Siginfo head is three ints: signal number, error number, origin
   12064             :      code.  */
   12065             :   int si_signo, si_errno, si_code;
   12066           6 :   if (! buf_read_int (core, &ptr, end, &si_signo)
   12067           6 :       || ! buf_read_int (core, &ptr, end, &si_errno)
   12068           6 :       || ! buf_read_int (core, &ptr, end, &si_code))
   12069             :     {
   12070           0 :     fail:
   12071           0 :       printf ("    Not enough data in NT_SIGINFO note.\n");
   12072           0 :       return;
   12073             :     }
   12074             : 
   12075             :   /* Next is a pointer-aligned union of structures.  On 64-bit
   12076             :      machines, that implies a word of padding.  */
   12077           6 :   if (gelf_getclass (core) == ELFCLASS64)
   12078           3 :     ptr += 4;
   12079             : 
   12080          12 :   printf ("    si_signo: %d, si_errno: %d, si_code: %d\n",
   12081             :           si_signo, si_errno, si_code);
   12082             : 
   12083           6 :   if (si_code > 0)
   12084           6 :     switch (si_signo)
   12085             :       {
   12086           6 :       case CORE_SIGILL:
   12087             :       case CORE_SIGFPE:
   12088             :       case CORE_SIGSEGV:
   12089             :       case CORE_SIGBUS:
   12090             :         {
   12091             :           uint64_t addr;
   12092           6 :           if (! buf_read_ulong (core, &ptr, end, &addr))
   12093             :             goto fail;
   12094          12 :           printf ("    fault address: %#" PRIx64 "\n", addr);
   12095           6 :           break;
   12096             :         }
   12097             :       default:
   12098             :         ;
   12099             :       }
   12100           0 :   else if (si_code == CORE_SI_USER)
   12101             :     {
   12102             :       int pid, uid;
   12103           0 :       if (! buf_read_int (core, &ptr, end, &pid)
   12104           0 :           || ! buf_read_int (core, &ptr, end, &uid))
   12105             :         goto fail;
   12106           0 :       printf ("    sender PID: %d, sender UID: %d\n", pid, uid);
   12107             :     }
   12108             : }
   12109             : 
   12110             : static void
   12111           6 : handle_file_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
   12112             : {
   12113           6 :   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
   12114           6 :   if (data == NULL)
   12115           0 :     error (EXIT_FAILURE, 0,
   12116           0 :            gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   12117             : 
   12118           6 :   unsigned char const *ptr = data->d_buf;
   12119           6 :   unsigned char const *const end = data->d_buf + data->d_size;
   12120             : 
   12121             :   uint64_t count, page_size;
   12122           6 :   if (! buf_read_ulong (core, &ptr, end, &count)
   12123           6 :       || ! buf_read_ulong (core, &ptr, end, &page_size))
   12124             :     {
   12125           0 :     fail:
   12126           0 :       printf ("    Not enough data in NT_FILE note.\n");
   12127           0 :       return;
   12128             :     }
   12129             : 
   12130           6 :   size_t addrsize = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
   12131           6 :   uint64_t maxcount = (size_t) (end - ptr) / (3 * addrsize);
   12132           6 :   if (count > maxcount)
   12133             :     goto fail;
   12134             : 
   12135             :   /* Where file names are stored.  */
   12136           6 :   unsigned char const *const fstart = ptr + 3 * count * addrsize;
   12137           6 :   char const *fptr = (char *) fstart;
   12138             : 
   12139          12 :   printf ("    %" PRId64 " files:\n", count);
   12140          59 :   for (uint64_t i = 0; i < count; ++i)
   12141             :     {
   12142             :       uint64_t mstart, mend, moffset;
   12143          53 :       if (! buf_read_ulong (core, &ptr, fstart, &mstart)
   12144          53 :           || ! buf_read_ulong (core, &ptr, fstart, &mend)
   12145          53 :           || ! buf_read_ulong (core, &ptr, fstart, &moffset))
   12146             :         goto fail;
   12147             : 
   12148          53 :       const char *fnext = memchr (fptr, '\0', (char *) end - fptr);
   12149          53 :       if (fnext == NULL)
   12150             :         goto fail;
   12151             : 
   12152         106 :       int ct = printf ("      %08" PRIx64 "-%08" PRIx64
   12153             :                        " %08" PRIx64 " %" PRId64,
   12154             :                        mstart, mend, moffset * page_size, mend - mstart);
   12155         106 :       printf ("%*s%s\n", ct > 50 ? 3 : 53 - ct, "", fptr);
   12156             : 
   12157          53 :       fptr = fnext + 1;
   12158             :     }
   12159             : }
   12160             : 
   12161             : static void
   12162          38 : handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
   12163             :                   const char *name, const void *desc)
   12164             : {
   12165             :   GElf_Word regs_offset;
   12166             :   size_t nregloc;
   12167             :   const Ebl_Register_Location *reglocs;
   12168             :   size_t nitems;
   12169             :   const Ebl_Core_Item *items;
   12170             : 
   12171          38 :   if (! ebl_core_note (ebl, nhdr, name, desc,
   12172             :                        &regs_offset, &nregloc, &reglocs, &nitems, &items))
   12173           1 :     return;
   12174             : 
   12175             :   /* Pass 0 for DESCSZ when there are registers in the note,
   12176             :      so that the ITEMS array does not describe the whole thing.
   12177             :      For non-register notes, the actual descsz might be a multiple
   12178             :      of the unit size, not just exactly the unit size.  */
   12179          93 :   unsigned int colno = handle_core_items (ebl->elf, desc,
   12180          56 :                                           nregloc == 0 ? nhdr->n_descsz : 0,
   12181             :                                           items, nitems);
   12182          37 :   if (colno != 0)
   12183             :     putchar_unlocked ('\n');
   12184             : 
   12185          37 :   colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
   12186             :                                  reglocs, nregloc);
   12187          37 :   if (colno != 0)
   12188             :     putchar_unlocked ('\n');
   12189             : }
   12190             : 
   12191             : static void
   12192          57 : handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
   12193             :                    GElf_Off start, Elf_Data *data)
   12194             : {
   12195          57 :   fputs_unlocked (gettext ("  Owner          Data size  Type\n"), stdout);
   12196             : 
   12197          57 :   if (data == NULL)
   12198             :     goto bad_note;
   12199             : 
   12200             :   size_t offset = 0;
   12201             :   GElf_Nhdr nhdr;
   12202             :   size_t name_offset;
   12203             :   size_t desc_offset;
   12204         188 :   while (offset < data->d_size
   12205         131 :          && (offset = gelf_getnote (data, offset,
   12206             :                                     &nhdr, &name_offset, &desc_offset)) > 0)
   12207             :     {
   12208         131 :       const char *name = nhdr.n_namesz == 0 ? "" : data->d_buf + name_offset;
   12209         131 :       const char *desc = data->d_buf + desc_offset;
   12210             : 
   12211             :       /* GNU Build Attributes are weird, they store most of their data
   12212             :          into the owner name field.  Extract just the owner name
   12213             :          prefix here, then use the rest later as data.  */
   12214         131 :       bool is_gnu_build_attr
   12215         131 :         = strncmp (name, ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX,
   12216             :                    strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX)) == 0;
   12217         131 :       const char *print_name = (is_gnu_build_attr
   12218         131 :                                 ? ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX : name);
   12219         131 :       size_t print_namesz = (is_gnu_build_attr
   12220         131 :                              ? strlen (print_name) : nhdr.n_namesz);
   12221             : 
   12222             :       char buf[100];
   12223             :       char buf2[100];
   12224         393 :       printf (gettext ("  %-13.*s  %9" PRId32 "  %s\n"),
   12225             :               (int) print_namesz, print_name, nhdr.n_descsz,
   12226         131 :               ehdr->e_type == ET_CORE
   12227          59 :               ? ebl_core_note_type_name (ebl, nhdr.n_type,
   12228             :                                          buf, sizeof (buf))
   12229          72 :               : ebl_object_note_type_name (ebl, name, nhdr.n_type,
   12230             :                                            nhdr.n_descsz,
   12231             :                                            buf2, sizeof (buf2)));
   12232             : 
   12233             :       /* Filter out invalid entries.  */
   12234             :       if (memchr (name, '\0', nhdr.n_namesz) != NULL
   12235             :           /* XXX For now help broken Linux kernels.  */
   12236             :           || 1)
   12237             :         {
   12238         131 :           if (ehdr->e_type == ET_CORE)
   12239             :             {
   12240          59 :               if (nhdr.n_type == NT_AUXV
   12241           9 :                   && (nhdr.n_namesz == 4 /* Broken old Linux kernels.  */
   12242           9 :                       || (nhdr.n_namesz == 5 && name[4] == '\0'))
   12243           9 :                   && !memcmp (name, "CORE", 4))
   12244           9 :                 handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
   12245             :                                   start + desc_offset);
   12246          50 :               else if (nhdr.n_namesz == 5 && strcmp (name, "CORE") == 0)
   12247          38 :                 switch (nhdr.n_type)
   12248             :                   {
   12249           6 :                   case NT_SIGINFO:
   12250           6 :                     handle_siginfo_note (ebl->elf, nhdr.n_descsz,
   12251             :                                          start + desc_offset);
   12252             :                     break;
   12253             : 
   12254           6 :                   case NT_FILE:
   12255           6 :                     handle_file_note (ebl->elf, nhdr.n_descsz,
   12256             :                                       start + desc_offset);
   12257             :                     break;
   12258             : 
   12259          26 :                   default:
   12260          26 :                     handle_core_note (ebl, &nhdr, name, desc);
   12261             :                   }
   12262             :               else
   12263          12 :                 handle_core_note (ebl, &nhdr, name, desc);
   12264             :             }
   12265             :           else
   12266          72 :             ebl_object_note (ebl, nhdr.n_namesz, name, nhdr.n_type,
   12267             :                              nhdr.n_descsz, desc);
   12268             :         }
   12269             :     }
   12270             : 
   12271          57 :   if (offset == data->d_size)
   12272          57 :     return;
   12273             : 
   12274           0 :  bad_note:
   12275           0 :   error (0, 0,
   12276           0 :          gettext ("cannot get content of note: %s"),
   12277             :          data != NULL ? "garbage data" : elf_errmsg (-1));
   12278             : }
   12279             : 
   12280             : static void
   12281          60 : handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
   12282             : {
   12283             :   /* If we have section headers, just look for SHT_NOTE sections.
   12284             :      In a debuginfo file, the program headers are not reliable.  */
   12285          60 :   if (shnum != 0)
   12286             :     {
   12287             :       /* Get the section header string table index.  */
   12288             :       size_t shstrndx;
   12289          49 :       if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
   12290             :         error (EXIT_FAILURE, 0,
   12291           0 :                gettext ("cannot get section header string table index"));
   12292             : 
   12293             :       Elf_Scn *scn = NULL;
   12294        1181 :       while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   12295             :         {
   12296             :           GElf_Shdr shdr_mem;
   12297        1132 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   12298             : 
   12299        1132 :           if (shdr == NULL || shdr->sh_type != SHT_NOTE)
   12300             :             /* Not what we are looking for.  */
   12301        1087 :             continue;
   12302             : 
   12303         135 :           printf (gettext ("\
   12304             : \nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
   12305             :                   elf_ndxscn (scn),
   12306          45 :                   elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   12307             :                   shdr->sh_size, shdr->sh_offset);
   12308             : 
   12309          45 :           handle_notes_data (ebl, ehdr, shdr->sh_offset,
   12310             :                              elf_getdata (scn, NULL));
   12311             :         }
   12312             :       return;
   12313             :     }
   12314             : 
   12315             :   /* We have to look through the program header to find the note
   12316             :      sections.  There can be more than one.  */
   12317         129 :   for (size_t cnt = 0; cnt < phnum; ++cnt)
   12318             :     {
   12319             :       GElf_Phdr mem;
   12320         129 :       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
   12321             : 
   12322         129 :       if (phdr == NULL || phdr->p_type != PT_NOTE)
   12323             :         /* Not what we are looking for.  */
   12324         117 :         continue;
   12325             : 
   12326          24 :       printf (gettext ("\
   12327             : \nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
   12328             :               phdr->p_filesz, phdr->p_offset);
   12329             : 
   12330          24 :       handle_notes_data (ebl, ehdr, phdr->p_offset,
   12331             :                          elf_getdata_rawchunk (ebl->elf,
   12332          12 :                                                phdr->p_offset, phdr->p_filesz,
   12333          12 :                                                (phdr->p_align == 8
   12334             :                                                 ? ELF_T_NHDR8 : ELF_T_NHDR)));
   12335             :     }
   12336             : }
   12337             : 
   12338             : 
   12339             : static void
   12340           5 : hex_dump (const uint8_t *data, size_t len)
   12341             : {
   12342           5 :   size_t pos = 0;
   12343          31 :   while (pos < len)
   12344             :     {
   12345          21 :       printf ("  0x%08zx ", pos);
   12346             : 
   12347          21 :       const size_t chunk = MIN (len - pos, 16);
   12348             : 
   12349         342 :       for (size_t i = 0; i < chunk; ++i)
   12350         321 :         if (i % 4 == 3)
   12351          80 :           printf ("%02x ", data[pos + i]);
   12352             :         else
   12353         241 :           printf ("%02x", data[pos + i]);
   12354             : 
   12355          21 :       if (chunk < 16)
   12356           1 :         printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
   12357             : 
   12358         321 :       for (size_t i = 0; i < chunk; ++i)
   12359             :         {
   12360         321 :           unsigned char b = data[pos + i];
   12361         642 :           printf ("%c", isprint (b) ? b : '.');
   12362             :         }
   12363             : 
   12364          21 :       putchar ('\n');
   12365          21 :       pos += chunk;
   12366             :     }
   12367           5 : }
   12368             : 
   12369             : static void
   12370           5 : dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
   12371             : {
   12372           5 :   if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
   12373           0 :     printf (gettext ("\nSection [%zu] '%s' has no data to dump.\n"),
   12374             :             elf_ndxscn (scn), name);
   12375             :   else
   12376             :     {
   12377           5 :       if (print_decompress)
   12378             :         {
   12379             :           /* We try to decompress the section, but keep the old shdr around
   12380             :              so we can show both the original shdr size and the uncompressed
   12381             :              data size.   */
   12382           4 :           if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
   12383             :             {
   12384           2 :               if (elf_compress (scn, 0, 0) < 0)
   12385           0 :                 printf ("WARNING: %s [%zd]\n",
   12386             :                         gettext ("Couldn't uncompress section"),
   12387             :                         elf_ndxscn (scn));
   12388             :             }
   12389           2 :           else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
   12390             :             {
   12391           2 :               if (elf_compress_gnu (scn, 0, 0) < 0)
   12392           0 :                 printf ("WARNING: %s [%zd]\n",
   12393             :                         gettext ("Couldn't uncompress section"),
   12394             :                         elf_ndxscn (scn));
   12395             :             }
   12396             :         }
   12397             : 
   12398           5 :       Elf_Data *data = elf_rawdata (scn, NULL);
   12399           5 :       if (data == NULL)
   12400           0 :         error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
   12401             :                elf_ndxscn (scn), name, elf_errmsg (-1));
   12402             :       else
   12403             :         {
   12404           5 :           if (data->d_size == shdr->sh_size)
   12405           1 :             printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
   12406             :                              " bytes at offset %#0" PRIx64 ":\n"),
   12407             :                     elf_ndxscn (scn), name,
   12408             :                     shdr->sh_size, shdr->sh_offset);
   12409             :           else
   12410           4 :             printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
   12411             :                              " bytes (%zd uncompressed) at offset %#0"
   12412             :                              PRIx64 ":\n"),
   12413             :                     elf_ndxscn (scn), name,
   12414             :                     shdr->sh_size, data->d_size, shdr->sh_offset);
   12415           5 :           hex_dump (data->d_buf, data->d_size);
   12416             :         }
   12417             :     }
   12418           5 : }
   12419             : 
   12420             : static void
   12421          89 : print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
   12422             : {
   12423          89 :   if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
   12424           0 :     printf (gettext ("\nSection [%zu] '%s' has no strings to dump.\n"),
   12425             :             elf_ndxscn (scn), name);
   12426             :   else
   12427             :     {
   12428          89 :       if (print_decompress)
   12429             :         {
   12430             :           /* We try to decompress the section, but keep the old shdr around
   12431             :              so we can show both the original shdr size and the uncompressed
   12432             :              data size.  */
   12433           1 :           if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
   12434             :             {
   12435           0 :               if (elf_compress (scn, 0, 0) < 0)
   12436           0 :                 printf ("WARNING: %s [%zd]\n",
   12437             :                         gettext ("Couldn't uncompress section"),
   12438             :                         elf_ndxscn (scn));
   12439             :             }
   12440           1 :           else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
   12441             :             {
   12442           1 :               if (elf_compress_gnu (scn, 0, 0) < 0)
   12443           0 :                 printf ("WARNING: %s [%zd]\n",
   12444             :                         gettext ("Couldn't uncompress section"),
   12445             :                         elf_ndxscn (scn));
   12446             :             }
   12447             :         }
   12448             : 
   12449          89 :       Elf_Data *data = elf_rawdata (scn, NULL);
   12450          89 :       if (data == NULL)
   12451           0 :         error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
   12452             :                elf_ndxscn (scn), name, elf_errmsg (-1));
   12453             :       else
   12454             :         {
   12455          89 :           if (data->d_size == shdr->sh_size)
   12456          88 :             printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
   12457             :                              " bytes at offset %#0" PRIx64 ":\n"),
   12458             :                     elf_ndxscn (scn), name,
   12459             :                     shdr->sh_size, shdr->sh_offset);
   12460             :           else
   12461           1 :             printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
   12462             :                              " bytes (%zd uncompressed) at offset %#0"
   12463             :                              PRIx64 ":\n"),
   12464             :                     elf_ndxscn (scn), name,
   12465             :                     shdr->sh_size, data->d_size, shdr->sh_offset);
   12466             : 
   12467          89 :           const char *start = data->d_buf;
   12468          89 :           const char *const limit = start + data->d_size;
   12469             :           do
   12470             :             {
   12471       16130 :               const char *end = memchr (start, '\0', limit - start);
   12472       16130 :               const size_t pos = start - (const char *) data->d_buf;
   12473       16130 :               if (unlikely (end == NULL))
   12474             :                 {
   12475           0 :                   printf ("  [%6zx]- %.*s\n",
   12476             :                           pos, (int) (limit - start), start);
   12477             :                   break;
   12478             :                 }
   12479       16130 :               printf ("  [%6zx]  %s\n", pos, start);
   12480       16130 :               start = end + 1;
   12481       16130 :             } while (start < limit);
   12482             :         }
   12483             :     }
   12484          89 : }
   12485             : 
   12486             : static void
   12487          46 : for_each_section_argument (Elf *elf, const struct section_argument *list,
   12488             :                            void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
   12489             :                                          const char *name))
   12490             : {
   12491             :   /* Get the section header string table index.  */
   12492             :   size_t shstrndx;
   12493          46 :   if (elf_getshdrstrndx (elf, &shstrndx) < 0)
   12494             :     error (EXIT_FAILURE, 0,
   12495           0 :            gettext ("cannot get section header string table index"));
   12496             : 
   12497         126 :   for (const struct section_argument *a = list; a != NULL; a = a->next)
   12498             :     {
   12499             :       Elf_Scn *scn;
   12500             :       GElf_Shdr shdr_mem;
   12501         126 :       const char *name = NULL;
   12502             : 
   12503         126 :       char *endp = NULL;
   12504         126 :       unsigned long int shndx = strtoul (a->arg, &endp, 0);
   12505         126 :       if (endp != a->arg && *endp == '\0')
   12506             :         {
   12507           0 :           scn = elf_getscn (elf, shndx);
   12508           0 :           if (scn == NULL)
   12509             :             {
   12510           0 :               error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
   12511           0 :               continue;
   12512             :             }
   12513             : 
   12514           0 :           if (gelf_getshdr (scn, &shdr_mem) == NULL)
   12515           0 :             error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
   12516             :                    elf_errmsg (-1));
   12517           0 :           name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
   12518             :         }
   12519             :       else
   12520             :         {
   12521             :           /* Need to look up the section by name.  */
   12522             :           scn = NULL;
   12523             :           bool found = false;
   12524        3207 :           while ((scn = elf_nextscn (elf, scn)) != NULL)
   12525             :             {
   12526        3081 :               if (gelf_getshdr (scn, &shdr_mem) == NULL)
   12527           0 :                 continue;
   12528        3081 :               name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
   12529        3081 :               if (name == NULL)
   12530           0 :                 continue;
   12531        3081 :               if (!strcmp (name, a->arg))
   12532             :                 {
   12533          94 :                   found = true;
   12534          94 :                   (*dump) (scn, &shdr_mem, name);
   12535             :                 }
   12536             :             }
   12537             : 
   12538         126 :           if (unlikely (!found) && !a->implicit)
   12539           0 :             error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
   12540             :         }
   12541             :     }
   12542          46 : }
   12543             : 
   12544             : static void
   12545             : dump_data (Ebl *ebl)
   12546             : {
   12547           5 :   for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
   12548             : }
   12549             : 
   12550             : static void
   12551             : dump_strings (Ebl *ebl)
   12552             : {
   12553          41 :   for_each_section_argument (ebl->elf, string_sections, &print_string_section);
   12554             : }
   12555             : 
   12556             : static void
   12557           0 : print_strings (Ebl *ebl)
   12558             : {
   12559             :   /* Get the section header string table index.  */
   12560             :   size_t shstrndx;
   12561           0 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   12562             :     error (EXIT_FAILURE, 0,
   12563           0 :            gettext ("cannot get section header string table index"));
   12564             : 
   12565             :   Elf_Scn *scn;
   12566             :   GElf_Shdr shdr_mem;
   12567             :   const char *name;
   12568             :   scn = NULL;
   12569           0 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   12570             :     {
   12571           0 :       if (gelf_getshdr (scn, &shdr_mem) == NULL)
   12572           0 :         continue;
   12573             : 
   12574           0 :       if (shdr_mem.sh_type != SHT_PROGBITS
   12575           0 :           || !(shdr_mem.sh_flags & SHF_STRINGS))
   12576           0 :         continue;
   12577             : 
   12578           0 :       name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
   12579           0 :       if (name == NULL)
   12580           0 :         continue;
   12581             : 
   12582           0 :       print_string_section (scn, &shdr_mem, name);
   12583             :     }
   12584           0 : }
   12585             : 
   12586             : static void
   12587           2 : dump_archive_index (Elf *elf, const char *fname)
   12588             : {
   12589             :   size_t narsym;
   12590           2 :   const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
   12591           2 :   if (arsym == NULL)
   12592             :     {
   12593           0 :       int result = elf_errno ();
   12594           0 :       if (unlikely (result != ELF_E_NO_INDEX))
   12595           0 :         error (EXIT_FAILURE, 0,
   12596           0 :                gettext ("cannot get symbol index of archive '%s': %s"),
   12597             :                fname, elf_errmsg (result));
   12598             :       else
   12599           0 :         printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
   12600           0 :       return;
   12601             :     }
   12602             : 
   12603           4 :   printf (gettext ("\nIndex of archive '%s' has %zu entries:\n"),
   12604             :           fname, narsym);
   12605             : 
   12606           2 :   size_t as_off = 0;
   12607          11 :   for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
   12608             :     {
   12609           9 :       if (s->as_off != as_off)
   12610             :         {
   12611           6 :           as_off = s->as_off;
   12612             : 
   12613           6 :           Elf *subelf = NULL;
   12614           6 :           if (unlikely (elf_rand (elf, as_off) == 0)
   12615           6 :               || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
   12616             :                            == NULL))
   12617             : #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
   12618             :             while (1)
   12619             : #endif
   12620           0 :               error (EXIT_FAILURE, 0,
   12621           0 :                      gettext ("cannot extract member at offset %zu in '%s': %s"),
   12622             :                      as_off, fname, elf_errmsg (-1));
   12623             : 
   12624           6 :           const Elf_Arhdr *h = elf_getarhdr (subelf);
   12625             : 
   12626          12 :           printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
   12627             : 
   12628           6 :           elf_end (subelf);
   12629             :         }
   12630             : 
   12631          18 :       printf ("\t%s\n", s->as_name);
   12632             :     }
   12633             : }
   12634             : 
   12635             : #include "debugpred.h"

Generated by: LCOV version 1.13