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;