LCOV - code coverage report
Current view: top level - src - readelf.c (source / functions) Hit Total Coverage
Test: elfutils-0.175 Lines: 3807 5499 69.2 %
Date: 2018-11-16 13:02:39 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         280 : main (int argc, char *argv[])
     317             : {
     318             :   /* We use no threads here which can interfere with handling a stream.  */
     319         280 :   (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
     320             : 
     321             :   /* Set locale.  */
     322         280 :   setlocale (LC_ALL, "");
     323             : 
     324             :   /* Initialize the message catalog.  */
     325         280 :   textdomain (PACKAGE_TARNAME);
     326             : 
     327             :   /* Look up once.  */
     328         280 :   yes_str = gettext ("yes");
     329         280 :   no_str = gettext ("no");
     330             : 
     331             :   /* Parse and process arguments.  */
     332             :   int remaining;
     333         280 :   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
     334             : 
     335             :   /* Before we start tell the ELF library which version we are using.  */
     336         280 :   elf_version (EV_CURRENT);
     337             : 
     338             :   /* Now process all the files given at the command line.  */
     339         280 :   bool only_one = remaining + 1 == argc;
     340             :   do
     341             :     {
     342             :       /* Open the file.  */
     343         572 :       int fd = open (argv[remaining], O_RDONLY);
     344         286 :       if (fd == -1)
     345             :         {
     346           0 :           error (0, errno, gettext ("cannot open input file"));
     347           0 :           continue;
     348             :         }
     349             : 
     350         286 :       process_file (fd, argv[remaining], only_one);
     351             : 
     352         286 :       close (fd);
     353             :     }
     354         286 :   while (++remaining < argc);
     355             : 
     356         280 :   return error_message_count != 0;
     357             : }
     358             : 
     359             : 
     360             : /* Handle program arguments.  */
     361             : static error_t
     362        1745 : 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        1745 :   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          15 :     case 'n':
     426          15 :       print_notes = true;
     427          15 :       any_control_option = true;
     428          15 :       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         280 :     case ARGP_KEY_FINI:
     548         280 :       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         272 : 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         272 :   if (*(bool *) arg)
     731             :     return DWARF_CB_ABORT;
     732         272 :   *(bool *) arg = true;
     733         272 :   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         284 : 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         284 :   const struct process_dwflmod_args *a = arg;
     750             : 
     751             :   /* Print the file name.  */
     752         284 :   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         284 :   process_elf_file (dwflmod, a->fd);
     761             : 
     762         284 :   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         293 : create_dwfl (int fd, const char *fname)
     795             : {
     796             :   /* Duplicate an fd for dwfl_report_offline to swallow.  */
     797         293 :   int dwfl_fd = dup (fd);
     798         293 :   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         293 :   Dwfl *dwfl = dwfl_begin (&callbacks);
     809         293 :   if (likely (dwfl != NULL))
     810             :     /* Let 0 be the logical address of the file (or first in archive).  */
     811         293 :     dwfl->offline_next_address = 0;
     812         293 :   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         293 :     dwfl_report_end (dwfl, NULL, NULL);
     827             : 
     828         293 :   return dwfl;
     829             : }
     830             : 
     831             : /* Process one input file.  */
     832             : static void
     833         286 : process_file (int fd, const char *fname, bool only_one)
     834             : {
     835         286 :   if (print_archive_index)
     836           2 :     check_archive_index (fd, fname, only_one);
     837             : 
     838         286 :   if (!any_control_option)
     839             :     return;
     840             : 
     841         284 :   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         284 :   Dwfl *dwfl = create_dwfl (fd, fname);
     857         284 :   if (dwfl != NULL)
     858             :     {
     859         284 :       if (only_one)
     860             :         {
     861             :           /* Clear ONLY_ONE if we have multiple modules, from an archive.  */
     862         272 :           bool seen = false;
     863         272 :           only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
     864             :         }
     865             : 
     866             :       /* Process the one or more modules gleaned from this file.  */
     867         284 :       struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
     868         284 :       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         284 :   if (! do_not_close_dwfl)
     873         284 :     dwfl_end (dwfl);
     874             : 
     875             :   /* Need to close the replaced fd if we created it.  Caller takes
     876             :      care of original.  */
     877         284 :   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          94 : elf_contains_chdrs (Elf *elf)
     884             : {
     885          94 :   Elf_Scn *scn = NULL;
     886      788819 :   while ((scn = elf_nextscn (elf, scn)) != NULL)
     887             :     {
     888             :       GElf_Shdr shdr_mem;
     889      788637 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
     890      788637 :       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         284 : process_elf_file (Dwfl_Module *dwflmod, int fd)
     899             : {
     900             :   GElf_Addr dwflbias;
     901         284 :   Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
     902             : 
     903             :   GElf_Ehdr ehdr_mem;
     904         284 :   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
     905             : 
     906         284 :   if (ehdr == NULL)
     907             :     {
     908           0 :       error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
     909           0 :       return;
     910             :     }
     911             : 
     912         284 :   Ebl *ebl = ebl_openbackend (elf);
     913         284 :   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         284 :   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         284 :   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         568 :   bool print_unchanged = ((print_section_header
     938         156 :                            || print_relocations
     939         155 :                            || dump_data_sections != NULL
     940         150 :                            || print_notes)
     941         433 :                           && (ehdr->e_type == ET_REL
     942          94 :                               || elf_contains_chdrs (ebl->elf)));
     943             : 
     944         284 :   Elf *pure_elf = NULL;
     945         284 :   Ebl *pure_ebl = ebl;
     946         284 :   if (print_unchanged)
     947             :     {
     948             :       /* Read the file afresh.  */
     949          61 :       off_t aroff = elf_getaroff (elf);
     950          61 :       pure_elf = dwelf_elf_begin (fd);
     951          61 :       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          61 :       if (pure_elf == NULL)
     960             :         {
     961           0 :           error (0, 0, gettext ("cannot read ELF: %s"), elf_errmsg (-1));
     962             :           return;
     963             :         }
     964          61 :       pure_ebl = ebl_openbackend (pure_elf);
     965          61 :       if (pure_ebl == NULL)
     966             :         goto ebl_error;
     967             :     }
     968             : 
     969         284 :   if (print_file_header)
     970          40 :     print_ehdr (ebl, ehdr);
     971         284 :   if (print_section_header)
     972         128 :     print_shdr (pure_ebl, ehdr);
     973         284 :   if (print_program_header)
     974          40 :     print_phdr (ebl, ehdr);
     975         284 :   if (print_section_groups)
     976          49 :     print_scngrp (ebl);
     977         284 :   if (print_dynamic_table)
     978          42 :     print_dynamic (ebl);
     979         284 :   if (print_relocations)
     980          41 :     print_relocs (pure_ebl, ehdr);
     981         284 :   if (print_histogram)
     982          40 :     handle_hash (ebl);
     983         284 :   if (print_symbol_table)
     984          54 :     print_symtab (ebl, SHT_DYNSYM);
     985         284 :   if (print_version_info)
     986          40 :     print_verinfo (ebl);
     987         284 :   if (print_symbol_table)
     988          54 :     print_symtab (ebl, SHT_SYMTAB);
     989         284 :   if (print_arch)
     990          44 :     print_liblist (ebl);
     991         284 :   if (print_arch)
     992          44 :     print_attributes (ebl, ehdr);
     993         284 :   if (dump_data_sections != NULL)
     994           5 :     dump_data (pure_ebl);
     995         284 :   if (string_sections != NULL)
     996          41 :     dump_strings (ebl);
     997         284 :   if ((print_debug_sections | implicit_debug_sections) != 0)
     998         145 :     print_debug (dwflmod, ebl, ehdr);
     999         284 :   if (print_notes)
    1000          55 :     handle_notes (pure_ebl, ehdr);
    1001         284 :   if (print_string_sections)
    1002           0 :     print_strings (ebl);
    1003             : 
    1004         284 :   ebl_closebackend (ebl);
    1005             : 
    1006         284 :   if (pure_ebl != ebl)
    1007             :     {
    1008          61 :       ebl_closebackend (pure_ebl);
    1009          61 :       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       14885 :   switch (value)
    1155             :     {
    1156             :     case STV_DEFAULT:
    1157             :       return "DEFAULT";
    1158           0 :     case STV_INTERNAL:
    1159             :       return "INTERNAL";
    1160          72 :     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       38711 :   for (int cnt = 0; cnt < nentries; ++cnt)
    2196             :     {
    2197             :       GElf_Rela relmem;
    2198       38543 :       GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
    2199       38543 :       if (likely (rel != NULL))
    2200             :         {
    2201             :           char buf[64];
    2202             :           GElf_Sym symmem;
    2203             :           Elf32_Word xndx;
    2204       38543 :           GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
    2205       38543 :                                             GELF_R_SYM (rel->r_info),
    2206             :                                             &symmem, &xndx);
    2207             : 
    2208       38543 :           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       38543 :           else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
    2261       82772 :             printf ("\
    2262             :   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
    2263             :                     class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2264       20693 :                     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       20693 :                     ? 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       41386 :                     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       17850 :               secshdr = gelf_getshdr (elf_getscn (ebl->elf,
    2280       17850 :                                                   sym->st_shndx == SHN_XINDEX
    2281           0 :                                                   ? xndx : sym->st_shndx),
    2282             :                                       &secshdr_mem);
    2283             : 
    2284       17850 :               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       53550 :                 printf ("\
    2298             :   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
    2299             :                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
    2300       17850 :                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
    2301             :                         /* Avoid the leading R_ which isn't carrying any
    2302             :                            information.  */
    2303       17850 :                         ? 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       17850 :                         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       14947 :   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       14885 :       GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
    2455             : 
    2456       14885 :       if (unlikely (sym == NULL))
    2457           0 :         continue;
    2458             : 
    2459             :       /* Determine the real section index.  */
    2460       14885 :       if (likely (sym->st_shndx != SHN_XINDEX))
    2461       14885 :         xndx = sym->st_shndx;
    2462             : 
    2463      119080 :       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       14885 :               ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
    2470             :                                     typebuf, sizeof (typebuf)),
    2471       14885 :               ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
    2472             :                                        bindbuf, sizeof (bindbuf)),
    2473       14885 :               get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
    2474       14885 :               ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
    2475             :                                 sizeof (scnbuf), NULL, shnum),
    2476       29770 :               elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
    2477             : 
    2478       14885 :       if (versym_data != NULL)
    2479             :         {
    2480             :           /* Get the version information.  */
    2481             :           GElf_Versym versym_mem;
    2482        1392 :           GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
    2483             : 
    2484        1392 :           if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
    2485             :             {
    2486        1186 :               bool is_nobits = false;
    2487        1186 :               bool check_def = xndx != SHN_UNDEF;
    2488             : 
    2489        1186 :               if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
    2490             :                 {
    2491             :                   GElf_Shdr symshdr_mem;
    2492        1150 :                   GElf_Shdr *symshdr =
    2493        1150 :                     gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
    2494             : 
    2495        1150 :                   is_nobits = (symshdr != NULL
    2496        1150 :                                && symshdr->sh_type == SHT_NOBITS);
    2497             :                 }
    2498             : 
    2499        1186 :               if (is_nobits || ! check_def)
    2500             :                 {
    2501             :                   /* We must test both.  */
    2502             :                   GElf_Vernaux vernaux_mem;
    2503         810 :                   GElf_Vernaux *vernaux = NULL;
    2504         810 :                   size_t vn_offset = 0;
    2505             : 
    2506             :                   GElf_Verneed verneed_mem;
    2507         810 :                   GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
    2508             :                                                            &verneed_mem);
    2509        4046 :                   while (verneed != NULL)
    2510             :                     {
    2511        3236 :                       size_t vna_offset = vn_offset;
    2512             : 
    2513        3236 :                       vernaux = gelf_getvernaux (verneed_data,
    2514        3236 :                                                  vna_offset += verneed->vn_aux,
    2515             :                                                  &vernaux_mem);
    2516        9821 :                       while (vernaux != NULL
    2517        6585 :                              && vernaux->vna_other != *versym
    2518        5775 :                              && vernaux->vna_next != 0)
    2519             :                         {
    2520             :                           /* Update the offset.  */
    2521        3349 :                           vna_offset += vernaux->vna_next;
    2522             : 
    2523        3349 :                           vernaux = (vernaux->vna_next == 0
    2524             :                                      ? NULL
    2525        3349 :                                      : gelf_getvernaux (verneed_data,
    2526             :                                                         vna_offset,
    2527             :                                                         &vernaux_mem));
    2528             :                         }
    2529             : 
    2530             :                       /* Check whether we found the version.  */
    2531        3236 :                       if (vernaux != NULL && vernaux->vna_other == *versym)
    2532             :                         /* Found it.  */
    2533             :                         break;
    2534             : 
    2535        2426 :                       vn_offset += verneed->vn_next;
    2536             :                       verneed = (verneed->vn_next == 0
    2537             :                                  ? NULL
    2538        2426 :                                  : gelf_getverneed (verneed_data, vn_offset,
    2539             :                                                     &verneed_mem));
    2540             :                     }
    2541             : 
    2542         810 :                   if (vernaux != NULL && vernaux->vna_other == *versym)
    2543             :                     {
    2544        2430 :                       printf ("@%s (%u)",
    2545             :                               elf_strptr (ebl->elf, verneed_stridx,
    2546         810 :                                           vernaux->vna_name),
    2547             :                               (unsigned int) vernaux->vna_other);
    2548         810 :                       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       14885 :       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         122 : get_ver_flags (unsigned int flags)
    2628             : {
    2629             :   static char buf[32];
    2630             :   char *endp;
    2631             : 
    2632         122 :   if (flags == 0)
    2633         117 :     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         119 :       for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
    2709             :         {
    2710             :           GElf_Vernaux auxmem;
    2711          82 :           GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
    2712          82 :           if (unlikely (aux == NULL))
    2713             :             break;
    2714             : 
    2715         410 :           printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
    2716             :                   auxoffset,
    2717         164 :                   elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
    2718          82 :                   get_ver_flags (aux->vna_flags),
    2719          82 :                   (unsigned short int) aux->vna_other);
    2720             : 
    2721          82 :           if (aux->vna_next == 0)
    2722             :             break;
    2723             : 
    2724          45 :           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         119 :               for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
    2927             :                 {
    2928             :                   GElf_Vernaux auxmem;
    2929             :                   GElf_Vernaux *aux;
    2930             : 
    2931          82 :                   aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
    2932          82 :                   if (unlikely (aux == NULL))
    2933             :                     break;
    2934             : 
    2935          82 :                   nvername = MAX (nvername,
    2936             :                                   (size_t) (aux->vna_other & 0x7fff));
    2937             : 
    2938          82 :                   if (aux->vna_next == 0)
    2939             :                     break;
    2940          45 :                   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         119 :               for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
    3023             :                 {
    3024             :                   GElf_Vernaux auxmem;
    3025          82 :                   GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
    3026             :                                                        &auxmem);
    3027          82 :                   if (unlikely (aux == NULL))
    3028             :                     break;
    3029             : 
    3030          82 :                   vername[aux->vna_other & 0x7fff]
    3031         164 :                     = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
    3032          82 :                   filename[aux->vna_other & 0x7fff]
    3033         164 :                     = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
    3034             : 
    3035          82 :                   if (aux->vna_next == 0)
    3036             :                     break;
    3037          45 :                   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        1315 :   for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
    3077             :     {
    3078        1305 :       if (cnt % 2 == 0)
    3079             :         printf ("\n %4d:", cnt);
    3080             : 
    3081             :       GElf_Versym symmem;
    3082        1305 :       GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
    3083        1305 :       if (sym == NULL)
    3084             :         break;
    3085             : 
    3086        1305 :       switch (*sym)
    3087             :         {
    3088             :           ssize_t n;
    3089         112 :         case 0:
    3090         112 :           fputs_unlocked (gettext ("   0 *local*                     "),
    3091             :                           stdout);
    3092             :           break;
    3093             : 
    3094          20 :         case 1:
    3095          20 :           fputs_unlocked (gettext ("   1 *global*                    "),
    3096             :                           stdout);
    3097             :           break;
    3098             : 
    3099        1173 :         default:
    3100        4692 :           n = printf ("%4d%c%s",
    3101        1173 :                       *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
    3102             :                       (vername != NULL
    3103        1173 :                        && (unsigned int) (*sym & 0x7fff) < nvername)
    3104        1173 :                       ? vername[*sym & 0x7fff] : "???");
    3105        1173 :           if ((unsigned int) (*sym & 0x7fff) < nvername
    3106        1173 :               && filename != NULL && filename[*sym & 0x7fff] != NULL)
    3107        1594 :             n += printf ("(%s)", filename[*sym & 0x7fff]);
    3108        1173 :           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          51 :       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
    3166             :         {
    3167          41 :           nzero_counts += counts[cnt] * cnt;
    3168         123 :           printf (gettext ("\
    3169             : %7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
    3170          41 :                   (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
    3171          41 :                   (nzero_counts * 100.0) / nsyms);
    3172             :         }
    3173             : 
    3174             :       Elf32_Word acc = 0;
    3175          41 :       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
    3176             :         {
    3177          41 :           acc += cnt;
    3178          41 :           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         222 :         Elf32_Word inner = bucket[cnt] - symbias;
    3380             :         do
    3381             :           {
    3382         425 :             ++nsyms;
    3383         425 :             if (maxlength < ++lengths[cnt])
    3384          41 :               ++maxlength;
    3385         425 :             if (inner >= max_nsyms)
    3386             :               goto invalid_data;
    3387             :           }
    3388         425 :         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      607252 : 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      607252 :   GElf_Off off = 0;
    3734     1821728 :   const char *name = (print_address_names && ! print_unresolved_addresses)
    3735      607152 :     ? dwfl_module_addrinfo (dwflmod, address, &off, &sym, NULL, NULL, NULL)
    3736     1214404 :     : NULL;
    3737             : 
    3738             :   const char *scn;
    3739      607252 :   if (print_unresolved_addresses)
    3740             :     {
    3741          72 :       address = raw;
    3742          72 :       scn = NULL;
    3743             :     }
    3744             :   else
    3745             :     {
    3746             :       /* Relativize the address.  */
    3747      607180 :       int n = dwfl_module_relocations (dwflmod);
    3748      607180 :       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      606180 :              : dwfl_module_relocation_info (dwflmod, i, NULL));
    3753             :     }
    3754             : 
    3755      607252 :   if ((name != NULL
    3756      596149 :        ? (off != 0
    3757             :           ? (scn != NULL
    3758             :              ? (address_size == 0
    3759      293160 :                 ? printf ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">",
    3760             :                           scn, address, name, off)
    3761     1273923 :                 : printf ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">",
    3762      424641 :                           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       53130 :                 : printf ("%s+%#0*" PRIx64 " <%s>",
    3774       17710 :                            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       11208 :              ? printf ("%s+%#" PRIx64, scn, address)
    3782       10678 :              : printf ("%s+%#0*" PRIx64, scn, 2 + address_size * 2, address))
    3783             :           : (address_size == 0
    3784          64 :              ? printf ("%#" PRIx64, address)
    3785     1810653 :              : printf ("%#0*" PRIx64, 2 + address_size * 2, address)))) < 0)
    3786           0 :     error (EXIT_FAILURE, 0, _("sprintf failure"));
    3787      607252 : }
    3788             : 
    3789             : 
    3790             : static const char *
    3791      772619 : dwarf_tag_string (unsigned int tag)
    3792             : {
    3793      772619 :   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     2722670 : dwarf_attr_string (unsigned int attrnum)
    3806             : {
    3807     2722670 :   switch (attrnum)
    3808             :     {
    3809             : #define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
    3810        4383 :       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     2722676 : dwarf_form_string (unsigned int form)
    3820             : {
    3821     2722676 :   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        2859 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3857        2859 :     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       16417 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    3874       16417 :     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      380372 :   if (likely (code < sizeof (known) / sizeof (known[0])))
    4030      380372 :     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     6238510 : 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     6238510 :   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      772619 : dwarf_tag_name (unsigned int tag)
    4122             : {
    4123      772619 :   const char *ret = dwarf_tag_string (tag);
    4124      772619 :   return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true);
    4125             : }
    4126             : 
    4127             : static const char *
    4128     2722670 : dwarf_attr_name (unsigned int attr)
    4129             : {
    4130     2722670 :   const char *ret = dwarf_attr_string (attr);
    4131     2722670 :   return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true);
    4132             : }
    4133             : 
    4134             : 
    4135             : static const char *
    4136     2722676 : dwarf_form_name (unsigned int form)
    4137             : {
    4138     2722676 :   const char *ret = dwarf_form_string (form);
    4139     2722676 :   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        2859 :   const char *ret = dwarf_inline_string (code);
    4155        2859 :   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       16417 :   const char *ret = dwarf_encoding_string (code);
    4163       16417 :   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      267298 : 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      267298 :   const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
    4323             : 
    4324      267298 :   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      647670 :   while (len-- > 0)
    4335             :     {
    4336      380372 :       uint_fast8_t op = *data++;
    4337             : 
    4338      760744 :       const char *op_name = dwarf_locexpr_opcode_string (op);
    4339      380372 :       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      380372 :       switch (op)
    4350             :         {
    4351        7461 :         case DW_OP_addr:;
    4352             :           /* Address operand.  */
    4353             :           Dwarf_Word addr;
    4354        7461 :           NEED (addrsize);
    4355        7461 :           if (addrsize == 4)
    4356          28 :             addr = read_4ubyte_unaligned (dbg, data);
    4357        7443 :           else if (addrsize == 8)
    4358        7461 :             addr = read_8ubyte_unaligned (dbg, data);
    4359             :           else
    4360             :             goto invalid;
    4361        7461 :           data += addrsize;
    4362        7461 :           CONSUME (addrsize);
    4363             : 
    4364        7461 :           printf ("%*s[%2" PRIuMAX "] %s ",
    4365             :                   indent, "", (uintmax_t) offset, op_name);
    4366        7461 :           print_dwarf_addr (dwflmod, 0, addr, addr);
    4367        7461 :           printf ("\n");
    4368             : 
    4369        7461 :           offset += 1 + addrsize;
    4370      387833 :           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        9509 :         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        9509 :           NEED (1);
    4397       19018 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 "\n",
    4398             :                   indent, "", (uintmax_t) offset,
    4399        9509 :                   op_name, *((uint8_t *) data));
    4400        9509 :           ++data;
    4401        9509 :           --len;
    4402        9509 :           offset += 2;
    4403        9509 :           break;
    4404             : 
    4405         948 :         case DW_OP_const2u:
    4406         948 :           NEED (2);
    4407             :           // XXX value might be modified by relocation
    4408        2844 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu16 "\n",
    4409             :                   indent, "", (uintmax_t) offset,
    4410        1896 :                   op_name, read_2ubyte_unaligned (dbg, data));
    4411         948 :           CONSUME (2);
    4412         948 :           data += 2;
    4413         948 :           offset += 3;
    4414         948 :           break;
    4415             : 
    4416         576 :         case DW_OP_const4u:
    4417         576 :           NEED (4);
    4418             :           // XXX value might be modified by relocation
    4419        1728 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu32 "\n",
    4420             :                   indent, "", (uintmax_t) offset,
    4421        1152 :                   op_name, read_4ubyte_unaligned (dbg, data));
    4422         576 :           CONSUME (4);
    4423         576 :           data += 4;
    4424         576 :           offset += 5;
    4425         576 :           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        2107 :         case DW_OP_const1s:
    4439        2107 :           NEED (1);
    4440             :           // XXX value might be modified by relocation
    4441        4214 :           printf ("%*s[%2" PRIuMAX "] %s %" PRId8 "\n",
    4442             :                   indent, "", (uintmax_t) offset,
    4443        2107 :                   op_name, *((int8_t *) data));
    4444        2107 :           ++data;
    4445        2107 :           --len;
    4446        2107 :           offset += 2;
    4447        2107 :           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        7815 :         case DW_OP_piece:
    4483             :         case DW_OP_regx:
    4484             :         case DW_OP_plus_uconst:
    4485             :         case DW_OP_constu:;
    4486        7815 :           const unsigned char *start = data;
    4487             :           uint64_t uleb;
    4488        7815 :           NEED (1);
    4489        7815 :           get_uleb128 (uleb, data, data + len);
    4490        7815 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
    4491             :                   indent, "", (uintmax_t) offset, op_name, uleb);
    4492        7815 :           CONSUME (data - start);
    4493        7815 :           offset += 1 + (data - start);
    4494        7815 :           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       68809 :         case DW_OP_fbreg:
    4530             :         case DW_OP_breg0 ... DW_OP_breg31:
    4531             :         case DW_OP_consts:
    4532       68809 :           start = data;
    4533             :           int64_t sleb;
    4534       68809 :           NEED (1);
    4535       68809 :           get_sleb128 (sleb, data, data + len);
    4536       68809 :           printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
    4537             :                   indent, "", (uintmax_t) offset, op_name, sleb);
    4538       68809 :           CONSUME (data - start);
    4539       68809 :           offset += 1 + (data - start);
    4540       68809 :           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         269 :         case DW_OP_skip:
    4575             :         case DW_OP_bra:
    4576         269 :           NEED (2);
    4577         269 :           printf ("%*s[%2" PRIuMAX "] %s %" PRIuMAX "\n",
    4578             :                   indent, "", (uintmax_t) offset, op_name,
    4579         269 :                   (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
    4580         269 :           CONSUME (2);
    4581         269 :           data += 2;
    4582         269 :           offset += 3;
    4583         269 :           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        3542 :         case DW_OP_implicit_pointer:
    4599             :         case DW_OP_GNU_implicit_pointer:
    4600             :           /* DIE offset operand.  */
    4601        3542 :           start = data;
    4602        3542 :           NEED (ref_size);
    4603        3542 :           if (ref_size != 4 && ref_size != 8)
    4604             :             goto invalid; /* Cannot be used in CFA.  */
    4605        3542 :           if (ref_size == 4)
    4606        3542 :             addr = read_4ubyte_unaligned (dbg, data);
    4607             :           else
    4608           0 :             addr = read_8ubyte_unaligned (dbg, data);
    4609        3542 :           data += ref_size;
    4610             :           /* Byte offset operand.  */
    4611        3542 :           NEED (1);
    4612        3542 :           get_sleb128 (sleb, data, data + len);
    4613             : 
    4614        7084 :           printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
    4615             :                   indent, "", (intmax_t) offset,
    4616             :                   op_name, (uintmax_t) addr, sleb);
    4617        3542 :           CONSUME (data - start);
    4618        3542 :           offset += 1 + (data - start);
    4619        3542 :           break;
    4620             : 
    4621       20399 :         case DW_OP_entry_value:
    4622             :         case DW_OP_GNU_entry_value:
    4623             :           /* Size plus expression block.  */
    4624       20399 :           start = data;
    4625       20399 :           NEED (1);
    4626       20399 :           get_uleb128 (uleb, data, data + len);
    4627       20399 :           printf ("%*s[%2" PRIuMAX "] %s:\n",
    4628             :                   indent, "", (uintmax_t) offset, op_name);
    4629       20399 :           NEED (uleb);
    4630       20399 :           print_ops (dwflmod, dbg, indent + 5, indent + 5, vers,
    4631             :                      addrsize, offset_size, cu, uleb, data);
    4632       20399 :           data += uleb;
    4633       20399 :           CONSUME (data - start);
    4634       20399 :           offset += 1 + (data - start);
    4635       20399 :           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      258422 :         default:
    4738             :           /* No Operand.  */
    4739      258422 :           printf ("%*s[%2" PRIuMAX "] %s\n",
    4740             :                   indent, "", (uintmax_t) offset, op_name);
    4741      258422 :           ++offset;
    4742      258422 :           break;
    4743             :         }
    4744             : 
    4745      380372 :       indent = indentrest;
    4746      380372 :       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       57510 : 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       57510 :   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       57510 :   return base;
    4786             : }
    4787             : 
    4788             : static Dwarf_Addr
    4789       57510 : listptr_base (struct listptr *p)
    4790             : {
    4791      115020 :   Dwarf_Die cu = CUDIE (p->cu);
    4792       57510 :   return cudie_base (&cu);
    4793             : }
    4794             : 
    4795             : static int
    4796      319295 : compare_listptr (const void *a, const void *b, void *arg)
    4797             : {
    4798      319295 :   const char *name = arg;
    4799      319295 :   struct listptr *p1 = (void *) a;
    4800      319295 :   struct listptr *p2 = (void *) b;
    4801             : 
    4802      319295 :   if (p1->offset < p2->offset)
    4803             :     return -1;
    4804       21006 :   if (p1->offset > p2->offset)
    4805             :     return 1;
    4806             : 
    4807        4241 :   if (!p1->warned && !p2->warned)
    4808             :     {
    4809        4241 :       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        4241 :       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        4241 :       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        4241 :       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       53200 : 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       53200 :   if (print_debug_sections & section)
    4873             :     {
    4874       53099 :       if (table->n == table->alloc)
    4875             :         {
    4876         176 :           if (table->alloc == 0)
    4877          81 :             table->alloc = 128;
    4878             :           else
    4879          95 :             table->alloc *= 2;
    4880         176 :           table->table = xrealloc (table->table,
    4881         176 :                                    table->alloc * sizeof table->table[0]);
    4882             :         }
    4883             : 
    4884       53099 :       struct listptr *p = &table->table[table->n++];
    4885             : 
    4886      106198 :       *p = (struct listptr)
    4887             :         {
    4888       53099 :           .addr64 = address_size == 8,
    4889       53099 :           .dwarf64 = offset_size == 8,
    4890             :           .offset = offset,
    4891             :           .cu = cu,
    4892             :           .attr = attr
    4893             :         };
    4894             : 
    4895       53099 :       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       49022 : 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       49022 :   if (table->n == 0)
    4920             :     return false;
    4921             : 
    4922      102020 :   while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
    4923       52998 :     ++*idxp;
    4924             : 
    4925       49022 :   struct listptr *p = &table->table[*idxp];
    4926             : 
    4927       49022 :   if (*idxp == table->n
    4928       49022 :       || 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       49022 :   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       49022 :   if (address_sizep != NULL)
    4945       49022 :     *address_sizep = listptr_address_size (p);
    4946       49022 :   if (offset_sizep != NULL)
    4947       40092 :     *offset_sizep = listptr_offset_size (p);
    4948       49022 :   if (base != NULL)
    4949       49022 :     *base = listptr_base (p);
    4950       49022 :   if (cu != NULL)
    4951       49022 :     *cu = p->cu;
    4952       49022 :   if (attr != NULL)
    4953       40092 :     *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       56876 :         {
    5030             :           size_t length;
    5031             :           Dwarf_Abbrev abbrev;
    5032             : 
    5033       57963 :           int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
    5034       57963 :           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       56876 :           unsigned int code = dwarf_getabbrevcode (&abbrev);
    5051       56876 :           unsigned int tag = dwarf_getabbrevtag (&abbrev);
    5052       56876 :           int has_children = dwarf_abbrevhaschildren (&abbrev);
    5053             : 
    5054      113752 :           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       56876 :           size_t cnt = 0;
    5061             :           unsigned int name;
    5062             :           unsigned int form;
    5063             :           Dwarf_Sword data;
    5064             :           Dwarf_Off enoffset;
    5065      333733 :           while (dwarf_getabbrevattr_data (&abbrev, cnt, &name, &form,
    5066             :                                            &data, &enoffset) == 0)
    5067             :             {
    5068      439962 :               printf ("          attr: %s, form: %s",
    5069             :                       dwarf_attr_name (name), dwarf_form_name (form));
    5070      219981 :               if (form == DW_FORM_implicit_const)
    5071           0 :                 printf (" (%" PRId64 ")", data);
    5072      439962 :               printf (", offset: %#" PRIx64 "\n", (uint64_t) enoffset);
    5073      219981 :               ++cnt;
    5074             :             }
    5075             : 
    5076       56876 :           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        1084 :       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       38193 :   while (readp < endp)
    5964             :     {
    5965       38133 :       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
    5966       38133 :       Dwarf_CU *cu = last_cu;
    5967             : 
    5968       38133 :       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       38133 :       if (last_cu != cu)
    5974             :         {
    5975             :           Dwarf_Die cudie;
    5976         585 :           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         585 :             printf (gettext ("\n CU [%6" PRIx64 "] base: "),
    5982             :                     dwarf_dieoffset (&cudie));
    5983         585 :           print_dwarf_addr (dwflmod, address_size, base, base);
    5984         585 :           printf ("\n");
    5985             :         }
    5986       38133 :       last_cu = cu;
    5987             : 
    5988       38133 :       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       38133 :       if (address_size == 8)
    5997             :         {
    5998       38133 :           begin = read_8ubyte_unaligned_inc (dbg, readp);
    5999       38133 :           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       38133 :       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       38133 :       else if (begin == 0 && end == 0) /* End of list entry.  */
    6017             :         {
    6018        8930 :           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       29203 :           if (first)            /* First address range entry in a list.  */
    6026             :             printf (" [%6tx] ", offset);
    6027             :           else
    6028             :             printf ("          ");
    6029             : 
    6030       29203 :           printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
    6031       29203 :           if (! print_unresolved_addresses)
    6032             :             {
    6033       29193 :               printf ("          ");
    6034       29193 :               print_dwarf_addr (dwflmod, address_size, base + begin,
    6035             :                                 base + begin);
    6036       29193 :               printf ("..\n          ");
    6037       29193 :               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        9703 : 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        9703 :   ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
    6056             :                                  bits ?: &ignore, type ?: &ignore);
    6057        9703 :   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        9703 :       if (bits != NULL && *bits <= 0)
    6072           0 :         *bits = loc != NULL ? loc->bits : 0;
    6073        9703 :       if (type != NULL && *type == DW_ATE_void)
    6074           0 :         *type = DW_ATE_unsigned;
    6075             : 
    6076             :     }
    6077        9703 :   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        4631 : 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        8855 :     register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
    6148             :     return regnamebuf;
    6149             :   }
    6150             : 
    6151        4631 :   puts ("\n   Program:");
    6152        4631 :   Dwarf_Word pc = vma_base;
    6153       85567 :   while (readp < endp)
    6154             :     {
    6155       76305 :       unsigned int opcode = *readp++;
    6156             : 
    6157       76305 :       if (opcode < DW_CFA_advance_loc)
    6158             :         /* Extended opcode.  */
    6159       43983 :         switch (opcode)
    6160             :           {
    6161             :             uint64_t op1;
    6162             :             int64_t sop1;
    6163             :             uint64_t op2;
    6164             :             int64_t sop2;
    6165             : 
    6166       12910 :           case DW_CFA_nop:
    6167       12910 :             puts ("     nop");
    6168       56893 :             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        1661 :           case DW_CFA_advance_loc1:
    6177        1661 :             if ((uint64_t) (endp - readp) < 1)
    6178             :               goto invalid;
    6179        3322 :             printf ("     advance_loc1 %u to %#" PRIx64 "\n",
    6180        1661 :                     *readp, pc += *readp * code_align);
    6181        1661 :             ++readp;
    6182        1661 :             break;
    6183         761 :           case DW_CFA_advance_loc2:
    6184         761 :             if ((uint64_t) (endp - readp) < 2)
    6185             :               goto invalid;
    6186         761 :             op1 = read_2ubyte_unaligned_inc (dbg, readp);
    6187         761 :             printf ("     advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
    6188         761 :                     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        2616 :           case DW_CFA_remember_state:
    6238        2616 :             puts ("     remember_state");
    6239        2616 :             break;
    6240        2616 :           case DW_CFA_restore_state:
    6241        2616 :             puts ("     restore_state");
    6242        2616 :             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       23187 :           case DW_CFA_def_cfa_offset:
    6261       23187 :             if ((uint64_t) (endp - readp) < 1)
    6262             :               goto invalid;
    6263       23187 :             get_uleb128 (op1, readp, endp);
    6264       23187 :             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       32322 :       else if (opcode < DW_CFA_offset)
    6379       23663 :         printf ("     advance_loc %u to %#" PRIx64 "\n",
    6380       23663 :                 opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
    6381        8659 :       else if (opcode < DW_CFA_restore)
    6382             :         {
    6383             :           uint64_t offset;
    6384        7341 :           if ((uint64_t) (endp - readp) < 1)
    6385             :             goto invalid;
    6386        7341 :           get_uleb128 (offset, readp, endp);
    6387       14682 :           printf ("     offset r%u (%s) at cfa%+" PRId64 "\n",
    6388             :                   opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
    6389             :         }
    6390             :       else
    6391        2636 :         printf ("     restore r%u (%s)\n",
    6392             :                 opcode & 0x3f, regname (opcode & 0x3f));
    6393             :     }
    6394             : }
    6395             : 
    6396             : 
    6397             : static unsigned int
    6398        4559 : encoded_ptr_size (int encoding, unsigned int ptr_size)
    6399             : {
    6400        4559 :   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        4741 :   while (readp < dataend)
    6569             :     {
    6570        4645 :       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        4645 :       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
    6581             : 
    6582        4689 :       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
    6583        4645 :       unsigned int length = 4;
    6584        4645 :       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        4645 :       if (unlikely (unit_length == 0))
    6594             :         {
    6595          28 :           printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
    6596          14 :           continue;
    6597             :         }
    6598             : 
    6599        4631 :       Dwarf_Word maxsize = dataend - readp;
    6600        4631 :       if (unlikely (unit_length > maxsize))
    6601             :         goto invalid_data;
    6602             : 
    6603        4631 :       unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    6604             : 
    6605        4631 :       ptrdiff_t start = readp - (unsigned char *) data->d_buf;
    6606        4631 :       const unsigned char *const cieend = readp + unit_length;
    6607        4631 :       if (unlikely (cieend > dataend))
    6608             :         goto invalid_data;
    6609             : 
    6610             :       Dwarf_Off cie_id;
    6611        4631 :       if (length == 4)
    6612             :         {
    6613        4631 :           if (unlikely (cieend - readp < 4))
    6614             :             goto invalid_data;
    6615        4675 :           cie_id = read_4ubyte_unaligned_inc (dbg, readp);
    6616        4631 :           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        4631 :       uint_fast8_t version = 2;
    6627             :       unsigned int code_alignment_factor;
    6628             :       int data_alignment_factor;
    6629        4631 :       unsigned int fde_encoding = 0;
    6630        4631 :       unsigned int lsda_encoding = 0;
    6631        4631 :       Dwarf_Word initial_location = 0;
    6632        4631 :       Dwarf_Word vma_base = 0;
    6633             : 
    6634        4631 :       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        4559 :           while (cie != NULL)
    6774        9118 :             if (is_eh_frame
    6775        4521 :                 ? ((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        4559 :           if (unlikely (cie == NULL))
    6781             :             {
    6782           0 :               puts ("invalid CIE reference in FDE");
    6783           0 :               return;
    6784             :             }
    6785             : 
    6786             :           /* Initialize from CIE data.  */
    6787        4559 :           fde_encoding = cie->fde_encoding;
    6788        4559 :           lsda_encoding = cie->lsda_encoding;
    6789        4559 :           ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
    6790        4559 :           code_alignment_factor = cie->code_alignment_factor;
    6791        4559 :           data_alignment_factor = cie->data_alignment_factor;
    6792             : 
    6793        4559 :           const unsigned char *base = readp;
    6794             :           // XXX There are sometimes relocations for this value
    6795        4581 :           initial_location = read_addr_unaligned_inc (ptr_size, dbg, readp);
    6796        4559 :           Dwarf_Word address_range
    6797        4581 :             = 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        4559 :           Dwarf_Addr pc_start = initial_location;
    6805        4559 :           if (ptr_size == 4)
    6806        4519 :             pc_start = (uint64_t) (int32_t) pc_start;
    6807        4559 :           if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
    6808        9030 :             pc_start += ((uint64_t) shdr->sh_addr
    6809        4515 :                          + (base - (const unsigned char *) data->d_buf)
    6810        4515 :                          - bias);
    6811             : 
    6812        9118 :           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        4559 :           print_dwarf_addr (dwflmod, cie->address_size,
    6818             :                             pc_start, initial_location);
    6819        4559 :           if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
    6820             :             {
    6821        9030 :               vma_base = (((uint64_t) shdr->sh_offset
    6822        4515 :                            + (base - (const unsigned char *) data->d_buf)
    6823        4515 :                            + (uint64_t) initial_location)
    6824             :                           & (ptr_size == 4
    6825             :                              ? UINT64_C (0xffffffff)
    6826        4515 :                              : UINT64_C (0xffffffffffffffff)));
    6827        4515 :               printf (gettext (" (offset: %#" PRIx64 ")"),
    6828             :                       (uint64_t) vma_base);
    6829             :             }
    6830             : 
    6831        4559 :           printf ("\n   address_range:            %#" PRIx64,
    6832             :                   (uint64_t) address_range);
    6833        4559 :           if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
    6834        4515 :             printf (gettext (" (end offset: %#" PRIx64 ")"),
    6835        4515 :                     ((uint64_t) vma_base + (uint64_t) address_range)
    6836             :                     & (ptr_size == 4
    6837             :                        ? UINT64_C (0xffffffff)
    6838        4515 :                        : UINT64_C (0xffffffffffffffff)));
    6839        4559 :           putchar ('\n');
    6840             : 
    6841        4559 :           if (cie->augmentation[0] == 'z')
    6842             :             {
    6843             :               unsigned int augmentationlen;
    6844        4515 :               if (cieend - readp < 1)
    6845             :                 goto invalid_data;
    6846        4515 :               get_uleb128 (augmentationlen, readp, cieend);
    6847             : 
    6848        4515 :               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        4515 :               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        4515 :               readp += augmentationlen;
    6887             :             }
    6888             :         }
    6889             : 
    6890             :       /* Handle the initialization instructions.  */
    6891        4631 :       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        4631 :         print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
    6895             :                            data_alignment_factor, version, ptr_size,
    6896             :                            fde_encoding, dwflmod, ebl, dbg);
    6897        4631 :       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      100207 : die_type_sign_bytes (Dwarf_Die *die, bool *is_signed, int *bytes)
    6907             : {
    6908             :   Dwarf_Attribute attr;
    6909             :   Dwarf_Die type;
    6910             : 
    6911      100207 :   *bytes = 0;
    6912      100207 :   *is_signed = false;
    6913             : 
    6914      100207 :   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      100207 : }
    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     2507048 : attr_callback (Dwarf_Attribute *attrp, void *arg)
    6946             : {
    6947     2507048 :   struct attrcb_args *cbargs = (struct attrcb_args *) arg;
    6948     2507048 :   const int level = cbargs->level;
    6949     2507048 :   Dwarf_Die *die = cbargs->die;
    6950     2507048 :   bool is_split = cbargs->is_split;
    6951             : 
    6952     2507048 :   unsigned int attr = dwarf_whatattr (attrp);
    6953     2507048 :   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     2507048 :   unsigned int form = dwarf_whatform (attrp);
    6963     2507048 :   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     2507048 :   switch (form)
    6973             :     {
    6974       39542 :     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       39542 :       if (!cbargs->silent)
    6982             :         {
    6983             :           Dwarf_Addr addr;
    6984       39273 :           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       39273 :           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       39265 :             printf ("           %*s%-20s (%s) ",
    7009             :                     (int) (level * 2), "", dwarf_attr_name (attr),
    7010             :                     dwarf_form_name (form));
    7011       39273 :           print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr, addr);
    7012       39273 :           printf ("\n");
    7013             :         }
    7014     2247020 :       break;
    7015             : 
    7016      466328 :     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      466328 :       if (cbargs->silent)
    7028             :         break;
    7029      465580 :       const char *str = dwarf_formstring (attrp);
    7030      465580 :       if (unlikely (str == NULL))
    7031             :         goto attrval_out;
    7032      465580 :       printf ("           %*s%-20s (%s) \"%s\"\n",
    7033             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7034             :               dwarf_form_name (form), str);
    7035             :       break;
    7036             : 
    7037      595253 :     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      595253 :       if (cbargs->silent)
    7047             :         break;
    7048             :       Dwarf_Die ref;
    7049      594466 :       if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
    7050             :         goto attrval_out;
    7051             : 
    7052     1188932 :       printf ("           %*s%-20s (%s) ",
    7053             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7054             :               dwarf_form_name (form));
    7055      594466 :       if (is_split)
    7056          33 :         printf ("{%6" PRIxMAX "}\n", (uintmax_t) dwarf_dieoffset (&ref));
    7057             :       else
    7058      594433 :         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     1248084 :     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     1248084 :       if (unlikely (dwarf_formudata (attrp, &num) != 0))
    7082             :         goto attrval_out;
    7083             : 
    7084     1248084 :       const char *valuestr = NULL;
    7085     1248084 :       bool as_hex_id = false;
    7086     1248084 :       switch (attr)
    7087             :         {
    7088             :           /* This case can take either a constant or a loclistptr.  */
    7089      206763 :         case DW_AT_data_member_location:
    7090      206763 :           if (form != DW_FORM_sec_offset
    7091      206763 :               && (cbargs->version >= 4
    7092       23806 :                   || (form != DW_FORM_data4 && form != DW_FORM_data8)))
    7093             :             {
    7094      206763 :               if (!cbargs->silent)
    7095      206763 :                 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       42224 :             if (cbargs->cu->version < 5)
    7120             :               {
    7121       42153 :                 if (! cbargs->is_split)
    7122             :                   {
    7123      126399 :                     nlpt = notice_listptr (section_loc, &known_locsptr,
    7124       42133 :                                            cbargs->addrsize,
    7125       42133 :                                            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       42224 :             if (!cbargs->silent)
    7148             :               {
    7149       42043 :                 if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
    7150       42036 :                   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       11019 :         case DW_AT_ranges:
    7179             :         case DW_AT_start_scope:
    7180             :           {
    7181             :             bool nlpt;
    7182       11019 :             if (cbargs->cu->version < 5)
    7183       33009 :               nlpt = notice_listptr (section_ranges, &known_rangelistptr,
    7184       22006 :                                      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       11019 :             if (!cbargs->silent)
    7202             :               {
    7203       10977 :                 if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
    7204       10975 :                   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       16417 :         case DW_AT_encoding:
    7267       32834 :           valuestr = dwarf_encoding_name (num);
    7268       16417 :           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        2859 :         case DW_AT_inline:
    7288        5718 :           valuestr = dwarf_inline_name (num);
    7289        2859 :           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      366893 :         case DW_AT_decl_file:
    7297             :         case DW_AT_call_file:
    7298      366893 :           {
    7299      366893 :             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      366472 :             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      366472 :                 if (dwarf_getsrcfiles (&cudie, &files, &nfiles) == 0)
    7312             :                   {
    7313      366472 :                     valuestr = dwarf_filesrc (files, num, NULL, NULL);
    7314      366472 :                     if (valuestr != NULL)
    7315             :                       {
    7316      366472 :                         char *filename = strrchr (valuestr, '/');
    7317      366472 :                         if (filename != NULL)
    7318      366472 :                           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      366472 :             if (valuestr == NULL)
    7332             :               valuestr = "???";
    7333             :           }
    7334      366472 :           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      988056 :       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      986215 :       if (attr == DW_AT_high_pc && dwarf_highpc (cbargs->die, &highpc) == 0)
    7351             :         {
    7352       27524 :           printf ("           %*s%-20s (%s) %" PRIuMAX " (",
    7353             :                   (int) (level * 2), "", dwarf_attr_name (attr),
    7354             :                   dwarf_form_name (form), (uintmax_t) num);
    7355       13762 :           print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, highpc, highpc);
    7356             :           printf (")\n");
    7357             :         }
    7358             :       else
    7359             :         {
    7360      972453 :           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      972451 :             {
    7368      972451 :               Dwarf_Sword snum = 0;
    7369             :               bool is_signed;
    7370      972451 :               int bytes = 0;
    7371      972451 :               if (attr == DW_AT_const_value)
    7372      100207 :                 die_type_sign_bytes (cbargs->die, &is_signed, &bytes);
    7373             :               else
    7374     1744488 :                 is_signed = (form == DW_FORM_sdata
    7375      872244 :                              || form == DW_FORM_implicit_const);
    7376             : 
    7377      972451 :               if (is_signed)
    7378         144 :                 if (unlikely (dwarf_formsdata (attrp, &snum) != 0))
    7379             :                   goto attrval_out;
    7380             : 
    7381      972451 :               if (valuestr == NULL)
    7382             :                 {
    7383      585854 :                   printf ("           %*s%-20s (%s) ",
    7384             :                           (int) (level * 2), "", dwarf_attr_name (attr),
    7385             :                           dwarf_form_name (form));
    7386             :                 }
    7387             :               else
    7388             :                 {
    7389      386597 :                   printf ("           %*s%-20s (%s) %s (",
    7390             :                           (int) (level * 2), "", dwarf_attr_name (attr),
    7391             :                           dwarf_form_name (form), valuestr);
    7392             :                 }
    7393             : 
    7394      972451 :               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      972244 :                 default:
    7425      972244 :                   if (is_signed)
    7426          21 :                     printf ("%" PRIdMAX, (intmax_t) snum);
    7427             :                   else
    7428      972223 :                     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      972451 :               if (attr == DW_AT_const_value
    7435      100207 :                   && (form == DW_FORM_sdata || form == DW_FORM_implicit_const)
    7436        1227 :                   && !is_signed)
    7437        1219 :                 printf (" (%" PRIdMAX ")", (intmax_t) num);
    7438             : 
    7439      972451 :               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       65933 :     case DW_FORM_flag_present:
    7460       65933 :       if (cbargs->silent)
    7461             :         break;
    7462       65659 :       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       82782 :     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       82782 :       if (cbargs->silent)
    7474             :         break;
    7475             :       Dwarf_Block block;
    7476       82653 :       if (unlikely (dwarf_formblock (attrp, &block) != 0))
    7477             :         goto attrval_out;
    7478             : 
    7479      165306 :       printf ("           %*s%-20s (%s) ",
    7480             :               (int) (level * 2), "", dwarf_attr_name (attr),
    7481             :               dwarf_form_name (form));
    7482             : 
    7483       82653 :       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       82637 :           if (form != DW_FORM_data16)
    7517             :             {
    7518       82637 :               putchar ('\n');
    7519      165274 :               print_ops (cbargs->dwflmod, cbargs->dbg,
    7520       82637 :                          12 + level * 2, 12 + level * 2,
    7521             :                          cbargs->version, cbargs->addrsize, cbargs->offset_size,
    7522       82637 :                          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     2247020 :   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      715566 :   do_cu:
    7693             :   do
    7694             :     {
    7695      716731 :       Dwarf_Off offset = dwarf_dieoffset (&dies[level]);
    7696      716731 :       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      716731 :       int tag = dwarf_tag (&dies[level]);
    7705      716731 :       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      716731 :       if (!silent)
    7715             :         {
    7716      715743 :           unsigned int code = dwarf_getabbrevcode (dies[level].abbrev);
    7717      715743 :           if (is_split)
    7718             :             printf (" {%6" PRIx64 "}  ", (uint64_t) offset);
    7719             :           else
    7720             :             printf (" [%6" PRIx64 "]  ", (uint64_t) offset);
    7721      715743 :           printf ("%*s%-20s abbrev: %u\n", (int) (level * 2), "",
    7722             :                   dwarf_tag_name (tag), code);
    7723             :         }
    7724             : 
    7725             :       /* Print the attribute values.  */
    7726      716731 :       args.level = level;
    7727      716731 :       args.die = &dies[level];
    7728      716731 :       (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
    7729             : 
    7730             :       /* Make room for the next level's DIE.  */
    7731      716731 :       if (level + 1 == maxdies)
    7732           0 :         dies = (Dwarf_Die *) xrealloc (dies,
    7733           0 :                                        (maxdies += 10)
    7734             :                                        * sizeof (Dwarf_Die));
    7735             : 
    7736      716731 :       int res = dwarf_child (&dies[level], &dies[level + 1]);
    7737      716731 :       if (res > 0)
    7738             :         {
    7739      716731 :           while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
    7740      102282 :             if (level-- == 0)
    7741             :               break;
    7742             : 
    7743      615614 :           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      101117 :       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      716731 :   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        1097 :       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        8148 :           while (*linep != 0)
    8448             :             {
    8449        7053 :               unsigned char *endp = memchr (linep, '\0', lineendp - linep);
    8450        7053 :               if (unlikely (endp == NULL))
    8451             :                 goto invalid_unit;
    8452             : 
    8453       14106 :               printf (" %s\n", (char *) linep);
    8454             : 
    8455        7053 :               linep = endp + 1;
    8456             :             }
    8457             :           /* Skip the final NUL byte.  */
    8458        1095 :           ++linep;
    8459             :         }
    8460             : 
    8461        1097 :       if (unlikely (linep >= lineendp))
    8462             :         goto invalid_unit;
    8463             : 
    8464        1097 :       puts (gettext ("\nFile name table:"));
    8465        1097 :       if (version > 4)
    8466             :         {
    8467             :           struct encpair { uint16_t desc; uint16_t form; };
    8468             :           struct encpair enc[256];
    8469             : 
    8470           4 :           printf (gettext ("      ["));
    8471           2 :           if ((size_t) (lineendp - linep) < 1)
    8472             :             goto invalid_data;
    8473           2 :           unsigned char file_name_format_count = *linep++;
    8474           8 :           for (int i = 0; i < file_name_format_count; i++)
    8475             :             {
    8476             :               uint64_t desc, form;
    8477           4 :               if ((size_t) (lineendp - linep) < 1)
    8478             :                 goto invalid_data;
    8479           4 :               get_uleb128 (desc, linep, lineendp);
    8480           4 :               if ((size_t) (lineendp - linep) < 1)
    8481             :                 goto invalid_data;
    8482           4 :               get_uleb128 (form, linep, lineendp);
    8483             : 
    8484           4 :               if (! libdw_valid_user_form (form))
    8485             :                 goto invalid_data;
    8486             : 
    8487             :               enc[i].desc = desc;
    8488           4 :               enc[i].form = form;
    8489             : 
    8490           8 :               printf ("%s(%s)",
    8491             :                       dwarf_line_content_description_name (desc),
    8492             :                       dwarf_form_name (form));
    8493           4 :               if (i + 1 < file_name_format_count)
    8494             :                 printf (", ");
    8495             :             }
    8496           2 :           printf ("]\n");
    8497             : 
    8498             :           uint64_t file_name_count;
    8499           2 :           if ((size_t) (lineendp - linep) < 1)
    8500             :             goto invalid_data;
    8501           2 :           get_uleb128 (file_name_count, linep, lineendp);
    8502             : 
    8503           4 :           if (file_name_format_count == 0
    8504           2 :               && file_name_count != 0)
    8505             :             goto invalid_data;
    8506             : 
    8507           8 :           for (uint64_t i = 0; i < file_name_count; i++)
    8508             :             {
    8509           8 :               printf (" %-5" PRIu64 " ", i);
    8510          32 :               for (int j = 0; j < file_name_format_count; j++)
    8511             :                 {
    8512          16 :                   linep = print_form_data (dbg, enc[j].form,
    8513             :                                            linep, lineendp, length,
    8514             :                                            str_offsets_base);
    8515          16 :                   if (j + 1 < file_name_format_count)
    8516             :                     printf (", ");
    8517             :                 }
    8518           8 :               printf ("\n");
    8519           8 :               if (linep >= lineendp)
    8520             :                 goto invalid_unit;
    8521             :             }
    8522             :         }
    8523             :       else
    8524             :         {
    8525        1095 :           puts (gettext (" Entry Dir   Time      Size      Name"));
    8526       22156 :           for (unsigned int cnt = 1; *linep != 0; ++cnt)
    8527             :             {
    8528             :               /* First comes the file name.  */
    8529       21061 :               char *fname = (char *) linep;
    8530       21061 :               unsigned char *endp = memchr (fname, '\0', lineendp - linep);
    8531       21061 :               if (unlikely (endp == NULL))
    8532             :                 goto invalid_unit;
    8533       21061 :               linep = endp + 1;
    8534             : 
    8535             :               /* Then the index.  */
    8536             :               unsigned int diridx;
    8537       21061 :               if (lineendp - linep < 1)
    8538             :                 goto invalid_unit;
    8539       21061 :               get_uleb128 (diridx, linep, lineendp);
    8540             : 
    8541             :               /* Next comes the modification time.  */
    8542             :               unsigned int mtime;
    8543       21061 :               if (lineendp - linep < 1)
    8544             :                 goto invalid_unit;
    8545       21061 :               get_uleb128 (mtime, linep, lineendp);
    8546             : 
    8547             :               /* Finally the length of the file.  */
    8548             :               unsigned int fsize;
    8549       21061 :               if (lineendp - linep < 1)
    8550             :                 goto invalid_unit;
    8551       21061 :               get_uleb128 (fsize, linep, lineendp);
    8552             : 
    8553       21061 :               printf (" %-5u %-5u %-9u %-9u %s\n",
    8554             :                       cnt, diridx, mtime, fsize, fname);
    8555             :             }
    8556             :           /* Skip the final NUL byte.  */
    8557        1095 :           ++linep;
    8558             :         }
    8559             : 
    8560        1097 :       puts (gettext ("\nLine number statements:"));
    8561             :       Dwarf_Word address = 0;
    8562             :       unsigned int op_index = 0;
    8563        1097 :       size_t line = 1;
    8564        1097 :       uint_fast8_t is_stmt = default_is_stmt;
    8565             : 
    8566             :       /* Apply the "operation advance" from a special opcode
    8567             :          or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
    8568             :       unsigned int op_addr_advance;
    8569             :       bool show_op_index;
    8570             :       inline void advance_pc (unsigned int op_advance)
    8571             :       {
    8572      300062 :         op_addr_advance = minimum_instr_len * ((op_index + op_advance)
    8573      150031 :                                                / max_ops_per_instr);
    8574      150031 :         address += op_addr_advance;
    8575      300062 :         show_op_index = (op_index > 0 ||
    8576      150031 :                          (op_index + op_advance) % max_ops_per_instr > 0);
    8577      150031 :         op_index = (op_index + op_advance) % max_ops_per_instr;
    8578             :       }
    8579             : 
    8580        1097 :       if (max_ops_per_instr == 0)
    8581             :         {
    8582           0 :           error (0, 0,
    8583           0 :                  gettext ("invalid maximum operations per instruction is zero"));
    8584           0 :           linep = lineendp;
    8585           0 :           continue;
    8586             :         }
    8587             : 
    8588      243402 :       while (linep < lineendp)
    8589             :         {
    8590      242305 :           size_t offset = linep - (const unsigned char *) data->d_buf;
    8591             :           unsigned int u128;
    8592             :           int s128;
    8593             : 
    8594             :           /* Read the opcode.  */
    8595      242305 :           unsigned int opcode = *linep++;
    8596             : 
    8597      242305 :           printf (" [%6" PRIx64 "]", (uint64_t)offset);
    8598             :           /* Is this a special opcode?  */
    8599      242305 :           if (likely (opcode >= opcode_base))
    8600             :             {
    8601      111302 :               if (unlikely (line_range == 0))
    8602             :                 goto invalid_unit;
    8603             : 
    8604             :               /* Yes.  Handling this is quite easy since the opcode value
    8605             :                  is computed with
    8606             : 
    8607             :                  opcode = (desired line increment - line_base)
    8608             :                            + (line_range * address advance) + opcode_base
    8609             :               */
    8610      111302 :               int line_increment = (line_base
    8611      111302 :                                     + (opcode - opcode_base) % line_range);
    8612             : 
    8613             :               /* Perform the increments.  */
    8614      111302 :               line += line_increment;
    8615      222604 :               advance_pc ((opcode - opcode_base) / line_range);
    8616             : 
    8617      222604 :               printf (gettext (" special opcode %u: address+%u = "),
    8618             :                       opcode, op_addr_advance);
    8619      111302 :               print_dwarf_addr (dwflmod, 0, address, address);
    8620      111302 :               if (show_op_index)
    8621           0 :                 printf (gettext (", op_index = %u, line%+d = %zu\n"),
    8622             :                         op_index, line_increment, line);
    8623             :               else
    8624      111302 :                 printf (gettext (", line%+d = %zu\n"),
    8625             :                         line_increment, line);
    8626             :             }
    8627      131003 :           else if (opcode == 0)
    8628             :             {
    8629             :               /* This an extended opcode.  */
    8630       12846 :               if (unlikely (linep + 2 > lineendp))
    8631             :                 goto invalid_unit;
    8632             : 
    8633             :               /* The length.  */
    8634       12846 :               unsigned int len = *linep++;
    8635             : 
    8636       12846 :               if (unlikely (linep + len > lineendp))
    8637             :                 goto invalid_unit;
    8638             : 
    8639             :               /* The sub-opcode.  */
    8640       12846 :               opcode = *linep++;
    8641             : 
    8642       25692 :               printf (gettext (" extended opcode %u: "), opcode);
    8643             : 
    8644       12846 :               switch (opcode)
    8645             :                 {
    8646        1126 :                 case DW_LNE_end_sequence:
    8647        1126 :                   puts (gettext (" end of sequence"));
    8648             : 
    8649             :                   /* Reset the registers we care about.  */
    8650             :                   address = 0;
    8651             :                   op_index = 0;
    8652        1126 :                   line = 1;
    8653        1126 :                   is_stmt = default_is_stmt;
    8654        1126 :                   break;
    8655             : 
    8656        1254 :                 case DW_LNE_set_address:
    8657             :                   op_index = 0;
    8658        1254 :                   if (unlikely ((size_t) (lineendp - linep) < address_size))
    8659             :                     goto invalid_unit;
    8660        1254 :                   if (address_size == 4)
    8661          17 :                     address = read_4ubyte_unaligned_inc (dbg, linep);
    8662             :                   else
    8663        1256 :                     address = read_8ubyte_unaligned_inc (dbg, linep);
    8664             :                   {
    8665        2508 :                     printf (gettext (" set address to "));
    8666        1254 :                     print_dwarf_addr (dwflmod, 0, address, address);
    8667             :                     printf ("\n");
    8668             :                   }
    8669             :                   break;
    8670             : 
    8671           0 :                 case DW_LNE_define_file:
    8672             :                   {
    8673           0 :                     char *fname = (char *) linep;
    8674           0 :                     unsigned char *endp = memchr (linep, '\0',
    8675           0 :                                                   lineendp - linep);
    8676           0 :                     if (unlikely (endp == NULL))
    8677             :                       goto invalid_unit;
    8678           0 :                     linep = endp + 1;
    8679             : 
    8680             :                     unsigned int diridx;
    8681           0 :                     if (lineendp - linep < 1)
    8682             :                       goto invalid_unit;
    8683           0 :                     get_uleb128 (diridx, linep, lineendp);
    8684             :                     Dwarf_Word mtime;
    8685           0 :                     if (lineendp - linep < 1)
    8686             :                       goto invalid_unit;
    8687           0 :                     get_uleb128 (mtime, linep, lineendp);
    8688             :                     Dwarf_Word filelength;
    8689           0 :                     if (lineendp - linep < 1)
    8690             :                       goto invalid_unit;
    8691           0 :                     get_uleb128 (filelength, linep, lineendp);
    8692             : 
    8693           0 :                     printf (gettext ("\
    8694             :  define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
    8695             :                             diridx, (uint64_t) mtime, (uint64_t) filelength,
    8696             :                             fname);
    8697             :                   }
    8698             :                   break;
    8699             : 
    8700       10466 :                 case DW_LNE_set_discriminator:
    8701             :                   /* Takes one ULEB128 parameter, the discriminator.  */
    8702       10466 :                   if (unlikely (standard_opcode_lengths[opcode] != 1))
    8703             :                     goto invalid_unit;
    8704             : 
    8705       10466 :                   get_uleb128 (u128, linep, lineendp);
    8706       10466 :                   printf (gettext (" set discriminator to %u\n"), u128);
    8707             :                   break;
    8708             : 
    8709           0 :                 default:
    8710             :                   /* Unknown, ignore it.  */
    8711           0 :                   puts (gettext (" unknown opcode"));
    8712           0 :                   linep += len - 1;
    8713           0 :                   break;
    8714             :                 }
    8715             :             }
    8716      118157 :           else if (opcode <= DW_LNS_set_isa)
    8717             :             {
    8718             :               /* This is a known standard opcode.  */
    8719      118157 :               switch (opcode)
    8720             :                 {
    8721        8388 :                 case DW_LNS_copy:
    8722             :                   /* Takes no argument.  */
    8723        8388 :                   puts (gettext (" copy"));
    8724        8388 :                   break;
    8725             : 
    8726       12204 :                 case DW_LNS_advance_pc:
    8727             :                   /* Takes one uleb128 parameter which is added to the
    8728             :                      address.  */
    8729       12204 :                   get_uleb128 (u128, linep, lineendp);
    8730       12204 :                   advance_pc (u128);
    8731             :                   {
    8732       24408 :                     printf (gettext (" advance address by %u to "),
    8733             :                             op_addr_advance);
    8734       12204 :                     print_dwarf_addr (dwflmod, 0, address, address);
    8735       12204 :                     if (show_op_index)
    8736           0 :                       printf (gettext (", op_index to %u"), op_index);
    8737             :                     printf ("\n");
    8738             :                   }
    8739             :                   break;
    8740             : 
    8741       48103 :                 case DW_LNS_advance_line:
    8742             :                   /* Takes one sleb128 parameter which is added to the
    8743             :                      line.  */
    8744       48103 :                   get_sleb128 (s128, linep, lineendp);
    8745       48103 :                   line += s128;
    8746       48103 :                   printf (gettext ("\
    8747             :  advance line by constant %d to %" PRId64 "\n"),
    8748             :                           s128, (int64_t) line);
    8749             :                   break;
    8750             : 
    8751       18325 :                 case DW_LNS_set_file:
    8752             :                   /* Takes one uleb128 parameter which is stored in file.  */
    8753       18325 :                   get_uleb128 (u128, linep, lineendp);
    8754       18325 :                   printf (gettext (" set file to %" PRIu64 "\n"),
    8755             :                           (uint64_t) u128);
    8756             :                   break;
    8757             : 
    8758         131 :                 case DW_LNS_set_column:
    8759             :                   /* Takes one uleb128 parameter which is stored in column.  */
    8760         131 :                   if (unlikely (standard_opcode_lengths[opcode] != 1))
    8761             :                     goto invalid_unit;
    8762             : 
    8763         131 :                   get_uleb128 (u128, linep, lineendp);
    8764         131 :                   printf (gettext (" set column to %" PRIu64 "\n"),
    8765             :                           (uint64_t) u128);
    8766             :                   break;
    8767             : 
    8768        4458 :                 case DW_LNS_negate_stmt:
    8769             :                   /* Takes no argument.  */
    8770        4458 :                   is_stmt = 1 - is_stmt;
    8771        4458 :                   printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
    8772             :                           "is_stmt", is_stmt);
    8773             :                   break;
    8774             : 
    8775           0 :                 case DW_LNS_set_basic_block:
    8776             :                   /* Takes no argument.  */
    8777           0 :                   puts (gettext (" set basic block flag"));
    8778           0 :                   break;
    8779             : 
    8780       26525 :                 case DW_LNS_const_add_pc:
    8781             :                   /* Takes no argument.  */
    8782             : 
    8783       26525 :                   if (unlikely (line_range == 0))
    8784             :                     goto invalid_unit;
    8785             : 
    8786       53050 :                   advance_pc ((255 - opcode_base) / line_range);
    8787             :                   {
    8788       53050 :                     printf (gettext (" advance address by constant %u to "),
    8789             :                             op_addr_advance);
    8790       26525 :                     print_dwarf_addr (dwflmod, 0, address, address);
    8791       26525 :                     if (show_op_index)
    8792           0 :                       printf (gettext (", op_index to %u"), op_index);
    8793             :                     printf ("\n");
    8794             :                   }
    8795             :                   break;
    8796             : 
    8797          22 :                 case DW_LNS_fixed_advance_pc:
    8798             :                   /* Takes one 16 bit parameter which is added to the
    8799             :                      address.  */
    8800          22 :                   if (unlikely (standard_opcode_lengths[opcode] != 1))
    8801             :                     goto invalid_unit;
    8802             : 
    8803          22 :                   u128 = read_2ubyte_unaligned_inc (dbg, linep);
    8804          22 :                   address += u128;
    8805             :                   op_index = 0;
    8806             :                   {
    8807          44 :                     printf (gettext ("\
    8808             :  advance address by fixed value %u to \n"),
    8809             :                             u128);
    8810          22 :                     print_dwarf_addr (dwflmod, 0, address, address);
    8811             :                     printf ("\n");
    8812             :                   }
    8813             :                   break;
    8814             : 
    8815           1 :                 case DW_LNS_set_prologue_end:
    8816             :                   /* Takes no argument.  */
    8817           1 :                   puts (gettext (" set prologue end flag"));
    8818           1 :                   break;
    8819             : 
    8820           0 :                 case DW_LNS_set_epilogue_begin:
    8821             :                   /* Takes no argument.  */
    8822           0 :                   puts (gettext (" set epilogue begin flag"));
    8823           0 :                   break;
    8824             : 
    8825           0 :                 case DW_LNS_set_isa:
    8826             :                   /* Takes one uleb128 parameter which is stored in isa.  */
    8827           0 :                   if (unlikely (standard_opcode_lengths[opcode] != 1))
    8828             :                     goto invalid_unit;
    8829             : 
    8830           0 :                   get_uleb128 (u128, linep, lineendp);
    8831           0 :                   printf (gettext (" set isa to %u\n"), u128);
    8832             :                   break;
    8833             :                 }
    8834             :             }
    8835             :           else
    8836             :             {
    8837             :               /* This is a new opcode the generator but not we know about.
    8838             :                  Read the parameters associated with it but then discard
    8839             :                  everything.  Read all the parameters for this opcode.  */
    8840           0 :               printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
    8841             :                                 " unknown opcode with %" PRIu8 " parameters:",
    8842             :                                 standard_opcode_lengths[opcode]),
    8843           0 :                       standard_opcode_lengths[opcode]);
    8844           0 :               for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
    8845             :                 {
    8846           0 :                   get_uleb128 (u128, linep, lineendp);
    8847           0 :                   if (n != standard_opcode_lengths[opcode])
    8848           0 :                     putc_unlocked (',', stdout);
    8849           0 :                   printf (" %u", u128);
    8850             :                 }
    8851             : 
    8852             :               /* Next round, ignore this opcode.  */
    8853           0 :               continue;
    8854             :             }
    8855             :         }
    8856             :     }
    8857             : 
    8858             :   /* There must only be one data block.  */
    8859          46 :   assert (elf_getdata (scn, data) == NULL);
    8860             : }
    8861             : 
    8862             : 
    8863             : static void
    8864           3 : print_debug_loclists_section (Dwfl_Module *dwflmod,
    8865             :                               Ebl *ebl,
    8866             :                               GElf_Ehdr *ehdr __attribute__ ((unused)),
    8867             :                               Elf_Scn *scn, GElf_Shdr *shdr,
    8868             :                               Dwarf *dbg)
    8869             : {
    8870           6 :   printf (gettext ("\
    8871             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    8872             :           elf_ndxscn (scn), section_name (ebl, shdr),
    8873           3 :           (uint64_t) shdr->sh_offset);
    8874             : 
    8875           6 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_loclists]
    8876           3 :                     ?: elf_rawdata (scn, NULL));
    8877           3 :   if (unlikely (data == NULL))
    8878             :     {
    8879           0 :       error (0, 0, gettext ("cannot get .debug_loclists content: %s"),
    8880             :              elf_errmsg (-1));
    8881           0 :       return;
    8882             :     }
    8883             : 
    8884             :   /* For the listptr to get the base address/CU.  */
    8885           6 :   sort_listptr (&known_loclistsptr, "loclistsptr");
    8886           3 :   size_t listptr_idx = 0;
    8887             : 
    8888           3 :   const unsigned char *readp = data->d_buf;
    8889           3 :   const unsigned char *const dataend = ((unsigned char *) data->d_buf
    8890           3 :                                         + data->d_size);
    8891          10 :   while (readp < dataend)
    8892             :     {
    8893           4 :       if (unlikely (readp > dataend - 4))
    8894             :         {
    8895           0 :         invalid_data:
    8896           0 :           error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
    8897             :                  elf_ndxscn (scn), section_name (ebl, shdr));
    8898           0 :           return;
    8899             :         }
    8900             : 
    8901           4 :       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
    8902           8 :       printf (gettext ("Table at Offset 0x%" PRIx64 ":\n\n"),
    8903             :               (uint64_t) offset);
    8904             : 
    8905           4 :       uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
    8906           4 :       unsigned int offset_size = 4;
    8907           4 :       if (unlikely (unit_length == 0xffffffff))
    8908             :         {
    8909           0 :           if (unlikely (readp > dataend - 8))
    8910             :             goto invalid_data;
    8911             : 
    8912           0 :           unit_length = read_8ubyte_unaligned_inc (dbg, readp);
    8913           0 :           offset_size = 8;
    8914             :         }
    8915           8 :       printf (gettext (" Length:         %8" PRIu64 "\n"), unit_length);
    8916             : 
    8917             :       /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
    8918             :          bytes to complete the header.  And this unit cannot go beyond
    8919             :          the section data.  */
    8920           4 :       if (readp > dataend - 8
    8921           4 :           || unit_length < 8
    8922           4 :           || unit_length > (uint64_t) (dataend - readp))
    8923             :         goto invalid_data;
    8924             : 
    8925           4 :       const unsigned char *nexthdr = readp + unit_length;
    8926             : 
    8927           4 :       uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
    8928           8 :       printf (gettext (" DWARF version:  %8" PRIu16 "\n"), version);
    8929             : 
    8930           4 :       if (version != 5)
    8931             :         {
    8932           0 :           error (0, 0, gettext ("Unknown version"));
    8933             :           goto next_table;
    8934             :         }
    8935             : 
    8936           4 :       uint8_t address_size = *readp++;
    8937           8 :       printf (gettext (" Address size:   %8" PRIu64 "\n"),
    8938             :               (uint64_t) address_size);
    8939             : 
    8940           4 :       if (address_size != 4 && address_size != 8)
    8941             :         {
    8942           0 :           error (0, 0, gettext ("unsupported address size"));
    8943             :           goto next_table;
    8944             :         }
    8945             : 
    8946           4 :       uint8_t segment_size = *readp++;
    8947           8 :       printf (gettext (" Segment size:   %8" PRIu64 "\n"),
    8948             :               (uint64_t) segment_size);
    8949             : 
    8950           4 :       if (segment_size != 0)
    8951             :         {
    8952           0 :           error (0, 0, gettext ("unsupported segment size"));
    8953             :           goto next_table;
    8954             :         }
    8955             : 
    8956           4 :       uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
    8957           8 :       printf (gettext (" Offset entries: %8" PRIu64 "\n"),
    8958             :               (uint64_t) offset_entry_count);
    8959             : 
    8960             :       /* We need the CU that uses this unit to get the initial base address. */
    8961           4 :       Dwarf_Addr cu_base = 0;
    8962           4 :       struct Dwarf_CU *cu = NULL;
    8963           4 :       if (listptr_cu (&known_loclistsptr, &listptr_idx,
    8964             :                       (Dwarf_Off) offset,
    8965           4 :                       (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
    8966             :                       &cu_base, &cu)
    8967           0 :           || split_dwarf_cu_base (dbg, &cu, &cu_base))
    8968           4 :         {
    8969             :           Dwarf_Die cudie;
    8970           4 :           if (dwarf_cu_die (cu, &cudie,
    8971             :                             NULL, NULL, NULL, NULL,
    8972             :                             NULL, NULL) == NULL)
    8973           0 :             printf (gettext (" Unknown CU base: "));
    8974             :           else
    8975           4 :             printf (gettext (" CU [%6" PRIx64 "] base: "),
    8976             :                     dwarf_dieoffset (&cudie));
    8977           4 :           print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
    8978           4 :           printf ("\n");
    8979             :         }
    8980             :       else
    8981           0 :         printf (gettext (" Not associated with a CU.\n"));
    8982             : 
    8983           4 :       printf ("\n");
    8984             : 
    8985           4 :       const unsigned char *offset_array_start = readp;
    8986           4 :       if (offset_entry_count > 0)
    8987             :         {
    8988           2 :           uint64_t max_entries = (unit_length - 8) / offset_size;
    8989           2 :           if (offset_entry_count > max_entries)
    8990             :             {
    8991           0 :               error (0, 0,
    8992           0 :                      gettext ("too many offset entries for unit length"));
    8993           0 :               offset_entry_count = max_entries;
    8994             :             }
    8995             : 
    8996           4 :           printf (gettext ("  Offsets starting at 0x%" PRIx64 ":\n"),
    8997             :                   (uint64_t) (offset_array_start
    8998           2 :                               - (unsigned char *) data->d_buf));
    8999          18 :           for (uint32_t idx = 0; idx < offset_entry_count; idx++)
    9000             :             {
    9001          16 :               printf ("   [%6" PRIu32 "] ", idx);
    9002          16 :               if (offset_size == 4)
    9003             :                 {
    9004          16 :                   uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
    9005             :                   printf ("0x%" PRIx32 "\n", off);
    9006             :                 }
    9007             :               else
    9008             :                 {
    9009           0 :                   uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
    9010             :                   printf ("0x%" PRIx64 "\n", off);
    9011             :                 }
    9012             :             }
    9013             :           printf ("\n");
    9014             :         }
    9015             : 
    9016           4 :       Dwarf_Addr base = cu_base;
    9017           4 :       bool start_of_list = true;
    9018          97 :       while (readp < nexthdr)
    9019             :         {
    9020          89 :           uint8_t kind = *readp++;
    9021             :           uint64_t op1, op2, len;
    9022             : 
    9023             :           /* Skip padding.  */
    9024          89 :           if (start_of_list && kind == DW_LLE_end_of_list)
    9025           0 :             continue;
    9026             : 
    9027          89 :           if (start_of_list)
    9028             :             {
    9029          32 :               base = cu_base;
    9030          96 :               printf ("  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
    9031          32 :                       (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
    9032          32 :                       (uint64_t) (readp - offset_array_start - 1));
    9033          32 :               start_of_list = false;
    9034             :             }
    9035             : 
    9036         178 :           printf ("    %s", dwarf_loc_list_encoding_name (kind));
    9037          89 :           switch (kind)
    9038             :             {
    9039          32 :             case DW_LLE_end_of_list:
    9040          32 :               start_of_list = true;
    9041             :               printf ("\n\n");
    9042             :               break;
    9043             : 
    9044           0 :             case DW_LLE_base_addressx:
    9045           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9046             :                 {
    9047           0 :                 invalid_entry:
    9048           0 :                   error (0, 0, gettext ("invalid loclists data"));
    9049             :                   goto next_table;
    9050             :                 }
    9051           0 :               get_uleb128 (op1, readp, nexthdr);
    9052           0 :               printf (" %" PRIx64 "\n", op1);
    9053           0 :               if (! print_unresolved_addresses)
    9054             :                 {
    9055             :                   Dwarf_Addr addr;
    9056           0 :                   if (get_indexed_addr (cu, op1, &addr) != 0)
    9057             :                     printf ("      ???\n");
    9058             :                   else
    9059             :                     {
    9060           0 :                       printf ("      ");
    9061           0 :                       print_dwarf_addr (dwflmod, address_size, addr, addr);
    9062             :                       printf ("\n");
    9063             :                     }
    9064             :                 }
    9065             :               break;
    9066             : 
    9067           0 :             case DW_LLE_startx_endx:
    9068           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9069             :                 goto invalid_entry;
    9070           0 :               get_uleb128 (op1, readp, nexthdr);
    9071           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9072             :                 goto invalid_entry;
    9073           0 :               get_uleb128 (op2, readp, nexthdr);
    9074           0 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    9075           0 :               if (! print_unresolved_addresses)
    9076             :                 {
    9077             :                   Dwarf_Addr addr1;
    9078             :                   Dwarf_Addr addr2;
    9079           0 :                   if (get_indexed_addr (cu, op1, &addr1) != 0
    9080           0 :                       || get_indexed_addr (cu, op2, &addr2) != 0)
    9081             :                     {
    9082           0 :                       printf ("      ???..\n");
    9083             :                       printf ("      ???\n");
    9084             :                     }
    9085             :                   else
    9086             :                     {
    9087           0 :                       printf ("      ");
    9088           0 :                       print_dwarf_addr (dwflmod, address_size, addr1, addr1);
    9089           0 :                       printf ("..\n      ");
    9090           0 :                       print_dwarf_addr (dwflmod, address_size,
    9091             :                                         addr2 - 1, addr2);
    9092             :                       printf ("\n");
    9093             :                     }
    9094             :                 }
    9095           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9096             :                 goto invalid_entry;
    9097           0 :               get_uleb128 (len, readp, nexthdr);
    9098           0 :               if ((uint64_t) (nexthdr - readp) < len)
    9099             :                 goto invalid_entry;
    9100           0 :               print_ops (dwflmod, dbg, 8, 8, version,
    9101             :                          address_size, offset_size, cu, len, readp);
    9102           0 :               readp += len;
    9103           0 :               break;
    9104             : 
    9105          26 :             case DW_LLE_startx_length:
    9106          26 :               if ((uint64_t) (nexthdr - readp) < 1)
    9107             :                 goto invalid_entry;
    9108          26 :               get_uleb128 (op1, readp, nexthdr);
    9109          26 :               if ((uint64_t) (nexthdr - readp) < 1)
    9110             :                 goto invalid_entry;
    9111          26 :               get_uleb128 (op2, readp, nexthdr);
    9112          26 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    9113          26 :               if (! print_unresolved_addresses)
    9114             :                 {
    9115             :                   Dwarf_Addr addr1;
    9116             :                   Dwarf_Addr addr2;
    9117          26 :                   if (get_indexed_addr (cu, op1, &addr1) != 0)
    9118             :                     {
    9119           0 :                       printf ("      ???..\n");
    9120             :                       printf ("      ???\n");
    9121             :                     }
    9122             :                   else
    9123             :                     {
    9124          26 :                       addr2 = addr1 + op2;
    9125          26 :                       printf ("      ");
    9126          26 :                       print_dwarf_addr (dwflmod, address_size, addr1, addr1);
    9127          26 :                       printf ("..\n      ");
    9128          26 :                       print_dwarf_addr (dwflmod, address_size,
    9129             :                                         addr2 - 1, addr2);
    9130             :                       printf ("\n");
    9131             :                     }
    9132             :                 }
    9133          26 :               if ((uint64_t) (nexthdr - readp) < 1)
    9134             :                 goto invalid_entry;
    9135          26 :               get_uleb128 (len, readp, nexthdr);
    9136          26 :               if ((uint64_t) (nexthdr - readp) < len)
    9137             :                 goto invalid_entry;
    9138          26 :               print_ops (dwflmod, dbg, 8, 8, version,
    9139             :                          address_size, offset_size, cu, len, readp);
    9140          26 :               readp += len;
    9141          26 :               break;
    9142             : 
    9143          24 :             case DW_LLE_offset_pair:
    9144          24 :               if ((uint64_t) (nexthdr - readp) < 1)
    9145             :                 goto invalid_entry;
    9146          24 :               get_uleb128 (op1, readp, nexthdr);
    9147          24 :               if ((uint64_t) (nexthdr - readp) < 1)
    9148             :                 goto invalid_entry;
    9149          24 :               get_uleb128 (op2, readp, nexthdr);
    9150          24 :               printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
    9151          24 :               if (! print_unresolved_addresses)
    9152             :                 {
    9153          24 :                   op1 += base;
    9154          24 :                   op2 += base;
    9155          24 :                   printf ("      ");
    9156          24 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    9157          24 :                   printf ("..\n      ");
    9158          24 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    9159             :                   printf ("\n");
    9160             :                 }
    9161          24 :               if ((uint64_t) (nexthdr - readp) < 1)
    9162             :                 goto invalid_entry;
    9163          24 :               get_uleb128 (len, readp, nexthdr);
    9164          24 :               if ((uint64_t) (nexthdr - readp) < len)
    9165             :                 goto invalid_entry;
    9166          24 :               print_ops (dwflmod, dbg, 8, 8, version,
    9167             :                          address_size, offset_size, cu, len, readp);
    9168          24 :               readp += len;
    9169          24 :               break;
    9170             : 
    9171           0 :             case DW_LLE_default_location:
    9172           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9173             :                 goto invalid_entry;
    9174           0 :               get_uleb128 (len, readp, nexthdr);
    9175           0 :               if ((uint64_t) (nexthdr - readp) < len)
    9176             :                 goto invalid_entry;
    9177           0 :               print_ops (dwflmod, dbg, 8, 8, version,
    9178             :                          address_size, offset_size, cu, len, readp);
    9179           0 :               readp += len;
    9180           0 :               break;
    9181             : 
    9182           5 :             case DW_LLE_base_address:
    9183           5 :               if (address_size == 4)
    9184             :                 {
    9185           0 :                   if ((uint64_t) (nexthdr - readp) < 4)
    9186             :                     goto invalid_entry;
    9187           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    9188             :                 }
    9189             :               else
    9190             :                 {
    9191           5 :                   if ((uint64_t) (nexthdr - readp) < 8)
    9192             :                     goto invalid_entry;
    9193           5 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    9194             :                 }
    9195           5 :               base = op1;
    9196           5 :               printf (" 0x%" PRIx64 "\n", base);
    9197           5 :               if (! print_unresolved_addresses)
    9198             :                 {
    9199           5 :                   printf ("      ");
    9200           5 :                   print_dwarf_addr (dwflmod, address_size, base, base);
    9201             :                   printf ("\n");
    9202             :                 }
    9203             :               break;
    9204             : 
    9205           0 :             case DW_LLE_start_end:
    9206           0 :               if (address_size == 4)
    9207             :                 {
    9208           0 :                   if ((uint64_t) (nexthdr - readp) < 8)
    9209             :                     goto invalid_entry;
    9210           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    9211           0 :                   op2 = read_4ubyte_unaligned_inc (dbg, readp);
    9212             :                 }
    9213             :               else
    9214             :                 {
    9215           0 :                   if ((uint64_t) (nexthdr - readp) < 16)
    9216             :                     goto invalid_entry;
    9217           0 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    9218           0 :                   op2 = read_8ubyte_unaligned_inc (dbg, readp);
    9219             :                 }
    9220           0 :               printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
    9221           0 :               if (! print_unresolved_addresses)
    9222             :                 {
    9223           0 :                   printf ("      ");
    9224           0 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    9225           0 :                   printf ("..\n      ");
    9226           0 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    9227             :                   printf ("\n");
    9228             :                 }
    9229           0 :               if ((uint64_t) (nexthdr - readp) < 1)
    9230             :                 goto invalid_entry;
    9231           0 :               get_uleb128 (len, readp, nexthdr);
    9232           0 :               if ((uint64_t) (nexthdr - readp) < len)
    9233             :                 goto invalid_entry;
    9234           0 :               print_ops (dwflmod, dbg, 8, 8, version,
    9235             :                          address_size, offset_size, cu, len, readp);
    9236           0 :               readp += len;
    9237           0 :               break;
    9238             : 
    9239           2 :             case DW_LLE_start_length:
    9240           2 :               if (address_size == 4)
    9241             :                 {
    9242           0 :                   if ((uint64_t) (nexthdr - readp) < 4)
    9243             :                     goto invalid_entry;
    9244           0 :                   op1 = read_4ubyte_unaligned_inc (dbg, readp);
    9245             :                 }
    9246             :               else
    9247             :                 {
    9248           2 :                   if ((uint64_t) (nexthdr - readp) < 8)
    9249             :                     goto invalid_entry;
    9250           2 :                   op1 = read_8ubyte_unaligned_inc (dbg, readp);
    9251             :                 }
    9252           2 :               if ((uint64_t) (nexthdr - readp) < 1)
    9253             :                 goto invalid_entry;
    9254           2 :               get_uleb128 (op2, readp, nexthdr);
    9255           2 :               printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
    9256           2 :               if (! print_unresolved_addresses)
    9257             :                 {
    9258           2 :                   op2 = op1 + op2;
    9259           2 :                   printf ("      ");
    9260           2 :                   print_dwarf_addr (dwflmod, address_size, op1, op1);
    9261           2 :                   printf ("..\n      ");
    9262           2 :                   print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
    9263             :                   printf ("\n");
    9264             :                 }
    9265           2 :               if ((uint64_t) (nexthdr - readp) < 1)
    9266             :                 goto invalid_entry;
    9267           2 :               get_uleb128 (len, readp, nexthdr);
    9268           2 :               if ((uint64_t) (nexthdr - readp) < len)
    9269             :                 goto invalid_entry;
    9270           2 :               print_ops (dwflmod, dbg, 8, 8, version,
    9271             :                          address_size, offset_size, cu, len, readp);
    9272           2 :               readp += len;
    9273           2 :               break;
    9274             : 
    9275             :             default:
    9276             :               goto invalid_entry;
    9277             :             }
    9278             :         }
    9279             : 
    9280           4 :     next_table:
    9281           4 :       if (readp != nexthdr)
    9282             :         {
    9283           0 :           size_t padding = nexthdr - readp;
    9284           0 :           printf (gettext ("   %zu padding bytes\n\n"), padding);
    9285           0 :           readp = nexthdr;
    9286             :         }
    9287             :     }
    9288             : }
    9289             : 
    9290             : 
    9291             : static void
    9292          44 : print_debug_loc_section (Dwfl_Module *dwflmod,
    9293             :                          Ebl *ebl, GElf_Ehdr *ehdr,
    9294             :                          Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    9295             : {
    9296          88 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_loc]
    9297          44 :                     ?: elf_rawdata (scn, NULL));
    9298             : 
    9299          44 :   if (unlikely (data == NULL))
    9300             :     {
    9301           0 :       error (0, 0, gettext ("cannot get .debug_loc content: %s"),
    9302             :              elf_errmsg (-1));
    9303           0 :       return;
    9304             :     }
    9305             : 
    9306          88 :   printf (gettext ("\
    9307             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    9308             :           elf_ndxscn (scn), section_name (ebl, shdr),
    9309          44 :           (uint64_t) shdr->sh_offset);
    9310             : 
    9311          88 :   sort_listptr (&known_locsptr, "loclistptr");
    9312          44 :   size_t listptr_idx = 0;
    9313             : 
    9314          44 :   uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
    9315          44 :   uint_fast8_t offset_size = 4;
    9316             : 
    9317          44 :   bool first = true;
    9318          44 :   Dwarf_Addr base = 0;
    9319          44 :   unsigned char *readp = data->d_buf;
    9320          44 :   unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
    9321          44 :   Dwarf_CU *last_cu = NULL;
    9322      204378 :   while (readp < endp)
    9323             :     {
    9324      204290 :       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
    9325      204290 :       Dwarf_CU *cu = last_cu;
    9326      204290 :       unsigned int attr = 0;
    9327             : 
    9328      204290 :       if (first && skip_listptr_hole (&known_locsptr, &listptr_idx,
    9329             :                                       &address_size, &offset_size, &base,
    9330             :                                       &cu, offset, &readp, endp, &attr))
    9331           0 :         continue;
    9332             : 
    9333      204290 :       if (last_cu != cu)
    9334             :        {
    9335             :         Dwarf_Die cudie;
    9336         974 :         if (dwarf_cu_die (cu, &cudie,
    9337             :                           NULL, NULL, NULL, NULL,
    9338             :                           NULL, NULL) == NULL)
    9339           0 :           printf (gettext ("\n Unknown CU base: "));
    9340             :         else
    9341         974 :           printf (gettext ("\n CU [%6" PRIx64 "] base: "),
    9342             :                   dwarf_dieoffset (&cudie));
    9343         974 :         print_dwarf_addr (dwflmod, address_size, base, base);
    9344         974 :         printf ("\n");
    9345             :        }
    9346      204290 :       last_cu = cu;
    9347             : 
    9348      204290 :       if (attr == DW_AT_GNU_locviews)
    9349             :         {
    9350           0 :           Dwarf_Off next_off = next_listptr_offset (&known_locsptr,
    9351             :                                                     listptr_idx);
    9352           0 :           const unsigned char *locp = readp;
    9353             :           const unsigned char *locendp;
    9354           0 :           if (next_off == 0
    9355           0 :               || next_off > (size_t) (endp
    9356           0 :                                       - (const unsigned char *) data->d_buf))
    9357             :             locendp = endp;
    9358             :           else
    9359           0 :             locendp = (const unsigned char *) data->d_buf + next_off;
    9360             : 
    9361           0 :           while (locp < locendp)
    9362             :             {
    9363             :               uint64_t v1, v2;
    9364           0 :               get_uleb128 (v1, locp, locendp);
    9365           0 :               if (locp >= locendp)
    9366             :                 {
    9367           0 :                   printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
    9368             :                   break;
    9369             :                 }
    9370           0 :               get_uleb128 (v2, locp, locendp);
    9371           0 :               if (first)                /* First view pair in a list.  */
    9372             :                 printf (" [%6tx] ", offset);
    9373             :               else
    9374             :                 printf ("          ");
    9375           0 :               printf ("view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
    9376           0 :               first = false;
    9377             :             }
    9378             : 
    9379           0 :           first = true;
    9380           0 :           readp = (unsigned char *) locendp;
    9381           0 :           continue;
    9382             :         }
    9383             : 
    9384             :       /* GNU DebugFission encoded addresses as addrx.  */
    9385      204290 :       bool is_debugfission = ((cu != NULL
    9386           0 :                                || split_dwarf_cu_base (dbg, &cu, &base))
    9387      408580 :                               && (cu->version < 5
    9388      204290 :                                   && cu->unit_type == DW_UT_split_compile));
    9389      204290 :       if (!is_debugfission
    9390      204230 :           && unlikely (data->d_size - offset < (size_t) address_size * 2))
    9391             :         {
    9392           0 :         invalid_data:
    9393           0 :           printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
    9394           0 :           break;
    9395             :         }
    9396             : 
    9397             :       Dwarf_Addr begin;
    9398             :       Dwarf_Addr end;
    9399      204290 :       bool use_base = true;
    9400      204290 :       if (is_debugfission)
    9401             :         {
    9402          60 :           const unsigned char *locp = readp;
    9403          60 :           const unsigned char *locendp = readp + data->d_size;
    9404          60 :           if (locp >= locendp)
    9405             :             goto invalid_data;
    9406             : 
    9407             :           Dwarf_Word idx;
    9408          60 :           unsigned char code = *locp++;
    9409          60 :           switch (code)
    9410             :             {
    9411          20 :             case DW_LLE_GNU_end_of_list_entry:
    9412          20 :               begin = 0;
    9413          20 :               end = 0;
    9414          20 :               break;
    9415             : 
    9416           0 :             case DW_LLE_GNU_base_address_selection_entry:
    9417           0 :               if (locp >= locendp)
    9418             :                 goto invalid_data;
    9419           0 :               begin = (Dwarf_Addr) -1;
    9420           0 :               get_uleb128 (idx, locp, locendp);
    9421           0 :               if (get_indexed_addr (cu, idx, &end) != 0)
    9422           0 :                 end = idx; /* ... */
    9423             :               break;
    9424             : 
    9425           0 :             case DW_LLE_GNU_start_end_entry:
    9426           0 :               if (locp >= locendp)
    9427             :                 goto invalid_data;
    9428           0 :               get_uleb128 (idx, locp, locendp);
    9429           0 :               if (get_indexed_addr (cu, idx, &begin) != 0)
    9430           0 :                 begin = idx; /* ... */
    9431           0 :               if (locp >= locendp)
    9432             :                 goto invalid_data;
    9433           0 :               get_uleb128 (idx, locp, locendp);
    9434           0 :               if (get_indexed_addr (cu, idx, &end) != 0)
    9435           0 :                 end = idx; /* ... */
    9436             :               use_base = false;
    9437             :               break;
    9438             : 
    9439          40 :             case DW_LLE_GNU_start_length_entry:
    9440          40 :               if (locp >= locendp)
    9441             :                 goto invalid_data;
    9442          40 :               get_uleb128 (idx, locp, locendp);
    9443          40 :               if (get_indexed_addr (cu, idx, &begin) != 0)
    9444           0 :                 begin = idx; /* ... */
    9445          40 :               if (locendp - locp < 4)
    9446             :                 goto invalid_data;
    9447          40 :               end = read_4ubyte_unaligned_inc (dbg, locp);
    9448          40 :               end += begin;
    9449          40 :               use_base = false;
    9450          40 :               break;
    9451             : 
    9452             :             default:
    9453             :                 goto invalid_data;
    9454             :             }
    9455             : 
    9456          60 :           readp = (unsigned char *) locp;
    9457             :         }
    9458      204230 :       else if (address_size == 8)
    9459             :         {
    9460      204284 :           begin = read_8ubyte_unaligned_inc (dbg, readp);
    9461      204284 :           end = read_8ubyte_unaligned_inc (dbg, readp);
    9462             :         }
    9463             :       else
    9464             :         {
    9465           0 :           begin = read_4ubyte_unaligned_inc (dbg, readp);
    9466           0 :           end = read_4ubyte_unaligned_inc (dbg, readp);
    9467           0 :           if (begin == (Dwarf_Addr) (uint32_t) -1)
    9468           0 :             begin = (Dwarf_Addr) -1l;
    9469             :         }
    9470             : 
    9471      204290 :       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
    9472             :         {
    9473           0 :           printf (gettext (" [%6tx] base address\n          "), offset);
    9474           0 :           print_dwarf_addr (dwflmod, address_size, end, end);
    9475           0 :           printf ("\n");
    9476           0 :           base = end;
    9477             :         }
    9478      204290 :       else if (begin == 0 && end == 0) /* End of list entry.  */
    9479             :         {
    9480       40092 :           if (first)
    9481           0 :             printf (gettext (" [%6tx] empty list\n"), offset);
    9482             :           first = true;
    9483             :         }
    9484             :       else
    9485             :         {
    9486             :           /* We have a location expression entry.  */
    9487      164198 :           uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
    9488             : 
    9489      164198 :           if (first)            /* First entry in a list.  */
    9490             :             printf (" [%6tx] ", offset);
    9491             :           else
    9492             :             printf ("          ");
    9493             : 
    9494      328396 :           printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
    9495      164198 :           if (! print_unresolved_addresses)
    9496             :             {
    9497      164168 :               Dwarf_Addr dab = use_base ? base + begin : begin;
    9498      164168 :               Dwarf_Addr dae = use_base ? base + end : end;
    9499      164168 :               printf ("          ");
    9500      164168 :               print_dwarf_addr (dwflmod, address_size, dab, dab);
    9501      164168 :               printf ("..\n          ");
    9502      164168 :               print_dwarf_addr (dwflmod, address_size, dae - 1, dae);
    9503             :               printf ("\n");
    9504             :             }
    9505             : 
    9506      164198 :           if (endp - readp <= (ptrdiff_t) len)
    9507             :             {
    9508           0 :               fputs (gettext ("   <INVALID DATA>\n"), stdout);
    9509           0 :               break;
    9510             :             }
    9511             : 
    9512      328396 :           print_ops (dwflmod, dbg, 11, 11,
    9513      164198 :                      cu != NULL ? cu->version : 3,
    9514             :                      address_size, offset_size, cu, len, readp);
    9515             : 
    9516      164198 :           first = false;
    9517      164198 :           readp += len;
    9518             :         }
    9519             :     }
    9520             : }
    9521             : 
    9522             : struct mac_culist
    9523             : {
    9524             :   Dwarf_Die die;
    9525             :   Dwarf_Off offset;
    9526             :   Dwarf_Files *files;
    9527             :   struct mac_culist *next;
    9528             : };
    9529             : 
    9530             : 
    9531             : static int
    9532           0 : mac_compare (const void *p1, const void *p2)
    9533             : {
    9534           0 :   struct mac_culist *m1 = (struct mac_culist *) p1;
    9535           0 :   struct mac_culist *m2 = (struct mac_culist *) p2;
    9536             : 
    9537           0 :   if (m1->offset < m2->offset)
    9538             :     return -1;
    9539           0 :   if (m1->offset > m2->offset)
    9540             :     return 1;
    9541           0 :   return 0;
    9542             : }
    9543             : 
    9544             : 
    9545             : static void
    9546           0 : print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
    9547             :                              Ebl *ebl,
    9548             :                              GElf_Ehdr *ehdr __attribute__ ((unused)),
    9549             :                              Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    9550             : {
    9551           0 :   printf (gettext ("\
    9552             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    9553             :           elf_ndxscn (scn), section_name (ebl, shdr),
    9554           0 :           (uint64_t) shdr->sh_offset);
    9555           0 :   putc_unlocked ('\n', stdout);
    9556             : 
    9557             :   /* There is no function in libdw to iterate over the raw content of
    9558             :      the section but it is easy enough to do.  */
    9559           0 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_macinfo]
    9560           0 :                     ?: elf_rawdata (scn, NULL));
    9561           0 :   if (unlikely (data == NULL))
    9562             :     {
    9563           0 :       error (0, 0, gettext ("cannot get macro information section data: %s"),
    9564             :              elf_errmsg (-1));
    9565           0 :       return;
    9566             :     }
    9567             : 
    9568             :   /* Get the source file information for all CUs.  */
    9569             :   Dwarf_Off offset;
    9570           0 :   Dwarf_Off ncu = 0;
    9571             :   size_t hsize;
    9572           0 :   struct mac_culist *culist = NULL;
    9573           0 :   size_t nculist = 0;
    9574           0 :   while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
    9575             :     {
    9576             :       Dwarf_Die cudie;
    9577           0 :       if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
    9578           0 :         continue;
    9579             : 
    9580             :       Dwarf_Attribute attr;
    9581           0 :       if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
    9582           0 :         continue;
    9583             : 
    9584             :       Dwarf_Word macoff;
    9585           0 :       if (dwarf_formudata (&attr, &macoff) != 0)
    9586           0 :         continue;
    9587             : 
    9588           0 :       struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
    9589           0 :       newp->die = cudie;
    9590           0 :       newp->offset = macoff;
    9591           0 :       newp->files = NULL;
    9592           0 :       newp->next = culist;
    9593           0 :       culist = newp;
    9594           0 :       ++nculist;
    9595             :     }
    9596             : 
    9597             :   /* Convert the list into an array for easier consumption.  */
    9598           0 :   struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
    9599             :                                                          * sizeof (*cus));
    9600             :   /* Add sentinel.  */
    9601           0 :   cus[nculist].offset = data->d_size;
    9602           0 :   cus[nculist].files = (Dwarf_Files *) -1l;
    9603           0 :   if (nculist > 0)
    9604             :     {
    9605           0 :       for (size_t cnt = nculist - 1; culist != NULL; --cnt)
    9606             :         {
    9607           0 :           assert (cnt < nculist);
    9608           0 :           cus[cnt] = *culist;
    9609           0 :           culist = culist->next;
    9610             :         }
    9611             : 
    9612             :       /* Sort the array according to the offset in the .debug_macinfo
    9613             :          section.  Note we keep the sentinel at the end.  */
    9614           0 :       qsort (cus, nculist, sizeof (*cus), mac_compare);
    9615             :     }
    9616             : 
    9617           0 :   const unsigned char *readp = (const unsigned char *) data->d_buf;
    9618           0 :   const unsigned char *readendp = readp + data->d_size;
    9619           0 :   int level = 1;
    9620             : 
    9621           0 :   while (readp < readendp)
    9622             :     {
    9623           0 :       unsigned int opcode = *readp++;
    9624             :       unsigned int u128;
    9625             :       unsigned int u128_2;
    9626             :       const unsigned char *endp;
    9627             : 
    9628           0 :       switch (opcode)
    9629             :         {
    9630           0 :         case DW_MACINFO_define:
    9631             :         case DW_MACINFO_undef:
    9632             :         case DW_MACINFO_vendor_ext:
    9633             :           /*  For the first two opcodes the parameters are
    9634             :                 line, string
    9635             :               For the latter
    9636             :                 number, string.
    9637             :               We can treat these cases together.  */
    9638           0 :           get_uleb128 (u128, readp, readendp);
    9639             : 
    9640           0 :           endp = memchr (readp, '\0', readendp - readp);
    9641           0 :           if (unlikely (endp == NULL))
    9642             :             {
    9643           0 :               printf (gettext ("\
    9644             : %*s*** non-terminated string at end of section"),
    9645             :                       level, "");
    9646             :               return;
    9647             :             }
    9648             : 
    9649           0 :           if (opcode == DW_MACINFO_define)
    9650           0 :             printf ("%*s#define %s, line %u\n",
    9651             :                     level, "", (char *) readp, u128);
    9652           0 :           else if (opcode == DW_MACINFO_undef)
    9653           0 :             printf ("%*s#undef %s, line %u\n",
    9654             :                     level, "", (char *) readp, u128);
    9655             :           else
    9656           0 :             printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
    9657             : 
    9658           0 :           readp = endp + 1;
    9659           0 :           break;
    9660             : 
    9661           0 :         case DW_MACINFO_start_file:
    9662             :           /* The two parameters are line and file index, in this order.  */
    9663           0 :           get_uleb128 (u128, readp, readendp);
    9664           0 :           if (readendp - readp < 1)
    9665             :             {
    9666           0 :               printf (gettext ("\
    9667             : %*s*** missing DW_MACINFO_start_file argument at end of section"),
    9668             :                       level, "");
    9669             :               return;
    9670             :             }
    9671           0 :           get_uleb128 (u128_2, readp, readendp);
    9672             : 
    9673             :           /* Find the CU DIE for this file.  */
    9674           0 :           size_t macoff = readp - (const unsigned char *) data->d_buf;
    9675           0 :           const char *fname = "???";
    9676           0 :           if (macoff >= cus[0].offset)
    9677             :             {
    9678           0 :               while (macoff >= cus[1].offset && cus[1].offset != data->d_size)
    9679           0 :                 ++cus;
    9680             : 
    9681           0 :               if (cus[0].files == NULL
    9682           0 :                 && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
    9683           0 :                 cus[0].files = (Dwarf_Files *) -1l;
    9684             : 
    9685           0 :               if (cus[0].files != (Dwarf_Files *) -1l)
    9686           0 :                 fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
    9687           0 :                          ?: "???");
    9688             :             }
    9689             : 
    9690           0 :           printf ("%*sstart_file %u, [%u] %s\n",
    9691             :                   level, "", u128, u128_2, fname);
    9692           0 :           ++level;
    9693           0 :           break;
    9694             : 
    9695           0 :         case DW_MACINFO_end_file:
    9696           0 :           --level;
    9697             :           printf ("%*send_file\n", level, "");
    9698             :           /* Nothing more to do.  */
    9699             :           break;
    9700             : 
    9701           0 :         default:
    9702             :           // XXX gcc seems to generate files with a trailing zero.
    9703           0 :           if (unlikely (opcode != 0 || readp != readendp))
    9704             :             printf ("%*s*** invalid opcode %u\n", level, "", opcode);
    9705             :           break;
    9706             :         }
    9707             :     }
    9708             : }
    9709             : 
    9710             : 
    9711             : static void
    9712           3 : print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
    9713             :                            Ebl *ebl,
    9714             :                            GElf_Ehdr *ehdr __attribute__ ((unused)),
    9715             :                            Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
    9716             : {
    9717           6 :   printf (gettext ("\
    9718             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
    9719             :           elf_ndxscn (scn), section_name (ebl, shdr),
    9720           3 :           (uint64_t) shdr->sh_offset);
    9721           6 :   putc_unlocked ('\n', stdout);
    9722             : 
    9723           3 :   Elf_Data *data =  elf_getdata (scn, NULL);
    9724           3 :   if (unlikely (data == NULL))
    9725             :     {
    9726           0 :       error (0, 0, gettext ("cannot get macro information section data: %s"),
    9727             :              elf_errmsg (-1));
    9728           0 :       return;
    9729             :     }
    9730             : 
    9731             :   /* Get the source file information for all CUs.  Uses same
    9732             :      datastructure as macinfo.  But uses offset field to directly
    9733             :      match .debug_line offset.  And just stored in a list.  */
    9734             :   Dwarf_Off offset;
    9735           3 :   Dwarf_Off ncu = 0;
    9736             :   size_t hsize;
    9737           3 :   struct mac_culist *culist = NULL;
    9738           3 :   size_t nculist = 0;
    9739          10 :   while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
    9740             :     {
    9741             :       Dwarf_Die cudie;
    9742           4 :       if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
    9743           0 :         continue;
    9744             : 
    9745             :       Dwarf_Attribute attr;
    9746           4 :       if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL)
    9747           0 :         continue;
    9748             : 
    9749             :       Dwarf_Word lineoff;
    9750           4 :       if (dwarf_formudata (&attr, &lineoff) != 0)
    9751           0 :         continue;
    9752             : 
    9753           4 :       struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
    9754           4 :       newp->die = cudie;
    9755           4 :       newp->offset = lineoff;
    9756           4 :       newp->files = NULL;
    9757           4 :       newp->next = culist;
    9758           4 :       culist = newp;
    9759           4 :       ++nculist;
    9760             :     }
    9761             : 
    9762           3 :   const unsigned char *readp = (const unsigned char *) data->d_buf;
    9763           3 :   const unsigned char *readendp = readp + data->d_size;
    9764             : 
    9765          14 :   while (readp < readendp)
    9766             :     {
    9767          16 :       printf (gettext (" Offset:             0x%" PRIx64 "\n"),
    9768           8 :               (uint64_t) (readp - (const unsigned char *) data->d_buf));
    9769             : 
    9770             :       // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
    9771             :       // optional vendor extension macro entry table.
    9772           8 :       if (readp + 2 > readendp)
    9773             :         {
    9774           0 :         invalid_data:
    9775           0 :           error (0, 0, gettext ("invalid data"));
    9776           0 :           return;
    9777             :         }
    9778           8 :       const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
    9779          16 :       printf (gettext (" Version:            %" PRIu16 "\n"), vers);
    9780             : 
    9781             :       // Version 4 is the GNU extension for DWARF4.  DWARF5 will use version
    9782             :       // 5 when it gets standardized.
    9783           8 :       if (vers != 4 && vers != 5)
    9784             :         {
    9785           0 :           printf (gettext ("  unknown version, cannot parse section\n"));
    9786             :           return;
    9787             :         }
    9788             : 
    9789           8 :       if (readp + 1 > readendp)
    9790             :         goto invalid_data;
    9791           8 :       const unsigned char flag = *readp++;
    9792          16 :       printf (gettext (" Flag:               0x%" PRIx8), flag);
    9793           8 :       if (flag != 0)
    9794             :         {
    9795           4 :           printf (" (");
    9796           4 :           if ((flag & 0x01) != 0)
    9797             :             {
    9798           0 :               printf ("offset_size");
    9799           0 :               if ((flag & 0xFE) !=  0)
    9800             :                 printf (", ");
    9801             :             }
    9802           4 :           if ((flag & 0x02) != 0)
    9803             :             {
    9804           4 :               printf ("debug_line_offset");
    9805           4 :               if ((flag & 0xFC) !=  0)
    9806             :                 printf (", ");
    9807             :             }
    9808           4 :           if ((flag & 0x04) != 0)
    9809             :             {
    9810           0 :               printf ("operands_table");
    9811           0 :               if ((flag & 0xF8) !=  0)
    9812             :                 printf (", ");
    9813             :             }
    9814           4 :           if ((flag & 0xF8) != 0)
    9815             :             printf ("unknown");
    9816             :           printf (")");
    9817             :         }
    9818           8 :       printf ("\n");
    9819             : 
    9820           8 :       unsigned int offset_len = (flag & 0x01) ? 8 : 4;
    9821          16 :       printf (gettext (" Offset length:      %" PRIu8 "\n"), offset_len);
    9822           8 :       Dwarf_Off line_offset = -1;
    9823           8 :       if (flag & 0x02)
    9824             :         {
    9825           4 :           if (offset_len == 8)
    9826           0 :             line_offset = read_8ubyte_unaligned_inc (dbg, readp);
    9827             :           else
    9828           4 :             line_offset = read_4ubyte_unaligned_inc (dbg, readp);
    9829           4 :           printf (gettext (" .debug_line offset: 0x%" PRIx64 "\n"),
    9830             :                   line_offset);
    9831             :         }
    9832             : 
    9833           4 :       struct mac_culist *cu = NULL;
    9834           4 :       if (line_offset != (Dwarf_Off) -1)
    9835             :         {
    9836             :           cu = culist;
    9837           5 :           while (cu != NULL && line_offset != cu->offset)
    9838           1 :             cu = cu->next;
    9839             :         }
    9840             : 
    9841           8 :       Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, (cu != NULL
    9842             :                                                                ? cu->die.cu
    9843             :                                                                : NULL));
    9844             : 
    9845             :       const unsigned char *vendor[DW_MACRO_hi_user - DW_MACRO_lo_user + 1];
    9846           8 :       memset (vendor, 0, sizeof vendor);
    9847           8 :       if (flag & 0x04)
    9848             :         {
    9849             :           // 1 byte length, for each item, 1 byte opcode, uleb128 number
    9850             :           // of arguments, for each argument 1 byte form code.
    9851           0 :           if (readp + 1 > readendp)
    9852             :             goto invalid_data;
    9853           0 :           unsigned int tlen = *readp++;
    9854           0 :           printf (gettext ("  extension opcode table, %" PRIu8 " items:\n"),
    9855             :                   tlen);
    9856           0 :           for (unsigned int i = 0; i < tlen; i++)
    9857             :             {
    9858           0 :               if (readp + 1 > readendp)
    9859             :                 goto invalid_data;
    9860           0 :               unsigned int opcode = *readp++;
    9861           0 :               printf (gettext ("    [%" PRIx8 "]"), opcode);
    9862           0 :               if (opcode < DW_MACRO_lo_user
    9863           0 :                   || opcode > DW_MACRO_hi_user)
    9864             :                 goto invalid_data;
    9865             :               // Record the start of description for this vendor opcode.
    9866             :               // uleb128 nr args, 1 byte per arg form.
    9867           0 :               vendor[opcode - DW_MACRO_lo_user] = readp;
    9868           0 :               if (readp + 1 > readendp)
    9869             :                 goto invalid_data;
    9870           0 :               unsigned int args = *readp++;
    9871           0 :               if (args > 0)
    9872             :                 {
    9873           0 :                   printf (gettext (" %" PRIu8 " arguments:"), args);
    9874           0 :                   while (args > 0)
    9875             :                     {
    9876           0 :                       if (readp + 1 > readendp)
    9877             :                         goto invalid_data;
    9878           0 :                       unsigned int form = *readp++;
    9879           0 :                       printf (" %s", dwarf_form_name (form));
    9880           0 :                       if (! libdw_valid_user_form (form))
    9881             :                         goto invalid_data;
    9882           0 :                       args--;
    9883           0 :                       if (args > 0)
    9884             :                         putchar_unlocked (',');
    9885             :                     }
    9886             :                 }
    9887             :               else
    9888           0 :                 printf (gettext (" no arguments."));
    9889           0 :               putchar_unlocked ('\n');
    9890             :             }
    9891             :         }
    9892           8 :       putchar_unlocked ('\n');
    9893             : 
    9894           8 :       int level = 1;
    9895           8 :       if (readp + 1 > readendp)
    9896             :         goto invalid_data;
    9897           8 :       unsigned int opcode = *readp++;
    9898         743 :       while (opcode != 0)
    9899             :         {
    9900             :           unsigned int u128;
    9901             :           unsigned int u128_2;
    9902             :           const unsigned char *endp;
    9903             :           uint64_t off;
    9904             : 
    9905         727 :           switch (opcode)
    9906             :             {
    9907           6 :             case DW_MACRO_start_file:
    9908           6 :               get_uleb128 (u128, readp, readendp);
    9909           6 :               if (readp >= readendp)
    9910             :                 goto invalid_data;
    9911           6 :               get_uleb128 (u128_2, readp, readendp);
    9912             : 
    9913             :               /* Find the CU DIE that matches this line offset.  */
    9914           6 :               const char *fname = "???";
    9915           6 :               if (cu != NULL)
    9916             :                 {
    9917           6 :                   if (cu->files == NULL
    9918           4 :                       && dwarf_getsrcfiles (&cu->die, &cu->files,
    9919             :                                             NULL) != 0)
    9920           0 :                     cu->files = (Dwarf_Files *) -1l;
    9921             : 
    9922           6 :                   if (cu->files != (Dwarf_Files *) -1l)
    9923           6 :                     fname = (dwarf_filesrc (cu->files, u128_2,
    9924           6 :                                             NULL, NULL) ?: "???");
    9925             :                 }
    9926           6 :               printf ("%*sstart_file %u, [%u] %s\n",
    9927             :                       level, "", u128, u128_2, fname);
    9928           6 :               ++level;
    9929           6 :               break;
    9930             : 
    9931           6 :             case DW_MACRO_end_file:
    9932           6 :               --level;
    9933             :               printf ("%*send_file\n", level, "");
    9934             :               break;
    9935             : 
    9936           1 :             case DW_MACRO_define:
    9937           1 :               get_uleb128 (u128, readp, readendp);
    9938           1 :               endp = memchr (readp, '\0', readendp - readp);
    9939           1 :               if (endp == NULL)
    9940             :                 goto invalid_data;
    9941           2 :               printf ("%*s#define %s, line %u\n",
    9942             :                       level, "", readp, u128);
    9943           1 :               readp = endp + 1;
    9944           1 :               break;
    9945             : 
    9946           0 :             case DW_MACRO_undef:
    9947           0 :               get_uleb128 (u128, readp, readendp);
    9948           0 :               endp = memchr (readp, '\0', readendp - readp);
    9949           0 :               if (endp == NULL)
    9950             :                 goto invalid_data;
    9951           0 :               printf ("%*s#undef %s, line %u\n",
    9952             :                       level, "", readp, u128);
    9953           0 :               readp = endp + 1;
    9954           0 :               break;
    9955             : 
    9956         707 :             case DW_MACRO_define_strp:
    9957         707 :               get_uleb128 (u128, readp, readendp);
    9958         707 :               if (readp + offset_len > readendp)
    9959             :                 goto invalid_data;
    9960         707 :               if (offset_len == 8)
    9961           0 :                 off = read_8ubyte_unaligned_inc (dbg, readp);
    9962             :               else
    9963         707 :                 off = read_4ubyte_unaligned_inc (dbg, readp);
    9964         707 :               printf ("%*s#define %s, line %u (indirect)\n",
    9965             :                       level, "", dwarf_getstring (dbg, off, NULL), u128);
    9966             :               break;
    9967             : 
    9968           1 :             case DW_MACRO_undef_strp:
    9969           1 :               get_uleb128 (u128, readp, readendp);
    9970           1 :               if (readp + offset_len > readendp)
    9971             :                 goto invalid_data;
    9972           1 :               if (offset_len == 8)
    9973           0 :                 off = read_8ubyte_unaligned_inc (dbg, readp);
    9974             :               else
    9975           1 :                 off = read_4ubyte_unaligned_inc (dbg, readp);
    9976           1 :               printf ("%*s#undef %s, line %u (indirect)\n",
    9977             :                       level, "", dwarf_getstring (dbg, off, NULL), u128);
    9978             :               break;
    9979             : 
    9980           6 :             case DW_MACRO_import:
    9981           6 :               if (readp + offset_len > readendp)
    9982             :                 goto invalid_data;
    9983           6 :               if (offset_len == 8)
    9984           0 :                 off = read_8ubyte_unaligned_inc (dbg, readp);
    9985             :               else
    9986           6 :                 off = read_4ubyte_unaligned_inc (dbg, readp);
    9987             :               printf ("%*s#include offset 0x%" PRIx64 "\n",
    9988             :                       level, "", off);
    9989             :               break;
    9990             : 
    9991           0 :             case DW_MACRO_define_sup:
    9992           0 :               get_uleb128 (u128, readp, readendp);
    9993           0 :               if (readp + offset_len > readendp)
    9994             :                 goto invalid_data;
    9995           0 :               printf ("%*s#define ", level, "");
    9996           0 :               readp =  print_form_data (dbg, DW_FORM_strp_sup,
    9997             :                                         readp, readendp, offset_len,
    9998             :                                         str_offsets_base);
    9999             :               printf (", line %u (sup)\n", u128);
   10000             :               break;
   10001             : 
   10002           0 :             case DW_MACRO_undef_sup:
   10003           0 :               get_uleb128 (u128, readp, readendp);
   10004           0 :               if (readp + offset_len > readendp)
   10005             :                 goto invalid_data;
   10006           0 :               printf ("%*s#undef ", level, "");
   10007           0 :               readp =  print_form_data (dbg, DW_FORM_strp_sup,
   10008             :                                         readp, readendp, offset_len,
   10009             :                                         str_offsets_base);
   10010             :               printf (", line %u (sup)\n", u128);
   10011             :               break;
   10012             : 
   10013           0 :             case DW_MACRO_import_sup:
   10014           0 :               if (readp + offset_len > readendp)
   10015             :                 goto invalid_data;
   10016           0 :               if (offset_len == 8)
   10017           0 :                 off = read_8ubyte_unaligned_inc (dbg, readp);
   10018             :               else
   10019           0 :                 off = read_4ubyte_unaligned_inc (dbg, readp);
   10020             :               // XXX Needs support for reading from supplementary object file.
   10021             :               printf ("%*s#include offset 0x%" PRIx64 " (sup)\n",
   10022             :                       level, "", off);
   10023             :               break;
   10024             : 
   10025           0 :             case DW_MACRO_define_strx:
   10026           0 :               get_uleb128 (u128, readp, readendp);
   10027           0 :               if (readp + offset_len > readendp)
   10028             :                 goto invalid_data;
   10029           0 :               printf ("%*s#define ", level, "");
   10030           0 :               readp =  print_form_data (dbg, DW_FORM_strx,
   10031             :                                         readp, readendp, offset_len,
   10032             :                                         str_offsets_base);
   10033             :               printf (", line %u (strx)\n", u128);
   10034             :               break;
   10035             : 
   10036           0 :             case DW_MACRO_undef_strx:
   10037           0 :               get_uleb128 (u128, readp, readendp);
   10038           0 :               if (readp + offset_len > readendp)
   10039             :                 goto invalid_data;
   10040           0 :               printf ("%*s#undef ", level, "");
   10041           0 :               readp =  print_form_data (dbg, DW_FORM_strx,
   10042             :                                         readp, readendp, offset_len,
   10043             :                                         str_offsets_base);
   10044             :               printf (", line %u (strx)\n", u128);
   10045             :               break;
   10046             : 
   10047           0 :             default:
   10048           0 :               printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
   10049           0 :               if (opcode < DW_MACRO_lo_user
   10050             :                   || opcode > DW_MACRO_lo_user
   10051           0 :                   || vendor[opcode - DW_MACRO_lo_user] == NULL)
   10052             :                 goto invalid_data;
   10053             : 
   10054             :               const unsigned char *op_desc;
   10055           0 :               op_desc = vendor[opcode - DW_MACRO_lo_user];
   10056             : 
   10057             :               // Just skip the arguments, we cannot really interpret them,
   10058             :               // but print as much as we can.
   10059           0 :               unsigned int args = *op_desc++;
   10060           0 :               while (args > 0 && readp < readendp)
   10061           0 :                 {
   10062           0 :                   unsigned int form = *op_desc++;
   10063           0 :                   readp = print_form_data (dbg, form, readp, readendp,
   10064             :                                            offset_len, str_offsets_base);
   10065           0 :                   args--;
   10066           0 :                   if (args > 0)
   10067             :                     printf (", ");
   10068             :                 }
   10069             :               putchar_unlocked ('\n');
   10070             :             }
   10071             : 
   10072         727 :           if (readp + 1 > readendp)
   10073             :             goto invalid_data;
   10074         727 :           opcode = *readp++;
   10075         727 :           if (opcode == 0)
   10076             :             putchar_unlocked ('\n');
   10077             :         }
   10078             :     }
   10079             : }
   10080             : 
   10081             : 
   10082             : /* Callback for printing global names.  */
   10083             : static int
   10084          34 : print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
   10085             :                 void *arg)
   10086             : {
   10087          34 :   int *np = (int *) arg;
   10088             : 
   10089         102 :   printf (gettext (" [%5d] DIE offset: %6" PRId64
   10090             :                    ", CU DIE offset: %6" PRId64 ", name: %s\n"),
   10091          34 :           (*np)++, global->die_offset, global->cu_offset, global->name);
   10092             : 
   10093          34 :   return 0;
   10094             : }
   10095             : 
   10096             : 
   10097             : /* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
   10098             : static void
   10099           8 : print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10100             :                               Ebl *ebl,
   10101             :                               GElf_Ehdr *ehdr __attribute__ ((unused)),
   10102             :                               Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   10103             : {
   10104          16 :   printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
   10105             :           elf_ndxscn (scn), section_name (ebl, shdr),
   10106           8 :           (uint64_t) shdr->sh_offset);
   10107             : 
   10108           8 :   int n = 0;
   10109           8 :   (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
   10110           8 : }
   10111             : 
   10112             : /* Print the content of the DWARF string section '.debug_str'.  */
   10113             : static void
   10114          45 : print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10115             :                          Ebl *ebl,
   10116             :                          GElf_Ehdr *ehdr __attribute__ ((unused)),
   10117             :                          Elf_Scn *scn, GElf_Shdr *shdr,
   10118             :                          Dwarf *dbg __attribute__ ((unused)))
   10119             : {
   10120          45 :   Elf_Data *data = elf_rawdata (scn, NULL);
   10121          45 :   const size_t sh_size = data ? data->d_size : 0;
   10122             : 
   10123             :   /* Compute floor(log16(shdr->sh_size)).  */
   10124          45 :   GElf_Addr tmp = sh_size;
   10125          45 :   int digits = 1;
   10126         200 :   while (tmp >= 16)
   10127             :     {
   10128         110 :       ++digits;
   10129         110 :       tmp >>= 4;
   10130             :     }
   10131          45 :   digits = MAX (4, digits);
   10132             : 
   10133         135 :   printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
   10134             :                    " %*s  String\n"),
   10135             :           elf_ndxscn (scn),
   10136          45 :           section_name (ebl, shdr), (uint64_t) shdr->sh_offset,
   10137             :           /* TRANS: the debugstr| prefix makes the string unique.  */
   10138          45 :           digits + 2, sgettext ("debugstr|Offset"));
   10139             : 
   10140          45 :   Dwarf_Off offset = 0;
   10141       61290 :   while (offset < sh_size)
   10142             :     {
   10143             :       size_t len;
   10144       61200 :       const char *str = (const char *) data->d_buf + offset;
   10145       61200 :       const char *endp = memchr (str, '\0', sh_size - offset);
   10146       61200 :       if (unlikely (endp == NULL))
   10147             :         {
   10148           0 :           printf (gettext (" *** error, missing string terminator\n"));
   10149             :           break;
   10150             :         }
   10151             : 
   10152       61200 :       printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
   10153       61200 :       len = endp - str;
   10154       61200 :       offset += len + 1;
   10155             :     }
   10156          45 : }
   10157             : 
   10158             : static void
   10159           4 : print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10160             :                                  Ebl *ebl,
   10161             :                                  GElf_Ehdr *ehdr __attribute__ ((unused)),
   10162             :                                  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   10163             : {
   10164           8 :   printf (gettext ("\
   10165             : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
   10166             :           elf_ndxscn (scn), section_name (ebl, shdr),
   10167           4 :           (uint64_t) shdr->sh_offset);
   10168             : 
   10169           4 :   if (shdr->sh_size == 0)
   10170             :     return;
   10171             : 
   10172             :   /* We like to get the section from libdw to make sure they are relocated.  */
   10173           8 :   Elf_Data *data = (dbg->sectiondata[IDX_debug_str_offsets]
   10174           4 :                     ?: elf_rawdata (scn, NULL));
   10175           4 :   if (unlikely (data == NULL))
   10176             :     {
   10177           0 :       error (0, 0, gettext ("cannot get .debug_str_offsets section data: %s"),
   10178             :              elf_errmsg (-1));
   10179             :       return;
   10180             :     }
   10181             : 
   10182           4 :   size_t idx = 0;
   10183           8 :   sort_listptr (&known_stroffbases, "str_offsets");
   10184             : 
   10185           4 :   const unsigned char *start = (const unsigned char *) data->d_buf;
   10186           4 :   const unsigned char *readp = start;
   10187           4 :   const unsigned char *readendp = ((const unsigned char *) data->d_buf
   10188           4 :                                    + data->d_size);
   10189             : 
   10190          12 :   while (readp < readendp)
   10191             :     {
   10192             :       /* Most string offset tables will have a header.  For split
   10193             :          dwarf unit GNU DebugFission didn't add one.  But they were
   10194             :          also only defined for split units (main or skeleton units
   10195             :          didn't have indirect strings).  So if we don't have a
   10196             :          DW_AT_str_offsets_base at all and this is offset zero, then
   10197             :          just start printing offsets immediately, if this is a .dwo
   10198             :          section.  */
   10199           4 :       Dwarf_Off off = (Dwarf_Off) (readp
   10200           4 :                                    - (const unsigned char *) data->d_buf);
   10201             : 
   10202           4 :       printf ("Table at offset %" PRIx64 " ", off);
   10203             : 
   10204           4 :       struct listptr *listptr = get_listptr (&known_stroffbases, idx++);
   10205           0 :       const unsigned char *next_unitp = readendp;
   10206             :       uint8_t offset_size;
   10207             :       bool has_header;
   10208           0 :       if (listptr == NULL)
   10209             :         {
   10210             :           /* This can happen for .dwo files.  There is only an header
   10211             :              in the case this is a version 5 split DWARF file.  */
   10212             :           Dwarf_CU *cu;
   10213             :           uint8_t unit_type;
   10214           4 :           if (dwarf_get_units (dbg, NULL, &cu, NULL, &unit_type,
   10215             :                                NULL, NULL) != 0)
   10216             :             {
   10217           0 :               error (0, 0, "Warning: Cannot find any DWARF unit.");
   10218             :               /* Just guess some values.  */
   10219           0 :               has_header = false;
   10220           0 :               offset_size = 4;
   10221             :             }
   10222           4 :           else if (off == 0
   10223           4 :                    && (unit_type == DW_UT_split_type
   10224           4 :                        || unit_type == DW_UT_split_compile))
   10225             :             {
   10226           4 :               has_header = cu->version > 4;
   10227           4 :               offset_size = cu->offset_size;
   10228             :             }
   10229             :           else
   10230             :             {
   10231           0 :               error (0, 0,
   10232             :                      "Warning: No CU references .debug_str_offsets after %"
   10233             :                      PRIx64, off);
   10234           0 :               has_header = cu->version > 4;
   10235           0 :               offset_size = cu->offset_size;
   10236             :             }
   10237           4 :           printf ("\n");
   10238             :         }
   10239             :       else
   10240             :         {
   10241             :           /* This must be DWARF5, since GNU DebugFission didn't define
   10242             :              DW_AT_str_offsets_base.  */
   10243           0 :           has_header = true;
   10244             : 
   10245             :           Dwarf_Die cudie;
   10246           0 :           if (dwarf_cu_die (listptr->cu, &cudie,
   10247             :                             NULL, NULL, NULL, NULL,
   10248             :                             NULL, NULL) == NULL)
   10249           0 :             printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
   10250             :           else
   10251           0 :             printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
   10252             :         }
   10253             : 
   10254           4 :       if (has_header)
   10255             :         {
   10256             :           uint64_t unit_length;
   10257             :           uint16_t version;
   10258             :           uint16_t padding;
   10259             : 
   10260           2 :           unit_length = read_4ubyte_unaligned_inc (dbg, readp);
   10261           2 :           if (unlikely (unit_length == 0xffffffff))
   10262             :             {
   10263           0 :               if (unlikely (readp > readendp - 8))
   10264             :                 {
   10265           0 :                 invalid_data:
   10266             :                   error (0, 0, "Invalid data");
   10267             :                   return;
   10268             :                 }
   10269           0 :               unit_length = read_8ubyte_unaligned_inc (dbg, readp);
   10270           0 :               offset_size = 8;
   10271             :             }
   10272             :           else
   10273             :             offset_size = 4;
   10274             : 
   10275           2 :           printf ("\n");
   10276           4 :           printf (gettext (" Length:        %8" PRIu64 "\n"),
   10277             :                   unit_length);
   10278           4 :           printf (gettext (" Offset size:   %8" PRIu8 "\n"),
   10279             :                   offset_size);
   10280             : 
   10281             :           /* We need at least 2-bytes (version) + 2-bytes (padding) =
   10282             :              4 bytes to complete the header.  And this unit cannot go
   10283             :              beyond the section data.  */
   10284           2 :           if (readp > readendp - 4
   10285           2 :               || unit_length < 4
   10286           2 :               || unit_length > (uint64_t) (readendp - readp))
   10287             :             goto invalid_data;
   10288             : 
   10289           2 :           next_unitp = readp + unit_length;
   10290             : 
   10291           2 :           version = read_2ubyte_unaligned_inc (dbg, readp);
   10292           4 :           printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
   10293             : 
   10294           2 :           if (version != 5)
   10295             :             {
   10296           0 :               error (0, 0, gettext ("Unknown version"));
   10297             :               goto next_unit;
   10298             :             }
   10299             : 
   10300           2 :           padding = read_2ubyte_unaligned_inc (dbg, readp);
   10301           4 :           printf (gettext (" Padding:       %8" PRIx16 "\n"), padding);
   10302             : 
   10303           2 :           if (listptr != NULL
   10304           0 :               && listptr->offset != (Dwarf_Off) (readp - start))
   10305             :             {
   10306             :               error (0, 0, "String offsets index doesn't start after header");
   10307             :               goto next_unit;
   10308             :             }
   10309             : 
   10310             :           printf ("\n");
   10311             :         }
   10312             : 
   10313           4 :       int digits = 1;
   10314           4 :       size_t offsets = (next_unitp - readp) / offset_size;
   10315          12 :       while (offsets >= 10)
   10316             :         {
   10317           4 :           ++digits;
   10318           4 :           offsets /= 10;
   10319             :         }
   10320             : 
   10321           4 :       unsigned int uidx = 0;
   10322           4 :       size_t index_offset =  readp - (const unsigned char *) data->d_buf;
   10323             :       printf (" Offsets start at 0x%zx:\n", index_offset);
   10324          64 :       while (readp <= next_unitp - offset_size)
   10325             :         {
   10326             :           Dwarf_Word offset;
   10327          60 :           if (offset_size == 4)
   10328          60 :             offset = read_4ubyte_unaligned_inc (dbg, readp);
   10329             :           else
   10330           0 :             offset = read_8ubyte_unaligned_inc (dbg, readp);
   10331          60 :           const char *str = dwarf_getstring (dbg, offset, NULL);
   10332         120 :           printf (" [%*u] [%*" PRIx64 "]  \"%s\"\n",
   10333          60 :                   digits, uidx++, (int) offset_size * 2, offset, str ?: "???");
   10334             :         }
   10335           4 :       printf ("\n");
   10336             : 
   10337           4 :       if (readp != next_unitp)
   10338           0 :         error (0, 0, "extra %zd bytes at end of unit",
   10339           0 :                (size_t) (next_unitp - readp));
   10340             : 
   10341           4 :     next_unit:
   10342             :       readp = next_unitp;
   10343             :     }
   10344             : }
   10345             : 
   10346             : 
   10347             : /* Print the content of the call frame search table section
   10348             :    '.eh_frame_hdr'.  */
   10349             : static void
   10350          14 : print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10351             :                                Ebl *ebl __attribute__ ((unused)),
   10352             :                                GElf_Ehdr *ehdr __attribute__ ((unused)),
   10353             :                                Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   10354             : {
   10355          28 :   printf (gettext ("\
   10356             : \nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
   10357             :           elf_ndxscn (scn));
   10358             : 
   10359          14 :   Elf_Data *data = elf_rawdata (scn, NULL);
   10360             : 
   10361          14 :   if (unlikely (data == NULL))
   10362             :     {
   10363           0 :       error (0, 0, gettext ("cannot get %s content: %s"),
   10364             :              ".eh_frame_hdr", elf_errmsg (-1));
   10365           0 :       return;
   10366             :     }
   10367             : 
   10368          14 :   const unsigned char *readp = data->d_buf;
   10369          14 :   const unsigned char *const dataend = ((unsigned char *) data->d_buf
   10370          14 :                                         + data->d_size);
   10371             : 
   10372          14 :   if (unlikely (readp + 4 > dataend))
   10373             :     {
   10374           0 :     invalid_data:
   10375           0 :       error (0, 0, gettext ("invalid data"));
   10376             :       return;
   10377             :     }
   10378             : 
   10379          14 :   unsigned int version = *readp++;
   10380          14 :   unsigned int eh_frame_ptr_enc = *readp++;
   10381          14 :   unsigned int fde_count_enc = *readp++;
   10382          14 :   unsigned int table_enc = *readp++;
   10383             : 
   10384          14 :   printf (" version:          %u\n"
   10385             :           " eh_frame_ptr_enc: %#x ",
   10386             :           version, eh_frame_ptr_enc);
   10387          14 :   print_encoding_base ("", eh_frame_ptr_enc);
   10388          14 :   printf (" fde_count_enc:    %#x ", fde_count_enc);
   10389          14 :   print_encoding_base ("", fde_count_enc);
   10390          14 :   printf (" table_enc:        %#x ", table_enc);
   10391          14 :   print_encoding_base ("", table_enc);
   10392             : 
   10393          14 :   uint64_t eh_frame_ptr = 0;
   10394          14 :   if (eh_frame_ptr_enc != DW_EH_PE_omit)
   10395             :     {
   10396          14 :       readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
   10397             :                             dbg);
   10398          14 :       if (unlikely (readp == NULL))
   10399             :         goto invalid_data;
   10400             : 
   10401          28 :       printf (" eh_frame_ptr:     %#" PRIx64, eh_frame_ptr);
   10402          14 :       if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
   10403          14 :         printf (" (offset: %#" PRIx64 ")",
   10404             :                 /* +4 because of the 4 byte header of the section.  */
   10405          14 :                 (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
   10406             : 
   10407             :       putchar_unlocked ('\n');
   10408             :     }
   10409             : 
   10410          14 :   uint64_t fde_count = 0;
   10411          14 :   if (fde_count_enc != DW_EH_PE_omit)
   10412             :     {
   10413          14 :       readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
   10414          14 :       if (unlikely (readp == NULL))
   10415             :         goto invalid_data;
   10416             : 
   10417          14 :       printf (" fde_count:        %" PRIu64 "\n", fde_count);
   10418             :     }
   10419             : 
   10420          14 :   if (fde_count == 0 || table_enc == DW_EH_PE_omit)
   10421             :     return;
   10422             : 
   10423          14 :   puts (" Table:");
   10424             : 
   10425             :   /* Optimize for the most common case.  */
   10426          14 :   if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
   10427        4422 :     while (fde_count > 0 && readp + 8 <= dataend)
   10428             :       {
   10429        4408 :         int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
   10430        8816 :         uint64_t initial_offset = ((uint64_t) shdr->sh_offset
   10431        4408 :                                    + (int64_t) initial_location);
   10432        4408 :         int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
   10433             :         // XXX Possibly print symbol name or section offset for initial_offset
   10434        4408 :         printf ("  %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
   10435             :                 " fde=[%6" PRIx64 "]\n",
   10436             :                 initial_location, initial_offset,
   10437        4408 :                 address, address - (eh_frame_ptr + 4));
   10438             :       }
   10439             :   else
   10440             :     while (0 && readp < dataend)
   10441             :       {
   10442             : 
   10443             :       }
   10444             : }
   10445             : 
   10446             : 
   10447             : /* Print the content of the exception handling table section
   10448             :    '.eh_frame_hdr'.  */
   10449             : static void
   10450           0 : print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
   10451             :                              Ebl *ebl __attribute__ ((unused)),
   10452             :                              GElf_Ehdr *ehdr __attribute__ ((unused)),
   10453             :                              Elf_Scn *scn,
   10454             :                              GElf_Shdr *shdr __attribute__ ((unused)),
   10455             :                              Dwarf *dbg __attribute__ ((unused)))
   10456             : {
   10457           0 :   printf (gettext ("\
   10458             : \nException handling table section [%2zu] '.gcc_except_table':\n"),
   10459             :           elf_ndxscn (scn));
   10460             : 
   10461           0 :   Elf_Data *data = elf_rawdata (scn, NULL);
   10462             : 
   10463           0 :   if (unlikely (data == NULL))
   10464             :     {
   10465           0 :       error (0, 0, gettext ("cannot get %s content: %s"),
   10466             :              ".gcc_except_table", elf_errmsg (-1));
   10467           0 :       return;
   10468             :     }
   10469             : 
   10470           0 :   const unsigned char *readp = data->d_buf;
   10471           0 :   const unsigned char *const dataend = readp + data->d_size;
   10472             : 
   10473           0 :   if (unlikely (readp + 1 > dataend))
   10474             :     {
   10475           0 :     invalid_data:
   10476           0 :       error (0, 0, gettext ("invalid data"));
   10477             :       return;
   10478             :     }
   10479           0 :   unsigned int lpstart_encoding = *readp++;
   10480           0 :   printf (gettext (" LPStart encoding:    %#x "), lpstart_encoding);
   10481           0 :   print_encoding_base ("", lpstart_encoding);
   10482           0 :   if (lpstart_encoding != DW_EH_PE_omit)
   10483             :     {
   10484             :       uint64_t lpstart;
   10485           0 :       readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
   10486           0 :       printf (" LPStart:             %#" PRIx64 "\n", lpstart);
   10487             :     }
   10488             : 
   10489           0 :   if (unlikely (readp + 1 > dataend))
   10490             :     goto invalid_data;
   10491           0 :   unsigned int ttype_encoding = *readp++;
   10492           0 :   printf (gettext (" TType encoding:      %#x "), ttype_encoding);
   10493           0 :   print_encoding_base ("", ttype_encoding);
   10494           0 :   const unsigned char *ttype_base = NULL;
   10495           0 :   if (ttype_encoding != DW_EH_PE_omit)
   10496             :     {
   10497             :       unsigned int ttype_base_offset;
   10498           0 :       get_uleb128 (ttype_base_offset, readp, dataend);
   10499           0 :       printf (" TType base offset:   %#x\n", ttype_base_offset);
   10500           0 :       if ((size_t) (dataend - readp) > ttype_base_offset)
   10501           0 :         ttype_base = readp + ttype_base_offset;
   10502             :     }
   10503             : 
   10504           0 :   if (unlikely (readp + 1 > dataend))
   10505             :     goto invalid_data;
   10506           0 :   unsigned int call_site_encoding = *readp++;
   10507           0 :   printf (gettext (" Call site encoding:  %#x "), call_site_encoding);
   10508           0 :   print_encoding_base ("", call_site_encoding);
   10509             :   unsigned int call_site_table_len;
   10510           0 :   get_uleb128 (call_site_table_len, readp, dataend);
   10511             : 
   10512           0 :   const unsigned char *const action_table = readp + call_site_table_len;
   10513           0 :   if (unlikely (action_table > dataend))
   10514             :     goto invalid_data;
   10515             :   unsigned int u = 0;
   10516             :   unsigned int max_action = 0;
   10517           0 :   while (readp < action_table)
   10518             :     {
   10519           0 :       if (u == 0)
   10520           0 :         puts (gettext ("\n Call site table:"));
   10521             : 
   10522             :       uint64_t call_site_start;
   10523           0 :       readp = read_encoded (call_site_encoding, readp, dataend,
   10524             :                             &call_site_start, dbg);
   10525             :       uint64_t call_site_length;
   10526           0 :       readp = read_encoded (call_site_encoding, readp, dataend,
   10527             :                             &call_site_length, dbg);
   10528             :       uint64_t landing_pad;
   10529           0 :       readp = read_encoded (call_site_encoding, readp, dataend,
   10530             :                             &landing_pad, dbg);
   10531             :       unsigned int action;
   10532           0 :       get_uleb128 (action, readp, dataend);
   10533           0 :       max_action = MAX (action, max_action);
   10534           0 :       printf (gettext (" [%4u] Call site start:   %#" PRIx64 "\n"
   10535             :                        "        Call site length:  %" PRIu64 "\n"
   10536             :                        "        Landing pad:       %#" PRIx64 "\n"
   10537             :                        "        Action:            %u\n"),
   10538             :               u++, call_site_start, call_site_length, landing_pad, action);
   10539             :     }
   10540           0 :   if (readp != action_table)
   10541             :     goto invalid_data;
   10542             : 
   10543           0 :   unsigned int max_ar_filter = 0;
   10544           0 :   if (max_action > 0)
   10545             :     {
   10546           0 :       puts ("\n Action table:");
   10547             : 
   10548           0 :       size_t maxdata = (size_t) (dataend - action_table);
   10549           0 :       if (max_action > maxdata || maxdata - max_action < 1)
   10550             :         {
   10551           0 :         invalid_action_table:
   10552           0 :           fputs (gettext ("   <INVALID DATA>\n"), stdout);
   10553           0 :           return;
   10554             :         }
   10555             : 
   10556           0 :       const unsigned char *const action_table_end
   10557           0 :         = action_table + max_action + 1;
   10558             : 
   10559           0 :       u = 0;
   10560             :       do
   10561             :         {
   10562             :           int ar_filter;
   10563           0 :           get_sleb128 (ar_filter, readp, action_table_end);
   10564           0 :           if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
   10565           0 :             max_ar_filter = ar_filter;
   10566             :           int ar_disp;
   10567           0 :           if (readp >= action_table_end)
   10568             :             goto invalid_action_table;
   10569           0 :           get_sleb128 (ar_disp, readp, action_table_end);
   10570             : 
   10571           0 :           printf (" [%4u] ar_filter:  % d\n"
   10572             :                   "        ar_disp:    % -5d",
   10573             :                   u, ar_filter, ar_disp);
   10574           0 :           if (abs (ar_disp) & 1)
   10575           0 :             printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
   10576           0 :           else if (ar_disp != 0)
   10577           0 :             puts (" -> ???");
   10578             :           else
   10579             :             putchar_unlocked ('\n');
   10580           0 :           ++u;
   10581             :         }
   10582           0 :       while (readp < action_table_end);
   10583             :     }
   10584             : 
   10585           0 :   if (max_ar_filter > 0 && ttype_base != NULL)
   10586             :     {
   10587             :       unsigned char dsize;
   10588           0 :       puts ("\n TType table:");
   10589             : 
   10590             :       // XXX Not *4, size of encoding;
   10591             :       switch (ttype_encoding & 7)
   10592             :         {
   10593             :         case DW_EH_PE_udata2:
   10594             :         case DW_EH_PE_sdata2:
   10595             :           dsize = 2;
   10596             :           break;
   10597             :         case DW_EH_PE_udata4:
   10598             :         case DW_EH_PE_sdata4:
   10599             :           dsize = 4;
   10600             :           break;
   10601             :         case DW_EH_PE_udata8:
   10602             :         case DW_EH_PE_sdata8:
   10603             :           dsize = 8;
   10604             :           break;
   10605           0 :         default:
   10606           0 :           dsize = 0;
   10607           0 :           error (1, 0, gettext ("invalid TType encoding"));
   10608             :         }
   10609             : 
   10610           0 :       if (max_ar_filter
   10611           0 :           > (size_t) (ttype_base - (const unsigned char *) data->d_buf) / dsize)
   10612             :         goto invalid_data;
   10613             : 
   10614           0 :       readp = ttype_base - max_ar_filter * dsize;
   10615             :       do
   10616             :         {
   10617             :           uint64_t ttype;
   10618           0 :           readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
   10619             :                                 dbg);
   10620           0 :           printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
   10621             :         }
   10622           0 :       while (readp < ttype_base);
   10623             :     }
   10624             : }
   10625             : 
   10626             : /* Print the content of the '.gdb_index' section.
   10627             :    http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
   10628             : */
   10629             : static void
   10630           2 : print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
   10631             :                          GElf_Ehdr *ehdr __attribute__ ((unused)),
   10632             :                          Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
   10633             : {
   10634           4 :   printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
   10635             :                    " contains %" PRId64 " bytes :\n"),
   10636             :           elf_ndxscn (scn), section_name (ebl, shdr),
   10637           2 :           (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
   10638             : 
   10639           2 :   Elf_Data *data = elf_rawdata (scn, NULL);
   10640             : 
   10641           2 :   if (unlikely (data == NULL))
   10642             :     {
   10643           0 :       error (0, 0, gettext ("cannot get %s content: %s"),
   10644             :              ".gdb_index", elf_errmsg (-1));
   10645           0 :       return;
   10646             :     }
   10647             : 
   10648             :   // .gdb_index is always in little endian.
   10649           2 :   Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
   10650           2 :   dbg = &dummy_dbg;
   10651             : 
   10652           2 :   const unsigned char *readp = data->d_buf;
   10653           2 :   const unsigned char *const dataend = readp + data->d_size;
   10654             : 
   10655           2 :   if (unlikely (readp + 4 > dataend))
   10656             :     {
   10657           0 :     invalid_data:
   10658           0 :       error (0, 0, gettext ("invalid data"));
   10659             :       return;
   10660             :     }
   10661             : 
   10662           2 :   int32_t vers = read_4ubyte_unaligned (dbg, readp);
   10663           4 :   printf (gettext (" Version:         %" PRId32 "\n"), vers);
   10664             : 
   10665             :   // The only difference between version 4 and version 5 is the
   10666             :   // hash used for generating the table.  Version 6 contains symbols
   10667             :   // for inlined functions, older versions didn't.  Version 7 adds
   10668             :   // symbol kinds.  Version 8 just indicates that it correctly includes
   10669             :   // TUs for symbols.
   10670           2 :   if (vers < 4 || vers > 8)
   10671             :     {
   10672           0 :       printf (gettext ("  unknown version, cannot parse section\n"));
   10673             :       return;
   10674             :     }
   10675             : 
   10676           2 :   readp += 4;
   10677           2 :   if (unlikely (readp + 4 > dataend))
   10678             :     goto invalid_data;
   10679             : 
   10680           2 :   uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
   10681           4 :   printf (gettext (" CU offset:       %#" PRIx32 "\n"), cu_off);
   10682             : 
   10683           2 :   readp += 4;
   10684           2 :   if (unlikely (readp + 4 > dataend))
   10685             :     goto invalid_data;
   10686             : 
   10687           2 :   uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
   10688           4 :   printf (gettext (" TU offset:       %#" PRIx32 "\n"), tu_off);
   10689             : 
   10690           2 :   readp += 4;
   10691           2 :   if (unlikely (readp + 4 > dataend))
   10692             :     goto invalid_data;
   10693             : 
   10694           2 :   uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
   10695           4 :   printf (gettext (" address offset:  %#" PRIx32 "\n"), addr_off);
   10696             : 
   10697           2 :   readp += 4;
   10698           2 :   if (unlikely (readp + 4 > dataend))
   10699             :     goto invalid_data;
   10700             : 
   10701           2 :   uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
   10702           4 :   printf (gettext (" symbol offset:   %#" PRIx32 "\n"), sym_off);
   10703             : 
   10704           2 :   readp += 4;
   10705           2 :   if (unlikely (readp + 4 > dataend))
   10706             :     goto invalid_data;
   10707             : 
   10708           2 :   uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
   10709           4 :   printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
   10710             : 
   10711           2 :   if (unlikely ((size_t) (dataend - (const unsigned char *) data->d_buf)
   10712             :                 < const_off))
   10713             :     goto invalid_data;
   10714             : 
   10715           2 :   readp = data->d_buf + cu_off;
   10716             : 
   10717           2 :   const unsigned char *nextp = data->d_buf + tu_off;
   10718           2 :   if (tu_off >= data->d_size)
   10719             :     goto invalid_data;
   10720             : 
   10721           2 :   size_t cu_nr = (nextp - readp) / 16;
   10722             : 
   10723           4 :   printf (gettext ("\n CU list at offset %#" PRIx32
   10724             :                    " contains %zu entries:\n"),
   10725             :           cu_off, cu_nr);
   10726             : 
   10727           2 :   size_t n = 0;
   10728           8 :   while (dataend - readp >= 16 && n < cu_nr)
   10729             :     {
   10730           4 :       uint64_t off = read_8ubyte_unaligned (dbg, readp);
   10731           4 :       readp += 8;
   10732             : 
   10733           4 :       uint64_t len = read_8ubyte_unaligned (dbg, readp);
   10734           4 :       readp += 8;
   10735             : 
   10736           4 :       printf (" [%4zu] start: %0#8" PRIx64
   10737             :               ", length: %5" PRIu64 "\n", n, off, len);
   10738           4 :       n++;
   10739             :     }
   10740             : 
   10741           2 :   readp = data->d_buf + tu_off;
   10742           2 :   nextp = data->d_buf + addr_off;
   10743           2 :   if (addr_off >= data->d_size)
   10744             :     goto invalid_data;
   10745             : 
   10746           2 :   size_t tu_nr = (nextp - readp) / 24;
   10747             : 
   10748           4 :   printf (gettext ("\n TU list at offset %#" PRIx32
   10749             :                    " contains %zu entries:\n"),
   10750             :           tu_off, tu_nr);
   10751             : 
   10752           2 :   n = 0;
   10753           6 :   while (dataend - readp >= 24 && n < tu_nr)
   10754             :     {
   10755           2 :       uint64_t off = read_8ubyte_unaligned (dbg, readp);
   10756           2 :       readp += 8;
   10757             : 
   10758           2 :       uint64_t type = read_8ubyte_unaligned (dbg, readp);
   10759           2 :       readp += 8;
   10760             : 
   10761           2 :       uint64_t sig = read_8ubyte_unaligned (dbg, readp);
   10762           2 :       readp += 8;
   10763             : 
   10764           2 :       printf (" [%4zu] CU offset: %5" PRId64
   10765             :               ", type offset: %5" PRId64
   10766             :               ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
   10767           2 :       n++;
   10768             :     }
   10769             : 
   10770           2 :   readp = data->d_buf + addr_off;
   10771           2 :   nextp = data->d_buf + sym_off;
   10772           2 :   if (sym_off >= data->d_size)
   10773             :     goto invalid_data;
   10774             : 
   10775           2 :   size_t addr_nr = (nextp - readp) / 20;
   10776             : 
   10777           4 :   printf (gettext ("\n Address list at offset %#" PRIx32
   10778             :                    " contains %zu entries:\n"),
   10779             :           addr_off, addr_nr);
   10780             : 
   10781           2 :   n = 0;
   10782           8 :   while (dataend - readp >= 20 && n < addr_nr)
   10783             :     {
   10784           4 :       uint64_t low = read_8ubyte_unaligned (dbg, readp);
   10785           4 :       readp += 8;
   10786             : 
   10787           4 :       uint64_t high = read_8ubyte_unaligned (dbg, readp);
   10788           4 :       readp += 8;
   10789             : 
   10790           4 :       uint32_t idx = read_4ubyte_unaligned (dbg, readp);
   10791           4 :       readp += 4;
   10792             : 
   10793           4 :       printf (" [%4zu] ", n);
   10794           4 :       print_dwarf_addr (dwflmod, 8, low, low);
   10795           4 :       printf ("..");
   10796           4 :       print_dwarf_addr (dwflmod, 8, high - 1, high);
   10797           4 :       printf (", CU index: %5" PRId32 "\n", idx);
   10798           4 :       n++;
   10799             :     }
   10800             : 
   10801           2 :   const unsigned char *const_start = data->d_buf + const_off;
   10802           2 :   if (const_off >= data->d_size)
   10803             :     goto invalid_data;
   10804             : 
   10805           2 :   readp = data->d_buf + sym_off;
   10806           2 :   nextp = const_start;
   10807           2 :   size_t sym_nr = (nextp - readp) / 8;
   10808             : 
   10809           4 :   printf (gettext ("\n Symbol table at offset %#" PRIx32
   10810             :                    " contains %zu slots:\n"),
   10811             :           addr_off, sym_nr);
   10812             : 
   10813           2 :   n = 0;
   10814        2052 :   while (dataend - readp >= 8 && n < sym_nr)
   10815             :     {
   10816        2048 :       uint32_t name = read_4ubyte_unaligned (dbg, readp);
   10817        2048 :       readp += 4;
   10818             : 
   10819        2048 :       uint32_t vector = read_4ubyte_unaligned (dbg, readp);
   10820        2048 :       readp += 4;
   10821             : 
   10822        2048 :       if (name != 0 || vector != 0)
   10823             :         {
   10824          14 :           const unsigned char *sym = const_start + name;
   10825          28 :           if (unlikely ((size_t) (dataend - const_start) < name
   10826             :                         || memchr (sym, '\0', dataend - sym) == NULL))
   10827             :             goto invalid_data;
   10828             : 
   10829          14 :           printf (" [%4zu] symbol: %s, CUs: ", n, sym);
   10830             : 
   10831          14 :           const unsigned char *readcus = const_start + vector;
   10832          14 :           if (unlikely ((size_t) (dataend - const_start) < vector))
   10833             :             goto invalid_data;
   10834          14 :           uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
   10835          44 :           while (cus--)
   10836             :             {
   10837             :               uint32_t cu_kind, cu, kind;
   10838             :               bool is_static;
   10839          16 :               readcus += 4;
   10840          16 :               if (unlikely (readcus + 4 > dataend))
   10841             :                 goto invalid_data;
   10842          16 :               cu_kind = read_4ubyte_unaligned (dbg, readcus);
   10843          16 :               cu = cu_kind & ((1 << 24) - 1);
   10844          16 :               kind = (cu_kind >> 28) & 7;
   10845          16 :               is_static = cu_kind & (1U << 31);
   10846          16 :               if (cu > cu_nr - 1)
   10847           2 :                 printf ("%" PRId32 "T", cu - (uint32_t) cu_nr);
   10848             :               else
   10849             :                 printf ("%" PRId32, cu);
   10850          16 :               if (kind != 0)
   10851             :                 {
   10852           8 :                   printf (" (");
   10853           8 :                   switch (kind)
   10854             :                     {
   10855           3 :                     case 1:
   10856             :                       printf ("type");
   10857             :                       break;
   10858           2 :                     case 2:
   10859             :                       printf ("var");
   10860             :                       break;
   10861           3 :                     case 3:
   10862             :                       printf ("func");
   10863             :                       break;
   10864           0 :                     case 4:
   10865             :                       printf ("other");
   10866             :                       break;
   10867           0 :                     default:
   10868             :                       printf ("unknown-0x%" PRIx32, kind);
   10869             :                       break;
   10870             :                     }
   10871           8 :                   printf (":%c)", (is_static ? 'S' : 'G'));
   10872             :                 }
   10873          16 :               if (cus > 0)
   10874             :                 printf (", ");
   10875             :             }
   10876             :           printf ("\n");
   10877             :         }
   10878        2048 :       n++;
   10879             :     }
   10880             : }
   10881             : 
   10882             : /* Returns true and sets split DWARF CU id if there is a split compile
   10883             :    unit in the given Dwarf, and no non-split units are found (before it).  */
   10884             : static bool
   10885         117 : is_split_dwarf (Dwarf *dbg, uint64_t *id, Dwarf_CU **split_cu)
   10886             : {
   10887         117 :   Dwarf_CU *cu = NULL;
   10888         234 :   while (dwarf_get_units (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
   10889             :     {
   10890             :       uint8_t unit_type;
   10891         117 :       if (dwarf_cu_info (cu, NULL, &unit_type, NULL, NULL,
   10892             :                          id, NULL, NULL) != 0)
   10893         117 :         return false;
   10894             : 
   10895         117 :       if (unit_type != DW_UT_split_compile && unit_type != DW_UT_split_type)
   10896             :         return false;
   10897             : 
   10898             :       /* We really only care about the split compile unit, the types
   10899             :          should be fine and self sufficient.  Also they don't have an
   10900             :          id that we can match with a skeleton unit.  */
   10901           9 :       if (unit_type == DW_UT_split_compile)
   10902             :         {
   10903           9 :           *split_cu = cu;
   10904           9 :           return true;
   10905             :         }
   10906             :     }
   10907             : 
   10908             :   return false;
   10909             : }
   10910             : 
   10911             : /* Check that there is one and only one Dwfl_Module, return in arg.  */
   10912             : static int
   10913           9 : getone_dwflmod (Dwfl_Module *dwflmod,
   10914             :                void **userdata __attribute__ ((unused)),
   10915             :                const char *name __attribute__ ((unused)),
   10916             :                Dwarf_Addr base __attribute__ ((unused)),
   10917             :                void *arg)
   10918             : {
   10919           9 :   Dwfl_Module **m = (Dwfl_Module **) arg;
   10920           9 :   if (*m != NULL)
   10921             :     return DWARF_CB_ABORT;
   10922           9 :   *m = dwflmod;
   10923           9 :   return DWARF_CB_OK;
   10924             : }
   10925             : 
   10926             : static void
   10927         145 : print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
   10928             : {
   10929             :   /* Used for skeleton file, if necessary for split DWARF.  */
   10930         145 :   Dwfl *skel_dwfl = NULL;
   10931         145 :   Dwfl_Module *skel_mod = NULL;
   10932         145 :   char *skel_name = NULL;
   10933         145 :   Dwarf *split_dbg = NULL;
   10934         145 :   Dwarf_CU *split_cu = NULL;
   10935             : 
   10936             :   /* Before we start the real work get a debug context descriptor.  */
   10937             :   Dwarf_Addr dwbias;
   10938         145 :   Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
   10939         435 :   Dwarf dummy_dbg =
   10940             :     {
   10941         145 :       .elf = ebl->elf,
   10942         145 :       .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
   10943             :     };
   10944         145 :   if (dbg == NULL)
   10945             :     {
   10946          28 :       if ((print_debug_sections & ~section_exception) != 0)
   10947           0 :         error (0, 0, gettext ("cannot get debug context descriptor: %s"),
   10948             :                dwfl_errmsg (-1));
   10949             :       dbg = &dummy_dbg;
   10950             :     }
   10951             :   else
   10952             :     {
   10953             :       /* If we are asked about a split dwarf (.dwo) file, use the user
   10954             :          provided, or find the corresponding skeleton file. If we got
   10955             :          a skeleton file, replace the given dwflmod and dbg, with one
   10956             :          derived from the skeleton file to provide enough context.  */
   10957             :       uint64_t split_id;
   10958         117 :       if (is_split_dwarf (dbg, &split_id, &split_cu))
   10959             :         {
   10960           9 :           if (dwarf_skeleton != NULL)
   10961           9 :             skel_name = strdup (dwarf_skeleton);
   10962             :           else
   10963             :             {
   10964             :               /* Replace file.dwo with file.o and see if that matches. */
   10965             :               const char *fname;
   10966           0 :               dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL,
   10967             :                                 &fname, NULL);
   10968           0 :               if (fname != NULL)
   10969             :                 {
   10970           0 :                   size_t flen = strlen (fname);
   10971           0 :                   if (flen > 4 && strcmp (".dwo", fname + flen - 4) == 0)
   10972             :                     {
   10973           0 :                       skel_name = strdup (fname);
   10974           0 :                       if (skel_name != NULL)
   10975             :                         {
   10976           0 :                           skel_name[flen - 3] = 'o';
   10977           0 :                           skel_name[flen - 2] = '\0';
   10978             :                         }
   10979             :                     }
   10980             :                 }
   10981             :             }
   10982             : 
   10983           9 :           if (skel_name != NULL)
   10984             :             {
   10985           9 :               int skel_fd = open (skel_name, O_RDONLY);
   10986           9 :               if (skel_fd == -1)
   10987           0 :                 fprintf (stderr, "Warning: Couldn't open DWARF skeleton file"
   10988             :                          " '%s'\n", skel_name);
   10989             :               else
   10990           9 :                 skel_dwfl = create_dwfl (skel_fd, skel_name);
   10991             : 
   10992           9 :               if (skel_dwfl != NULL)
   10993             :                 {
   10994           9 :                   if (dwfl_getmodules (skel_dwfl, &getone_dwflmod,
   10995             :                                        &skel_mod, 0) != 0)
   10996             :                     {
   10997           0 :                       fprintf (stderr, "Warning: Bad DWARF skeleton,"
   10998             :                                " multiple modules '%s'\n", skel_name);
   10999           0 :                       dwfl_end (skel_dwfl);
   11000           0 :                       skel_mod = NULL;
   11001             :                     }
   11002             :                 }
   11003           0 :               else if (skel_fd != -1)
   11004           0 :                 fprintf (stderr, "Warning: Couldn't create skeleton dwfl for"
   11005             :                          " '%s': %s\n", skel_name, dwfl_errmsg (-1));
   11006             : 
   11007           9 :               if (skel_mod != NULL)
   11008             :                 {
   11009           9 :                   Dwarf *skel_dbg = dwfl_module_getdwarf (skel_mod, &dwbias);
   11010           9 :                   if (skel_dbg != NULL)
   11011             :                     {
   11012             :                       /* First check the skeleton CU DIE, only fetch
   11013             :                          the split DIE if we know the id matches to
   11014             :                          not unnecessary search for any split DIEs we
   11015             :                          don't need. */
   11016           9 :                       Dwarf_CU *cu = NULL;
   11017          22 :                       while (dwarf_get_units (skel_dbg, cu, &cu,
   11018             :                                               NULL, NULL, NULL, NULL) == 0)
   11019             :                         {
   11020             :                           uint8_t unit_type;
   11021             :                           uint64_t skel_id;
   11022          13 :                           if (dwarf_cu_info (cu, NULL, &unit_type, NULL, NULL,
   11023             :                                              &skel_id, NULL, NULL) == 0
   11024          13 :                               && unit_type == DW_UT_skeleton
   11025          13 :                               && split_id == skel_id)
   11026             :                             {
   11027             :                               Dwarf_Die subdie;
   11028           9 :                               if (dwarf_cu_info (cu, NULL, NULL, NULL,
   11029             :                                                  &subdie,
   11030             :                                                  NULL, NULL, NULL) == 0
   11031           9 :                                   && dwarf_tag (&subdie) != DW_TAG_invalid)
   11032             :                                 {
   11033           9 :                                   split_dbg = dwarf_cu_getdwarf (subdie.cu);
   11034           9 :                                   if (split_dbg == NULL)
   11035           0 :                                     fprintf (stderr,
   11036             :                                              "Warning: Couldn't get split_dbg:"
   11037             :                                              " %s\n", dwarf_errmsg (-1));
   11038           9 :                                   break;
   11039             :                                 }
   11040             :                               else
   11041             :                                 {
   11042             :                                   /* Everything matches up, but not
   11043             :                                      according to libdw. Which means
   11044             :                                      the user knew better.  So...
   11045             :                                      Terrible hack... We can never
   11046             :                                      destroy the underlying dwfl
   11047             :                                      because it would free the wrong
   11048             :                                      Dwarfs... So we leak memory...*/
   11049           0 :                                   if (cu->split == NULL
   11050           0 :                                       && dwarf_skeleton != NULL)
   11051             :                                     {
   11052           0 :                                       do_not_close_dwfl = true;
   11053           0 :                                       __libdw_link_skel_split (cu, split_cu);
   11054           0 :                                       split_dbg = dwarf_cu_getdwarf (split_cu);
   11055           0 :                                       break;
   11056             :                                     }
   11057             :                                   else
   11058           0 :                                     fprintf (stderr, "Warning: Couldn't get"
   11059             :                                              " skeleton subdie: %s\n",
   11060             :                                              dwarf_errmsg (-1));
   11061             :                                 }
   11062             :                             }
   11063             :                         }
   11064           9 :                       if (split_dbg == NULL)
   11065           0 :                         fprintf (stderr, "Warning: '%s' didn't contain a skeleton for split id %" PRIx64 "\n", skel_name, split_id);
   11066             :                     }
   11067             :                   else
   11068           0 :                     fprintf (stderr, "Warning: Couldn't get skeleton DWARF:"
   11069             :                              " %s\n", dwfl_errmsg (-1));
   11070             :                 }
   11071             :             }
   11072             : 
   11073           9 :           if (split_dbg != NULL)
   11074             :             {
   11075           9 :               dbg = split_dbg;
   11076           9 :               dwflmod = skel_mod;
   11077             :             }
   11078           0 :           else if (skel_name == NULL)
   11079           0 :             fprintf (stderr,
   11080             :                      "Warning: split DWARF file, but no skeleton found.\n");
   11081             :         }
   11082         108 :       else if (dwarf_skeleton != NULL)
   11083           0 :         fprintf (stderr, "Warning: DWARF skeleton given,"
   11084             :                  " but not a split DWARF file\n");
   11085             :     }
   11086             : 
   11087             :   /* Get the section header string table index.  */
   11088             :   size_t shstrndx;
   11089         145 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   11090             :     error (EXIT_FAILURE, 0,
   11091           0 :            gettext ("cannot get section header string table index"));
   11092             : 
   11093             :   /* If the .debug_info section is listed as implicitly required then
   11094             :      we must make sure to handle it before handling any other debug
   11095             :      section.  Various other sections depend on the CU DIEs being
   11096             :      scanned (silently) first.  */
   11097         145 :   bool implicit_info = (implicit_debug_sections & section_info) != 0;
   11098         145 :   bool explicit_info = (print_debug_sections & section_info) != 0;
   11099         145 :   if (implicit_info)
   11100             :     {
   11101             :       Elf_Scn *scn = NULL;
   11102        1514 :       while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   11103             :         {
   11104             :           GElf_Shdr shdr_mem;
   11105        1514 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   11106             : 
   11107        1514 :           if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
   11108             :             {
   11109         620 :               const char *name = elf_strptr (ebl->elf, shstrndx,
   11110         620 :                                              shdr->sh_name);
   11111         620 :               if (name == NULL)
   11112           0 :                 continue;
   11113             : 
   11114         620 :               if (strcmp (name, ".debug_info") == 0
   11115         558 :                   || strcmp (name, ".debug_info.dwo") == 0
   11116         549 :                   || strcmp (name, ".zdebug_info") == 0
   11117         543 :                   || strcmp (name, ".zdebug_info.dwo") == 0)
   11118             :                 {
   11119          77 :                   print_debug_info_section (dwflmod, ebl, ehdr,
   11120             :                                             scn, shdr, dbg);
   11121          77 :                   break;
   11122             :                 }
   11123             :             }
   11124             :         }
   11125          77 :       print_debug_sections &= ~section_info;
   11126          77 :       implicit_debug_sections &= ~section_info;
   11127             :     }
   11128             : 
   11129             :   /* Look through all the sections for the debugging sections to print.  */
   11130             :   Elf_Scn *scn = NULL;
   11131        4398 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   11132             :     {
   11133             :       GElf_Shdr shdr_mem;
   11134        4253 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   11135             : 
   11136        4253 :       if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
   11137             :         {
   11138             :           static const struct
   11139             :           {
   11140             :             const char *name;
   11141             :             enum section_e bitmask;
   11142             :             void (*fp) (Dwfl_Module *, Ebl *,
   11143             :                         GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
   11144             :           } debug_sections[] =
   11145             :             {
   11146             : #define NEW_SECTION(name) \
   11147             :               { ".debug_" #name, section_##name, print_debug_##name##_section }
   11148             :               NEW_SECTION (abbrev),
   11149             :               NEW_SECTION (addr),
   11150             :               NEW_SECTION (aranges),
   11151             :               NEW_SECTION (frame),
   11152             :               NEW_SECTION (info),
   11153             :               NEW_SECTION (types),
   11154             :               NEW_SECTION (line),
   11155             :               NEW_SECTION (loc),
   11156             :               /* loclists is loc for DWARF5.  */
   11157             :               { ".debug_loclists", section_loc,
   11158             :                 print_debug_loclists_section },
   11159             :               NEW_SECTION (pubnames),
   11160             :               NEW_SECTION (str),
   11161             :               /* A DWARF5 specialised debug string section.  */
   11162             :               { ".debug_line_str", section_str,
   11163             :                 print_debug_str_section },
   11164             :               /* DWARF5 string offsets table.  */
   11165             :               { ".debug_str_offsets", section_str,
   11166             :                 print_debug_str_offsets_section },
   11167             :               NEW_SECTION (macinfo),
   11168             :               NEW_SECTION (macro),
   11169             :               NEW_SECTION (ranges),
   11170             :               /* rnglists is ranges for DWARF5.  */
   11171             :               { ".debug_rnglists", section_ranges,
   11172             :                 print_debug_rnglists_section },
   11173             :               { ".eh_frame", section_frame | section_exception,
   11174             :                 print_debug_frame_section },
   11175             :               { ".eh_frame_hdr", section_frame | section_exception,
   11176             :                 print_debug_frame_hdr_section },
   11177             :               { ".gcc_except_table", section_frame | section_exception,
   11178             :                 print_debug_exception_table },
   11179             :               { ".gdb_index", section_gdb_index, print_gdb_index_section }
   11180             :             };
   11181        2073 :           const int ndebug_sections = (sizeof (debug_sections)
   11182             :                                        / sizeof (debug_sections[0]));
   11183        2073 :           const char *name = elf_strptr (ebl->elf, shstrndx,
   11184        2073 :                                          shdr->sh_name);
   11185        2073 :           if (name == NULL)
   11186           0 :             continue;
   11187             : 
   11188             :           int n;
   11189       30604 :           for (n = 0; n < ndebug_sections; ++n)
   11190             :             {
   11191       31566 :               size_t dbglen = strlen (debug_sections[n].name);
   11192       31566 :               size_t scnlen = strlen (name);
   11193       31566 :               if ((strncmp (name, debug_sections[n].name, dbglen) == 0
   11194         964 :                    && (dbglen == scnlen
   11195         138 :                        || (scnlen == dbglen + 4
   11196         121 :                            && strstr (name, ".dwo") == name + dbglen)))
   11197       30686 :                   || (name[0] == '.' && name[1] == 'z'
   11198         566 :                       && debug_sections[n].name[1] == 'd'
   11199         566 :                       && strncmp (&name[2], &debug_sections[n].name[1],
   11200             :                                   dbglen - 1) == 0
   11201          82 :                       && (scnlen == dbglen + 1
   11202           0 :                           || (scnlen == dbglen + 5
   11203           0 :                               && strstr (name, ".dwo") == name + dbglen + 1))))
   11204             :                 {
   11205        1924 :                   if ((print_debug_sections | implicit_debug_sections)
   11206         962 :                       & debug_sections[n].bitmask)
   11207         357 :                     debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
   11208             :                   break;
   11209             :                 }
   11210             :             }
   11211             :         }
   11212             :     }
   11213             : 
   11214         145 :   dwfl_end (skel_dwfl);
   11215         145 :   free (skel_name);
   11216             : 
   11217             :   /* Turn implicit and/or explicit back on in case we go over another file.  */
   11218         145 :   if (implicit_info)
   11219          77 :     implicit_debug_sections |= section_info;
   11220         145 :   if (explicit_info)
   11221          59 :     print_debug_sections |= section_info;
   11222             : 
   11223         145 :   reset_listptr (&known_locsptr);
   11224         145 :   reset_listptr (&known_loclistsptr);
   11225         145 :   reset_listptr (&known_rangelistptr);
   11226         145 :   reset_listptr (&known_rnglistptr);
   11227         145 :   reset_listptr (&known_addrbases);
   11228         145 :   reset_listptr (&known_stroffbases);
   11229         145 : }
   11230             : 
   11231             : 
   11232             : #define ITEM_INDENT             4
   11233             : #define WRAP_COLUMN             75
   11234             : 
   11235             : /* Print "NAME: FORMAT", wrapping when output text would make the line
   11236             :    exceed WRAP_COLUMN.  Unpadded numbers look better for the core items
   11237             :    but this function is also used for registers which should be printed
   11238             :    aligned.  Fortunately registers output uses fixed fields width (such
   11239             :    as %11d) for the alignment.
   11240             : 
   11241             :    Line breaks should not depend on the particular values although that
   11242             :    may happen in some cases of the core items.  */
   11243             : 
   11244             : static unsigned int
   11245             : __attribute__ ((format (printf, 6, 7)))
   11246         820 : print_core_item (unsigned int colno, char sep, unsigned int wrap,
   11247             :                  size_t name_width, const char *name, const char *format, ...)
   11248             : {
   11249         820 :   size_t len = strlen (name);
   11250         820 :   if (name_width < len)
   11251         396 :     name_width = len;
   11252             : 
   11253             :   char *out;
   11254             :   va_list ap;
   11255         820 :   va_start (ap, format);
   11256         820 :   int out_len = vasprintf (&out, format, ap);
   11257         820 :   va_end (ap);
   11258         820 :   if (out_len == -1)
   11259           0 :     error (EXIT_FAILURE, 0, _("memory exhausted"));
   11260             : 
   11261         820 :   size_t n = name_width + sizeof ": " - 1 + out_len;
   11262             : 
   11263         820 :   if (colno == 0)
   11264             :     {
   11265          51 :       printf ("%*s", ITEM_INDENT, "");
   11266          51 :       colno = ITEM_INDENT + n;
   11267             :     }
   11268         769 :   else if (colno + 2 + n < wrap)
   11269             :     {
   11270         934 :       printf ("%c ", sep);
   11271         467 :       colno += 2 + n;
   11272             :     }
   11273             :   else
   11274             :     {
   11275         302 :       printf ("\n%*s", ITEM_INDENT, "");
   11276         302 :       colno = ITEM_INDENT + n;
   11277             :     }
   11278             : 
   11279        1640 :   printf ("%s: %*s%s", name, (int) (name_width - len), "", out);
   11280             : 
   11281         820 :   free (out);
   11282             : 
   11283         820 :   return colno;
   11284             : }
   11285             : 
   11286             : static const void *
   11287         930 : convert (Elf *core, Elf_Type type, uint_fast16_t count,
   11288             :          void *value, const void *data, size_t size)
   11289             : {
   11290        1860 :   Elf_Data valuedata =
   11291             :     {
   11292             :       .d_type = type,
   11293             :       .d_buf = value,
   11294         930 :       .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
   11295             :       .d_version = EV_CURRENT,
   11296             :     };
   11297         930 :   Elf_Data indata =
   11298             :     {
   11299             :       .d_type = type,
   11300             :       .d_buf = (void *) data,
   11301             :       .d_size = valuedata.d_size,
   11302             :       .d_version = EV_CURRENT,
   11303             :     };
   11304             : 
   11305        1860 :   Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
   11306        1860 :                  ? elf32_xlatetom : elf64_xlatetom)
   11307         930 :     (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
   11308         930 :   if (d == NULL)
   11309           0 :     error (EXIT_FAILURE, 0,
   11310           0 :            gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   11311             : 
   11312         930 :   return data + indata.d_size;
   11313             : }
   11314             : 
   11315             : typedef uint8_t GElf_Byte;
   11316             : 
   11317             : static unsigned int
   11318         399 : handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
   11319             :                   unsigned int colno, size_t *repeated_size)
   11320             : {
   11321         399 :   uint_fast16_t count = item->count ?: 1;
   11322             :   /* Ebl_Core_Item count is always a small number.
   11323             :      Make sure the backend didn't put in some large bogus value.  */
   11324          62 :   assert (count < 128);
   11325             : 
   11326             : #define TYPES                                                                 \
   11327             :   DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8);                         \
   11328             :   DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16);                       \
   11329             :   DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32);                       \
   11330             :   DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32);                         \
   11331             :   DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64);                            \
   11332             :   DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64)
   11333             : 
   11334             : #define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name
   11335             :   typedef union { TYPES; } value_t;
   11336         399 :   void *data = alloca (count * sizeof (value_t));
   11337             : #undef DO_TYPE
   11338             : 
   11339             : #define DO_TYPE(NAME, Name, hex, dec) \
   11340             :     GElf_##Name *value_##Name __attribute__((unused)) = data
   11341         399 :   TYPES;
   11342             : #undef DO_TYPE
   11343             : 
   11344         399 :   size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
   11345         399 :   size_t convsize = size;
   11346         399 :   if (repeated_size != NULL)
   11347             :     {
   11348           1 :       if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
   11349             :         {
   11350           0 :           data = alloca (*repeated_size);
   11351           0 :           count *= *repeated_size / size;
   11352           0 :           convsize = count * size;
   11353           0 :           *repeated_size -= convsize;
   11354             :         }
   11355           1 :       else if (item->count != 0 || item->format != '\n')
   11356           0 :         *repeated_size -= size;
   11357             :     }
   11358             : 
   11359         399 :   convert (core, item->type, count, data, desc + item->offset, convsize);
   11360             : 
   11361         399 :   Elf_Type type = item->type;
   11362         399 :   if (type == ELF_T_ADDR)
   11363           0 :     type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
   11364             : 
   11365         399 :   switch (item->format)
   11366             :     {
   11367         193 :     case 'd':
   11368         193 :       assert (count == 1);
   11369         193 :       switch (type)
   11370             :         {
   11371             : #define DO_TYPE(NAME, Name, hex, dec)                                         \
   11372             :           case ELF_T_##NAME:                                                  \
   11373             :             colno = print_core_item (colno, ',', WRAP_COLUMN,                 \
   11374             :                                      0, item->name, dec, value_##Name[0]); \
   11375             :             break
   11376          27 :           TYPES;
   11377             : #undef DO_TYPE
   11378           0 :         default:
   11379           0 :           abort ();
   11380             :         }
   11381             :       break;
   11382             : 
   11383         110 :     case 'x':
   11384         110 :       assert (count == 1);
   11385         110 :       switch (type)
   11386             :         {
   11387             : #define DO_TYPE(NAME, Name, hex, dec)                                         \
   11388             :           case ELF_T_##NAME:                                                  \
   11389             :             colno = print_core_item (colno, ',', WRAP_COLUMN,                 \
   11390             :                                      0, item->name, hex, value_##Name[0]);      \
   11391             :             break
   11392           0 :           TYPES;
   11393             : #undef DO_TYPE
   11394           0 :         default:
   11395           0 :           abort ();
   11396             :         }
   11397             :       break;
   11398             : 
   11399          22 :     case 'b':
   11400             :     case 'B':
   11401          22 :       assert (size % sizeof (unsigned int) == 0);
   11402          22 :       unsigned int nbits = count * size * 8;
   11403          22 :       unsigned int pop = 0;
   11404          56 :       for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
   11405          34 :         pop += __builtin_popcount (*i);
   11406          22 :       bool negate = pop > nbits / 2;
   11407          22 :       const unsigned int bias = item->format == 'b';
   11408             : 
   11409          44 :       {
   11410          22 :         char printed[(negate ? nbits - pop : pop) * 16 + 1];
   11411          22 :         char *p = printed;
   11412          22 :         *p = '\0';
   11413             : 
   11414             :         if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
   11415             :           {
   11416             :             assert (size == sizeof (unsigned int) * 2);
   11417             :             for (unsigned int *i = data;
   11418             :                  (void *) i < data + count * size; i += 2)
   11419             :               {
   11420             :                 unsigned int w = i[1];
   11421             :                 i[1] = i[0];
   11422             :                 i[0] = w;
   11423             :               }
   11424             :           }
   11425             : 
   11426          22 :         unsigned int lastbit = 0;
   11427          22 :         unsigned int run = 0;
   11428          78 :         for (const unsigned int *i = data;
   11429          34 :              (void *) i < data + count * size; ++i)
   11430             :           {
   11431          34 :             unsigned int bit = ((void *) i - data) * 8;
   11432          34 :             unsigned int w = negate ? ~*i : *i;
   11433          34 :             while (w != 0)
   11434             :               {
   11435             :                 /* Note that a right shift equal to (or greater than)
   11436             :                    the number of bits of w is undefined behaviour.  In
   11437             :                    particular when the least significant bit is bit 32
   11438             :                    (w = 0x8000000) then w >>= n is undefined.  So
   11439             :                    explicitly handle that case separately.  */
   11440           0 :                 unsigned int n = ffs (w);
   11441           0 :                 if (n < sizeof (w) * 8)
   11442           0 :                   w >>= n;
   11443             :                 else
   11444             :                   w = 0;
   11445           0 :                 bit += n;
   11446             : 
   11447           0 :                 if (lastbit != 0 && lastbit + 1 == bit)
   11448           0 :                   ++run;
   11449             :                 else
   11450             :                   {
   11451           0 :                     if (lastbit == 0)
   11452           0 :                       p += sprintf (p, "%u", bit - bias);
   11453           0 :                     else if (run == 0)
   11454           0 :                       p += sprintf (p, ",%u", bit - bias);
   11455             :                     else
   11456           0 :                       p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
   11457             :                     run = 0;
   11458             :                   }
   11459             : 
   11460             :                 lastbit = bit;
   11461             :               }
   11462             :           }
   11463          22 :         if (lastbit > 0 && run > 0 && lastbit + 1 != nbits)
   11464           0 :           p += sprintf (p, "-%u", lastbit - bias);
   11465             : 
   11466          22 :         colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
   11467             :                                  negate ? "~<%s>" : "<%s>", printed);
   11468             :       }
   11469          22 :       break;
   11470             : 
   11471          44 :     case 'T':
   11472             :     case (char) ('T'|0x80):
   11473          44 :       assert (count == 2);
   11474             :       Dwarf_Word sec;
   11475             :       Dwarf_Word usec;
   11476          44 :       switch (type)
   11477             :         {
   11478             : #define DO_TYPE(NAME, Name, hex, dec)                                         \
   11479             :           case ELF_T_##NAME:                                                  \
   11480             :             sec = value_##Name[0];                                            \
   11481             :             usec = value_##Name[1];                                           \
   11482             :             break
   11483           0 :           TYPES;
   11484             : #undef DO_TYPE
   11485           0 :         default:
   11486           0 :           abort ();
   11487             :         }
   11488          44 :       if (unlikely (item->format == (char) ('T'|0x80)))
   11489             :         {
   11490             :           /* This is a hack for an ill-considered 64-bit ABI where
   11491             :              tv_usec is actually a 32-bit field with 32 bits of padding
   11492             :              rounding out struct timeval.  We've already converted it as
   11493             :              a 64-bit field.  For little-endian, this just means the
   11494             :              high half is the padding; it's presumably zero, but should
   11495             :              be ignored anyway.  For big-endian, it means the 32-bit
   11496             :              field went into the high half of USEC.  */
   11497             :           GElf_Ehdr ehdr_mem;
   11498           0 :           GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
   11499           0 :           if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
   11500           0 :             usec >>= 32;
   11501             :           else
   11502           0 :             usec &= UINT32_MAX;
   11503             :         }
   11504          44 :       colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
   11505             :                                "%" PRIu64 ".%.6" PRIu64, sec, usec);
   11506          44 :       break;
   11507             : 
   11508           9 :     case 'c':
   11509           9 :       assert (count == 1);
   11510           9 :       colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
   11511           9 :                                "%c", value_Byte[0]);
   11512           9 :       break;
   11513             : 
   11514          18 :     case 's':
   11515          18 :       colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
   11516             :                                "%.*s", (int) count, value_Byte);
   11517          18 :       break;
   11518             : 
   11519           1 :     case '\n':
   11520             :       /* This is a list of strings separated by '\n'.  */
   11521           1 :       assert (item->count == 0);
   11522           1 :       assert (repeated_size != NULL);
   11523           1 :       assert (item->name == NULL);
   11524           1 :       if (unlikely (item->offset >= *repeated_size))
   11525             :         break;
   11526             : 
   11527           1 :       const char *s = desc + item->offset;
   11528           1 :       size = *repeated_size - item->offset;
   11529           1 :       *repeated_size = 0;
   11530          49 :       while (size > 0)
   11531             :         {
   11532          48 :           const char *eol = memchr (s, '\n', size);
   11533          48 :           int len = size;
   11534          48 :           if (eol != NULL)
   11535          47 :             len = eol - s;
   11536          48 :           printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
   11537          48 :           if (eol == NULL)
   11538             :             break;
   11539          47 :           size -= eol + 1 - s;
   11540          47 :           s = eol + 1;
   11541             :         }
   11542             : 
   11543             :       colno = WRAP_COLUMN;
   11544             :       break;
   11545             : 
   11546             :     case 'h':
   11547             :       break;
   11548             : 
   11549           0 :     default:
   11550           0 :       error (0, 0, "XXX not handling format '%c' for %s",
   11551             :              item->format, item->name);
   11552             :       break;
   11553             :     }
   11554             : 
   11555             : #undef TYPES
   11556             : 
   11557         399 :   return colno;
   11558             : }
   11559             : 
   11560             : 
   11561             : /* Sort items by group, and by layout offset within each group.  */
   11562             : static int
   11563         891 : compare_core_items (const void *a, const void *b)
   11564             : {
   11565         891 :   const Ebl_Core_Item *const *p1 = a;
   11566         891 :   const Ebl_Core_Item *const *p2 = b;
   11567         891 :   const Ebl_Core_Item *item1 = *p1;
   11568         891 :   const Ebl_Core_Item *item2 = *p2;
   11569             : 
   11570         891 :   return ((item1->group == item2->group ? 0
   11571         891 :            : strcmp (item1->group, item2->group))
   11572         428 :           ?: (int) item1->offset - (int) item2->offset);
   11573             : }
   11574             : 
   11575             : /* Sort item groups by layout offset of the first item in the group.  */
   11576             : static int
   11577         139 : compare_core_item_groups (const void *a, const void *b)
   11578             : {
   11579         139 :   const Ebl_Core_Item *const *const *p1 = a;
   11580         139 :   const Ebl_Core_Item *const *const *p2 = b;
   11581         139 :   const Ebl_Core_Item *const *group1 = *p1;
   11582         139 :   const Ebl_Core_Item *const *group2 = *p2;
   11583         139 :   const Ebl_Core_Item *item1 = *group1;
   11584         139 :   const Ebl_Core_Item *item2 = *group2;
   11585             : 
   11586         139 :   return (int) item1->offset - (int) item2->offset;
   11587             : }
   11588             : 
   11589             : static unsigned int
   11590          37 : handle_core_items (Elf *core, const void *desc, size_t descsz,
   11591             :                    const Ebl_Core_Item *items, size_t nitems)
   11592             : {
   11593          37 :   if (nitems == 0)
   11594             :     return 0;
   11595          34 :   unsigned int colno = 0;
   11596             : 
   11597             :   /* FORMAT '\n' makes sense to be present only as a single item as it
   11598             :      processes all the data of a note.  FORMATs 'b' and 'B' have a special case
   11599             :      if present as a single item but they can be also processed with other
   11600             :      items below.  */
   11601          34 :   if (nitems == 1 && (items[0].format == '\n' || items[0].format == 'b'
   11602           8 :                       || items[0].format == 'B'))
   11603             :     {
   11604           1 :       assert (items[0].offset == 0);
   11605           1 :       size_t size = descsz;
   11606           1 :       colno = handle_core_item (core, items, desc, colno, &size);
   11607             :       /* If SIZE is not zero here there is some remaining data.  But we do not
   11608             :          know how to process it anyway.  */
   11609             :       return colno;
   11610             :     }
   11611         390 :   for (size_t i = 0; i < nitems; ++i)
   11612         390 :     assert (items[i].format != '\n');
   11613             : 
   11614             :   /* Sort to collect the groups together.  */
   11615          33 :   const Ebl_Core_Item *sorted_items[nitems];
   11616         423 :   for (size_t i = 0; i < nitems; ++i)
   11617         390 :     sorted_items[i] = &items[i];
   11618          33 :   qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
   11619             : 
   11620             :   /* Collect the unique groups and sort them.  */
   11621          33 :   const Ebl_Core_Item **groups[nitems];
   11622          33 :   groups[0] = &sorted_items[0];
   11623          33 :   size_t ngroups = 1;
   11624         390 :   for (size_t i = 1; i < nitems; ++i)
   11625         357 :     if (sorted_items[i]->group != sorted_items[i - 1]->group
   11626          75 :         && strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
   11627          75 :       groups[ngroups++] = &sorted_items[i];
   11628          33 :   qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
   11629             : 
   11630             :   /* Write out all the groups.  */
   11631          33 :   const void *last = desc;
   11632             :   do
   11633             :     {
   11634         145 :       for (size_t i = 0; i < ngroups; ++i)
   11635             :         {
   11636         618 :           for (const Ebl_Core_Item **item = groups[i];
   11637         508 :                (item < &sorted_items[nitems]
   11638         473 :                 && ((*item)->group == groups[i][0]->group
   11639          75 :                     || !strcmp ((*item)->group, groups[i][0]->group)));
   11640         398 :                ++item)
   11641         398 :             colno = handle_core_item (core, *item, desc, colno, NULL);
   11642             : 
   11643             :           /* Force a line break at the end of the group.  */
   11644         110 :           colno = WRAP_COLUMN;
   11645             :         }
   11646             : 
   11647          35 :       if (descsz == 0)
   11648             :         break;
   11649             : 
   11650             :       /* This set of items consumed a certain amount of the note's data.
   11651             :          If there is more data there, we have another unit of the same size.
   11652             :          Loop to print that out too.  */
   11653          20 :       const Ebl_Core_Item *item = &items[nitems - 1];
   11654          40 :       size_t eltsz = item->offset + gelf_fsize (core, item->type,
   11655          20 :                                                 item->count ?: 1, EV_CURRENT);
   11656             : 
   11657          20 :       int reps = -1;
   11658             :       do
   11659             :         {
   11660          20 :           ++reps;
   11661          20 :           desc += eltsz;
   11662          20 :           descsz -= eltsz;
   11663             :         }
   11664          20 :       while (descsz >= eltsz && !memcmp (desc, last, eltsz));
   11665             : 
   11666          20 :       if (reps == 1)
   11667             :         {
   11668             :           /* For just one repeat, print it unabridged twice.  */
   11669             :           desc -= eltsz;
   11670             :           descsz += eltsz;
   11671             :         }
   11672          20 :       else if (reps > 1)
   11673           0 :         printf (gettext ("\n%*s... <repeats %u more times> ..."),
   11674             :                 ITEM_INDENT, "", reps);
   11675             : 
   11676          20 :       last = desc;
   11677             :     }
   11678          20 :   while (descsz > 0);
   11679             : 
   11680             :   return colno;
   11681             : }
   11682             : 
   11683             : static unsigned int
   11684             : handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
   11685             :                       unsigned int colno)
   11686             : {
   11687           0 :   desc += regloc->offset;
   11688             : 
   11689           0 :   abort ();                     /* XXX */
   11690             :   return colno;
   11691             : }
   11692             : 
   11693             : 
   11694             : static unsigned int
   11695         162 : handle_core_register (Ebl *ebl, Elf *core, int maxregname,
   11696             :                       const Ebl_Register_Location *regloc, const void *desc,
   11697             :                       unsigned int colno)
   11698             : {
   11699         162 :   if (regloc->bits % 8 != 0)
   11700           0 :     return handle_bit_registers (regloc, desc, colno);
   11701             : 
   11702         162 :   desc += regloc->offset;
   11703             : 
   11704         586 :   for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
   11705             :     {
   11706             :       char name[REGNAMESZ];
   11707             :       int bits;
   11708             :       int type;
   11709         424 :       register_info (ebl, reg, regloc, name, &bits, &type);
   11710             : 
   11711             : #define TYPES                                                                 \
   11712             :       BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8);                          \
   11713             :       BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16);                       \
   11714             :       BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32);                             \
   11715             :       BITS (64, XWORD, "%20" PRId64, "  0x%.16" PRIx64)
   11716             : 
   11717             : #define BITS(bits, xtype, sfmt, ufmt)                           \
   11718             :       uint##bits##_t b##bits; int##bits##_t b##bits##s
   11719             :       union { TYPES; uint64_t b128[2]; } value;
   11720             : #undef  BITS
   11721             : 
   11722         424 :       switch (type)
   11723             :         {
   11724         336 :         case DW_ATE_unsigned:
   11725             :         case DW_ATE_signed:
   11726             :         case DW_ATE_address:
   11727         336 :           switch (bits)
   11728             :             {
   11729             : #define BITS(bits, xtype, sfmt, ufmt)                                         \
   11730             :             case bits:                                                        \
   11731             :               desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0);           \
   11732             :               if (type == DW_ATE_signed)                                      \
   11733             :                 colno = print_core_item (colno, ' ', WRAP_COLUMN,             \
   11734             :                                          maxregname, name,                    \
   11735             :                                          sfmt, value.b##bits##s);             \
   11736             :               else                                                            \
   11737             :                 colno = print_core_item (colno, ' ', WRAP_COLUMN,             \
   11738             :                                          maxregname, name,                    \
   11739             :                                          ufmt, value.b##bits);                \
   11740             :               break
   11741             : 
   11742           0 :             TYPES;
   11743             : 
   11744          48 :             case 128:
   11745          48 :               assert (type == DW_ATE_unsigned);
   11746          48 :               desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
   11747          48 :               int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
   11748          96 :               colno = print_core_item (colno, ' ', WRAP_COLUMN,
   11749             :                                        maxregname, name,
   11750             :                                        "0x%.16" PRIx64 "%.16" PRIx64,
   11751          48 :                                        value.b128[!be], value.b128[be]);
   11752          48 :               break;
   11753             : 
   11754           0 :             default:
   11755           0 :               abort ();
   11756             : #undef  BITS
   11757             :             }
   11758             :           break;
   11759             : 
   11760          88 :         default:
   11761             :           /* Print each byte in hex, the whole thing in native byte order.  */
   11762          88 :           assert (bits % 8 == 0);
   11763          88 :           const uint8_t *bytes = desc;
   11764          88 :           desc += bits / 8;
   11765          88 :           char hex[bits / 4 + 1];
   11766          88 :           hex[bits / 4] = '\0';
   11767          88 :           int incr = 1;
   11768          88 :           if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
   11769             :             {
   11770          48 :               bytes += bits / 8 - 1;
   11771          48 :               incr = -1;
   11772             :             }
   11773          88 :           size_t idx = 0;
   11774         872 :           for (char *h = hex; bits > 0; bits -= 8, idx += incr)
   11775             :             {
   11776         784 :               *h++ = "0123456789abcdef"[bytes[idx] >> 4];
   11777         784 :               *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
   11778             :             }
   11779          88 :           colno = print_core_item (colno, ' ', WRAP_COLUMN,
   11780             :                                    maxregname, name, "0x%s", hex);
   11781             :           break;
   11782             :         }
   11783         424 :       desc += regloc->pad;
   11784             : 
   11785             : #undef TYPES
   11786             :     }
   11787             : 
   11788             :   return colno;
   11789             : }
   11790             : 
   11791             : 
   11792             : struct register_info
   11793             : {
   11794             :   const Ebl_Register_Location *regloc;
   11795             :   const char *set;
   11796             :   char name[REGNAMESZ];
   11797             :   int regno;
   11798             :   int bits;
   11799             :   int type;
   11800             : };
   11801             : 
   11802             : static int
   11803             : register_bitpos (const struct register_info *r)
   11804             : {
   11805        2066 :   return (r->regloc->offset * 8
   11806        4132 :           + ((r->regno - r->regloc->regno)
   11807        2066 :              * (r->regloc->bits + r->regloc->pad * 8)));
   11808             : }
   11809             : 
   11810             : static int
   11811        1062 : compare_sets_by_info (const struct register_info *r1,
   11812             :                       const struct register_info *r2)
   11813             : {
   11814        1062 :   return ((int) r2->bits - (int) r1->bits
   11815        3128 :           ?: register_bitpos (r1) - register_bitpos (r2));
   11816             : }
   11817             : 
   11818             : /* Sort registers by set, and by size and layout offset within each set.  */
   11819             : static int
   11820        4595 : compare_registers (const void *a, const void *b)
   11821             : {
   11822        4595 :   const struct register_info *r1 = a;
   11823        4595 :   const struct register_info *r2 = b;
   11824             : 
   11825             :   /* Unused elements sort last.  */
   11826        4595 :   if (r1->regloc == NULL)
   11827        3309 :     return r2->regloc == NULL ? 0 : 1;
   11828        1286 :   if (r2->regloc == NULL)
   11829             :     return -1;
   11830             : 
   11831        1121 :   return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
   11832          79 :           ?: compare_sets_by_info (r1, r2));
   11833             : }
   11834             : 
   11835             : /* Sort register sets by layout offset of the first register in the set.  */
   11836             : static int
   11837          20 : compare_register_sets (const void *a, const void *b)
   11838             : {
   11839          20 :   const struct register_info *const *p1 = a;
   11840          20 :   const struct register_info *const *p2 = b;
   11841          20 :   return compare_sets_by_info (*p1, *p2);
   11842             : }
   11843             : 
   11844             : static unsigned int
   11845          37 : handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
   11846             :                        const Ebl_Register_Location *reglocs, size_t nregloc)
   11847             : {
   11848          37 :   if (nregloc == 0)
   11849             :     return 0;
   11850             : 
   11851          18 :   ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
   11852          18 :   if (maxnreg <= 0)
   11853             :     {
   11854           0 :       for (size_t i = 0; i < nregloc; ++i)
   11855           0 :         if (maxnreg < reglocs[i].regno + reglocs[i].count)
   11856           0 :           maxnreg = reglocs[i].regno + reglocs[i].count;
   11857           0 :       assert (maxnreg > 0);
   11858             :     }
   11859             : 
   11860          18 :   struct register_info regs[maxnreg];
   11861          36 :   memset (regs, 0, sizeof regs);
   11862             : 
   11863             :   /* Sort to collect the sets together.  */
   11864          18 :   int maxreg = 0;
   11865         180 :   for (size_t i = 0; i < nregloc; ++i)
   11866         748 :     for (int reg = reglocs[i].regno;
   11867         586 :          reg < reglocs[i].regno + reglocs[i].count;
   11868         424 :          ++reg)
   11869             :       {
   11870         424 :         assert (reg < maxnreg);
   11871         424 :         if (reg > maxreg)
   11872         230 :           maxreg = reg;
   11873         424 :         struct register_info *info = &regs[reg];
   11874         424 :         info->regloc = &reglocs[i];
   11875         424 :         info->regno = reg;
   11876         848 :         info->set = register_info (ebl, reg, &reglocs[i],
   11877         424 :                                    info->name, &info->bits, &info->type);
   11878             :       }
   11879          18 :   qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
   11880             : 
   11881             :   /* Collect the unique sets and sort them.  */
   11882         864 :   inline bool same_set (const struct register_info *a,
   11883             :                         const struct register_info *b)
   11884             :   {
   11885        1728 :     return (a < &regs[maxnreg] && a->regloc != NULL
   11886         864 :             && b < &regs[maxnreg] && b->regloc != NULL
   11887         846 :             && a->bits == b->bits
   11888        1692 :             && (a->set == b->set || !strcmp (a->set, b->set)));
   11889             :   }
   11890          18 :   struct register_info *sets[maxreg + 1];
   11891          18 :   sets[0] = &regs[0];
   11892          18 :   size_t nsets = 1;
   11893        1279 :   for (int i = 1; i <= maxreg; ++i)
   11894        1261 :     if (regs[i].regloc != NULL && !same_set (&regs[i], &regs[i - 1]))
   11895          16 :       sets[nsets++] = &regs[i];
   11896          18 :   qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
   11897             : 
   11898             :   /* Write out all the sets.  */
   11899          18 :   unsigned int colno = 0;
   11900          52 :   for (size_t i = 0; i < nsets; ++i)
   11901             :     {
   11902             :       /* Find the longest name of a register in this set.  */
   11903          34 :       size_t maxname = 0;
   11904             :       const struct register_info *end;
   11905         458 :       for (end = sets[i]; same_set (sets[i], end); ++end)
   11906             :         {
   11907         424 :           size_t len = strlen (end->name);
   11908         424 :           if (len > maxname)
   11909          52 :             maxname = len;
   11910             :         }
   11911             : 
   11912         196 :       for (const struct register_info *reg = sets[i];
   11913             :            reg < end;
   11914         162 :            reg += reg->regloc->count ?: 1)
   11915         162 :         colno = handle_core_register (ebl, core, maxname,
   11916             :                                       reg->regloc, desc, colno);
   11917             : 
   11918             :       /* Force a line break at the end of the group.  */
   11919          34 :       colno = WRAP_COLUMN;
   11920             :     }
   11921             : 
   11922             :   return colno;
   11923             : }
   11924             : 
   11925             : static void
   11926           9 : handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
   11927             : {
   11928           9 :   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
   11929           9 :   if (data == NULL)
   11930           0 :   elf_error:
   11931           0 :     error (EXIT_FAILURE, 0,
   11932           0 :            gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   11933             : 
   11934           9 :   const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
   11935         177 :   for (size_t i = 0; i < nauxv; ++i)
   11936             :     {
   11937             :       GElf_auxv_t av_mem;
   11938         168 :       GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
   11939         168 :       if (av == NULL)
   11940             :         goto elf_error;
   11941             : 
   11942             :       const char *name;
   11943             :       const char *fmt;
   11944         168 :       if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
   11945             :         {
   11946             :           /* Unknown type.  */
   11947           0 :           if (av->a_un.a_val == 0)
   11948           0 :             printf ("    %" PRIu64 "\n", av->a_type);
   11949             :           else
   11950           0 :             printf ("    %" PRIu64 ": %#" PRIx64 "\n",
   11951             :                     av->a_type, av->a_un.a_val);
   11952             :         }
   11953             :       else
   11954         168 :         switch (fmt[0])
   11955             :           {
   11956           9 :           case '\0':            /* Normally zero.  */
   11957           9 :             if (av->a_un.a_val == 0)
   11958             :               {
   11959           9 :                 printf ("    %s\n", name);
   11960             :                 break;
   11961             :               }
   11962             :             FALLTHROUGH;
   11963             :           case 'x':             /* hex */
   11964             :           case 'p':             /* address */
   11965             :           case 's':             /* address of string */
   11966          74 :             printf ("    %s: %#" PRIx64 "\n", name, av->a_un.a_val);
   11967             :             break;
   11968          81 :           case 'u':
   11969          81 :             printf ("    %s: %" PRIu64 "\n", name, av->a_un.a_val);
   11970             :             break;
   11971           0 :           case 'd':
   11972           0 :             printf ("    %s: %" PRId64 "\n", name, av->a_un.a_val);
   11973             :             break;
   11974             : 
   11975           4 :           case 'b':
   11976           8 :             printf ("    %s: %#" PRIx64 "  ", name, av->a_un.a_val);
   11977           4 :             GElf_Xword bit = 1;
   11978           4 :             const char *pfx = "<";
   11979         110 :             for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
   11980             :               {
   11981         106 :                 if (av->a_un.a_val & bit)
   11982             :                   {
   11983          77 :                     printf ("%s%s", pfx, p);
   11984          77 :                     pfx = " ";
   11985             :                   }
   11986         106 :                 bit <<= 1;
   11987             :               }
   11988             :             printf (">\n");
   11989             :             break;
   11990             : 
   11991           0 :           default:
   11992           0 :             abort ();
   11993             :           }
   11994             :     }
   11995           9 : }
   11996             : 
   11997             : static bool
   11998             : buf_has_data (unsigned char const *ptr, unsigned char const *end, size_t sz)
   11999             : {
   12000         195 :   return ptr < end && (size_t) (end - ptr) >= sz;
   12001             : }
   12002             : 
   12003             : static bool
   12004          18 : buf_read_int (Elf *core, unsigned char const **ptrp, unsigned char const *end,
   12005             :               int *retp)
   12006             : {
   12007          36 :   if (! buf_has_data (*ptrp, end, 4))
   12008             :     return false;
   12009             : 
   12010          18 :   *ptrp = convert (core, ELF_T_WORD, 1, retp, *ptrp, 4);
   12011          18 :   return true;
   12012             : }
   12013             : 
   12014             : static bool
   12015         177 : buf_read_ulong (Elf *core, unsigned char const **ptrp, unsigned char const *end,
   12016             :                 uint64_t *retp)
   12017             : {
   12018         177 :   size_t sz = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
   12019         354 :   if (! buf_has_data (*ptrp, end, sz))
   12020             :     return false;
   12021             : 
   12022             :   union
   12023             :   {
   12024             :     uint64_t u64;
   12025             :     uint32_t u32;
   12026             :   } u;
   12027             : 
   12028         177 :   *ptrp = convert (core, ELF_T_ADDR, 1, &u, *ptrp, sz);
   12029             : 
   12030         177 :   if (sz == 4)
   12031          93 :     *retp = u.u32;
   12032             :   else
   12033          84 :     *retp = u.u64;
   12034             :   return true;
   12035             : }
   12036             : 
   12037             : static void
   12038           6 : handle_siginfo_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
   12039             : {
   12040           6 :   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
   12041           6 :   if (data == NULL)
   12042           0 :     error (EXIT_FAILURE, 0,
   12043           0 :            gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   12044             : 
   12045           6 :   unsigned char const *ptr = data->d_buf;
   12046           6 :   unsigned char const *const end = data->d_buf + data->d_size;
   12047             : 
   12048             :   /* Siginfo head is three ints: signal number, error number, origin
   12049             :      code.  */
   12050             :   int si_signo, si_errno, si_code;
   12051           6 :   if (! buf_read_int (core, &ptr, end, &si_signo)
   12052           6 :       || ! buf_read_int (core, &ptr, end, &si_errno)
   12053           6 :       || ! buf_read_int (core, &ptr, end, &si_code))
   12054             :     {
   12055           0 :     fail:
   12056           0 :       printf ("    Not enough data in NT_SIGINFO note.\n");
   12057           0 :       return;
   12058             :     }
   12059             : 
   12060             :   /* Next is a pointer-aligned union of structures.  On 64-bit
   12061             :      machines, that implies a word of padding.  */
   12062           6 :   if (gelf_getclass (core) == ELFCLASS64)
   12063           3 :     ptr += 4;
   12064             : 
   12065          12 :   printf ("    si_signo: %d, si_errno: %d, si_code: %d\n",
   12066             :           si_signo, si_errno, si_code);
   12067             : 
   12068           6 :   if (si_code > 0)
   12069           6 :     switch (si_signo)
   12070             :       {
   12071           6 :       case CORE_SIGILL:
   12072             :       case CORE_SIGFPE:
   12073             :       case CORE_SIGSEGV:
   12074             :       case CORE_SIGBUS:
   12075             :         {
   12076             :           uint64_t addr;
   12077           6 :           if (! buf_read_ulong (core, &ptr, end, &addr))
   12078             :             goto fail;
   12079          12 :           printf ("    fault address: %#" PRIx64 "\n", addr);
   12080           6 :           break;
   12081             :         }
   12082             :       default:
   12083             :         ;
   12084             :       }
   12085           0 :   else if (si_code == CORE_SI_USER)
   12086             :     {
   12087             :       int pid, uid;
   12088           0 :       if (! buf_read_int (core, &ptr, end, &pid)
   12089           0 :           || ! buf_read_int (core, &ptr, end, &uid))
   12090             :         goto fail;
   12091           0 :       printf ("    sender PID: %d, sender UID: %d\n", pid, uid);
   12092             :     }
   12093             : }
   12094             : 
   12095             : static void
   12096           6 : handle_file_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
   12097             : {
   12098           6 :   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
   12099           6 :   if (data == NULL)
   12100           0 :     error (EXIT_FAILURE, 0,
   12101           0 :            gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
   12102             : 
   12103           6 :   unsigned char const *ptr = data->d_buf;
   12104           6 :   unsigned char const *const end = data->d_buf + data->d_size;
   12105             : 
   12106             :   uint64_t count, page_size;
   12107           6 :   if (! buf_read_ulong (core, &ptr, end, &count)
   12108           6 :       || ! buf_read_ulong (core, &ptr, end, &page_size))
   12109             :     {
   12110           0 :     fail:
   12111           0 :       printf ("    Not enough data in NT_FILE note.\n");
   12112           0 :       return;
   12113             :     }
   12114             : 
   12115           6 :   size_t addrsize = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
   12116           6 :   uint64_t maxcount = (size_t) (end - ptr) / (3 * addrsize);
   12117           6 :   if (count > maxcount)
   12118             :     goto fail;
   12119             : 
   12120             :   /* Where file names are stored.  */
   12121           6 :   unsigned char const *const fstart = ptr + 3 * count * addrsize;
   12122           6 :   char const *fptr = (char *) fstart;
   12123             : 
   12124          12 :   printf ("    %" PRId64 " files:\n", count);
   12125          59 :   for (uint64_t i = 0; i < count; ++i)
   12126             :     {
   12127             :       uint64_t mstart, mend, moffset;
   12128          53 :       if (! buf_read_ulong (core, &ptr, fstart, &mstart)
   12129          53 :           || ! buf_read_ulong (core, &ptr, fstart, &mend)
   12130          53 :           || ! buf_read_ulong (core, &ptr, fstart, &moffset))
   12131             :         goto fail;
   12132             : 
   12133          53 :       const char *fnext = memchr (fptr, '\0', (char *) end - fptr);
   12134          53 :       if (fnext == NULL)
   12135             :         goto fail;
   12136             : 
   12137         106 :       int ct = printf ("      %08" PRIx64 "-%08" PRIx64
   12138             :                        " %08" PRIx64 " %" PRId64,
   12139             :                        mstart, mend, moffset * page_size, mend - mstart);
   12140         106 :       printf ("%*s%s\n", ct > 50 ? 3 : 53 - ct, "", fptr);
   12141             : 
   12142          53 :       fptr = fnext + 1;
   12143             :     }
   12144             : }
   12145             : 
   12146             : static void
   12147          38 : handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
   12148             :                   const char *name, const void *desc)
   12149             : {
   12150             :   GElf_Word regs_offset;
   12151             :   size_t nregloc;
   12152             :   const Ebl_Register_Location *reglocs;
   12153             :   size_t nitems;
   12154             :   const Ebl_Core_Item *items;
   12155             : 
   12156          38 :   if (! ebl_core_note (ebl, nhdr, name,
   12157             :                        &regs_offset, &nregloc, &reglocs, &nitems, &items))
   12158           1 :     return;
   12159             : 
   12160             :   /* Pass 0 for DESCSZ when there are registers in the note,
   12161             :      so that the ITEMS array does not describe the whole thing.
   12162             :      For non-register notes, the actual descsz might be a multiple
   12163             :      of the unit size, not just exactly the unit size.  */
   12164          93 :   unsigned int colno = handle_core_items (ebl->elf, desc,
   12165          56 :                                           nregloc == 0 ? nhdr->n_descsz : 0,
   12166             :                                           items, nitems);
   12167          37 :   if (colno != 0)
   12168             :     putchar_unlocked ('\n');
   12169             : 
   12170          37 :   colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
   12171             :                                  reglocs, nregloc);
   12172          37 :   if (colno != 0)
   12173             :     putchar_unlocked ('\n');
   12174             : }
   12175             : 
   12176             : static void
   12177          51 : handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
   12178             :                    GElf_Off start, Elf_Data *data)
   12179             : {
   12180          51 :   fputs_unlocked (gettext ("  Owner          Data size  Type\n"), stdout);
   12181             : 
   12182          51 :   if (data == NULL)
   12183             :     goto bad_note;
   12184             : 
   12185             :   size_t offset = 0;
   12186             :   GElf_Nhdr nhdr;
   12187             :   size_t name_offset;
   12188             :   size_t desc_offset;
   12189         171 :   while (offset < data->d_size
   12190         120 :          && (offset = gelf_getnote (data, offset,
   12191             :                                     &nhdr, &name_offset, &desc_offset)) > 0)
   12192             :     {
   12193         120 :       const char *name = nhdr.n_namesz == 0 ? "" : data->d_buf + name_offset;
   12194         120 :       const char *desc = data->d_buf + desc_offset;
   12195             : 
   12196             :       /* GNU Build Attributes are weird, they store most of their data
   12197             :          into the owner name field.  Extract just the owner name
   12198             :          prefix here, then use the rest later as data.  */
   12199         120 :       bool is_gnu_build_attr
   12200         120 :         = strncmp (name, ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX,
   12201             :                    strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX)) == 0;
   12202         120 :       const char *print_name = (is_gnu_build_attr
   12203         120 :                                 ? ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX : name);
   12204         120 :       size_t print_namesz = (is_gnu_build_attr
   12205         120 :                              ? strlen (print_name) : nhdr.n_namesz);
   12206             : 
   12207             :       char buf[100];
   12208             :       char buf2[100];
   12209         360 :       printf (gettext ("  %-13.*s  %9" PRId32 "  %s\n"),
   12210             :               (int) print_namesz, print_name, nhdr.n_descsz,
   12211         120 :               ehdr->e_type == ET_CORE
   12212          59 :               ? ebl_core_note_type_name (ebl, nhdr.n_type,
   12213             :                                          buf, sizeof (buf))
   12214          61 :               : ebl_object_note_type_name (ebl, name, nhdr.n_type,
   12215             :                                            nhdr.n_descsz,
   12216             :                                            buf2, sizeof (buf2)));
   12217             : 
   12218             :       /* Filter out invalid entries.  */
   12219             :       if (memchr (name, '\0', nhdr.n_namesz) != NULL
   12220             :           /* XXX For now help broken Linux kernels.  */
   12221             :           || 1)
   12222             :         {
   12223         120 :           if (ehdr->e_type == ET_CORE)
   12224             :             {
   12225          59 :               if (nhdr.n_type == NT_AUXV
   12226           9 :                   && (nhdr.n_namesz == 4 /* Broken old Linux kernels.  */
   12227           9 :                       || (nhdr.n_namesz == 5 && name[4] == '\0'))
   12228           9 :                   && !memcmp (name, "CORE", 4))
   12229           9 :                 handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
   12230             :                                   start + desc_offset);
   12231          50 :               else if (nhdr.n_namesz == 5 && strcmp (name, "CORE") == 0)
   12232          38 :                 switch (nhdr.n_type)
   12233             :                   {
   12234           6 :                   case NT_SIGINFO:
   12235           6 :                     handle_siginfo_note (ebl->elf, nhdr.n_descsz,
   12236             :                                          start + desc_offset);
   12237             :                     break;
   12238             : 
   12239           6 :                   case NT_FILE:
   12240           6 :                     handle_file_note (ebl->elf, nhdr.n_descsz,
   12241             :                                       start + desc_offset);
   12242             :                     break;
   12243             : 
   12244          26 :                   default:
   12245          26 :                     handle_core_note (ebl, &nhdr, name, desc);
   12246             :                   }
   12247             :               else
   12248          12 :                 handle_core_note (ebl, &nhdr, name, desc);
   12249             :             }
   12250             :           else
   12251          61 :             ebl_object_note (ebl, nhdr.n_namesz, name, nhdr.n_type,
   12252             :                              nhdr.n_descsz, desc);
   12253             :         }
   12254             :     }
   12255             : 
   12256          51 :   if (offset == data->d_size)
   12257          51 :     return;
   12258             : 
   12259           0 :  bad_note:
   12260           0 :   error (0, 0,
   12261           0 :          gettext ("cannot get content of note: %s"),
   12262             :          data != NULL ? "garbage data" : elf_errmsg (-1));
   12263             : }
   12264             : 
   12265             : static void
   12266          55 : handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
   12267             : {
   12268             :   /* If we have section headers, just look for SHT_NOTE sections.
   12269             :      In a debuginfo file, the program headers are not reliable.  */
   12270          55 :   if (shnum != 0)
   12271             :     {
   12272             :       /* Get the section header string table index.  */
   12273             :       size_t shstrndx;
   12274          44 :       if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
   12275             :         error (EXIT_FAILURE, 0,
   12276           0 :                gettext ("cannot get section header string table index"));
   12277             : 
   12278             :       Elf_Scn *scn = NULL;
   12279        1142 :       while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   12280             :         {
   12281             :           GElf_Shdr shdr_mem;
   12282        1098 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   12283             : 
   12284        1098 :           if (shdr == NULL || shdr->sh_type != SHT_NOTE)
   12285             :             /* Not what we are looking for.  */
   12286        1059 :             continue;
   12287             : 
   12288         117 :           printf (gettext ("\
   12289             : \nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
   12290             :                   elf_ndxscn (scn),
   12291          39 :                   elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   12292             :                   shdr->sh_size, shdr->sh_offset);
   12293             : 
   12294          39 :           handle_notes_data (ebl, ehdr, shdr->sh_offset,
   12295             :                              elf_getdata (scn, NULL));
   12296             :         }
   12297             :       return;
   12298             :     }
   12299             : 
   12300             :   /* We have to look through the program header to find the note
   12301             :      sections.  There can be more than one.  */
   12302         129 :   for (size_t cnt = 0; cnt < phnum; ++cnt)
   12303             :     {
   12304             :       GElf_Phdr mem;
   12305         129 :       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
   12306             : 
   12307         129 :       if (phdr == NULL || phdr->p_type != PT_NOTE)
   12308             :         /* Not what we are looking for.  */
   12309         117 :         continue;
   12310             : 
   12311          24 :       printf (gettext ("\
   12312             : \nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
   12313             :               phdr->p_filesz, phdr->p_offset);
   12314             : 
   12315          24 :       handle_notes_data (ebl, ehdr, phdr->p_offset,
   12316             :                          elf_getdata_rawchunk (ebl->elf,
   12317          12 :                                                phdr->p_offset, phdr->p_filesz,
   12318          12 :                                                (phdr->p_align == 8
   12319             :                                                 ? ELF_T_NHDR8 : ELF_T_NHDR)));
   12320             :     }
   12321             : }
   12322             : 
   12323             : 
   12324             : static void
   12325           5 : hex_dump (const uint8_t *data, size_t len)
   12326             : {
   12327           5 :   size_t pos = 0;
   12328          31 :   while (pos < len)
   12329             :     {
   12330          21 :       printf ("  0x%08zx ", pos);
   12331             : 
   12332          21 :       const size_t chunk = MIN (len - pos, 16);
   12333             : 
   12334         342 :       for (size_t i = 0; i < chunk; ++i)
   12335         321 :         if (i % 4 == 3)
   12336          80 :           printf ("%02x ", data[pos + i]);
   12337             :         else
   12338         241 :           printf ("%02x", data[pos + i]);
   12339             : 
   12340          21 :       if (chunk < 16)
   12341           1 :         printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
   12342             : 
   12343         321 :       for (size_t i = 0; i < chunk; ++i)
   12344             :         {
   12345         321 :           unsigned char b = data[pos + i];
   12346         642 :           printf ("%c", isprint (b) ? b : '.');
   12347             :         }
   12348             : 
   12349          21 :       putchar ('\n');
   12350          21 :       pos += chunk;
   12351             :     }
   12352           5 : }
   12353             : 
   12354             : static void
   12355           5 : dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
   12356             : {
   12357           5 :   if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
   12358           0 :     printf (gettext ("\nSection [%zu] '%s' has no data to dump.\n"),
   12359             :             elf_ndxscn (scn), name);
   12360             :   else
   12361             :     {
   12362           5 :       if (print_decompress)
   12363             :         {
   12364             :           /* We try to decompress the section, but keep the old shdr around
   12365             :              so we can show both the original shdr size and the uncompressed
   12366             :              data size.   */
   12367           4 :           if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
   12368             :             {
   12369           2 :               if (elf_compress (scn, 0, 0) < 0)
   12370           0 :                 printf ("WARNING: %s [%zd]\n",
   12371             :                         gettext ("Couldn't uncompress section"),
   12372             :                         elf_ndxscn (scn));
   12373             :             }
   12374           2 :           else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
   12375             :             {
   12376           2 :               if (elf_compress_gnu (scn, 0, 0) < 0)
   12377           0 :                 printf ("WARNING: %s [%zd]\n",
   12378             :                         gettext ("Couldn't uncompress section"),
   12379             :                         elf_ndxscn (scn));
   12380             :             }
   12381             :         }
   12382             : 
   12383           5 :       Elf_Data *data = elf_rawdata (scn, NULL);
   12384           5 :       if (data == NULL)
   12385           0 :         error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
   12386             :                elf_ndxscn (scn), name, elf_errmsg (-1));
   12387             :       else
   12388             :         {
   12389           5 :           if (data->d_size == shdr->sh_size)
   12390           1 :             printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
   12391             :                              " bytes at offset %#0" PRIx64 ":\n"),
   12392             :                     elf_ndxscn (scn), name,
   12393             :                     shdr->sh_size, shdr->sh_offset);
   12394             :           else
   12395           4 :             printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
   12396             :                              " bytes (%zd uncompressed) at offset %#0"
   12397             :                              PRIx64 ":\n"),
   12398             :                     elf_ndxscn (scn), name,
   12399             :                     shdr->sh_size, data->d_size, shdr->sh_offset);
   12400           5 :           hex_dump (data->d_buf, data->d_size);
   12401             :         }
   12402             :     }
   12403           5 : }
   12404             : 
   12405             : static void
   12406          89 : print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
   12407             : {
   12408          89 :   if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
   12409           0 :     printf (gettext ("\nSection [%zu] '%s' has no strings to dump.\n"),
   12410             :             elf_ndxscn (scn), name);
   12411             :   else
   12412             :     {
   12413          89 :       if (print_decompress)
   12414             :         {
   12415             :           /* We try to decompress the section, but keep the old shdr around
   12416             :              so we can show both the original shdr size and the uncompressed
   12417             :              data size.  */
   12418           1 :           if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
   12419             :             {
   12420           0 :               if (elf_compress (scn, 0, 0) < 0)
   12421           0 :                 printf ("WARNING: %s [%zd]\n",
   12422             :                         gettext ("Couldn't uncompress section"),
   12423             :                         elf_ndxscn (scn));
   12424             :             }
   12425           1 :           else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
   12426             :             {
   12427           1 :               if (elf_compress_gnu (scn, 0, 0) < 0)
   12428           0 :                 printf ("WARNING: %s [%zd]\n",
   12429             :                         gettext ("Couldn't uncompress section"),
   12430             :                         elf_ndxscn (scn));
   12431             :             }
   12432             :         }
   12433             : 
   12434          89 :       Elf_Data *data = elf_rawdata (scn, NULL);
   12435          89 :       if (data == NULL)
   12436           0 :         error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
   12437             :                elf_ndxscn (scn), name, elf_errmsg (-1));
   12438             :       else
   12439             :         {
   12440          89 :           if (data->d_size == shdr->sh_size)
   12441          88 :             printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
   12442             :                              " bytes at offset %#0" PRIx64 ":\n"),
   12443             :                     elf_ndxscn (scn), name,
   12444             :                     shdr->sh_size, shdr->sh_offset);
   12445             :           else
   12446           1 :             printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
   12447             :                              " bytes (%zd uncompressed) at offset %#0"
   12448             :                              PRIx64 ":\n"),
   12449             :                     elf_ndxscn (scn), name,
   12450             :                     shdr->sh_size, data->d_size, shdr->sh_offset);
   12451             : 
   12452          89 :           const char *start = data->d_buf;
   12453          89 :           const char *const limit = start + data->d_size;
   12454             :           do
   12455             :             {
   12456       16129 :               const char *end = memchr (start, '\0', limit - start);
   12457       16129 :               const size_t pos = start - (const char *) data->d_buf;
   12458       16129 :               if (unlikely (end == NULL))
   12459             :                 {
   12460           0 :                   printf ("  [%6zx]- %.*s\n",
   12461             :                           pos, (int) (limit - start), start);
   12462             :                   break;
   12463             :                 }
   12464       16129 :               printf ("  [%6zx]  %s\n", pos, start);
   12465       16129 :               start = end + 1;
   12466       16129 :             } while (start < limit);
   12467             :         }
   12468             :     }
   12469          89 : }
   12470             : 
   12471             : static void
   12472          46 : for_each_section_argument (Elf *elf, const struct section_argument *list,
   12473             :                            void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
   12474             :                                          const char *name))
   12475             : {
   12476             :   /* Get the section header string table index.  */
   12477             :   size_t shstrndx;
   12478          46 :   if (elf_getshdrstrndx (elf, &shstrndx) < 0)
   12479             :     error (EXIT_FAILURE, 0,
   12480           0 :            gettext ("cannot get section header string table index"));
   12481             : 
   12482         126 :   for (const struct section_argument *a = list; a != NULL; a = a->next)
   12483             :     {
   12484             :       Elf_Scn *scn;
   12485             :       GElf_Shdr shdr_mem;
   12486         126 :       const char *name = NULL;
   12487             : 
   12488         126 :       char *endp = NULL;
   12489         126 :       unsigned long int shndx = strtoul (a->arg, &endp, 0);
   12490         126 :       if (endp != a->arg && *endp == '\0')
   12491             :         {
   12492           0 :           scn = elf_getscn (elf, shndx);
   12493           0 :           if (scn == NULL)
   12494             :             {
   12495           0 :               error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
   12496           0 :               continue;
   12497             :             }
   12498             : 
   12499           0 :           if (gelf_getshdr (scn, &shdr_mem) == NULL)
   12500           0 :             error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
   12501             :                    elf_errmsg (-1));
   12502           0 :           name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
   12503             :         }
   12504             :       else
   12505             :         {
   12506             :           /* Need to look up the section by name.  */
   12507             :           scn = NULL;
   12508             :           bool found = false;
   12509        3207 :           while ((scn = elf_nextscn (elf, scn)) != NULL)
   12510             :             {
   12511        3081 :               if (gelf_getshdr (scn, &shdr_mem) == NULL)
   12512           0 :                 continue;
   12513        3081 :               name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
   12514        3081 :               if (name == NULL)
   12515           0 :                 continue;
   12516        3081 :               if (!strcmp (name, a->arg))
   12517             :                 {
   12518          94 :                   found = true;
   12519          94 :                   (*dump) (scn, &shdr_mem, name);
   12520             :                 }
   12521             :             }
   12522             : 
   12523         126 :           if (unlikely (!found) && !a->implicit)
   12524           0 :             error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
   12525             :         }
   12526             :     }
   12527          46 : }
   12528             : 
   12529             : static void
   12530             : dump_data (Ebl *ebl)
   12531             : {
   12532           5 :   for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
   12533             : }
   12534             : 
   12535             : static void
   12536             : dump_strings (Ebl *ebl)
   12537             : {
   12538          41 :   for_each_section_argument (ebl->elf, string_sections, &print_string_section);
   12539             : }
   12540             : 
   12541             : static void
   12542           0 : print_strings (Ebl *ebl)
   12543             : {
   12544             :   /* Get the section header string table index.  */
   12545             :   size_t shstrndx;
   12546           0 :   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   12547             :     error (EXIT_FAILURE, 0,
   12548           0 :            gettext ("cannot get section header string table index"));
   12549             : 
   12550             :   Elf_Scn *scn;
   12551             :   GElf_Shdr shdr_mem;
   12552             :   const char *name;
   12553             :   scn = NULL;
   12554           0 :   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   12555             :     {
   12556           0 :       if (gelf_getshdr (scn, &shdr_mem) == NULL)
   12557           0 :         continue;
   12558             : 
   12559           0 :       if (shdr_mem.sh_type != SHT_PROGBITS
   12560           0 :           || !(shdr_mem.sh_flags & SHF_STRINGS))
   12561           0 :         continue;
   12562             : 
   12563           0 :       name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
   12564           0 :       if (name == NULL)
   12565           0 :         continue;
   12566             : 
   12567           0 :       print_string_section (scn, &shdr_mem, name);
   12568             :     }
   12569           0 : }
   12570             : 
   12571             : static void
   12572           2 : dump_archive_index (Elf *elf, const char *fname)
   12573             : {
   12574             :   size_t narsym;
   12575           2 :   const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
   12576           2 :   if (arsym == NULL)
   12577             :     {
   12578           0 :       int result = elf_errno ();
   12579           0 :       if (unlikely (result != ELF_E_NO_INDEX))
   12580           0 :         error (EXIT_FAILURE, 0,
   12581           0 :                gettext ("cannot get symbol index of archive '%s': %s"),
   12582             :                fname, elf_errmsg (result));
   12583             :       else
   12584           0 :         printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
   12585           0 :       return;
   12586             :     }
   12587             : 
   12588           4 :   printf (gettext ("\nIndex of archive '%s' has %zu entries:\n"),
   12589             :           fname, narsym);
   12590             : 
   12591           2 :   size_t as_off = 0;
   12592          11 :   for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
   12593             :     {
   12594           9 :       if (s->as_off != as_off)
   12595             :         {
   12596           6 :           as_off = s->as_off;
   12597             : 
   12598           6 :           Elf *subelf = NULL;
   12599           6 :           if (unlikely (elf_rand (elf, as_off) == 0)
   12600           6 :               || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
   12601             :                            == NULL))
   12602             : #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
   12603             :             while (1)
   12604             : #endif
   12605           0 :               error (EXIT_FAILURE, 0,
   12606           0 :                      gettext ("cannot extract member at offset %zu in '%s': %s"),
   12607             :                      as_off, fname, elf_errmsg (-1));
   12608             : 
   12609           6 :           const Elf_Arhdr *h = elf_getarhdr (subelf);
   12610             : 
   12611          12 :           printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
   12612             : 
   12613           6 :           elf_end (subelf);
   12614             :         }
   12615             : 
   12616          18 :       printf ("\t%s\n", s->as_name);
   12617             :     }
   12618             : }
   12619             : 
   12620             : #include "debugpred.h"

Generated by: LCOV version 1.13