LCOV - code coverage report
Current view: top level - elfutils/src - readelf.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 2465 3587 68.7 %
Date: 2013-03-08 Functions: 104 120 86.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1540 3158 48.8 %

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

Generated by: LCOV version 1.9