Home | History | Annotate | Download | only in src
      1 /* Print information from ELF file in human-readable form.
      2    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
      3    Written by Ulrich Drepper <drepper (at) redhat.com>, 1999.
      4 
      5    This program is Open Source software; you can redistribute it and/or
      6    modify it under the terms of the Open Software License version 1.0 as
      7    published by the Open Source Initiative.
      8 
      9    You should have received a copy of the Open Software License along
     10    with this program; if not, you may obtain a copy of the Open Software
     11    License version 1.0 from http://www.opensource.org/licenses/osl.php or
     12    by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
     13    3001 King Ranch Road, Ukiah, CA 95482.   */
     14 
     15 #ifdef HAVE_CONFIG_H
     16 # include <config.h>
     17 #endif
     18 
     19 #include <argp.h>
     20 #include <assert.h>
     21 #include <dwarf.h>
     22 #include <errno.h>
     23 #include <error.h>
     24 #include <fcntl.h>
     25 #include <gelf.h>
     26 #include <inttypes.h>
     27 #include <langinfo.h>
     28 #include <libdw.h>
     29 #include <libebl.h>
     30 #include <libintl.h>
     31 #include <locale.h>
     32 #include <stdbool.h>
     33 #include <stdlib.h>
     34 #include <string.h>
     35 #include <time.h>
     36 #include <unistd.h>
     37 #include <sys/param.h>
     38 
     39 #include <system.h>
     40 #include "../libdw/libdwP.h"
     41 #include "../libdw/memory-access.h"
     42 
     43 
     44 /* Name and version of program.  */
     45 static void print_version (FILE *stream, struct argp_state *state);
     46 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
     47 
     48 /* Definitions of arguments for argp functions.  */
     49 static const struct argp_option options[] =
     50 {
     51   { NULL, 0, NULL, 0, N_("Output selection:") },
     52   { "all", 'a', NULL, 0, N_("Equivalent to: -h -l") },
     53   { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment") },
     54   { "file-header", 'h', NULL, 0, N_("Display the ELF file header") },
     55   { "histogram", 'I', NULL, 0,
     56     N_("Display histogram of bucket list lengths") },
     57   { "program-headers", 'l', NULL, 0, N_("Display the program headers") },
     58   { "relocs", 'r', NULL, 0, N_("Display relocations") },
     59   { "section-headers", 'S', NULL, 0, N_("Display the sections' header") },
     60   { "symbols", 's', NULL, 0, N_("Display the symbol table") },
     61   { "version-info", 'V', NULL, 0, N_("Display versioning information") },
     62   { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
     63     N_("Display DWARF section content.  SECTION can be one of abbrev, "
     64        "aranges, frame, info, loc, line, pubnames, str, or macinfo.") },
     65   { "notes", 'n', NULL, 0, N_("Display the core notes") },
     66   { "arch-specific", 'A', NULL, 0,
     67     N_("Display architecture specific information (if any)") },
     68 
     69   { NULL, 0, NULL, 0, N_("Output control:") },
     70 
     71   { NULL, 0, NULL, 0, NULL }
     72 };
     73 
     74 /* Short description of program.  */
     75 static const char doc[] = N_("\
     76 Print information from ELF file in human-readable form.");
     77 
     78 /* Strings for arguments in help texts.  */
     79 static const char args_doc[] = N_("FILE...");
     80 
     81 /* Prototype for option handler.  */
     82 static error_t parse_opt (int key, char *arg, struct argp_state *state);
     83 
     84 /* Function to print some extra text in the help message.  */
     85 static char *more_help (int key, const char *text, void *input);
     86 
     87 /* Data structure to communicate with argp functions.  */
     88 static struct argp argp =
     89 {
     90   options, parse_opt, args_doc, doc, NULL, more_help
     91 };
     92 
     93 
     94 /* Flags set by the option controlling the output.  */
     95 
     96 /* True if any of the control options is set.  */
     97 static bool any_control_option;
     98 
     99 /* True if dynamic segment should be printed.  */
    100 static bool print_dynamic_table;
    101 
    102 /* True if the file header should be printed.  */
    103 static bool print_file_header;
    104 
    105 /* True if the program headers should be printed.  */
    106 static bool print_program_header;
    107 
    108 /* True if relocations should be printed.  */
    109 static bool print_relocations;
    110 
    111 /* True if the section headers should be printed.  */
    112 static bool print_section_header;
    113 
    114 /* True if the symbol table should be printed.  */
    115 static bool print_symbol_table;
    116 
    117 /* True if the version information should be printed.  */
    118 static bool print_version_info;
    119 
    120 /* True if section groups should be printed.  */
    121 static bool print_section_groups;
    122 
    123 /* True if bucket list length histogram should be printed.  */
    124 static bool print_histogram;
    125 
    126 /* True if the architecture specific data should be printed.  */
    127 static bool print_arch;
    128 
    129 /* True if note section content should be printed.  */
    130 static bool print_notes;
    131 
    132 /* Select printing of debugging sections.  */
    133 static enum section_e
    134 {
    135   section_abbrev = 1,	/* .debug_abbrev  */
    136   section_aranges = 2,	/* .debug_aranges  */
    137   section_frame = 4,	/* .debug_frame or .eh_frame  */
    138   section_info = 8,	/* .debug_info  */
    139   section_line = 16,	/* .debug_line  */
    140   section_loc = 32,	/* .debug_loc  */
    141   section_pubnames = 64,/* .debug_pubnames  */
    142   section_str = 128,	/* .debug_str  */
    143   section_macinfo = 256,/* .debug_macinfo  */
    144   section_all = (section_abbrev | section_aranges | section_frame
    145 		 | section_info | section_line | section_loc
    146 		 | section_pubnames | section_str | section_macinfo)
    147 } print_debug_sections;
    148 
    149 /* Number of sections in the file.  */
    150 static size_t shnum;
    151 
    152 
    153 /* Declarations of local functions.  */
    154 static void process_file (int fd, Elf *elf, const char *prefix,
    155 			  const char *fname, bool only_one);
    156 static void process_elf_file (Elf *elf, const char *prefix, const char *fname,
    157 			      bool only_one);
    158 static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
    159 static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
    160 static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
    161 static void print_scngrp (Ebl *ebl, GElf_Ehdr *ehdr);
    162 static void print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr);
    163 static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
    164 static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
    165 			       GElf_Shdr *shdr);
    166 static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
    167 				GElf_Shdr *shdr);
    168 static void print_symtab (Ebl *ebl, GElf_Ehdr *ehdr, int type);
    169 static void handle_symtab (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
    170 			   GElf_Shdr *shdr);
    171 static void print_verinfo (Ebl *ebl, GElf_Ehdr *ehdr);
    172 static void handle_verneed (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
    173 			    GElf_Shdr *shdr);
    174 static void handle_verdef (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
    175 			   GElf_Shdr *shdr);
    176 static void handle_versym (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
    177 			   GElf_Shdr *shdr);
    178 static void print_debug (Ebl *ebl, GElf_Ehdr *ehdr);
    179 static void handle_hash (Ebl *ebl, GElf_Ehdr *ehdr);
    180 static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
    181 static void print_liblist (Ebl *ebl, GElf_Ehdr *ehdr);
    182 
    183 
    184 int
    185 main (int argc, char *argv[])
    186 {
    187   int remaining;
    188   bool only_one;
    189 
    190   /* Set locale.  */
    191   setlocale (LC_ALL, "");
    192 
    193   /* Initialize the message catalog.  */
    194   textdomain (PACKAGE);
    195 
    196   /* Parse and process arguments.  */
    197   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
    198 
    199   /* If no control option or no ELF file is given punt.  */
    200   if ((any_control_option == 0 && print_debug_sections == 0)
    201       || remaining >= argc)
    202     {
    203       argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
    204 		 program_invocation_short_name);
    205       exit (1);
    206     }
    207 
    208   /* Before we start tell the ELF library which version we are using.  */
    209   elf_version (EV_CURRENT);
    210 
    211   /* Now process all the files given at the command line.  */
    212   only_one = remaining + 1 == argc;
    213   do
    214     {
    215       int fd;
    216       Elf *elf;
    217 
    218       /* Open the file.  */
    219       fd = open (argv[remaining], O_RDONLY);
    220       if (fd == -1)
    221 	{
    222 	  error (0, errno, gettext ("cannot open input file"));
    223 	  continue;
    224 	}
    225 
    226       /* Create an `Elf' descriptor.  */
    227       elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
    228       if (elf == NULL)
    229 	error (0, 0, gettext ("cannot generate Elf descriptor: %s\n"),
    230 	       elf_errmsg (-1));
    231       else
    232 	{
    233 	  process_file (fd, elf, NULL, argv[remaining], only_one);
    234 
    235 	  /* Now we can close the descriptor.  */
    236 	  if (elf_end (elf) != 0)
    237 	    error (0, 0, gettext ("error while closing Elf descriptor: %s"),
    238 		   elf_errmsg (-1));
    239 	}
    240 
    241       close (fd);
    242     }
    243   while (++remaining < argc);
    244 
    245   return error_message_count != 0;
    246 }
    247 
    248 
    249 /* Handle program arguments.  */
    250 static error_t
    251 parse_opt (int key, char *arg, struct argp_state *state)
    252 {
    253   switch (key)
    254     {
    255     case 'a':
    256       print_file_header = true;
    257       print_program_header = true;
    258       print_relocations = true;
    259       print_section_header = true;
    260       print_symbol_table = true;
    261       print_version_info = true;
    262       print_dynamic_table = true;
    263       print_section_groups = true;
    264       print_histogram = true;
    265       print_arch = true;
    266       print_notes = true;
    267       any_control_option = true;
    268       break;
    269     case 'A':
    270       print_arch = true;
    271       any_control_option = true;
    272       break;
    273     case 'd':
    274       print_dynamic_table = true;
    275       any_control_option = true;
    276       break;
    277     case 'g':
    278       print_section_groups = true;
    279       any_control_option = true;
    280       break;
    281     case 'h':
    282       print_file_header = true;
    283       any_control_option = true;
    284       break;
    285     case 'I':
    286       print_histogram = true;
    287       any_control_option = true;
    288       break;
    289     case 'l':
    290       print_program_header = true;
    291       any_control_option = true;
    292       break;
    293     case 'n':
    294       print_notes = true;
    295       any_control_option = true;
    296       break;
    297     case 'r':
    298       print_relocations = true;
    299       any_control_option = true;
    300      break;
    301     case 'S':
    302       print_section_header = true;
    303       any_control_option = true;
    304       break;
    305     case 's':
    306       print_symbol_table = true;
    307       any_control_option = true;
    308       break;
    309     case 'V':
    310       print_version_info = true;
    311       any_control_option = true;
    312       break;
    313     case 'w':
    314       if (arg == NULL)
    315 	print_debug_sections = section_all;
    316       else if (strcmp (arg, "abbrev") == 0)
    317 	print_debug_sections |= section_abbrev;
    318       else if (strcmp (arg, "aranges") == 0)
    319 	print_debug_sections |= section_aranges;
    320       else if (strcmp (arg, "frame") == 0)
    321 	print_debug_sections |= section_frame;
    322       else if (strcmp (arg, "info") == 0)
    323 	print_debug_sections |= section_info;
    324       else if (strcmp (arg, "loc") == 0)
    325 	print_debug_sections |= section_loc;
    326       else if (strcmp (arg, "line") == 0)
    327 	print_debug_sections |= section_line;
    328       else if (strcmp (arg, "pubnames") == 0)
    329 	print_debug_sections |= section_pubnames;
    330       else if (strcmp (arg, "str") == 0)
    331 	print_debug_sections |= section_str;
    332       else if (strcmp (arg, "macinfo") == 0)
    333 	print_debug_sections |= section_macinfo;
    334       else
    335 	{
    336 	  fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
    337 		   arg);
    338 	  argp_help (&argp, stderr, ARGP_HELP_SEE,
    339 		     program_invocation_short_name);
    340 	  exit (1);
    341 	}
    342       break;
    343     default:
    344       return ARGP_ERR_UNKNOWN;
    345     }
    346   return 0;
    347 }
    348 
    349 
    350 static char *
    351 more_help (int key, const char *text, void *input)
    352 {
    353   char *buf;
    354 
    355   switch (key)
    356     {
    357     case ARGP_KEY_HELP_EXTRA:
    358       /* We print some extra information.  */
    359       if (asprintf (&buf, gettext ("Please report bugs to %s.\n"),
    360 		    PACKAGE_BUGREPORT) < 0)
    361 	buf = NULL;
    362       return buf;
    363 
    364     default:
    365       break;
    366     }
    367   return (char *) text;
    368 }
    369 
    370 
    371 /* Print the version information.  */
    372 static void
    373 print_version (FILE *stream, struct argp_state *state)
    374 {
    375   fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, VERSION);
    376   fprintf (stream, gettext ("\
    377 Copyright (C) %s Red Hat, Inc.\n\
    378 This is free software; see the source for copying conditions.  There is NO\n\
    379 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
    380 "), "2004");
    381   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
    382 }
    383 
    384 
    385 /* Process one file.  */
    386 static void
    387 process_file (int fd, Elf *elf, const char *prefix, const char *fname,
    388 	      bool only_one)
    389 {
    390   /* We can handle two types of files: ELF files and archives.  */
    391   Elf_Kind kind = elf_kind (elf);
    392   struct stat64 st;
    393 
    394   switch (kind)
    395     {
    396     case ELF_K_ELF:
    397       /* Yes!  It's an ELF file.  */
    398       process_elf_file (elf, prefix, fname, only_one);
    399       break;
    400 
    401     case ELF_K_AR:
    402       {
    403 	Elf *subelf;
    404 	Elf_Cmd cmd = ELF_C_READ_MMAP;
    405 	size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
    406 	size_t fname_len = strlen (fname) + 1;
    407 	char new_prefix[prefix_len + 1 + fname_len];
    408 	char *cp = new_prefix;
    409 
    410 	/* Create the full name of the file.  */
    411 	if (prefix != NULL)
    412 	  {
    413 	    cp = mempcpy (cp, prefix, prefix_len);
    414 	    *cp++ = ':';
    415 	  }
    416 	memcpy (cp, fname, fname_len);
    417 
    418 	/* It's an archive.  We process each file in it.  */
    419 	while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
    420 	  {
    421 	    kind = elf_kind (subelf);
    422 
    423 	    /* Call this function recursively.  */
    424 	    if (kind == ELF_K_ELF || kind == ELF_K_AR)
    425 	      {
    426 		Elf_Arhdr *arhdr = elf_getarhdr (subelf);
    427 		assert (arhdr != NULL);
    428 
    429 		process_file (fd, subelf, new_prefix, arhdr->ar_name, false);
    430 	      }
    431 
    432 	    /* Get next archive element.  */
    433 	    cmd = elf_next (subelf);
    434 	    if (elf_end (subelf) != 0)
    435 	      error (0, 0,
    436 		     gettext (" error while freeing sub-ELF descriptor: %s\n"),
    437 		     elf_errmsg (-1));
    438 	  }
    439       }
    440       break;
    441 
    442     default:
    443       if (fstat64 (fd, &st) != 0)
    444 	error (0, errno, gettext ("cannot stat input file"));
    445       else if (st.st_size == 0)
    446 	error (0, 0, gettext ("input file is empty"));
    447       else
    448 	/* We cannot do anything.  */
    449 	error (0, 0, gettext ("\
    450 Not an ELF file - it has the wrong magic bytes at the start"));
    451       break;
    452     }
    453 }
    454 
    455 
    456 /* Process one file.  */
    457 static void
    458 process_elf_file (Elf *elf, const char *prefix, const char *fname,
    459 		  bool only_one)
    460 {
    461   GElf_Ehdr ehdr_mem;
    462   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
    463   Ebl *ebl;
    464 
    465   /* Print the file name.  */
    466   if (!only_one)
    467     {
    468       if (prefix != NULL)
    469 	printf ("\n%s(%s):\n\n", prefix, fname);
    470       else
    471 	printf ("\n%s:\n\n", fname);
    472     }
    473 
    474   if (ehdr == NULL)
    475     {
    476       error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
    477       return;
    478     }
    479 
    480   ebl = ebl_openbackend (elf);
    481   if (ebl == NULL)
    482     {
    483       error (0, errno, gettext ("cannot create EBL handle"));
    484       return;
    485     }
    486 
    487   /* Determine the number of sections.  */
    488   if (elf_getshnum (ebl->elf, &shnum) < 0)
    489     error (EXIT_FAILURE, 0,
    490 	   gettext ("cannot determine number of sections: %s"),
    491 	   elf_errmsg (-1));
    492 
    493   if (print_file_header)
    494     print_ehdr (ebl, ehdr);
    495   if (print_section_header)
    496     print_shdr (ebl, ehdr);
    497   if (print_program_header)
    498     print_phdr (ebl, ehdr);
    499   if (print_section_groups)
    500     print_scngrp (ebl, ehdr);
    501   if (print_dynamic_table)
    502     print_dynamic (ebl, ehdr);
    503   if (print_relocations)
    504     print_relocs (ebl, ehdr);
    505   if (print_histogram)
    506     handle_hash (ebl, ehdr);
    507   if (print_symbol_table)
    508     print_symtab (ebl, ehdr, SHT_DYNSYM);
    509   if (print_version_info)
    510     print_verinfo (ebl, ehdr);
    511   if (print_symbol_table)
    512     print_symtab (ebl, ehdr, SHT_SYMTAB);
    513   if (print_arch)
    514     print_liblist (ebl, ehdr);
    515   if (print_debug_sections != 0)
    516     print_debug (ebl, ehdr);
    517   if (print_notes)
    518     handle_notes (ebl, ehdr);
    519 
    520   ebl_closebackend (ebl);
    521 }
    522 
    523 
    524 /* Print file type.  */
    525 static void
    526 print_file_type (unsigned short int e_type)
    527 {
    528   if (e_type <= ET_CORE)
    529     {
    530       static const char *knowntypes[] =
    531       {
    532 	N_("NONE (None)"),
    533 	N_("REL (Relocatable file)"),
    534 	N_("EXEC (Executable file)"),
    535 	N_("DYN (Shared object file)"),
    536 	N_("CORE (Core file)")
    537       };
    538       puts (gettext (knowntypes[e_type]));
    539     }
    540   else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
    541     printf (gettext ("OS Specific: (%x)\n"),  e_type);
    542   else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
    543     printf (gettext ("Processor Specific: (%x)\n"),  e_type);
    544   else
    545     puts ("???");
    546 }
    547 
    548 
    549 /* Print ELF header.  */
    550 static void
    551 print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
    552 {
    553   char buf[512];
    554   size_t cnt;
    555 
    556   fputs_unlocked (gettext ("ELF Header:\n  Magic:  "), stdout);
    557   for (cnt = 0; cnt < EI_NIDENT; ++cnt)
    558     printf (" %02hhx", ehdr->e_ident[cnt]);
    559 
    560   printf (gettext ("\n  Class:                             %s\n"),
    561 	  ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
    562 	  : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
    563 	  : "\?\?\?");
    564 
    565   printf (gettext ("  Data:                              %s\n"),
    566 	  ehdr->e_ident[EI_DATA] == ELFDATA2LSB
    567 	  ? "2's complement, little endian"
    568 	  : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
    569 	  ? "2's complement, big endian" : "\?\?\?");
    570 
    571   printf (gettext ("  Version:                           %hhd %s\n"),
    572 	  ehdr->e_ident[EI_VERSION],
    573 	  ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
    574 	  : "(\?\?\?)");
    575 
    576   printf (gettext ("  OS/ABI:                            %s\n"),
    577 	  ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
    578 
    579   printf (gettext ("  ABI Version:                       %hhd\n"),
    580 	  ehdr->e_ident[EI_ABIVERSION]);
    581 
    582   fputs_unlocked (gettext ("  Type:                              "), stdout);
    583   print_file_type (ehdr->e_type);
    584 
    585   printf (gettext ("  Machine:                           %s\n"), ebl->name);
    586 
    587   printf (gettext ("  Version:                           %d %s\n"),
    588 	  ehdr->e_version,
    589 	  ehdr->e_version  == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
    590 
    591   printf (gettext ("  Entry point address:               %#" PRIx64 "\n"),
    592 	  ehdr->e_entry);
    593 
    594   printf (gettext ("  Start of program headers:          %" PRId64 " %s\n"),
    595 	  ehdr->e_phoff, gettext ("(bytes into file)"));
    596 
    597   printf (gettext ("  Start of section headers:          %" PRId64 " %s\n"),
    598 	  ehdr->e_shoff, gettext ("(bytes into file)"));
    599 
    600   printf (gettext ("  Flags:                             %s\n"),
    601 	  ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
    602 
    603   printf (gettext ("  Size of this header:               %" PRId16 " %s\n"),
    604 	  ehdr->e_ehsize, gettext ("(bytes)"));
    605 
    606   printf (gettext ("  Size of program header entries:    %" PRId16 " %s\n"),
    607 	  ehdr->e_phentsize, gettext ("(bytes)"));
    608 
    609   printf (gettext ("  Number of program headers entries: %" PRId16 "\n"),
    610 	  ehdr->e_phnum);
    611 
    612   printf (gettext ("  Size of section header entries:    %" PRId16 " %s\n"),
    613 	  ehdr->e_shentsize, gettext ("(bytes)"));
    614 
    615   printf (gettext ("  Number of section headers entries: %" PRId16),
    616 	  ehdr->e_shnum);
    617   if (ehdr->e_shnum == 0)
    618     {
    619       GElf_Shdr shdr_mem;
    620       GElf_Shdr *shdr;
    621 
    622       shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
    623       if (shdr != NULL)
    624 	printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
    625 		(uint32_t) shdr->sh_size);
    626       else
    627 	fputs_unlocked (gettext (" ([0] not available)"), stdout);
    628     }
    629   fputc_unlocked ('\n', stdout);
    630 
    631   if (ehdr->e_shstrndx == SHN_XINDEX)
    632     {
    633       GElf_Shdr shdr_mem;
    634       GElf_Shdr *shdr;
    635 
    636       shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
    637       if (shdr != NULL)
    638 	/* We managed to get the zeroth section.  */
    639 	snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
    640 		  (uint32_t) shdr->sh_link);
    641       else
    642 	{
    643 	  strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
    644 	  buf[sizeof (buf) - 1] = '\0';
    645 	}
    646 
    647       printf (gettext ("  Section header string table index: XINDEX%s\n\n"),
    648 	      buf);
    649     }
    650   else
    651     printf (gettext ("  Section header string table index: %" PRId16 "\n\n"),
    652 	    ehdr->e_shstrndx);
    653 }
    654 
    655 
    656 static const char *
    657 get_visibility_type (int value)
    658 {
    659   switch (value)
    660     {
    661     case STV_DEFAULT:
    662       return "DEFAULT";
    663     case STV_INTERNAL:
    664       return "INTERNAL";
    665     case STV_HIDDEN:
    666       return "HIDDEN";
    667     case STV_PROTECTED:
    668       return "PROTECTED";
    669     default:
    670       return "???";
    671     }
    672 }
    673 
    674 
    675 /* Print the section headers.  */
    676 static void
    677 print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
    678 {
    679   size_t cnt;
    680   size_t shstrndx;
    681 
    682   if (! print_file_header)
    683     printf (gettext ("\
    684 There are %d section headers, starting at offset %#" PRIx64 ":\n\
    685 \n"),
    686 	    ehdr->e_shnum, ehdr->e_shoff);
    687 
    688   /* Get the section header string table index.  */
    689   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
    690     error (EXIT_FAILURE, 0,
    691 	   gettext ("cannot get section header string table index"));
    692 
    693   puts (gettext ("Section Headers:"));
    694 
    695   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
    696     puts (gettext ("[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al"));
    697   else
    698     puts (gettext ("[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al"));
    699 
    700   for (cnt = 0; cnt < shnum; ++cnt)
    701     {
    702       char buf[128];
    703       char flagbuf[20];
    704       char *cp;
    705       Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
    706       GElf_Shdr shdr_mem;
    707       GElf_Shdr *shdr;
    708 
    709       if (scn == NULL)
    710 	error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
    711 	       elf_errmsg (-1));
    712 
    713       /* Get the section header.  */
    714       shdr = gelf_getshdr (scn, &shdr_mem);
    715       if (shdr == NULL)
    716 	error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
    717 	       elf_errmsg (-1));
    718 
    719       cp = flagbuf;
    720       if (shdr->sh_flags & SHF_WRITE)
    721 	*cp++ = 'W';
    722       if (shdr->sh_flags & SHF_ALLOC)
    723 	*cp++ = 'A';
    724       if (shdr->sh_flags & SHF_EXECINSTR)
    725 	*cp++ = 'X';
    726       if (shdr->sh_flags & SHF_MERGE)
    727 	*cp++ = 'M';
    728       if (shdr->sh_flags & SHF_STRINGS)
    729 	*cp++ = 'S';
    730       if (shdr->sh_flags & SHF_INFO_LINK)
    731 	*cp++ = 'I';
    732       if (shdr->sh_flags & SHF_LINK_ORDER)
    733 	*cp++ = 'L';
    734       if (shdr->sh_flags & SHF_OS_NONCONFORMING)
    735 	*cp++ = 'N';
    736       if (shdr->sh_flags & SHF_GROUP)
    737 	*cp++ = 'G';
    738       if (shdr->sh_flags & SHF_TLS)
    739 	*cp++ = 'T';
    740       if (shdr->sh_flags & SHF_ORDERED)
    741 	*cp++ = 'O';
    742       if (shdr->sh_flags & SHF_EXCLUDE)
    743 	*cp++ = 'E';
    744       *cp = '\0';
    745 
    746       printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
    747 	      " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
    748 	      " %2" PRId64 "\n",
    749 	      cnt,
    750 	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
    751 	      ?: "<corrupt>",
    752 	      ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
    753 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
    754 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
    755 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
    756 	      shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
    757 	      shdr->sh_addralign);
    758     }
    759 
    760   fputc_unlocked ('\n', stdout);
    761 }
    762 
    763 
    764 /* Print the program header.  */
    765 static void
    766 print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
    767 {
    768   size_t cnt;
    769   size_t shstrndx;
    770 
    771   if (ehdr->e_phnum == 0)
    772     /* No program header, this is OK in relocatable objects.  */
    773     return;
    774 
    775   puts (gettext ("Program Headers:"));
    776   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
    777     puts (gettext ("\
    778   Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"));
    779   else
    780     puts (gettext ("\
    781   Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align"));
    782 
    783   /* Process all program headers.  */
    784   bool has_relro = false;
    785   GElf_Addr relro_from = 0;
    786   GElf_Addr relro_to = 0;
    787   for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
    788     {
    789       char buf[128];
    790       GElf_Phdr mem;
    791       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
    792 
    793       /* If for some reason the header cannot be returned show this.  */
    794       if (phdr == NULL)
    795 	{
    796 	  puts ("  ???");
    797 	  continue;
    798 	}
    799 
    800       printf ("  %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
    801 	      " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
    802 	      ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
    803 	      phdr->p_offset,
    804 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
    805 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
    806 	      phdr->p_filesz,
    807 	      phdr->p_memsz,
    808 	      phdr->p_flags & PF_R ? 'R' : ' ',
    809 	      phdr->p_flags & PF_W ? 'W' : ' ',
    810 	      phdr->p_flags & PF_X ? 'E' : ' ',
    811 	      phdr->p_align);
    812 
    813       if (phdr->p_type == PT_INTERP)
    814 	{
    815 	  /* We can show the user the name of the interpreter.  */
    816 	  size_t maxsize;
    817 	  char *filedata = elf_rawfile (ebl->elf, &maxsize);
    818 
    819 	  if (filedata != NULL && phdr->p_offset < maxsize)
    820 	    printf (gettext ("\t[Requesting program interpreter: %s]\n"),
    821 		    filedata + phdr->p_offset);
    822 	}
    823       else if (phdr->p_type == PT_GNU_RELRO)
    824 	{
    825 	  has_relro = true;
    826 	  relro_from = phdr->p_vaddr;
    827 	  relro_to = relro_from + phdr->p_memsz;
    828 	}
    829     }
    830 
    831   /* Get the section header string table index.  */
    832   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
    833     error (EXIT_FAILURE, 0,
    834 	   gettext ("cannot get section header string table index"));
    835 
    836   puts (gettext ("\n Section to Segment mapping:\n  Segment Sections..."));
    837 
    838   for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
    839     {
    840       GElf_Phdr phdr_mem;
    841       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
    842       size_t inner;
    843 
    844       /* Print the segment number.  */
    845       printf ("   %2.2zu     ", cnt);
    846 
    847       /* This must not happen.  */
    848       if (phdr == NULL)
    849 	error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
    850 	       elf_errmsg (-1));
    851 
    852       /* Iterate over the sections.  */
    853       bool in_relro = false;
    854       for (inner = 1; inner < shnum; ++inner)
    855 	{
    856 	  Elf_Scn *scn = elf_getscn (ebl->elf, inner);
    857 	  GElf_Shdr shdr_mem;
    858 	  GElf_Shdr *shdr;
    859 
    860 	  /* It should not happen.  */
    861 	  if (scn == NULL)
    862 	    error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
    863 		   elf_errmsg (-1));
    864 
    865 	  /* Get the section header.  */
    866 	  shdr = gelf_getshdr (scn, &shdr_mem);
    867 	  if (shdr == NULL)
    868 	    error (EXIT_FAILURE, 0,
    869 		   gettext ("cannot get section header: %s"),
    870 		   elf_errmsg (-1));
    871 
    872 	  if (shdr->sh_size > 0
    873 	      /* Compare allocated sections by VMA, unallocated
    874 		 sections by file offset.  */
    875 	      && (shdr->sh_flags & SHF_ALLOC
    876 		  ? (shdr->sh_addr >= phdr->p_vaddr
    877 		     && (shdr->sh_addr + shdr->sh_size
    878 			 <= phdr->p_vaddr + phdr->p_memsz))
    879 		  : (shdr->sh_offset >= phdr->p_offset
    880 		     && (shdr->sh_offset + shdr->sh_size
    881 			 <= phdr->p_offset + phdr->p_filesz))))
    882 	    {
    883 	      if (has_relro && !in_relro
    884 		  && shdr->sh_addr >= relro_from
    885 		  && shdr->sh_addr + shdr->sh_size <= relro_to)
    886 		{
    887 		  fputs_unlocked (" [RELRO:", stdout);
    888 		  in_relro = true;
    889 		}
    890 	      else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
    891 		{
    892 		  fputs_unlocked ("]", stdout);
    893 		  in_relro =  false;
    894 		}
    895 	      else if (has_relro && in_relro
    896 		       && shdr->sh_addr + shdr->sh_size > relro_to)
    897 		fputs_unlocked ("] <RELRO:", stdout);
    898 
    899 	      printf (" %s",
    900 		      elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
    901 
    902 	      /* Signal that this sectin is only partially covered.  */
    903 	      if (has_relro && in_relro
    904 		       && shdr->sh_addr + shdr->sh_size > relro_to)
    905 		{
    906 		  fputs_unlocked (">", stdout);
    907 		  in_relro =  false;
    908 		}
    909 	    }
    910 	}
    911       if (in_relro)
    912 	fputs_unlocked ("]", stdout);
    913 
    914       /* Finish the line.  */
    915       fputc_unlocked ('\n', stdout);
    916     }
    917 }
    918 
    919 
    920 static void
    921 handle_scngrp (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
    922 {
    923   Elf_Data *data;
    924   Elf32_Word *grpref;
    925   Elf_Scn *symscn;
    926   GElf_Shdr symshdr_mem;
    927   GElf_Shdr *symshdr;
    928   Elf_Data *symdata;
    929   GElf_Sym sym_mem;
    930   size_t cnt;
    931   size_t shstrndx;
    932 
    933   /* Get the data of the section.  */
    934   data = elf_getdata (scn, NULL);
    935 
    936   symscn = elf_getscn (ebl->elf, shdr->sh_link);
    937   symshdr = gelf_getshdr (symscn, &symshdr_mem);
    938   symdata = elf_getdata (symscn, NULL);
    939 
    940   if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
    941       || symdata == NULL)
    942     return;
    943 
    944   /* Get the section header string table index.  */
    945   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
    946     error (EXIT_FAILURE, 0,
    947 	   gettext ("cannot get section header string table index"));
    948 
    949   grpref = (Elf32_Word *) data->d_buf;
    950 
    951   printf ((grpref[0] & GRP_COMDAT)
    952 	  ? ngettext ("\
    953 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
    954 		      "\
    955 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
    956 		      data->d_size / sizeof (Elf32_Word) - 1)
    957 	  : ngettext ("\
    958 \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
    959 \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
    960 		      data->d_size / sizeof (Elf32_Word) - 1),
    961 	  elf_ndxscn (scn),
    962 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
    963 	  elf_strptr (ebl->elf, symshdr->sh_link,
    964 		      gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name)
    965 	  ?: gettext ("<INVALID SYMBOL>"),
    966 	  data->d_size / sizeof (Elf32_Word) - 1);
    967 
    968   for (cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
    969     {
    970       GElf_Shdr grpshdr_mem;
    971       GElf_Shdr *grpshdr;
    972 
    973       grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
    974 			      &grpshdr_mem);
    975 
    976       if (grpshdr == NULL)
    977 	printf (gettext ("  [%2u] <INVALID SECTION>\n"), grpref[cnt]);
    978       else
    979 	printf ("  [%2u] %s\n",
    980 		grpref[cnt],
    981 		elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name)
    982 		?: gettext ("<INVALID SECTION>"));
    983     }
    984 }
    985 
    986 
    987 static void
    988 print_scngrp (Ebl *ebl, GElf_Ehdr *ehdr)
    989 {
    990   /* Find all relocation sections and handle them.  */
    991   Elf_Scn *scn = NULL;
    992 
    993   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    994     {
    995        /* Handle the section if it is a symbol table.  */
    996       GElf_Shdr shdr_mem;
    997       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    998 
    999       if (shdr != NULL && shdr->sh_type == SHT_GROUP)
   1000 	handle_scngrp (ebl, ehdr, scn, shdr);
   1001     }
   1002 }
   1003 
   1004 
   1005 static const struct flags
   1006 {
   1007   int mask;
   1008   const char *str;
   1009 } dt_flags[] =
   1010   {
   1011     { DF_ORIGIN, "ORIGIN" },
   1012     { DF_SYMBOLIC, "SYMBOLIC" },
   1013     { DF_TEXTREL, "TEXTREL" },
   1014     { DF_BIND_NOW, "BIND_NOW" },
   1015     { DF_STATIC_TLS, "STATIC_TLS" }
   1016   };
   1017 static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
   1018 
   1019 static const struct flags dt_flags_1[] =
   1020   {
   1021     { DF_1_NOW, "NOW" },
   1022     { DF_1_GLOBAL, "GLOBAL" },
   1023     { DF_1_GROUP, "GROUP" },
   1024     { DF_1_NODELETE, "NODELETE" },
   1025     { DF_1_LOADFLTR, "LOADFLTR" },
   1026     { DF_1_INITFIRST, "INITFIRST" },
   1027     { DF_1_NOOPEN, "NOOPEN" },
   1028     { DF_1_ORIGIN, "ORIGIN" },
   1029     { DF_1_DIRECT, "DIRECT" },
   1030     { DF_1_TRANS, "TRANS" },
   1031     { DF_1_INTERPOSE, "INTERPOSE" },
   1032     { DF_1_NODEFLIB, "NODEFLIB" },
   1033     { DF_1_NODUMP, "NODUMP" },
   1034     { DF_1_CONFALT, "CONFALT" },
   1035     { DF_1_ENDFILTEE, "ENDFILTEE" },
   1036     { DF_1_DISPRELDNE, "DISPRELDNE" },
   1037     { DF_1_DISPRELPND, "DISPRELPND" },
   1038   };
   1039 static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
   1040 
   1041 static const struct flags dt_feature_1[] =
   1042   {
   1043     { DTF_1_PARINIT, "PARINIT" },
   1044     { DTF_1_CONFEXP, "CONFEXP" }
   1045   };
   1046 static const int ndt_feature_1 = (sizeof (dt_feature_1)
   1047 				  / sizeof (dt_feature_1[0]));
   1048 
   1049 static const struct flags dt_posflag_1[] =
   1050   {
   1051     { DF_P1_LAZYLOAD, "LAZYLOAD" },
   1052     { DF_P1_GROUPPERM, "GROUPPERM" }
   1053   };
   1054 static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
   1055 				  / sizeof (dt_posflag_1[0]));
   1056 
   1057 
   1058 static void
   1059 print_flags (int class, GElf_Xword d_val, const struct flags *flags,
   1060 		int nflags)
   1061 {
   1062   bool first = true;
   1063   int cnt;
   1064 
   1065   for (cnt = 0; cnt < nflags; ++cnt)
   1066     if (d_val & flags[cnt].mask)
   1067       {
   1068 	if (!first)
   1069 	  putchar_unlocked (' ');
   1070 	fputs_unlocked (flags[cnt].str, stdout);
   1071 	d_val &= ~flags[cnt].mask;
   1072 	first = false;
   1073       }
   1074 
   1075   if (d_val != 0)
   1076     {
   1077       if (!first)
   1078 	putchar_unlocked (' ');
   1079       printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
   1080     }
   1081 
   1082   putchar_unlocked ('\n');
   1083 }
   1084 
   1085 
   1086 static void
   1087 print_dt_flags (int class, GElf_Xword d_val)
   1088 {
   1089   print_flags (class, d_val, dt_flags, ndt_flags);
   1090 }
   1091 
   1092 
   1093 static void
   1094 print_dt_flags_1 (int class, GElf_Xword d_val)
   1095 {
   1096   print_flags (class, d_val, dt_flags_1, ndt_flags_1);
   1097 }
   1098 
   1099 
   1100 static void
   1101 print_dt_feature_1 (int class, GElf_Xword d_val)
   1102 {
   1103   print_flags (class, d_val, dt_feature_1, ndt_feature_1);
   1104 }
   1105 
   1106 
   1107 static void
   1108 print_dt_posflag_1 (int class, GElf_Xword d_val)
   1109 {
   1110   print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
   1111 }
   1112 
   1113 
   1114 static void
   1115 handle_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   1116 {
   1117   int class = gelf_getclass (ebl->elf);
   1118   GElf_Shdr glink;
   1119   Elf_Data *data;
   1120   size_t cnt;
   1121   size_t shstrndx;
   1122 
   1123   /* Get the data of the section.  */
   1124   data = elf_getdata (scn, NULL);
   1125   if (data == NULL)
   1126     return;
   1127 
   1128   /* Get the section header string table index.  */
   1129   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
   1130     error (EXIT_FAILURE, 0,
   1131 	   gettext ("cannot get section header string table index"));
   1132 
   1133   printf (ngettext ("\
   1134 \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   1135 		    "\
   1136 \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   1137 		    shdr->sh_size / shdr->sh_entsize),
   1138 	  (unsigned long int) (shdr->sh_size / shdr->sh_entsize),
   1139 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   1140 	  shdr->sh_offset,
   1141 	  (int) shdr->sh_link,
   1142 	  elf_strptr (ebl->elf, shstrndx,
   1143 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   1144 				    &glink)->sh_name));
   1145   fputs_unlocked (gettext ("  Type              Value\n"), stdout);
   1146 
   1147   for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
   1148     {
   1149       char buf[64];
   1150       GElf_Dyn dynmem;
   1151       GElf_Dyn *dyn;
   1152 
   1153       dyn = gelf_getdyn (data, cnt, &dynmem);
   1154       if (dyn == NULL)
   1155 	break;
   1156 
   1157       printf ("  %-17s ",
   1158 	      ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
   1159 
   1160       switch (dyn->d_tag)
   1161 	{
   1162 	case DT_NULL:
   1163 	case DT_DEBUG:
   1164 	case DT_BIND_NOW:
   1165 	case DT_TEXTREL:
   1166 	  /* No further output.  */
   1167 	  fputc ('\n', stdout);
   1168 	  break;
   1169 
   1170 	case DT_NEEDED:
   1171 	  printf (gettext ("Shared library: [%s]\n"),
   1172 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1173 	  break;
   1174 
   1175 	case DT_SONAME:
   1176 	  printf (gettext ("Library soname: [%s]\n"),
   1177 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1178 	  break;
   1179 
   1180 	case DT_RPATH:
   1181 	  printf (gettext ("Library rpath: [%s]\n"),
   1182 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1183 	  break;
   1184 
   1185 	case DT_RUNPATH:
   1186 	  printf (gettext ("Library runpath: [%s]\n"),
   1187 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
   1188 	  break;
   1189 
   1190 	case DT_PLTRELSZ:
   1191 	case DT_RELASZ:
   1192 	case DT_STRSZ:
   1193 	case DT_RELSZ:
   1194 	case DT_RELAENT:
   1195 	case DT_SYMENT:
   1196 	case DT_RELENT:
   1197 	case DT_PLTPADSZ:
   1198 	case DT_MOVEENT:
   1199 	case DT_MOVESZ:
   1200 	case DT_INIT_ARRAYSZ:
   1201 	case DT_FINI_ARRAYSZ:
   1202 	case DT_SYMINSZ:
   1203 	case DT_SYMINENT:
   1204 	case DT_GNU_CONFLICTSZ:
   1205 	case DT_GNU_LIBLISTSZ:
   1206 	  printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
   1207 	  break;
   1208 
   1209 	case DT_VERDEFNUM:
   1210 	case DT_VERNEEDNUM:
   1211 	case DT_RELACOUNT:
   1212 	case DT_RELCOUNT:
   1213 	  printf ("%" PRId64 "\n", dyn->d_un.d_val);
   1214 	  break;
   1215 
   1216 	case DT_PLTREL:
   1217 	  puts (ebl_dynamic_tag_name (ebl, dyn->d_un.d_val, NULL, 0));
   1218 	  break;
   1219 
   1220 	case DT_FLAGS:
   1221 	  print_dt_flags (class, dyn->d_un.d_val);
   1222 	  break;
   1223 
   1224 	case DT_FLAGS_1:
   1225 	  print_dt_flags_1 (class, dyn->d_un.d_val);
   1226 	  break;
   1227 
   1228 	case DT_FEATURE_1:
   1229 	  print_dt_feature_1 (class, dyn->d_un.d_val);
   1230 	  break;
   1231 
   1232 	case DT_POSFLAG_1:
   1233 	  print_dt_posflag_1 (class, dyn->d_un.d_val);
   1234 	  break;
   1235 
   1236 	default:
   1237 	  printf ("%#0*" PRIx64 "\n",
   1238 		  class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
   1239 	  break;
   1240 	}
   1241     }
   1242 }
   1243 
   1244 
   1245 /* Print the dynamic segment.  */
   1246 static void
   1247 print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr)
   1248 {
   1249   /* Find all relocation sections and handle them.  */
   1250   Elf_Scn *scn = NULL;
   1251 
   1252   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   1253     {
   1254        /* Handle the section if it is a symbol table.  */
   1255       GElf_Shdr shdr_mem;
   1256       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1257 
   1258       if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
   1259 	{
   1260 	  handle_dynamic (ebl, ehdr, scn, shdr);
   1261 	  break;
   1262 	}
   1263     }
   1264 }
   1265 
   1266 
   1267 /* Print relocations.  */
   1268 static void
   1269 print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
   1270 {
   1271   /* Find all relocation sections and handle them.  */
   1272   Elf_Scn *scn = NULL;
   1273 
   1274   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   1275     {
   1276        /* Handle the section if it is a symbol table.  */
   1277       GElf_Shdr shdr_mem;
   1278       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1279 
   1280       if (shdr != NULL)
   1281 	{
   1282 	  if (shdr->sh_type == SHT_REL)
   1283 	    handle_relocs_rel (ebl, ehdr, scn, shdr);
   1284 	  else if (shdr->sh_type == SHT_RELA)
   1285 	    handle_relocs_rela (ebl, ehdr, scn, shdr);
   1286 	}
   1287     }
   1288 }
   1289 
   1290 
   1291 /* Handle a relocation section.  */
   1292 static void
   1293 handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   1294 {
   1295   int class = gelf_getclass (ebl->elf);
   1296   int nentries = shdr->sh_size / shdr->sh_entsize;
   1297   int cnt;
   1298   Elf_Data *data;
   1299   Elf_Scn *symscn;
   1300   GElf_Shdr symshdr_mem;
   1301   GElf_Shdr *symshdr;
   1302   Elf_Data *symdata;
   1303   GElf_Shdr destshdr_mem;
   1304   GElf_Shdr *destshdr;
   1305   Elf_Scn *xndxscn;
   1306   Elf_Data *xndxdata = NULL;
   1307   size_t shstrndx;
   1308 
   1309   /* Get the data of the section.  */
   1310   data = elf_getdata (scn, NULL);
   1311   if (data == NULL)
   1312     return;
   1313 
   1314   /* Get the symbol table information.  */
   1315   symscn = elf_getscn (ebl->elf, shdr->sh_link);
   1316   symshdr = gelf_getshdr (symscn, &symshdr_mem);
   1317   symdata = elf_getdata (symscn, NULL);
   1318 
   1319   /* Get the section header of the section the relocations are for.  */
   1320   destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
   1321 			   &destshdr_mem);
   1322 
   1323   if (symshdr == NULL || symdata == NULL || destshdr == NULL)
   1324     {
   1325       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
   1326 	      shdr->sh_offset);
   1327       return;
   1328     }
   1329 
   1330   /* Search for the optional extended section index table.  */
   1331   xndxscn = NULL;
   1332   while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
   1333     {
   1334       GElf_Shdr xndxshdr_mem;
   1335       GElf_Shdr *xndxshdr;
   1336 
   1337       xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
   1338       if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
   1339 	  && xndxshdr->sh_link == elf_ndxscn (symscn))
   1340 	{
   1341 	  /* Found it.  */
   1342 	  xndxdata = elf_getdata (xndxscn, NULL);
   1343 	  break;
   1344 	}
   1345     }
   1346 
   1347   /* Get the section header string table index.  */
   1348   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
   1349     error (EXIT_FAILURE, 0,
   1350 	   gettext ("cannot get section header string table index"));
   1351 
   1352   if (shdr->sh_info != 0)
   1353     printf (ngettext ("\
   1354 \nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   1355 		    "\
   1356 \nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   1357 		      nentries),
   1358 	    (unsigned int) elf_ndxscn (scn),
   1359 	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   1360 	    (unsigned int) shdr->sh_info,
   1361 	    elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
   1362 	    shdr->sh_offset,
   1363 	    nentries);
   1364   else
   1365     /* The .rel.dyn section does not refer to a specific section but
   1366        instead of section index zero.  Do not try to print a section
   1367        name.  */
   1368     printf (ngettext ("\
   1369 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   1370 		    "\
   1371 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   1372 		      nentries),
   1373 	    (unsigned int) elf_ndxscn (scn),
   1374 	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   1375 	    shdr->sh_offset,
   1376 	    nentries);
   1377   fputs_unlocked (class == ELFCLASS32
   1378 		  ? gettext ("\
   1379   Offset      Type                 Value       Name\n")
   1380 		  : gettext ("\
   1381   Offset              Type                 Value               Name\n"),
   1382 	 stdout);
   1383 
   1384   for (cnt = 0; cnt < nentries; ++cnt)
   1385     {
   1386       GElf_Rel relmem;
   1387       GElf_Rel *rel;
   1388 
   1389       rel = gelf_getrel (data, cnt, &relmem);
   1390       if (rel != NULL)
   1391 	{
   1392 	  char buf[128];
   1393 	  GElf_Sym symmem;
   1394 	  GElf_Sym *sym;
   1395 	  Elf32_Word xndx;
   1396 
   1397 	  sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (rel->r_info),
   1398 				  &symmem, &xndx);
   1399 	  if (sym == NULL)
   1400 	    printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
   1401 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1402 		    ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1403 		    /* Avoid the leading R_ which isn't carrying any
   1404 		       information.  */
   1405 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1406 					   buf, sizeof (buf)) + 2
   1407 		    : gettext ("<INVALID RELOC>"),
   1408 		    gettext ("INVALID SYMBOL"),
   1409 		    (long int) GELF_R_SYM (rel->r_info));
   1410 	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
   1411 	    printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
   1412 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1413 		    ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1414 		    /* Avoid the leading R_ which isn't carrying any
   1415 		       information.  */
   1416 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1417 					   buf, sizeof (buf)) + 2
   1418 		    : gettext ("<INVALID RELOC>"),
   1419 		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
   1420 		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
   1421 	  else
   1422 	    {
   1423 	      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
   1424 						   sym->st_shndx == SHN_XINDEX
   1425 						   ? xndx : sym->st_shndx),
   1426 				       &destshdr_mem);
   1427 
   1428 	      if (shdr == NULL)
   1429 		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
   1430 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1431 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1432 			/* Avoid the leading R_ which isn't carrying any
   1433 			   information.  */
   1434 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1435 					       buf, sizeof (buf)) + 2
   1436 			: gettext ("<INVALID RELOC>"),
   1437 			gettext ("INVALID SECTION"),
   1438 			(long int) (sym->st_shndx == SHN_XINDEX
   1439 				    ? xndx : sym->st_shndx));
   1440 	      else
   1441 		printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
   1442 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1443 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1444 			/* Avoid the leading R_ which isn't carrying any
   1445 			   information.  */
   1446 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1447 					       buf, sizeof (buf)) + 2
   1448 			: gettext ("<INVALID RELOC>"),
   1449 			class == ELFCLASS32 ? 10 : 18, sym->st_value,
   1450 			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
   1451 	    }
   1452 	}
   1453     }
   1454 }
   1455 
   1456 
   1457 /* Handle a relocation section.  */
   1458 static void
   1459 handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   1460 {
   1461   int class = gelf_getclass (ebl->elf);
   1462   int nentries = shdr->sh_size / shdr->sh_entsize;
   1463 
   1464   /* Get the data of the section.  */
   1465   Elf_Data *data = elf_getdata (scn, NULL);
   1466   if (data == NULL)
   1467     return;
   1468 
   1469   /* Get the symbol table information.  */
   1470   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
   1471   GElf_Shdr symshdr_mem;
   1472   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
   1473   Elf_Data *symdata = elf_getdata (symscn, NULL);
   1474 
   1475   /* Get the section header of the section the relocations are for.  */
   1476   GElf_Shdr destshdr_mem;
   1477   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
   1478 				      &destshdr_mem);
   1479 
   1480   if (symshdr == NULL || symdata == NULL || destshdr == NULL)
   1481     {
   1482       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
   1483 	      shdr->sh_offset);
   1484       return;
   1485     }
   1486 
   1487   /* Search for the optional extended section index table.  */
   1488   Elf_Data *xndxdata = NULL;
   1489   Elf_Scn *xndxscn = NULL;
   1490   while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
   1491     {
   1492       GElf_Shdr xndxshdr_mem;
   1493       GElf_Shdr *xndxshdr;
   1494 
   1495       xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
   1496       if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
   1497 	  && xndxshdr->sh_link == elf_ndxscn (symscn))
   1498 	{
   1499 	  /* Found it.  */
   1500 	  xndxdata = elf_getdata (xndxscn, NULL);
   1501 	  break;
   1502 	}
   1503     }
   1504 
   1505   /* Get the section header string table index.  */
   1506   size_t shstrndx;
   1507   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
   1508     error (EXIT_FAILURE, 0,
   1509 	   gettext ("cannot get section header string table index"));
   1510 
   1511   printf (ngettext ("\
   1512 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   1513 		    "\
   1514 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   1515 		    nentries),
   1516 	  elf_ndxscn (scn),
   1517 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   1518 	  (unsigned int) shdr->sh_info,
   1519 	  elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
   1520 	  shdr->sh_offset,
   1521 	  nentries);
   1522   fputs_unlocked (class == ELFCLASS32
   1523 		  ? gettext ("\
   1524   Offset      Type            Value       Addend Name\n")
   1525 		  : gettext ("\
   1526   Offset              Type            Value               Addend Name\n"),
   1527 		  stdout);
   1528 
   1529   for (int cnt = 0; cnt < nentries; ++cnt)
   1530     {
   1531       GElf_Rela relmem;
   1532       GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
   1533       if (rel != NULL)
   1534 	{
   1535 	  char buf[64];
   1536 	  GElf_Sym symmem;
   1537 	  GElf_Sym *sym;
   1538 	  Elf32_Word xndx;
   1539 
   1540 	  sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (rel->r_info),
   1541 				  &symmem, &xndx);
   1542 
   1543 	  if (sym == NULL)
   1544 	    printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
   1545 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1546 		    ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1547 		    /* Avoid the leading R_ which isn't carrying any
   1548 		       information.  */
   1549 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1550 					   buf, sizeof (buf)) + 2
   1551 		    : gettext ("<INVALID RELOC>"),
   1552 		    gettext ("INVALID SYMBOL"),
   1553 		    (long int) GELF_R_SYM (rel->r_info));
   1554 	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
   1555 	    printf ("\
   1556   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  +%5" PRId64 " %s\n",
   1557 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1558 		    ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1559 		    /* Avoid the leading R_ which isn't carrying any
   1560 		       information.  */
   1561 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1562 					   buf, sizeof (buf)) + 2
   1563 		    : gettext ("<INVALID RELOC>"),
   1564 		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
   1565 		    rel->r_addend,
   1566 		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
   1567 	  else
   1568 	    {
   1569 	      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
   1570 						   sym->st_shndx == SHN_XINDEX
   1571 						   ? xndx : sym->st_shndx),
   1572 				       &destshdr_mem);
   1573 
   1574 	      if (shdr == NULL)
   1575 		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
   1576 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1577 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1578 			/* Avoid the leading R_ which isn't carrying any
   1579 			   information.  */
   1580 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1581 					       buf, sizeof (buf)) + 2
   1582 			: gettext ("<INVALID RELOC>"),
   1583 			gettext ("INVALID SECTION"),
   1584 			(long int) (sym->st_shndx == SHN_XINDEX
   1585 				    ? xndx : sym->st_shndx));
   1586 	      else
   1587 		printf ("\
   1588   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  +%5" PRId64 " %s\n",
   1589 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
   1590 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
   1591 			/* Avoid the leading R_ which isn't carrying any
   1592 			   information.  */
   1593 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
   1594 					       buf, sizeof (buf)) + 2
   1595 			: gettext ("<INVALID RELOC>"),
   1596 			class == ELFCLASS32 ? 10 : 18, sym->st_value,
   1597 			rel->r_addend,
   1598 			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
   1599 	    }
   1600 	}
   1601     }
   1602 }
   1603 
   1604 
   1605 /* Print the program header.  */
   1606 static void
   1607 print_symtab (Ebl *ebl, GElf_Ehdr *ehdr, int type)
   1608 {
   1609   /* Find the symbol table(s).  For this we have to search through the
   1610      section table.  */
   1611   Elf_Scn *scn = NULL;
   1612 
   1613   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   1614     {
   1615       /* Handle the section if it is a symbol table.  */
   1616       GElf_Shdr shdr_mem;
   1617       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1618 
   1619       if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
   1620 	handle_symtab (ebl, ehdr, scn, shdr);
   1621     }
   1622 }
   1623 
   1624 
   1625 static void
   1626 handle_symtab (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   1627 {
   1628   Elf_Data *versym_data = NULL;
   1629   Elf_Data *verneed_data = NULL;
   1630   Elf_Data *verdef_data = NULL;
   1631   Elf_Data *xndx_data = NULL;
   1632   Elf_Scn *runscn;
   1633   Elf_Data *data;
   1634   int class = gelf_getclass (ebl->elf);
   1635   unsigned int nsyms;
   1636   unsigned int cnt;
   1637   Elf32_Word verneed_stridx = 0;
   1638   Elf32_Word verdef_stridx = 0;
   1639   GElf_Shdr glink;
   1640   size_t shstrndx;
   1641 
   1642   /* Get the data of the section.  */
   1643   data = elf_getdata (scn, NULL);
   1644   if (data == NULL)
   1645     return;
   1646 
   1647   /* Find out whether we have other sections we might need.  */
   1648   runscn = NULL;
   1649   while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
   1650     {
   1651       GElf_Shdr runshdr_mem;
   1652       GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
   1653 
   1654       if (runshdr != NULL)
   1655 	{
   1656 	  if (runshdr->sh_type == SHT_GNU_versym
   1657 	      && runshdr->sh_link == elf_ndxscn (scn))
   1658 	    /* Bingo, found the version information.  Now get the data.  */
   1659 	    versym_data = elf_getdata (runscn, NULL);
   1660 	  else if (runshdr->sh_type == SHT_GNU_verneed)
   1661 	    {
   1662 	      /* This is the information about the needed versions.  */
   1663 	      verneed_data = elf_getdata (runscn, NULL);
   1664 	      verneed_stridx = runshdr->sh_link;
   1665 	    }
   1666 	  else if (runshdr->sh_type == SHT_GNU_verdef)
   1667 	    {
   1668 	      /* This is the information about the defined versions.  */
   1669 	      verdef_data = elf_getdata (runscn, NULL);
   1670 	      verdef_stridx = runshdr->sh_link;
   1671 	    }
   1672 	  else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
   1673 	      && runshdr->sh_link == elf_ndxscn (scn))
   1674 	    /* Extended section index.  */
   1675 	    xndx_data = elf_getdata (runscn, NULL);
   1676 	}
   1677     }
   1678 
   1679   /* Get the section header string table index.  */
   1680   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
   1681     error (EXIT_FAILURE, 0,
   1682 	   gettext ("cannot get section header string table index"));
   1683 
   1684   /* Now we can compute the number of entries in the section.  */
   1685   nsyms = data->d_size / (class == ELFCLASS32
   1686 			  ? sizeof (Elf32_Sym) : sizeof (Elf64_Sym));
   1687 
   1688   printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
   1689 		    "\nSymbol table [%2u] '%s' contains %u entries:\n",
   1690 		    nsyms),
   1691 	  (unsigned int) elf_ndxscn (scn),
   1692 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
   1693   printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
   1694 		    " %lu local symbols  String table: [%2u] '%s'\n",
   1695 		    shdr->sh_info),
   1696 	  (unsigned long int) shdr->sh_info,
   1697 	  (unsigned int) shdr->sh_link,
   1698 	  elf_strptr (ebl->elf, shstrndx,
   1699 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   1700 				    &glink)->sh_name));
   1701 
   1702   fputs_unlocked (class == ELFCLASS32
   1703 		  ? gettext ("\
   1704   Num:    Value   Size Type    Bind   Vis          Ndx Name\n")
   1705 		  : gettext ("\
   1706   Num:            Value   Size Type    Bind   Vis          Ndx Name\n"),
   1707 		  stdout);
   1708 
   1709   for (cnt = 0; cnt < nsyms; ++cnt)
   1710     {
   1711       char typebuf[64];
   1712       char bindbuf[64];
   1713       char scnbuf[64];
   1714       Elf32_Word xndx;
   1715       GElf_Sym sym_mem;
   1716       GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
   1717 
   1718       if (sym == NULL)
   1719 	continue;
   1720 
   1721       /* Determine the real section index.  */
   1722       if (sym->st_shndx != SHN_XINDEX)
   1723 	xndx = sym->st_shndx;
   1724 
   1725       printf (gettext ("\
   1726 %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
   1727 	      cnt,
   1728 	      class == ELFCLASS32 ? 8 : 16,
   1729 	      sym->st_value,
   1730 	      sym->st_size,
   1731 	      ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
   1732 				    typebuf, sizeof (typebuf)),
   1733 	      ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
   1734 				       bindbuf, sizeof (bindbuf)),
   1735 	      get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
   1736 	      ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
   1737 				sizeof (scnbuf), NULL, shnum),
   1738 	      elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
   1739 
   1740       if (versym_data != NULL)
   1741 	{
   1742 	  /* Get the version information.  */
   1743 	  GElf_Versym versym_mem;
   1744 	  GElf_Versym *versym;
   1745 
   1746 	  versym = gelf_getversym (versym_data, cnt, &versym_mem);
   1747 
   1748 	  if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
   1749 	    {
   1750 	      bool is_nobits = false;
   1751 	      bool check_def = xndx != SHN_UNDEF;
   1752 
   1753 	      if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
   1754 		{
   1755 		  GElf_Shdr symshdr_mem;
   1756 		  GElf_Shdr *symshdr =
   1757 		    gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
   1758 
   1759 		  is_nobits = (symshdr != NULL
   1760 			       && symshdr->sh_type == SHT_NOBITS);
   1761 		}
   1762 
   1763 	      if (is_nobits || ! check_def)
   1764 		{
   1765 		  /* We must test both.  */
   1766 		  GElf_Verneed verneed_mem;
   1767 		  GElf_Verneed *verneed;
   1768 		  GElf_Vernaux vernaux_mem;
   1769 		  GElf_Vernaux *vernaux = NULL;
   1770 		  size_t vn_offset = 0;
   1771 
   1772 		  verneed = gelf_getverneed (verneed_data, 0, &verneed_mem);
   1773 		  while (verneed != NULL)
   1774 		    {
   1775 		      size_t vna_offset = vn_offset;
   1776 
   1777 		      vernaux = gelf_getvernaux (verneed_data,
   1778 						 vna_offset += verneed->vn_aux,
   1779 						 &vernaux_mem);
   1780 		      while (vernaux != NULL
   1781 			     && vernaux->vna_other != *versym
   1782 			     && vernaux->vna_next != 0)
   1783 			{
   1784 			  /* Update the offset.  */
   1785 			  vna_offset += vernaux->vna_next;
   1786 
   1787 			  vernaux = (vernaux->vna_next == 0
   1788 				     ? NULL
   1789 				     : gelf_getvernaux (verneed_data,
   1790 							vna_offset,
   1791 							&vernaux_mem));
   1792 			}
   1793 
   1794 		      /* Check whether we found the version.  */
   1795 		      if (vernaux != NULL && vernaux->vna_other == *versym)
   1796 			/* Found it.  */
   1797 			break;
   1798 
   1799 		      vn_offset += verneed->vn_next;
   1800 		      verneed = (verneed->vn_next == 0
   1801 				 ? NULL
   1802 				 : gelf_getverneed (verneed_data, vn_offset,
   1803 						    &verneed_mem));
   1804 		    }
   1805 
   1806 		  if (vernaux != NULL && vernaux->vna_other == *versym)
   1807 		    {
   1808 		      printf ("@%s (%u)",
   1809 			      elf_strptr (ebl->elf, verneed_stridx,
   1810 					  vernaux->vna_name),
   1811 			      (unsigned int) vernaux->vna_other);
   1812 		      check_def = 0;
   1813 		    }
   1814 		  else if (! is_nobits)
   1815 		    error (0, 0, gettext ("bad dynamic symbol"));
   1816 		  else
   1817 		    check_def = 1;
   1818 		}
   1819 
   1820 	      if (check_def && *versym != 0x8001)
   1821 		{
   1822 		  /* We must test both.  */
   1823 		  GElf_Verdef verdef_mem;
   1824 		  GElf_Verdef *verdef;
   1825 		  size_t vd_offset = 0;
   1826 
   1827 		  verdef = gelf_getverdef (verdef_data, 0, &verdef_mem);
   1828 		  while (verdef != NULL)
   1829 		    {
   1830 		      if (verdef->vd_ndx == (*versym & 0x7fff))
   1831 			/* Found the definition.  */
   1832 			break;
   1833 
   1834 		      vd_offset += verdef->vd_next;
   1835 		      verdef = (verdef->vd_next == 0
   1836 				? NULL
   1837 				: gelf_getverdef (verdef_data, vd_offset,
   1838 						  &verdef_mem));
   1839 		    }
   1840 
   1841 		  if (verdef != NULL)
   1842 		    {
   1843 		      GElf_Verdaux verdaux_mem;
   1844 		      GElf_Verdaux *verdaux;
   1845 
   1846 		      verdaux = gelf_getverdaux (verdef_data,
   1847 						 vd_offset + verdef->vd_aux,
   1848 						 &verdaux_mem);
   1849 
   1850 		      if (verdaux != NULL)
   1851 			printf ((*versym & 0x8000) ? "@%s" : "@@%s",
   1852 				elf_strptr (ebl->elf, verdef_stridx,
   1853 					    verdaux->vda_name));
   1854 		    }
   1855 		}
   1856 	    }
   1857 	}
   1858 
   1859       putchar ('\n');
   1860     }
   1861 }
   1862 
   1863 
   1864 /* Print version information.  */
   1865 static void
   1866 print_verinfo (Ebl *ebl, GElf_Ehdr *ehdr)
   1867 {
   1868   /* Find the version information sections.  For this we have to
   1869      search through the section table.  */
   1870   Elf_Scn *scn = NULL;
   1871 
   1872   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   1873     {
   1874       /* Handle the section if it is part of the versioning handling.  */
   1875       GElf_Shdr shdr_mem;
   1876       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1877 
   1878       if (shdr != NULL)
   1879 	{
   1880 	  if (shdr->sh_type == SHT_GNU_verneed)
   1881 	    handle_verneed (ebl, ehdr, scn, shdr);
   1882 	  else if (shdr->sh_type == SHT_GNU_verdef)
   1883 	    handle_verdef (ebl, ehdr, scn, shdr);
   1884 	  else if (shdr->sh_type == SHT_GNU_versym)
   1885 	    handle_versym (ebl, ehdr, scn, shdr);
   1886 	}
   1887     }
   1888 }
   1889 
   1890 
   1891 static const char *
   1892 get_ver_flags (unsigned int flags)
   1893 {
   1894   static char buf[32];
   1895   char *endp;
   1896 
   1897   if (flags == 0)
   1898     return gettext ("none");
   1899 
   1900   if (flags & VER_FLG_BASE)
   1901     endp = stpcpy (buf, "BASE ");
   1902   else
   1903     endp = buf;
   1904 
   1905   if (flags & VER_FLG_WEAK)
   1906     {
   1907       if (endp != buf)
   1908         endp = stpcpy (endp, "| ");
   1909 
   1910       endp = stpcpy (endp, "WEAK ");
   1911     }
   1912 
   1913   if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
   1914     {
   1915       strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
   1916       buf[sizeof (buf) - 1] = '\0';
   1917     }
   1918 
   1919   return buf;
   1920 }
   1921 
   1922 
   1923 static void
   1924 handle_verneed (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   1925 {
   1926   Elf_Data *data;
   1927   int class = gelf_getclass (ebl->elf);
   1928   GElf_Shdr glink;
   1929   int cnt;
   1930   unsigned int offset;
   1931   size_t shstrndx;
   1932 
   1933   /* Get the data of the section.  */
   1934   data = elf_getdata (scn, NULL);
   1935   if (data == NULL)
   1936     return;
   1937 
   1938   /* Get the section header string table index.  */
   1939   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
   1940     error (EXIT_FAILURE, 0,
   1941 	   gettext ("cannot get section header string table index"));
   1942 
   1943   printf (ngettext ("\
   1944 \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   1945 		    "\
   1946 \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   1947 		    shdr->sh_info),
   1948 	  (unsigned int) elf_ndxscn (scn),
   1949 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
   1950 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   1951 	  shdr->sh_offset,
   1952 	  (unsigned int) shdr->sh_link,
   1953 	  elf_strptr (ebl->elf, shstrndx,
   1954 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   1955 				    &glink)->sh_name));
   1956 
   1957   offset = 0;
   1958   for (cnt = shdr->sh_info; --cnt >= 0; )
   1959     {
   1960       GElf_Verneed needmem;
   1961       GElf_Verneed *need;
   1962       unsigned int auxoffset;
   1963       int cnt2;
   1964 
   1965       /* Get the data at the next offset.  */
   1966       need = gelf_getverneed (data, offset, &needmem);
   1967       if (need == NULL)
   1968 	break;
   1969 
   1970       printf (gettext ("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
   1971 	      offset, (unsigned short int) need->vn_version,
   1972 	      elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
   1973 	      (unsigned short int) need->vn_cnt);
   1974 
   1975       auxoffset = offset + need->vn_aux;
   1976       for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
   1977 	{
   1978 	  GElf_Vernaux auxmem;
   1979 	  GElf_Vernaux *aux;
   1980 
   1981 	  aux = gelf_getvernaux (data, auxoffset, &auxmem);
   1982 	  if (aux == NULL)
   1983 	    break;
   1984 
   1985 	  printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
   1986 		  auxoffset,
   1987 		  elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
   1988 		  get_ver_flags (aux->vna_flags),
   1989 		  (unsigned short int) aux->vna_other);
   1990 
   1991 	  auxoffset += aux->vna_next;
   1992 	}
   1993 
   1994       /* Find the next offset.  */
   1995       offset += need->vn_next;
   1996     }
   1997 }
   1998 
   1999 
   2000 static void
   2001 handle_verdef (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   2002 {
   2003   Elf_Data *data;
   2004   int class = gelf_getclass (ebl->elf);
   2005   GElf_Shdr glink;
   2006   int cnt;
   2007   unsigned int offset;
   2008   size_t shstrndx;
   2009 
   2010   /* Get the data of the section.  */
   2011   data = elf_getdata (scn, NULL);
   2012   if (data == NULL)
   2013     return;
   2014 
   2015   /* Get the section header string table index.  */
   2016   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
   2017     error (EXIT_FAILURE, 0,
   2018 	   gettext ("cannot get section header string table index"));
   2019 
   2020   printf (ngettext ("\
   2021 \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2022 		    "\
   2023 \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
   2024 		    shdr->sh_info),
   2025 	  (unsigned int) elf_ndxscn (scn),
   2026 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2027 	  shdr->sh_info,
   2028 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   2029 	  shdr->sh_offset,
   2030 	  (unsigned int) shdr->sh_link,
   2031 	  elf_strptr (ebl->elf, shstrndx,
   2032 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   2033 				    &glink)->sh_name));
   2034 
   2035   offset = 0;
   2036   for (cnt = shdr->sh_info; --cnt >= 0; )
   2037     {
   2038       GElf_Verdef defmem;
   2039       GElf_Verdef *def;
   2040       GElf_Verdaux auxmem;
   2041       GElf_Verdaux *aux;
   2042       unsigned int auxoffset;
   2043       int cnt2;
   2044 
   2045       /* Get the data at the next offset.  */
   2046       def = gelf_getverdef (data, offset, &defmem);
   2047       if (def == NULL)
   2048 	break;
   2049 
   2050       auxoffset = offset + def->vd_aux;
   2051       aux = gelf_getverdaux (data, auxoffset, &auxmem);
   2052       if (aux == NULL)
   2053 	break;
   2054 
   2055       printf (gettext ("\
   2056   %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"),
   2057 	      offset, def->vd_version,
   2058 	      get_ver_flags (def->vd_flags),
   2059 	      def->vd_ndx,
   2060 	      def->vd_cnt,
   2061 	      elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
   2062 
   2063       auxoffset += aux->vda_next;
   2064       for (cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
   2065 	{
   2066 	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
   2067 	  if (aux == NULL)
   2068 	    break;
   2069 
   2070 	  printf (gettext ("  %#06x: Parent %d: %s\n"),
   2071 		  auxoffset, cnt2,
   2072 		  elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
   2073 
   2074 	  auxoffset += aux->vda_next;
   2075 	}
   2076 
   2077       /* Find the next offset.  */
   2078       offset += def->vd_next;
   2079     }
   2080 }
   2081 
   2082 
   2083 static void
   2084 handle_versym (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   2085 {
   2086   Elf_Data *data;
   2087   int class = gelf_getclass (ebl->elf);
   2088   Elf_Scn *verscn;
   2089   GElf_Shdr glink;
   2090   Elf_Scn *defscn;
   2091   Elf_Scn *needscn;
   2092   const char **vername;
   2093   const char **filename;
   2094   size_t nvername;
   2095   unsigned int cnt;
   2096   size_t shstrndx;
   2097 
   2098   /* Get the data of the section.  */
   2099   data = elf_getdata (scn, NULL);
   2100   if (data == NULL)
   2101     return;
   2102 
   2103   /* Get the section header string table index.  */
   2104   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
   2105     error (EXIT_FAILURE, 0,
   2106 	   gettext ("cannot get section header string table index"));
   2107 
   2108   /* We have to find the version definition section and extract the
   2109      version names.  */
   2110   defscn = NULL;
   2111   needscn = NULL;
   2112 
   2113   verscn = NULL;
   2114   while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
   2115     {
   2116       GElf_Shdr vershdr_mem;
   2117       GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
   2118 
   2119       if (vershdr != NULL)
   2120 	{
   2121 	  if (vershdr->sh_type == SHT_GNU_verdef)
   2122 	    defscn = verscn;
   2123 	  else if (vershdr->sh_type == SHT_GNU_verneed)
   2124 	    needscn = verscn;
   2125 	}
   2126     }
   2127 
   2128   if (defscn != NULL || needscn != NULL)
   2129     {
   2130       /* We have a version information (better should have).  Now get
   2131 	 the version names.  First find the maximum version number.  */
   2132       nvername = 0;
   2133       if (defscn != NULL)
   2134 	{
   2135 	  /* Run through the version definitions and find the highest
   2136 	     index.  */
   2137 	  unsigned int offset = 0;
   2138 	  Elf_Data *defdata;
   2139 	  GElf_Shdr defshdrmem;
   2140 	  GElf_Shdr *defshdr;
   2141 
   2142 	  defdata = elf_getdata (defscn, NULL);
   2143 	  if (defdata == NULL)
   2144 	    return;
   2145 
   2146 	  defshdr = gelf_getshdr (defscn, &defshdrmem);
   2147 	  if (defshdr == NULL)
   2148 	    return;
   2149 
   2150 	  for (cnt = 0; cnt < defshdr->sh_info; ++cnt)
   2151 	    {
   2152 	      GElf_Verdef defmem;
   2153 	      GElf_Verdef *def;
   2154 
   2155 	      /* Get the data at the next offset.  */
   2156 	      def = gelf_getverdef (defdata, offset, &defmem);
   2157 	      if (def == NULL)
   2158 		break;
   2159 
   2160 	      nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
   2161 
   2162 	      offset += def->vd_next;
   2163 	    }
   2164 	}
   2165       if (needscn != NULL)
   2166 	{
   2167 	  unsigned int offset = 0;
   2168 	  Elf_Data *needdata;
   2169 	  GElf_Shdr needshdrmem;
   2170 	  GElf_Shdr *needshdr;
   2171 
   2172 	  needdata = elf_getdata (needscn, NULL);
   2173 	  if (needdata == NULL)
   2174 	    return;
   2175 
   2176 	  needshdr = gelf_getshdr (needscn, &needshdrmem);
   2177 	  if (needshdr == NULL)
   2178 	    return;
   2179 
   2180 	  for (cnt = 0; cnt < needshdr->sh_info; ++cnt)
   2181 	    {
   2182 	      GElf_Verneed needmem;
   2183 	      GElf_Verneed *need;
   2184 	      unsigned int auxoffset;
   2185 	      int cnt2;
   2186 
   2187 	      /* Get the data at the next offset.  */
   2188 	      need = gelf_getverneed (needdata, offset, &needmem);
   2189 	      if (need == NULL)
   2190 		break;
   2191 
   2192 	      /* Run through the auxiliary entries.  */
   2193 	      auxoffset = offset + need->vn_aux;
   2194 	      for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
   2195 		{
   2196 		  GElf_Vernaux auxmem;
   2197 		  GElf_Vernaux *aux;
   2198 
   2199 		  aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
   2200 		  if (aux == NULL)
   2201 		    break;
   2202 
   2203 		  nvername = MAX (nvername,
   2204 				  (size_t) (aux->vna_other & 0x7fff));
   2205 
   2206 		  auxoffset += aux->vna_next;
   2207 		}
   2208 
   2209 	      offset += need->vn_next;
   2210 	    }
   2211 	}
   2212 
   2213       /* This is the number of versions we know about.  */
   2214       ++nvername;
   2215 
   2216       /* Allocate the array.  */
   2217       vername = (const char **) alloca (nvername * sizeof (const char *));
   2218       filename = (const char **) alloca (nvername * sizeof (const char *));
   2219 
   2220       /* Run through the data structures again and collect the strings.  */
   2221       if (defscn != NULL)
   2222 	{
   2223 	  /* Run through the version definitions and find the highest
   2224 	     index.  */
   2225 	  unsigned int offset = 0;
   2226 	  Elf_Data *defdata;
   2227 	  GElf_Shdr defshdrmem;
   2228 	  GElf_Shdr *defshdr;
   2229 
   2230 	  defdata = elf_getdata (defscn, NULL);
   2231 	  if (defdata == NULL)
   2232 	    return;
   2233 
   2234 	  defshdr = gelf_getshdr (defscn, &defshdrmem);
   2235 	  if (defshdr == NULL)
   2236 	    return;
   2237 
   2238 	  for (cnt = 0; cnt < defshdr->sh_info; ++cnt)
   2239 	    {
   2240 	      GElf_Verdef defmem;
   2241 	      GElf_Verdef *def;
   2242 	      GElf_Verdaux auxmem;
   2243 	      GElf_Verdaux *aux;
   2244 
   2245 	      /* Get the data at the next offset.  */
   2246 	      def = gelf_getverdef (defdata, offset, &defmem);
   2247 	      if (def == NULL)
   2248 		break;
   2249 
   2250 	      aux = gelf_getverdaux (defdata, offset + def->vd_aux, &auxmem);
   2251 	      if (aux == NULL)
   2252 		break;
   2253 
   2254 	      vername[def->vd_ndx & 0x7fff]
   2255 		= elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
   2256 	      filename[def->vd_ndx & 0x7fff] = NULL;
   2257 
   2258 	      offset += def->vd_next;
   2259 	    }
   2260 	}
   2261       if (needscn != NULL)
   2262 	{
   2263 	  unsigned int offset = 0;
   2264 	  Elf_Data *needdata;
   2265 	  GElf_Shdr needshdrmem;
   2266 	  GElf_Shdr *needshdr;
   2267 
   2268 	  needdata = elf_getdata (needscn, NULL);
   2269 	  if (needdata == NULL)
   2270 	    return;
   2271 
   2272 	  needshdr = gelf_getshdr (needscn, &needshdrmem);
   2273 	  if (needshdr == NULL)
   2274 	    return;
   2275 
   2276 	  for (cnt = 0; cnt < needshdr->sh_info; ++cnt)
   2277 	    {
   2278 	      GElf_Verneed needmem;
   2279 	      GElf_Verneed *need;
   2280 	      unsigned int auxoffset;
   2281 	      int cnt2;
   2282 
   2283 	      /* Get the data at the next offset.  */
   2284 	      need = gelf_getverneed (needdata, offset, &needmem);
   2285 	      if (need == NULL)
   2286 		break;
   2287 
   2288 	      /* Run through the auxiliary entries.  */
   2289 	      auxoffset = offset + need->vn_aux;
   2290 	      for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
   2291 		{
   2292 		  GElf_Vernaux auxmem;
   2293 		  GElf_Vernaux *aux;
   2294 
   2295 		  aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
   2296 		  if (aux == NULL)
   2297 		    break;
   2298 
   2299 		  vername[aux->vna_other & 0x7fff]
   2300 		    = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
   2301 		  filename[aux->vna_other & 0x7fff]
   2302 		    = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
   2303 
   2304 		  auxoffset += aux->vna_next;
   2305 		}
   2306 
   2307 	      offset += need->vn_next;
   2308 	    }
   2309 	}
   2310     }
   2311   else
   2312     {
   2313       vername = NULL;
   2314       nvername = 1;
   2315       filename = NULL;
   2316     }
   2317 
   2318   /* Print the header.  */
   2319   printf (ngettext ("\
   2320 \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
   2321 		    "\
   2322 \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
   2323 		    shdr->sh_size / shdr->sh_entsize),
   2324 	  (unsigned int) elf_ndxscn (scn),
   2325 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2326 	  (int) (shdr->sh_size / shdr->sh_entsize),
   2327 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
   2328 	  shdr->sh_offset,
   2329 	  (unsigned int) shdr->sh_link,
   2330 	  elf_strptr (ebl->elf, shstrndx,
   2331 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
   2332 				    &glink)->sh_name));
   2333 
   2334   /* Now we can finally look at the actual contents of this section.  */
   2335   for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
   2336     {
   2337       GElf_Versym symmem;
   2338       GElf_Versym *sym;
   2339       ssize_t n;
   2340 
   2341       if (cnt % 2 == 0)
   2342 	printf ("\n %4d:", cnt);
   2343 
   2344       sym = gelf_getversym (data, cnt, &symmem);
   2345       if (sym == NULL)
   2346 	break;
   2347 
   2348       switch (*sym)
   2349 	{
   2350 	case 0:
   2351 	  fputs_unlocked (gettext ("   0 *local*                     "),
   2352 			  stdout);
   2353 	  break;
   2354 
   2355 	case 1:
   2356 	  fputs_unlocked (gettext ("   1 *global*                    "),
   2357 			  stdout);
   2358 	  break;
   2359 
   2360 	default:
   2361 	  n = printf ("%4d%c%s",
   2362 		      *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
   2363 		      (unsigned int) (*sym & 0x7fff) < nvername
   2364 		      ? vername[*sym & 0x7fff] : "???");
   2365 	  if ((unsigned int) (*sym & 0x7fff) < nvername
   2366 	      && filename[*sym & 0x7fff] != NULL)
   2367 	    n += printf ("(%s)", filename[*sym & 0x7fff]);
   2368 	  printf ("%*s", MAX (0, 33 - (int) n), " ");
   2369 	  break;
   2370 	}
   2371     }
   2372   putchar ('\n');
   2373 }
   2374 
   2375 
   2376 static void
   2377 handle_hash (Ebl *ebl, GElf_Ehdr *ehdr)
   2378 {
   2379   /* Find the symbol table(s).  For this we have to search through the
   2380      section table.  */
   2381   Elf_Scn *scn = NULL;
   2382   size_t shstrndx;
   2383 
   2384   /* Get the section header string table index.  */
   2385   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
   2386     error (EXIT_FAILURE, 0,
   2387 	   gettext ("cannot get section header string table index"));
   2388 
   2389   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   2390     {
   2391       /* Handle the section if it is a symbol table.  */
   2392       GElf_Shdr shdr_mem;
   2393       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   2394 
   2395       if (shdr != NULL && shdr->sh_type == SHT_HASH)
   2396 	{
   2397 	  Elf_Data *data = elf_getdata (scn, NULL);
   2398 	  Elf32_Word nbucket;
   2399 	  Elf32_Word nchain;
   2400 	  Elf32_Word *bucket;
   2401 	  Elf32_Word *chain;
   2402 	  uint32_t *lengths;
   2403 	  uint32_t *counts;
   2404 	  Elf32_Word cnt;
   2405 	  Elf32_Word maxlength = 0;
   2406 	  Elf32_Word nsyms = 0;
   2407 	  uint64_t nzero_counts = 0;
   2408 	  GElf_Shdr glink;
   2409 
   2410 	  if (data == NULL)
   2411 	    {
   2412 	      error (0, 0, gettext ("cannot get data for section %d: %s"),
   2413 		     (int) elf_ndxscn (scn), elf_errmsg (-1));
   2414 	      continue;
   2415 	    }
   2416 
   2417 	  nbucket = ((Elf32_Word *) data->d_buf)[0];
   2418 	  nchain = ((Elf32_Word *) data->d_buf)[1];
   2419 	  bucket = &((Elf32_Word *) data->d_buf)[2];
   2420 	  chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
   2421 
   2422 	  printf (ngettext ("\
   2423 \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",
   2424 			    "\
   2425 \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",
   2426 			    nbucket),
   2427 		  (unsigned int) elf_ndxscn (scn),
   2428 		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2429 		  (int) nbucket,
   2430 		  gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
   2431 		  shdr->sh_addr,
   2432 		  shdr->sh_offset,
   2433 		  (unsigned int) shdr->sh_link,
   2434 		  elf_strptr (ebl->elf, shstrndx,
   2435 			      gelf_getshdr (elf_getscn (ebl->elf,
   2436 							shdr->sh_link),
   2437 					    &glink)->sh_name));
   2438 
   2439 	  lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
   2440 
   2441 	  for (cnt = 0; cnt < nbucket; ++cnt)
   2442 	    if (bucket[cnt] != 0)
   2443 	      {
   2444 		Elf32_Word inner;
   2445 
   2446 		inner = bucket[cnt];
   2447 		while (inner > 0 && inner < nchain)
   2448 		  {
   2449 		    ++nsyms;
   2450 		    if (maxlength < ++lengths[cnt])
   2451 		      ++maxlength;
   2452 
   2453 		    inner = chain[inner];
   2454 		  }
   2455 	      }
   2456 
   2457 	  counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
   2458 
   2459 	  for (cnt = 0; cnt < nbucket; ++cnt)
   2460 	    ++counts[lengths[cnt]];
   2461 
   2462 	  if (nbucket > 0)
   2463 	    {
   2464 	      uint64_t success = 0;
   2465 	      Elf32_Word acc;
   2466 
   2467 	      puts (gettext (" Length  Number  % of total  Coverage"));
   2468 	      printf (gettext ("      0  %6" PRIu32 "      %5.1f%%\n"),
   2469 		      counts[0], (counts[0] * 100.0) / nbucket);
   2470 
   2471 	      for (cnt = 1; cnt <= maxlength; ++cnt)
   2472 		{
   2473 		  nzero_counts += counts[cnt] * cnt;
   2474 		  printf (gettext ("\
   2475 %7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
   2476 			  (int) cnt,
   2477 			  counts[cnt], (counts[cnt] * 100.0) / nbucket,
   2478 			  (nzero_counts * 100.0) / nsyms);
   2479 		}
   2480 
   2481 	      acc = 0;
   2482 	      for (cnt = 1; cnt <= maxlength; ++cnt)
   2483 		{
   2484 		  acc += cnt;
   2485 		  success += counts[cnt] * acc;
   2486 		}
   2487 
   2488 	      printf (gettext ("\
   2489  Average number of tests:   successful lookup: %f\n\
   2490                           unsuccessful lookup: %f\n"),
   2491 		      (double) success / (double) nzero_counts,
   2492 		      (double) nzero_counts / (double) nbucket);
   2493 	    }
   2494 
   2495 	  free (counts);
   2496 	  free (lengths);
   2497 	}
   2498     }
   2499 }
   2500 
   2501 
   2502 static void
   2503 print_liblist (Ebl *ebl, GElf_Ehdr *ehdr)
   2504 {
   2505   /* Find the library list sections.  For this we have to search
   2506      through the section table.  */
   2507   Elf_Scn *scn = NULL;
   2508 
   2509   /* Get the section header string table index.  */
   2510   size_t shstrndx;
   2511   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
   2512     error (EXIT_FAILURE, 0,
   2513 	   gettext ("cannot get section header string table index"));
   2514 
   2515   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   2516     {
   2517       GElf_Shdr shdr_mem;
   2518       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   2519 
   2520       if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
   2521 	{
   2522 	  int nentries = shdr->sh_size / shdr->sh_entsize;
   2523 	  printf (ngettext ("\
   2524 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
   2525 			    "\
   2526 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
   2527 			    nentries),
   2528 		  elf_ndxscn (scn),
   2529 		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
   2530 		  shdr->sh_offset,
   2531 		  nentries);
   2532 
   2533 	  Elf_Data *data = elf_getdata (scn, NULL);
   2534 	  if (data == NULL)
   2535 	    return;
   2536 
   2537 	  puts (gettext ("\
   2538        Library                       Time Stamp          Checksum Version Flags"));
   2539 
   2540 	  for (int cnt = 0; cnt < nentries; ++cnt)
   2541 	    {
   2542 	      GElf_Lib lib_mem;
   2543 	      GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
   2544 	      if (lib == NULL)
   2545 		continue;
   2546 
   2547 	      time_t t = (time_t) lib->l_time_stamp;
   2548 	      struct tm *tm = gmtime (&t);
   2549 	      if (tm == NULL)
   2550 		continue;
   2551 
   2552 	      printf ("  [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
   2553 		      cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
   2554 		      tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
   2555 		      tm->tm_hour, tm->tm_min, tm->tm_sec,
   2556 		      (unsigned int) lib->l_checksum,
   2557 		      (unsigned int) lib->l_version,
   2558 		      (unsigned int) lib->l_flags);
   2559 	    }
   2560 	}
   2561     }
   2562 }
   2563 
   2564 
   2565 static const char *
   2566 dwarf_tag_string (unsigned int tag)
   2567 {
   2568   static const char *known_tags[]  =
   2569     {
   2570       [DW_TAG_array_type] = "array_type",
   2571       [DW_TAG_class_type] = "class_type",
   2572       [DW_TAG_entry_point] = "entry_point",
   2573       [DW_TAG_enumeration_type] = "enumeration_type",
   2574       [DW_TAG_formal_parameter] = "formal_parameter",
   2575       [DW_TAG_imported_declaration] = "imported_declaration",
   2576       [DW_TAG_label] = "label",
   2577       [DW_TAG_lexical_block] = "lexical_block",
   2578       [DW_TAG_member] = "member",
   2579       [DW_TAG_pointer_type] = "pointer_type",
   2580       [DW_TAG_reference_type] = "reference_type",
   2581       [DW_TAG_compile_unit] = "compile_unit",
   2582       [DW_TAG_string_type] = "string_type",
   2583       [DW_TAG_structure_type] = "structure_type",
   2584       [DW_TAG_subroutine_type] = "subroutine_type",
   2585       [DW_TAG_typedef] = "typedef",
   2586       [DW_TAG_union_type] = "union_type",
   2587       [DW_TAG_unspecified_parameters] = "unspecified_parameters",
   2588       [DW_TAG_variant] = "variant",
   2589       [DW_TAG_common_block] = "common_block",
   2590       [DW_TAG_common_inclusion] = "common_inclusion",
   2591       [DW_TAG_inheritance] = "inheritance",
   2592       [DW_TAG_inlined_subroutine] = "inlined_subroutine",
   2593       [DW_TAG_module] = "module",
   2594       [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
   2595       [DW_TAG_set_type] = "set_type",
   2596       [DW_TAG_subrange_type] = "subrange_type",
   2597       [DW_TAG_with_stmt] = "with_stmt",
   2598       [DW_TAG_access_declaration] = "access_declaration",
   2599       [DW_TAG_base_type] = "base_type",
   2600       [DW_TAG_catch_block] = "catch_block",
   2601       [DW_TAG_const_type] = "const_type",
   2602       [DW_TAG_constant] = "constant",
   2603       [DW_TAG_enumerator] = "enumerator",
   2604       [DW_TAG_file_type] = "file_type",
   2605       [DW_TAG_friend] = "friend",
   2606       [DW_TAG_namelist] = "namelist",
   2607       [DW_TAG_namelist_item] = "namelist_item",
   2608       [DW_TAG_packed_type] = "packed_type",
   2609       [DW_TAG_subprogram] = "subprogram",
   2610       [DW_TAG_template_type_param] = "template_type_param",
   2611       [DW_TAG_template_value_param] = "template_value_param",
   2612       [DW_TAG_thrown_type] = "thrown_type",
   2613       [DW_TAG_try_block] = "try_block",
   2614       [DW_TAG_variant_part] = "variant_part",
   2615       [DW_TAG_variable] = "variable",
   2616       [DW_TAG_volatile_type] = "volatile_type",
   2617     };
   2618   const unsigned int nknown_tags = (sizeof (known_tags)
   2619 				    / sizeof (known_tags[0]));
   2620   static char buf[40];
   2621   const char *result = NULL;
   2622 
   2623   if (tag < nknown_tags)
   2624     result = known_tags[tag];
   2625 
   2626   if (result == NULL)
   2627     /* There are a few known extensions.  */
   2628     switch (tag)
   2629       {
   2630       case DW_TAG_MIPS_loop:
   2631 	result = "MIPS_loop";
   2632 	break;
   2633 
   2634       case DW_TAG_format_label:
   2635 	result = "format_label";
   2636 	break;
   2637 
   2638       case DW_TAG_function_template:
   2639 	result = "function_template";
   2640 	break;
   2641 
   2642       case DW_TAG_class_template:
   2643 	result = "class_template";
   2644 	break;
   2645 
   2646       default:
   2647 	if (tag < DW_TAG_lo_user)
   2648 	  snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag);
   2649 	else
   2650 	  snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag);
   2651 	result = buf;
   2652 	break;
   2653       }
   2654 
   2655   return result;
   2656 }
   2657 
   2658 
   2659 static const char *
   2660 dwarf_attr_string (unsigned int attrnum)
   2661 {
   2662   static const char *known_attrs[] =
   2663     {
   2664       [DW_AT_sibling] = "sibling",
   2665       [DW_AT_location] = "location",
   2666       [DW_AT_name] = "name",
   2667       [DW_AT_ordering] = "ordering",
   2668       [DW_AT_subscr_data] = "subscr_data",
   2669       [DW_AT_byte_size] = "byte_size",
   2670       [DW_AT_bit_offset] = "bit_offset",
   2671       [DW_AT_bit_size] = "bit_size",
   2672       [DW_AT_element_list] = "element_list",
   2673       [DW_AT_stmt_list] = "stmt_list",
   2674       [DW_AT_low_pc] = "low_pc",
   2675       [DW_AT_high_pc] = "high_pc",
   2676       [DW_AT_language] = "language",
   2677       [DW_AT_member] = "member",
   2678       [DW_AT_discr] = "discr",
   2679       [DW_AT_discr_value] = "discr_value",
   2680       [DW_AT_visibility] = "visibility",
   2681       [DW_AT_import] = "import",
   2682       [DW_AT_string_length] = "string_length",
   2683       [DW_AT_common_reference] = "common_reference",
   2684       [DW_AT_comp_dir] = "comp_dir",
   2685       [DW_AT_const_value] = "const_value",
   2686       [DW_AT_containing_type] = "containing_type",
   2687       [DW_AT_default_value] = "default_value",
   2688       [DW_AT_inline] = "inline",
   2689       [DW_AT_is_optional] = "is_optional",
   2690       [DW_AT_lower_bound] = "lower_bound",
   2691       [DW_AT_producer] = "producer",
   2692       [DW_AT_prototyped] = "prototyped",
   2693       [DW_AT_return_addr] = "return_addr",
   2694       [DW_AT_start_scope] = "start_scope",
   2695       [DW_AT_stride_size] = "stride_size",
   2696       [DW_AT_upper_bound] = "upper_bound",
   2697       [DW_AT_abstract_origin] = "abstract_origin",
   2698       [DW_AT_accessibility] = "accessibility",
   2699       [DW_AT_address_class] = "address_class",
   2700       [DW_AT_artificial] = "artificial",
   2701       [DW_AT_base_types] = "base_types",
   2702       [DW_AT_calling_convention] = "calling_convention",
   2703       [DW_AT_count] = "count",
   2704       [DW_AT_data_member_location] = "data_member_location",
   2705       [DW_AT_decl_column] = "decl_column",
   2706       [DW_AT_decl_file] = "decl_file",
   2707       [DW_AT_decl_line] = "decl_line",
   2708       [DW_AT_declaration] = "declaration",
   2709       [DW_AT_discr_list] = "discr_list",
   2710       [DW_AT_encoding] = "encoding",
   2711       [DW_AT_external] = "external",
   2712       [DW_AT_frame_base] = "frame_base",
   2713       [DW_AT_friend] = "friend",
   2714       [DW_AT_identifier_case] = "identifier_case",
   2715       [DW_AT_macro_info] = "macro_info",
   2716       [DW_AT_namelist_items] = "namelist_items",
   2717       [DW_AT_priority] = "priority",
   2718       [DW_AT_segment] = "segment",
   2719       [DW_AT_specification] = "specification",
   2720       [DW_AT_static_link] = "static_link",
   2721       [DW_AT_type] = "type",
   2722       [DW_AT_use_location] = "use_location",
   2723       [DW_AT_variable_parameter] = "variable_parameter",
   2724       [DW_AT_virtuality] = "virtuality",
   2725       [DW_AT_vtable_elem_location] = "vtable_elem_location"
   2726     };
   2727   const unsigned int nknown_attrs = (sizeof (known_attrs)
   2728 				     / sizeof (known_attrs[0]));
   2729   static char buf[40];
   2730   const char *result = NULL;
   2731 
   2732   if (attrnum < nknown_attrs)
   2733     result = known_attrs[attrnum];
   2734 
   2735   if (result == NULL)
   2736     /* There are a few known extensions.  */
   2737     switch (attrnum)
   2738       {
   2739       case DW_AT_MIPS_fde:
   2740 	result = "MIPS_fde";
   2741 	break;
   2742 
   2743       case DW_AT_MIPS_loop_begin:
   2744 	result = "MIPS_loop_begin";
   2745 	break;
   2746 
   2747       case DW_AT_MIPS_tail_loop_begin:
   2748 	result = "MIPS_tail_loop_begin";
   2749 	break;
   2750 
   2751       case DW_AT_MIPS_epilog_begin:
   2752 	result = "MIPS_epilog_begin";
   2753 	break;
   2754 
   2755       case DW_AT_MIPS_loop_unroll_factor:
   2756 	result = "MIPS_loop_unroll_factor";
   2757 	break;
   2758 
   2759       case DW_AT_MIPS_software_pipeline_depth:
   2760 	result = "MIPS_software_pipeline_depth";
   2761 	break;
   2762 
   2763       case DW_AT_MIPS_linkage_name:
   2764 	result = "MIPS_linkage_name";
   2765 	break;
   2766 
   2767       case DW_AT_MIPS_stride:
   2768 	result = "MIPS_stride";
   2769 	break;
   2770 
   2771       case DW_AT_MIPS_abstract_name:
   2772 	result = "MIPS_abstract_name";
   2773 	break;
   2774 
   2775       case DW_AT_MIPS_clone_origin:
   2776 	result = "MIPS_clone_origin";
   2777 	break;
   2778 
   2779       case DW_AT_MIPS_has_inlines:
   2780 	result = "MIPS_has_inlines";
   2781 	break;
   2782 
   2783       case DW_AT_MIPS_stride_byte:
   2784 	result = "MIPS_stride_byte";
   2785 	break;
   2786 
   2787       case DW_AT_MIPS_stride_elem:
   2788 	result = "MIPS_stride_elem";
   2789 	break;
   2790 
   2791       case DW_AT_MIPS_ptr_dopetype:
   2792 	result = "MIPS_ptr_dopetype";
   2793 	break;
   2794 
   2795       case DW_AT_MIPS_allocatable_dopetype:
   2796 	result = "MIPS_allocatable_dopetype";
   2797 	break;
   2798 
   2799       case DW_AT_MIPS_assumed_shape_dopetype:
   2800 	result = "MIPS_assumed_shape_dopetype";
   2801 	break;
   2802 
   2803       case DW_AT_MIPS_assumed_size:
   2804 	result = "MIPS_assumed_size";
   2805 	break;
   2806 
   2807       case DW_AT_sf_names:
   2808 	result = "sf_names";
   2809 	break;
   2810 
   2811       case DW_AT_src_info:
   2812 	result = "src_info";
   2813 	break;
   2814 
   2815       case DW_AT_mac_info:
   2816 	result = "mac_info";
   2817 	break;
   2818 
   2819       case DW_AT_src_coords:
   2820 	result = "src_coords";
   2821 	break;
   2822 
   2823       case DW_AT_body_begin:
   2824 	result = "body_begin";
   2825 	break;
   2826 
   2827       case DW_AT_body_end:
   2828 	result = "body_end";
   2829 	break;
   2830 
   2831       default:
   2832 	if (attrnum < DW_AT_lo_user)
   2833 	  snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"),
   2834 		    attrnum);
   2835 	else
   2836 	  snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"),
   2837 		    attrnum);
   2838 	result = buf;
   2839 	break;
   2840       }
   2841 
   2842   return result;
   2843 }
   2844 
   2845 
   2846 static const char *
   2847 dwarf_form_string (unsigned int form)
   2848 {
   2849   static const char *known_forms[] =
   2850     {
   2851       [DW_FORM_addr] = "addr",
   2852       [DW_FORM_block2] = "block2",
   2853       [DW_FORM_block4] = "block4",
   2854       [DW_FORM_data2] = "data2",
   2855       [DW_FORM_data4] = "data4",
   2856       [DW_FORM_data8] = "data8",
   2857       [DW_FORM_string] = "string",
   2858       [DW_FORM_block] = "block",
   2859       [DW_FORM_block1] = "block1",
   2860       [DW_FORM_data1] = "data1",
   2861       [DW_FORM_flag] = "flag",
   2862       [DW_FORM_sdata] = "sdata",
   2863       [DW_FORM_strp] = "strp",
   2864       [DW_FORM_udata] = "udata",
   2865       [DW_FORM_ref_addr] = "ref_addr",
   2866       [DW_FORM_ref1] = "ref1",
   2867       [DW_FORM_ref2] = "ref2",
   2868       [DW_FORM_ref4] = "ref4",
   2869       [DW_FORM_ref8] = "ref8",
   2870       [DW_FORM_ref_udata] = "ref_udata",
   2871       [DW_FORM_indirect] = "indirect"
   2872     };
   2873   const unsigned int nknown_forms = (sizeof (known_forms)
   2874 				     / sizeof (known_forms[0]));
   2875   static char buf[40];
   2876   const char *result = NULL;
   2877 
   2878   if (form < nknown_forms)
   2879     result = known_forms[form];
   2880 
   2881   if (result == NULL)
   2882     snprintf (buf, sizeof buf, gettext ("unknown form %" PRIx64),
   2883 	      (uint64_t) form);
   2884 
   2885   return result;
   2886 }
   2887 
   2888 
   2889 static const char *
   2890 dwarf_lang_string (unsigned int lang)
   2891 {
   2892   static const char *known[] =
   2893     {
   2894       [DW_LANG_C89] = "ISO C89",
   2895       [DW_LANG_C] = "C",
   2896       [DW_LANG_Ada83] = "Ada83",
   2897       [DW_LANG_C_plus_plus ] = "C++",
   2898       [DW_LANG_Cobol74] = "Cobol74",
   2899       [DW_LANG_Cobol85] = "Cobol85",
   2900       [DW_LANG_Fortran77] = "Fortran77",
   2901       [DW_LANG_Fortran90] = "Fortran90",
   2902       [DW_LANG_Pascal83] = "Pascal83",
   2903       [DW_LANG_Modula2] = "Modula2",
   2904       [DW_LANG_Java] = "Java",
   2905       [DW_LANG_C99] = "ISO C99",
   2906       [DW_LANG_Ada95] = "Ada95",
   2907       [DW_LANG_Fortran95] = "Fortran95",
   2908       [DW_LANG_PL1] = "PL1"
   2909     };
   2910 
   2911   if (lang < sizeof (known) / sizeof (known[0]))
   2912     return known[lang];
   2913   else if (lang == DW_LANG_Mips_Assembler)
   2914     /* This language tag is used for assembler in general.  */
   2915     return "Assembler";
   2916 
   2917   if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user)
   2918     {
   2919       static char buf[100];
   2920       snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user);
   2921       return buf;
   2922     }
   2923 
   2924   return "???";
   2925 }
   2926 
   2927 
   2928 static void
   2929 print_ops (Dwarf *dbg, int level, unsigned int addrsize, Dwarf_Word len,
   2930 	   unsigned char *data)
   2931 {
   2932   static const char *known[] =
   2933     {
   2934       [DW_OP_addr] = "addr",
   2935       [DW_OP_deref] = "deref",
   2936       [DW_OP_const1u] = "const1u",
   2937       [DW_OP_const1s] = "const1s",
   2938       [DW_OP_const2u] = "const2u",
   2939       [DW_OP_const2s] = "const2s",
   2940       [DW_OP_const4u] = "const4u",
   2941       [DW_OP_const4s] = "const4s",
   2942       [DW_OP_const8u] = "const8u",
   2943       [DW_OP_const8s] = "const8s",
   2944       [DW_OP_constu] = "constu",
   2945       [DW_OP_consts] = "consts",
   2946       [DW_OP_dup] = "dup",
   2947       [DW_OP_drop] = "drop",
   2948       [DW_OP_over] = "over",
   2949       [DW_OP_pick] = "pick",
   2950       [DW_OP_swap] = "swap",
   2951       [DW_OP_rot] = "rot",
   2952       [DW_OP_xderef] = "xderef",
   2953       [DW_OP_abs] = "abs",
   2954       [DW_OP_and] = "and",
   2955       [DW_OP_div] = "div",
   2956       [DW_OP_minus] = "minus",
   2957       [DW_OP_mod] = "mod",
   2958       [DW_OP_mul] = "mul",
   2959       [DW_OP_neg] = "neg",
   2960       [DW_OP_not] = "not",
   2961       [DW_OP_or] = "or",
   2962       [DW_OP_plus] = "plus",
   2963       [DW_OP_plus_uconst] = "plus_uconst",
   2964       [DW_OP_shl] = "shl",
   2965       [DW_OP_shr] = "shr",
   2966       [DW_OP_shra] = "shra",
   2967       [DW_OP_xor] = "xor",
   2968       [DW_OP_bra] = "bra",
   2969       [DW_OP_eq] = "eq",
   2970       [DW_OP_ge] = "ge",
   2971       [DW_OP_gt] = "gt",
   2972       [DW_OP_le] = "le",
   2973       [DW_OP_lt] = "lt",
   2974       [DW_OP_ne] = "ne",
   2975       [DW_OP_skip] = "skip",
   2976       [DW_OP_lit0] = "lit0",
   2977       [DW_OP_lit1] = "lit1",
   2978       [DW_OP_lit2] = "lit2",
   2979       [DW_OP_lit3] = "lit3",
   2980       [DW_OP_lit4] = "lit4",
   2981       [DW_OP_lit5] = "lit5",
   2982       [DW_OP_lit6] = "lit6",
   2983       [DW_OP_lit7] = "lit7",
   2984       [DW_OP_lit8] = "lit8",
   2985       [DW_OP_lit9] = "lit9",
   2986       [DW_OP_lit10] = "lit10",
   2987       [DW_OP_lit11] = "lit11",
   2988       [DW_OP_lit12] = "lit12",
   2989       [DW_OP_lit13] = "lit13",
   2990       [DW_OP_lit14] = "lit14",
   2991       [DW_OP_lit15] = "lit15",
   2992       [DW_OP_lit16] = "lit16",
   2993       [DW_OP_lit17] = "lit17",
   2994       [DW_OP_lit18] = "lit18",
   2995       [DW_OP_lit19] = "lit19",
   2996       [DW_OP_lit20] = "lit20",
   2997       [DW_OP_lit21] = "lit21",
   2998       [DW_OP_lit22] = "lit22",
   2999       [DW_OP_lit23] = "lit23",
   3000       [DW_OP_lit24] = "lit24",
   3001       [DW_OP_lit25] = "lit25",
   3002       [DW_OP_lit26] = "lit26",
   3003       [DW_OP_lit27] = "lit27",
   3004       [DW_OP_lit28] = "lit28",
   3005       [DW_OP_lit29] = "lit29",
   3006       [DW_OP_lit30] = "lit30",
   3007       [DW_OP_lit31] = "lit31",
   3008       [DW_OP_reg0] = "reg0",
   3009       [DW_OP_reg1] = "reg1",
   3010       [DW_OP_reg2] = "reg2",
   3011       [DW_OP_reg3] = "reg3",
   3012       [DW_OP_reg4] = "reg4",
   3013       [DW_OP_reg5] = "reg5",
   3014       [DW_OP_reg6] = "reg6",
   3015       [DW_OP_reg7] = "reg7",
   3016       [DW_OP_reg8] = "reg8",
   3017       [DW_OP_reg9] = "reg9",
   3018       [DW_OP_reg10] = "reg10",
   3019       [DW_OP_reg11] = "reg11",
   3020       [DW_OP_reg12] = "reg12",
   3021       [DW_OP_reg13] = "reg13",
   3022       [DW_OP_reg14] = "reg14",
   3023       [DW_OP_reg15] = "reg15",
   3024       [DW_OP_reg16] = "reg16",
   3025       [DW_OP_reg17] = "reg17",
   3026       [DW_OP_reg18] = "reg18",
   3027       [DW_OP_reg19] = "reg19",
   3028       [DW_OP_reg20] = "reg20",
   3029       [DW_OP_reg21] = "reg21",
   3030       [DW_OP_reg22] = "reg22",
   3031       [DW_OP_reg23] = "reg23",
   3032       [DW_OP_reg24] = "reg24",
   3033       [DW_OP_reg25] = "reg25",
   3034       [DW_OP_reg26] = "reg26",
   3035       [DW_OP_reg27] = "reg27",
   3036       [DW_OP_reg28] = "reg28",
   3037       [DW_OP_reg29] = "reg29",
   3038       [DW_OP_reg30] = "reg30",
   3039       [DW_OP_reg31] = "reg31",
   3040       [DW_OP_breg0] = "breg0",
   3041       [DW_OP_breg1] = "breg1",
   3042       [DW_OP_breg2] = "breg2",
   3043       [DW_OP_breg3] = "breg3",
   3044       [DW_OP_breg4] = "breg4",
   3045       [DW_OP_breg5] = "breg5",
   3046       [DW_OP_breg6] = "breg6",
   3047       [DW_OP_breg7] = "breg7",
   3048       [DW_OP_breg8] = "breg8",
   3049       [DW_OP_breg9] = "breg9",
   3050       [DW_OP_breg10] = "breg10",
   3051       [DW_OP_breg11] = "breg11",
   3052       [DW_OP_breg12] = "breg12",
   3053       [DW_OP_breg13] = "breg13",
   3054       [DW_OP_breg14] = "breg14",
   3055       [DW_OP_breg15] = "breg15",
   3056       [DW_OP_breg16] = "breg16",
   3057       [DW_OP_breg17] = "breg17",
   3058       [DW_OP_breg18] = "breg18",
   3059       [DW_OP_breg19] = "breg19",
   3060       [DW_OP_breg20] = "breg20",
   3061       [DW_OP_breg21] = "breg21",
   3062       [DW_OP_breg22] = "breg22",
   3063       [DW_OP_breg23] = "breg23",
   3064       [DW_OP_breg24] = "breg24",
   3065       [DW_OP_breg25] = "breg25",
   3066       [DW_OP_breg26] = "breg26",
   3067       [DW_OP_breg27] = "breg27",
   3068       [DW_OP_breg28] = "breg28",
   3069       [DW_OP_breg29] = "breg29",
   3070       [DW_OP_breg30] = "breg30",
   3071       [DW_OP_breg31] = "breg31",
   3072       [DW_OP_regx] = "regx",
   3073       [DW_OP_fbreg] = "fbreg",
   3074       [DW_OP_bregx] = "bregx",
   3075       [DW_OP_piece] = "piece",
   3076       [DW_OP_deref_size] = "deref_size",
   3077       [DW_OP_xderef_size] = "xderef_size",
   3078       [DW_OP_nop] = "nop",
   3079       [DW_OP_push_object_address] = "push_object_address",
   3080       [DW_OP_call2] = "call2",
   3081       [DW_OP_call4] = "call4",
   3082       [DW_OP_call_ref] = "call_ref",
   3083     };
   3084 
   3085   Dwarf_Word offset = 0;
   3086   while (len-- > 0)
   3087     {
   3088       size_t op = *((unsigned char *) data);
   3089       ++data;
   3090 
   3091       switch (op)
   3092 	{
   3093 	case DW_OP_call_ref:
   3094 	case DW_OP_addr:;
   3095 	  /* Address operand.  */
   3096 	  Dwarf_Word addr;
   3097 	  if (addrsize == 4)
   3098 	    addr = read_4ubyte_unaligned (dbg, data);
   3099 	  else
   3100 	    {
   3101 	      assert (addrsize == 8);
   3102 	      addr = read_8ubyte_unaligned (dbg, data);
   3103 	    }
   3104 	  data += addrsize;
   3105 	  len -= addrsize;
   3106 
   3107 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRIuMAX "\n",
   3108 		  (int) (20 + level * 2), "", (uintmax_t) offset,
   3109 		  known[op] ?: "???", (uintmax_t) addr);
   3110 	  offset += 1 + addrsize;
   3111 	  break;
   3112 
   3113 	case DW_OP_deref_size:		/* XXX Correct?  */
   3114 	case DW_OP_xderef_size:		/* XXX Correct?  */
   3115 	case DW_OP_pick:
   3116 	case DW_OP_const1u:
   3117 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRIu8 "\n",
   3118 		  (int) (20 + level * 2), "", (uintmax_t) offset,
   3119 		  known[op] ?: "???", *((uint8_t *) data));
   3120 	  ++data;
   3121 	  --len;
   3122 	  offset += 2;
   3123 	  break;
   3124 
   3125 	case DW_OP_const2u:
   3126 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRIu16 "\n",
   3127 		  (int) (20 + level * 2), "", (uintmax_t) offset,
   3128 		  known[op] ?: "???", read_2ubyte_unaligned (dbg, data));
   3129 	  len -= 2;
   3130 	  data += 2;
   3131 	  offset += 3;
   3132 	  break;
   3133 
   3134 	case DW_OP_const4u:
   3135 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRIu32 "\n",
   3136 		  (int) (20 + level * 2), "", (uintmax_t) offset,
   3137 		  known[op] ?: "???", read_4ubyte_unaligned (dbg, data));
   3138 	  len -= 4;
   3139 	  data += 4;
   3140 	  offset += 5;
   3141 	  break;
   3142 
   3143 	case DW_OP_const8u:
   3144 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRIu64 "\n",
   3145 		  (int) (20 + level * 2), "", (uintmax_t) offset,
   3146 		  known[op] ?: "???", read_8ubyte_unaligned (dbg, data));
   3147 	  len -= 8;
   3148 	  data += 8;
   3149 	  offset += 9;
   3150 	  break;
   3151 
   3152 	case DW_OP_const1s:
   3153 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRId8 "\n",
   3154 		  (int) (20 + level * 2), "", (uintmax_t) offset,
   3155 		  known[op] ?: "???", *((int8_t *) data));
   3156 	  ++data;
   3157 	  --len;
   3158 	  offset += 2;
   3159 	  break;
   3160 
   3161 	case DW_OP_const2s:
   3162 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRId16 "\n",
   3163 		  (int) (20 + level * 2), "", (uintmax_t) offset,
   3164 		  known[op] ?: "???", read_2sbyte_unaligned (dbg, data));
   3165 	  len -= 2;
   3166 	  data += 2;
   3167 	  offset += 3;
   3168 	  break;
   3169 
   3170 	case DW_OP_const4s:
   3171 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRId32 "\n",
   3172 		  (int) (20 + level * 2), "", (uintmax_t) offset,
   3173 		  known[op] ?: "???", read_4sbyte_unaligned (dbg, data));
   3174 	  len -= 4;
   3175 	  data += 4;
   3176 	  offset += 5;
   3177 	  break;
   3178 
   3179 	case DW_OP_const8s:
   3180 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRId64 "\n",
   3181 		  (int) (20 + level * 2), "", (uintmax_t) offset,
   3182 		  known[op] ?: "???", read_8sbyte_unaligned (dbg, data));
   3183 	  len -= 8;
   3184 	  data += 8;
   3185 	  offset += 9;
   3186 	  break;
   3187 
   3188 	case DW_OP_piece:		/* XXX Correct?  */
   3189 	case DW_OP_regx:
   3190 	case DW_OP_plus_uconst:
   3191 	case DW_OP_constu:;
   3192 	  unsigned char *start = data;
   3193 	  unsigned int uleb;
   3194 	  get_uleb128 (uleb, data);
   3195 	  printf ("           %*s [%4" PRIuMAX "] %s %u\n",
   3196 		  (int) (20 + level * 2), "", (uintmax_t) offset,
   3197 		  known[op] ?: "???", uleb);
   3198 	  len -= data - start;
   3199 	  offset += 1 + (data - start);
   3200 	  break;
   3201 
   3202 	case DW_OP_fbreg:
   3203 	case DW_OP_breg0 ... DW_OP_breg31:
   3204 	case DW_OP_consts:
   3205 	  start = data;
   3206 	  unsigned int sleb;
   3207 	  get_sleb128 (sleb, data);
   3208 	  printf ("           %*s [%4" PRIuMAX "] %s %d\n",
   3209 		  (int) (20 + level * 2), "", (uintmax_t) offset,
   3210 		  known[op] ?: "???", sleb);
   3211 	  len -= data - start;
   3212 	  offset += 1 + (data - start);
   3213 	  break;
   3214 
   3215 	case DW_OP_bregx:
   3216 	  start = data;
   3217 	  get_uleb128 (uleb, data);
   3218 	  get_sleb128 (sleb, data);
   3219 	  printf ("           %*s [%4" PRIuMAX "] %s %u %d\n",
   3220 		  (int) (20 + level * 2), "", (uintmax_t) offset,
   3221 		  known[op] ?: "???", uleb, sleb);
   3222 	  len -= data - start;
   3223 	  offset += 1 + (data - start);
   3224 	  break;
   3225 
   3226 	case DW_OP_call2:
   3227 	case DW_OP_call4:
   3228 	case DW_OP_skip:
   3229 	case DW_OP_bra:
   3230 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRIuMAX "\n",
   3231 		  (int) (20 + level * 2), "", (uintmax_t) offset,
   3232 		  known[op] ?: "???",
   3233 		  (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
   3234 	  len -= 2;
   3235 	  data += 2;
   3236 	  offset += 3;
   3237 	  break;
   3238 
   3239 	default:
   3240 	  /* No Operand.  */
   3241 	  printf ("           %*s [%4" PRIuMAX "] %s\n",
   3242 		  (int) (20 + level * 2), "", (uintmax_t) offset,
   3243 		  known[op] ?: "???");
   3244 	  ++offset;
   3245 	  break;
   3246 	}
   3247     }
   3248 }
   3249 
   3250 
   3251 static void
   3252 print_debug_abbrev_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
   3253 			    GElf_Shdr *shdr, Dwarf *dbg)
   3254 {
   3255   printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
   3256 		   " [ Code]\n"),
   3257 	  ".debug_abbrev", (uint64_t) shdr->sh_offset);
   3258 
   3259   Dwarf_Off offset = 0;
   3260   while (1)
   3261     {
   3262       size_t length;
   3263       Dwarf_Abbrev abbrev;
   3264 
   3265       if  (dwarf_offabbrev (dbg, offset, &length, &abbrev) != 0)
   3266 	{
   3267 	  printf (gettext (" *** error while reading abbreviation: %s\n"),
   3268 		  dwarf_errmsg (-1));
   3269 	  break;
   3270 	}
   3271 
   3272       if (length == 1)
   3273 	/* This is the NUL byte at the end of the section.  */
   3274 	break;
   3275 
   3276       /* We know these calls can never fail.  */
   3277       unsigned int code = dwarf_getabbrevcode (&abbrev);
   3278       unsigned int tag = dwarf_getabbrevtag (&abbrev);
   3279       int has_children = dwarf_abbrevhaschildren (&abbrev);
   3280 
   3281       printf (gettext (" [%5u] offset: %" PRId64
   3282 		       ", children: %s, tag: %s\n"),
   3283 	      code, (int64_t) offset,
   3284 	      has_children ? gettext ("yes") : gettext ("no"),
   3285 	      dwarf_tag_string (tag));
   3286 
   3287       size_t cnt = 0;
   3288       unsigned int name;
   3289       unsigned int form;
   3290       Dwarf_Off enoffset;
   3291       while (dwarf_getabbrevattr (&abbrev, cnt, &name, &form, &enoffset) == 0)
   3292 	{
   3293 	  printf ("          attr: %s, form: %s, offset: %#" PRIx64 "\n",
   3294 		  dwarf_attr_string (name), dwarf_form_string (form),
   3295 		  (uint64_t) enoffset);
   3296 
   3297 	  ++cnt;
   3298 	}
   3299 
   3300       offset += length;
   3301     }
   3302 }
   3303 
   3304 
   3305 /* Print content of DWARF .debug_aranges section.  We fortunately do
   3306    not have to know a bit about the structure of the section, libdwarf
   3307    takes care of it.  */
   3308 static void
   3309 print_debug_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
   3310 			     GElf_Shdr *shdr, Dwarf *dbg)
   3311 {
   3312   Dwarf_Aranges *aranges;
   3313   size_t cnt;
   3314   if (dwarf_getaranges (dbg, &aranges, &cnt) != 0)
   3315     {
   3316       error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
   3317 	     dwarf_errmsg (-1));
   3318       return;
   3319     }
   3320 
   3321   printf (ngettext ("\
   3322 \nDWARF section '%s' at offset %#" PRIx64 " contains %zu entry:\n",
   3323 		    "\
   3324 \nDWARF section '%s' at offset %#" PRIx64 " contains %zu entries:\n",
   3325 		    cnt),
   3326 	  ".debug_aranges", (uint64_t) shdr->sh_offset, cnt);
   3327 
   3328   /* Compute floor(log16(cnt)).  */
   3329   size_t tmp = cnt;
   3330   int digits = 1;
   3331   while (tmp >= 16)
   3332     {
   3333       ++digits;
   3334       tmp >>= 4;
   3335     }
   3336 
   3337   for (size_t n = 0; n < cnt; ++n)
   3338     {
   3339       Dwarf_Arange *runp = dwarf_onearange (aranges, n);
   3340       if (runp == NULL)
   3341 	{
   3342 	  printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
   3343 	  return;
   3344 	}
   3345 
   3346       Dwarf_Addr start;
   3347       Dwarf_Word length;
   3348       Dwarf_Off offset;
   3349 
   3350       if (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0)
   3351 	printf (gettext (" [%*zu] ???\n"), digits, n);
   3352       else
   3353 	printf (gettext (" [%*zu] start: %0#*" PRIx64
   3354 			 ", length: %5" PRIu64 ", CU DIE offset: %6"
   3355 			 PRId64 "\n"),
   3356 		digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
   3357 		(uint64_t) start, (uint64_t) length, (int64_t) offset);
   3358     }
   3359 }
   3360 
   3361 
   3362 static void
   3363 print_debug_frame_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
   3364 			   GElf_Shdr *shdr, Dwarf *dbg)
   3365 {
   3366 }
   3367 
   3368 
   3369 struct attrcb_args
   3370 {
   3371   Dwarf *dbg;
   3372   int level;
   3373   unsigned int addrsize;
   3374   Dwarf_Off cu_offset;
   3375 };
   3376 
   3377 
   3378 static int
   3379 attr_callback (Dwarf_Attribute *attrp, void *arg)
   3380 {
   3381   struct attrcb_args *cbargs = (struct attrcb_args *) arg;
   3382   const int level = cbargs->level;
   3383 
   3384   unsigned int attr = dwarf_whatattr (attrp);
   3385   if (unlikely (attr == 0))
   3386     {
   3387       error (0, 0, gettext ("cannot get attribute code: %s"),
   3388 	     dwarf_errmsg (-1));
   3389       return DWARF_CB_ABORT;
   3390     }
   3391 
   3392   unsigned int form = dwarf_whatform (attrp);
   3393   if (unlikely (form == 0))
   3394     {
   3395       error (0, 0, gettext ("cannot get attribute form: %s"),
   3396 	     dwarf_errmsg (-1));
   3397       return DWARF_CB_ABORT;
   3398     }
   3399 
   3400   switch (form)
   3401     {
   3402     case DW_FORM_addr:;
   3403       Dwarf_Addr addr;
   3404       if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
   3405 	{
   3406 	attrval_out:
   3407 	  error (0, 0, gettext ("cannot get attribute value: %s"),
   3408 		 dwarf_errmsg (-1));
   3409 	  return DWARF_CB_ABORT;
   3410 	}
   3411       printf ("           %*s%-20s %#0*" PRIxMAX "\n",
   3412 	      (int) (level * 2), "", dwarf_attr_string (attr),
   3413 	      (int) (cbargs->addrsize * 2), (uintmax_t) addr);
   3414       break;
   3415 
   3416     case DW_FORM_indirect:
   3417     case DW_FORM_strp:
   3418     case DW_FORM_string:;
   3419       const char *str = dwarf_formstring (attrp);
   3420       if (unlikely (str == NULL))
   3421 	goto attrval_out;
   3422       printf ("           %*s%-20s \"%s\"\n",
   3423 	      (int) (level * 2), "", dwarf_attr_string (attr), str);
   3424       break;
   3425 
   3426     case DW_FORM_ref_addr:
   3427     case DW_FORM_ref_udata:
   3428     case DW_FORM_ref8:
   3429     case DW_FORM_ref4:
   3430     case DW_FORM_ref2:
   3431     case DW_FORM_ref1:;
   3432       Dwarf_Off ref;
   3433       if (unlikely (dwarf_formref (attrp, &ref) != 0))
   3434 	goto attrval_out;
   3435 
   3436       printf ("           %*s%-20s [%6" PRIxMAX "]\n",
   3437 	      (int) (level * 2), "", dwarf_attr_string (attr),
   3438 	      (uintmax_t) (ref + cbargs->cu_offset));
   3439       break;
   3440 
   3441     case DW_FORM_udata:
   3442     case DW_FORM_sdata:
   3443     case DW_FORM_data8:
   3444     case DW_FORM_data4:
   3445     case DW_FORM_data2:
   3446     case DW_FORM_data1:;
   3447       Dwarf_Word num;
   3448       if (unlikely (dwarf_formudata (attrp, &num) != 0))
   3449 	goto attrval_out;
   3450 
   3451       if (attr == DW_AT_language)
   3452 	{
   3453 	  printf ("           %*s%-20s %s (%d)\n",
   3454 		  (int) (level * 2), "", dwarf_attr_string (attr),
   3455 		  dwarf_lang_string (num), (int) num);
   3456 	  break;
   3457 	}
   3458 
   3459       printf ("           %*s%-20s %" PRIuMAX "\n",
   3460 	      (int) (level * 2), "", dwarf_attr_string (attr),
   3461 	      (uintmax_t) num);
   3462       break;
   3463 
   3464     case DW_FORM_flag:;
   3465       bool flag;
   3466       if (unlikely (dwarf_formflag (attrp, &flag) != 0))
   3467 	goto attrval_out;
   3468 
   3469       printf ("           %*s%-20s %s\n",
   3470 	      (int) (level * 2), "", dwarf_attr_string (attr),
   3471 	      nl_langinfo (flag ? YESSTR : NOSTR));
   3472       break;
   3473 
   3474     case DW_FORM_block4:
   3475     case DW_FORM_block2:
   3476     case DW_FORM_block1:
   3477     case DW_FORM_block:;
   3478       Dwarf_Block block;
   3479       if (unlikely (dwarf_formblock (attrp, &block) != 0))
   3480 	goto attrval_out;
   3481 
   3482       printf ("           %*s%-20s %" PRIxMAX " byte block\n",
   3483 	      (int) (level * 2), "", dwarf_attr_string (attr),
   3484 	      (uintmax_t) block.length);
   3485 
   3486       if (attr == DW_AT_data_member_location)
   3487 	print_ops (cbargs->dbg, level, cbargs->addrsize, block.length,
   3488 		   block.data);
   3489       break;
   3490 
   3491     default:
   3492       printf ("           %*s%-20s [form: %d] ???\n",
   3493 	      (int) (level * 2), "", dwarf_attr_string (attr),
   3494 	      (int) form);
   3495       break;
   3496     }
   3497 
   3498   return DWARF_CB_OK;
   3499 }
   3500 
   3501 
   3502 static void
   3503 print_debug_info_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
   3504 			  GElf_Shdr *shdr, Dwarf *dbg)
   3505 {
   3506   printf (gettext ("\
   3507 \nDWARF section '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
   3508 	  ".debug_info", (uint64_t) shdr->sh_offset);
   3509 
   3510   /* If the section is empty we don't have to do anything.  */
   3511   if (shdr->sh_size == 0)
   3512     return;
   3513 
   3514   size_t maxdies = 20;
   3515   Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
   3516 
   3517   Dwarf_Off offset = 0;
   3518 
   3519   /* New compilation unit.  */
   3520   size_t cuhl;
   3521   //Dwarf_Half version;
   3522   Dwarf_Off abbroffset;
   3523   uint8_t addrsize;
   3524   uint8_t offsize;
   3525   Dwarf_Off nextcu;
   3526  next_cu:
   3527   if (dwarf_nextcu (dbg, offset, &nextcu, &cuhl, &abbroffset, &addrsize,
   3528 		    &offsize) != 0)
   3529     goto do_return;
   3530 
   3531   printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
   3532 		   " Version: %" PRIu16 ", Abbreviation section offset: %"
   3533 		   PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8 "\n"),
   3534 	  (uint64_t) offset, /*version*/2, abbroffset, addrsize, offsize);
   3535 
   3536 
   3537   struct attrcb_args args;
   3538   args.dbg = dbg;
   3539   args.addrsize = addrsize;
   3540   args.cu_offset = offset;
   3541 
   3542   offset += cuhl;
   3543 
   3544   int level = 0;
   3545 
   3546   if (unlikely (dwarf_offdie (dbg, offset, &dies[level]) == NULL))
   3547     {
   3548       error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
   3549 			    " in section '%s': %s"),
   3550 	     (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
   3551       goto do_return;
   3552     }
   3553 
   3554   do
   3555     {
   3556       offset = dwarf_dieoffset (&dies[level]);
   3557       if (offset == -1l)
   3558 	{
   3559 	  error (0, 0, gettext ("cannot get DIE offset: %s"),
   3560 		 dwarf_errmsg (-1));
   3561 	  goto do_return;
   3562 	}
   3563 
   3564       int tag = dwarf_tag (&dies[level]);
   3565       if (tag == DW_TAG_invalid)
   3566 	{
   3567 	  error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
   3568 				" in section '%s': %s"),
   3569 		 (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
   3570 	  goto do_return;
   3571 	}
   3572 
   3573       static const char *const lowtags[] =
   3574 	{
   3575 	  [DW_TAG_array_type] = "array_type",
   3576 	  [DW_TAG_class_type] = "class_type",
   3577 	  [DW_TAG_entry_point] = "entry_point",
   3578 	  [DW_TAG_enumeration_type] = "enumeration_type",
   3579 	  [DW_TAG_formal_parameter] = "formal_parameter",
   3580 	  [DW_TAG_imported_declaration] = "imported_declaration",
   3581 	  [DW_TAG_label] = "label",
   3582 	  [DW_TAG_lexical_block] = "lexical_block",
   3583 	  [DW_TAG_member] = "member",
   3584 	  [DW_TAG_pointer_type] = "pointer_type",
   3585 	  [DW_TAG_reference_type] = "reference_type",
   3586 	  [DW_TAG_compile_unit] = "compile_unit",
   3587 	  [DW_TAG_string_type] = "string_type",
   3588 	  [DW_TAG_structure_type] = "structure_type",
   3589 	  [DW_TAG_subroutine_type] = "subroutine_type",
   3590 	  [DW_TAG_typedef] = "typedef",
   3591 	  [DW_TAG_union_type] = "union_type",
   3592 	  [DW_TAG_unspecified_parameters] = "unspecified_parameters",
   3593 	  [DW_TAG_variant] = "variant",
   3594 	  [DW_TAG_common_block] = "common_block",
   3595 	  [DW_TAG_common_inclusion] = "common_inclusion",
   3596 	  [DW_TAG_inheritance] = "inheritance",
   3597 	  [DW_TAG_inlined_subroutine] = "inlined_subroutine",
   3598 	  [DW_TAG_module] = "module",
   3599 	  [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
   3600 	  [DW_TAG_set_type] = "set_type",
   3601 	  [DW_TAG_subrange_type] = "subrange_type",
   3602 	  [DW_TAG_with_stmt] = "with_stmt",
   3603 	  [DW_TAG_access_declaration] = "access_declaration",
   3604 	  [DW_TAG_base_type] = "base_type",
   3605 	  [DW_TAG_catch_block] = "catch_block",
   3606 	  [DW_TAG_const_type] = "const_type",
   3607 	  [DW_TAG_constant] = "constant",
   3608 	  [DW_TAG_enumerator] = "enumerator",
   3609 	  [DW_TAG_file_type] = "file_type",
   3610 	  [DW_TAG_friend] = "friend",
   3611 	  [DW_TAG_namelist] = "namelist",
   3612 	  [DW_TAG_namelist_item] = "namelist_item",
   3613 	  [DW_TAG_packed_type] = "packed_type",
   3614 	  [DW_TAG_subprogram] = "subprogram",
   3615 	  [DW_TAG_template_type_param] = "template_type_param",
   3616 	  [DW_TAG_template_value_param] = "template_value_param",
   3617 	  [DW_TAG_thrown_type] = "thrown_type",
   3618 	  [DW_TAG_try_block] = "try_block",
   3619 	  [DW_TAG_variant_part] = "variant_part",
   3620 	  [DW_TAG_variable] = "variable",
   3621 	  [DW_TAG_volatile_type] = "volatile_type"
   3622 	};
   3623 
   3624       const char *tagstr;
   3625       switch (tag)
   3626 	{
   3627 	case DW_TAG_lo_user:
   3628 	  tagstr = "lo_user";
   3629 	  break;
   3630 
   3631 	case DW_TAG_MIPS_loop:
   3632 	  tagstr = "MIPS_loop";
   3633 	  break;
   3634 
   3635 	case DW_TAG_format_label:
   3636 	  tagstr = "format_label";
   3637 	  break;
   3638 
   3639 	case DW_TAG_function_template:
   3640 	  tagstr = "function_template";
   3641 	  break;
   3642 
   3643 	case DW_TAG_class_template:
   3644 	  tagstr = "class_template";
   3645 	  break;
   3646 	case DW_TAG_hi_user:
   3647 	  tagstr = "hi_user";
   3648 	  break;
   3649 
   3650 	default:
   3651 	  if (tag < sizeof (lowtags) / sizeof (lowtags[0]))
   3652 	    tagstr = lowtags[tag];
   3653 	  else
   3654 	    tagstr = "???";
   3655 	  break;
   3656 	}
   3657 
   3658       printf (" [%6" PRIx64 "]  %*s%s\n",
   3659 	      (uint64_t) offset, (int) (level * 2), "", tagstr);
   3660 
   3661       /* Print the attribute values.  */
   3662       args.level = level;
   3663       (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
   3664 
   3665       /* Make room for the next level's DIE.  */
   3666       if (level + 1 == maxdies)
   3667 	dies = (Dwarf_Die *) xrealloc (dies,
   3668 				       (maxdies += 10)
   3669 				       * sizeof (Dwarf_Die));
   3670 
   3671       int res = dwarf_child (&dies[level], &dies[level + 1]);
   3672       if (res > 0)
   3673 	{
   3674 	  while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
   3675 	    if (level-- == 0)
   3676 	      break;
   3677 
   3678 	  if (res == -1)
   3679 	    {
   3680 	      error (0, 0, gettext ("cannot get next DIE: %s\n"),
   3681 		     dwarf_errmsg (-1));
   3682 	      goto do_return;
   3683 	    }
   3684 	}
   3685       else if (unlikely (res < 0))
   3686 	{
   3687 	  error (0, 0, gettext ("cannot get next DIE: %s"),
   3688 		 dwarf_errmsg (-1));
   3689 	  goto do_return;
   3690 	}
   3691       else
   3692 	++level;
   3693     }
   3694   while (level >= 0);
   3695 
   3696   offset = nextcu;
   3697   if (offset != 0)
   3698      goto next_cu;
   3699 
   3700  do_return:
   3701   free (dies);
   3702 }
   3703 
   3704 
   3705 static void
   3706 print_debug_line_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
   3707 			  GElf_Shdr *shdr, Dwarf *dbg)
   3708 {
   3709   printf (gettext ("\
   3710 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
   3711 	  ".debug_line", (uint64_t) shdr->sh_offset);
   3712 
   3713   if (shdr->sh_size == 0)
   3714     return;
   3715 
   3716   /* There is no functionality in libdw to read the information in the
   3717      way it is represented here.  Hardcode the decoder.  */
   3718   Elf_Data *data = elf_getdata (scn, NULL);
   3719   if (data == NULL || data->d_buf == NULL)
   3720     {
   3721       error (0, 0, gettext ("cannot get line data section data: %s"),
   3722 	     elf_errmsg (-1));
   3723       return;
   3724     }
   3725 
   3726   const unsigned char *linep = (const unsigned char *) data->d_buf;
   3727   const unsigned char *lineendp;
   3728 
   3729   while (linep
   3730 	 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
   3731     {
   3732       size_t start_offset = linep - (const unsigned char *) data->d_buf;
   3733 
   3734       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
   3735       unsigned int length = 4;
   3736       if (unlikely (unit_length == 0xffffffff))
   3737 	{
   3738 	  if (unlikely (linep + 8 > lineendp))
   3739 	    {
   3740 	    invalid_data:
   3741 	      error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
   3742 		     elf_ndxscn (scn), ".debug_line");
   3743 	      return;
   3744 	    }
   3745 	  unit_length = read_8ubyte_unaligned_inc (dbg, linep);
   3746 	  length = 8;
   3747 	}
   3748 
   3749       /* Check whether we have enough room in the section.  */
   3750       if (unit_length < 2 + length + 5 * 1
   3751 	  || unlikely (linep + unit_length > lineendp))
   3752 	goto invalid_data;
   3753       lineendp = linep + unit_length;
   3754 
   3755       /* The next element of the header is the version identifier.  */
   3756       uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
   3757 
   3758       /* Next comes the header length.  */
   3759       Dwarf_Word header_length;
   3760       if (length == 4)
   3761 	header_length = read_4ubyte_unaligned_inc (dbg, linep);
   3762       else
   3763 	header_length = read_8ubyte_unaligned_inc (dbg, linep);
   3764       //const unsigned char *header_start = linep;
   3765 
   3766       /* Next the minimum instruction length.  */
   3767       uint_fast8_t minimum_instr_len = *linep++;
   3768 
   3769         /* Then the flag determining the default value of the is_stmt
   3770 	   register.  */
   3771       uint_fast8_t default_is_stmt = *linep++;
   3772 
   3773       /* Now the line base.  */
   3774       int_fast8_t line_base = *((const int_fast8_t *) linep);
   3775       ++linep;
   3776 
   3777       /* And the line range.  */
   3778       uint_fast8_t line_range = *linep++;
   3779 
   3780       /* The opcode base.  */
   3781       uint_fast8_t opcode_base = *linep++;
   3782 
   3783       /* Print what we got so far.  */
   3784       printf (gettext ("\n"
   3785 		       " Length:                     %" PRIu64 "\n"
   3786 		       " DWARF version:              %" PRIuFAST16 "\n"
   3787 		       " Prologue length:            %" PRIu64 "\n"
   3788 		       " Minimum instruction length: %" PRIuFAST8 "\n"
   3789 		       " Initial value if '%s': %" PRIuFAST8 "\n"
   3790 		       " Line base:                  %" PRIdFAST8 "\n"
   3791 		       " Line range:                 %" PRIuFAST8 "\n"
   3792 		       " Opcode base:                %" PRIuFAST8 "\n"
   3793 		       "\n"
   3794 		       "Opcodes:\n"),
   3795 	      (uint64_t) unit_length, version, (uint64_t) header_length,
   3796 	      minimum_instr_len, "is_stmt", default_is_stmt, line_base,
   3797 	      line_range, opcode_base);
   3798 
   3799       if (unlikely (linep + opcode_base - 1 >= lineendp))
   3800 	goto invalid_data;
   3801       int opcode_base_l10 = 1;
   3802       unsigned int tmp = opcode_base;
   3803       while (tmp > 10)
   3804 	{
   3805 	  tmp /= 10;
   3806 	  ++opcode_base_l10;
   3807 	}
   3808       const uint8_t *standard_opcode_lengths = linep - 1;
   3809       for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
   3810 	printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
   3811 			  "  [%*" PRIuFAST8 "]  %hhu arguments\n",
   3812 			  (int) linep[cnt - 1]),
   3813 		opcode_base_l10, cnt, linep[cnt - 1]);
   3814       linep += opcode_base - 1;
   3815       if (unlikely (linep >= lineendp))
   3816 	goto invalid_data;
   3817 
   3818       puts (gettext ("\nDirectory table:"));
   3819       while (*linep != 0)
   3820 	{
   3821 	  unsigned char *endp = memchr (linep, '\0', lineendp - linep);
   3822 	  if (endp == NULL)
   3823 	    goto invalid_data;
   3824 
   3825 	  printf (" %s\n", (char *) linep);
   3826 
   3827 	  linep = endp + 1;
   3828 	}
   3829       /* Skip the final NUL byte.  */
   3830       ++linep;
   3831 
   3832       if (unlikely (linep >= lineendp))
   3833 	goto invalid_data;
   3834       puts (gettext ("\nFile name table:\n"
   3835 		     " Entry Dir   Time      Size      Name"));
   3836       for (unsigned int cnt = 1; *linep != 0; ++cnt)
   3837 	{
   3838 	  /* First comes the file name.  */
   3839 	  char *fname = (char *) linep;
   3840 	  unsigned char *endp = memchr (fname, '\0', lineendp - linep);
   3841 	  if (endp == NULL)
   3842 	    goto invalid_data;
   3843 	  linep = endp + 1;
   3844 
   3845 	  /* Then the index.  */
   3846 	  unsigned int diridx;
   3847 	  get_uleb128 (diridx, linep);
   3848 
   3849 	  /* Next comes the modification time.  */
   3850 	  unsigned int mtime;
   3851 	  get_uleb128 (mtime, linep);
   3852 
   3853 	  /* Finally the length of the file.  */
   3854 	  unsigned int fsize;
   3855 	  get_uleb128 (fsize, linep);
   3856 
   3857 	  printf (" %-5u %-5u %-9u %-9u %s\n",
   3858 		  cnt, diridx, mtime, fsize, fname);
   3859 	}
   3860       /* Skip the final NUL byte.  */
   3861       ++linep;
   3862 
   3863       puts (gettext ("\nLine number statements:"));
   3864       Dwarf_Word address = 0;
   3865       size_t line = 1;
   3866       uint_fast8_t is_stmt = default_is_stmt;
   3867 
   3868       /* Default address value, in case we do not find the CU.  */
   3869       size_t address_size
   3870 	= elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
   3871 
   3872       /* Determine the CU this block is for.  */
   3873       Dwarf_Off cuoffset;
   3874       Dwarf_Off ncuoffset = 0;
   3875       size_t hsize;
   3876       while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
   3877 			   NULL, NULL, NULL) == 0)
   3878 	{
   3879 	  Dwarf_Die cudie;
   3880 	  if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
   3881 	    continue;
   3882 	  Dwarf_Attribute stmt_list;
   3883 	  if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
   3884 	    continue;
   3885 	  Dwarf_Word lineoff;
   3886 	  if (dwarf_formudata (&stmt_list, &lineoff) != 0)
   3887 	    continue;
   3888 	  if (lineoff == start_offset)
   3889 	    {
   3890 	      /* Found the CU.  */
   3891 	      address_size = cudie.cu->address_size;
   3892 	      break;
   3893 	    }
   3894 	}
   3895 
   3896       while (linep < lineendp)
   3897 	{
   3898 	  unsigned int u128;
   3899 	  int s128;
   3900 
   3901 	  /* Read the opcode.  */
   3902 	  unsigned int opcode = *linep++;
   3903 
   3904 	  /* Is this a special opcode?  */
   3905 	  if (likely (opcode >= opcode_base))
   3906 	    {
   3907 	      /* Yes.  Handling this is quite easy since the opcode value
   3908 		 is computed with
   3909 
   3910 		 opcode = (desired line increment - line_base)
   3911 		           + (line_range * address advance) + opcode_base
   3912 	      */
   3913 	      int line_increment = (line_base
   3914 				    + (opcode - opcode_base) % line_range);
   3915 	      unsigned int address_increment = (minimum_instr_len
   3916 						* ((opcode - opcode_base)
   3917 						   / line_range));
   3918 
   3919 	      /* Perform the increments.  */
   3920 	      line += line_increment;
   3921 	      address += address_increment;
   3922 
   3923 	      printf (gettext ("\
   3924  special opcode %u: address+%u = %#" PRIx64 ", line%+d = %zu\n"),
   3925 		      opcode, address_increment, (uint64_t) address,
   3926 		      line_increment, line);
   3927 	    }
   3928 	  else if (opcode == 0)
   3929 	    {
   3930 	      /* This an extended opcode.  */
   3931 	      if (unlikely (linep + 2 > lineendp))
   3932 		goto invalid_data;
   3933 
   3934 	      /* The length.  */
   3935 	      unsigned int len = *linep++;
   3936 
   3937 	      if (unlikely (linep + len > lineendp))
   3938 		goto invalid_data;
   3939 
   3940 	      /* The sub-opcode.  */
   3941 	      opcode = *linep++;
   3942 
   3943 	      printf (gettext (" extended opcode %u: "), opcode);
   3944 
   3945 	      switch (opcode)
   3946 		{
   3947 		case DW_LNE_end_sequence:
   3948 		  puts (gettext ("end of sequence"));
   3949 
   3950 		  /* Reset the registers we care about.  */
   3951 		  address = 0;
   3952 		  line = 1;
   3953 		  is_stmt = default_is_stmt;
   3954 		  break;
   3955 
   3956 		case DW_LNE_set_address:
   3957 		  if (address_size == 4)
   3958 		    address = read_4ubyte_unaligned_inc (dbg, linep);
   3959 		  else
   3960 		    address = read_8ubyte_unaligned_inc (dbg, linep);
   3961 		  printf (gettext ("set address to %#" PRIx64 "\n"),
   3962 			  (uint64_t) address);
   3963 		  break;
   3964 
   3965 		case DW_LNE_define_file:
   3966 		  {
   3967 		    char *fname = (char *) linep;
   3968 		    unsigned char *endp = memchr (linep, '\0',
   3969 						  lineendp - linep);
   3970 		    if (endp == NULL)
   3971 		      goto invalid_data;
   3972 		    linep = endp + 1;
   3973 
   3974 		    unsigned int diridx;
   3975 		    get_uleb128 (diridx, linep);
   3976 		    Dwarf_Word mtime;
   3977 		    get_uleb128 (mtime, linep);
   3978 		    Dwarf_Word filelength;
   3979 		    get_uleb128 (filelength, linep);
   3980 
   3981 		    printf (gettext ("\
   3982 define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
   3983 			    diridx, (uint64_t) mtime, (uint64_t) filelength,
   3984 			    fname);
   3985 		  }
   3986 		  break;
   3987 
   3988 		default:
   3989 		  /* Unknown, ignore it.  */
   3990 		  puts (gettext ("unknown opcode"));
   3991 		  linep += len - 1;
   3992 		  break;
   3993 		}
   3994 	    }
   3995 	  else if (opcode <= DW_LNS_set_epilog_begin)
   3996 	    {
   3997 	      /* This is a known standard opcode.  */
   3998 	      switch (opcode)
   3999 		{
   4000 		case DW_LNS_copy:
   4001 		  /* Takes no argument.  */
   4002 		  puts (gettext (" copy"));
   4003 		  break;
   4004 
   4005 		case DW_LNS_advance_pc:
   4006 		  /* Takes one uleb128 parameter which is added to the
   4007 		     address.  */
   4008 		  get_uleb128 (u128, linep);
   4009 		  address += minimum_instr_len * u128;
   4010 		  printf (gettext ("\
   4011  advance address by %u to %#" PRIx64 "\n"),
   4012 			  u128, (uint64_t) address);
   4013 		  break;
   4014 
   4015 		case DW_LNS_advance_line:
   4016 		  /* Takes one sleb128 parameter which is added to the
   4017 		     line.  */
   4018 		  get_sleb128 (s128, linep);
   4019 		  line += s128;
   4020 		  printf (gettext ("\
   4021  advance line by constant %d to %" PRId64 "\n"),
   4022 			  s128, (int64_t) line);
   4023 		  break;
   4024 
   4025 		case DW_LNS_set_file:
   4026 		  /* Takes one uleb128 parameter which is stored in file.  */
   4027 		  get_uleb128 (u128, linep);
   4028 		  printf (gettext (" set file to %" PRIu64 "\n"),
   4029 			  (uint64_t) u128);
   4030 		  break;
   4031 
   4032 		case DW_LNS_set_column:
   4033 		  /* Takes one uleb128 parameter which is stored in column.  */
   4034 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
   4035 		    goto invalid_data;
   4036 
   4037 		  get_uleb128 (u128, linep);
   4038 		  printf (gettext (" set column to %" PRIu64 "\n"),
   4039 			  (uint64_t) u128);
   4040 		  break;
   4041 
   4042 		case DW_LNS_negate_stmt:
   4043 		  /* Takes no argument.  */
   4044 		  is_stmt = 1 - is_stmt;
   4045 		  printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
   4046 			  "is_stmt", is_stmt);
   4047 		  break;
   4048 
   4049 		case DW_LNS_set_basic_block:
   4050 		  /* Takes no argument.  */
   4051 		  puts (gettext (" set basic block flag"));
   4052 		  break;
   4053 
   4054 		case DW_LNS_const_add_pc:
   4055 		  /* Takes no argument.  */
   4056 		  u128 = (minimum_instr_len
   4057 			  * ((255 - opcode_base) / line_range));
   4058 		  address += u128;
   4059 		  printf (gettext ("\
   4060  advance address by constant %u to %#" PRIx64 "\n"),
   4061 			  u128, (uint64_t) address);
   4062 		  break;
   4063 
   4064 		case DW_LNS_fixed_advance_pc:
   4065 		  /* Takes one 16 bit parameter which is added to the
   4066 		     address.  */
   4067 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
   4068 		    goto invalid_data;
   4069 
   4070 		  u128 = read_2ubyte_unaligned_inc (dbg, linep);
   4071 		  address += u128;
   4072 		  printf (gettext ("\
   4073  advance address by fixed value %u to %#" PRIx64 "\n"),
   4074 			  u128, (uint64_t) address);
   4075 		  break;
   4076 
   4077 		case DW_LNS_set_prologue_end:
   4078 		  /* Takes no argument.  */
   4079 		  puts (gettext (" set prologue end flag"));
   4080 		  break;
   4081 
   4082 		case DW_LNS_set_epilog_begin:
   4083 		  /* Takes no argument.  */
   4084 		  puts (gettext (" set epilogue begin flag"));
   4085 		  break;
   4086 		}
   4087 	    }
   4088 	  else
   4089 	    {
   4090 	      /* This is a new opcode the generator but not we know about.
   4091 		 Read the parameters associated with it but then discard
   4092 		 everything.  Read all the parameters for this opcode.  */
   4093 	      printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
   4094 				" unknown opcode with %" PRIu8 " parameters:",
   4095 				standard_opcode_lengths[opcode]),
   4096 		      standard_opcode_lengths[opcode]);
   4097 	      for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
   4098 		{
   4099 		  get_uleb128 (u128, linep);
   4100 		  if (n != standard_opcode_lengths[opcode])
   4101 		    putc_unlocked (',', stdout);
   4102 		  printf (" %u", u128);
   4103 		}
   4104 
   4105 	      /* Next round, ignore this opcode.  */
   4106 	      continue;
   4107 	    }
   4108 	}
   4109     }
   4110 
   4111   /* There must only be one data block.  */
   4112   assert (elf_getdata (scn, data) == NULL);
   4113 }
   4114 
   4115 
   4116 static void
   4117 print_debug_loc_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
   4118 			 GElf_Shdr *shdr, Dwarf *dbg)
   4119 {
   4120   printf (gettext ("\
   4121 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
   4122 	  ".debug_loc", (uint64_t) shdr->sh_offset);
   4123 
   4124   // XXX add something
   4125 }
   4126 
   4127 
   4128 struct mac_culist
   4129 {
   4130   Dwarf_Die die;
   4131   Dwarf_Off offset;
   4132   Dwarf_Files *files;
   4133   struct mac_culist *next;
   4134 };
   4135 
   4136 
   4137 static int
   4138 mac_compare (const void *p1, const void *p2)
   4139 {
   4140   struct mac_culist *m1 = (struct mac_culist *) p1;
   4141   struct mac_culist *m2 = (struct mac_culist *) p2;
   4142 
   4143   if (m1->offset < m2->offset)
   4144     return -1;
   4145   if (m1->offset > m2->offset)
   4146     return 1;
   4147   return 0;
   4148 }
   4149 
   4150 
   4151 static void
   4152 print_debug_macinfo_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
   4153 			 GElf_Shdr *shdr, Dwarf *dbg)
   4154 {
   4155   printf (gettext ("\
   4156 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
   4157 	  ".debug_macinfo", (uint64_t) shdr->sh_offset);
   4158   putc_unlocked ('\n', stdout);
   4159 
   4160   /* There is no function in libdw to iterate over the raw content of
   4161      the section but it is easy enough to do.  */
   4162   Elf_Data *data = elf_getdata (scn, NULL);
   4163   if (data == NULL || data->d_buf == NULL)
   4164     {
   4165       error (0, 0, gettext ("cannot get macro information section data: %s"),
   4166 	     elf_errmsg (-1));
   4167       return;
   4168     }
   4169 
   4170   /* Get the source file information for all CUs.  */
   4171   Dwarf_Off offset;
   4172   Dwarf_Off ncu = 0;
   4173   size_t hsize;
   4174   struct mac_culist *culist = NULL;
   4175   size_t nculist = 0;
   4176   while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
   4177     {
   4178       Dwarf_Die cudie;
   4179       if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
   4180 	continue;
   4181 
   4182       Dwarf_Attribute attr;
   4183       if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
   4184 	continue;
   4185 
   4186       Dwarf_Word macoff;
   4187       if (dwarf_formudata (&attr, &macoff) != 0)
   4188 	continue;
   4189 
   4190       struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
   4191       newp->die = cudie;
   4192       newp->offset = macoff;
   4193       newp->files = NULL;
   4194       newp->next = culist;
   4195       culist = newp;
   4196       ++nculist;
   4197     }
   4198 
   4199   /* Convert the list into an array for easier consumption.  */
   4200   struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
   4201 							 * sizeof (*cus));
   4202   /* Add sentinel.  */
   4203   cus[nculist].offset = data->d_size;
   4204   if (nculist > 0)
   4205     {
   4206       for (size_t cnt = nculist - 1; culist != NULL; --cnt)
   4207 	{
   4208 	  assert (cnt < nculist);
   4209 	  cus[cnt] = *culist;
   4210 	  culist = culist->next;
   4211 	}
   4212 
   4213       /* Sort the array according to the offset in the .debug_macinfo
   4214 	 section.  Note we keep the sentinel at the end.  */
   4215       qsort (cus, nculist, sizeof (*cus), mac_compare);
   4216     }
   4217 
   4218   const unsigned char *readp = (const unsigned char *) data->d_buf;
   4219   const unsigned char *readendp = readp + data->d_size;
   4220   int level = 1;
   4221 
   4222   while (readp < readendp)
   4223     {
   4224       unsigned int opcode = *readp++;
   4225       unsigned int u128;
   4226       unsigned int u128_2;
   4227       const unsigned char *endp;
   4228 
   4229       switch (opcode)
   4230 	{
   4231 	case DW_MACINFO_define:
   4232 	case DW_MACINFO_undef:
   4233 	case DW_MACINFO_vendor_ext:
   4234 	  /*  For the first two opcodes the parameters are
   4235 	        line, string
   4236 	      For the latter
   4237 	        number, string.
   4238 	      We can treat these cases together.  */
   4239 	  get_uleb128 (u128, readp);
   4240 
   4241 	  endp = memchr (readp, '\0', readendp - readp);
   4242 	  if (endp == NULL)
   4243 	    {
   4244 	      printf (gettext ("\
   4245 %*s*** non-terminated string at end of section"),
   4246 		      level, "");
   4247 	      return;
   4248 	    }
   4249 
   4250 	  if (opcode == DW_MACINFO_define)
   4251 	    printf ("%*s#define %s, line %u\n",
   4252 		    level, "", (char *) readp, u128);
   4253 	  else if (opcode == DW_MACINFO_undef)
   4254 	    printf ("%*s#undef %s, line %u\n",
   4255 		    level, "", (char *) readp, u128);
   4256 	  else
   4257 	    printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
   4258 
   4259 	  readp = endp + 1;
   4260 	  break;
   4261 
   4262 	case DW_MACINFO_start_file:
   4263 	  /* The two parameters are line and file index, in this order.  */
   4264 	  get_uleb128 (u128, readp);
   4265 	  get_uleb128 (u128_2, readp);
   4266 
   4267 	  /* Find the CU DIE for this file.  */
   4268 	  ptrdiff_t macoff = readp - (const unsigned char *) data->d_buf;
   4269 	  const char *fname = "???";
   4270 	  if (macoff >= cus[0].offset)
   4271 	    {
   4272 	      while (macoff >= cus[1].offset)
   4273 		++cus;
   4274 
   4275 	      if (cus[0].files == NULL
   4276 		&& dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
   4277 		cus[0].files = (Dwarf_Files *) -1l;
   4278 
   4279 	      if (cus[0].files != (Dwarf_Files *) -1l)
   4280 		fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
   4281 			 ?: "???");
   4282 	    }
   4283 
   4284 	  printf ("%*sstart_file %u, [%u] %s\n",
   4285 		  level, "", u128, u128_2, fname);
   4286 	  ++level;
   4287 	  break;
   4288 
   4289 	case DW_MACINFO_end_file:
   4290 	  --level;
   4291 	  printf ("%*send_file\n", level, "");
   4292 	  /* Nothing more to do.  */
   4293 	  break;
   4294 
   4295 	default:
   4296 	  // XXX gcc seems to generate files with a trailing zero.
   4297 	  if (opcode != 0 || readp != readendp)
   4298 	    printf ("%*s*** invalid opcode %u\n", level, "", opcode);
   4299 	  break;
   4300 	}
   4301     }
   4302 }
   4303 
   4304 
   4305 /* Callback for printing global names.  */
   4306 static int
   4307 print_pubnames (Dwarf *dbg, Dwarf_Global *global, void *arg)
   4308 {
   4309   int *np = (int *) arg;
   4310 
   4311   printf (gettext (" [%5d] DIE offset: %6" PRId64
   4312 		   ", CU DIE offset: %6" PRId64 ", name: %s\n"),
   4313 	  (*np)++, global->die_offset, global->cu_offset, global->name);
   4314 
   4315   return 0;
   4316 }
   4317 
   4318 
   4319 /* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
   4320 static void
   4321 print_debug_pubnames_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
   4322 			      GElf_Shdr *shdr, Dwarf *dbg)
   4323 {
   4324   printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
   4325 	  ".debug_pubnames", (uint64_t) shdr->sh_offset);
   4326 
   4327   int n = 0;
   4328   (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
   4329 }
   4330 
   4331 /* Print the content of the DWARF string section '.debug_str'.  */
   4332 static void
   4333 print_debug_str_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
   4334 			 GElf_Shdr *shdr, Dwarf *dbg)
   4335 {
   4336   /* Compute floor(log16(shdr->sh_size)).  */
   4337   GElf_Addr tmp = shdr->sh_size;
   4338   int digits = 1;
   4339   while (tmp >= 16)
   4340     {
   4341       ++digits;
   4342       tmp >>= 4;
   4343     }
   4344   digits = MAX (4, digits);
   4345 
   4346   printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
   4347 		   " %*s  String\n"),
   4348 	  ".debug_str", (uint64_t) shdr->sh_offset,
   4349 	  /* TRANS: the debugstr| prefix makes the string unique.  */
   4350 	  digits + 2, sgettext ("debugstr|Offset"));
   4351 
   4352   Dwarf_Off offset = 0;
   4353   while (offset < shdr->sh_size)
   4354     {
   4355       size_t len;
   4356       const char *str = dwarf_getstring (dbg, offset, &len);
   4357       if (str == NULL)
   4358 	{
   4359 	  printf (gettext (" *** error while reading strings: %s\n"),
   4360 		  dwarf_errmsg (-1));
   4361 	  break;
   4362 	}
   4363 
   4364       printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
   4365 
   4366       offset += len + 1;
   4367     }
   4368 }
   4369 
   4370 
   4371 static void
   4372 print_debug (Ebl *ebl, GElf_Ehdr *ehdr)
   4373 {
   4374   /* Find the version information sections.  For this we have to
   4375      search through the section table.  */
   4376   Dwarf *dbg;
   4377   Elf_Scn *scn;
   4378   size_t shstrndx;
   4379 
   4380   /* Before we start the real work get a debug context descriptor.  */
   4381   dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
   4382   if (dbg == NULL)
   4383     {
   4384       error (0, 0, gettext ("cannot get debug context descriptor: %s"),
   4385 	     dwarf_errmsg (-1));
   4386       return;
   4387     }
   4388 
   4389   /* Get the section header string table index.  */
   4390   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
   4391     error (EXIT_FAILURE, 0,
   4392 	   gettext ("cannot get section header string table index"));
   4393 
   4394   scn = NULL;
   4395   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
   4396     {
   4397       /* Handle the section if it is part of the versioning handling.  */
   4398       GElf_Shdr shdr_mem;
   4399       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   4400 
   4401       if (shdr != NULL || shdr->sh_type != SHT_PROGBITS)
   4402 	{
   4403 	  static const struct
   4404 	  {
   4405 	    const char *name;
   4406 	    enum section_e bitmask;
   4407 	    void (*fp) (Ebl *, GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
   4408 	  } debug_sections[] =
   4409 	    {
   4410 #define NEW_SECTION(name) \
   4411 	      { ".debug_" #name, section_##name, print_debug_##name##_section }
   4412 	      NEW_SECTION (abbrev),
   4413 	      NEW_SECTION (aranges),
   4414 	      NEW_SECTION (frame),
   4415 	      NEW_SECTION (info),
   4416 	      NEW_SECTION (line),
   4417 	      NEW_SECTION (loc),
   4418 	      NEW_SECTION (pubnames),
   4419 	      NEW_SECTION (str),
   4420 	      NEW_SECTION (macinfo),
   4421 	      { ".eh_frame", section_frame, print_debug_frame_section }
   4422 	    };
   4423 	  const int ndebug_sections = (sizeof (debug_sections)
   4424 				       / sizeof (debug_sections[0]));
   4425 	  const char *name = elf_strptr (ebl->elf, shstrndx,
   4426 					 shdr->sh_name);
   4427 	  int n;
   4428 
   4429 	  for (n = 0; n < ndebug_sections; ++n)
   4430 	    if (strcmp (name, debug_sections[n].name) == 0)
   4431 	      {
   4432 		if (print_debug_sections & debug_sections[n].bitmask)
   4433 		  debug_sections[n].fp (ebl, ehdr, scn, shdr, dbg);
   4434 		break;
   4435 	      }
   4436 	}
   4437     }
   4438 
   4439   /* We are done with the DWARF handling.  */
   4440   dwarf_end (dbg);
   4441 }
   4442 
   4443 
   4444 static void
   4445 handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
   4446 {
   4447   int class = gelf_getclass (ebl->elf);
   4448   size_t cnt;
   4449 
   4450   /* We have to look through the program header to find the note
   4451      sections.  There can be more than one.  */
   4452   for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
   4453     {
   4454       GElf_Phdr mem;
   4455       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
   4456 
   4457       if (phdr == NULL || phdr->p_type != PT_NOTE)
   4458 	/* Not what we are looking for.  */
   4459 	continue;
   4460 
   4461       printf (gettext ("\
   4462 \nNote segment of %" PRId64 " bytes at offset %#0" PRIx64 ":\n"),
   4463 	      phdr->p_filesz, phdr->p_offset);
   4464 
   4465       char *notemem = gelf_rawchunk (ebl->elf, phdr->p_offset, phdr->p_filesz);
   4466       if (notemem == NULL)
   4467 	error (EXIT_FAILURE, 0,
   4468 	       gettext ("cannot get content of note section: %s"),
   4469 	       elf_errmsg (-1));
   4470 
   4471       fputs_unlocked (gettext ("  Owner          Data size  Type\n"), stdout);
   4472 
   4473 
   4474       /* Handle the note section content.  It consists of one or more
   4475 	 entries each of which consists of five parts:
   4476 
   4477 	 - a 32-bit name length
   4478 	 - a 32-bit descriptor length
   4479 	 - a 32-bit type field
   4480 	 - the NUL-terminated name, length as specified in the first field
   4481 	 - the descriptor, length as specified in the second field
   4482 
   4483 	 The variable sized fields are padded to 32- or 64-bits
   4484 	 depending on whether the file is a 32- or 64-bit ELF file.
   4485       */
   4486       size_t align = class == ELFCLASS32 ? 4 : 8;
   4487 #define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1))
   4488 
   4489       size_t idx = 0;
   4490       while (idx < phdr->p_filesz)
   4491 	{
   4492 	  /* XXX Handle 64-bit note section entries correctly.  */
   4493 	  struct
   4494 	  {
   4495 	    uint32_t namesz;
   4496 	    uint32_t descsz;
   4497 	    uint32_t type;
   4498 	    char name[0];
   4499 	  } *noteentry = (__typeof (noteentry)) (notemem + idx);
   4500 
   4501 	  if (idx + 12 > phdr->p_filesz
   4502 	      || (idx + 12 + ALIGNED_LEN (noteentry->namesz)
   4503 		  + ALIGNED_LEN (noteentry->descsz) > phdr->p_filesz))
   4504 	    /* This entry isn't completely contained in the note
   4505 	       section.  Ignore it.  */
   4506 	    break;
   4507 
   4508 	  char buf[100];
   4509 	  char buf2[100];
   4510 	  printf (gettext ("  %-13.*s  %9" PRId32 "  %s\n"),
   4511 		  (int) noteentry->namesz, noteentry->name,
   4512 		  noteentry->descsz,
   4513 		  ehdr->e_type == ET_CORE
   4514 		  ? ebl_core_note_type_name (ebl, noteentry->type,
   4515 					     buf, sizeof (buf))
   4516 		  : ebl_object_note_type_name (ebl, noteentry->type,
   4517 					       buf2, sizeof (buf2)));
   4518 
   4519 	  /* Filter out invalid entries.  */
   4520 	  if (memchr (noteentry->name, '\0', noteentry->namesz) != NULL
   4521 	      /* XXX For now help broken Linux kernels.  */
   4522 	      || 1)
   4523 	    {
   4524 	      if (ehdr->e_type == ET_CORE)
   4525 		ebl_core_note (ebl, noteentry->name, noteentry->type,
   4526 			       noteentry->descsz,
   4527 			       &noteentry->name[ALIGNED_LEN (noteentry->namesz)]);
   4528 	      else
   4529 		ebl_object_note (ebl, noteentry->name, noteentry->type,
   4530 				 noteentry->descsz,
   4531 				 &noteentry->name[ALIGNED_LEN (noteentry->namesz)]);
   4532 	    }
   4533 
   4534 	  /* Move to the next entry.  */
   4535 	  idx += (12 + ALIGNED_LEN (noteentry->namesz)
   4536 		  + ALIGNED_LEN (noteentry->descsz));
   4537 	}
   4538 
   4539       gelf_freechunk (ebl->elf, notemem);
   4540     }
   4541 }
   4542