Home | History | Annotate | Download | only in src
      1 /* Print information from ELF file in human-readable form.
      2    Copyright (C) 1999-2018 Red Hat, Inc.
      3    This file is part of elfutils.
      4 
      5    This file is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by
      7    the Free Software Foundation; either version 3 of the License, or
      8    (at your option) any later version.
      9 
     10    elfutils is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13    GNU General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License
     16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     17 
     18 #ifdef HAVE_CONFIG_H
     19 # include <config.h>
     20 #endif
     21 
     22 #include <argp.h>
     23 #include <assert.h>
     24 #include <ctype.h>
     25 #include <dwarf.h>
     26 #include <errno.h>
     27 #include <fcntl.h>
     28 #include <gelf.h>
     29 #include <inttypes.h>
     30 #include <langinfo.h>
     31 #include <libdw.h>
     32 #include <libdwfl.h>
     33 #include <libintl.h>
     34 #include <locale.h>
     35 #include <stdarg.h>
     36 #include <stdbool.h>
     37 #include <stdio.h>
     38 #include <stdio_ext.h>
     39 #include <stdlib.h>
     40 #include <string.h>
     41 #include <strings.h>
     42 #include <time.h>
     43 #include <unistd.h>
     44 #include <sys/stat.h>
     45 #include <signal.h>
     46 
     47 #include <libeu.h>
     48 #include <system.h>
     49 #include <printversion.h>
     50 #include "../libelf/libelfP.h"
     51 #include "../libelf/common.h"
     52 #include "../libebl/libeblP.h"
     53 #include "../libdwelf/libdwelf.h"
     54 #include "../libdw/libdwP.h"
     55 #include "../libdwfl/libdwflP.h"
     56 #include "../libdw/memory-access.h"
     57 
     58 #include "../libdw/known-dwarf.h"
     59 
     60 #ifdef __linux__
     61 #define CORE_SIGILL  SIGILL
     62 #define CORE_SIGBUS  SIGBUS
     63 #define CORE_SIGFPE  SIGFPE
     64 #define CORE_SIGSEGV SIGSEGV
     65 #define CORE_SI_USER SI_USER
     66 #else
     67 /* We want the linux version of those as that is what shows up in the core files. */
     68 #define CORE_SIGILL  4  /* Illegal instruction (ANSI).  */
     69 #define CORE_SIGBUS  7  /* BUS error (4.2 BSD).  */
     70 #define CORE_SIGFPE  8  /* Floating-point exception (ANSI).  */
     71 #define CORE_SIGSEGV 11 /* Segmentation violation (ANSI).  */
     72 #define CORE_SI_USER 0  /* Sent by kill, sigsend.  */
     73 #endif
     74 
     75 /* Name and version of program.  */
     76 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
     77 
     78 /* Bug report address.  */
     79 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
     80 
     81 /* argp key value for --elf-section, non-ascii.  */
     82 #define ELF_INPUT_SECTION 256
     83 
     84 /* argp key value for --dwarf-skeleton, non-ascii.  */
     85 #define DWARF_SKELETON 257
     86 
     87 /* Terrible hack for hooking unrelated skeleton/split compile units,
     88    see __libdw_link_skel_split in print_debug.  */
     89 static bool do_not_close_dwfl = false;
     90 
     91 /* Definitions of arguments for argp functions.  */
     92 static const struct argp_option options[] =
     93 {
     94   { NULL, 0, NULL, 0, N_("ELF input selection:"), 0 },
     95   { "elf-section", ELF_INPUT_SECTION, "SECTION", OPTION_ARG_OPTIONAL,
     96     N_("Use the named SECTION (default .gnu_debugdata) as (compressed) ELF "
     97        "input data"), 0 },
     98   { "dwarf-skeleton", DWARF_SKELETON, "FILE", 0,
     99     N_("Used with -w to find the skeleton Compile Units in FILE associated "
    100        "with the Split Compile units in a .dwo input file"), 0 },
    101   { NULL, 0, NULL, 0, N_("ELF output selection:"), 0 },
    102   { "all", 'a', NULL, 0,
    103     N_("All these plus -p .strtab -p .dynstr -p .comment"), 0 },
    104   { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
    105   { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
    106   { "histogram", 'I', NULL, 0,
    107     N_("Display histogram of bucket list lengths"), 0 },
    108   { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
    109   { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
    110   { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
    111   { "section-groups", 'g', NULL, 0, N_("Display the section groups"), 0 },
    112   { "section-headers", 'S', NULL, 0, N_("Display the sections' headers"), 0 },
    113   { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
    114   { "symbols", 's', "SECTION", OPTION_ARG_OPTIONAL,
    115     N_("Display the symbol table sections"), 0 },
    116   { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
    117   { "notes", 'n', NULL, 0, N_("Display the ELF notes"), 0 },
    118   { "arch-specific", 'A', NULL, 0,
    119     N_("Display architecture specific information, if any"), 0 },
    120   { "exception", 'e', NULL, 0,
    121     N_("Display sections for exception handling"), 0 },
    122 
    123   { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 },
    124   { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
    125     N_("Display DWARF section content.  SECTION can be one of abbrev, addr, "
    126        "aranges, decodedaranges, frame, gdb_index, info, info+, loc, line, "
    127        "decodedline, ranges, pubnames, str, macinfo, macro or exception"), 0 },
    128   { "hex-dump", 'x', "SECTION", 0,
    129     N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
    130   { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
    131     N_("Print string contents of sections"), 0 },
    132   { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
    133   { "archive-index", 'c', NULL, 0,
    134     N_("Display the symbol index of an archive"), 0 },
    135 
    136   { NULL, 0, NULL, 0, N_("Output control:"), 0 },
    137   { "numeric-addresses", 'N', NULL, 0,
    138     N_("Do not find symbol names for addresses in DWARF data"), 0 },
    139   { "unresolved-address-offsets", 'U', NULL, 0,
    140     N_("Display just offsets instead of resolving values to addresses in DWARF data"), 0 },
    141   { "wide", 'W', NULL, 0,
    142     N_("Ignored for compatibility (lines always wide)"), 0 },
    143   { "decompress", 'z', NULL, 0,
    144     N_("Show compression information for compressed sections (when used with -S); decompress section before dumping data (when used with -p or -x)"), 0 },
    145   { NULL, 0, NULL, 0, NULL, 0 }
    146 };
    147 
    148 /* Short description of program.  */
    149 static const char doc[] = N_("\
    150 Print information from ELF file in human-readable form.");
    151 
    152 /* Strings for arguments in help texts.  */
    153 static const char args_doc[] = N_("FILE...");
    154 
    155 /* Prototype for option handler.  */
    156 static error_t parse_opt (int key, char *arg, struct argp_state *state);
    157 
    158 /* Data structure to communicate with argp functions.  */
    159 static struct argp argp =
    160 {
    161   options, parse_opt, args_doc, doc, NULL, NULL, NULL
    162 };
    163 
    164 /* If non-null, the section from which we should read to (compressed) ELF.  */
    165 static const char *elf_input_section = NULL;
    166 
    167 /* If non-null, the file that contains the skeleton CUs.  */
    168 static const char *dwarf_skeleton = NULL;
    169 
    170 /* Flags set by the option controlling the output.  */
    171 
    172 /* True if dynamic segment should be printed.  */
    173 static bool print_dynamic_table;
    174 
    175 /* True if the file header should be printed.  */
    176 static bool print_file_header;
    177 
    178 /* True if the program headers should be printed.  */
    179 static bool print_program_header;
    180 
    181 /* True if relocations should be printed.  */
    182 static bool print_relocations;
    183 
    184 /* True if the section headers should be printed.  */
    185 static bool print_section_header;
    186 
    187 /* True if the symbol table should be printed.  */
    188 static bool print_symbol_table;
    189 
    190 /* A specific section name, or NULL to print all symbol tables.  */
    191 static char *symbol_table_section;
    192 
    193 /* True if the version information should be printed.  */
    194 static bool print_version_info;
    195 
    196 /* True if section groups should be printed.  */
    197 static bool print_section_groups;
    198 
    199 /* True if bucket list length histogram should be printed.  */
    200 static bool print_histogram;
    201 
    202 /* True if the architecture specific data should be printed.  */
    203 static bool print_arch;
    204 
    205 /* True if note section content should be printed.  */
    206 static bool print_notes;
    207 
    208 /* True if SHF_STRINGS section content should be printed.  */
    209 static bool print_string_sections;
    210 
    211 /* True if archive index should be printed.  */
    212 static bool print_archive_index;
    213 
    214 /* True if any of the control options except print_archive_index is set.  */
    215 static bool any_control_option;
    216 
    217 /* True if we should print addresses from DWARF in symbolic form.  */
    218 static bool print_address_names = true;
    219 
    220 /* True if we should print raw values instead of relativized addresses.  */
    221 static bool print_unresolved_addresses = false;
    222 
    223 /* True if we should print the .debug_aranges section using libdw.  */
    224 static bool decodedaranges = false;
    225 
    226 /* True if we should print the .debug_aranges section using libdw.  */
    227 static bool decodedline = false;
    228 
    229 /* True if we want to show more information about compressed sections.  */
    230 static bool print_decompress = false;
    231 
    232 /* True if we want to show split compile units for debug_info skeletons.  */
    233 static bool show_split_units = false;
    234 
    235 /* Select printing of debugging sections.  */
    236 static enum section_e
    237 {
    238   section_abbrev = 1,		/* .debug_abbrev  */
    239   section_aranges = 2,		/* .debug_aranges  */
    240   section_frame = 4,		/* .debug_frame or .eh_frame & al.  */
    241   section_info = 8,		/* .debug_info, (implies .debug_types)  */
    242   section_line = 16,		/* .debug_line  */
    243   section_loc = 32,		/* .debug_loc  */
    244   section_pubnames = 64,	/* .debug_pubnames  */
    245   section_str = 128,		/* .debug_str  */
    246   section_macinfo = 256,	/* .debug_macinfo  */
    247   section_ranges = 512, 	/* .debug_ranges  */
    248   section_exception = 1024,	/* .eh_frame & al.  */
    249   section_gdb_index = 2048,	/* .gdb_index  */
    250   section_macro = 4096,		/* .debug_macro  */
    251   section_addr = 8192,		/* .debug_addr  */
    252   section_types = 16384,	/* .debug_types (implied by .debug_info)  */
    253   section_all = (section_abbrev | section_aranges | section_frame
    254 		 | section_info | section_line | section_loc
    255 		 | section_pubnames | section_str | section_macinfo
    256 		 | section_ranges | section_exception | section_gdb_index
    257 		 | section_macro | section_addr | section_types)
    258 } print_debug_sections, implicit_debug_sections;
    259 
    260 /* Select hex dumping of sections.  */
    261 static struct section_argument *dump_data_sections;
    262 static struct section_argument **dump_data_sections_tail = &dump_data_sections;
    263 
    264 /* Select string dumping of sections.  */
    265 static struct section_argument *string_sections;
    266 static struct section_argument **string_sections_tail = &string_sections;
    267 
    268 struct section_argument
    269 {
    270   struct section_argument *next;
    271   const char *arg;
    272   bool implicit;
    273 };
    274 
    275 /* Numbers of sections and program headers in the file.  */
    276 static size_t shnum;
    277 static size_t phnum;
    278 
    279 
    280 /* Declarations of local functions.  */
    281 static void process_file (int fd, const char *fname, bool only_one);
    282 static void process_elf_file (Dwfl_Module *dwflmod, int fd);
    283 static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
    284 static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
    285 static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
    286 static void print_scngrp (Ebl *ebl);
    287 static void print_dynamic (Ebl *ebl);
    288 static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
    289 static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
    290 			       GElf_Shdr *shdr);
    291 static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
    292 				GElf_Shdr *shdr);
    293 static void print_symtab (Ebl *ebl, int type);
    294 static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
    295 static void print_verinfo (Ebl *ebl);
    296 static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
    297 static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
    298 static void handle_versym (Ebl *ebl, Elf_Scn *scn,
    299 			   GElf_Shdr *shdr);
    300 static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
    301 static void handle_hash (Ebl *ebl);
    302 static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
    303 static void print_liblist (Ebl *ebl);
    304 static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
    305 static void dump_data (Ebl *ebl);
    306 static void dump_strings (Ebl *ebl);
    307 static void print_strings (Ebl *ebl);
    308 static void dump_archive_index (Elf *, const char *);
    309 
    310 
    311 /* Looked up once with gettext in main.  */
    312 static char *yes_str;
    313 static char *no_str;
    314 
    315 int
    316 main (int argc, char *argv[])
    317 {
    318   /* We use no threads here which can interfere with handling a stream.  */
    319   (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
    320 
    321   /* Set locale.  */
    322   setlocale (LC_ALL, "");
    323 
    324   /* Initialize the message catalog.  */
    325   textdomain (PACKAGE_TARNAME);
    326 
    327   /* Look up once.  */
    328   yes_str = gettext ("yes");
    329   no_str = gettext ("no");
    330 
    331   /* Parse and process arguments.  */
    332   int remaining;
    333   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
    334 
    335   /* Before we start tell the ELF library which version we are using.  */
    336   elf_version (EV_CURRENT);
    337 
    338   /* Now process all the files given at the command line.  */
    339   bool only_one = remaining + 1 == argc;
    340   do
    341     {
    342       /* Open the file.  */
    343       int fd = open (argv[remaining], O_RDONLY);
    344       if (fd == -1)
    345 	{
    346 	  error (0, errno, gettext ("cannot open input file"));
    347 	  continue;
    348 	}
    349 
    350       process_file (fd, argv[remaining], only_one);
    351 
    352       close (fd);
    353     }
    354   while (++remaining < argc);
    355 
    356   return error_message_count != 0;
    357 }
    358 
    359 
    360 /* Handle program arguments.  */
    361 static error_t
    362 parse_opt (int key, char *arg,
    363 	   struct argp_state *state __attribute__ ((unused)))
    364 {
    365   void add_dump_section (const char *name, bool implicit)
    366   {
    367     struct section_argument *a = xmalloc (sizeof *a);
    368     a->arg = name;
    369     a->next = NULL;
    370     a->implicit = implicit;
    371     struct section_argument ***tailp
    372       = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
    373     **tailp = a;
    374     *tailp = &a->next;
    375   }
    376 
    377   switch (key)
    378     {
    379     case 'a':
    380       print_file_header = true;
    381       print_program_header = true;
    382       print_relocations = true;
    383       print_section_header = true;
    384       print_symbol_table = true;
    385       print_version_info = true;
    386       print_dynamic_table = true;
    387       print_section_groups = true;
    388       print_histogram = true;
    389       print_arch = true;
    390       print_notes = true;
    391       implicit_debug_sections |= section_exception;
    392       add_dump_section (".strtab", true);
    393       add_dump_section (".dynstr", true);
    394       add_dump_section (".comment", true);
    395       any_control_option = true;
    396       break;
    397     case 'A':
    398       print_arch = true;
    399       any_control_option = true;
    400       break;
    401     case 'd':
    402       print_dynamic_table = true;
    403       any_control_option = true;
    404       break;
    405     case 'e':
    406       print_debug_sections |= section_exception;
    407       any_control_option = true;
    408       break;
    409     case 'g':
    410       print_section_groups = true;
    411       any_control_option = true;
    412       break;
    413     case 'h':
    414       print_file_header = true;
    415       any_control_option = true;
    416       break;
    417     case 'I':
    418       print_histogram = true;
    419       any_control_option = true;
    420       break;
    421     case 'l':
    422       print_program_header = true;
    423       any_control_option = true;
    424       break;
    425     case 'n':
    426       print_notes = true;
    427       any_control_option = true;
    428       break;
    429     case 'r':
    430       print_relocations = true;
    431       any_control_option = true;
    432      break;
    433     case 'S':
    434       print_section_header = true;
    435       any_control_option = true;
    436       break;
    437     case 's':
    438       print_symbol_table = true;
    439       any_control_option = true;
    440       symbol_table_section = arg;
    441       break;
    442     case 'V':
    443       print_version_info = true;
    444       any_control_option = true;
    445       break;
    446     case 'c':
    447       print_archive_index = true;
    448       break;
    449     case 'w':
    450       if (arg == NULL)
    451 	{
    452 	  print_debug_sections = section_all;
    453 	  implicit_debug_sections = section_info;
    454 	  show_split_units = true;
    455 	}
    456       else if (strcmp (arg, "abbrev") == 0)
    457 	print_debug_sections |= section_abbrev;
    458       else if (strcmp (arg, "addr") == 0)
    459 	{
    460 	  print_debug_sections |= section_addr;
    461 	  implicit_debug_sections |= section_info;
    462 	}
    463       else if (strcmp (arg, "aranges") == 0)
    464 	print_debug_sections |= section_aranges;
    465       else if (strcmp (arg, "decodedaranges") == 0)
    466 	{
    467 	  print_debug_sections |= section_aranges;
    468 	  decodedaranges = true;
    469 	}
    470       else if (strcmp (arg, "ranges") == 0)
    471 	{
    472 	  print_debug_sections |= section_ranges;
    473 	  implicit_debug_sections |= section_info;
    474 	}
    475       else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
    476 	print_debug_sections |= section_frame;
    477       else if (strcmp (arg, "info") == 0)
    478 	{
    479 	  print_debug_sections |= section_info;
    480 	  print_debug_sections |= section_types;
    481 	}
    482       else if (strcmp (arg, "info+") == 0)
    483 	{
    484 	  print_debug_sections |= section_info;
    485 	  print_debug_sections |= section_types;
    486 	  show_split_units = true;
    487 	}
    488       else if (strcmp (arg, "loc") == 0)
    489 	{
    490 	  print_debug_sections |= section_loc;
    491 	  implicit_debug_sections |= section_info;
    492 	}
    493       else if (strcmp (arg, "line") == 0)
    494 	print_debug_sections |= section_line;
    495       else if (strcmp (arg, "decodedline") == 0)
    496 	{
    497 	  print_debug_sections |= section_line;
    498 	  decodedline = true;
    499 	}
    500       else if (strcmp (arg, "pubnames") == 0)
    501 	print_debug_sections |= section_pubnames;
    502       else if (strcmp (arg, "str") == 0)
    503 	{
    504 	  print_debug_sections |= section_str;
    505 	  /* For mapping string offset tables to CUs.  */
    506 	  implicit_debug_sections |= section_info;
    507 	}
    508       else if (strcmp (arg, "macinfo") == 0)
    509 	print_debug_sections |= section_macinfo;
    510       else if (strcmp (arg, "macro") == 0)
    511 	print_debug_sections |= section_macro;
    512       else if (strcmp (arg, "exception") == 0)
    513 	print_debug_sections |= section_exception;
    514       else if (strcmp (arg, "gdb_index") == 0)
    515 	print_debug_sections |= section_gdb_index;
    516       else
    517 	{
    518 	  fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
    519 		   arg);
    520 	  argp_help (&argp, stderr, ARGP_HELP_SEE,
    521 		     program_invocation_short_name);
    522 	  exit (1);
    523 	}
    524       any_control_option = true;
    525       break;
    526     case 'p':
    527       any_control_option = true;
    528       if (arg == NULL)
    529 	{
    530 	  print_string_sections = true;
    531 	  break;
    532 	}
    533       FALLTHROUGH;
    534     case 'x':
    535       add_dump_section (arg, false);
    536       any_control_option = true;
    537       break;
    538     case 'N':
    539       print_address_names = false;
    540       break;
    541     case 'U':
    542       print_unresolved_addresses = true;
    543       break;
    544     case ARGP_KEY_NO_ARGS:
    545       fputs (gettext ("Missing file name.\n"), stderr);
    546       goto do_argp_help;
    547     case ARGP_KEY_FINI:
    548       if (! any_control_option && ! print_archive_index)
    549 	{
    550 	  fputs (gettext ("No operation specified.\n"), stderr);
    551 	do_argp_help:
    552 	  argp_help (&argp, stderr, ARGP_HELP_SEE,
    553 		     program_invocation_short_name);
    554 	  exit (EXIT_FAILURE);
    555 	}
    556       break;
    557     case 'W':			/* Ignored.  */
    558       break;
    559     case 'z':
    560       print_decompress = true;
    561       break;
    562     case ELF_INPUT_SECTION:
    563       if (arg == NULL)
    564 	elf_input_section = ".gnu_debugdata";
    565       else
    566 	elf_input_section = arg;
    567       break;
    568     case DWARF_SKELETON:
    569       dwarf_skeleton = arg;
    570       break;
    571     default:
    572       return ARGP_ERR_UNKNOWN;
    573     }
    574   return 0;
    575 }
    576 
    577 
    578 /* Create a file descriptor to read the data from the
    579    elf_input_section given a file descriptor to an ELF file.  */
    580 static int
    581 open_input_section (int fd)
    582 {
    583   size_t shnums;
    584   size_t cnt;
    585   size_t shstrndx;
    586   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
    587   if (elf == NULL)
    588     {
    589       error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
    590 	     elf_errmsg (-1));
    591       return -1;
    592     }
    593 
    594   if (elf_getshdrnum (elf, &shnums) < 0)
    595     {
    596       error (0, 0, gettext ("cannot determine number of sections: %s"),
    597 	     elf_errmsg (-1));
    598     open_error:
    599       elf_end (elf);
    600       return -1;
    601     }
    602 
    603   if (elf_getshdrstrndx (elf, &shstrndx) < 0)
    604     {
    605       error (0, 0, gettext ("cannot get section header string table index"));
    606       goto open_error;
    607     }
    608 
    609   for (cnt = 0; cnt < shnums; ++cnt)
    610     {
    611       Elf_Scn *scn = elf_getscn (elf, cnt);
    612       if (scn == NULL)
    613 	{
    614 	  error (0, 0, gettext ("cannot get section: %s"),
    615 		 elf_errmsg (-1));
    616 	  goto open_error;
    617 	}
    618 
    619       GElf_Shdr shdr_mem;
    620       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    621       if (unlikely (shdr == NULL))
    622 	{
    623 	  error (0, 0, gettext ("cannot get section header: %s"),
    624 		 elf_errmsg (-1));
    625 	  goto open_error;
    626 	}
    627 
    628       const char *sname = elf_strptr (elf, shstrndx, shdr->sh_name);
    629       if (sname == NULL)
    630 	{
    631 	  error (0, 0, gettext ("cannot get section name"));
    632 	  goto open_error;
    633 	}
    634 
    635       if (strcmp (sname, elf_input_section) == 0)
    636 	{
    637 	  Elf_Data *data = elf_rawdata (scn, NULL);
    638 	  if (data == NULL)
    639 	    {
    640 	      error (0, 0, gettext ("cannot get %s content: %s"),
    641 		     sname, elf_errmsg (-1));
    642 	      goto open_error;
    643 	    }
    644 
    645 	  /* Create (and immediately unlink) a temporary file to store
    646 	     section data in to create a file descriptor for it.  */
    647 	  const char *tmpdir = getenv ("TMPDIR") ?: P_tmpdir;
    648 	  static const char suffix[] = "/readelfXXXXXX";
    649 	  int tmplen = strlen (tmpdir) + sizeof (suffix);
    650 	  char *tempname = alloca (tmplen);
    651 	  sprintf (tempname, "%s%s", tmpdir, suffix);
    652 
    653 	  int sfd = mkstemp (tempname);
    654 	  if (sfd == -1)
    655 	    {
    656 	      error (0, 0, gettext ("cannot create temp file '%s'"),
    657 		     tempname);
    658 	      goto open_error;
    659 	    }
    660 	  unlink (tempname);
    661 
    662 	  ssize_t size = data->d_size;
    663 	  if (write_retry (sfd, data->d_buf, size) != size)
    664 	    {
    665 	      error (0, 0, gettext ("cannot write section data"));
    666 	      goto open_error;
    667 	    }
    668 
    669 	  if (elf_end (elf) != 0)
    670 	    {
    671 	      error (0, 0, gettext ("error while closing Elf descriptor: %s"),
    672 		     elf_errmsg (-1));
    673 	      return -1;
    674 	    }
    675 
    676 	  if (lseek (sfd, 0, SEEK_SET) == -1)
    677 	    {
    678 	      error (0, 0, gettext ("error while rewinding file descriptor"));
    679 	      return -1;
    680 	    }
    681 
    682 	  return sfd;
    683 	}
    684     }
    685 
    686   /* Named section not found.  */
    687   if (elf_end (elf) != 0)
    688     error (0, 0, gettext ("error while closing Elf descriptor: %s"),
    689 	   elf_errmsg (-1));
    690   return -1;
    691 }
    692 
    693 /* Check if the file is an archive, and if so dump its index.  */
    694 static void
    695 check_archive_index (int fd, const char *fname, bool only_one)
    696 {
    697   /* Create an `Elf' descriptor.  */
    698   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
    699   if (elf == NULL)
    700     error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
    701 	   elf_errmsg (-1));
    702   else
    703     {
    704       if (elf_kind (elf) == ELF_K_AR)
    705 	{
    706 	  if (!only_one)
    707 	    printf ("\n%s:\n\n", fname);
    708 	  dump_archive_index (elf, fname);
    709 	}
    710       else
    711 	error (0, 0,
    712 	       gettext ("'%s' is not an archive, cannot print archive index"),
    713 	       fname);
    714 
    715       /* Now we can close the descriptor.  */
    716       if (elf_end (elf) != 0)
    717 	error (0, 0, gettext ("error while closing Elf descriptor: %s"),
    718 	       elf_errmsg (-1));
    719     }
    720 }
    721 
    722 /* Trivial callback used for checking if we opened an archive.  */
    723 static int
    724 count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
    725 	       void **userdata __attribute__ ((unused)),
    726 	       const char *name __attribute__ ((unused)),
    727 	       Dwarf_Addr base __attribute__ ((unused)),
    728 	       void *arg)
    729 {
    730   if (*(bool *) arg)
    731     return DWARF_CB_ABORT;
    732   *(bool *) arg = true;
    733   return DWARF_CB_OK;
    734 }
    735 
    736 struct process_dwflmod_args
    737 {
    738   int fd;
    739   bool only_one;
    740 };
    741 
    742 static int
    743 process_dwflmod (Dwfl_Module *dwflmod,
    744 		 void **userdata __attribute__ ((unused)),
    745 		 const char *name __attribute__ ((unused)),
    746 		 Dwarf_Addr base __attribute__ ((unused)),
    747 		 void *arg)
    748 {
    749   const struct process_dwflmod_args *a = arg;
    750 
    751   /* Print the file name.  */
    752   if (!a->only_one)
    753     {
    754       const char *fname;
    755       dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
    756 
    757       printf ("\n%s:\n\n", fname);
    758     }
    759 
    760   process_elf_file (dwflmod, a->fd);
    761 
    762   return DWARF_CB_OK;
    763 }
    764 
    765 /* Stub libdwfl callback, only the ELF handle already open is ever used.
    766    Only used for finding the alternate debug file if the Dwarf comes from
    767    the main file.  We are not interested in separate debuginfo.  */
    768 static int
    769 find_no_debuginfo (Dwfl_Module *mod,
    770 		   void **userdata,
    771 		   const char *modname,
    772 		   Dwarf_Addr base,
    773 		   const char *file_name,
    774 		   const char *debuglink_file,
    775 		   GElf_Word debuglink_crc,
    776 		   char **debuginfo_file_name)
    777 {
    778   Dwarf_Addr dwbias;
    779   dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
    780 
    781   /* We are only interested if the Dwarf has been setup on the main
    782      elf file but is only missing the alternate debug link.  If dwbias
    783      hasn't even been setup, this is searching for separate debuginfo
    784      for the main elf.  We don't care in that case.  */
    785   if (dwbias == (Dwarf_Addr) -1)
    786     return -1;
    787 
    788   return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
    789 				       file_name, debuglink_file,
    790 				       debuglink_crc, debuginfo_file_name);
    791 }
    792 
    793 static Dwfl *
    794 create_dwfl (int fd, const char *fname)
    795 {
    796   /* Duplicate an fd for dwfl_report_offline to swallow.  */
    797   int dwfl_fd = dup (fd);
    798   if (unlikely (dwfl_fd < 0))
    799     error (EXIT_FAILURE, errno, "dup");
    800 
    801   /* Use libdwfl in a trivial way to open the libdw handle for us.
    802      This takes care of applying relocations to DWARF data in ET_REL files.  */
    803   static const Dwfl_Callbacks callbacks =
    804     {
    805       .section_address = dwfl_offline_section_address,
    806       .find_debuginfo = find_no_debuginfo
    807     };
    808   Dwfl *dwfl = dwfl_begin (&callbacks);
    809   if (likely (dwfl != NULL))
    810     /* Let 0 be the logical address of the file (or first in archive).  */
    811     dwfl->offline_next_address = 0;
    812   if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
    813     {
    814       struct stat st;
    815       if (fstat (dwfl_fd, &st) != 0)
    816 	error (0, errno, gettext ("cannot stat input file"));
    817       else if (unlikely (st.st_size == 0))
    818 	error (0, 0, gettext ("input file is empty"));
    819       else
    820 	error (0, 0, gettext ("failed reading '%s': %s"),
    821 	       fname, dwfl_errmsg (-1));
    822       close (dwfl_fd);		/* Consumed on success, not on failure.  */
    823       dwfl = NULL;
    824     }
    825   else
    826     dwfl_report_end (dwfl, NULL, NULL);
    827 
    828   return dwfl;
    829 }
    830 
    831 /* Process one input file.  */
    832 static void
    833 process_file (int fd, const char *fname, bool only_one)
    834 {
    835   if (print_archive_index)
    836     check_archive_index (fd, fname, only_one);
    837 
    838   if (!any_control_option)
    839     return;
    840 
    841   if (elf_input_section != NULL)
    842     {
    843       /* Replace fname and fd with section content. */
    844       char *fnname = alloca (strlen (fname) + strlen (elf_input_section) + 2);
    845       sprintf (fnname, "%s:%s", fname, elf_input_section);
    846       fd = open_input_section (fd);
    847       if (fd == -1)
    848         {
    849           error (0, 0, gettext ("No such section '%s' in '%s'"),
    850 		 elf_input_section, fname);
    851           return;
    852         }
    853       fname = fnname;
    854     }
    855 
    856   Dwfl *dwfl = create_dwfl (fd, fname);
    857   if (dwfl != NULL)
    858     {
    859       if (only_one)
    860 	{
    861 	  /* Clear ONLY_ONE if we have multiple modules, from an archive.  */
    862 	  bool seen = false;
    863 	  only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
    864 	}
    865 
    866       /* Process the one or more modules gleaned from this file.  */
    867       struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
    868       dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
    869     }
    870   /* Terrible hack for hooking unrelated skeleton/split compile units,
    871      see __libdw_link_skel_split in print_debug.  */
    872   if (! do_not_close_dwfl)
    873     dwfl_end (dwfl);
    874 
    875   /* Need to close the replaced fd if we created it.  Caller takes
    876      care of original.  */
    877   if (elf_input_section != NULL)
    878     close (fd);
    879 }
    880 
    881 /* Check whether there are any compressed sections in the ELF file.  */
    882 static bool
    883 elf_contains_chdrs (Elf *elf)
    884 {
    885   Elf_Scn *scn = NULL;
    886   while ((scn = elf_nextscn (elf, scn)) != NULL)
    887     {
    888       GElf_Shdr shdr_mem;
    889       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    890       if (shdr != NULL && (shdr->sh_flags & SHF_COMPRESSED) != 0)
    891 	return true;
    892     }
    893   return false;
    894 }
    895 
    896 /* Process one ELF file.  */
    897 static void
    898 process_elf_file (Dwfl_Module *dwflmod, int fd)
    899 {
    900   GElf_Addr dwflbias;
    901   Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
    902 
    903   GElf_Ehdr ehdr_mem;
    904   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
    905 
    906   if (ehdr == NULL)
    907     {
    908       error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
    909       return;
    910     }
    911 
    912   Ebl *ebl = ebl_openbackend (elf);
    913   if (unlikely (ebl == NULL))
    914     {
    915     ebl_error:
    916       error (0, errno, gettext ("cannot create EBL handle"));
    917       return;
    918     }
    919 
    920   /* Determine the number of sections.  */
    921   if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
    922     error (EXIT_FAILURE, 0,
    923 	   gettext ("cannot determine number of sections: %s"),
    924 	   elf_errmsg (-1));
    925 
    926   /* Determine the number of phdrs.  */
    927   if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
    928     error (EXIT_FAILURE, 0,
    929 	   gettext ("cannot determine number of program headers: %s"),
    930 	   elf_errmsg (-1));
    931 
    932   /* For an ET_REL file, libdwfl has adjusted the in-core shdrs and
    933      may have applied relocation to some sections.  If there are any
    934      compressed sections, any pass (or libdw/libdwfl) might have
    935      uncompressed them.  So we need to get a fresh Elf handle on the
    936      file to display those.  */
    937   bool print_unchanged = ((print_section_header
    938 			   || print_relocations
    939 			   || dump_data_sections != NULL
    940 			   || print_notes)
    941 			  && (ehdr->e_type == ET_REL
    942 			      || elf_contains_chdrs (ebl->elf)));
    943 
    944   Elf *pure_elf = NULL;
    945   Ebl *pure_ebl = ebl;
    946   if (print_unchanged)
    947     {
    948       /* Read the file afresh.  */
    949       off_t aroff = elf_getaroff (elf);
    950       pure_elf = dwelf_elf_begin (fd);
    951       if (aroff > 0)
    952 	{
    953 	  /* Archive member.  */
    954 	  (void) elf_rand (pure_elf, aroff);
    955 	  Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
    956 	  elf_end (pure_elf);
    957 	  pure_elf = armem;
    958 	}
    959       if (pure_elf == NULL)
    960 	{
    961 	  error (0, 0, gettext ("cannot read ELF: %s"), elf_errmsg (-1));
    962 	  return;
    963 	}
    964       pure_ebl = ebl_openbackend (pure_elf);
    965       if (pure_ebl == NULL)
    966 	goto ebl_error;
    967     }
    968 
    969   if (print_file_header)
    970     print_ehdr (ebl, ehdr);
    971   if (print_section_header)
    972     print_shdr (pure_ebl, ehdr);
    973   if (print_program_header)
    974     print_phdr (ebl, ehdr);
    975   if (print_section_groups)
    976     print_scngrp (ebl);
    977   if (print_dynamic_table)
    978     print_dynamic (ebl);
    979   if (print_relocations)
    980     print_relocs (pure_ebl, ehdr);
    981   if (print_histogram)
    982     handle_hash (ebl);
    983   if (print_symbol_table)
    984     print_symtab (ebl, SHT_DYNSYM);
    985   if (print_version_info)
    986     print_verinfo (ebl);
    987   if (print_symbol_table)
    988     print_symtab (ebl, SHT_SYMTAB);
    989   if (print_arch)
    990     print_liblist (ebl);
    991   if (print_arch)
    992     print_attributes (ebl, ehdr);
    993   if (dump_data_sections != NULL)
    994     dump_data (pure_ebl);
    995   if (string_sections != NULL)
    996     dump_strings (ebl);
    997   if ((print_debug_sections | implicit_debug_sections) != 0)
    998     print_debug (dwflmod, ebl, ehdr);
    999   if (print_notes)
   1000     handle_notes (pure_ebl, ehdr);
   1001   if (print_string_sections)
   1002     print_strings (ebl);
   1003 
   1004   ebl_closebackend (ebl);
   1005 
   1006   if (pure_ebl != ebl)
   1007     {
   1008       ebl_closebackend (pure_ebl);
   1009       elf_end (pure_elf);
   1010     }
   1011 }
   1012 
   1013 
   1014 /* Print file type.  */
   1015 static void
   1016 print_file_type (unsigned short int e_type)
   1017 {
   1018   if (likely (e_type <= ET_CORE))
   1019     {
   1020       static const char *const knowntypes[] =
   1021       {
   1022 	N_("NONE (None)"),
   1023 	N_("REL (Relocatable file)"),
   1024 	N_("EXEC (Executable file)"),
   1025 	N_("DYN (Shared object file)"),
   1026 	N_("CORE (Core file)")
   1027       };
   1028       puts (gettext (knowntypes[e_type]));
   1029     }
   1030   else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
   1031     printf (gettext ("OS Specific: (%x)\n"),  e_type);
   1032   else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
   1033     printf (gettext ("Processor Specific: (%x)\n"),  e_type);
   1034   else
   1035     puts ("???");
   1036 }
   1037 
   1038 
   1039 /* Print ELF header.  */
   1040 static void
   1041 print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
   1042 {
   1043   fputs_unlocked (gettext ("ELF Header:\n  Magic:  "), stdout);
   1044   for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
   1045     printf (" %02hhx", ehdr->e_ident[cnt]);
   1046 
   1047   printf (gettext ("\n  Class:                             %s\n"),
   1048 	  ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
   1049 	  : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
   1050 	  : "\?\?\?");
   1051 
   1052   printf (gettext ("  Data:                              %s\n"),
   1053 	  ehdr->e_ident[EI_DATA] == ELFDATA2LSB
   1054 	  ? "2's complement, little endian"
   1055 	  : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
   1056 	  ? "2's complement, big endian" : "\?\?\?");
   1057 
   1058   printf (gettext ("  Ident Version:                     %hhd %s\n"),
   1059 	  ehdr->e_ident[EI_VERSION],
   1060 	  ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
   1061 	  : "(\?\?\?)");
   1062 
   1063   char buf[512];
   1064   printf (gettext ("  OS/ABI:                            %s\n"),
   1065 	  ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
   1066 
   1067   printf (gettext ("  ABI Version:                       %hhd\n"),
   1068 	  ehdr->e_ident[EI_ABIVERSION]);
   1069 
   1070   fputs_unlocked (gettext ("  Type:                              "), stdout);
   1071   print_file_type (ehdr->e_type);
   1072 
   1073   printf (gettext ("  Machine:                           %s\n"), ebl->name);
   1074 
   1075   printf (gettext ("  Version:                           %d %s\n"),
   1076 	  ehdr->e_version,
   1077 	  ehdr->e_version  == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
   1078 
   1079   printf (gettext ("  Entry point address:               %#" PRIx64 "\n"),
   1080 	  ehdr->e_entry);
   1081 
   1082   printf (gettext ("  Start of program headers:          %" PRId64 " %s\n"),
   1083 	  ehdr->e_phoff, gettext ("(bytes into file)"));
   1084 
   1085   printf (gettext ("  Start of section headers:          %" PRId64 " %s\n"),
   1086 	  ehdr->e_shoff, gettext ("(bytes into file)"));
   1087 
   1088   printf (gettext ("  Flags:                             %s\n"),
   1089 	  ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
   1090 
   1091   printf (gettext ("  Size of this header:               %" PRId16 " %s\n"),
   1092 	  ehdr->e_ehsize, gettext ("(bytes)"));
   1093 
   1094   printf (gettext ("  Size of program header entries:    %" PRId16 " %s\n"),
   1095 	  ehdr->e_phentsize, gettext ("(bytes)"));
   1096 
   1097   printf (gettext ("  Number of program headers entries: %" PRId16),
   1098 	  ehdr->e_phnum);
   1099   if (ehdr->e_phnum == PN_XNUM)
   1100     {
   1101       GElf_Shdr shdr_mem;
   1102       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
   1103       if (shdr != NULL)
   1104 	printf (gettext (" (%" PRIu32 " in [0].sh_info)"),
   1105 		(uint32_t) shdr->sh_info);
   1106       else
   1107 	fputs_unlocked (gettext (" ([0] not available)"), stdout);
   1108     }
   1109   fputc_unlocked ('\n', stdout);
   1110 
   1111   printf (gettext ("  Size of section header entries:    %" PRId16 " %s\n"),
   1112 	  ehdr->e_shentsize, gettext ("(bytes)"));
   1113 
   1114   printf (gettext ("  Number of section headers entries: %" PRId16),
   1115 	  ehdr->e_shnum);
   1116   if (ehdr->e_shnum == 0)
   1117     {
   1118       GElf_Shdr shdr_mem;
   1119       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
   1120       if (shdr != NULL)
   1121 	printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
   1122 		(uint32_t) shdr->sh_size);
   1123       else
   1124 	fputs_unlocked (gettext (" ([0] not available)"), stdout);
   1125     }
   1126   fputc_unlocked ('\n', stdout);
   1127 
   1128   if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
   1129     {
   1130       GElf_Shdr shdr_mem;
   1131       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
   1132       if (shdr != NULL)
   1133 	/* We managed to get the zeroth section.  */
   1134 	snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
   1135 		  (uint32_t) shdr->sh_link);
   1136       else
   1137 	{
   1138 	  strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
   1139 	  buf[sizeof (buf) - 1] = '\0';
   1140 	}
   1141 
   1142       printf (gettext ("  Section header string table index: XINDEX%s\n\n"),
   1143 	      buf);
   1144     }
   1145   else
   1146     printf (gettext ("  Section header string table index: %" PRId16 "\n\n"),
   1147 	    ehdr->e_shstrndx);
   1148 }
   1149 
   1150 
   1151 static const char *
   1152 get_visibility_type (int value)
   1153 {
   1154   switch (value)
   1155     {
   1156     case STV_DEFAULT:
   1157       return "DEFAULT";
   1158     case STV_INTERNAL:
   1159       return "INTERNAL";
   1160     case STV_HIDDEN:
   1161       return "HIDDEN";
   1162     case STV_PROTECTED:
   1163       return "PROTECTED";
   1164     default:
   1165       return "???";
   1166     }
   1167 }
   1168 
   1169 static const char *
   1170 elf_ch_type_name (unsigned int code)
   1171 {
   1172   if (code == 0)
   1173     return "NONE";
   1174 
   1175   if (code == ELFCOMPRESS_ZLIB)
   1176     return "ZLIB";
   1177 
   1178   return "UNKNOWN";
   1179 }
   1180 
   1181 /* Print the section headers.  */
   1182 static void
   1183 print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
   1184 {
   1185   size_t cnt;
   1186   size_t shstrndx;
   1187 
   1188   if (! print_file_header)
   1189     {
   1190       size_t sections;
   1191       if (unlikely (elf_getshdrnum (ebl->elf, &sections) < 0))
   1192 	error (EXIT_FAILURE, 0,
   1193 	       gettext ("cannot get number of sections: %s"),
   1194 	       elf_errmsg (-1));
   1195 
   1196       printf (gettext ("\
   1197 There are %zd section headers, starting at offset %#" PRIx64 ":\n\
   1198 \n"),
   1199 	      sections, ehdr->e_shoff);
   1200     }
   1201 
   1202   /* Get the section header string table index.  */
   1203   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   1204     error (EXIT_FAILURE, 0,
   1205 	   gettext ("cannot get section header string table index: %s"),
   1206 	   elf_errmsg (-1));
   1207 
   1208   puts (gettext ("Section Headers:"));
   1209 
   1210   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
   1211     puts (gettext ("[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al"));
   1212   else
   1213     puts (gettext ("[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al"));
   1214 
   1215   if (print_decompress)
   1216     {
   1217       if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
   1218 	puts (gettext ("     [Compression  Size   Al]"));
   1219       else
   1220 	puts (gettext ("     [Compression  Size     Al]"));
   1221     }
   1222 
   1223   for (cnt = 0; cnt < shnum; ++cnt)
   1224     {
   1225       Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
   1226 
   1227       if (unlikely (scn == NULL))
   1228 	error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
   1229 	       elf_errmsg (-1));
   1230 
   1231       /* Get the section header.  */
   1232       GElf_Shdr shdr_mem;
   1233       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1234       if (unlikely (shdr == NULL))
   1235 	error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
   1236 	       elf_errmsg (-1));
   1237 
   1238       char flagbuf[20];
   1239       char *cp = flagbuf;
   1240       if (shdr->sh_flags & SHF_WRITE)
   1241 	*cp++ = 'W';
   1242       if (shdr->sh_flags & SHF_ALLOC)
   1243 	*cp++ = 'A';
   1244       if (shdr->sh_flags & SHF_EXECINSTR)
   1245 	*cp++ = 'X';
   1246       if (shdr->sh_flags & SHF_MERGE)
   1247 	*cp++ = 'M';
   1248       if (shdr->sh_flags & SHF_STRINGS)
   1249 	*cp++ = 'S';
   1250       if (shdr->sh_flags & SHF_INFO_LINK)
   1251 	*cp++ = 'I';
   1252       if (shdr->sh_flags & SHF_LINK_ORDER)
   1253 	*cp++ = 'L';
   1254       if (shdr->sh_flags & SHF_OS_NONCONFORMING)
   1255 	*cp++ = 'N';
   1256       if (shdr->sh_flags & SHF_GROUP)
   1257 	*cp++ = 'G';
   1258       if (shdr->sh_flags & SHF_TLS)
   1259 	*cp++ = 'T';
   1260       if (shdr->sh_flags & SHF_COMPRESSED)
   1261 	*cp++ = 'C';
   1262       if (shdr->sh_flags & SHF_ORDERED)
   1263 	*cp++ = 'O';
   1264       if (shdr->sh_flags & SHF_EXCLUDE)
   1265 	*cp++ = 'E';
   1266       *cp = '\0';
   1267 
   1268       const char *sname;
   1269       char buf[128];
   1270       sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "<corrupt>";
   1271       printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
   1272 	      " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
   1273 	      " %2" PRId64 "\n",
   1274 	      cnt, sname,
   1275 	      ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
   1276 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
   1277 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
   1278 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
   1279 	      shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
   1280 	      shdr->sh_addralign);
   1281 
   1282       if (print_decompress)
   1283 	{
   1284 	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
   1285 	    {
   1286 	      GElf_Chdr chdr;
   1287 	      if (gelf_getchdr (scn, &chdr) != NULL)
   1288 		printf ("     [ELF %s (%" PRId32 ") %0*" PRIx64
   1289 			" %2" PRId64 "]\n",
   1290 			elf_ch_type_name (chdr.ch_type),
   1291 			chdr.ch_type,
   1292 			ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8,
   1293 			chdr.ch_size, chdr.ch_addralign);
   1294 	      else
   1295 		error (0, 0,
   1296 		       gettext ("bad compression header for section %zd: %s"),
   1297 		       elf_ndxscn (scn), elf_errmsg (-1));
   1298 	    }
   1299 	  else if (strncmp(".zdebug", sname, strlen (".zdebug")) == 0)
   1300 	    {
   1301 	      ssize_t size;
   1302 	      if ((size = dwelf_scn_gnu_compressed_size (scn)) >= 0)
   1303 		printf ("     [GNU ZLIB     %0*zx   ]\n",
   1304 			ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, size);
   1305 	      else
   1306 		error (0, 0,
   1307 		       gettext ("bad gnu compressed size for section %zd: %s"),
   1308 		       elf_ndxscn (scn), elf_errmsg (-1));
   1309 	    }
   1310 	}
   1311     }
   1312 
   1313   fputc_unlocked ('\n', stdout);
   1314 }
   1315 
   1316 
   1317 /* Print the program header.  */
   1318 static void
   1319 print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
   1320 {
   1321   if (phnum == 0)
   1322     /* No program header, this is OK in relocatable objects.  */
   1323     return;
   1324 
   1325   puts (gettext ("Program Headers:"));
   1326   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
   1327     puts (gettext ("\
   1328   Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"));
   1329   else
   1330     puts (gettext ("\
   1331   Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align"));
   1332 
   1333   /* Process all program headers.  */
   1334   bool has_relro = false;
   1335   GElf_Addr relro_from = 0;
   1336   GElf_Addr relro_to = 0;
   1337   for (size_t cnt = 0; cnt < phnum; ++cnt)
   1338     {
   1339       char buf[128];
   1340       GElf_Phdr mem;
   1341       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
   1342 
   1343       /* If for some reason the header cannot be returned show this.  */
   1344       if (unlikely (phdr == NULL))
   1345 	{
   1346 	  puts ("  ???");
   1347 	  continue;
   1348 	}
   1349 
   1350       printf ("  %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
   1351 	      " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
   1352 	      ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
   1353 	      phdr->p_offset,
   1354 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
   1355 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
   1356 	      phdr->p_filesz,
   1357 	      phdr->p_memsz,
   1358 	      phdr->p_flags & PF_R ? 'R' : ' ',
   1359 	      phdr->p_flags & PF_W ? 'W' : ' ',
   1360 	      phdr->p_flags & PF_X ? 'E' : ' ',
   1361 	      phdr->p_align);
   1362 
   1363       if (phdr->p_type == PT_INTERP)
   1364 	{
   1365 	  /* If we are sure the file offset is valid then we can show
   1366 	     the user the name of the interpreter.  We check whether
   1367 	     there is a section at the file offset.  Normally there
   1368 	     would be a section called ".interp".  But in separate
   1369 	     .debug files it is a NOBITS section (and so doesn't match
   1370 	     with gelf_offscn).  Which probably means the offset is
   1371 	     not valid another reason could be because the ELF file
   1372 	     just doesn't contain any section headers, in that case
   1373 	     just play it safe and don't display anything.  */
   1374 
   1375 	  Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
   1376 	  GElf_Shdr shdr_mem;
   1377 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1378 
   1379 	  size_t maxsize;
   1380 	  char *filedata = elf_rawfile (ebl->elf, &maxsize);
   1381 
   1382 	  if (shdr != NULL && shdr->sh_type == SHT_PROGBITS
   1383 	      && filedata != NULL && phdr->p_offset < maxsize
   1384 	      && phdr->p_filesz <= maxsize - phdr->p_offset
   1385 	      && memchr (filedata + phdr->p_offset, '\0',
   1386 			 phdr->p_filesz) != NULL)
   1387 	    printf (gettext ("\t[Requesting program interpreter: %s]\n"),
   1388 		    filedata + phdr->p_offset);
   1389 	}
   1390       else if (phdr->p_type == PT_GNU_RELRO)
   1391 	{
   1392 	  has_relro = true;
   1393 	  relro_from = phdr->p_vaddr;
   1394 	  relro_to = relro_from + phdr->p_memsz;
   1395 	}
   1396     }
   1397 
   1398   size_t sections;
   1399   if (unlikely (elf_getshdrnum (ebl->elf, &sections) < 0))
   1400     error (EXIT_FAILURE, 0,
   1401            gettext ("cannot get number of sections: %s"),
   1402            elf_errmsg (-1));
   1403 
   1404   if (sections == 0)
   1405     /* No sections in the file.  Punt.  */
   1406     return;
   1407 
   1408   /* Get the section header string table index.  */
   1409   size_t shstrndx;
   1410   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   1411     error (EXIT_FAILURE, 0,
   1412 	   gettext ("cannot get section header string table index"));
   1413 
   1414   puts (gettext ("\n Section to Segment mapping:\n  Segment Sections..."));
   1415 
   1416   for (size_t cnt = 0; cnt < phnum; ++cnt)
   1417     {
   1418       /* Print the segment number.  */
   1419       printf ("   %2.2zu     ", cnt);
   1420 
   1421       GElf_Phdr phdr_mem;
   1422       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
   1423       /* This must not happen.  */
   1424       if (unlikely (phdr == NULL))
   1425 	error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
   1426 	       elf_errmsg (-1));
   1427 
   1428       /* Iterate over the sections.  */
   1429       bool in_relro = false;
   1430       bool in_ro = false;
   1431       for (size_t inner = 1; inner < shnum; ++inner)
   1432 	{
   1433 	  Elf_Scn *scn = elf_getscn (ebl->elf, inner);
   1434 	  /* This should not happen.  */
   1435 	  if (unlikely (scn == NULL))
   1436 	    error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
   1437 		   elf_errmsg (-1));
   1438 
   1439 	  /* Get the section header.  */
   1440 	  GElf_Shdr shdr_mem;
   1441 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1442 	  if (unlikely (shdr == NULL))
   1443 	    error (EXIT_FAILURE, 0,
   1444 		   gettext ("cannot get section header: %s"),
   1445 		   elf_errmsg (-1));
   1446 
   1447 	  if (shdr->sh_size > 0
   1448 	      /* Compare allocated sections by VMA, unallocated
   1449 		 sections by file offset.  */
   1450 	      && (shdr->sh_flags & SHF_ALLOC
   1451 		  ? (shdr->sh_addr >= phdr->p_vaddr
   1452 		     && (shdr->sh_addr + shdr->sh_size
   1453 			 <= phdr->p_vaddr + phdr->p_memsz))
   1454 		  : (shdr->sh_offset >= phdr->p_offset
   1455 		     && (shdr->sh_offset + shdr->sh_size
   1456 			 <= phdr->p_offset + phdr->p_filesz))))
   1457 	    {
   1458 	      if (has_relro && !in_relro
   1459 		  && shdr->sh_addr >= relro_from
   1460 		  && shdr->sh_addr + shdr->sh_size <= relro_to)
   1461 		{
   1462 		  fputs_unlocked (" [RELRO:", stdout);
   1463 		  in_relro = true;
   1464 		}
   1465 	      else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
   1466 		{
   1467 		  fputs_unlocked ("]", stdout);
   1468 		  in_relro =  false;
   1469 		}
   1470 	      else if (has_relro && in_relro
   1471 		       && shdr->sh_addr + shdr->sh_size > relro_to)
   1472 		fputs_unlocked ("] <RELRO:", stdout);
   1473 	      else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
   1474 		{
   1475 		  if (!in_ro)
   1476 		    {
   1477 		      fputs_unlocked (" [RO:", stdout);
   1478 		      in_ro = true;
   1479 		    }
   1480 		}
   1481 	      else
   1482 		{
   1483 		  /* Determine the segment this section is part of.  */
   1484 		  size_t cnt2;
   1485 		  GElf_Phdr phdr2_mem;
   1486 		  GElf_Phdr *phdr2 = NULL;
   1487 		  for (cnt2 = 0; cnt2 < phnum; ++cnt2)
   1488 		    {
   1489 		      phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
   1490 
   1491 		      if (phdr2 != NULL && phdr2->p_type == PT_LOAD
   1492 			  && shdr->sh_addr >= phdr2->p_vaddr
   1493 			  && (shdr->sh_addr + shdr->sh_size
   1494 			      <= phdr2->p_vaddr + phdr2->p_memsz))
   1495 			break;
   1496 		    }
   1497 
   1498 		  if (cnt2 < phnum)
   1499 		    {
   1500 		      if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
   1501 			{
   1502 			  fputs_unlocked (" [RO:", stdout);
   1503 			  in_ro = true;
   1504 			}
   1505 		      else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
   1506 			{
   1507 			  fputs_unlocked ("]", stdout);
   1508 			  in_ro = false;
   1509 			}
   1510 		    }
   1511 		}
   1512 
   1513 	      printf (" %s",
   1514 		      elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
   1515 
   1516 	      /* Signal that this sectin is only partially covered.  */
   1517 	      if (has_relro && in_relro
   1518 		       && shdr->sh_addr + shdr->sh_size > relro_to)
   1519 		{
   1520 		  fputs_unlocked (">", stdout);
   1521 		  in_relro =  false;
   1522 		}
   1523 	    }
   1524 	}
   1525       if (in_relro || in_ro)
   1526 	fputs_unlocked ("]", stdout);
   1527 
   1528       /* Finish the line.  */
   1529       fputc_unlocked ('\n', stdout);
   1530     }
   1531 }
   1532 
   1533 
   1534 static const char *
   1535 section_name (Ebl *ebl, GElf_Shdr *shdr)
   1536 {
   1537   size_t shstrndx;
   1538   if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
   1539     return "???";
   1540   return elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "???";
   1541 }
   1542 
   1543 
   1544 static void
   1545 handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   1546 {
   1547   /* Get the data of the section.  */
   1548   Elf_Data *data = elf_getdata (scn, NULL);
   1549 
   1550   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
   1551   GElf_Shdr symshdr_mem;
   1552   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
   1553   Elf_Data *symdata = elf_getdata (symscn, NULL);
   1554 
   1555   if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
   1556       || symdata == NULL)
   1557     return;
   1558 
   1559   /* Get the section header string table index.  */
   1560   size_t shstrndx;
   1561   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   1562     error (EXIT_FAILURE, 0,
   1563 	   gettext ("cannot get section header string table index"));
   1564 
   1565   Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
   1566 
   1567   GElf_Sym sym_mem;
   1568   GElf_Sym *sym = gelf_getsym (symdata, shdr->sh_info, &sym_mem);
   1569 
   1570   printf ((grpref[0] & GRP_COMDAT)
   1571 	  ? ngettext ("\
   1572 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
   1573 		      "\
   1574 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
   1575 		      data->d_size / sizeof (Elf32_Word) - 1)
   1576 	  : ngettext ("\
   1577 \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
   1578 \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
   1579 		      data->d_size / sizeof (Elf32_Word) - 1),
   1580 	  elf_ndxscn (scn),
   1581 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   1582 	  (sym == NULL ? NULL
   1583 	   : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
   1584 	  ?: gettext ("<INVALID SYMBOL>"),
   1585 	  data->d_size / sizeof (Elf32_Word) - 1);
   1586 
   1587   for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
   1588     {
   1589       GElf_Shdr grpshdr_mem;
   1590       GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
   1591 					 &grpshdr_mem);
   1592 
   1593       const char *str;
   1594       printf ("  [%2u] %s\n",
   1595 	      grpref[cnt],
   1596 	      grpshdr != NULL
   1597 	      && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
   1598 	      ? str : gettext ("<INVALID SECTION>"));
   1599     }
   1600 }
   1601 
   1602 
   1603 static void
   1604 print_scngrp (Ebl *ebl)
   1605 {
   1606   /* Find all relocation sections and handle them.  */
   1607   Elf_Scn *scn = NULL;
   1608 
   1609   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   1610     {
   1611        /* Handle the section if it is a symbol table.  */
   1612       GElf_Shdr shdr_mem;
   1613       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1614 
   1615       if (shdr != NULL && shdr->sh_type == SHT_GROUP)
   1616 	{
   1617 	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
   1618 	    {
   1619 	      if (elf_compress (scn, 0, 0) < 0)
   1620 		printf ("WARNING: %s [%zd]\n",
   1621 			gettext ("Couldn't uncompress section"),
   1622 			elf_ndxscn (scn));
   1623 	      shdr = gelf_getshdr (scn, &shdr_mem);
   1624 	      if (unlikely (shdr == NULL))
   1625 		error (EXIT_FAILURE, 0,
   1626 		       gettext ("cannot get section [%zd] header: %s"),
   1627 		       elf_ndxscn (scn),
   1628 		       elf_errmsg (-1));
   1629 	    }
   1630 	  handle_scngrp (ebl, scn, shdr);
   1631 	}
   1632     }
   1633 }
   1634 
   1635 
   1636 static const struct flags
   1637 {
   1638   int mask;
   1639   const char *str;
   1640 } dt_flags[] =
   1641   {
   1642     { DF_ORIGIN, "ORIGIN" },
   1643     { DF_SYMBOLIC, "SYMBOLIC" },
   1644     { DF_TEXTREL, "TEXTREL" },
   1645     { DF_BIND_NOW, "BIND_NOW" },
   1646     { DF_STATIC_TLS, "STATIC_TLS" }
   1647   };
   1648 static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
   1649 
   1650 static const struct flags dt_flags_1[] =
   1651   {
   1652     { DF_1_NOW, "NOW" },
   1653     { DF_1_GLOBAL, "GLOBAL" },
   1654     { DF_1_GROUP, "GROUP" },
   1655     { DF_1_NODELETE, "NODELETE" },
   1656     { DF_1_LOADFLTR, "LOADFLTR" },
   1657     { DF_1_INITFIRST, "INITFIRST" },
   1658     { DF_1_NOOPEN, "NOOPEN" },
   1659     { DF_1_ORIGIN, "ORIGIN" },
   1660     { DF_1_DIRECT, "DIRECT" },
   1661     { DF_1_TRANS, "TRANS" },
   1662     { DF_1_INTERPOSE, "INTERPOSE" },
   1663     { DF_1_NODEFLIB, "NODEFLIB" },
   1664     { DF_1_NODUMP, "NODUMP" },
   1665     { DF_1_CONFALT, "CONFALT" },
   1666     { DF_1_ENDFILTEE, "ENDFILTEE" },
   1667     { DF_1_DISPRELDNE, "DISPRELDNE" },
   1668     { DF_1_DISPRELPND, "DISPRELPND" },
   1669   };
   1670 static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
   1671 
   1672 static const struct flags dt_feature_1[] =
   1673   {
   1674     { DTF_1_PARINIT, "PARINIT" },
   1675     { DTF_1_CONFEXP, "CONFEXP" }
   1676   };
   1677 static const int ndt_feature_1 = (sizeof (dt_feature_1)
   1678 				  / sizeof (dt_feature_1[0]));
   1679 
   1680 static const struct flags dt_posflag_1[] =
   1681   {
   1682     { DF_P1_LAZYLOAD, "LAZYLOAD" },
   1683     { DF_P1_GROUPPERM, "GROUPPERM" }
   1684   };
   1685 static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
   1686 				  / sizeof (dt_posflag_1[0]));
   1687 
   1688 
   1689 static void
   1690 print_flags (int class, GElf_Xword d_val, const struct flags *flags,
   1691 		int nflags)
   1692 {
   1693   bool first = true;
   1694   int cnt;
   1695 
   1696   for (cnt = 0; cnt < nflags; ++cnt)
   1697     if (d_val & flags[cnt].mask)
   1698       {
   1699 	if (!first)
   1700 	  putchar_unlocked (' ');
   1701 	fputs_unlocked (flags[cnt].str, stdout);
   1702 	d_val &= ~flags[cnt].mask;
   1703 	first = false;
   1704       }
   1705 
   1706   if (d_val != 0)
   1707     {
   1708       if (!first)
   1709 	putchar_unlocked (' ');
   1710       printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
   1711     }
   1712 
   1713   putchar_unlocked ('\n');
   1714 }
   1715 
   1716 
   1717 static void
   1718 print_dt_flags (int class, GElf_Xword d_val)
   1719 {
   1720   print_flags (class, d_val, dt_flags, ndt_flags);
   1721 }
   1722 
   1723 
   1724 static void
   1725 print_dt_flags_1 (int class, GElf_Xword d_val)
   1726 {
   1727   print_flags (class, d_val, dt_flags_1, ndt_flags_1);
   1728 }
   1729 
   1730 
   1731 static void
   1732 print_dt_feature_1 (int class, GElf_Xword d_val)
   1733 {
   1734   print_flags (class, d_val, dt_feature_1, ndt_feature_1);
   1735 }
   1736 
   1737 
   1738 static void
   1739 print_dt_posflag_1 (int class, GElf_Xword d_val)
   1740 {
   1741   print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
   1742 }
   1743 
   1744 
   1745 static void
   1746 handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   1747 {
   1748   int class = gelf_getclass (ebl->elf);
   1749   GElf_Shdr glink_mem;
   1750   GElf_Shdr *glink;
   1751   Elf_Data *data;
   1752   size_t cnt;
   1753   size_t shstrndx;
   1754   size_t sh_entsize;
   1755 
   1756   /* Get the data of the section.  */
   1757   data = elf_getdata (scn, NULL);
   1758   if (data == NULL)
   1759     return;
   1760 
   1761   /* Get the section header string table index.  */
   1762   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   1763     error (EXIT_FAILURE, 0,
   1764 	   gettext ("cannot get section header string table index"));
   1765 
   1766   sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT);
   1767 
   1768   glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
   1769   if (glink == NULL)
   1770     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
   1771 	   elf_ndxscn (scn));
   1772 
   1773   printf (ngettext ("\
   1774 \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   1775 		    "\
   1776 \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   1777 		    shdr->sh_size / sh_entsize),
   1778 	  (unsigned long int) (shdr->sh_size / sh_entsize),
   1779 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   1780 	  shdr->sh_offset,
   1781 	  (int) shdr->sh_link,
   1782 	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
   1783   fputs_unlocked (gettext ("  Type              Value\n"), stdout);
   1784 
   1785   for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
   1786     {
   1787       GElf_Dyn dynmem;
   1788       GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
   1789       if (dyn == NULL)
   1790 	break;
   1791 
   1792       char buf[64];
   1793       printf ("  %-17s ",
   1794 	      ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
   1795 
   1796       switch (dyn->d_tag)
   1797 	{
   1798 	case DT_NULL:
   1799 	case DT_DEBUG:
   1800 	case DT_BIND_NOW:
   1801 	case DT_TEXTREL:
   1802 	  /* No further output.  */
   1803 	  fputc_unlocked ('\n', stdout);
   1804 	  break;
   1805 
   1806 	case DT_NEEDED:
   1807 	  printf (gettext ("Shared library: [%s]\n"),
   1808 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1809 	  break;
   1810 
   1811 	case DT_SONAME:
   1812 	  printf (gettext ("Library soname: [%s]\n"),
   1813 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1814 	  break;
   1815 
   1816 	case DT_RPATH:
   1817 	  printf (gettext ("Library rpath: [%s]\n"),
   1818 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1819 	  break;
   1820 
   1821 	case DT_RUNPATH:
   1822 	  printf (gettext ("Library runpath: [%s]\n"),
   1823 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1824 	  break;
   1825 
   1826 	case DT_PLTRELSZ:
   1827 	case DT_RELASZ:
   1828 	case DT_STRSZ:
   1829 	case DT_RELSZ:
   1830 	case DT_RELAENT:
   1831 	case DT_SYMENT:
   1832 	case DT_RELENT:
   1833 	case DT_PLTPADSZ:
   1834 	case DT_MOVEENT:
   1835 	case DT_MOVESZ:
   1836 	case DT_INIT_ARRAYSZ:
   1837 	case DT_FINI_ARRAYSZ:
   1838 	case DT_SYMINSZ:
   1839 	case DT_SYMINENT:
   1840 	case DT_GNU_CONFLICTSZ:
   1841 	case DT_GNU_LIBLISTSZ:
   1842 	  printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
   1843 	  break;
   1844 
   1845 	case DT_VERDEFNUM:
   1846 	case DT_VERNEEDNUM:
   1847 	case DT_RELACOUNT:
   1848 	case DT_RELCOUNT:
   1849 	  printf ("%" PRId64 "\n", dyn->d_un.d_val);
   1850 	  break;
   1851 
   1852 	case DT_PLTREL:;
   1853 	  const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
   1854 						      NULL, 0);
   1855 	  puts (tagname ?: "???");
   1856 	  break;
   1857 
   1858 	case DT_FLAGS:
   1859 	  print_dt_flags (class, dyn->d_un.d_val);
   1860 	  break;
   1861 
   1862 	case DT_FLAGS_1:
   1863 	  print_dt_flags_1 (class, dyn->d_un.d_val);
   1864 	  break;
   1865 
   1866 	case DT_FEATURE_1:
   1867 	  print_dt_feature_1 (class, dyn->d_un.d_val);
   1868 	  break;
   1869 
   1870 	case DT_POSFLAG_1:
   1871 	  print_dt_posflag_1 (class, dyn->d_un.d_val);
   1872 	  break;
   1873 
   1874 	default:
   1875 	  printf ("%#0*" PRIx64 "\n",
   1876 		  class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
   1877 	  break;
   1878 	}
   1879     }
   1880 }
   1881 
   1882 
   1883 /* Print the dynamic segment.  */
   1884 static void
   1885 print_dynamic (Ebl *ebl)
   1886 {
   1887   for (size_t i = 0; i < phnum; ++i)
   1888     {
   1889       GElf_Phdr phdr_mem;
   1890       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
   1891 
   1892       if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
   1893 	{
   1894 	  Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
   1895 	  GElf_Shdr shdr_mem;
   1896 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1897 	  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
   1898 	    handle_dynamic (ebl, scn, shdr);
   1899 	  break;
   1900 	}
   1901     }
   1902 }
   1903 
   1904 
   1905 /* Print relocations.  */
   1906 static void
   1907 print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
   1908 {
   1909   /* Find all relocation sections and handle them.  */
   1910   Elf_Scn *scn = NULL;
   1911 
   1912   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   1913     {
   1914        /* Handle the section if it is a symbol table.  */
   1915       GElf_Shdr shdr_mem;
   1916       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1917 
   1918       if (likely (shdr != NULL))
   1919 	{
   1920 	  if (shdr->sh_type == SHT_REL)
   1921 	    handle_relocs_rel (ebl, ehdr, scn, shdr);
   1922 	  else if (shdr->sh_type == SHT_RELA)
   1923 	    handle_relocs_rela (ebl, ehdr, scn, shdr);
   1924 	}
   1925     }
   1926 }
   1927 
   1928 
   1929 /* Handle a relocation section.  */
   1930 static void
   1931 handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   1932 {
   1933   int class = gelf_getclass (ebl->elf);
   1934   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
   1935   int nentries = shdr->sh_size / sh_entsize;
   1936 
   1937   /* Get the data of the section.  */
   1938   Elf_Data *data = elf_getdata (scn, NULL);
   1939   if (data == NULL)
   1940     return;
   1941 
   1942   /* Get the symbol table information.  */
   1943   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
   1944   GElf_Shdr symshdr_mem;
   1945   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
   1946   Elf_Data *symdata = elf_getdata (symscn, NULL);
   1947 
   1948   /* Get the section header of the section the relocations are for.  */
   1949   GElf_Shdr destshdr_mem;
   1950   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
   1951 				      &destshdr_mem);
   1952 
   1953   if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
   1954     {
   1955       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
   1956 	      shdr->sh_offset);
   1957       return;
   1958     }
   1959 
   1960   /* Search for the optional extended section index table.  */
   1961   Elf_Data *xndxdata = NULL;
   1962   int xndxscnidx = elf_scnshndx (scn);
   1963   if (unlikely (xndxscnidx > 0))
   1964     xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
   1965 
   1966   /* Get the section header string table index.  */
   1967   size_t shstrndx;
   1968   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   1969     error (EXIT_FAILURE, 0,
   1970 	   gettext ("cannot get section header string table index"));
   1971 
   1972   if (shdr->sh_info != 0)
   1973     printf (ngettext ("\
   1974 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   1975 		    "\
   1976 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   1977 		      nentries),
   1978 	    elf_ndxscn (scn),
   1979 	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   1980 	    (unsigned int) shdr->sh_info,
   1981 	    elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
   1982 	    shdr->sh_offset,
   1983 	    nentries);
   1984   else
   1985     /* The .rel.dyn section does not refer to a specific section but
   1986        instead of section index zero.  Do not try to print a section
   1987        name.  */
   1988     printf (ngettext ("\
   1989 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   1990 		    "\
   1991 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   1992 		      nentries),
   1993 	    (unsigned int) elf_ndxscn (scn),
   1994 	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   1995 	    shdr->sh_offset,
   1996 	    nentries);
   1997   fputs_unlocked (class == ELFCLASS32
   1998 		  ? gettext ("\
   1999   Offset      Type                 Value       Name\n")
   2000 		  : gettext ("\
   2001   Offset              Type                 Value               Name\n"),
   2002 	 stdout);
   2003 
   2004   int is_statically_linked = 0;
   2005   for (int cnt = 0; cnt < nentries; ++cnt)
   2006     {
   2007       GElf_Rel relmem;
   2008       GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
   2009       if (likely (rel != NULL))
   2010 	{
   2011 	  char buf[128];
   2012 	  GElf_Sym symmem;
   2013 	  Elf32_Word xndx;
   2014 	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
   2015 					    GELF_R_SYM (rel->r_info),
   2016 					    &symmem, &xndx);
   2017 	  if (unlikely (sym == NULL))
   2018 	    {
   2019 	      /* As a special case we have to handle relocations in static
   2020 		 executables.  This only happens for IRELATIVE relocations
   2021 		 (so far).  There is no symbol table.  */
   2022 	      if (is_statically_linked == 0)
   2023 		{
   2024 		  /* Find the program header and look for a PT_INTERP entry. */
   2025 		  is_statically_linked = -1;
   2026 		  if (ehdr->e_type == ET_EXEC)
   2027 		    {
   2028 		      is_statically_linked = 1;
   2029 
   2030 		      for (size_t inner = 0; inner < phnum; ++inner)
   2031 			{
   2032 			  GElf_Phdr phdr_mem;
   2033 			  GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
   2034 							  &phdr_mem);
   2035 			  if (phdr != NULL && phdr->p_type == PT_INTERP)
   2036 			    {
   2037 			      is_statically_linked = -1;
   2038 			      break;
   2039 			    }
   2040 			}
   2041 		    }
   2042 		}
   2043 
   2044 	      if (is_statically_linked > 0 && shdr->sh_link == 0)
   2045 		printf ("\
   2046   %#0*" PRIx64 "  %-20s %*s  %s\n",
   2047 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   2048 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   2049 			/* Avoid the leading R_ which isn't carrying any
   2050 			   information.  */
   2051 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   2052 					       buf, sizeof (buf)) + 2
   2053 			: gettext ("<INVALID RELOC>"),
   2054 			class == ELFCLASS32 ? 10 : 18, "",
   2055 			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
   2056 	      else
   2057 		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
   2058 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   2059 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   2060 			/* Avoid the leading R_ which isn't carrying any
   2061 			   information.  */
   2062 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   2063 					       buf, sizeof (buf)) + 2
   2064 			: gettext ("<INVALID RELOC>"),
   2065 			gettext ("INVALID SYMBOL"),
   2066 			(long int) GELF_R_SYM (rel->r_info));
   2067 	    }
   2068 	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
   2069 	    printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
   2070 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   2071 		    likely (ebl_reloc_type_check (ebl,
   2072 						  GELF_R_TYPE (rel->r_info)))
   2073 		    /* Avoid the leading R_ which isn't carrying any
   2074 		       information.  */
   2075 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   2076 					   buf, sizeof (buf)) + 2
   2077 		    : gettext ("<INVALID RELOC>"),
   2078 		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
   2079 		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
   2080 	  else
   2081 	    {
   2082 	      /* This is a relocation against a STT_SECTION symbol.  */
   2083 	      GElf_Shdr secshdr_mem;
   2084 	      GElf_Shdr *secshdr;
   2085 	      secshdr = gelf_getshdr (elf_getscn (ebl->elf,
   2086 						  sym->st_shndx == SHN_XINDEX
   2087 						  ? xndx : sym->st_shndx),
   2088 				      &secshdr_mem);
   2089 
   2090 	      if (unlikely (secshdr == NULL))
   2091 		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
   2092 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   2093 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   2094 			/* Avoid the leading R_ which isn't carrying any
   2095 			   information.  */
   2096 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   2097 					       buf, sizeof (buf)) + 2
   2098 			: gettext ("<INVALID RELOC>"),
   2099 			gettext ("INVALID SECTION"),
   2100 			(long int) (sym->st_shndx == SHN_XINDEX
   2101 				    ? xndx : sym->st_shndx));
   2102 	      else
   2103 		printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
   2104 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   2105 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   2106 			/* Avoid the leading R_ which isn't carrying any
   2107 			   information.  */
   2108 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   2109 					       buf, sizeof (buf)) + 2
   2110 			: gettext ("<INVALID RELOC>"),
   2111 			class == ELFCLASS32 ? 10 : 18, sym->st_value,
   2112 			elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
   2113 	    }
   2114 	}
   2115     }
   2116 }
   2117 
   2118 
   2119 /* Handle a relocation section.  */
   2120 static void
   2121 handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   2122 {
   2123   int class = gelf_getclass (ebl->elf);
   2124   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
   2125   int nentries = shdr->sh_size / sh_entsize;
   2126 
   2127   /* Get the data of the section.  */
   2128   Elf_Data *data = elf_getdata (scn, NULL);
   2129   if (data == NULL)
   2130     return;
   2131 
   2132   /* Get the symbol table information.  */
   2133   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
   2134   GElf_Shdr symshdr_mem;
   2135   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
   2136   Elf_Data *symdata = elf_getdata (symscn, NULL);
   2137 
   2138   /* Get the section header of the section the relocations are for.  */
   2139   GElf_Shdr destshdr_mem;
   2140   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
   2141 				      &destshdr_mem);
   2142 
   2143   if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
   2144     {
   2145       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
   2146 	      shdr->sh_offset);
   2147       return;
   2148     }
   2149 
   2150   /* Search for the optional extended section index table.  */
   2151   Elf_Data *xndxdata = NULL;
   2152   int xndxscnidx = elf_scnshndx (scn);
   2153   if (unlikely (xndxscnidx > 0))
   2154     xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
   2155 
   2156   /* Get the section header string table index.  */
   2157   size_t shstrndx;
   2158   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   2159     error (EXIT_FAILURE, 0,
   2160 	   gettext ("cannot get section header string table index"));
   2161 
   2162   if (shdr->sh_info != 0)
   2163     printf (ngettext ("\
   2164 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   2165 		    "\
   2166 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   2167 		    nentries),
   2168 	  elf_ndxscn (scn),
   2169 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2170 	  (unsigned int) shdr->sh_info,
   2171 	  elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
   2172 	  shdr->sh_offset,
   2173 	  nentries);
   2174   else
   2175     /* The .rela.dyn section does not refer to a specific section but
   2176        instead of section index zero.  Do not try to print a section
   2177        name.  */
   2178     printf (ngettext ("\
   2179 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   2180 		    "\
   2181 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   2182 		      nentries),
   2183 	    (unsigned int) elf_ndxscn (scn),
   2184 	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2185 	    shdr->sh_offset,
   2186 	    nentries);
   2187   fputs_unlocked (class == ELFCLASS32
   2188 		  ? gettext ("\
   2189   Offset      Type            Value       Addend Name\n")
   2190 		  : gettext ("\
   2191   Offset              Type            Value               Addend Name\n"),
   2192 		  stdout);
   2193 
   2194   int is_statically_linked = 0;
   2195   for (int cnt = 0; cnt < nentries; ++cnt)
   2196     {
   2197       GElf_Rela relmem;
   2198       GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
   2199       if (likely (rel != NULL))
   2200 	{
   2201 	  char buf[64];
   2202 	  GElf_Sym symmem;
   2203 	  Elf32_Word xndx;
   2204 	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
   2205 					    GELF_R_SYM (rel->r_info),
   2206 					    &symmem, &xndx);
   2207 
   2208 	  if (unlikely (sym == NULL))
   2209 	    {
   2210 	      /* As a special case we have to handle relocations in static
   2211 		 executables.  This only happens for IRELATIVE relocations
   2212 		 (so far).  There is no symbol table.  */
   2213 	      if (is_statically_linked == 0)
   2214 		{
   2215 		  /* Find the program header and look for a PT_INTERP entry. */
   2216 		  is_statically_linked = -1;
   2217 		  if (ehdr->e_type == ET_EXEC)
   2218 		    {
   2219 		      is_statically_linked = 1;
   2220 
   2221 		      for (size_t inner = 0; inner < phnum; ++inner)
   2222 			{
   2223 			  GElf_Phdr phdr_mem;
   2224 			  GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
   2225 							  &phdr_mem);
   2226 			  if (phdr != NULL && phdr->p_type == PT_INTERP)
   2227 			    {
   2228 			      is_statically_linked = -1;
   2229 			      break;
   2230 			    }
   2231 			}
   2232 		    }
   2233 		}
   2234 
   2235 	      if (is_statically_linked > 0 && shdr->sh_link == 0)
   2236 		printf ("\
   2237   %#0*" PRIx64 "  %-15s %*s  %#6" PRIx64 " %s\n",
   2238 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   2239 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   2240 			/* Avoid the leading R_ which isn't carrying any
   2241 			   information.  */
   2242 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   2243 					       buf, sizeof (buf)) + 2
   2244 			: gettext ("<INVALID RELOC>"),
   2245 			class == ELFCLASS32 ? 10 : 18, "",
   2246 			rel->r_addend,
   2247 			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
   2248 	      else
   2249 		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
   2250 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   2251 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   2252 			/* Avoid the leading R_ which isn't carrying any
   2253 			   information.  */
   2254 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   2255 					       buf, sizeof (buf)) + 2
   2256 			: gettext ("<INVALID RELOC>"),
   2257 			gettext ("INVALID SYMBOL"),
   2258 			(long int) GELF_R_SYM (rel->r_info));
   2259 	    }
   2260 	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
   2261 	    printf ("\
   2262   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
   2263 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   2264 		    likely (ebl_reloc_type_check (ebl,
   2265 						  GELF_R_TYPE (rel->r_info)))
   2266 		    /* Avoid the leading R_ which isn't carrying any
   2267 		       information.  */
   2268 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   2269 					   buf, sizeof (buf)) + 2
   2270 		    : gettext ("<INVALID RELOC>"),
   2271 		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
   2272 		    rel->r_addend,
   2273 		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
   2274 	  else
   2275 	    {
   2276 	      /* This is a relocation against a STT_SECTION symbol.  */
   2277 	      GElf_Shdr secshdr_mem;
   2278 	      GElf_Shdr *secshdr;
   2279 	      secshdr = gelf_getshdr (elf_getscn (ebl->elf,
   2280 						  sym->st_shndx == SHN_XINDEX
   2281 						  ? xndx : sym->st_shndx),
   2282 				      &secshdr_mem);
   2283 
   2284 	      if (unlikely (secshdr == NULL))
   2285 		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
   2286 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   2287 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   2288 			/* Avoid the leading R_ which isn't carrying any
   2289 			   information.  */
   2290 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   2291 					       buf, sizeof (buf)) + 2
   2292 			: gettext ("<INVALID RELOC>"),
   2293 			gettext ("INVALID SECTION"),
   2294 			(long int) (sym->st_shndx == SHN_XINDEX
   2295 				    ? xndx : sym->st_shndx));
   2296 	      else
   2297 		printf ("\
   2298   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
   2299 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   2300 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   2301 			/* Avoid the leading R_ which isn't carrying any
   2302 			   information.  */
   2303 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   2304 					       buf, sizeof (buf)) + 2
   2305 			: gettext ("<INVALID RELOC>"),
   2306 			class == ELFCLASS32 ? 10 : 18, sym->st_value,
   2307 			rel->r_addend,
   2308 			elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
   2309 	    }
   2310 	}
   2311     }
   2312 }
   2313 
   2314 
   2315 /* Print the program header.  */
   2316 static void
   2317 print_symtab (Ebl *ebl, int type)
   2318 {
   2319   /* Find the symbol table(s).  For this we have to search through the
   2320      section table.  */
   2321   Elf_Scn *scn = NULL;
   2322 
   2323   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   2324     {
   2325       /* Handle the section if it is a symbol table.  */
   2326       GElf_Shdr shdr_mem;
   2327       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   2328 
   2329       if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
   2330 	{
   2331 	  if (symbol_table_section != NULL)
   2332 	    {
   2333 	      /* Get the section header string table index.  */
   2334 	      size_t shstrndx;
   2335 	      const char *sname;
   2336 	      if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   2337 		error (EXIT_FAILURE, 0,
   2338 		       gettext ("cannot get section header string table index"));
   2339 	      sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
   2340 	      if (sname == NULL || strcmp (sname, symbol_table_section) != 0)
   2341 		continue;
   2342 	    }
   2343 
   2344 	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
   2345 	    {
   2346 	      if (elf_compress (scn, 0, 0) < 0)
   2347 		printf ("WARNING: %s [%zd]\n",
   2348 			gettext ("Couldn't uncompress section"),
   2349 			elf_ndxscn (scn));
   2350 	      shdr = gelf_getshdr (scn, &shdr_mem);
   2351 	      if (unlikely (shdr == NULL))
   2352 		error (EXIT_FAILURE, 0,
   2353 		       gettext ("cannot get section [%zd] header: %s"),
   2354 		       elf_ndxscn (scn), elf_errmsg (-1));
   2355 	    }
   2356 	  handle_symtab (ebl, scn, shdr);
   2357 	}
   2358     }
   2359 }
   2360 
   2361 
   2362 static void
   2363 handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   2364 {
   2365   Elf_Data *versym_data = NULL;
   2366   Elf_Data *verneed_data = NULL;
   2367   Elf_Data *verdef_data = NULL;
   2368   Elf_Data *xndx_data = NULL;
   2369   int class = gelf_getclass (ebl->elf);
   2370   Elf32_Word verneed_stridx = 0;
   2371   Elf32_Word verdef_stridx = 0;
   2372 
   2373   /* Get the data of the section.  */
   2374   Elf_Data *data = elf_getdata (scn, NULL);
   2375   if (data == NULL)
   2376     return;
   2377 
   2378   /* Find out whether we have other sections we might need.  */
   2379   Elf_Scn *runscn = NULL;
   2380   while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
   2381     {
   2382       GElf_Shdr runshdr_mem;
   2383       GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
   2384 
   2385       if (likely (runshdr != NULL))
   2386 	{
   2387 	  if (runshdr->sh_type == SHT_GNU_versym
   2388 	      && runshdr->sh_link == elf_ndxscn (scn))
   2389 	    /* Bingo, found the version information.  Now get the data.  */
   2390 	    versym_data = elf_getdata (runscn, NULL);
   2391 	  else if (runshdr->sh_type == SHT_GNU_verneed)
   2392 	    {
   2393 	      /* This is the information about the needed versions.  */
   2394 	      verneed_data = elf_getdata (runscn, NULL);
   2395 	      verneed_stridx = runshdr->sh_link;
   2396 	    }
   2397 	  else if (runshdr->sh_type == SHT_GNU_verdef)
   2398 	    {
   2399 	      /* This is the information about the defined versions.  */
   2400 	      verdef_data = elf_getdata (runscn, NULL);
   2401 	      verdef_stridx = runshdr->sh_link;
   2402 	    }
   2403 	  else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
   2404 	      && runshdr->sh_link == elf_ndxscn (scn))
   2405 	    /* Extended section index.  */
   2406 	    xndx_data = elf_getdata (runscn, NULL);
   2407 	}
   2408     }
   2409 
   2410   /* Get the section header string table index.  */
   2411   size_t shstrndx;
   2412   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   2413     error (EXIT_FAILURE, 0,
   2414 	   gettext ("cannot get section header string table index"));
   2415 
   2416   GElf_Shdr glink_mem;
   2417   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   2418 				   &glink_mem);
   2419   if (glink == NULL)
   2420     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
   2421 	   elf_ndxscn (scn));
   2422 
   2423   /* Now we can compute the number of entries in the section.  */
   2424   unsigned int nsyms = data->d_size / (class == ELFCLASS32
   2425 				       ? sizeof (Elf32_Sym)
   2426 				       : sizeof (Elf64_Sym));
   2427 
   2428   printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
   2429 		    "\nSymbol table [%2u] '%s' contains %u entries:\n",
   2430 		    nsyms),
   2431 	  (unsigned int) elf_ndxscn (scn),
   2432 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
   2433   printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
   2434 		    " %lu local symbols  String table: [%2u] '%s'\n",
   2435 		    shdr->sh_info),
   2436 	  (unsigned long int) shdr->sh_info,
   2437 	  (unsigned int) shdr->sh_link,
   2438 	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
   2439 
   2440   fputs_unlocked (class == ELFCLASS32
   2441 		  ? gettext ("\
   2442   Num:    Value   Size Type    Bind   Vis          Ndx Name\n")
   2443 		  : gettext ("\
   2444   Num:            Value   Size Type    Bind   Vis          Ndx Name\n"),
   2445 		  stdout);
   2446 
   2447   for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
   2448     {
   2449       char typebuf[64];
   2450       char bindbuf[64];
   2451       char scnbuf[64];
   2452       Elf32_Word xndx;
   2453       GElf_Sym sym_mem;
   2454       GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
   2455 
   2456       if (unlikely (sym == NULL))
   2457 	continue;
   2458 
   2459       /* Determine the real section index.  */
   2460       if (likely (sym->st_shndx != SHN_XINDEX))
   2461 	xndx = sym->st_shndx;
   2462 
   2463       printf (gettext ("\
   2464 %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
   2465 	      cnt,
   2466 	      class == ELFCLASS32 ? 8 : 16,
   2467 	      sym->st_value,
   2468 	      sym->st_size,
   2469 	      ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
   2470 				    typebuf, sizeof (typebuf)),
   2471 	      ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
   2472 				       bindbuf, sizeof (bindbuf)),
   2473 	      get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
   2474 	      ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
   2475 				sizeof (scnbuf), NULL, shnum),
   2476 	      elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
   2477 
   2478       if (versym_data != NULL)
   2479 	{
   2480 	  /* Get the version information.  */
   2481 	  GElf_Versym versym_mem;
   2482 	  GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
   2483 
   2484 	  if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
   2485 	    {
   2486 	      bool is_nobits = false;
   2487 	      bool check_def = xndx != SHN_UNDEF;
   2488 
   2489 	      if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
   2490 		{
   2491 		  GElf_Shdr symshdr_mem;
   2492 		  GElf_Shdr *symshdr =
   2493 		    gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
   2494 
   2495 		  is_nobits = (symshdr != NULL
   2496 			       && symshdr->sh_type == SHT_NOBITS);
   2497 		}
   2498 
   2499 	      if (is_nobits || ! check_def)
   2500 		{
   2501 		  /* We must test both.  */
   2502 		  GElf_Vernaux vernaux_mem;
   2503 		  GElf_Vernaux *vernaux = NULL;
   2504 		  size_t vn_offset = 0;
   2505 
   2506 		  GElf_Verneed verneed_mem;
   2507 		  GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
   2508 							   &verneed_mem);
   2509 		  while (verneed != NULL)
   2510 		    {
   2511 		      size_t vna_offset = vn_offset;
   2512 
   2513 		      vernaux = gelf_getvernaux (verneed_data,
   2514 						 vna_offset += verneed->vn_aux,
   2515 						 &vernaux_mem);
   2516 		      while (vernaux != NULL
   2517 			     && vernaux->vna_other != *versym
   2518 			     && vernaux->vna_next != 0)
   2519 			{
   2520 			  /* Update the offset.  */
   2521 			  vna_offset += vernaux->vna_next;
   2522 
   2523 			  vernaux = (vernaux->vna_next == 0
   2524 				     ? NULL
   2525 				     : gelf_getvernaux (verneed_data,
   2526 							vna_offset,
   2527 							&vernaux_mem));
   2528 			}
   2529 
   2530 		      /* Check whether we found the version.  */
   2531 		      if (vernaux != NULL && vernaux->vna_other == *versym)
   2532 			/* Found it.  */
   2533 			break;
   2534 
   2535 		      vn_offset += verneed->vn_next;
   2536 		      verneed = (verneed->vn_next == 0
   2537 				 ? NULL
   2538 				 : gelf_getverneed (verneed_data, vn_offset,
   2539 						    &verneed_mem));
   2540 		    }
   2541 
   2542 		  if (vernaux != NULL && vernaux->vna_other == *versym)
   2543 		    {
   2544 		      printf ("@%s (%u)",
   2545 			      elf_strptr (ebl->elf, verneed_stridx,
   2546 					  vernaux->vna_name),
   2547 			      (unsigned int) vernaux->vna_other);
   2548 		      check_def = 0;
   2549 		    }
   2550 		  else if (unlikely (! is_nobits))
   2551 		    error (0, 0, gettext ("bad dynamic symbol"));
   2552 		  else
   2553 		    check_def = 1;
   2554 		}
   2555 
   2556 	      if (check_def && *versym != 0x8001)
   2557 		{
   2558 		  /* We must test both.  */
   2559 		  size_t vd_offset = 0;
   2560 
   2561 		  GElf_Verdef verdef_mem;
   2562 		  GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
   2563 							&verdef_mem);
   2564 		  while (verdef != NULL)
   2565 		    {
   2566 		      if (verdef->vd_ndx == (*versym & 0x7fff))
   2567 			/* Found the definition.  */
   2568 			break;
   2569 
   2570 		      vd_offset += verdef->vd_next;
   2571 		      verdef = (verdef->vd_next == 0
   2572 				? NULL
   2573 				: gelf_getverdef (verdef_data, vd_offset,
   2574 						  &verdef_mem));
   2575 		    }
   2576 
   2577 		  if (verdef != NULL)
   2578 		    {
   2579 		      GElf_Verdaux verdaux_mem;
   2580 		      GElf_Verdaux *verdaux
   2581 			= gelf_getverdaux (verdef_data,
   2582 					   vd_offset + verdef->vd_aux,
   2583 					   &verdaux_mem);
   2584 
   2585 		      if (verdaux != NULL)
   2586 			printf ((*versym & 0x8000) ? "@%s" : "@@%s",
   2587 				elf_strptr (ebl->elf, verdef_stridx,
   2588 					    verdaux->vda_name));
   2589 		    }
   2590 		}
   2591 	    }
   2592 	}
   2593 
   2594       putchar_unlocked ('\n');
   2595     }
   2596 }
   2597 
   2598 
   2599 /* Print version information.  */
   2600 static void
   2601 print_verinfo (Ebl *ebl)
   2602 {
   2603   /* Find the version information sections.  For this we have to
   2604      search through the section table.  */
   2605   Elf_Scn *scn = NULL;
   2606 
   2607   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   2608     {
   2609       /* Handle the section if it is part of the versioning handling.  */
   2610       GElf_Shdr shdr_mem;
   2611       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   2612 
   2613       if (likely (shdr != NULL))
   2614 	{
   2615 	  if (shdr->sh_type == SHT_GNU_verneed)
   2616 	    handle_verneed (ebl, scn, shdr);
   2617 	  else if (shdr->sh_type == SHT_GNU_verdef)
   2618 	    handle_verdef (ebl, scn, shdr);
   2619 	  else if (shdr->sh_type == SHT_GNU_versym)
   2620 	    handle_versym (ebl, scn, shdr);
   2621 	}
   2622     }
   2623 }
   2624 
   2625 
   2626 static const char *
   2627 get_ver_flags (unsigned int flags)
   2628 {
   2629   static char buf[32];
   2630   char *endp;
   2631 
   2632   if (flags == 0)
   2633     return gettext ("none");
   2634 
   2635   if (flags & VER_FLG_BASE)
   2636     endp = stpcpy (buf, "BASE ");
   2637   else
   2638     endp = buf;
   2639 
   2640   if (flags & VER_FLG_WEAK)
   2641     {
   2642       if (endp != buf)
   2643 	endp = stpcpy (endp, "| ");
   2644 
   2645       endp = stpcpy (endp, "WEAK ");
   2646     }
   2647 
   2648   if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
   2649     {
   2650       strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
   2651       buf[sizeof (buf) - 1] = '\0';
   2652     }
   2653 
   2654   return buf;
   2655 }
   2656 
   2657 
   2658 static void
   2659 handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   2660 {
   2661   int class = gelf_getclass (ebl->elf);
   2662 
   2663   /* Get the data of the section.  */
   2664   Elf_Data *data = elf_getdata (scn, NULL);
   2665   if (data == NULL)
   2666     return;
   2667 
   2668   /* Get the section header string table index.  */
   2669   size_t shstrndx;
   2670   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   2671     error (EXIT_FAILURE, 0,
   2672 	   gettext ("cannot get section header string table index"));
   2673 
   2674   GElf_Shdr glink_mem;
   2675   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   2676 				   &glink_mem);
   2677   if (glink == NULL)
   2678     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
   2679 	   elf_ndxscn (scn));
   2680 
   2681   printf (ngettext ("\
   2682 \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2683 		    "\
   2684 \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2685 		    shdr->sh_info),
   2686 	  (unsigned int) elf_ndxscn (scn),
   2687 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
   2688 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   2689 	  shdr->sh_offset,
   2690 	  (unsigned int) shdr->sh_link,
   2691 	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
   2692 
   2693   unsigned int offset = 0;
   2694   for (int cnt = shdr->sh_info; --cnt >= 0; )
   2695     {
   2696       /* Get the data at the next offset.  */
   2697       GElf_Verneed needmem;
   2698       GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
   2699       if (unlikely (need == NULL))
   2700 	break;
   2701 
   2702       printf (gettext ("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
   2703 	      offset, (unsigned short int) need->vn_version,
   2704 	      elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
   2705 	      (unsigned short int) need->vn_cnt);
   2706 
   2707       unsigned int auxoffset = offset + need->vn_aux;
   2708       for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
   2709 	{
   2710 	  GElf_Vernaux auxmem;
   2711 	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
   2712 	  if (unlikely (aux == NULL))
   2713 	    break;
   2714 
   2715 	  printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
   2716 		  auxoffset,
   2717 		  elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
   2718 		  get_ver_flags (aux->vna_flags),
   2719 		  (unsigned short int) aux->vna_other);
   2720 
   2721 	  if (aux->vna_next == 0)
   2722 	    break;
   2723 
   2724 	  auxoffset += aux->vna_next;
   2725 	}
   2726 
   2727       /* Find the next offset.  */
   2728       if (need->vn_next == 0)
   2729 	break;
   2730 
   2731       offset += need->vn_next;
   2732     }
   2733 }
   2734 
   2735 
   2736 static void
   2737 handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   2738 {
   2739   /* Get the data of the section.  */
   2740   Elf_Data *data = elf_getdata (scn, NULL);
   2741   if (data == NULL)
   2742     return;
   2743 
   2744   /* Get the section header string table index.  */
   2745   size_t shstrndx;
   2746   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   2747     error (EXIT_FAILURE, 0,
   2748 	   gettext ("cannot get section header string table index"));
   2749 
   2750   GElf_Shdr glink_mem;
   2751   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   2752 				   &glink_mem);
   2753   if (glink == NULL)
   2754     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
   2755 	   elf_ndxscn (scn));
   2756 
   2757   int class = gelf_getclass (ebl->elf);
   2758   printf (ngettext ("\
   2759 \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2760 		    "\
   2761 \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2762 		    shdr->sh_info),
   2763 	  (unsigned int) elf_ndxscn (scn),
   2764 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2765 	  shdr->sh_info,
   2766 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   2767 	  shdr->sh_offset,
   2768 	  (unsigned int) shdr->sh_link,
   2769 	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
   2770 
   2771   unsigned int offset = 0;
   2772   for (int cnt = shdr->sh_info; --cnt >= 0; )
   2773     {
   2774       /* Get the data at the next offset.  */
   2775       GElf_Verdef defmem;
   2776       GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
   2777       if (unlikely (def == NULL))
   2778 	break;
   2779 
   2780       unsigned int auxoffset = offset + def->vd_aux;
   2781       GElf_Verdaux auxmem;
   2782       GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
   2783       if (unlikely (aux == NULL))
   2784 	break;
   2785 
   2786       printf (gettext ("\
   2787   %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"),
   2788 	      offset, def->vd_version,
   2789 	      get_ver_flags (def->vd_flags),
   2790 	      def->vd_ndx,
   2791 	      def->vd_cnt,
   2792 	      elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
   2793 
   2794       auxoffset += aux->vda_next;
   2795       for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
   2796 	{
   2797 	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
   2798 	  if (unlikely (aux == NULL))
   2799 	    break;
   2800 
   2801 	  printf (gettext ("  %#06x: Parent %d: %s\n"),
   2802 		  auxoffset, cnt2,
   2803 		  elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
   2804 
   2805 	  if (aux->vda_next == 0)
   2806 	    break;
   2807 
   2808 	  auxoffset += aux->vda_next;
   2809 	}
   2810 
   2811       /* Find the next offset.  */
   2812       if (def->vd_next == 0)
   2813 	break;
   2814       offset += def->vd_next;
   2815     }
   2816 }
   2817 
   2818 
   2819 static void
   2820 handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   2821 {
   2822   int class = gelf_getclass (ebl->elf);
   2823   const char **vername;
   2824   const char **filename;
   2825 
   2826   /* Get the data of the section.  */
   2827   Elf_Data *data = elf_getdata (scn, NULL);
   2828   if (data == NULL)
   2829     return;
   2830 
   2831   /* Get the section header string table index.  */
   2832   size_t shstrndx;
   2833   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   2834     error (EXIT_FAILURE, 0,
   2835 	   gettext ("cannot get section header string table index"));
   2836 
   2837   /* We have to find the version definition section and extract the
   2838      version names.  */
   2839   Elf_Scn *defscn = NULL;
   2840   Elf_Scn *needscn = NULL;
   2841 
   2842   Elf_Scn *verscn = NULL;
   2843   while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
   2844     {
   2845       GElf_Shdr vershdr_mem;
   2846       GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
   2847 
   2848       if (likely (vershdr != NULL))
   2849 	{
   2850 	  if (vershdr->sh_type == SHT_GNU_verdef)
   2851 	    defscn = verscn;
   2852 	  else if (vershdr->sh_type == SHT_GNU_verneed)
   2853 	    needscn = verscn;
   2854 	}
   2855     }
   2856 
   2857   size_t nvername;
   2858   if (defscn != NULL || needscn != NULL)
   2859     {
   2860       /* We have a version information (better should have).  Now get
   2861 	 the version names.  First find the maximum version number.  */
   2862       nvername = 0;
   2863       if (defscn != NULL)
   2864 	{
   2865 	  /* Run through the version definitions and find the highest
   2866 	     index.  */
   2867 	  unsigned int offset = 0;
   2868 	  Elf_Data *defdata;
   2869 	  GElf_Shdr defshdrmem;
   2870 	  GElf_Shdr *defshdr;
   2871 
   2872 	  defdata = elf_getdata (defscn, NULL);
   2873 	  if (unlikely (defdata == NULL))
   2874 	    return;
   2875 
   2876 	  defshdr = gelf_getshdr (defscn, &defshdrmem);
   2877 	  if (unlikely (defshdr == NULL))
   2878 	    return;
   2879 
   2880 	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
   2881 	    {
   2882 	      GElf_Verdef defmem;
   2883 	      GElf_Verdef *def;
   2884 
   2885 	      /* Get the data at the next offset.  */
   2886 	      def = gelf_getverdef (defdata, offset, &defmem);
   2887 	      if (unlikely (def == NULL))
   2888 		break;
   2889 
   2890 	      nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
   2891 
   2892 	      if (def->vd_next == 0)
   2893 		break;
   2894 	      offset += def->vd_next;
   2895 	    }
   2896 	}
   2897       if (needscn != NULL)
   2898 	{
   2899 	  unsigned int offset = 0;
   2900 	  Elf_Data *needdata;
   2901 	  GElf_Shdr needshdrmem;
   2902 	  GElf_Shdr *needshdr;
   2903 
   2904 	  needdata = elf_getdata (needscn, NULL);
   2905 	  if (unlikely (needdata == NULL))
   2906 	    return;
   2907 
   2908 	  needshdr = gelf_getshdr (needscn, &needshdrmem);
   2909 	  if (unlikely (needshdr == NULL))
   2910 	    return;
   2911 
   2912 	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
   2913 	    {
   2914 	      GElf_Verneed needmem;
   2915 	      GElf_Verneed *need;
   2916 	      unsigned int auxoffset;
   2917 	      int cnt2;
   2918 
   2919 	      /* Get the data at the next offset.  */
   2920 	      need = gelf_getverneed (needdata, offset, &needmem);
   2921 	      if (unlikely (need == NULL))
   2922 		break;
   2923 
   2924 	      /* Run through the auxiliary entries.  */
   2925 	      auxoffset = offset + need->vn_aux;
   2926 	      for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
   2927 		{
   2928 		  GElf_Vernaux auxmem;
   2929 		  GElf_Vernaux *aux;
   2930 
   2931 		  aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
   2932 		  if (unlikely (aux == NULL))
   2933 		    break;
   2934 
   2935 		  nvername = MAX (nvername,
   2936 				  (size_t) (aux->vna_other & 0x7fff));
   2937 
   2938 		  if (aux->vna_next == 0)
   2939 		    break;
   2940 		  auxoffset += aux->vna_next;
   2941 		}
   2942 
   2943 	      if (need->vn_next == 0)
   2944 		break;
   2945 	      offset += need->vn_next;
   2946 	    }
   2947 	}
   2948 
   2949       /* This is the number of versions we know about.  */
   2950       ++nvername;
   2951 
   2952       /* Allocate the array.  */
   2953       vername = (const char **) alloca (nvername * sizeof (const char *));
   2954       memset(vername, 0, nvername * sizeof (const char *));
   2955       filename = (const char **) alloca (nvername * sizeof (const char *));
   2956       memset(filename, 0, nvername * sizeof (const char *));
   2957 
   2958       /* Run through the data structures again and collect the strings.  */
   2959       if (defscn != NULL)
   2960 	{
   2961 	  /* Run through the version definitions and find the highest
   2962 	     index.  */
   2963 	  unsigned int offset = 0;
   2964 	  Elf_Data *defdata;
   2965 	  GElf_Shdr defshdrmem;
   2966 	  GElf_Shdr *defshdr;
   2967 
   2968 	  defdata = elf_getdata (defscn, NULL);
   2969 	  if (unlikely (defdata == NULL))
   2970 	    return;
   2971 
   2972 	  defshdr = gelf_getshdr (defscn, &defshdrmem);
   2973 	  if (unlikely (defshdr == NULL))
   2974 	    return;
   2975 
   2976 	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
   2977 	    {
   2978 
   2979 	      /* Get the data at the next offset.  */
   2980 	      GElf_Verdef defmem;
   2981 	      GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
   2982 	      if (unlikely (def == NULL))
   2983 		break;
   2984 
   2985 	      GElf_Verdaux auxmem;
   2986 	      GElf_Verdaux *aux = gelf_getverdaux (defdata,
   2987 						   offset + def->vd_aux,
   2988 						   &auxmem);
   2989 	      if (unlikely (aux == NULL))
   2990 		break;
   2991 
   2992 	      vername[def->vd_ndx & 0x7fff]
   2993 		= elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
   2994 	      filename[def->vd_ndx & 0x7fff] = NULL;
   2995 
   2996 	      if (def->vd_next == 0)
   2997 		break;
   2998 	      offset += def->vd_next;
   2999 	    }
   3000 	}
   3001       if (needscn != NULL)
   3002 	{
   3003 	  unsigned int offset = 0;
   3004 
   3005 	  Elf_Data *needdata = elf_getdata (needscn, NULL);
   3006 	  GElf_Shdr needshdrmem;
   3007 	  GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
   3008 	  if (unlikely (needdata == NULL || needshdr == NULL))
   3009 	    return;
   3010 
   3011 	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
   3012 	    {
   3013 	      /* Get the data at the next offset.  */
   3014 	      GElf_Verneed needmem;
   3015 	      GElf_Verneed *need = gelf_getverneed (needdata, offset,
   3016 						    &needmem);
   3017 	      if (unlikely (need == NULL))
   3018 		break;
   3019 
   3020 	      /* Run through the auxiliary entries.  */
   3021 	      unsigned int auxoffset = offset + need->vn_aux;
   3022 	      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
   3023 		{
   3024 		  GElf_Vernaux auxmem;
   3025 		  GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
   3026 						       &auxmem);
   3027 		  if (unlikely (aux == NULL))
   3028 		    break;
   3029 
   3030 		  vername[aux->vna_other & 0x7fff]
   3031 		    = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
   3032 		  filename[aux->vna_other & 0x7fff]
   3033 		    = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
   3034 
   3035 		  if (aux->vna_next == 0)
   3036 		    break;
   3037 		  auxoffset += aux->vna_next;
   3038 		}
   3039 
   3040 	      if (need->vn_next == 0)
   3041 		break;
   3042 	      offset += need->vn_next;
   3043 	    }
   3044 	}
   3045     }
   3046   else
   3047     {
   3048       vername = NULL;
   3049       nvername = 1;
   3050       filename = NULL;
   3051     }
   3052 
   3053   GElf_Shdr glink_mem;
   3054   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   3055 				   &glink_mem);
   3056   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_HALF, 1, EV_CURRENT);
   3057   if (glink == NULL)
   3058     error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
   3059 	   elf_ndxscn (scn));
   3060 
   3061   /* Print the header.  */
   3062   printf (ngettext ("\
   3063 \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
   3064 		    "\
   3065 \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
   3066 		    shdr->sh_size / sh_entsize),
   3067 	  (unsigned int) elf_ndxscn (scn),
   3068 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   3069 	  (int) (shdr->sh_size / sh_entsize),
   3070 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   3071 	  shdr->sh_offset,
   3072 	  (unsigned int) shdr->sh_link,
   3073 	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
   3074 
   3075   /* Now we can finally look at the actual contents of this section.  */
   3076   for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
   3077     {
   3078       if (cnt % 2 == 0)
   3079 	printf ("\n %4d:", cnt);
   3080 
   3081       GElf_Versym symmem;
   3082       GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
   3083       if (sym == NULL)
   3084 	break;
   3085 
   3086       switch (*sym)
   3087 	{
   3088 	  ssize_t n;
   3089 	case 0:
   3090 	  fputs_unlocked (gettext ("   0 *local*                     "),
   3091 			  stdout);
   3092 	  break;
   3093 
   3094 	case 1:
   3095 	  fputs_unlocked (gettext ("   1 *global*                    "),
   3096 			  stdout);
   3097 	  break;
   3098 
   3099 	default:
   3100 	  n = printf ("%4d%c%s",
   3101 		      *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
   3102 		      (vername != NULL
   3103 		       && (unsigned int) (*sym & 0x7fff) < nvername)
   3104 		      ? vername[*sym & 0x7fff] : "???");
   3105 	  if ((unsigned int) (*sym & 0x7fff) < nvername
   3106 	      && filename != NULL && filename[*sym & 0x7fff] != NULL)
   3107 	    n += printf ("(%s)", filename[*sym & 0x7fff]);
   3108 	  printf ("%*s", MAX (0, 33 - (int) n), " ");
   3109 	  break;
   3110 	}
   3111     }
   3112   putchar_unlocked ('\n');
   3113 }
   3114 
   3115 
   3116 static void
   3117 print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
   3118 		 uint_fast32_t maxlength, Elf32_Word nbucket,
   3119 		 uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
   3120 {
   3121   uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
   3122 
   3123   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
   3124     ++counts[lengths[cnt]];
   3125 
   3126   GElf_Shdr glink_mem;
   3127   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf,
   3128 					       shdr->sh_link),
   3129 				   &glink_mem);
   3130   if (glink == NULL)
   3131     {
   3132       error (0, 0, gettext ("invalid sh_link value in section %zu"),
   3133 	     elf_ndxscn (scn));
   3134       return;
   3135     }
   3136 
   3137   printf (ngettext ("\
   3138 \nHistogram for bucket list length in section [%2u] '%s' (total of %d bucket):\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   3139 		    "\
   3140 \nHistogram for bucket list length in section [%2u] '%s' (total of %d buckets):\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   3141 		    nbucket),
   3142 	  (unsigned int) elf_ndxscn (scn),
   3143 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   3144 	  (int) nbucket,
   3145 	  gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
   3146 	  shdr->sh_addr,
   3147 	  shdr->sh_offset,
   3148 	  (unsigned int) shdr->sh_link,
   3149 	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
   3150 
   3151   if (extrastr != NULL)
   3152     fputs (extrastr, stdout);
   3153 
   3154   if (likely (nbucket > 0))
   3155     {
   3156       uint64_t success = 0;
   3157 
   3158       /* xgettext:no-c-format */
   3159       fputs_unlocked (gettext ("\
   3160  Length  Number  % of total  Coverage\n"), stdout);
   3161       printf (gettext ("      0  %6" PRIu32 "      %5.1f%%\n"),
   3162 	      counts[0], (counts[0] * 100.0) / nbucket);
   3163 
   3164       uint64_t nzero_counts = 0;
   3165       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
   3166 	{
   3167 	  nzero_counts += counts[cnt] * cnt;
   3168 	  printf (gettext ("\
   3169 %7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
   3170 		  (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
   3171 		  (nzero_counts * 100.0) / nsyms);
   3172 	}
   3173 
   3174       Elf32_Word acc = 0;
   3175       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
   3176 	{
   3177 	  acc += cnt;
   3178 	  success += counts[cnt] * acc;
   3179 	}
   3180 
   3181       printf (gettext ("\
   3182  Average number of tests:   successful lookup: %f\n\
   3183 			  unsuccessful lookup: %f\n"),
   3184 	      (double) success / (double) nzero_counts,
   3185 	      (double) nzero_counts / (double) nbucket);
   3186     }
   3187 
   3188   free (counts);
   3189 }
   3190 
   3191 
   3192 /* This function handles the traditional System V-style hash table format.  */
   3193 static void
   3194 handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
   3195 {
   3196   Elf_Data *data = elf_getdata (scn, NULL);
   3197   if (unlikely (data == NULL))
   3198     {
   3199       error (0, 0, gettext ("cannot get data for section %d: %s"),
   3200 	     (int) elf_ndxscn (scn), elf_errmsg (-1));
   3201       return;
   3202     }
   3203 
   3204   if (unlikely (data->d_size < 2 * sizeof (Elf32_Word)))
   3205     {
   3206     invalid_data:
   3207       error (0, 0, gettext ("invalid data in sysv.hash section %d"),
   3208 	     (int) elf_ndxscn (scn));
   3209       return;
   3210     }
   3211 
   3212   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
   3213   Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
   3214 
   3215   uint64_t used_buf = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
   3216   if (used_buf > data->d_size)
   3217     goto invalid_data;
   3218 
   3219   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
   3220   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
   3221 
   3222   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
   3223 
   3224   uint_fast32_t maxlength = 0;
   3225   uint_fast32_t nsyms = 0;
   3226   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
   3227     {
   3228       Elf32_Word inner = bucket[cnt];
   3229       Elf32_Word chain_len = 0;
   3230       while (inner > 0 && inner < nchain)
   3231 	{
   3232 	  ++nsyms;
   3233 	  ++chain_len;
   3234 	  if (chain_len > nchain)
   3235 	    {
   3236 	      error (0, 0, gettext ("invalid chain in sysv.hash section %d"),
   3237 		     (int) elf_ndxscn (scn));
   3238 	      free (lengths);
   3239 	      return;
   3240 	    }
   3241 	  if (maxlength < ++lengths[cnt])
   3242 	    ++maxlength;
   3243 
   3244 	  inner = chain[inner];
   3245 	}
   3246     }
   3247 
   3248   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
   3249 		   lengths, NULL);
   3250 
   3251   free (lengths);
   3252 }
   3253 
   3254 
   3255 /* This function handles the incorrect, System V-style hash table
   3256    format some 64-bit architectures use.  */
   3257 static void
   3258 handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
   3259 {
   3260   Elf_Data *data = elf_getdata (scn, NULL);
   3261   if (unlikely (data == NULL))
   3262     {
   3263       error (0, 0, gettext ("cannot get data for section %d: %s"),
   3264 	     (int) elf_ndxscn (scn), elf_errmsg (-1));
   3265       return;
   3266     }
   3267 
   3268   if (unlikely (data->d_size < 2 * sizeof (Elf64_Xword)))
   3269     {
   3270     invalid_data:
   3271       error (0, 0, gettext ("invalid data in sysv.hash64 section %d"),
   3272 	     (int) elf_ndxscn (scn));
   3273       return;
   3274     }
   3275 
   3276   Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
   3277   Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
   3278 
   3279   uint64_t maxwords = data->d_size / sizeof (Elf64_Xword);
   3280   if (maxwords < 2
   3281       || maxwords - 2 < nbucket
   3282       || maxwords - 2 - nbucket < nchain)
   3283     goto invalid_data;
   3284 
   3285   Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
   3286   Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
   3287 
   3288   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
   3289 
   3290   uint_fast32_t maxlength = 0;
   3291   uint_fast32_t nsyms = 0;
   3292   for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
   3293     {
   3294       Elf64_Xword inner = bucket[cnt];
   3295       Elf64_Xword chain_len = 0;
   3296       while (inner > 0 && inner < nchain)
   3297 	{
   3298 	  ++nsyms;
   3299 	  ++chain_len;
   3300 	  if (chain_len > nchain)
   3301 	    {
   3302 	      error (0, 0, gettext ("invalid chain in sysv.hash64 section %d"),
   3303 		     (int) elf_ndxscn (scn));
   3304 	      free (lengths);
   3305 	      return;
   3306 	    }
   3307 	  if (maxlength < ++lengths[cnt])
   3308 	    ++maxlength;
   3309 
   3310 	  inner = chain[inner];
   3311 	}
   3312     }
   3313 
   3314   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
   3315 		   lengths, NULL);
   3316 
   3317   free (lengths);
   3318 }
   3319 
   3320 
   3321 /* This function handles the GNU-style hash table format.  */
   3322 static void
   3323 handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
   3324 {
   3325   uint32_t *lengths = NULL;
   3326   Elf_Data *data = elf_getdata (scn, NULL);
   3327   if (unlikely (data == NULL))
   3328     {
   3329       error (0, 0, gettext ("cannot get data for section %d: %s"),
   3330 	     (int) elf_ndxscn (scn), elf_errmsg (-1));
   3331       return;
   3332     }
   3333 
   3334   if (unlikely (data->d_size < 4 * sizeof (Elf32_Word)))
   3335     {
   3336     invalid_data:
   3337       free (lengths);
   3338       error (0, 0, gettext ("invalid data in gnu.hash section %d"),
   3339 	     (int) elf_ndxscn (scn));
   3340       return;
   3341     }
   3342 
   3343   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
   3344   Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
   3345 
   3346   /* Next comes the size of the bitmap.  It's measured in words for
   3347      the architecture.  It's 32 bits for 32 bit archs, and 64 bits for
   3348      64 bit archs.  There is always a bloom filter present, so zero is
   3349      an invalid value.  */
   3350   Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
   3351   if (gelf_getclass (ebl->elf) == ELFCLASS64)
   3352     bitmask_words *= 2;
   3353 
   3354   if (bitmask_words == 0)
   3355     goto invalid_data;
   3356 
   3357   Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
   3358 
   3359   /* Is there still room for the sym chain?
   3360      Use uint64_t calculation to prevent 32bit overlow.  */
   3361   uint64_t used_buf = (4ULL + bitmask_words + nbucket) * sizeof (Elf32_Word);
   3362   uint32_t max_nsyms = (data->d_size - used_buf) / sizeof (Elf32_Word);
   3363   if (used_buf > data->d_size)
   3364     goto invalid_data;
   3365 
   3366   lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
   3367 
   3368   Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
   3369   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
   3370   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
   3371 						    + nbucket];
   3372 
   3373   /* Compute distribution of chain lengths.  */
   3374   uint_fast32_t maxlength = 0;
   3375   uint_fast32_t nsyms = 0;
   3376   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
   3377     if (bucket[cnt] != 0)
   3378       {
   3379 	Elf32_Word inner = bucket[cnt] - symbias;
   3380 	do
   3381 	  {
   3382 	    ++nsyms;
   3383 	    if (maxlength < ++lengths[cnt])
   3384 	      ++maxlength;
   3385 	    if (inner >= max_nsyms)
   3386 	      goto invalid_data;
   3387 	  }
   3388 	while ((chain[inner++] & 1) == 0);
   3389       }
   3390 
   3391   /* Count bits in bitmask.  */
   3392   uint_fast32_t nbits = 0;
   3393   for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
   3394     {
   3395       uint_fast32_t word = bitmask[cnt];
   3396 
   3397       word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
   3398       word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
   3399       word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
   3400       word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
   3401       nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
   3402     }
   3403 
   3404   char *str;
   3405   if (unlikely (asprintf (&str, gettext ("\
   3406  Symbol Bias: %u\n\
   3407  Bitmask Size: %zu bytes  %" PRIuFAST32 "%% bits set  2nd hash shift: %u\n"),
   3408 			  (unsigned int) symbias,
   3409 			  bitmask_words * sizeof (Elf32_Word),
   3410 			  ((nbits * 100 + 50)
   3411 			   / (uint_fast32_t) (bitmask_words
   3412 					      * sizeof (Elf32_Word) * 8)),
   3413 			  (unsigned int) shift) == -1))
   3414     error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
   3415 
   3416   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
   3417 		   lengths, str);
   3418 
   3419   free (str);
   3420   free (lengths);
   3421 }
   3422 
   3423 
   3424 /* Find the symbol table(s).  For this we have to search through the
   3425    section table.  */
   3426 static void
   3427 handle_hash (Ebl *ebl)
   3428 {
   3429   /* Get the section header string table index.  */
   3430   size_t shstrndx;
   3431   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   3432     error (EXIT_FAILURE, 0,
   3433 	   gettext ("cannot get section header string table index"));
   3434 
   3435   Elf_Scn *scn = NULL;
   3436   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   3437     {
   3438       /* Handle the section if it is a symbol table.  */
   3439       GElf_Shdr shdr_mem;
   3440       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   3441 
   3442       if (likely (shdr != NULL))
   3443 	{
   3444 	  if ((shdr->sh_type == SHT_HASH || shdr->sh_type == SHT_GNU_HASH)
   3445 	      && (shdr->sh_flags & SHF_COMPRESSED) != 0)
   3446 	    {
   3447 	      if (elf_compress (scn, 0, 0) < 0)
   3448 		printf ("WARNING: %s [%zd]\n",
   3449 			gettext ("Couldn't uncompress section"),
   3450 			elf_ndxscn (scn));
   3451 	      shdr = gelf_getshdr (scn, &shdr_mem);
   3452 	      if (unlikely (shdr == NULL))
   3453 		error (EXIT_FAILURE, 0,
   3454 		       gettext ("cannot get section [%zd] header: %s"),
   3455 		       elf_ndxscn (scn), elf_errmsg (-1));
   3456 	    }
   3457 
   3458 	  if (shdr->sh_type == SHT_HASH)
   3459 	    {
   3460 	      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
   3461 		handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
   3462 	      else
   3463 		handle_sysv_hash (ebl, scn, shdr, shstrndx);
   3464 	    }
   3465 	  else if (shdr->sh_type == SHT_GNU_HASH)
   3466 	    handle_gnu_hash (ebl, scn, shdr, shstrndx);
   3467 	}
   3468     }
   3469 }
   3470 
   3471 
   3472 static void
   3473 print_liblist (Ebl *ebl)
   3474 {
   3475   /* Find the library list sections.  For this we have to search
   3476      through the section table.  */
   3477   Elf_Scn *scn = NULL;
   3478 
   3479   /* Get the section header string table index.  */
   3480   size_t shstrndx;
   3481   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   3482     error (EXIT_FAILURE, 0,
   3483 	   gettext ("cannot get section header string table index"));
   3484 
   3485   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   3486     {
   3487       GElf_Shdr shdr_mem;
   3488       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   3489 
   3490       if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
   3491 	{
   3492 	  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_LIB, 1, EV_CURRENT);
   3493 	  int nentries = shdr->sh_size / sh_entsize;
   3494 	  printf (ngettext ("\
   3495 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   3496 			    "\
   3497 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   3498 			    nentries),
   3499 		  elf_ndxscn (scn),
   3500 		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   3501 		  shdr->sh_offset,
   3502 		  nentries);
   3503 
   3504 	  Elf_Data *data = elf_getdata (scn, NULL);
   3505 	  if (data == NULL)
   3506 	    return;
   3507 
   3508 	  puts (gettext ("\
   3509        Library                       Time Stamp          Checksum Version Flags"));
   3510 
   3511 	  for (int cnt = 0; cnt < nentries; ++cnt)
   3512 	    {
   3513 	      GElf_Lib lib_mem;
   3514 	      GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
   3515 	      if (unlikely (lib == NULL))
   3516 		continue;
   3517 
   3518 	      time_t t = (time_t) lib->l_time_stamp;
   3519 	      struct tm *tm = gmtime (&t);
   3520 	      if (unlikely (tm == NULL))
   3521 		continue;
   3522 
   3523 	      printf ("  [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
   3524 		      cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
   3525 		      tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
   3526 		      tm->tm_hour, tm->tm_min, tm->tm_sec,
   3527 		      (unsigned int) lib->l_checksum,
   3528 		      (unsigned int) lib->l_version,
   3529 		      (unsigned int) lib->l_flags);
   3530 	    }
   3531 	}
   3532     }
   3533 }
   3534 
   3535 static void
   3536 print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
   3537 {
   3538   /* Find the object attributes sections.  For this we have to search
   3539      through the section table.  */
   3540   Elf_Scn *scn = NULL;
   3541 
   3542   /* Get the section header string table index.  */
   3543   size_t shstrndx;
   3544   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
   3545     error (EXIT_FAILURE, 0,
   3546 	   gettext ("cannot get section header string table index"));
   3547 
   3548   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   3549     {
   3550       GElf_Shdr shdr_mem;
   3551       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   3552 
   3553       if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
   3554 			   && (shdr->sh_type != SHT_ARM_ATTRIBUTES
   3555 			       || ehdr->e_machine != EM_ARM)))
   3556 	continue;
   3557 
   3558       printf (gettext ("\
   3559 \nObject attributes section [%2zu] '%s' of %" PRIu64
   3560 		       " bytes at offset %#0" PRIx64 ":\n"),
   3561 	      elf_ndxscn (scn),
   3562 	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   3563 	      shdr->sh_size, shdr->sh_offset);
   3564 
   3565       Elf_Data *data = elf_rawdata (scn, NULL);
   3566       if (unlikely (data == NULL || data->d_size == 0))
   3567 	return;
   3568 
   3569       const unsigned char *p = data->d_buf;
   3570 
   3571       /* There is only one 'version', A.  */
   3572       if (unlikely (*p++ != 'A'))
   3573 	return;
   3574 
   3575       fputs_unlocked (gettext ("  Owner          Size\n"), stdout);
   3576 
   3577       inline size_t left (void)
   3578       {
   3579 	return (const unsigned char *) data->d_buf + data->d_size - p;
   3580       }
   3581 
   3582       /* Loop over the sections.  */
   3583       while (left () >= 4)
   3584 	{
   3585 	  /* Section length.  */
   3586 	  uint32_t len;
   3587 	  memcpy (&len, p, sizeof len);
   3588 
   3589 	  if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
   3590 	    CONVERT (len);
   3591 
   3592 	  if (unlikely (len > left ()))
   3593 	    break;
   3594 
   3595 	  /* Section vendor name.  */
   3596 	  const unsigned char *name = p + sizeof len;
   3597 	  p += len;
   3598 
   3599 	  unsigned const char *q = memchr (name, '\0', len);
   3600 	  if (unlikely (q == NULL))
   3601 	    break;
   3602 	  ++q;
   3603 
   3604 	  printf (gettext ("  %-13s  %4" PRIu32 "\n"), name, len);
   3605 
   3606 	  bool gnu_vendor = (q - name == sizeof "gnu"
   3607 			     && !memcmp (name, "gnu", sizeof "gnu"));
   3608 
   3609 	  /* Loop over subsections.  */
   3610 	  if (shdr->sh_type != SHT_GNU_ATTRIBUTES
   3611 	      || gnu_vendor)
   3612 	    while (q < p)
   3613 	      {
   3614 		const unsigned char *const sub = q;
   3615 
   3616 		unsigned int subsection_tag;
   3617 		get_uleb128 (subsection_tag, q, p);
   3618 		if (unlikely (q >= p))
   3619 		  break;
   3620 
   3621 		uint32_t subsection_len;
   3622 		if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
   3623 		  break;
   3624 
   3625 		memcpy (&subsection_len, q, sizeof subsection_len);
   3626 
   3627 		if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
   3628 		  CONVERT (subsection_len);
   3629 
   3630 		/* Don't overflow, ptrdiff_t might be 32bits, but signed.  */
   3631 		if (unlikely (subsection_len == 0
   3632 			      || subsection_len >= (uint32_t) PTRDIFF_MAX
   3633 			      || p - sub < (ptrdiff_t) subsection_len))
   3634 		  break;
   3635 
   3636 		const unsigned char *r = q + sizeof subsection_len;
   3637 		q = sub + subsection_len;
   3638 
   3639 		switch (subsection_tag)
   3640 		  {
   3641 		  default:
   3642 		    /* Unknown subsection, print and skip.  */
   3643 		    printf (gettext ("    %-4u %12" PRIu32 "\n"),
   3644 			    subsection_tag, subsection_len);
   3645 		    break;
   3646 
   3647 		  case 1:	/* Tag_File */
   3648 		    printf (gettext ("    File: %11" PRIu32 "\n"),
   3649 			    subsection_len);
   3650 
   3651 		    while (r < q)
   3652 		      {
   3653 			unsigned int tag;
   3654 			get_uleb128 (tag, r, q);
   3655 			if (unlikely (r >= q))
   3656 			  break;
   3657 
   3658 			/* GNU style tags have either a uleb128 value,
   3659 			   when lowest bit is not set, or a string
   3660 			   when the lowest bit is set.
   3661 			   "compatibility" (32) is special.  It has
   3662 			   both a string and a uleb128 value.  For
   3663 			   non-gnu we assume 6 till 31 only take ints.
   3664 			   XXX see arm backend, do we need a separate
   3665 			   hook?  */
   3666 			uint64_t value = 0;
   3667 			const char *string = NULL;
   3668 			if (tag == 32 || (tag & 1) == 0
   3669 			    || (! gnu_vendor && (tag > 5 && tag < 32)))
   3670 			  {
   3671 			    get_uleb128 (value, r, q);
   3672 			    if (r > q)
   3673 			      break;
   3674 			  }
   3675 			if (tag == 32
   3676 			    || ((tag & 1) != 0
   3677 				&& (