1/* Print information from ELF file in human-readable form.
2   Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Red Hat, Inc.
3   This file is part of Red Hat elfutils.
4   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
5
6   Red Hat elfutils is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by the
8   Free Software Foundation; version 2 of the License.
9
10   Red Hat elfutils is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   General Public License for more details.
14
15   You should have received a copy of the GNU General Public License along
16   with Red Hat elfutils; if not, write to the Free Software Foundation,
17   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18
19   Red Hat elfutils is an included package of the Open Invention Network.
20   An included package of the Open Invention Network is a package for which
21   Open Invention Network licensees cross-license their patents.  No patent
22   license is granted, either expressly or impliedly, by designation as an
23   included package.  Should you wish to participate in the Open Invention
24   Network licensing program, please visit www.openinventionnetwork.com
25   <http://www.openinventionnetwork.com>.  */
26
27#ifdef HAVE_CONFIG_H
28# include <config.h>
29#endif
30
31#include <argp.h>
32#include <assert.h>
33#include <ctype.h>
34#include <dwarf.h>
35#include <errno.h>
36#include <error.h>
37#include <fcntl.h>
38#include <gelf.h>
39#include <inttypes.h>
40#include <langinfo.h>
41#include <libdw.h>
42#include <libdwfl.h>
43#include <libintl.h>
44#include <locale.h>
45#include <stdarg.h>
46#include <stdbool.h>
47#include <stdlib.h>
48#include <string.h>
49#include <time.h>
50#include <unistd.h>
51#include <sys/param.h>
52
53#include <system.h>
54#include "../libelf/libelfP.h"
55#include "../libelf/common.h"
56#include "../libebl/libeblP.h"
57#include "../libdw/libdwP.h"
58#include "../libdwfl/libdwflP.h"
59#include "../libdw/memory-access.h"
60
61
62/* Name and version of program.  */
63static void print_version (FILE *stream, struct argp_state *state);
64void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
65
66/* Bug report address.  */
67const char *argp_program_bug_address = PACKAGE_BUGREPORT;
68
69/* Definitions of arguments for argp functions.  */
70static const struct argp_option options[] =
71{
72  { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
73  { "all", 'a', NULL, 0, N_("Equivalent to: -h -l"), 0 },
74  { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
75  { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
76  { "histogram", 'I', NULL, 0,
77    N_("Display histogram of bucket list lengths"), 0 },
78  { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
79  { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
80  { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
81  { "section-headers", 'S', NULL, 0, N_("Display the sections' header"), 0 },
82  { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
83  { "symbols", 's', NULL, 0, N_("Display the symbol table"), 0 },
84  { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
85  { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
86    N_("Display DWARF section content.  SECTION can be one of abbrev, "
87       "aranges, frame, info, loc, line, ranges, pubnames, str, or macinfo."),
88    0 },
89  { "notes", 'n', NULL, 0, N_("Display the core notes"), 0 },
90  { "arch-specific", 'A', NULL, 0,
91    N_("Display architecture specific information (if any)"), 0 },
92  { "hex-dump", 'x', "SECTION", 0,
93    N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
94  { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
95    N_("Print string contents of sections"), 0 },
96  { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
97  { "archive-index", 'c', NULL, 0,
98    N_("Display the symbol index of an archive"), 0 },
99
100  { NULL, 0, NULL, 0, N_("Output control:"), 0 },
101
102  { NULL, 0, NULL, 0, NULL, 0 }
103};
104
105/* Short description of program.  */
106static const char doc[] = N_("\
107Print information from ELF file in human-readable form.");
108
109/* Strings for arguments in help texts.  */
110static const char args_doc[] = N_("FILE...");
111
112/* Prototype for option handler.  */
113static error_t parse_opt (int key, char *arg, struct argp_state *state);
114
115/* Data structure to communicate with argp functions.  */
116static struct argp argp =
117{
118  options, parse_opt, args_doc, doc, NULL, NULL, NULL
119};
120
121
122/* Flags set by the option controlling the output.  */
123
124/* True if dynamic segment should be printed.  */
125static bool print_dynamic_table;
126
127/* True if the file header should be printed.  */
128static bool print_file_header;
129
130/* True if the program headers should be printed.  */
131static bool print_program_header;
132
133/* True if relocations should be printed.  */
134static bool print_relocations;
135
136/* True if the section headers should be printed.  */
137static bool print_section_header;
138
139/* True if the symbol table should be printed.  */
140static bool print_symbol_table;
141
142/* True if the version information should be printed.  */
143static bool print_version_info;
144
145/* True if section groups should be printed.  */
146static bool print_section_groups;
147
148/* True if bucket list length histogram should be printed.  */
149static bool print_histogram;
150
151/* True if the architecture specific data should be printed.  */
152static bool print_arch;
153
154/* True if note section content should be printed.  */
155static bool print_notes;
156
157/* True if SHF_STRINGS section content should be printed.  */
158static bool print_string_sections;
159
160/* True if archive index should be printed.  */
161static bool print_archive_index;
162
163/* True if any of the control options except print_archive_index is set.  */
164static bool any_control_option;
165
166/* Select printing of debugging sections.  */
167static enum section_e
168{
169  section_abbrev = 1,	/* .debug_abbrev  */
170  section_aranges = 2,	/* .debug_aranges  */
171  section_frame = 4,	/* .debug_frame or .eh_frame  */
172  section_info = 8,	/* .debug_info  */
173  section_line = 16,	/* .debug_line  */
174  section_loc = 32,	/* .debug_loc  */
175  section_pubnames = 64,/* .debug_pubnames  */
176  section_str = 128,	/* .debug_str  */
177  section_macinfo = 256,/* .debug_macinfo  */
178  section_ranges = 512, /* .debug_ranges  */
179  section_all = (section_abbrev | section_aranges | section_frame
180		 | section_info | section_line | section_loc
181		 | section_pubnames | section_str | section_macinfo
182		 | section_ranges)
183} print_debug_sections;
184
185/* Select hex dumping of sections.  */
186static struct section_argument *dump_data_sections;
187static struct section_argument **dump_data_sections_tail = &dump_data_sections;
188
189/* Select string dumping of sections.  */
190static struct section_argument *string_sections;
191static struct section_argument **string_sections_tail = &string_sections;
192
193struct section_argument
194{
195  struct section_argument *next;
196  const char *arg;
197};
198
199/* Number of sections in the file.  */
200static size_t shnum;
201
202
203/* Declarations of local functions.  */
204static void process_file (int fd, const char *fname, bool only_one);
205static void process_elf_file (Dwfl_Module *dwflmod, int fd);
206static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
207static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
208static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
209static void print_scngrp (Ebl *ebl);
210static void print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr);
211static void print_relocs (Ebl *ebl);
212static void handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
213static void handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
214static void print_symtab (Ebl *ebl, int type);
215static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
216static void print_verinfo (Ebl *ebl);
217static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
218static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
219static void handle_versym (Ebl *ebl, Elf_Scn *scn,
220			   GElf_Shdr *shdr);
221static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
222static void handle_hash (Ebl *ebl);
223static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
224static void print_liblist (Ebl *ebl);
225static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
226static void dump_data (Ebl *ebl);
227static void dump_strings (Ebl *ebl);
228static void print_strings (Ebl *ebl);
229static void dump_archive_index (Elf *, const char *);
230
231
232int
233main (int argc, char *argv[])
234{
235  /* Set locale.  */
236  setlocale (LC_ALL, "");
237
238  /* Initialize the message catalog.  */
239  textdomain (PACKAGE_TARNAME);
240
241  /* Parse and process arguments.  */
242  int remaining;
243  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
244
245  /* Before we start tell the ELF library which version we are using.  */
246  elf_version (EV_CURRENT);
247
248  /* Now process all the files given at the command line.  */
249  bool only_one = remaining + 1 == argc;
250  do
251    {
252      /* Open the file.  */
253      int fd = open (argv[remaining], O_RDONLY);
254      if (fd == -1)
255	{
256	  error (0, errno, gettext ("cannot open input file"));
257	  continue;
258	}
259
260      process_file (fd, argv[remaining], only_one);
261
262      close (fd);
263    }
264  while (++remaining < argc);
265
266  return error_message_count != 0;
267}
268
269
270/* Handle program arguments.  */
271static error_t
272parse_opt (int key, char *arg,
273	   struct argp_state *state __attribute__ ((unused)))
274{
275  switch (key)
276    {
277    case 'a':
278      print_file_header = true;
279      print_program_header = true;
280      print_relocations = true;
281      print_section_header = true;
282      print_symbol_table = true;
283      print_version_info = true;
284      print_dynamic_table = true;
285      print_section_groups = true;
286      print_histogram = true;
287      print_arch = true;
288      print_notes = true;
289      any_control_option = true;
290      break;
291    case 'A':
292      print_arch = true;
293      any_control_option = true;
294      break;
295    case 'd':
296      print_dynamic_table = true;
297      any_control_option = true;
298      break;
299    case 'g':
300      print_section_groups = true;
301      any_control_option = true;
302      break;
303    case 'h':
304      print_file_header = true;
305      any_control_option = true;
306      break;
307    case 'I':
308      print_histogram = true;
309      any_control_option = true;
310      break;
311    case 'l':
312      print_program_header = true;
313      any_control_option = true;
314      break;
315    case 'n':
316      print_notes = true;
317      any_control_option = true;
318      break;
319    case 'r':
320      print_relocations = true;
321      any_control_option = true;
322     break;
323    case 'S':
324      print_section_header = true;
325      any_control_option = true;
326      break;
327    case 's':
328      print_symbol_table = true;
329      any_control_option = true;
330      break;
331    case 'V':
332      print_version_info = true;
333      any_control_option = true;
334      break;
335    case 'c':
336      print_archive_index = true;
337      break;
338    case 'w':
339      if (arg == NULL)
340	print_debug_sections = section_all;
341      else if (strcmp (arg, "abbrev") == 0)
342	print_debug_sections |= section_abbrev;
343      else if (strcmp (arg, "aranges") == 0)
344	print_debug_sections |= section_aranges;
345      else if (strcmp (arg, "ranges") == 0)
346	print_debug_sections |= section_ranges;
347      else if (strcmp (arg, "frame") == 0)
348	print_debug_sections |= section_frame;
349      else if (strcmp (arg, "info") == 0)
350	print_debug_sections |= section_info;
351      else if (strcmp (arg, "loc") == 0)
352	print_debug_sections |= section_loc;
353      else if (strcmp (arg, "line") == 0)
354	print_debug_sections |= section_line;
355      else if (strcmp (arg, "pubnames") == 0)
356	print_debug_sections |= section_pubnames;
357      else if (strcmp (arg, "str") == 0)
358	print_debug_sections |= section_str;
359      else if (strcmp (arg, "macinfo") == 0)
360	print_debug_sections |= section_macinfo;
361      else
362	{
363	  fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
364		   arg);
365	  argp_help (&argp, stderr, ARGP_HELP_SEE,
366		     program_invocation_short_name);
367	  exit (1);
368	}
369      any_control_option = true;
370      break;
371    case 'p':
372      any_control_option = true;
373      if (arg == NULL)
374	{
375	  print_string_sections = true;
376	  break;
377	}
378      /* Fall through.  */
379    case 'x':
380      {
381	struct section_argument *a = xmalloc (sizeof *a);
382	a->arg = arg;
383	a->next = NULL;
384	struct section_argument ***tailp
385	  = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
386	**tailp = a;
387	*tailp = &a->next;
388      }
389      any_control_option = true;
390      break;
391    case ARGP_KEY_NO_ARGS:
392      fputs (gettext ("Missing file name.\n"), stderr);
393      goto do_argp_help;
394    case ARGP_KEY_FINI:
395      if (! any_control_option && ! print_archive_index)
396	{
397	  fputs (gettext ("No operation specified.\n"), stderr);
398	do_argp_help:
399	  argp_help (&argp, stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
400		     program_invocation_short_name);
401	  exit (1);
402	}
403      break;
404    default:
405      return ARGP_ERR_UNKNOWN;
406    }
407  return 0;
408}
409
410
411/* Print the version information.  */
412static void
413print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
414{
415  fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
416  fprintf (stream, gettext ("\
417Copyright (C) %s Red Hat, Inc.\n\
418This is free software; see the source for copying conditions.  There is NO\n\
419warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
420"), "2008");
421  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
422}
423
424
425/* Check if the file is an archive, and if so dump its index.  */
426static void
427check_archive_index (int fd, const char *fname, bool only_one)
428{
429  /* Create an `Elf' descriptor.  */
430  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
431  if (elf == NULL)
432    error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
433	   elf_errmsg (-1));
434  else
435    {
436      if (elf_kind (elf) == ELF_K_AR)
437	{
438	  if (!only_one)
439	    printf ("\n%s:\n\n", fname);
440	  dump_archive_index (elf, fname);
441	}
442      else
443	error (0, 0,
444	       gettext ("'%s' is not an archive, cannot print archive index"),
445	       fname);
446
447      /* Now we can close the descriptor.  */
448      if (elf_end (elf) != 0)
449	error (0, 0, gettext ("error while closing Elf descriptor: %s"),
450	       elf_errmsg (-1));
451    }
452}
453
454/* Trivial callback used for checking if we opened an archive.  */
455static int
456count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
457	       void **userdata __attribute__ ((unused)),
458	       const char *name __attribute__ ((unused)),
459	       Dwarf_Addr base __attribute__ ((unused)),
460	       void *arg)
461{
462  if (*(bool *) arg)
463    return DWARF_CB_ABORT;
464  *(bool *) arg = true;
465  return DWARF_CB_OK;
466}
467
468struct process_dwflmod_args
469{
470  int fd;
471  bool only_one;
472};
473
474static int
475process_dwflmod (Dwfl_Module *dwflmod,
476		 void **userdata __attribute__ ((unused)),
477		 const char *name __attribute__ ((unused)),
478		 Dwarf_Addr base __attribute__ ((unused)),
479		 void *arg)
480{
481  const struct process_dwflmod_args *a = arg;
482
483  /* Print the file name.  */
484  if (!a->only_one)
485    {
486      const char *fname;
487      dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
488
489      printf ("\n%s:\n\n", fname);
490    }
491
492  process_elf_file (dwflmod, a->fd);
493
494  return DWARF_CB_OK;
495}
496
497/* Stub libdwfl callback, only the ELF handle already open is ever used.  */
498static int
499find_no_debuginfo (Dwfl_Module *mod __attribute__ ((unused)),
500		   void **userdata __attribute__ ((unused)),
501		   const char *modname __attribute__ ((unused)),
502		   Dwarf_Addr base __attribute__ ((unused)),
503		   const char *file_name __attribute__ ((unused)),
504		   const char *debuglink_file __attribute__ ((unused)),
505		   GElf_Word debuglink_crc __attribute__ ((unused)),
506		   char **debuginfo_file_name __attribute__ ((unused)))
507{
508  return -1;
509}
510
511/* Process one input file.  */
512static void
513process_file (int fd, const char *fname, bool only_one)
514{
515  if (print_archive_index)
516    check_archive_index (fd, fname, only_one);
517
518  if (!any_control_option)
519    return;
520
521  /* Duplicate an fd for dwfl_report_offline to swallow.  */
522  int dwfl_fd = dup (fd);
523  if (unlikely (dwfl_fd < 0))
524    error (EXIT_FAILURE, errno, "dup");
525
526  /* Use libdwfl in a trivial way to open the libdw handle for us.
527     This takes care of applying relocations to DWARF data in ET_REL files.  */
528  static const Dwfl_Callbacks callbacks =
529    {
530      .section_address = dwfl_offline_section_address,
531      .find_debuginfo = find_no_debuginfo
532    };
533  Dwfl *dwfl = dwfl_begin (&callbacks);
534  if (likely (dwfl != NULL))
535    /* Let 0 be the logical address of the file (or first in archive).  */
536    dwfl->offline_next_address = 0;
537  if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
538    {
539      struct stat64 st;
540      if (fstat64 (fd, &st) != 0)
541	error (0, errno, gettext ("cannot stat input file"));
542      else if (unlikely (st.st_size == 0))
543	error (0, 0, gettext ("input file is empty"));
544      else
545	error (0, 0, gettext ("failed reading '%s': %s"),
546	       fname, dwfl_errmsg (-1));
547    }
548  else
549    {
550      dwfl_report_end (dwfl, NULL, NULL);
551
552      if (only_one)
553	{
554	  /* Clear ONLY_ONE if we have multiple modules, from an archive.  */
555	  bool seen = false;
556	  only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
557	}
558
559      /* Process the one or more modules gleaned from this file.  */
560      struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
561      dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
562    }
563  dwfl_end (dwfl);
564}
565
566
567/* Process one ELF file.  */
568static void
569process_elf_file (Dwfl_Module *dwflmod, int fd)
570{
571  GElf_Addr dwflbias;
572  Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
573
574  GElf_Ehdr ehdr_mem;
575  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
576
577  if (ehdr == NULL)
578    {
579    elf_error:
580      error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
581      return;
582    }
583
584  Ebl *ebl = ebl_openbackend (elf);
585  if (unlikely (ebl == NULL))
586    {
587    ebl_error:
588      error (0, errno, gettext ("cannot create EBL handle"));
589      return;
590    }
591
592  /* Determine the number of sections.  */
593  if (unlikely (elf_getshnum (ebl->elf, &shnum) < 0))
594    error (EXIT_FAILURE, 0,
595	   gettext ("cannot determine number of sections: %s"),
596	   elf_errmsg (-1));
597
598  /* For an ET_REL file, libdwfl has adjusted the in-core shdrs
599     and may have applied relocation to some sections.
600     So we need to get a fresh Elf handle on the file to display those.  */
601  bool print_unrelocated = (print_section_header
602			    || print_relocations
603			    || dump_data_sections != NULL
604			    || print_notes);
605
606  Elf *pure_elf = NULL;
607  Ebl *pure_ebl = ebl;
608  if (ehdr->e_type == ET_REL && print_unrelocated)
609    {
610      /* Read the file afresh.  */
611      off64_t aroff = elf_getaroff (elf);
612      pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
613      if (aroff > 0)
614	{
615	  /* Archive member.  */
616	  (void) elf_rand (pure_elf, aroff);
617	  Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
618	  elf_end (pure_elf);
619	  pure_elf = armem;
620	}
621      if (pure_elf == NULL)
622	goto elf_error;
623      pure_ebl = ebl_openbackend (pure_elf);
624      if (pure_ebl == NULL)
625	goto ebl_error;
626    }
627
628  if (print_file_header)
629    print_ehdr (ebl, ehdr);
630  if (print_section_header)
631    print_shdr (pure_ebl, ehdr);
632  if (print_program_header)
633    print_phdr (ebl, ehdr);
634  if (print_section_groups)
635    print_scngrp (ebl);
636  if (print_dynamic_table)
637    print_dynamic (ebl, ehdr);
638  if (print_relocations)
639    print_relocs (pure_ebl);
640  if (print_histogram)
641    handle_hash (ebl);
642  if (print_symbol_table)
643    print_symtab (ebl, SHT_DYNSYM);
644  if (print_version_info)
645    print_verinfo (ebl);
646  if (print_symbol_table)
647    print_symtab (ebl, SHT_SYMTAB);
648  if (print_arch)
649    print_liblist (ebl);
650  if (print_arch)
651    print_attributes (ebl, ehdr);
652  if (dump_data_sections != NULL)
653    dump_data (pure_ebl);
654  if (string_sections != NULL)
655    dump_strings (ebl);
656  if (print_debug_sections != 0)
657    print_debug (dwflmod, ebl, ehdr);
658  if (print_notes)
659    handle_notes (pure_ebl, ehdr);
660  if (print_string_sections)
661    print_strings (ebl);
662
663  ebl_closebackend (ebl);
664
665  if (pure_ebl != ebl)
666    {
667      ebl_closebackend (pure_ebl);
668      elf_end (pure_elf);
669    }
670}
671
672
673/* Print file type.  */
674static void
675print_file_type (unsigned short int e_type)
676{
677  if (likely (e_type <= ET_CORE))
678    {
679      static const char *const knowntypes[] =
680      {
681	N_("NONE (None)"),
682	N_("REL (Relocatable file)"),
683	N_("EXEC (Executable file)"),
684	N_("DYN (Shared object file)"),
685	N_("CORE (Core file)")
686      };
687      puts (gettext (knowntypes[e_type]));
688    }
689  else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
690    printf (gettext ("OS Specific: (%x)\n"),  e_type);
691  else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
692    printf (gettext ("Processor Specific: (%x)\n"),  e_type);
693  else
694    puts ("???");
695}
696
697
698/* Print ELF header.  */
699static void
700print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
701{
702  fputs_unlocked (gettext ("ELF Header:\n  Magic:  "), stdout);
703  for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
704    printf (" %02hhx", ehdr->e_ident[cnt]);
705
706  printf (gettext ("\n  Class:                             %s\n"),
707	  ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
708	  : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
709	  : "\?\?\?");
710
711  printf (gettext ("  Data:                              %s\n"),
712	  ehdr->e_ident[EI_DATA] == ELFDATA2LSB
713	  ? "2's complement, little endian"
714	  : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
715	  ? "2's complement, big endian" : "\?\?\?");
716
717  printf (gettext ("  Ident Version:                     %hhd %s\n"),
718	  ehdr->e_ident[EI_VERSION],
719	  ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
720	  : "(\?\?\?)");
721
722  char buf[512];
723  printf (gettext ("  OS/ABI:                            %s\n"),
724	  ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
725
726  printf (gettext ("  ABI Version:                       %hhd\n"),
727	  ehdr->e_ident[EI_ABIVERSION]);
728
729  fputs_unlocked (gettext ("  Type:                              "), stdout);
730  print_file_type (ehdr->e_type);
731
732  printf (gettext ("  Machine:                           %s\n"), ebl->name);
733
734  printf (gettext ("  Version:                           %d %s\n"),
735	  ehdr->e_version,
736	  ehdr->e_version  == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
737
738  printf (gettext ("  Entry point address:               %#" PRIx64 "\n"),
739	  ehdr->e_entry);
740
741  printf (gettext ("  Start of program headers:          %" PRId64 " %s\n"),
742	  ehdr->e_phoff, gettext ("(bytes into file)"));
743
744  printf (gettext ("  Start of section headers:          %" PRId64 " %s\n"),
745	  ehdr->e_shoff, gettext ("(bytes into file)"));
746
747  printf (gettext ("  Flags:                             %s\n"),
748	  ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
749
750  printf (gettext ("  Size of this header:               %" PRId16 " %s\n"),
751	  ehdr->e_ehsize, gettext ("(bytes)"));
752
753  printf (gettext ("  Size of program header entries:    %" PRId16 " %s\n"),
754	  ehdr->e_phentsize, gettext ("(bytes)"));
755
756  printf (gettext ("  Number of program headers entries: %" PRId16 "\n"),
757	  ehdr->e_phnum);
758
759  printf (gettext ("  Size of section header entries:    %" PRId16 " %s\n"),
760	  ehdr->e_shentsize, gettext ("(bytes)"));
761
762  printf (gettext ("  Number of section headers entries: %" PRId16),
763	  ehdr->e_shnum);
764  if (ehdr->e_shnum == 0)
765    {
766      GElf_Shdr shdr_mem;
767      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
768      if (shdr != NULL)
769	printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
770		(uint32_t) shdr->sh_size);
771      else
772	fputs_unlocked (gettext (" ([0] not available)"), stdout);
773    }
774  fputc_unlocked ('\n', stdout);
775
776  if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
777    {
778      GElf_Shdr shdr_mem;
779      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
780      if (shdr != NULL)
781	/* We managed to get the zeroth section.  */
782	snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
783		  (uint32_t) shdr->sh_link);
784      else
785	{
786	  strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
787	  buf[sizeof (buf) - 1] = '\0';
788	}
789
790      printf (gettext ("  Section header string table index: XINDEX%s\n\n"),
791	      buf);
792    }
793  else
794    printf (gettext ("  Section header string table index: %" PRId16 "\n\n"),
795	    ehdr->e_shstrndx);
796}
797
798
799static const char *
800get_visibility_type (int value)
801{
802  switch (value)
803    {
804    case STV_DEFAULT:
805      return "DEFAULT";
806    case STV_INTERNAL:
807      return "INTERNAL";
808    case STV_HIDDEN:
809      return "HIDDEN";
810    case STV_PROTECTED:
811      return "PROTECTED";
812    default:
813      return "???";
814    }
815}
816
817
818/* Print the section headers.  */
819static void
820print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
821{
822  size_t cnt;
823  size_t shstrndx;
824
825  if (! print_file_header)
826    printf (gettext ("\
827There are %d section headers, starting at offset %#" PRIx64 ":\n\
828\n"),
829	    ehdr->e_shnum, ehdr->e_shoff);
830
831  /* Get the section header string table index.  */
832  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
833    error (EXIT_FAILURE, 0,
834	   gettext ("cannot get section header string table index"));
835
836  puts (gettext ("Section Headers:"));
837
838  if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
839    puts (gettext ("[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al"));
840  else
841    puts (gettext ("[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al"));
842
843  for (cnt = 0; cnt < shnum; ++cnt)
844    {
845      Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
846
847      if (unlikely (scn == NULL))
848	error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
849	       elf_errmsg (-1));
850
851      /* Get the section header.  */
852      GElf_Shdr shdr_mem;
853      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
854      if (unlikely (shdr == NULL))
855	error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
856	       elf_errmsg (-1));
857
858      char flagbuf[20];
859      char *cp = flagbuf;
860      if (shdr->sh_flags & SHF_WRITE)
861	*cp++ = 'W';
862      if (shdr->sh_flags & SHF_ALLOC)
863	*cp++ = 'A';
864      if (shdr->sh_flags & SHF_EXECINSTR)
865	*cp++ = 'X';
866      if (shdr->sh_flags & SHF_MERGE)
867	*cp++ = 'M';
868      if (shdr->sh_flags & SHF_STRINGS)
869	*cp++ = 'S';
870      if (shdr->sh_flags & SHF_INFO_LINK)
871	*cp++ = 'I';
872      if (shdr->sh_flags & SHF_LINK_ORDER)
873	*cp++ = 'L';
874      if (shdr->sh_flags & SHF_OS_NONCONFORMING)
875	*cp++ = 'N';
876      if (shdr->sh_flags & SHF_GROUP)
877	*cp++ = 'G';
878      if (shdr->sh_flags & SHF_TLS)
879	*cp++ = 'T';
880      if (shdr->sh_flags & SHF_ORDERED)
881	*cp++ = 'O';
882      if (shdr->sh_flags & SHF_EXCLUDE)
883	*cp++ = 'E';
884      *cp = '\0';
885
886      char buf[128];
887      printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
888	      " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
889	      " %2" PRId64 "\n",
890	      cnt,
891	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
892	      ?: "<corrupt>",
893	      ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
894	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
895	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
896	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
897	      shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
898	      shdr->sh_addralign);
899    }
900
901  fputc_unlocked ('\n', stdout);
902}
903
904
905/* Print the program header.  */
906static void
907print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
908{
909  if (ehdr->e_phnum == 0)
910    /* No program header, this is OK in relocatable objects.  */
911    return;
912
913  puts (gettext ("Program Headers:"));
914  if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
915    puts (gettext ("\
916  Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"));
917  else
918    puts (gettext ("\
919  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align"));
920
921  /* Process all program headers.  */
922  bool has_relro = false;
923  GElf_Addr relro_from = 0;
924  GElf_Addr relro_to = 0;
925  for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt)
926    {
927      char buf[128];
928      GElf_Phdr mem;
929      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
930
931      /* If for some reason the header cannot be returned show this.  */
932      if (unlikely (phdr == NULL))
933	{
934	  puts ("  ???");
935	  continue;
936	}
937
938      printf ("  %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
939	      " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
940	      ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
941	      phdr->p_offset,
942	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
943	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
944	      phdr->p_filesz,
945	      phdr->p_memsz,
946	      phdr->p_flags & PF_R ? 'R' : ' ',
947	      phdr->p_flags & PF_W ? 'W' : ' ',
948	      phdr->p_flags & PF_X ? 'E' : ' ',
949	      phdr->p_align);
950
951      if (phdr->p_type == PT_INTERP)
952	{
953	  /* We can show the user the name of the interpreter.  */
954	  size_t maxsize;
955	  char *filedata = elf_rawfile (ebl->elf, &maxsize);
956
957	  if (filedata != NULL && phdr->p_offset < maxsize)
958	    printf (gettext ("\t[Requesting program interpreter: %s]\n"),
959		    filedata + phdr->p_offset);
960	}
961      else if (phdr->p_type == PT_GNU_RELRO)
962	{
963	  has_relro = true;
964	  relro_from = phdr->p_vaddr;
965	  relro_to = relro_from + phdr->p_memsz;
966	}
967    }
968
969  /* Get the section header string table index.  */
970  size_t shstrndx;
971  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
972    error (EXIT_FAILURE, 0,
973	   gettext ("cannot get section header string table index"));
974
975  puts (gettext ("\n Section to Segment mapping:\n  Segment Sections..."));
976
977  for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt)
978    {
979      /* Print the segment number.  */
980      printf ("   %2.2zu     ", cnt);
981
982      GElf_Phdr phdr_mem;
983      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
984      /* This must not happen.  */
985      if (unlikely (phdr == NULL))
986	error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
987	       elf_errmsg (-1));
988
989      /* Iterate over the sections.  */
990      bool in_relro = false;
991      bool in_ro = false;
992      for (size_t inner = 1; inner < shnum; ++inner)
993	{
994	  Elf_Scn *scn = elf_getscn (ebl->elf, inner);
995	  /* This should not happen.  */
996	  if (unlikely (scn == NULL))
997	    error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
998		   elf_errmsg (-1));
999
1000	  /* Get the section header.  */
1001	  GElf_Shdr shdr_mem;
1002	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1003	  if (unlikely (shdr == NULL))
1004	    error (EXIT_FAILURE, 0,
1005		   gettext ("cannot get section header: %s"),
1006		   elf_errmsg (-1));
1007
1008	  if (shdr->sh_size > 0
1009	      /* Compare allocated sections by VMA, unallocated
1010		 sections by file offset.  */
1011	      && (shdr->sh_flags & SHF_ALLOC
1012		  ? (shdr->sh_addr >= phdr->p_vaddr
1013		     && (shdr->sh_addr + shdr->sh_size
1014			 <= phdr->p_vaddr + phdr->p_memsz))
1015		  : (shdr->sh_offset >= phdr->p_offset
1016		     && (shdr->sh_offset + shdr->sh_size
1017			 <= phdr->p_offset + phdr->p_filesz))))
1018	    {
1019	      if (has_relro && !in_relro
1020		  && shdr->sh_addr >= relro_from
1021		  && shdr->sh_addr + shdr->sh_size <= relro_to)
1022		{
1023		  fputs_unlocked (" [RELRO:", stdout);
1024		  in_relro = true;
1025		}
1026	      else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
1027		{
1028		  fputs_unlocked ("]", stdout);
1029		  in_relro =  false;
1030		}
1031	      else if (has_relro && in_relro
1032		       && shdr->sh_addr + shdr->sh_size > relro_to)
1033		fputs_unlocked ("] <RELRO:", stdout);
1034	      else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
1035		{
1036		  if (!in_ro)
1037		    {
1038		      fputs_unlocked (" [RO:", stdout);
1039		      in_ro = true;
1040		    }
1041		}
1042	      else
1043		{
1044		  /* Determine the segment this section is part of.  */
1045		  size_t cnt2;
1046		  GElf_Phdr *phdr2 = NULL;
1047		  for (cnt2 = 0; cnt2 < ehdr->e_phnum; ++cnt2)
1048		    {
1049		      GElf_Phdr phdr2_mem;
1050		      phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
1051
1052		      if (phdr2 != NULL && phdr2->p_type == PT_LOAD
1053			  && shdr->sh_addr >= phdr2->p_vaddr
1054			  && (shdr->sh_addr + shdr->sh_size
1055			      <= phdr2->p_vaddr + phdr2->p_memsz))
1056			break;
1057		    }
1058
1059		  if (cnt2 < ehdr->e_phnum)
1060		    {
1061		      if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
1062			{
1063			  fputs_unlocked (" [RO:", stdout);
1064			  in_ro = true;
1065			}
1066		      else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
1067			{
1068			  fputs_unlocked ("]", stdout);
1069			  in_ro = false;
1070			}
1071		    }
1072		}
1073
1074	      printf (" %s",
1075		      elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1076
1077	      /* Signal that this sectin is only partially covered.  */
1078	      if (has_relro && in_relro
1079		       && shdr->sh_addr + shdr->sh_size > relro_to)
1080		{
1081		  fputs_unlocked (">", stdout);
1082		  in_relro =  false;
1083		}
1084	    }
1085	}
1086      if (in_relro || in_ro)
1087	fputs_unlocked ("]", stdout);
1088
1089      /* Finish the line.  */
1090      fputc_unlocked ('\n', stdout);
1091    }
1092}
1093
1094
1095static void
1096handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1097{
1098  /* Get the data of the section.  */
1099  Elf_Data *data = elf_getdata (scn, NULL);
1100
1101  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1102  GElf_Shdr symshdr_mem;
1103  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1104  Elf_Data *symdata = elf_getdata (symscn, NULL);
1105
1106  if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
1107      || symdata == NULL)
1108    return;
1109
1110  /* Get the section header string table index.  */
1111  size_t shstrndx;
1112  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
1113    error (EXIT_FAILURE, 0,
1114	   gettext ("cannot get section header string table index"));
1115
1116  Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
1117
1118  GElf_Sym sym_mem;
1119  printf ((grpref[0] & GRP_COMDAT)
1120	  ? ngettext ("\
1121\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
1122		      "\
1123\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1124		      data->d_size / sizeof (Elf32_Word) - 1)
1125	  : ngettext ("\
1126\nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
1127\nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1128		      data->d_size / sizeof (Elf32_Word) - 1),
1129	  elf_ndxscn (scn),
1130	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1131	  elf_strptr (ebl->elf, symshdr->sh_link,
1132		      gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name)
1133	  ?: gettext ("<INVALID SYMBOL>"),
1134	  data->d_size / sizeof (Elf32_Word) - 1);
1135
1136  for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1137    {
1138      GElf_Shdr grpshdr_mem;
1139      GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
1140					 &grpshdr_mem);
1141
1142      const char *str;
1143      printf ("  [%2u] %s\n",
1144	      grpref[cnt],
1145	      grpshdr != NULL
1146	      && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
1147	      ? str : gettext ("<INVALID SECTION>"));
1148    }
1149}
1150
1151
1152static void
1153print_scngrp (Ebl *ebl)
1154{
1155  /* Find all relocation sections and handle them.  */
1156  Elf_Scn *scn = NULL;
1157
1158  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1159    {
1160       /* Handle the section if it is a symbol table.  */
1161      GElf_Shdr shdr_mem;
1162      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1163
1164      if (shdr != NULL && shdr->sh_type == SHT_GROUP)
1165	handle_scngrp (ebl, scn, shdr);
1166    }
1167}
1168
1169
1170static const struct flags
1171{
1172  int mask;
1173  const char *str;
1174} dt_flags[] =
1175  {
1176    { DF_ORIGIN, "ORIGIN" },
1177    { DF_SYMBOLIC, "SYMBOLIC" },
1178    { DF_TEXTREL, "TEXTREL" },
1179    { DF_BIND_NOW, "BIND_NOW" },
1180    { DF_STATIC_TLS, "STATIC_TLS" }
1181  };
1182static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
1183
1184static const struct flags dt_flags_1[] =
1185  {
1186    { DF_1_NOW, "NOW" },
1187    { DF_1_GLOBAL, "GLOBAL" },
1188    { DF_1_GROUP, "GROUP" },
1189    { DF_1_NODELETE, "NODELETE" },
1190    { DF_1_LOADFLTR, "LOADFLTR" },
1191    { DF_1_INITFIRST, "INITFIRST" },
1192    { DF_1_NOOPEN, "NOOPEN" },
1193    { DF_1_ORIGIN, "ORIGIN" },
1194    { DF_1_DIRECT, "DIRECT" },
1195    { DF_1_TRANS, "TRANS" },
1196    { DF_1_INTERPOSE, "INTERPOSE" },
1197    { DF_1_NODEFLIB, "NODEFLIB" },
1198    { DF_1_NODUMP, "NODUMP" },
1199    { DF_1_CONFALT, "CONFALT" },
1200    { DF_1_ENDFILTEE, "ENDFILTEE" },
1201    { DF_1_DISPRELDNE, "DISPRELDNE" },
1202    { DF_1_DISPRELPND, "DISPRELPND" },
1203  };
1204static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
1205
1206static const struct flags dt_feature_1[] =
1207  {
1208    { DTF_1_PARINIT, "PARINIT" },
1209    { DTF_1_CONFEXP, "CONFEXP" }
1210  };
1211static const int ndt_feature_1 = (sizeof (dt_feature_1)
1212				  / sizeof (dt_feature_1[0]));
1213
1214static const struct flags dt_posflag_1[] =
1215  {
1216    { DF_P1_LAZYLOAD, "LAZYLOAD" },
1217    { DF_P1_GROUPPERM, "GROUPPERM" }
1218  };
1219static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
1220				  / sizeof (dt_posflag_1[0]));
1221
1222
1223static void
1224print_flags (int class, GElf_Xword d_val, const struct flags *flags,
1225		int nflags)
1226{
1227  bool first = true;
1228  int cnt;
1229
1230  for (cnt = 0; cnt < nflags; ++cnt)
1231    if (d_val & flags[cnt].mask)
1232      {
1233	if (!first)
1234	  putchar_unlocked (' ');
1235	fputs_unlocked (flags[cnt].str, stdout);
1236	d_val &= ~flags[cnt].mask;
1237	first = false;
1238      }
1239
1240  if (d_val != 0)
1241    {
1242      if (!first)
1243	putchar_unlocked (' ');
1244      printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
1245    }
1246
1247  putchar_unlocked ('\n');
1248}
1249
1250
1251static void
1252print_dt_flags (int class, GElf_Xword d_val)
1253{
1254  print_flags (class, d_val, dt_flags, ndt_flags);
1255}
1256
1257
1258static void
1259print_dt_flags_1 (int class, GElf_Xword d_val)
1260{
1261  print_flags (class, d_val, dt_flags_1, ndt_flags_1);
1262}
1263
1264
1265static void
1266print_dt_feature_1 (int class, GElf_Xword d_val)
1267{
1268  print_flags (class, d_val, dt_feature_1, ndt_feature_1);
1269}
1270
1271
1272static void
1273print_dt_posflag_1 (int class, GElf_Xword d_val)
1274{
1275  print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
1276}
1277
1278
1279static void
1280handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1281{
1282  int class = gelf_getclass (ebl->elf);
1283  GElf_Shdr glink;
1284  Elf_Data *data;
1285  size_t cnt;
1286  size_t shstrndx;
1287
1288  /* Get the data of the section.  */
1289  data = elf_getdata (scn, NULL);
1290  if (data == NULL)
1291    return;
1292
1293  /* Get the section header string table index.  */
1294  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
1295    error (EXIT_FAILURE, 0,
1296	   gettext ("cannot get section header string table index"));
1297
1298  printf (ngettext ("\
1299\nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
1300		    "\
1301\nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
1302		    shdr->sh_size / shdr->sh_entsize),
1303	  (unsigned long int) (shdr->sh_size / shdr->sh_entsize),
1304	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
1305	  shdr->sh_offset,
1306	  (int) shdr->sh_link,
1307	  elf_strptr (ebl->elf, shstrndx,
1308		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1309				    &glink)->sh_name));
1310  fputs_unlocked (gettext ("  Type              Value\n"), stdout);
1311
1312  for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1313    {
1314      GElf_Dyn dynmem;
1315      GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
1316      if (dyn == NULL)
1317	break;
1318
1319      char buf[64];
1320      printf ("  %-17s ",
1321	      ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
1322
1323      switch (dyn->d_tag)
1324	{
1325	case DT_NULL:
1326	case DT_DEBUG:
1327	case DT_BIND_NOW:
1328	case DT_TEXTREL:
1329	  /* No further output.  */
1330	  fputc_unlocked ('\n', stdout);
1331	  break;
1332
1333	case DT_NEEDED:
1334	  printf (gettext ("Shared library: [%s]\n"),
1335		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1336	  break;
1337
1338	case DT_SONAME:
1339	  printf (gettext ("Library soname: [%s]\n"),
1340		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1341	  break;
1342
1343	case DT_RPATH:
1344	  printf (gettext ("Library rpath: [%s]\n"),
1345		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1346	  break;
1347
1348	case DT_RUNPATH:
1349	  printf (gettext ("Library runpath: [%s]\n"),
1350		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1351	  break;
1352
1353	case DT_PLTRELSZ:
1354	case DT_RELASZ:
1355	case DT_STRSZ:
1356	case DT_RELSZ:
1357	case DT_RELAENT:
1358	case DT_SYMENT:
1359	case DT_RELENT:
1360	case DT_PLTPADSZ:
1361	case DT_MOVEENT:
1362	case DT_MOVESZ:
1363	case DT_INIT_ARRAYSZ:
1364	case DT_FINI_ARRAYSZ:
1365	case DT_SYMINSZ:
1366	case DT_SYMINENT:
1367	case DT_GNU_CONFLICTSZ:
1368	case DT_GNU_LIBLISTSZ:
1369	  printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
1370	  break;
1371
1372	case DT_VERDEFNUM:
1373	case DT_VERNEEDNUM:
1374	case DT_RELACOUNT:
1375	case DT_RELCOUNT:
1376	  printf ("%" PRId64 "\n", dyn->d_un.d_val);
1377	  break;
1378
1379	case DT_PLTREL:
1380	  puts (ebl_dynamic_tag_name (ebl, dyn->d_un.d_val, NULL, 0));
1381	  break;
1382
1383	case DT_FLAGS:
1384	  print_dt_flags (class, dyn->d_un.d_val);
1385	  break;
1386
1387	case DT_FLAGS_1:
1388	  print_dt_flags_1 (class, dyn->d_un.d_val);
1389	  break;
1390
1391	case DT_FEATURE_1:
1392	  print_dt_feature_1 (class, dyn->d_un.d_val);
1393	  break;
1394
1395	case DT_POSFLAG_1:
1396	  print_dt_posflag_1 (class, dyn->d_un.d_val);
1397	  break;
1398
1399	default:
1400	  printf ("%#0*" PRIx64 "\n",
1401		  class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
1402	  break;
1403	}
1404    }
1405}
1406
1407
1408/* Print the dynamic segment.  */
1409static void
1410print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr)
1411{
1412  for (int i = 0; i < ehdr->e_phnum; ++i)
1413    {
1414      GElf_Phdr phdr_mem;
1415      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
1416
1417      if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
1418	{
1419	  Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
1420	  GElf_Shdr shdr_mem;
1421	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1422	  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
1423	    handle_dynamic (ebl, scn, shdr);
1424	  break;
1425	}
1426    }
1427}
1428
1429
1430/* Print relocations.  */
1431static void
1432print_relocs (Ebl *ebl)
1433{
1434  /* Find all relocation sections and handle them.  */
1435  Elf_Scn *scn = NULL;
1436
1437  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1438    {
1439       /* Handle the section if it is a symbol table.  */
1440      GElf_Shdr shdr_mem;
1441      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1442
1443      if (likely (shdr != NULL))
1444	{
1445	  if (shdr->sh_type == SHT_REL)
1446	    handle_relocs_rel (ebl, scn, shdr);
1447	  else if (shdr->sh_type == SHT_RELA)
1448	    handle_relocs_rela (ebl, scn, shdr);
1449	}
1450    }
1451}
1452
1453
1454/* Handle a relocation section.  */
1455static void
1456handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1457{
1458  int class = gelf_getclass (ebl->elf);
1459  int nentries = shdr->sh_size / shdr->sh_entsize;
1460
1461  /* Get the data of the section.  */
1462  Elf_Data *data = elf_getdata (scn, NULL);
1463  if (data == NULL)
1464    return;
1465
1466  /* Get the symbol table information.  */
1467  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1468  GElf_Shdr symshdr_mem;
1469  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1470  Elf_Data *symdata = elf_getdata (symscn, NULL);
1471
1472  /* Get the section header of the section the relocations are for.  */
1473  GElf_Shdr destshdr_mem;
1474  GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1475				      &destshdr_mem);
1476
1477  if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
1478    {
1479      printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1480	      shdr->sh_offset);
1481      return;
1482    }
1483
1484  /* Search for the optional extended section index table.  */
1485  Elf_Data *xndxdata = NULL;
1486  int xndxscnidx = elf_scnshndx (scn);
1487  if (unlikely (xndxscnidx > 0))
1488    xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
1489
1490  /* Get the section header string table index.  */
1491  size_t shstrndx;
1492  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
1493    error (EXIT_FAILURE, 0,
1494	   gettext ("cannot get section header string table index"));
1495
1496  if (shdr->sh_info != 0)
1497    printf (ngettext ("\
1498\nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1499		    "\
1500\nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1501		      nentries),
1502	    (unsigned int) elf_ndxscn (scn),
1503	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1504	    (unsigned int) shdr->sh_info,
1505	    elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1506	    shdr->sh_offset,
1507	    nentries);
1508  else
1509    /* The .rel.dyn section does not refer to a specific section but
1510       instead of section index zero.  Do not try to print a section
1511       name.  */
1512    printf (ngettext ("\
1513\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1514		    "\
1515\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1516		      nentries),
1517	    (unsigned int) elf_ndxscn (scn),
1518	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1519	    shdr->sh_offset,
1520	    nentries);
1521  fputs_unlocked (class == ELFCLASS32
1522		  ? gettext ("\
1523  Offset      Type                 Value       Name\n")
1524		  : gettext ("\
1525  Offset              Type                 Value               Name\n"),
1526	 stdout);
1527
1528  for (int cnt = 0; cnt < nentries; ++cnt)
1529    {
1530      GElf_Rel relmem;
1531      GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
1532      if (likely (rel != NULL))
1533	{
1534	  char buf[128];
1535	  GElf_Sym symmem;
1536	  Elf32_Word xndx;
1537	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1538					    GELF_R_SYM (rel->r_info),
1539					    &symmem, &xndx);
1540	  if (unlikely (sym == NULL))
1541	    printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
1542		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1543		    ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1544		    /* Avoid the leading R_ which isn't carrying any
1545		       information.  */
1546		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1547					   buf, sizeof (buf)) + 2
1548		    : gettext ("<INVALID RELOC>"),
1549		    gettext ("INVALID SYMBOL"),
1550		    (long int) GELF_R_SYM (rel->r_info));
1551	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1552	    printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
1553		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1554		    likely (ebl_reloc_type_check (ebl,
1555						  GELF_R_TYPE (rel->r_info)))
1556		    /* Avoid the leading R_ which isn't carrying any
1557		       information.  */
1558		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1559					   buf, sizeof (buf)) + 2
1560		    : gettext ("<INVALID RELOC>"),
1561		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
1562		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1563	  else
1564	    {
1565	      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
1566						   sym->st_shndx == SHN_XINDEX
1567						   ? xndx : sym->st_shndx),
1568				       &destshdr_mem);
1569
1570	      if (unlikely (destshdr == NULL))
1571		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
1572			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1573			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1574			/* Avoid the leading R_ which isn't carrying any
1575			   information.  */
1576			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1577					       buf, sizeof (buf)) + 2
1578			: gettext ("<INVALID RELOC>"),
1579			gettext ("INVALID SECTION"),
1580			(long int) (sym->st_shndx == SHN_XINDEX
1581				    ? xndx : sym->st_shndx));
1582	      else
1583		printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
1584			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1585			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1586			/* Avoid the leading R_ which isn't carrying any
1587			   information.  */
1588			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1589					       buf, sizeof (buf)) + 2
1590			: gettext ("<INVALID RELOC>"),
1591			class == ELFCLASS32 ? 10 : 18, sym->st_value,
1592			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1593	    }
1594	}
1595    }
1596}
1597
1598
1599/* Handle a relocation section.  */
1600static void
1601handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1602{
1603  int class = gelf_getclass (ebl->elf);
1604  int nentries = shdr->sh_size / shdr->sh_entsize;
1605
1606  /* Get the data of the section.  */
1607  Elf_Data *data = elf_getdata (scn, NULL);
1608  if (data == NULL)
1609    return;
1610
1611  /* Get the symbol table information.  */
1612  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1613  GElf_Shdr symshdr_mem;
1614  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1615  Elf_Data *symdata = elf_getdata (symscn, NULL);
1616
1617  /* Get the section header of the section the relocations are for.  */
1618  GElf_Shdr destshdr_mem;
1619  GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1620				      &destshdr_mem);
1621
1622  if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
1623    {
1624      printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1625	      shdr->sh_offset);
1626      return;
1627    }
1628
1629  /* Search for the optional extended section index table.  */
1630  Elf_Data *xndxdata = NULL;
1631  int xndxscnidx = elf_scnshndx (scn);
1632  if (unlikely (xndxscnidx > 0))
1633    xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
1634
1635  /* Get the section header string table index.  */
1636  size_t shstrndx;
1637  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
1638    error (EXIT_FAILURE, 0,
1639	   gettext ("cannot get section header string table index"));
1640
1641  printf (ngettext ("\
1642\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1643		    "\
1644\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1645		    nentries),
1646	  elf_ndxscn (scn),
1647	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1648	  (unsigned int) shdr->sh_info,
1649	  elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1650	  shdr->sh_offset,
1651	  nentries);
1652  fputs_unlocked (class == ELFCLASS32
1653		  ? gettext ("\
1654  Offset      Type            Value       Addend Name\n")
1655		  : gettext ("\
1656  Offset              Type            Value               Addend Name\n"),
1657		  stdout);
1658
1659  for (int cnt = 0; cnt < nentries; ++cnt)
1660    {
1661      GElf_Rela relmem;
1662      GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
1663      if (likely (rel != NULL))
1664	{
1665	  char buf[64];
1666	  GElf_Sym symmem;
1667	  Elf32_Word xndx;
1668	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1669					    GELF_R_SYM (rel->r_info),
1670					    &symmem, &xndx);
1671
1672	  if (unlikely (sym == NULL))
1673	    printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
1674		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1675		    ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1676		    /* Avoid the leading R_ which isn't carrying any
1677		       information.  */
1678		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1679					   buf, sizeof (buf)) + 2
1680		    : gettext ("<INVALID RELOC>"),
1681		    gettext ("INVALID SYMBOL"),
1682		    (long int) GELF_R_SYM (rel->r_info));
1683	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1684	    printf ("\
1685  %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
1686		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1687		    likely (ebl_reloc_type_check (ebl,
1688						  GELF_R_TYPE (rel->r_info)))
1689		    /* Avoid the leading R_ which isn't carrying any
1690		       information.  */
1691		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1692					   buf, sizeof (buf)) + 2
1693		    : gettext ("<INVALID RELOC>"),
1694		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
1695		    rel->r_addend,
1696		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1697	  else
1698	    {
1699	      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
1700						   sym->st_shndx == SHN_XINDEX
1701						   ? xndx : sym->st_shndx),
1702				       &destshdr_mem);
1703
1704	      if (unlikely (shdr == NULL))
1705		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
1706			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1707			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1708			/* Avoid the leading R_ which isn't carrying any
1709			   information.  */
1710			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1711					       buf, sizeof (buf)) + 2
1712			: gettext ("<INVALID RELOC>"),
1713			gettext ("INVALID SECTION"),
1714			(long int) (sym->st_shndx == SHN_XINDEX
1715				    ? xndx : sym->st_shndx));
1716	      else
1717		printf ("\
1718  %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
1719			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1720			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1721			/* Avoid the leading R_ which isn't carrying any
1722			   information.  */
1723			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1724					       buf, sizeof (buf)) + 2
1725			: gettext ("<INVALID RELOC>"),
1726			class == ELFCLASS32 ? 10 : 18, sym->st_value,
1727			rel->r_addend,
1728			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1729	    }
1730	}
1731    }
1732}
1733
1734
1735/* Print the program header.  */
1736static void
1737print_symtab (Ebl *ebl, int type)
1738{
1739  /* Find the symbol table(s).  For this we have to search through the
1740     section table.  */
1741  Elf_Scn *scn = NULL;
1742
1743  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1744    {
1745      /* Handle the section if it is a symbol table.  */
1746      GElf_Shdr shdr_mem;
1747      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1748
1749      if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
1750	handle_symtab (ebl, scn, shdr);
1751    }
1752}
1753
1754
1755static void
1756handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1757{
1758  Elf_Data *versym_data = NULL;
1759  Elf_Data *verneed_data = NULL;
1760  Elf_Data *verdef_data = NULL;
1761  Elf_Data *xndx_data = NULL;
1762  int class = gelf_getclass (ebl->elf);
1763  Elf32_Word verneed_stridx = 0;
1764  Elf32_Word verdef_stridx = 0;
1765
1766  /* Get the data of the section.  */
1767  Elf_Data *data = elf_getdata (scn, NULL);
1768  if (data == NULL)
1769    return;
1770
1771  /* Find out whether we have other sections we might need.  */
1772  Elf_Scn *runscn = NULL;
1773  while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
1774    {
1775      GElf_Shdr runshdr_mem;
1776      GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
1777
1778      if (likely (runshdr != NULL))
1779	{
1780	  if (runshdr->sh_type == SHT_GNU_versym
1781	      && runshdr->sh_link == elf_ndxscn (scn))
1782	    /* Bingo, found the version information.  Now get the data.  */
1783	    versym_data = elf_getdata (runscn, NULL);
1784	  else if (runshdr->sh_type == SHT_GNU_verneed)
1785	    {
1786	      /* This is the information about the needed versions.  */
1787	      verneed_data = elf_getdata (runscn, NULL);
1788	      verneed_stridx = runshdr->sh_link;
1789	    }
1790	  else if (runshdr->sh_type == SHT_GNU_verdef)
1791	    {
1792	      /* This is the information about the defined versions.  */
1793	      verdef_data = elf_getdata (runscn, NULL);
1794	      verdef_stridx = runshdr->sh_link;
1795	    }
1796	  else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
1797	      && runshdr->sh_link == elf_ndxscn (scn))
1798	    /* Extended section index.  */
1799	    xndx_data = elf_getdata (runscn, NULL);
1800	}
1801    }
1802
1803  /* Get the section header string table index.  */
1804  size_t shstrndx;
1805  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
1806    error (EXIT_FAILURE, 0,
1807	   gettext ("cannot get section header string table index"));
1808
1809  /* Now we can compute the number of entries in the section.  */
1810  unsigned int nsyms = data->d_size / (class == ELFCLASS32
1811				       ? sizeof (Elf32_Sym)
1812				       : sizeof (Elf64_Sym));
1813
1814  printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
1815		    "\nSymbol table [%2u] '%s' contains %u entries:\n",
1816		    nsyms),
1817	  (unsigned int) elf_ndxscn (scn),
1818	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
1819  GElf_Shdr glink;
1820  printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
1821		    " %lu local symbols  String table: [%2u] '%s'\n",
1822		    shdr->sh_info),
1823	  (unsigned long int) shdr->sh_info,
1824	  (unsigned int) shdr->sh_link,
1825	  elf_strptr (ebl->elf, shstrndx,
1826		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1827				    &glink)->sh_name));
1828
1829  fputs_unlocked (class == ELFCLASS32
1830		  ? gettext ("\
1831  Num:    Value   Size Type    Bind   Vis          Ndx Name\n")
1832		  : gettext ("\
1833  Num:            Value   Size Type    Bind   Vis          Ndx Name\n"),
1834		  stdout);
1835
1836  for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
1837    {
1838      char typebuf[64];
1839      char bindbuf[64];
1840      char scnbuf[64];
1841      Elf32_Word xndx;
1842      GElf_Sym sym_mem;
1843      GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
1844
1845      if (unlikely (sym == NULL))
1846	continue;
1847
1848      /* Determine the real section index.  */
1849      if (likely (sym->st_shndx != SHN_XINDEX))
1850	xndx = sym->st_shndx;
1851
1852      printf (gettext ("\
1853%5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
1854	      cnt,
1855	      class == ELFCLASS32 ? 8 : 16,
1856	      sym->st_value,
1857	      sym->st_size,
1858	      ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
1859				    typebuf, sizeof (typebuf)),
1860	      ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
1861				       bindbuf, sizeof (bindbuf)),
1862	      get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
1863	      ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
1864				sizeof (scnbuf), NULL, shnum),
1865	      elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
1866
1867      if (versym_data != NULL)
1868	{
1869	  /* Get the version information.  */
1870	  GElf_Versym versym_mem;
1871	  GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
1872
1873	  if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
1874	    {
1875	      bool is_nobits = false;
1876	      bool check_def = xndx != SHN_UNDEF;
1877
1878	      if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
1879		{
1880		  GElf_Shdr symshdr_mem;
1881		  GElf_Shdr *symshdr =
1882		    gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
1883
1884		  is_nobits = (symshdr != NULL
1885			       && symshdr->sh_type == SHT_NOBITS);
1886		}
1887
1888	      if (is_nobits || ! check_def)
1889		{
1890		  /* We must test both.  */
1891		  GElf_Vernaux vernaux_mem;
1892		  GElf_Vernaux *vernaux = NULL;
1893		  size_t vn_offset = 0;
1894
1895		  GElf_Verneed verneed_mem;
1896		  GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
1897							   &verneed_mem);
1898		  while (verneed != NULL)
1899		    {
1900		      size_t vna_offset = vn_offset;
1901
1902		      vernaux = gelf_getvernaux (verneed_data,
1903						 vna_offset += verneed->vn_aux,
1904						 &vernaux_mem);
1905		      while (vernaux != NULL
1906			     && vernaux->vna_other != *versym
1907			     && vernaux->vna_next != 0)
1908			{
1909			  /* Update the offset.  */
1910			  vna_offset += vernaux->vna_next;
1911
1912			  vernaux = (vernaux->vna_next == 0
1913				     ? NULL
1914				     : gelf_getvernaux (verneed_data,
1915							vna_offset,
1916							&vernaux_mem));
1917			}
1918
1919		      /* Check whether we found the version.  */
1920		      if (vernaux != NULL && vernaux->vna_other == *versym)
1921			/* Found it.  */
1922			break;
1923
1924		      vn_offset += verneed->vn_next;
1925		      verneed = (verneed->vn_next == 0
1926				 ? NULL
1927				 : gelf_getverneed (verneed_data, vn_offset,
1928						    &verneed_mem));
1929		    }
1930
1931		  if (vernaux != NULL && vernaux->vna_other == *versym)
1932		    {
1933		      printf ("@%s (%u)",
1934			      elf_strptr (ebl->elf, verneed_stridx,
1935					  vernaux->vna_name),
1936			      (unsigned int) vernaux->vna_other);
1937		      check_def = 0;
1938		    }
1939		  else if (unlikely (! is_nobits))
1940		    error (0, 0, gettext ("bad dynamic symbol"));
1941		  else
1942		    check_def = 1;
1943		}
1944
1945	      if (check_def && *versym != 0x8001)
1946		{
1947		  /* We must test both.  */
1948		  size_t vd_offset = 0;
1949
1950		  GElf_Verdef verdef_mem;
1951		  GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
1952							&verdef_mem);
1953		  while (verdef != NULL)
1954		    {
1955		      if (verdef->vd_ndx == (*versym & 0x7fff))
1956			/* Found the definition.  */
1957			break;
1958
1959		      vd_offset += verdef->vd_next;
1960		      verdef = (verdef->vd_next == 0
1961				? NULL
1962				: gelf_getverdef (verdef_data, vd_offset,
1963						  &verdef_mem));
1964		    }
1965
1966		  if (verdef != NULL)
1967		    {
1968		      GElf_Verdaux verdaux_mem;
1969		      GElf_Verdaux *verdaux
1970			= gelf_getverdaux (verdef_data,
1971					   vd_offset + verdef->vd_aux,
1972					   &verdaux_mem);
1973
1974		      if (verdaux != NULL)
1975			printf ((*versym & 0x8000) ? "@%s" : "@@%s",
1976				elf_strptr (ebl->elf, verdef_stridx,
1977					    verdaux->vda_name));
1978		    }
1979		}
1980	    }
1981	}
1982
1983      putchar_unlocked ('\n');
1984    }
1985}
1986
1987
1988/* Print version information.  */
1989static void
1990print_verinfo (Ebl *ebl)
1991{
1992  /* Find the version information sections.  For this we have to
1993     search through the section table.  */
1994  Elf_Scn *scn = NULL;
1995
1996  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1997    {
1998      /* Handle the section if it is part of the versioning handling.  */
1999      GElf_Shdr shdr_mem;
2000      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2001
2002      if (likely (shdr != NULL))
2003	{
2004	  if (shdr->sh_type == SHT_GNU_verneed)
2005	    handle_verneed (ebl, scn, shdr);
2006	  else if (shdr->sh_type == SHT_GNU_verdef)
2007	    handle_verdef (ebl, scn, shdr);
2008	  else if (shdr->sh_type == SHT_GNU_versym)
2009	    handle_versym (ebl, scn, shdr);
2010	}
2011    }
2012}
2013
2014
2015static const char *
2016get_ver_flags (unsigned int flags)
2017{
2018  static char buf[32];
2019  char *endp;
2020
2021  if (flags == 0)
2022    return gettext ("none");
2023
2024  if (flags & VER_FLG_BASE)
2025    endp = stpcpy (buf, "BASE ");
2026  else
2027    endp = buf;
2028
2029  if (flags & VER_FLG_WEAK)
2030    {
2031      if (endp != buf)
2032        endp = stpcpy (endp, "| ");
2033
2034      endp = stpcpy (endp, "WEAK ");
2035    }
2036
2037  if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
2038    {
2039      strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
2040      buf[sizeof (buf) - 1] = '\0';
2041    }
2042
2043  return buf;
2044}
2045
2046
2047static void
2048handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2049{
2050  int class = gelf_getclass (ebl->elf);
2051
2052  /* Get the data of the section.  */
2053  Elf_Data *data = elf_getdata (scn, NULL);
2054  if (data == NULL)
2055    return;
2056
2057  /* Get the section header string table index.  */
2058  size_t shstrndx;
2059  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
2060    error (EXIT_FAILURE, 0,
2061	   gettext ("cannot get section header string table index"));
2062
2063  GElf_Shdr glink;
2064  printf (ngettext ("\
2065\nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
2066		    "\
2067\nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
2068		    shdr->sh_info),
2069	  (unsigned int) elf_ndxscn (scn),
2070	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
2071	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2072	  shdr->sh_offset,
2073	  (unsigned int) shdr->sh_link,
2074	  elf_strptr (ebl->elf, shstrndx,
2075		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2076				    &glink)->sh_name));
2077
2078  unsigned int offset = 0;
2079  for (int cnt = shdr->sh_info; --cnt >= 0; )
2080    {
2081      /* Get the data at the next offset.  */
2082      GElf_Verneed needmem;
2083      GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
2084      if (unlikely (need == NULL))
2085	break;
2086
2087      printf (gettext ("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
2088	      offset, (unsigned short int) need->vn_version,
2089	      elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
2090	      (unsigned short int) need->vn_cnt);
2091
2092      unsigned int auxoffset = offset + need->vn_aux;
2093      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2094	{
2095	  GElf_Vernaux auxmem;
2096	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
2097	  if (unlikely (aux == NULL))
2098	    break;
2099
2100	  printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
2101		  auxoffset,
2102		  elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
2103		  get_ver_flags (aux->vna_flags),
2104		  (unsigned short int) aux->vna_other);
2105
2106	  auxoffset += aux->vna_next;
2107	}
2108
2109      /* Find the next offset.  */
2110      offset += need->vn_next;
2111    }
2112}
2113
2114
2115static void
2116handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2117{
2118  /* Get the data of the section.  */
2119  Elf_Data *data = elf_getdata (scn, NULL);
2120  if (data == NULL)
2121    return;
2122
2123  /* Get the section header string table index.  */
2124  size_t shstrndx;
2125  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
2126    error (EXIT_FAILURE, 0,
2127	   gettext ("cannot get section header string table index"));
2128
2129  int class = gelf_getclass (ebl->elf);
2130  GElf_Shdr glink;
2131  printf (ngettext ("\
2132\nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
2133		    "\
2134\nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
2135		    shdr->sh_info),
2136	  (unsigned int) elf_ndxscn (scn),
2137	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2138	  shdr->sh_info,
2139	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2140	  shdr->sh_offset,
2141	  (unsigned int) shdr->sh_link,
2142	  elf_strptr (ebl->elf, shstrndx,
2143		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2144				    &glink)->sh_name));
2145
2146  unsigned int offset = 0;
2147  for (int cnt = shdr->sh_info; --cnt >= 0; )
2148    {
2149      /* Get the data at the next offset.  */
2150      GElf_Verdef defmem;
2151      GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
2152      if (unlikely (def == NULL))
2153	break;
2154
2155      unsigned int auxoffset = offset + def->vd_aux;
2156      GElf_Verdaux auxmem;
2157      GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
2158      if (unlikely (aux == NULL))
2159	break;
2160
2161      printf (gettext ("\
2162  %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"),
2163	      offset, def->vd_version,
2164	      get_ver_flags (def->vd_flags),
2165	      def->vd_ndx,
2166	      def->vd_cnt,
2167	      elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2168
2169      auxoffset += aux->vda_next;
2170      for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
2171	{
2172	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
2173	  if (unlikely (aux == NULL))
2174	    break;
2175
2176	  printf (gettext ("  %#06x: Parent %d: %s\n"),
2177		  auxoffset, cnt2,
2178		  elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2179
2180	  auxoffset += aux->vda_next;
2181	}
2182
2183      /* Find the next offset.  */
2184      offset += def->vd_next;
2185    }
2186}
2187
2188
2189static void
2190handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2191{
2192  int class = gelf_getclass (ebl->elf);
2193  const char **vername;
2194  const char **filename;
2195
2196  /* Get the data of the section.  */
2197  Elf_Data *data = elf_getdata (scn, NULL);
2198  if (data == NULL)
2199    return;
2200
2201  /* Get the section header string table index.  */
2202  size_t shstrndx;
2203  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
2204    error (EXIT_FAILURE, 0,
2205	   gettext ("cannot get section header string table index"));
2206
2207  /* We have to find the version definition section and extract the
2208     version names.  */
2209  Elf_Scn *defscn = NULL;
2210  Elf_Scn *needscn = NULL;
2211
2212  Elf_Scn *verscn = NULL;
2213  while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
2214    {
2215      GElf_Shdr vershdr_mem;
2216      GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
2217
2218      if (likely (vershdr != NULL))
2219	{
2220	  if (vershdr->sh_type == SHT_GNU_verdef)
2221	    defscn = verscn;
2222	  else if (vershdr->sh_type == SHT_GNU_verneed)
2223	    needscn = verscn;
2224	}
2225    }
2226
2227  size_t nvername;
2228  if (defscn != NULL || needscn != NULL)
2229    {
2230      /* We have a version information (better should have).  Now get
2231	 the version names.  First find the maximum version number.  */
2232      nvername = 0;
2233      if (defscn != NULL)
2234	{
2235	  /* Run through the version definitions and find the highest
2236	     index.  */
2237	  unsigned int offset = 0;
2238	  Elf_Data *defdata;
2239	  GElf_Shdr defshdrmem;
2240	  GElf_Shdr *defshdr;
2241
2242	  defdata = elf_getdata (defscn, NULL);
2243	  if (unlikely (defdata == NULL))
2244	    return;
2245
2246	  defshdr = gelf_getshdr (defscn, &defshdrmem);
2247	  if (unlikely (defshdr == NULL))
2248	    return;
2249
2250	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
2251	    {
2252	      GElf_Verdef defmem;
2253	      GElf_Verdef *def;
2254
2255	      /* Get the data at the next offset.  */
2256	      def = gelf_getverdef (defdata, offset, &defmem);
2257	      if (unlikely (def == NULL))
2258		break;
2259
2260	      nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
2261
2262	      offset += def->vd_next;
2263	    }
2264	}
2265      if (needscn != NULL)
2266	{
2267	  unsigned int offset = 0;
2268	  Elf_Data *needdata;
2269	  GElf_Shdr needshdrmem;
2270	  GElf_Shdr *needshdr;
2271
2272	  needdata = elf_getdata (needscn, NULL);
2273	  if (unlikely (needdata == NULL))
2274	    return;
2275
2276	  needshdr = gelf_getshdr (needscn, &needshdrmem);
2277	  if (unlikely (needshdr == NULL))
2278	    return;
2279
2280	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
2281	    {
2282	      GElf_Verneed needmem;
2283	      GElf_Verneed *need;
2284	      unsigned int auxoffset;
2285	      int cnt2;
2286
2287	      /* Get the data at the next offset.  */
2288	      need = gelf_getverneed (needdata, offset, &needmem);
2289	      if (unlikely (need == NULL))
2290		break;
2291
2292	      /* Run through the auxiliary entries.  */
2293	      auxoffset = offset + need->vn_aux;
2294	      for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
2295		{
2296		  GElf_Vernaux auxmem;
2297		  GElf_Vernaux *aux;
2298
2299		  aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
2300		  if (unlikely (aux == NULL))
2301		    break;
2302
2303		  nvername = MAX (nvername,
2304				  (size_t) (aux->vna_other & 0x7fff));
2305
2306		  auxoffset += aux->vna_next;
2307		}
2308
2309	      offset += need->vn_next;
2310	    }
2311	}
2312
2313      /* This is the number of versions we know about.  */
2314      ++nvername;
2315
2316      /* Allocate the array.  */
2317      vername = (const char **) alloca (nvername * sizeof (const char *));
2318      filename = (const char **) alloca (nvername * sizeof (const char *));
2319
2320      /* Run through the data structures again and collect the strings.  */
2321      if (defscn != NULL)
2322	{
2323	  /* Run through the version definitions and find the highest
2324	     index.  */
2325	  unsigned int offset = 0;
2326	  Elf_Data *defdata;
2327	  GElf_Shdr defshdrmem;
2328	  GElf_Shdr *defshdr;
2329
2330	  defdata = elf_getdata (defscn, NULL);
2331	  if (unlikely (defdata == NULL))
2332	    return;
2333
2334	  defshdr = gelf_getshdr (defscn, &defshdrmem);
2335	  if (unlikely (defshdr == NULL))
2336	    return;
2337
2338	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
2339	    {
2340
2341	      /* Get the data at the next offset.  */
2342	      GElf_Verdef defmem;
2343	      GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
2344	      GElf_Verdaux auxmem;
2345	      GElf_Verdaux *aux = gelf_getverdaux (defdata,
2346						   offset + def->vd_aux,
2347						   &auxmem);
2348	      if (unlikely (def == NULL || aux == NULL))
2349		break;
2350
2351	      vername[def->vd_ndx & 0x7fff]
2352		= elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
2353	      filename[def->vd_ndx & 0x7fff] = NULL;
2354
2355	      offset += def->vd_next;
2356	    }
2357	}
2358      if (needscn != NULL)
2359	{
2360	  unsigned int offset = 0;
2361
2362	  Elf_Data *needdata = elf_getdata (needscn, NULL);
2363	  GElf_Shdr needshdrmem;
2364	  GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
2365	  if (unlikely (needdata == NULL || needshdr == NULL))
2366	    return;
2367
2368	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
2369	    {
2370	      /* Get the data at the next offset.  */
2371	      GElf_Verneed needmem;
2372	      GElf_Verneed *need = gelf_getverneed (needdata, offset,
2373						    &needmem);
2374	      if (unlikely (need == NULL))
2375		break;
2376
2377	      /* Run through the auxiliary entries.  */
2378	      unsigned int auxoffset = offset + need->vn_aux;
2379	      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2380		{
2381		  GElf_Vernaux auxmem;
2382		  GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
2383						       &auxmem);
2384		  if (unlikely (aux == NULL))
2385		    break;
2386
2387		  vername[aux->vna_other & 0x7fff]
2388		    = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
2389		  filename[aux->vna_other & 0x7fff]
2390		    = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
2391
2392		  auxoffset += aux->vna_next;
2393		}
2394
2395	      offset += need->vn_next;
2396	    }
2397	}
2398    }
2399  else
2400    {
2401      vername = NULL;
2402      nvername = 1;
2403      filename = NULL;
2404    }
2405
2406  /* Print the header.  */
2407  GElf_Shdr glink;
2408  printf (ngettext ("\
2409\nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
2410		    "\
2411\nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
2412		    shdr->sh_size / shdr->sh_entsize),
2413	  (unsigned int) elf_ndxscn (scn),
2414	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2415	  (int) (shdr->sh_size / shdr->sh_entsize),
2416	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2417	  shdr->sh_offset,
2418	  (unsigned int) shdr->sh_link,
2419	  elf_strptr (ebl->elf, shstrndx,
2420		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2421				    &glink)->sh_name));
2422
2423  /* Now we can finally look at the actual contents of this section.  */
2424  for (unsigned int cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
2425    {
2426      if (cnt % 2 == 0)
2427	printf ("\n %4d:", cnt);
2428
2429      GElf_Versym symmem;
2430      GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
2431      if (sym == NULL)
2432	break;
2433
2434      switch (*sym)
2435	{
2436	  ssize_t n;
2437	case 0:
2438	  fputs_unlocked (gettext ("   0 *local*                     "),
2439			  stdout);
2440	  break;
2441
2442	case 1:
2443	  fputs_unlocked (gettext ("   1 *global*                    "),
2444			  stdout);
2445	  break;
2446
2447	default:
2448	  n = printf ("%4d%c%s",
2449		      *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
2450		      (unsigned int) (*sym & 0x7fff) < nvername
2451		      ? vername[*sym & 0x7fff] : "???");
2452	  if ((unsigned int) (*sym & 0x7fff) < nvername
2453	      && filename[*sym & 0x7fff] != NULL)
2454	    n += printf ("(%s)", filename[*sym & 0x7fff]);
2455	  printf ("%*s", MAX (0, 33 - (int) n), " ");
2456	  break;
2457	}
2458    }
2459  putchar_unlocked ('\n');
2460}
2461
2462
2463static void
2464print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
2465		 uint_fast32_t maxlength, Elf32_Word nbucket,
2466		 uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
2467{
2468  uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
2469
2470  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2471    ++counts[lengths[cnt]];
2472
2473  GElf_Shdr glink;
2474  printf (ngettext ("\
2475\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",
2476		    "\
2477\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",
2478		    nbucket),
2479	  (unsigned int) elf_ndxscn (scn),
2480	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2481	  (int) nbucket,
2482	  gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
2483	  shdr->sh_addr,
2484	  shdr->sh_offset,
2485	  (unsigned int) shdr->sh_link,
2486	  elf_strptr (ebl->elf, shstrndx,
2487		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2488				    &glink)->sh_name));
2489
2490  if (extrastr != NULL)
2491    fputs (extrastr, stdout);
2492
2493  if (likely (nbucket > 0))
2494    {
2495      uint64_t success = 0;
2496
2497      fputs_unlocked (gettext ("\
2498 Length  Number  % of total  Coverage\n"), stdout);
2499      printf (gettext ("      0  %6" PRIu32 "      %5.1f%%\n"),
2500	      counts[0], (counts[0] * 100.0) / nbucket);
2501
2502      uint64_t nzero_counts = 0;
2503      for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
2504	{
2505	  nzero_counts += counts[cnt] * cnt;
2506	  printf (gettext ("\
2507%7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
2508		  (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
2509		  (nzero_counts * 100.0) / nsyms);
2510	}
2511
2512      Elf32_Word acc = 0;
2513      for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
2514	{
2515	  acc += cnt;
2516	  success += counts[cnt] * acc;
2517	}
2518
2519      printf (gettext ("\
2520 Average number of tests:   successful lookup: %f\n\
2521                          unsuccessful lookup: %f\n"),
2522	      (double) success / (double) nzero_counts,
2523	      (double) nzero_counts / (double) nbucket);
2524    }
2525
2526  free (counts);
2527}
2528
2529
2530/* This function handles the traditional System V-style hash table format.  */
2531static void
2532handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2533{
2534  Elf_Data *data = elf_getdata (scn, NULL);
2535  if (unlikely (data == NULL))
2536    {
2537      error (0, 0, gettext ("cannot get data for section %d: %s"),
2538	     (int) elf_ndxscn (scn), elf_errmsg (-1));
2539      return;
2540    }
2541
2542  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
2543  Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
2544  Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
2545  Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
2546
2547  uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2548
2549  uint_fast32_t maxlength = 0;
2550  uint_fast32_t nsyms = 0;
2551  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2552    {
2553      Elf32_Word inner = bucket[cnt];
2554      while (inner > 0 && inner < nchain)
2555	{
2556	  ++nsyms;
2557	  if (maxlength < ++lengths[cnt])
2558	    ++maxlength;
2559
2560	  inner = chain[inner];
2561	}
2562    }
2563
2564  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
2565		   lengths, NULL);
2566
2567  free (lengths);
2568}
2569
2570
2571/* This function handles the incorrect, System V-style hash table
2572   format some 64-bit architectures use.  */
2573static void
2574handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2575{
2576  Elf_Data *data = elf_getdata (scn, NULL);
2577  if (unlikely (data == NULL))
2578    {
2579      error (0, 0, gettext ("cannot get data for section %d: %s"),
2580	     (int) elf_ndxscn (scn), elf_errmsg (-1));
2581      return;
2582    }
2583
2584  Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
2585  Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
2586  Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
2587  Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
2588
2589  uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2590
2591  uint_fast32_t maxlength = 0;
2592  uint_fast32_t nsyms = 0;
2593  for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
2594    {
2595      Elf64_Xword inner = bucket[cnt];
2596      while (inner > 0 && inner < nchain)
2597	{
2598	  ++nsyms;
2599	  if (maxlength < ++lengths[cnt])
2600	    ++maxlength;
2601
2602	  inner = chain[inner];
2603	}
2604    }
2605
2606  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
2607		   lengths, NULL);
2608
2609  free (lengths);
2610}
2611
2612
2613/* This function handles the GNU-style hash table format.  */
2614static void
2615handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2616{
2617  Elf_Data *data = elf_getdata (scn, NULL);
2618  if (unlikely (data == NULL))
2619    {
2620      error (0, 0, gettext ("cannot get data for section %d: %s"),
2621	     (int) elf_ndxscn (scn), elf_errmsg (-1));
2622      return;
2623    }
2624
2625  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
2626  Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
2627
2628  /* Next comes the size of the bitmap.  It's measured in words for
2629     the architecture.  It's 32 bits for 32 bit archs, and 64 bits for
2630     64 bit archs.  */
2631  Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
2632  if (gelf_getclass (ebl->elf) == ELFCLASS64)
2633    bitmask_words *= 2;
2634
2635  Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
2636
2637  uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2638
2639  Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
2640  Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
2641  Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
2642						    + nbucket];
2643
2644  /* Compute distribution of chain lengths.  */
2645  uint_fast32_t maxlength = 0;
2646  uint_fast32_t nsyms = 0;
2647  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2648    if (bucket[cnt] != 0)
2649      {
2650	Elf32_Word inner = bucket[cnt] - symbias;
2651	do
2652	  {
2653	    ++nsyms;
2654	    if (maxlength < ++lengths[cnt])
2655	      ++maxlength;
2656	  }
2657	while ((chain[inner++] & 1) == 0);
2658      }
2659
2660  /* Count bits in bitmask.  */
2661  uint_fast32_t nbits = 0;
2662  for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
2663    {
2664      uint_fast32_t word = bitmask[cnt];
2665
2666      word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
2667      word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
2668      word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
2669      word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
2670      nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
2671    }
2672
2673  char *str;
2674  if (unlikely (asprintf (&str, gettext ("\
2675 Symbol Bias: %u\n\
2676 Bitmask Size: %zu bytes  %" PRIuFAST32 "%% bits set  2nd hash shift: %u\n"),
2677			  (unsigned int) symbias,
2678			  bitmask_words * sizeof (Elf32_Word),
2679			  ((nbits * 100 + 50)
2680			   / (uint_fast32_t) (bitmask_words
2681					      * sizeof (Elf32_Word) * 8)),
2682			  (unsigned int) shift) == -1))
2683    error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
2684
2685  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
2686		   lengths, str);
2687
2688  free (str);
2689  free (lengths);
2690}
2691
2692
2693/* Find the symbol table(s).  For this we have to search through the
2694   section table.  */
2695static void
2696handle_hash (Ebl *ebl)
2697{
2698  /* Get the section header string table index.  */
2699  size_t shstrndx;
2700  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
2701    error (EXIT_FAILURE, 0,
2702	   gettext ("cannot get section header string table index"));
2703
2704  Elf_Scn *scn = NULL;
2705  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2706    {
2707      /* Handle the section if it is a symbol table.  */
2708      GElf_Shdr shdr_mem;
2709      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2710
2711      if (likely (shdr != NULL))
2712	{
2713	  if (shdr->sh_type == SHT_HASH)
2714	    {
2715	      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
2716		handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
2717	      else
2718		handle_sysv_hash (ebl, scn, shdr, shstrndx);
2719	    }
2720	  else if (shdr->sh_type == SHT_GNU_HASH)
2721	    handle_gnu_hash (ebl, scn, shdr, shstrndx);
2722	}
2723    }
2724}
2725
2726
2727static void
2728print_liblist (Ebl *ebl)
2729{
2730  /* Find the library list sections.  For this we have to search
2731     through the section table.  */
2732  Elf_Scn *scn = NULL;
2733
2734  /* Get the section header string table index.  */
2735  size_t shstrndx;
2736  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
2737    error (EXIT_FAILURE, 0,
2738	   gettext ("cannot get section header string table index"));
2739
2740  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2741    {
2742      GElf_Shdr shdr_mem;
2743      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2744
2745      if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
2746	{
2747	  int nentries = shdr->sh_size / shdr->sh_entsize;
2748	  printf (ngettext ("\
2749\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2750			    "\
2751\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2752			    nentries),
2753		  elf_ndxscn (scn),
2754		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2755		  shdr->sh_offset,
2756		  nentries);
2757
2758	  Elf_Data *data = elf_getdata (scn, NULL);
2759	  if (data == NULL)
2760	    return;
2761
2762	  puts (gettext ("\
2763       Library                       Time Stamp          Checksum Version Flags"));
2764
2765	  for (int cnt = 0; cnt < nentries; ++cnt)
2766	    {
2767	      GElf_Lib lib_mem;
2768	      GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
2769	      if (unlikely (lib == NULL))
2770		continue;
2771
2772	      time_t t = (time_t) lib->l_time_stamp;
2773	      struct tm *tm = gmtime (&t);
2774	      if (unlikely (tm == NULL))
2775		continue;
2776
2777	      printf ("  [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
2778		      cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
2779		      tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
2780		      tm->tm_hour, tm->tm_min, tm->tm_sec,
2781		      (unsigned int) lib->l_checksum,
2782		      (unsigned int) lib->l_version,
2783		      (unsigned int) lib->l_flags);
2784	    }
2785	}
2786    }
2787}
2788
2789static void
2790print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
2791{
2792  /* Find the object attributes sections.  For this we have to search
2793     through the section table.  */
2794  Elf_Scn *scn = NULL;
2795
2796  /* Get the section header string table index.  */
2797  size_t shstrndx;
2798  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
2799    error (EXIT_FAILURE, 0,
2800	   gettext ("cannot get section header string table index"));
2801
2802  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2803    {
2804      GElf_Shdr shdr_mem;
2805      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2806
2807      if (shdr == NULL || shdr->sh_type != SHT_GNU_ATTRIBUTES)
2808	continue;
2809
2810      printf (gettext ("\
2811\nObject attributes section [%2zu] '%s' of %" PRIu64
2812		       " bytes at offset %#0" PRIx64 ":\n"),
2813	      elf_ndxscn (scn),
2814	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2815	      shdr->sh_size, shdr->sh_offset);
2816
2817      Elf_Data *data = elf_rawdata (scn, NULL);
2818      if (data == NULL)
2819	return;
2820
2821      const unsigned char *p = data->d_buf;
2822
2823      if (unlikely (*p++ != 'A'))
2824	return;
2825
2826      fputs_unlocked (gettext ("  Owner          Size\n"), stdout);
2827
2828      inline size_t left (void)
2829      {
2830	return (const unsigned char *) data->d_buf + data->d_size - p;
2831      }
2832
2833      while (left () >= 4)
2834	{
2835	  uint32_t len;
2836	  memcpy (&len, p, sizeof len);
2837
2838	  if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
2839	    CONVERT (len);
2840
2841	  if (unlikely (len > left ()))
2842	    break;
2843
2844	  const unsigned char *name = p + sizeof len;
2845	  p += len;
2846
2847	  unsigned const char *q = memchr (name, '\0', len);
2848	  if (unlikely (q == NULL))
2849	    continue;
2850	  ++q;
2851
2852	  printf (gettext ("  %-13s  %4" PRIu32 "\n"), name, len);
2853
2854	  if (q - name == sizeof "gnu"
2855	      && !memcmp (name, "gnu", sizeof "gnu"))
2856	    while (q < p)
2857	      {
2858		const unsigned char *const sub = q;
2859
2860		unsigned int subsection_tag;
2861		get_uleb128 (subsection_tag, q);
2862		if (unlikely (q >= p))
2863		  break;
2864
2865		uint32_t subsection_len;
2866		if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
2867		  break;
2868
2869		memcpy (&subsection_len, q, sizeof subsection_len);
2870
2871		if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
2872		  CONVERT (subsection_len);
2873
2874		if (unlikely (p - sub < (ptrdiff_t) subsection_len))
2875		  break;
2876
2877		const unsigned char *r = q + sizeof subsection_len;
2878		q = sub + subsection_len;
2879
2880		switch (subsection_tag)
2881		  {
2882		  default:
2883		    printf (gettext ("    %-4u %12" PRIu32 "\n"),
2884			    subsection_tag, subsection_len);
2885		    break;
2886
2887		  case 1:	/* Tag_File */
2888		    printf (gettext ("    File: %11" PRIu32 "\n"),
2889			    subsection_len);
2890
2891		    while (r < q)
2892		      {
2893			unsigned int tag;
2894			get_uleb128 (tag, r);
2895			if (unlikely (r >= q))
2896			  break;
2897
2898			uint64_t value = 0;
2899			const char *string = NULL;
2900			if (tag == 32 || (tag & 1) == 0)
2901			  {
2902			    get_uleb128 (value, r);
2903			    if (r > q)
2904			      break;
2905			  }
2906			if (tag == 32 || (tag & 1) != 0)
2907			  {
2908			    r = memchr (r, '\0', q - r);
2909			    if (r == NULL)
2910			      break;
2911			    ++r;
2912			  }
2913
2914			const char *tag_name = NULL;
2915			const char *value_name = NULL;
2916			ebl_check_object_attribute (ebl, (const char *) name,
2917						    tag, value,
2918						    &tag_name, &value_name);
2919
2920			if (tag_name != NULL)
2921			  {
2922			    if (tag == 32)
2923			      printf (gettext ("      %s: %" PRId64 ", %s\n"),
2924				      tag_name, value, string);
2925			    else if (string == NULL && value_name == NULL)
2926			      printf (gettext ("      %s: %" PRId64 "\n"),
2927				      tag_name, value);
2928			    else
2929			      printf (gettext ("      %s: %s\n"),
2930				      tag_name, string ?: value_name);
2931			  }
2932			else
2933			  {
2934			    assert (tag != 32);
2935			    if (string == NULL)
2936			      printf (gettext ("      %u: %" PRId64 "\n"),
2937				      tag, value);
2938			    else
2939			      printf (gettext ("      %u: %s\n"),
2940				      tag, string);
2941			  }
2942		      }
2943		  }
2944	      }
2945	}
2946    }
2947}
2948
2949
2950static char *
2951format_dwarf_addr (Dwfl_Module *dwflmod,
2952		   int address_size, Dwarf_Addr address)
2953{
2954  /* See if there is a name we can give for this address.  */
2955  GElf_Sym sym;
2956  const char *name = dwfl_module_addrsym (dwflmod, address, &sym, NULL);
2957  if (name != NULL)
2958    sym.st_value = address - sym.st_value;
2959
2960  /* Relativize the address.  */
2961  int n = dwfl_module_relocations (dwflmod);
2962  int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
2963
2964  /* In an ET_REL file there is a section name to refer to.  */
2965  const char *scn = (i < 0 ? NULL
2966		     : dwfl_module_relocation_info (dwflmod, i, NULL));
2967
2968  char *result;
2969  if ((name != NULL
2970       ? (sym.st_value != 0
2971	  ? (scn != NULL
2972	     ? (address_size == 0
2973		? asprintf (&result,
2974			    gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
2975			    scn, address, name, sym.st_value)
2976		: asprintf (&result,
2977			    gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
2978			    scn, 2 + address_size * 2, address,
2979			    name, sym.st_value))
2980	     : (address_size == 0
2981		? asprintf (&result,
2982			    gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
2983			    address, name, sym.st_value)
2984		: asprintf (&result,
2985			    gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
2986			    2 + address_size * 2, address,
2987			    name, sym.st_value)))
2988	  : (scn != NULL
2989	     ? (address_size == 0
2990		? asprintf (&result,
2991			    gettext ("%s+%#" PRIx64 " <%s>"),
2992			    scn, address, name)
2993		: asprintf (&result,
2994			    gettext ("%s+%#0*" PRIx64 " <%s>"),
2995			    scn, 2 + address_size * 2, address, name))
2996	     : (address_size == 0
2997		? asprintf (&result,
2998			    gettext ("%#" PRIx64 " <%s>"),
2999			    address, name)
3000		: asprintf (&result,
3001			    gettext ("%#0*" PRIx64 " <%s>"),
3002			    2 + address_size * 2, address, name))))
3003       : (scn != NULL
3004	  ? (address_size == 0
3005	     ? asprintf (&result,
3006			 gettext ("%s+%#" PRIx64),
3007			 scn, address)
3008	     : asprintf (&result,
3009			 gettext ("%s+%#0*" PRIx64),
3010			 scn, 2 + address_size * 2, address))
3011	  : (address_size == 0
3012	     ? asprintf (&result,
3013			 "%#" PRIx64,
3014			 address)
3015	     : asprintf (&result,
3016			 "%#0*" PRIx64,
3017			 2 + address_size * 2, address)))) < 0)
3018    error (EXIT_FAILURE, 0, _("memory exhausted"));
3019
3020  return result;
3021}
3022
3023static const char *
3024dwarf_tag_string (unsigned int tag)
3025{
3026  static const char *const known_tags[]  =
3027    {
3028      [DW_TAG_array_type] = "array_type",
3029      [DW_TAG_class_type] = "class_type",
3030      [DW_TAG_entry_point] = "entry_point",
3031      [DW_TAG_enumeration_type] = "enumeration_type",
3032      [DW_TAG_formal_parameter] = "formal_parameter",
3033      [DW_TAG_imported_declaration] = "imported_declaration",
3034      [DW_TAG_label] = "label",
3035      [DW_TAG_lexical_block] = "lexical_block",
3036      [DW_TAG_member] = "member",
3037      [DW_TAG_pointer_type] = "pointer_type",
3038      [DW_TAG_reference_type] = "reference_type",
3039      [DW_TAG_compile_unit] = "compile_unit",
3040      [DW_TAG_string_type] = "string_type",
3041      [DW_TAG_structure_type] = "structure_type",
3042      [DW_TAG_subroutine_type] = "subroutine_type",
3043      [DW_TAG_typedef] = "typedef",
3044      [DW_TAG_union_type] = "union_type",
3045      [DW_TAG_unspecified_parameters] = "unspecified_parameters",
3046      [DW_TAG_variant] = "variant",
3047      [DW_TAG_common_block] = "common_block",
3048      [DW_TAG_common_inclusion] = "common_inclusion",
3049      [DW_TAG_inheritance] = "inheritance",
3050      [DW_TAG_inlined_subroutine] = "inlined_subroutine",
3051      [DW_TAG_module] = "module",
3052      [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
3053      [DW_TAG_set_type] = "set_type",
3054      [DW_TAG_subrange_type] = "subrange_type",
3055      [DW_TAG_with_stmt] = "with_stmt",
3056      [DW_TAG_access_declaration] = "access_declaration",
3057      [DW_TAG_base_type] = "base_type",
3058      [DW_TAG_catch_block] = "catch_block",
3059      [DW_TAG_const_type] = "const_type",
3060      [DW_TAG_constant] = "constant",
3061      [DW_TAG_enumerator] = "enumerator",
3062      [DW_TAG_file_type] = "file_type",
3063      [DW_TAG_friend] = "friend",
3064      [DW_TAG_namelist] = "namelist",
3065      [DW_TAG_namelist_item] = "namelist_item",
3066      [DW_TAG_packed_type] = "packed_type",
3067      [DW_TAG_subprogram] = "subprogram",
3068      [DW_TAG_template_type_parameter] = "template_type_parameter",
3069      [DW_TAG_template_value_parameter] = "template_value_parameter",
3070      [DW_TAG_thrown_type] = "thrown_type",
3071      [DW_TAG_try_block] = "try_block",
3072      [DW_TAG_variant_part] = "variant_part",
3073      [DW_TAG_variable] = "variable",
3074      [DW_TAG_volatile_type] = "volatile_type",
3075      [DW_TAG_dwarf_procedure] = "dwarf_procedure",
3076      [DW_TAG_restrict_type] = "restrict_type",
3077      [DW_TAG_interface_type] = "interface_type",
3078      [DW_TAG_namespace] = "namespace",
3079      [DW_TAG_imported_module] = "imported_module",
3080      [DW_TAG_unspecified_type] = "unspecified_type",
3081      [DW_TAG_partial_unit] = "partial_unit",
3082      [DW_TAG_imported_unit] = "imported_unit",
3083      [DW_TAG_mutable_type] = "mutable_type",
3084      [DW_TAG_condition] = "condition",
3085      [DW_TAG_shared_type] = "shared_type",
3086    };
3087  const unsigned int nknown_tags = (sizeof (known_tags)
3088				    / sizeof (known_tags[0]));
3089  static char buf[40];
3090  const char *result = NULL;
3091
3092  if (likely (tag < nknown_tags))
3093    result = known_tags[tag];
3094
3095  if (unlikely (result == NULL))
3096    /* There are a few known extensions.  */
3097    switch (tag)
3098      {
3099      case DW_TAG_MIPS_loop:
3100	result = "MIPS_loop";
3101	break;
3102
3103      case DW_TAG_format_label:
3104	result = "format_label";
3105	break;
3106
3107      case DW_TAG_function_template:
3108	result = "function_template";
3109	break;
3110
3111      case DW_TAG_class_template:
3112	result = "class_template";
3113	break;
3114
3115      default:
3116	if (tag < DW_TAG_lo_user)
3117	  snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag);
3118	else
3119	  snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag);
3120	result = buf;
3121	break;
3122      }
3123
3124  return result;
3125}
3126
3127
3128static const char *
3129dwarf_attr_string (unsigned int attrnum)
3130{
3131  static const char *const known_attrs[] =
3132    {
3133      [DW_AT_sibling] = "sibling",
3134      [DW_AT_location] = "location",
3135      [DW_AT_name] = "name",
3136      [DW_AT_ordering] = "ordering",
3137      [DW_AT_subscr_data] = "subscr_data",
3138      [DW_AT_byte_size] = "byte_size",
3139      [DW_AT_bit_offset] = "bit_offset",
3140      [DW_AT_bit_size] = "bit_size",
3141      [DW_AT_element_list] = "element_list",
3142      [DW_AT_stmt_list] = "stmt_list",
3143      [DW_AT_low_pc] = "low_pc",
3144      [DW_AT_high_pc] = "high_pc",
3145      [DW_AT_language] = "language",
3146      [DW_AT_member] = "member",
3147      [DW_AT_discr] = "discr",
3148      [DW_AT_discr_value] = "discr_value",
3149      [DW_AT_visibility] = "visibility",
3150      [DW_AT_import] = "import",
3151      [DW_AT_string_length] = "string_length",
3152      [DW_AT_common_reference] = "common_reference",
3153      [DW_AT_comp_dir] = "comp_dir",
3154      [DW_AT_const_value] = "const_value",
3155      [DW_AT_containing_type] = "containing_type",
3156      [DW_AT_default_value] = "default_value",
3157      [DW_AT_inline] = "inline",
3158      [DW_AT_is_optional] = "is_optional",
3159      [DW_AT_lower_bound] = "lower_bound",
3160      [DW_AT_producer] = "producer",
3161      [DW_AT_prototyped] = "prototyped",
3162      [DW_AT_return_addr] = "return_addr",
3163      [DW_AT_start_scope] = "start_scope",
3164      [DW_AT_bit_stride] = "bit_stride",
3165      [DW_AT_upper_bound] = "upper_bound",
3166      [DW_AT_abstract_origin] = "abstract_origin",
3167      [DW_AT_accessibility] = "accessibility",
3168      [DW_AT_address_class] = "address_class",
3169      [DW_AT_artificial] = "artificial",
3170      [DW_AT_base_types] = "base_types",
3171      [DW_AT_calling_convention] = "calling_convention",
3172      [DW_AT_count] = "count",
3173      [DW_AT_data_member_location] = "data_member_location",
3174      [DW_AT_decl_column] = "decl_column",
3175      [DW_AT_decl_file] = "decl_file",
3176      [DW_AT_decl_line] = "decl_line",
3177      [DW_AT_declaration] = "declaration",
3178      [DW_AT_discr_list] = "discr_list",
3179      [DW_AT_encoding] = "encoding",
3180      [DW_AT_external] = "external",
3181      [DW_AT_frame_base] = "frame_base",
3182      [DW_AT_friend] = "friend",
3183      [DW_AT_identifier_case] = "identifier_case",
3184      [DW_AT_macro_info] = "macro_info",
3185      [DW_AT_namelist_item] = "namelist_item",
3186      [DW_AT_priority] = "priority",
3187      [DW_AT_segment] = "segment",
3188      [DW_AT_specification] = "specification",
3189      [DW_AT_static_link] = "static_link",
3190      [DW_AT_type] = "type",
3191      [DW_AT_use_location] = "use_location",
3192      [DW_AT_variable_parameter] = "variable_parameter",
3193      [DW_AT_virtuality] = "virtuality",
3194      [DW_AT_vtable_elem_location] = "vtable_elem_location",
3195      [DW_AT_allocated] = "allocated",
3196      [DW_AT_associated] = "associated",
3197      [DW_AT_data_location] = "data_location",
3198      [DW_AT_byte_stride] = "byte_stride",
3199      [DW_AT_entry_pc] = "entry_pc",
3200      [DW_AT_use_UTF8] = "use_UTF8",
3201      [DW_AT_extension] = "extension",
3202      [DW_AT_ranges] = "ranges",
3203      [DW_AT_trampoline] = "trampoline",
3204      [DW_AT_call_column] = "call_column",
3205      [DW_AT_call_file] = "call_file",
3206      [DW_AT_call_line] = "call_line",
3207      [DW_AT_description] = "description",
3208      [DW_AT_binary_scale] = "binary_scale",
3209      [DW_AT_decimal_scale] = "decimal_scale",
3210      [DW_AT_small] = "small",
3211      [DW_AT_decimal_sign] = "decimal_sign",
3212      [DW_AT_digit_count] = "digit_count",
3213      [DW_AT_picture_string] = "picture_string",
3214      [DW_AT_mutable] = "mutable",
3215      [DW_AT_threads_scaled] = "threads_scaled",
3216      [DW_AT_explicit] = "explicit",
3217      [DW_AT_object_pointer] = "object_pointer",
3218      [DW_AT_endianity] = "endianity",
3219      [DW_AT_elemental] = "elemental",
3220      [DW_AT_pure] = "pure",
3221      [DW_AT_recursive] = "recursive",
3222    };
3223  const unsigned int nknown_attrs = (sizeof (known_attrs)
3224				     / sizeof (known_attrs[0]));
3225  static char buf[40];
3226  const char *result = NULL;
3227
3228  if (likely (attrnum < nknown_attrs))
3229    result = known_attrs[attrnum];
3230
3231  if (unlikely (result == NULL))
3232    /* There are a few known extensions.  */
3233    switch (attrnum)
3234      {
3235      case DW_AT_MIPS_fde:
3236	result = "MIPS_fde";
3237	break;
3238
3239      case DW_AT_MIPS_loop_begin:
3240	result = "MIPS_loop_begin";
3241	break;
3242
3243      case DW_AT_MIPS_tail_loop_begin:
3244	result = "MIPS_tail_loop_begin";
3245	break;
3246
3247      case DW_AT_MIPS_epilog_begin:
3248	result = "MIPS_epilog_begin";
3249	break;
3250
3251      case DW_AT_MIPS_loop_unroll_factor:
3252	result = "MIPS_loop_unroll_factor";
3253	break;
3254
3255      case DW_AT_MIPS_software_pipeline_depth:
3256	result = "MIPS_software_pipeline_depth";
3257	break;
3258
3259      case DW_AT_MIPS_linkage_name:
3260	result = "MIPS_linkage_name";
3261	break;
3262
3263      case DW_AT_MIPS_stride:
3264	result = "MIPS_stride";
3265	break;
3266
3267      case DW_AT_MIPS_abstract_name:
3268	result = "MIPS_abstract_name";
3269	break;
3270
3271      case DW_AT_MIPS_clone_origin:
3272	result = "MIPS_clone_origin";
3273	break;
3274
3275      case DW_AT_MIPS_has_inlines:
3276	result = "MIPS_has_inlines";
3277	break;
3278
3279      case DW_AT_MIPS_stride_byte:
3280	result = "MIPS_stride_byte";
3281	break;
3282
3283      case DW_AT_MIPS_stride_elem:
3284	result = "MIPS_stride_elem";
3285	break;
3286
3287      case DW_AT_MIPS_ptr_dopetype:
3288	result = "MIPS_ptr_dopetype";
3289	break;
3290
3291      case DW_AT_MIPS_allocatable_dopetype:
3292	result = "MIPS_allocatable_dopetype";
3293	break;
3294
3295      case DW_AT_MIPS_assumed_shape_dopetype:
3296	result = "MIPS_assumed_shape_dopetype";
3297	break;
3298
3299      case DW_AT_MIPS_assumed_size:
3300	result = "MIPS_assumed_size";
3301	break;
3302
3303      case DW_AT_sf_names:
3304	result = "sf_names";
3305	break;
3306
3307      case DW_AT_src_info:
3308	result = "src_info";
3309	break;
3310
3311      case DW_AT_mac_info:
3312	result = "mac_info";
3313	break;
3314
3315      case DW_AT_src_coords:
3316	result = "src_coords";
3317	break;
3318
3319      case DW_AT_body_begin:
3320	result = "body_begin";
3321	break;
3322
3323      case DW_AT_body_end:
3324	result = "body_end";
3325	break;
3326
3327      default:
3328	if (attrnum < DW_AT_lo_user)
3329	  snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"),
3330		    attrnum);
3331	else
3332	  snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"),
3333		    attrnum);
3334	result = buf;
3335	break;
3336      }
3337
3338  return result;
3339}
3340
3341
3342static const char *
3343dwarf_form_string (unsigned int form)
3344{
3345  static const char *const known_forms[] =
3346    {
3347      [DW_FORM_addr] = "addr",
3348      [DW_FORM_block2] = "block2",
3349      [DW_FORM_block4] = "block4",
3350      [DW_FORM_data2] = "data2",
3351      [DW_FORM_data4] = "data4",
3352      [DW_FORM_data8] = "data8",
3353      [DW_FORM_string] = "string",
3354      [DW_FORM_block] = "block",
3355      [DW_FORM_block1] = "block1",
3356      [DW_FORM_data1] = "data1",
3357      [DW_FORM_flag] = "flag",
3358      [DW_FORM_sdata] = "sdata",
3359      [DW_FORM_strp] = "strp",
3360      [DW_FORM_udata] = "udata",
3361      [DW_FORM_ref_addr] = "ref_addr",
3362      [DW_FORM_ref1] = "ref1",
3363      [DW_FORM_ref2] = "ref2",
3364      [DW_FORM_ref4] = "ref4",
3365      [DW_FORM_ref8] = "ref8",
3366      [DW_FORM_ref_udata] = "ref_udata",
3367      [DW_FORM_indirect] = "indirect"
3368    };
3369  const unsigned int nknown_forms = (sizeof (known_forms)
3370				     / sizeof (known_forms[0]));
3371  static char buf[40];
3372  const char *result = NULL;
3373
3374  if (likely (form < nknown_forms))
3375    result = known_forms[form];
3376
3377  if (unlikely (result == NULL))
3378    snprintf (buf, sizeof buf, gettext ("unknown form %" PRIx64),
3379	      (uint64_t) form);
3380
3381  return result;
3382}
3383
3384
3385static const char *
3386dwarf_lang_string (unsigned int lang)
3387{
3388  static const char *const known[] =
3389    {
3390      [DW_LANG_C89] = "ISO C89",
3391      [DW_LANG_C] = "C",
3392      [DW_LANG_Ada83] = "Ada83",
3393      [DW_LANG_C_plus_plus] = "C++",
3394      [DW_LANG_Cobol74] = "Cobol74",
3395      [DW_LANG_Cobol85] = "Cobol85",
3396      [DW_LANG_Fortran77] = "Fortran77",
3397      [DW_LANG_Fortran90] = "Fortran90",
3398      [DW_LANG_Pascal83] = "Pascal83",
3399      [DW_LANG_Modula2] = "Modula2",
3400      [DW_LANG_Java] = "Java",
3401      [DW_LANG_C99] = "ISO C99",
3402      [DW_LANG_Ada95] = "Ada95",
3403      [DW_LANG_Fortran95] = "Fortran95",
3404      [DW_LANG_PL1] = "PL1",
3405      [DW_LANG_Objc] = "Objective C",
3406      [DW_LANG_ObjC_plus_plus] = "Objective C++",
3407      [DW_LANG_UPC] = "UPC",
3408      [DW_LANG_D] = "D",
3409    };
3410
3411  if (likely (lang < sizeof (known) / sizeof (known[0])))
3412    return known[lang];
3413  else if (lang == DW_LANG_Mips_Assembler)
3414    /* This language tag is used for assembler in general.  */
3415    return "Assembler";
3416
3417  if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user)
3418    {
3419      static char buf[30];
3420      snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user);
3421      return buf;
3422    }
3423
3424  return "???";
3425}
3426
3427
3428static const char *
3429dwarf_inline_string (unsigned int code)
3430{
3431  static const char *const known[] =
3432    {
3433      [DW_INL_not_inlined] = "not_inlined",
3434      [DW_INL_inlined] = "inlined",
3435      [DW_INL_declared_not_inlined] = "declared_not_inlined",
3436      [DW_INL_declared_inlined] = "declared_inlined"
3437    };
3438
3439  if (likely (code < sizeof (known) / sizeof (known[0])))
3440    return known[code];
3441
3442  return "???";
3443}
3444
3445
3446static const char *
3447dwarf_encoding_string (unsigned int code)
3448{
3449  static const char *const known[] =
3450    {
3451      [DW_ATE_void] = "void",
3452      [DW_ATE_address] = "address",
3453      [DW_ATE_boolean] = "boolean",
3454      [DW_ATE_complex_float] = "complex_float",
3455      [DW_ATE_float] = "float",
3456      [DW_ATE_signed] = "signed",
3457      [DW_ATE_signed_char] = "signed_char",
3458      [DW_ATE_unsigned] = "unsigned",
3459      [DW_ATE_unsigned_char] = "unsigned_char",
3460      [DW_ATE_imaginary_float] = "imaginary_float",
3461      [DW_ATE_packed_decimal] = "packed_decimal",
3462      [DW_ATE_numeric_string] = "numeric_string",
3463      [DW_ATE_edited] = "edited",
3464      [DW_ATE_signed_fixed] = "signed_fixed",
3465      [DW_ATE_unsigned_fixed] = "unsigned_fixed",
3466      [DW_ATE_decimal_float] = "decimal_float",
3467    };
3468
3469  if (likely (code < sizeof (known) / sizeof (known[0])))
3470    return known[code];
3471
3472  if (code >= DW_ATE_lo_user && code <= DW_ATE_hi_user)
3473    {
3474      static char buf[30];
3475      snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_ATE_lo_user);
3476      return buf;
3477    }
3478
3479  return "???";
3480}
3481
3482
3483static const char *
3484dwarf_access_string (unsigned int code)
3485{
3486  static const char *const known[] =
3487    {
3488      [DW_ACCESS_public] = "public",
3489      [DW_ACCESS_protected] = "protected",
3490      [DW_ACCESS_private] = "private"
3491    };
3492
3493  if (likely (code < sizeof (known) / sizeof (known[0])))
3494    return known[code];
3495
3496  return "???";
3497}
3498
3499
3500static const char *
3501dwarf_visibility_string (unsigned int code)
3502{
3503  static const char *const known[] =
3504    {
3505      [DW_VIS_local] = "local",
3506      [DW_VIS_exported] = "exported",
3507      [DW_VIS_qualified] = "qualified"
3508    };
3509
3510  if (likely (code < sizeof (known) / sizeof (known[0])))
3511    return known[code];
3512
3513  return "???";
3514}
3515
3516
3517static const char *
3518dwarf_virtuality_string (unsigned int code)
3519{
3520  static const char *const known[] =
3521    {
3522      [DW_VIRTUALITY_none] = "none",
3523      [DW_VIRTUALITY_virtual] = "virtual",
3524      [DW_VIRTUALITY_pure_virtual] = "pure_virtual"
3525    };
3526
3527  if (likely (code < sizeof (known) / sizeof (known[0])))
3528    return known[code];
3529
3530  return "???";
3531}
3532
3533
3534static const char *
3535dwarf_identifier_case_string (unsigned int code)
3536{
3537  static const char *const known[] =
3538    {
3539      [DW_ID_case_sensitive] = "sensitive",
3540      [DW_ID_up_case] = "up_case",
3541      [DW_ID_down_case] = "down_case",
3542      [DW_ID_case_insensitive] = "insensitive"
3543    };
3544
3545  if (likely (code < sizeof (known) / sizeof (known[0])))
3546    return known[code];
3547
3548  return "???";
3549}
3550
3551
3552static const char *
3553dwarf_calling_convention_string (unsigned int code)
3554{
3555  static const char *const known[] =
3556    {
3557      [DW_CC_normal] = "normal",
3558      [DW_CC_program] = "program",
3559      [DW_CC_nocall] = "nocall",
3560    };
3561
3562  if (likely (code < sizeof (known) / sizeof (known[0])))
3563    return known[code];
3564
3565  if (code >= DW_CC_lo_user && code <= DW_CC_hi_user)
3566    {
3567      static char buf[30];
3568      snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_CC_lo_user);
3569      return buf;
3570    }
3571
3572  return "???";
3573}
3574
3575
3576static const char *
3577dwarf_ordering_string (unsigned int code)
3578{
3579  static const char *const known[] =
3580    {
3581      [DW_ORD_row_major] = "row_major",
3582      [DW_ORD_col_major] = "col_major"
3583    };
3584
3585  if (likely (code < sizeof (known) / sizeof (known[0])))
3586    return known[code];
3587
3588  return "???";
3589}
3590
3591
3592static const char *
3593dwarf_discr_list_string (unsigned int code)
3594{
3595  static const char *const known[] =
3596    {
3597      [DW_DSC_label] = "label",
3598      [DW_DSC_range] = "range"
3599    };
3600
3601  if (likely (code < sizeof (known) / sizeof (known[0])))
3602    return known[code];
3603
3604  return "???";
3605}
3606
3607
3608static void
3609print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
3610	   unsigned int addrsize, Dwarf_Word len, const unsigned char *data)
3611{
3612  static const char *const known[] =
3613    {
3614      [DW_OP_addr] = "addr",
3615      [DW_OP_deref] = "deref",
3616      [DW_OP_const1u] = "const1u",
3617      [DW_OP_const1s] = "const1s",
3618      [DW_OP_const2u] = "const2u",
3619      [DW_OP_const2s] = "const2s",
3620      [DW_OP_const4u] = "const4u",
3621      [DW_OP_const4s] = "const4s",
3622      [DW_OP_const8u] = "const8u",
3623      [DW_OP_const8s] = "const8s",
3624      [DW_OP_constu] = "constu",
3625      [DW_OP_consts] = "consts",
3626      [DW_OP_dup] = "dup",
3627      [DW_OP_drop] = "drop",
3628      [DW_OP_over] = "over",
3629      [DW_OP_pick] = "pick",
3630      [DW_OP_swap] = "swap",
3631      [DW_OP_rot] = "rot",
3632      [DW_OP_xderef] = "xderef",
3633      [DW_OP_abs] = "abs",
3634      [DW_OP_and] = "and",
3635      [DW_OP_div] = "div",
3636      [DW_OP_minus] = "minus",
3637      [DW_OP_mod] = "mod",
3638      [DW_OP_mul] = "mul",
3639      [DW_OP_neg] = "neg",
3640      [DW_OP_not] = "not",
3641      [DW_OP_or] = "or",
3642      [DW_OP_plus] = "plus",
3643      [DW_OP_plus_uconst] = "plus_uconst",
3644      [DW_OP_shl] = "shl",
3645      [DW_OP_shr] = "shr",
3646      [DW_OP_shra] = "shra",
3647      [DW_OP_xor] = "xor",
3648      [DW_OP_bra] = "bra",
3649      [DW_OP_eq] = "eq",
3650      [DW_OP_ge] = "ge",
3651      [DW_OP_gt] = "gt",
3652      [DW_OP_le] = "le",
3653      [DW_OP_lt] = "lt",
3654      [DW_OP_ne] = "ne",
3655      [DW_OP_skip] = "skip",
3656      [DW_OP_lit0] = "lit0",
3657      [DW_OP_lit1] = "lit1",
3658      [DW_OP_lit2] = "lit2",
3659      [DW_OP_lit3] = "lit3",
3660      [DW_OP_lit4] = "lit4",
3661      [DW_OP_lit5] = "lit5",
3662      [DW_OP_lit6] = "lit6",
3663      [DW_OP_lit7] = "lit7",
3664      [DW_OP_lit8] = "lit8",
3665      [DW_OP_lit9] = "lit9",
3666      [DW_OP_lit10] = "lit10",
3667      [DW_OP_lit11] = "lit11",
3668      [DW_OP_lit12] = "lit12",
3669      [DW_OP_lit13] = "lit13",
3670      [DW_OP_lit14] = "lit14",
3671      [DW_OP_lit15] = "lit15",
3672      [DW_OP_lit16] = "lit16",
3673      [DW_OP_lit17] = "lit17",
3674      [DW_OP_lit18] = "lit18",
3675      [DW_OP_lit19] = "lit19",
3676      [DW_OP_lit20] = "lit20",
3677      [DW_OP_lit21] = "lit21",
3678      [DW_OP_lit22] = "lit22",
3679      [DW_OP_lit23] = "lit23",
3680      [DW_OP_lit24] = "lit24",
3681      [DW_OP_lit25] = "lit25",
3682      [DW_OP_lit26] = "lit26",
3683      [DW_OP_lit27] = "lit27",
3684      [DW_OP_lit28] = "lit28",
3685      [DW_OP_lit29] = "lit29",
3686      [DW_OP_lit30] = "lit30",
3687      [DW_OP_lit31] = "lit31",
3688      [DW_OP_reg0] = "reg0",
3689      [DW_OP_reg1] = "reg1",
3690      [DW_OP_reg2] = "reg2",
3691      [DW_OP_reg3] = "reg3",
3692      [DW_OP_reg4] = "reg4",
3693      [DW_OP_reg5] = "reg5",
3694      [DW_OP_reg6] = "reg6",
3695      [DW_OP_reg7] = "reg7",
3696      [DW_OP_reg8] = "reg8",
3697      [DW_OP_reg9] = "reg9",
3698      [DW_OP_reg10] = "reg10",
3699      [DW_OP_reg11] = "reg11",
3700      [DW_OP_reg12] = "reg12",
3701      [DW_OP_reg13] = "reg13",
3702      [DW_OP_reg14] = "reg14",
3703      [DW_OP_reg15] = "reg15",
3704      [DW_OP_reg16] = "reg16",
3705      [DW_OP_reg17] = "reg17",
3706      [DW_OP_reg18] = "reg18",
3707      [DW_OP_reg19] = "reg19",
3708      [DW_OP_reg20] = "reg20",
3709      [DW_OP_reg21] = "reg21",
3710      [DW_OP_reg22] = "reg22",
3711      [DW_OP_reg23] = "reg23",
3712      [DW_OP_reg24] = "reg24",
3713      [DW_OP_reg25] = "reg25",
3714      [DW_OP_reg26] = "reg26",
3715      [DW_OP_reg27] = "reg27",
3716      [DW_OP_reg28] = "reg28",
3717      [DW_OP_reg29] = "reg29",
3718      [DW_OP_reg30] = "reg30",
3719      [DW_OP_reg31] = "reg31",
3720      [DW_OP_breg0] = "breg0",
3721      [DW_OP_breg1] = "breg1",
3722      [DW_OP_breg2] = "breg2",
3723      [DW_OP_breg3] = "breg3",
3724      [DW_OP_breg4] = "breg4",
3725      [DW_OP_breg5] = "breg5",
3726      [DW_OP_breg6] = "breg6",
3727      [DW_OP_breg7] = "breg7",
3728      [DW_OP_breg8] = "breg8",
3729      [DW_OP_breg9] = "breg9",
3730      [DW_OP_breg10] = "breg10",
3731      [DW_OP_breg11] = "breg11",
3732      [DW_OP_breg12] = "breg12",
3733      [DW_OP_breg13] = "breg13",
3734      [DW_OP_breg14] = "breg14",
3735      [DW_OP_breg15] = "breg15",
3736      [DW_OP_breg16] = "breg16",
3737      [DW_OP_breg17] = "breg17",
3738      [DW_OP_breg18] = "breg18",
3739      [DW_OP_breg19] = "breg19",
3740      [DW_OP_breg20] = "breg20",
3741      [DW_OP_breg21] = "breg21",
3742      [DW_OP_breg22] = "breg22",
3743      [DW_OP_breg23] = "breg23",
3744      [DW_OP_breg24] = "breg24",
3745      [DW_OP_breg25] = "breg25",
3746      [DW_OP_breg26] = "breg26",
3747      [DW_OP_breg27] = "breg27",
3748      [DW_OP_breg28] = "breg28",
3749      [DW_OP_breg29] = "breg29",
3750      [DW_OP_breg30] = "breg30",
3751      [DW_OP_breg31] = "breg31",
3752      [DW_OP_regx] = "regx",
3753      [DW_OP_fbreg] = "fbreg",
3754      [DW_OP_bregx] = "bregx",
3755      [DW_OP_piece] = "piece",
3756      [DW_OP_deref_size] = "deref_size",
3757      [DW_OP_xderef_size] = "xderef_size",
3758      [DW_OP_nop] = "nop",
3759      [DW_OP_push_object_address] = "push_object_address",
3760      [DW_OP_call2] = "call2",
3761      [DW_OP_call4] = "call4",
3762      [DW_OP_call_ref] = "call_ref",
3763      [DW_OP_form_tls_address] = "form_tls_address",
3764      [DW_OP_call_frame_cfa] = "call_frame_cfa",
3765      [DW_OP_bit_piece] = "bit_piece",
3766    };
3767
3768  Dwarf_Word offset = 0;
3769  while (len-- > 0)
3770    {
3771      uint_fast8_t op = *data++;
3772
3773      switch (op)
3774	{
3775	case DW_OP_call_ref:
3776	case DW_OP_addr:;
3777	  /* Address operand.  */
3778	  Dwarf_Word addr;
3779	  if (addrsize == 4)
3780	    addr = read_4ubyte_unaligned (dbg, data);
3781	  else
3782	    {
3783	      assert (addrsize == 8);
3784	      addr = read_8ubyte_unaligned (dbg, data);
3785	    }
3786	  data += addrsize;
3787	  len -= addrsize;
3788
3789	  if (op == DW_OP_addr)
3790	    {
3791	      char *a = format_dwarf_addr (dwflmod, 0, addr);
3792	      printf ("%*s[%4" PRIuMAX "] %s %s\n",
3793		      indent, "", (uintmax_t) offset,
3794		      known[op] ?: "???", a);
3795	      free (a);
3796	    }
3797	  else
3798	    printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
3799		    indent, "", (uintmax_t) offset,
3800		    known[op] ?: "???", (uintmax_t) addr);
3801	  offset += 1 + addrsize;
3802	  break;
3803
3804	case DW_OP_deref_size:
3805	case DW_OP_xderef_size:
3806	case DW_OP_pick:
3807	case DW_OP_const1u:
3808	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
3809		  indent, "", (uintmax_t) offset,
3810		  known[op] ?: "???", *((uint8_t *) data));
3811	  ++data;
3812	  --len;
3813	  offset += 2;
3814	  break;
3815
3816	case DW_OP_const2u:
3817	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
3818		  indent, "", (uintmax_t) offset,
3819		  known[op] ?: "???", read_2ubyte_unaligned (dbg, data));
3820	  len -= 2;
3821	  data += 2;
3822	  offset += 3;
3823	  break;
3824
3825	case DW_OP_const4u:
3826	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
3827		  indent, "", (uintmax_t) offset,
3828		  known[op] ?: "???", read_4ubyte_unaligned (dbg, data));
3829	  len -= 4;
3830	  data += 4;
3831	  offset += 5;
3832	  break;
3833
3834	case DW_OP_const8u:
3835	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
3836		  indent, "", (uintmax_t) offset,
3837		  known[op] ?: "???", read_8ubyte_unaligned (dbg, data));
3838	  len -= 8;
3839	  data += 8;
3840	  offset += 9;
3841	  break;
3842
3843	case DW_OP_const1s:
3844	  printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
3845		  indent, "", (uintmax_t) offset,
3846		  known[op] ?: "???", *((int8_t *) data));
3847	  ++data;
3848	  --len;
3849	  offset += 2;
3850	  break;
3851
3852	case DW_OP_const2s:
3853	  printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
3854		  indent, "", (uintmax_t) offset,
3855		  known[op] ?: "???", read_2sbyte_unaligned (dbg, data));
3856	  len -= 2;
3857	  data += 2;
3858	  offset += 3;
3859	  break;
3860
3861	case DW_OP_const4s:
3862	  printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
3863		  indent, "", (uintmax_t) offset,
3864		  known[op] ?: "???", read_4sbyte_unaligned (dbg, data));
3865	  len -= 4;
3866	  data += 4;
3867	  offset += 5;
3868	  break;
3869
3870	case DW_OP_const8s:
3871	  printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
3872		  indent, "", (uintmax_t) offset,
3873		  known[op] ?: "???", read_8sbyte_unaligned (dbg, data));
3874	  len -= 8;
3875	  data += 8;
3876	  offset += 9;
3877	  break;
3878
3879	case DW_OP_piece:
3880	case DW_OP_regx:
3881	case DW_OP_plus_uconst:
3882	case DW_OP_constu:;
3883	  const unsigned char *start = data;
3884	  unsigned int uleb;
3885	  get_uleb128 (uleb, data);
3886	  printf ("%*s[%4" PRIuMAX "] %s %u\n",
3887		  indent, "", (uintmax_t) offset,
3888		  known[op] ?: "???", uleb);
3889	  len -= data - start;
3890	  offset += 1 + (data - start);
3891	  break;
3892
3893	case DW_OP_bit_piece:
3894	  start = data;
3895	  unsigned int uleb2;
3896	  get_uleb128 (uleb, data);
3897	  get_uleb128 (uleb2, data);
3898	  printf ("%*s[%4" PRIuMAX "] %s %u, %u\n",
3899		  indent, "", (uintmax_t) offset,
3900		  known[op] ?: "???", uleb, uleb2);
3901	  len -= data - start;
3902	  offset += 1 + (data - start);
3903	  break;
3904
3905	case DW_OP_fbreg:
3906	case DW_OP_breg0 ... DW_OP_breg31:
3907	case DW_OP_consts:
3908	  start = data;
3909	  unsigned int sleb;
3910	  get_sleb128 (sleb, data);
3911	  printf ("%*s[%4" PRIuMAX "] %s %d\n",
3912		  indent, "", (uintmax_t) offset,
3913		  known[op] ?: "???", sleb);
3914	  len -= data - start;
3915	  offset += 1 + (data - start);
3916	  break;
3917
3918	case DW_OP_bregx:
3919	  start = data;
3920	  get_uleb128 (uleb, data);
3921	  get_sleb128 (sleb, data);
3922	  printf ("%*s[%4" PRIuMAX "] %s %u %d\n",
3923		  indent, "", (uintmax_t) offset,
3924		  known[op] ?: "???", uleb, sleb);
3925	  len -= data - start;
3926	  offset += 1 + (data - start);
3927	  break;
3928
3929	case DW_OP_call2:
3930	case DW_OP_call4:
3931	case DW_OP_skip:
3932	case DW_OP_bra:
3933	  printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
3934		  indent, "", (uintmax_t) offset,
3935		  known[op] ?: "???",
3936		  (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
3937	  len -= 2;
3938	  data += 2;
3939	  offset += 3;
3940	  break;
3941
3942	default:
3943	  /* No Operand.  */
3944	  if (op < sizeof known / sizeof known[0] && known[op] != NULL)
3945	    printf ("%*s[%4" PRIuMAX "] %s\n",
3946		    indent, "", (uintmax_t) offset, known[op]);
3947	  else
3948	    printf ("%*s[%4" PRIuMAX "] %#x\n",
3949		    indent, "", (uintmax_t) offset, op);
3950	  ++offset;
3951	  break;
3952	}
3953
3954      indent = indentrest;
3955    }
3956}
3957
3958
3959static void
3960print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
3961			    Ebl *ebl __attribute__ ((unused)),
3962			    GElf_Ehdr *ehdr __attribute__ ((unused)),
3963			    Elf_Scn *scn __attribute__ ((unused)),
3964			    GElf_Shdr *shdr, Dwarf *dbg)
3965{
3966  printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
3967		   " [ Code]\n"),
3968	  ".debug_abbrev", (uint64_t) shdr->sh_offset);
3969
3970  Dwarf_Off offset = 0;
3971  while (offset < shdr->sh_size)
3972    {
3973      printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
3974	      offset);
3975
3976      while (1)
3977	{
3978	  size_t length;
3979	  Dwarf_Abbrev abbrev;
3980
3981	  int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
3982	  if (res != 0)
3983	    {
3984	      if (unlikely (res < 0))
3985		{
3986		  printf (gettext ("\
3987 *** error while reading abbreviation: %s\n"),
3988			  dwarf_errmsg (-1));
3989		  return;
3990		}
3991
3992	      /* This is the NUL byte at the end of the section.  */
3993	      ++offset;
3994	      break;
3995	    }
3996
3997	  /* We know these calls can never fail.  */
3998	  unsigned int code = dwarf_getabbrevcode (&abbrev);
3999	  unsigned int tag = dwarf_getabbrevtag (&abbrev);
4000	  int has_children = dwarf_abbrevhaschildren (&abbrev);
4001
4002	  printf (gettext (" [%5u] offset: %" PRId64
4003			   ", children: %s, tag: %s\n"),
4004		  code, (int64_t) offset,
4005		  has_children ? gettext ("yes") : gettext ("no"),
4006		  dwarf_tag_string (tag));
4007
4008	  size_t cnt = 0;
4009	  unsigned int name;
4010	  unsigned int form;
4011	  Dwarf_Off enoffset;
4012	  while (dwarf_getabbrevattr (&abbrev, cnt,
4013				      &name, &form, &enoffset) == 0)
4014	    {
4015	      printf ("          attr: %s, form: %s, offset: %#" PRIx64 "\n",
4016		      dwarf_attr_string (name), dwarf_form_string (form),
4017		      (uint64_t) enoffset);
4018
4019	      ++cnt;
4020	    }
4021
4022	  offset += length;
4023	}
4024    }
4025}
4026
4027
4028/* Print content of DWARF .debug_aranges section.  We fortunately do
4029   not have to know a bit about the structure of the section, libdwarf
4030   takes care of it.  */
4031static void
4032print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
4033			     Ebl *ebl __attribute__ ((unused)),
4034			     GElf_Ehdr *ehdr __attribute__ ((unused)),
4035			     Elf_Scn *scn __attribute__ ((unused)),
4036			     GElf_Shdr *shdr, Dwarf *dbg)
4037{
4038  Dwarf_Aranges *aranges;
4039  size_t cnt;
4040  if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
4041    {
4042      error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
4043	     dwarf_errmsg (-1));
4044      return;
4045    }
4046
4047  printf (ngettext ("\
4048\nDWARF section '%s' at offset %#" PRIx64 " contains %zu entry:\n",
4049		    "\
4050\nDWARF section '%s' at offset %#" PRIx64 " contains %zu entries:\n",
4051		    cnt),
4052	  ".debug_aranges", (uint64_t) shdr->sh_offset, cnt);
4053
4054  /* Compute floor(log16(cnt)).  */
4055  size_t tmp = cnt;
4056  int digits = 1;
4057  while (tmp >= 16)
4058    {
4059      ++digits;
4060      tmp >>= 4;
4061    }
4062
4063  for (size_t n = 0; n < cnt; ++n)
4064    {
4065      Dwarf_Arange *runp = dwarf_onearange (aranges, n);
4066      if (unlikely (runp == NULL))
4067	{
4068	  printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
4069	  return;
4070	}
4071
4072      Dwarf_Addr start;
4073      Dwarf_Word length;
4074      Dwarf_Off offset;
4075
4076      if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
4077	printf (gettext (" [%*zu] ???\n"), digits, n);
4078      else
4079	printf (gettext (" [%*zu] start: %0#*" PRIx64
4080			 ", length: %5" PRIu64 ", CU DIE offset: %6"
4081			 PRId64 "\n"),
4082		digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
4083		(uint64_t) start, (uint64_t) length, (int64_t) offset);
4084    }
4085}
4086
4087/* Print content of DWARF .debug_ranges section.  */
4088static void
4089print_debug_ranges_section (Dwfl_Module *dwflmod,
4090			    Ebl *ebl __attribute__ ((unused)),
4091			    GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr,
4092			    Dwarf *dbg)
4093{
4094  Elf_Data *data = elf_rawdata (scn, NULL);
4095
4096  if (unlikely (data == NULL))
4097    {
4098      error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
4099	     elf_errmsg (-1));
4100      return;
4101    }
4102
4103  printf (gettext ("\
4104\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
4105	  ".debug_ranges", (uint64_t) shdr->sh_offset);
4106
4107  size_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
4108
4109  bool first = true;
4110  unsigned char *readp = data->d_buf;
4111  while (readp < (unsigned char *) data->d_buf + data->d_size)
4112    {
4113      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
4114
4115      if (unlikely (data->d_size - offset < address_size * 2))
4116	{
4117	  printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
4118	  break;
4119	}
4120
4121      Dwarf_Addr begin;
4122      Dwarf_Addr end;
4123      if (address_size == 8)
4124	{
4125	  begin = read_8ubyte_unaligned_inc (dbg, readp);
4126	  end = read_8ubyte_unaligned_inc (dbg, readp);
4127	}
4128      else
4129	{
4130	  begin = read_4ubyte_unaligned_inc (dbg, readp);
4131	  end = read_4ubyte_unaligned_inc (dbg, readp);
4132	  if (begin == (Dwarf_Addr) (uint32_t) -1)
4133	    begin = (Dwarf_Addr) -1l;
4134	}
4135
4136      if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
4137	{
4138	  char *b = format_dwarf_addr (dwflmod, address_size, end);
4139	  printf (gettext (" [%6tx]  base address %s\n"), offset, b);
4140	  free (b);
4141	}
4142      else if (begin == 0 && end == 0) /* End of list entry.  */
4143	first = true;
4144      else
4145	{
4146	  char *b = format_dwarf_addr (dwflmod, address_size, begin);
4147	  char *e = format_dwarf_addr (dwflmod, address_size, end);
4148	  /* We have an address range entry.  */
4149	  if (first)		/* First address range entry in a list.  */
4150	    printf (gettext (" [%6tx]  %s..%s\n"), offset, b, e);
4151	  else
4152	    printf (gettext ("           %s..%s\n"), b, e);
4153	  free (b);
4154	  free (e);
4155
4156	  first = false;
4157	}
4158    }
4159}
4160
4161
4162static void
4163print_debug_frame_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
4164			   Ebl *ebl __attribute__ ((unused)),
4165			   GElf_Ehdr *ehdr __attribute__ ((unused)),
4166			   Elf_Scn *scn __attribute__ ((unused)),
4167			   GElf_Shdr *shdr __attribute__ ((unused)),
4168			   Dwarf *dbg __attribute__ ((unused)))
4169{
4170}
4171
4172
4173struct attrcb_args
4174{
4175  Dwfl_Module *dwflmod;
4176  Dwarf *dbg;
4177  int level;
4178  unsigned int addrsize;
4179  Dwarf_Off cu_offset;
4180};
4181
4182
4183static int
4184attr_callback (Dwarf_Attribute *attrp, void *arg)
4185{
4186  struct attrcb_args *cbargs = (struct attrcb_args *) arg;
4187  const int level = cbargs->level;
4188
4189  unsigned int attr = dwarf_whatattr (attrp);
4190  if (unlikely (attr == 0))
4191    {
4192      error (0, 0, gettext ("cannot get attribute code: %s"),
4193	     dwarf_errmsg (-1));
4194      return DWARF_CB_ABORT;
4195    }
4196
4197  unsigned int form = dwarf_whatform (attrp);
4198  if (unlikely (form == 0))
4199    {
4200      error (0, 0, gettext ("cannot get attribute form: %s"),
4201	     dwarf_errmsg (-1));
4202      return DWARF_CB_ABORT;
4203    }
4204
4205  switch (form)
4206    {
4207    case DW_FORM_addr:
4208      {
4209	Dwarf_Addr addr;
4210	if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
4211	  {
4212	  attrval_out:
4213	    error (0, 0, gettext ("cannot get attribute value: %s"),
4214		   dwarf_errmsg (-1));
4215	    return DWARF_CB_ABORT;
4216	  }
4217	char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr);
4218	printf ("           %*s%-20s %s\n",
4219		(int) (level * 2), "", dwarf_attr_string (attr), a);
4220	free (a);
4221      }
4222      break;
4223
4224    case DW_FORM_indirect:
4225    case DW_FORM_strp:
4226    case DW_FORM_string:;
4227      const char *str = dwarf_formstring (attrp);
4228      if (unlikely (str == NULL))
4229	goto attrval_out;
4230      printf ("           %*s%-20s \"%s\"\n",
4231	      (int) (level * 2), "", dwarf_attr_string (attr), str);
4232      break;
4233
4234    case DW_FORM_ref_addr:
4235    case DW_FORM_ref_udata:
4236    case DW_FORM_ref8:
4237    case DW_FORM_ref4:
4238    case DW_FORM_ref2:
4239    case DW_FORM_ref1:;
4240      Dwarf_Die ref;
4241      if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
4242	goto attrval_out;
4243
4244      printf ("           %*s%-20s [%6" PRIxMAX "]\n",
4245	      (int) (level * 2), "", dwarf_attr_string (attr),
4246	      (uintmax_t) dwarf_dieoffset (&ref));
4247      break;
4248
4249    case DW_FORM_udata:
4250    case DW_FORM_sdata:
4251    case DW_FORM_data8:
4252    case DW_FORM_data4:
4253    case DW_FORM_data2:
4254    case DW_FORM_data1:;
4255      Dwarf_Word num;
4256      if (unlikely (dwarf_formudata (attrp, &num) != 0))
4257	goto attrval_out;
4258
4259      const char *valuestr = NULL;
4260      switch (attr)
4261	{
4262	case DW_AT_location:
4263	case DW_AT_data_location:
4264	case DW_AT_data_member_location:
4265	case DW_AT_vtable_elem_location:
4266	case DW_AT_string_length:
4267	case DW_AT_use_location:
4268	case DW_AT_frame_base:
4269	case DW_AT_return_addr:
4270	case DW_AT_static_link:
4271	  printf ("           %*s%-20s location list [%6" PRIxMAX "]\n",
4272		  (int) (level * 2), "", dwarf_attr_string (attr),
4273		  (uintmax_t) num);
4274	  return DWARF_CB_OK;
4275
4276	case DW_AT_ranges:
4277	  printf ("           %*s%-20s range list [%6" PRIxMAX "]\n",
4278		  (int) (level * 2), "", dwarf_attr_string (attr),
4279		  (uintmax_t) num);
4280	  return DWARF_CB_OK;
4281
4282	case DW_AT_language:
4283	  valuestr = dwarf_lang_string (num);
4284	  break;
4285	case DW_AT_encoding:
4286	  valuestr = dwarf_encoding_string (num);
4287	  break;
4288	case DW_AT_accessibility:
4289	  valuestr = dwarf_access_string (num);
4290	  break;
4291	case DW_AT_visibility:
4292	  valuestr = dwarf_visibility_string (num);
4293	  break;
4294	case DW_AT_virtuality:
4295	  valuestr = dwarf_virtuality_string (num);
4296	  break;
4297	case DW_AT_identifier_case:
4298	  valuestr = dwarf_identifier_case_string (num);
4299	  break;
4300	case DW_AT_calling_convention:
4301	  valuestr = dwarf_calling_convention_string (num);
4302	  break;
4303	case DW_AT_inline:
4304	  valuestr = dwarf_inline_string (num);
4305	  break;
4306	case DW_AT_ordering:
4307	  valuestr = dwarf_ordering_string (num);
4308	  break;
4309	case DW_AT_discr_list:
4310	  valuestr = dwarf_discr_list_string (num);
4311	  break;
4312	default:
4313	  /* Nothing.  */
4314	  break;
4315	}
4316
4317      if (valuestr == NULL)
4318	printf ("           %*s%-20s %" PRIuMAX "\n",
4319		(int) (level * 2), "", dwarf_attr_string (attr),
4320		(uintmax_t) num);
4321      else
4322	printf ("           %*s%-20s %s (%" PRIuMAX ")\n",
4323		(int) (level * 2), "", dwarf_attr_string (attr),
4324		valuestr, (uintmax_t) num);
4325      break;
4326
4327    case DW_FORM_flag:;
4328      bool flag;
4329      if (unlikely (dwarf_formflag (attrp, &flag) != 0))
4330	goto attrval_out;
4331
4332      printf ("           %*s%-20s %s\n",
4333	      (int) (level * 2), "", dwarf_attr_string (attr),
4334	      nl_langinfo (flag ? YESSTR : NOSTR));
4335      break;
4336
4337    case DW_FORM_block4:
4338    case DW_FORM_block2:
4339    case DW_FORM_block1:
4340    case DW_FORM_block:;
4341      Dwarf_Block block;
4342      if (unlikely (dwarf_formblock (attrp, &block) != 0))
4343	goto attrval_out;
4344
4345      printf ("           %*s%-20s %" PRIxMAX " byte block\n",
4346	      (int) (level * 2), "", dwarf_attr_string (attr),
4347	      (uintmax_t) block.length);
4348
4349      switch (attr)
4350	{
4351	case DW_AT_location:
4352	case DW_AT_data_location:
4353	case DW_AT_data_member_location:
4354	case DW_AT_vtable_elem_location:
4355	case DW_AT_string_length:
4356	case DW_AT_use_location:
4357	case DW_AT_frame_base:
4358	case DW_AT_return_addr:
4359	case DW_AT_static_link:
4360	case DW_AT_allocated:
4361	case DW_AT_associated:
4362	case DW_AT_bit_size:
4363	case DW_AT_bit_offset:
4364	case DW_AT_bit_stride:
4365	case DW_AT_byte_size:
4366	case DW_AT_byte_stride:
4367	case DW_AT_count:
4368	case DW_AT_lower_bound:
4369	case DW_AT_upper_bound:
4370	  print_ops (cbargs->dwflmod, cbargs->dbg,
4371		     12 + level * 2, 12 + level * 2,
4372		     cbargs->addrsize, block.length, block.data);
4373	  break;
4374	}
4375      break;
4376
4377    default:
4378      printf ("           %*s%-20s [form: %d] ???\n",
4379	      (int) (level * 2), "", dwarf_attr_string (attr),
4380	      (int) form);
4381      break;
4382    }
4383
4384  return DWARF_CB_OK;
4385}
4386
4387
4388static void
4389print_debug_info_section (Dwfl_Module *dwflmod,
4390			  Ebl *ebl __attribute__ ((unused)),
4391			  GElf_Ehdr *ehdr __attribute__ ((unused)),
4392			  Elf_Scn *scn __attribute__ ((unused)),
4393			  GElf_Shdr *shdr, Dwarf *dbg)
4394{
4395  printf (gettext ("\
4396\nDWARF section '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
4397	  ".debug_info", (uint64_t) shdr->sh_offset);
4398
4399  /* If the section is empty we don't have to do anything.  */
4400  if (shdr->sh_size == 0)
4401    return;
4402
4403  int maxdies = 20;
4404  Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
4405
4406  Dwarf_Off offset = 0;
4407
4408  /* New compilation unit.  */
4409  size_t cuhl;
4410  //Dwarf_Half version;
4411  Dwarf_Off abbroffset;
4412  uint8_t addrsize;
4413  uint8_t offsize;
4414  Dwarf_Off nextcu;
4415 next_cu:
4416  if (dwarf_nextcu (dbg, offset, &nextcu, &cuhl, &abbroffset, &addrsize,
4417		    &offsize) != 0)
4418    goto do_return;
4419
4420  printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
4421		   " Version: %" PRIu16 ", Abbreviation section offset: %"
4422		   PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8 "\n"),
4423	  (uint64_t) offset, /*version*/2, abbroffset, addrsize, offsize);
4424
4425
4426  struct attrcb_args args;
4427  args.dwflmod = dwflmod;
4428  args.dbg = dbg;
4429  args.addrsize = addrsize;
4430  args.cu_offset = offset;
4431
4432  offset += cuhl;
4433
4434  int level = 0;
4435
4436  if (unlikely (dwarf_offdie (dbg, offset, &dies[level]) == NULL))
4437    {
4438      error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
4439			    " in section '%s': %s"),
4440	     (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
4441      goto do_return;
4442    }
4443
4444  do
4445    {
4446      offset = dwarf_dieoffset (&dies[level]);
4447      if (unlikely (offset == ~0ul))
4448	{
4449	  error (0, 0, gettext ("cannot get DIE offset: %s"),
4450		 dwarf_errmsg (-1));
4451	  goto do_return;
4452	}
4453
4454      int tag = dwarf_tag (&dies[level]);
4455      if (unlikely (tag == DW_TAG_invalid))
4456	{
4457	  error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
4458				" in section '%s': %s"),
4459		 (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
4460	  goto do_return;
4461	}
4462
4463      printf (" [%6" PRIx64 "]  %*s%s\n",
4464	      (uint64_t) offset, (int) (level * 2), "",
4465	      dwarf_tag_string (tag));
4466
4467      /* Print the attribute values.  */
4468      args.level = level;
4469      (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
4470
4471      /* Make room for the next level's DIE.  */
4472      if (level + 1 == maxdies)
4473	dies = (Dwarf_Die *) xrealloc (dies,
4474				       (maxdies += 10)
4475				       * sizeof (Dwarf_Die));
4476
4477      int res = dwarf_child (&dies[level], &dies[level + 1]);
4478      if (res > 0)
4479	{
4480	  while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
4481	    if (level-- == 0)
4482	      break;
4483
4484	  if (unlikely (res == -1))
4485	    {
4486	      error (0, 0, gettext ("cannot get next DIE: %s\n"),
4487		     dwarf_errmsg (-1));
4488	      goto do_return;
4489	    }
4490	}
4491      else if (unlikely (res < 0))
4492	{
4493	  error (0, 0, gettext ("cannot get next DIE: %s"),
4494		 dwarf_errmsg (-1));
4495	  goto do_return;
4496	}
4497      else
4498	++level;
4499    }
4500  while (level >= 0);
4501
4502  offset = nextcu;
4503  if (offset != 0)
4504     goto next_cu;
4505
4506 do_return:
4507  free (dies);
4508}
4509
4510
4511static void
4512print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
4513			  GElf_Ehdr *ehdr __attribute__ ((unused)),
4514			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
4515{
4516  printf (gettext ("\
4517\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
4518	  ".debug_line", (uint64_t) shdr->sh_offset);
4519
4520  if (shdr->sh_size == 0)
4521    return;
4522
4523  /* There is no functionality in libdw to read the information in the
4524     way it is represented here.  Hardcode the decoder.  */
4525  Elf_Data *data = elf_getdata (scn, NULL);
4526  if (unlikely (data == NULL || data->d_buf == NULL))
4527    {
4528      error (0, 0, gettext ("cannot get line data section data: %s"),
4529	     elf_errmsg (-1));
4530      return;
4531    }
4532
4533  const unsigned char *linep = (const unsigned char *) data->d_buf;
4534  const unsigned char *lineendp;
4535
4536  while (linep
4537	 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
4538    {
4539      size_t start_offset = linep - (const unsigned char *) data->d_buf;
4540
4541      printf (gettext ("\nTable at offset %Zu:\n"), start_offset);
4542
4543      Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
4544      unsigned int length = 4;
4545      if (unlikely (unit_length == 0xffffffff))
4546	{
4547	  if (unlikely (linep + 8 > lineendp))
4548	    {
4549	    invalid_data:
4550	      error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
4551		     elf_ndxscn (scn), ".debug_line");
4552	      return;
4553	    }
4554	  unit_length = read_8ubyte_unaligned_inc (dbg, linep);
4555	  length = 8;
4556	}
4557
4558      /* Check whether we have enough room in the section.  */
4559      if (unit_length < 2 + length + 5 * 1
4560	  || unlikely (linep + unit_length > lineendp))
4561	goto invalid_data;
4562      lineendp = linep + unit_length;
4563
4564      /* The next element of the header is the version identifier.  */
4565      uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
4566
4567      /* Next comes the header length.  */
4568      Dwarf_Word header_length;
4569      if (length == 4)
4570	header_length = read_4ubyte_unaligned_inc (dbg, linep);
4571      else
4572	header_length = read_8ubyte_unaligned_inc (dbg, linep);
4573      //const unsigned char *header_start = linep;
4574
4575      /* Next the minimum instruction length.  */
4576      uint_fast8_t minimum_instr_len = *linep++;
4577
4578        /* Then the flag determining the default value of the is_stmt
4579	   register.  */
4580      uint_fast8_t default_is_stmt = *linep++;
4581
4582      /* Now the line base.  */
4583      int_fast8_t line_base = *((const int_fast8_t *) linep);
4584      ++linep;
4585
4586      /* And the line range.  */
4587      uint_fast8_t line_range = *linep++;
4588
4589      /* The opcode base.  */
4590      uint_fast8_t opcode_base = *linep++;
4591
4592      /* Print what we got so far.  */
4593      printf (gettext ("\n"
4594		       " Length:                     %" PRIu64 "\n"
4595		       " DWARF version:              %" PRIuFAST16 "\n"
4596		       " Prologue length:            %" PRIu64 "\n"
4597		       " Minimum instruction length: %" PRIuFAST8 "\n"
4598		       " Initial value if '%s': %" PRIuFAST8 "\n"
4599		       " Line base:                  %" PRIdFAST8 "\n"
4600		       " Line range:                 %" PRIuFAST8 "\n"
4601		       " Opcode base:                %" PRIuFAST8 "\n"
4602		       "\n"
4603		       "Opcodes:\n"),
4604	      (uint64_t) unit_length, version, (uint64_t) header_length,
4605	      minimum_instr_len, "is_stmt", default_is_stmt, line_base,
4606	      line_range, opcode_base);
4607
4608      if (unlikely (linep + opcode_base - 1 >= lineendp))
4609	{
4610	invalid_unit:
4611	  error (0, 0,
4612		 gettext ("invalid data at offset %tu in section [%zu] '%s'"),
4613		 linep - (const unsigned char *) data->d_buf,
4614		 elf_ndxscn (scn), ".debug_line");
4615	  linep = lineendp;
4616	  continue;
4617	}
4618      int opcode_base_l10 = 1;
4619      unsigned int tmp = opcode_base;
4620      while (tmp > 10)
4621	{
4622	  tmp /= 10;
4623	  ++opcode_base_l10;
4624	}
4625      const uint8_t *standard_opcode_lengths = linep - 1;
4626      for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
4627	printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
4628			  "  [%*" PRIuFAST8 "]  %hhu arguments\n",
4629			  (int) linep[cnt - 1]),
4630		opcode_base_l10, cnt, linep[cnt - 1]);
4631      linep += opcode_base - 1;
4632      if (unlikely (linep >= lineendp))
4633	goto invalid_unit;
4634
4635      puts (gettext ("\nDirectory table:"));
4636      while (*linep != 0)
4637	{
4638	  unsigned char *endp = memchr (linep, '\0', lineendp - linep);
4639	  if (unlikely (endp == NULL))
4640	    goto invalid_unit;
4641
4642	  printf (" %s\n", (char *) linep);
4643
4644	  linep = endp + 1;
4645	}
4646      /* Skip the final NUL byte.  */
4647      ++linep;
4648
4649      if (unlikely (linep >= lineendp))
4650	goto invalid_unit;
4651      puts (gettext ("\nFile name table:\n"
4652		     " Entry Dir   Time      Size      Name"));
4653      for (unsigned int cnt = 1; *linep != 0; ++cnt)
4654	{
4655	  /* First comes the file name.  */
4656	  char *fname = (char *) linep;
4657	  unsigned char *endp = memchr (fname, '\0', lineendp - linep);
4658	  if (unlikely (endp == NULL))
4659	    goto invalid_unit;
4660	  linep = endp + 1;
4661
4662	  /* Then the index.  */
4663	  unsigned int diridx;
4664	  get_uleb128 (diridx, linep);
4665
4666	  /* Next comes the modification time.  */
4667	  unsigned int mtime;
4668	  get_uleb128 (mtime, linep);
4669
4670	  /* Finally the length of the file.  */
4671	  unsigned int fsize;
4672	  get_uleb128 (fsize, linep);
4673
4674	  printf (" %-5u %-5u %-9u %-9u %s\n",
4675		  cnt, diridx, mtime, fsize, fname);
4676	}
4677      /* Skip the final NUL byte.  */
4678      ++linep;
4679
4680      puts (gettext ("\nLine number statements:"));
4681      Dwarf_Word address = 0;
4682      size_t line = 1;
4683      uint_fast8_t is_stmt = default_is_stmt;
4684
4685      /* Default address value, in case we do not find the CU.  */
4686      size_t address_size
4687	= elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
4688
4689      /* Determine the CU this block is for.  */
4690      Dwarf_Off cuoffset;
4691      Dwarf_Off ncuoffset = 0;
4692      size_t hsize;
4693      while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
4694			   NULL, NULL, NULL) == 0)
4695	{
4696	  Dwarf_Die cudie;
4697	  if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
4698	    continue;
4699	  Dwarf_Attribute stmt_list;
4700	  if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
4701	    continue;
4702	  Dwarf_Word lineoff;
4703	  if (dwarf_formudata (&stmt_list, &lineoff) != 0)
4704	    continue;
4705	  if (lineoff == start_offset)
4706	    {
4707	      /* Found the CU.  */
4708	      address_size = cudie.cu->address_size;
4709	      break;
4710	    }
4711	}
4712
4713      while (linep < lineendp)
4714	{
4715	  unsigned int u128;
4716	  int s128;
4717
4718	  /* Read the opcode.  */
4719	  unsigned int opcode = *linep++;
4720
4721	  /* Is this a special opcode?  */
4722	  if (likely (opcode >= opcode_base))
4723	    {
4724	      /* Yes.  Handling this is quite easy since the opcode value
4725		 is computed with
4726
4727		 opcode = (desired line increment - line_base)
4728		           + (line_range * address advance) + opcode_base
4729	      */
4730	      int line_increment = (line_base
4731				    + (opcode - opcode_base) % line_range);
4732	      unsigned int address_increment = (minimum_instr_len
4733						* ((opcode - opcode_base)
4734						   / line_range));
4735
4736	      /* Perform the increments.  */
4737	      line += line_increment;
4738	      address += address_increment;
4739
4740	      char *a = format_dwarf_addr (dwflmod, 0, address);
4741	      printf (gettext ("\
4742 special opcode %u: address+%u = %s, line%+d = %zu\n"),
4743		      opcode, address_increment, a, line_increment, line);
4744	      free (a);
4745	    }
4746	  else if (opcode == 0)
4747	    {
4748	      /* This an extended opcode.  */
4749	      if (unlikely (linep + 2 > lineendp))
4750		goto invalid_unit;
4751
4752	      /* The length.  */
4753	      unsigned int len = *linep++;
4754
4755	      if (unlikely (linep + len > lineendp))
4756		goto invalid_unit;
4757
4758	      /* The sub-opcode.  */
4759	      opcode = *linep++;
4760
4761	      printf (gettext (" extended opcode %u: "), opcode);
4762
4763	      switch (opcode)
4764		{
4765		case DW_LNE_end_sequence:
4766		  puts (gettext ("end of sequence"));
4767
4768		  /* Reset the registers we care about.  */
4769		  address = 0;
4770		  line = 1;
4771		  is_stmt = default_is_stmt;
4772		  break;
4773
4774		case DW_LNE_set_address:
4775		  if (address_size == 4)
4776		    address = read_4ubyte_unaligned_inc (dbg, linep);
4777		  else
4778		    address = read_8ubyte_unaligned_inc (dbg, linep);
4779		  {
4780		    char *a = format_dwarf_addr (dwflmod, 0, address);
4781		    printf (gettext ("set address to %s\n"), a);
4782		    free (a);
4783		  }
4784		  break;
4785
4786		case DW_LNE_define_file:
4787		  {
4788		    char *fname = (char *) linep;
4789		    unsigned char *endp = memchr (linep, '\0',
4790						  lineendp - linep);
4791		    if (unlikely (endp == NULL))
4792		      goto invalid_unit;
4793		    linep = endp + 1;
4794
4795		    unsigned int diridx;
4796		    get_uleb128 (diridx, linep);
4797		    Dwarf_Word mtime;
4798		    get_uleb128 (mtime, linep);
4799		    Dwarf_Word filelength;
4800		    get_uleb128 (filelength, linep);
4801
4802		    printf (gettext ("\
4803define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
4804			    diridx, (uint64_t) mtime, (uint64_t) filelength,
4805			    fname);
4806		  }
4807		  break;
4808
4809		default:
4810		  /* Unknown, ignore it.  */
4811		  puts (gettext ("unknown opcode"));
4812		  linep += len - 1;
4813		  break;
4814		}
4815	    }
4816	  else if (opcode <= DW_LNS_set_epilogue_begin)
4817	    {
4818	      /* This is a known standard opcode.  */
4819	      switch (opcode)
4820		{
4821		case DW_LNS_copy:
4822		  /* Takes no argument.  */
4823		  puts (gettext (" copy"));
4824		  break;
4825
4826		case DW_LNS_advance_pc:
4827		  /* Takes one uleb128 parameter which is added to the
4828		     address.  */
4829		  get_uleb128 (u128, linep);
4830		  address += minimum_instr_len * u128;
4831		  {
4832		    char *a = format_dwarf_addr (dwflmod, 0, address);
4833		    printf (gettext ("advance address by %u to %s\n"),
4834			    u128, a);
4835		    free (a);
4836		  }
4837		  break;
4838
4839		case DW_LNS_advance_line:
4840		  /* Takes one sleb128 parameter which is added to the
4841		     line.  */
4842		  get_sleb128 (s128, linep);
4843		  line += s128;
4844		  printf (gettext ("\
4845 advance line by constant %d to %" PRId64 "\n"),
4846			  s128, (int64_t) line);
4847		  break;
4848
4849		case DW_LNS_set_file:
4850		  /* Takes one uleb128 parameter which is stored in file.  */
4851		  get_uleb128 (u128, linep);
4852		  printf (gettext (" set file to %" PRIu64 "\n"),
4853			  (uint64_t) u128);
4854		  break;
4855
4856		case DW_LNS_set_column:
4857		  /* Takes one uleb128 parameter which is stored in column.  */
4858		  if (unlikely (standard_opcode_lengths[opcode] != 1))
4859		    goto invalid_unit;
4860
4861		  get_uleb128 (u128, linep);
4862		  printf (gettext (" set column to %" PRIu64 "\n"),
4863			  (uint64_t) u128);
4864		  break;
4865
4866		case DW_LNS_negate_stmt:
4867		  /* Takes no argument.  */
4868		  is_stmt = 1 - is_stmt;
4869		  printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
4870			  "is_stmt", is_stmt);
4871		  break;
4872
4873		case DW_LNS_set_basic_block:
4874		  /* Takes no argument.  */
4875		  puts (gettext (" set basic block flag"));
4876		  break;
4877
4878		case DW_LNS_const_add_pc:
4879		  /* Takes no argument.  */
4880		  u128 = (minimum_instr_len
4881			  * ((255 - opcode_base) / line_range));
4882		  address += u128;
4883		  {
4884		    char *a = format_dwarf_addr (dwflmod, 0, address);
4885		    printf (gettext ("advance address by constant %u to %s\n"),
4886			    u128, a);
4887		    free (a);
4888		  }
4889		  break;
4890
4891		case DW_LNS_fixed_advance_pc:
4892		  /* Takes one 16 bit parameter which is added to the
4893		     address.  */
4894		  if (unlikely (standard_opcode_lengths[opcode] != 1))
4895		    goto invalid_unit;
4896
4897		  u128 = read_2ubyte_unaligned_inc (dbg, linep);
4898		  address += u128;
4899		  {
4900		    char *a = format_dwarf_addr (dwflmod, 0, address);
4901		    printf (gettext ("\
4902advance address by fixed value %u to %s\n"),
4903			    u128, a);
4904		    free (a);
4905		  }
4906		  break;
4907
4908		case DW_LNS_set_prologue_end:
4909		  /* Takes no argument.  */
4910		  puts (gettext (" set prologue end flag"));
4911		  break;
4912
4913		case DW_LNS_set_epilogue_begin:
4914		  /* Takes no argument.  */
4915		  puts (gettext (" set epilogue begin flag"));
4916		  break;
4917		}
4918	    }
4919	  else
4920	    {
4921	      /* This is a new opcode the generator but not we know about.
4922		 Read the parameters associated with it but then discard
4923		 everything.  Read all the parameters for this opcode.  */
4924	      printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
4925				" unknown opcode with %" PRIu8 " parameters:",
4926				standard_opcode_lengths[opcode]),
4927		      standard_opcode_lengths[opcode]);
4928	      for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
4929		{
4930		  get_uleb128 (u128, linep);
4931		  if (n != standard_opcode_lengths[opcode])
4932		    putc_unlocked (',', stdout);
4933		  printf (" %u", u128);
4934		}
4935
4936	      /* Next round, ignore this opcode.  */
4937	      continue;
4938	    }
4939	}
4940    }
4941
4942  /* There must only be one data block.  */
4943  assert (elf_getdata (scn, data) == NULL);
4944}
4945
4946
4947static void
4948print_debug_loc_section (Dwfl_Module *dwflmod,
4949			 Ebl *ebl __attribute__ ((unused)),
4950			 GElf_Ehdr *ehdr __attribute__ ((unused)),
4951			 Elf_Scn *scn __attribute__ ((unused)),
4952			 GElf_Shdr *shdr,
4953			 Dwarf *dbg __attribute__ ((unused)))
4954{
4955  Elf_Data *data = elf_rawdata (scn, NULL);
4956
4957  if (unlikely (data == NULL))
4958    {
4959      error (0, 0, gettext ("cannot get .debug_loc content: %s"),
4960	     elf_errmsg (-1));
4961      return;
4962    }
4963
4964  printf (gettext ("\
4965\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
4966	  ".debug_loc", (uint64_t) shdr->sh_offset);
4967
4968  size_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
4969
4970  bool first = true;
4971  unsigned char *readp = data->d_buf;
4972  while (readp < (unsigned char *) data->d_buf + data->d_size)
4973    {
4974      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
4975
4976      if (unlikely (data->d_size - offset < address_size * 2))
4977	{
4978	  printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
4979	  break;
4980	}
4981
4982      Dwarf_Addr begin;
4983      Dwarf_Addr end;
4984      if (address_size == 8)
4985	{
4986	  begin = read_8ubyte_unaligned_inc (dbg, readp);
4987	  end = read_8ubyte_unaligned_inc (dbg, readp);
4988	}
4989      else
4990	{
4991	  begin = read_4ubyte_unaligned_inc (dbg, readp);
4992	  end = read_4ubyte_unaligned_inc (dbg, readp);
4993	  if (begin == (Dwarf_Addr) (uint32_t) -1)
4994	    begin = (Dwarf_Addr) -1l;
4995	}
4996
4997      if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
4998	{
4999	  char *b = format_dwarf_addr (dwflmod, address_size, end);
5000	  printf (gettext (" [%6tx]  base address %s\n"), offset, b);
5001	  free (b);
5002	}
5003      else if (begin == 0 && end == 0) /* End of list entry.  */
5004	first = true;
5005      else
5006	{
5007	  /* We have a location expression entry.  */
5008	  uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
5009
5010	  char *b = format_dwarf_addr (dwflmod, address_size, begin);
5011	  char *e = format_dwarf_addr (dwflmod, address_size, end);
5012
5013	  if (first)		/* First entry in a list.  */
5014	    printf (gettext (" [%6tx]  %s..%s"), offset, b, e);
5015	  else
5016	    printf (gettext ("           %s..%s"), b, e);
5017
5018	  free (b);
5019	  free (e);
5020
5021	  print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
5022		     address_size, len, readp);
5023
5024	  first = false;
5025	  readp += len;
5026	}
5027    }
5028}
5029
5030struct mac_culist
5031{
5032  Dwarf_Die die;
5033  Dwarf_Off offset;
5034  Dwarf_Files *files;
5035  struct mac_culist *next;
5036};
5037
5038
5039static int
5040mac_compare (const void *p1, const void *p2)
5041{
5042  struct mac_culist *m1 = (struct mac_culist *) p1;
5043  struct mac_culist *m2 = (struct mac_culist *) p2;
5044
5045  if (m1->offset < m2->offset)
5046    return -1;
5047  if (m1->offset > m2->offset)
5048    return 1;
5049  return 0;
5050}
5051
5052
5053static void
5054print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
5055			     Ebl *ebl __attribute__ ((unused)),
5056			     GElf_Ehdr *ehdr __attribute__ ((unused)),
5057			     Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5058{
5059  printf (gettext ("\
5060\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
5061	  ".debug_macinfo", (uint64_t) shdr->sh_offset);
5062  putc_unlocked ('\n', stdout);
5063
5064  /* There is no function in libdw to iterate over the raw content of
5065     the section but it is easy enough to do.  */
5066  Elf_Data *data = elf_getdata (scn, NULL);
5067  if (unlikely (data == NULL || data->d_buf == NULL))
5068    {
5069      error (0, 0, gettext ("cannot get macro information section data: %s"),
5070	     elf_errmsg (-1));
5071      return;
5072    }
5073
5074  /* Get the source file information for all CUs.  */
5075  Dwarf_Off offset;
5076  Dwarf_Off ncu = 0;
5077  size_t hsize;
5078  struct mac_culist *culist = NULL;
5079  size_t nculist = 0;
5080  while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
5081    {
5082      Dwarf_Die cudie;
5083      if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
5084	continue;
5085
5086      Dwarf_Attribute attr;
5087      if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
5088	continue;
5089
5090      Dwarf_Word macoff;
5091      if (dwarf_formudata (&attr, &macoff) != 0)
5092	continue;
5093
5094      struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
5095      newp->die = cudie;
5096      newp->offset = macoff;
5097      newp->files = NULL;
5098      newp->next = culist;
5099      culist = newp;
5100      ++nculist;
5101    }
5102
5103  /* Convert the list into an array for easier consumption.  */
5104  struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
5105							 * sizeof (*cus));
5106  /* Add sentinel.  */
5107  cus[nculist].offset = data->d_size;
5108  if (nculist > 0)
5109    {
5110      for (size_t cnt = nculist - 1; culist != NULL; --cnt)
5111	{
5112	  assert (cnt < nculist);
5113	  cus[cnt] = *culist;
5114	  culist = culist->next;
5115	}
5116
5117      /* Sort the array according to the offset in the .debug_macinfo
5118	 section.  Note we keep the sentinel at the end.  */
5119      qsort (cus, nculist, sizeof (*cus), mac_compare);
5120    }
5121
5122  const unsigned char *readp = (const unsigned char *) data->d_buf;
5123  const unsigned char *readendp = readp + data->d_size;
5124  int level = 1;
5125
5126  while (readp < readendp)
5127    {
5128      unsigned int opcode = *readp++;
5129      unsigned int u128;
5130      unsigned int u128_2;
5131      const unsigned char *endp;
5132
5133      switch (opcode)
5134	{
5135	case DW_MACINFO_define:
5136	case DW_MACINFO_undef:
5137	case DW_MACINFO_vendor_ext:
5138	  /*  For the first two opcodes the parameters are
5139	        line, string
5140	      For the latter
5141	        number, string.
5142	      We can treat these cases together.  */
5143	  get_uleb128 (u128, readp);
5144
5145	  endp = memchr (readp, '\0', readendp - readp);
5146	  if (unlikely (endp == NULL))
5147	    {
5148	      printf (gettext ("\
5149%*s*** non-terminated string at end of section"),
5150		      level, "");
5151	      return;
5152	    }
5153
5154	  if (opcode == DW_MACINFO_define)
5155	    printf ("%*s#define %s, line %u\n",
5156		    level, "", (char *) readp, u128);
5157	  else if (opcode == DW_MACINFO_undef)
5158	    printf ("%*s#undef %s, line %u\n",
5159		    level, "", (char *) readp, u128);
5160	  else
5161	    printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
5162
5163	  readp = endp + 1;
5164	  break;
5165
5166	case DW_MACINFO_start_file:
5167	  /* The two parameters are line and file index, in this order.  */
5168	  get_uleb128 (u128, readp);
5169	  get_uleb128 (u128_2, readp);
5170
5171	  /* Find the CU DIE for this file.  */
5172	  size_t macoff = readp - (const unsigned char *) data->d_buf;
5173	  const char *fname = "???";
5174	  if (macoff >= cus[0].offset)
5175	    {
5176	      while (macoff >= cus[1].offset)
5177		++cus;
5178
5179	      if (cus[0].files == NULL
5180		&& dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
5181		cus[0].files = (Dwarf_Files *) -1l;
5182
5183	      if (cus[0].files != (Dwarf_Files *) -1l)
5184		fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
5185			 ?: "???");
5186	    }
5187
5188	  printf ("%*sstart_file %u, [%u] %s\n",
5189		  level, "", u128, u128_2, fname);
5190	  ++level;
5191	  break;
5192
5193	case DW_MACINFO_end_file:
5194	  --level;
5195	  printf ("%*send_file\n", level, "");
5196	  /* Nothing more to do.  */
5197	  break;
5198
5199	default:
5200	  // XXX gcc seems to generate files with a trailing zero.
5201	  if (unlikely (opcode != 0 || readp != readendp))
5202	    printf ("%*s*** invalid opcode %u\n", level, "", opcode);
5203	  break;
5204	}
5205    }
5206}
5207
5208
5209/* Callback for printing global names.  */
5210static int
5211print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
5212		void *arg)
5213{
5214  int *np = (int *) arg;
5215
5216  printf (gettext (" [%5d] DIE offset: %6" PRId64
5217		   ", CU DIE offset: %6" PRId64 ", name: %s\n"),
5218	  (*np)++, global->die_offset, global->cu_offset, global->name);
5219
5220  return 0;
5221}
5222
5223
5224/* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
5225static void
5226print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
5227			      Ebl *ebl __attribute__ ((unused)),
5228			      GElf_Ehdr *ehdr __attribute__ ((unused)),
5229			      Elf_Scn *scn __attribute__ ((unused)),
5230			      GElf_Shdr *shdr, Dwarf *dbg)
5231{
5232  printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
5233	  ".debug_pubnames", (uint64_t) shdr->sh_offset);
5234
5235  int n = 0;
5236  (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
5237}
5238
5239/* Print the content of the DWARF string section '.debug_str'.  */
5240static void
5241print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
5242			 Ebl *ebl __attribute__ ((unused)),
5243			 GElf_Ehdr *ehdr __attribute__ ((unused)),
5244			 Elf_Scn *scn __attribute__ ((unused)),
5245			 GElf_Shdr *shdr, Dwarf *dbg)
5246{
5247  /* Compute floor(log16(shdr->sh_size)).  */
5248  GElf_Addr tmp = shdr->sh_size;
5249  int digits = 1;
5250  while (tmp >= 16)
5251    {
5252      ++digits;
5253      tmp >>= 4;
5254    }
5255  digits = MAX (4, digits);
5256
5257  printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
5258		   " %*s  String\n"),
5259	  ".debug_str", (uint64_t) shdr->sh_offset,
5260	  /* TRANS: the debugstr| prefix makes the string unique.  */
5261	  digits + 2, sgettext ("debugstr|Offset"));
5262
5263  Dwarf_Off offset = 0;
5264  while (offset < shdr->sh_size)
5265    {
5266      size_t len;
5267      const char *str = dwarf_getstring (dbg, offset, &len);
5268      if (unlikely (str == NULL))
5269	{
5270	  printf (gettext (" *** error while reading strings: %s\n"),
5271		  dwarf_errmsg (-1));
5272	  break;
5273	}
5274
5275      printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
5276
5277      offset += len + 1;
5278    }
5279}
5280
5281static void
5282print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
5283{
5284  /* Before we start the real work get a debug context descriptor.  */
5285  Dwarf_Addr dwbias;
5286  Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
5287  if (dbg == NULL)
5288    {
5289      error (0, 0, gettext ("cannot get debug context descriptor: %s"),
5290	     dwfl_errmsg (-1));
5291      return;
5292    }
5293
5294  /* Get the section header string table index.  */
5295  size_t shstrndx;
5296  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
5297    error (EXIT_FAILURE, 0,
5298	   gettext ("cannot get section header string table index"));
5299
5300  /* Look through all the sections for the debugging sections to print.  */
5301  Elf_Scn *scn = NULL;
5302  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
5303    {
5304      GElf_Shdr shdr_mem;
5305      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
5306
5307      if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
5308	{
5309	  static const struct
5310	  {
5311	    const char *name;
5312	    enum section_e bitmask;
5313	    void (*fp) (Dwfl_Module *, Ebl *,
5314			GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
5315	  } debug_sections[] =
5316	    {
5317#define NEW_SECTION(name) \
5318	      { ".debug_" #name, section_##name, print_debug_##name##_section }
5319	      NEW_SECTION (abbrev),
5320	      NEW_SECTION (aranges),
5321	      NEW_SECTION (frame),
5322	      NEW_SECTION (info),
5323	      NEW_SECTION (line),
5324	      NEW_SECTION (loc),
5325	      NEW_SECTION (pubnames),
5326	      NEW_SECTION (str),
5327	      NEW_SECTION (macinfo),
5328	      NEW_SECTION (ranges),
5329	      { ".eh_frame", section_frame, print_debug_frame_section }
5330	    };
5331	  const int ndebug_sections = (sizeof (debug_sections)
5332				       / sizeof (debug_sections[0]));
5333	  const char *name = elf_strptr (ebl->elf, shstrndx,
5334					 shdr->sh_name);
5335	  int n;
5336
5337	  for (n = 0; n < ndebug_sections; ++n)
5338	    if (strcmp (name, debug_sections[n].name) == 0)
5339	      {
5340		if (print_debug_sections & debug_sections[n].bitmask)
5341		  debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
5342		break;
5343	      }
5344	}
5345    }
5346}
5347
5348
5349#define ITEM_INDENT		4
5350#define ITEM_WRAP_COLUMN	150
5351#define REGISTER_WRAP_COLUMN	75
5352
5353/* Print "NAME: FORMAT", wrapping when FORMAT_MAX chars of FORMAT would
5354   make the line exceed ITEM_WRAP_COLUMN.  Unpadded numbers look better
5355   for the core items.  But we do not want the line breaks to depend on
5356   the particular values.  */
5357static unsigned int
5358__attribute__ ((format (printf, 7, 8)))
5359print_core_item (unsigned int colno, char sep, unsigned int wrap,
5360		 size_t name_width, const char *name,
5361		 size_t format_max, const char *format, ...)
5362{
5363  size_t len = strlen (name);
5364  if (name_width < len)
5365    name_width = len;
5366
5367  size_t n = name_width + sizeof ": " - 1 + format_max;
5368
5369  if (colno == 0)
5370    {
5371      printf ("%*s", ITEM_INDENT, "");
5372      colno = ITEM_INDENT + n;
5373    }
5374  else if (colno + 2 + n < wrap)
5375    {
5376      printf ("%c ", sep);
5377      colno += 2 + n;
5378    }
5379  else
5380    {
5381      printf ("\n%*s", ITEM_INDENT, "");
5382      colno = ITEM_INDENT + n;
5383    }
5384
5385  printf ("%s: %*s", name, (int) (name_width - len), "");
5386
5387  va_list ap;
5388  va_start (ap, format);
5389  vprintf (format, ap);
5390  va_end (ap);
5391
5392  return colno;
5393}
5394
5395static const void *
5396convert (Elf *core, Elf_Type type, uint_fast16_t count,
5397	 void *value, const void *data, size_t size)
5398{
5399  Elf_Data valuedata =
5400    {
5401      .d_type = type,
5402      .d_buf = value,
5403      .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
5404      .d_version = EV_CURRENT,
5405    };
5406  Elf_Data indata =
5407    {
5408      .d_type = type,
5409      .d_buf = (void *) data,
5410      .d_size = valuedata.d_size,
5411      .d_version = EV_CURRENT,
5412    };
5413
5414  Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
5415		 ? elf32_xlatetom : elf64_xlatetom)
5416    (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
5417  if (d == NULL)
5418    error (EXIT_FAILURE, 0,
5419	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
5420
5421  return data + indata.d_size;
5422}
5423
5424typedef uint8_t GElf_Byte;
5425
5426static unsigned int
5427handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
5428		  unsigned int colno, size_t *repeated_size)
5429{
5430  uint_fast16_t count = item->count ?: 1;
5431
5432#define TYPES								      \
5433  DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8, 4);			      \
5434  DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16, 6);			      \
5435  DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32, 11);			      \
5436  DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32, 11);			      \
5437  DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64, 20);		      \
5438  DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64, 20)
5439
5440#define DO_TYPE(NAME, Name, hex, dec, max) GElf_##Name Name[count]
5441  union { TYPES; } value;
5442#undef DO_TYPE
5443
5444  void *data = &value;
5445  size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
5446  size_t convsize = size;
5447  if (repeated_size != NULL)
5448    {
5449      if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
5450	{
5451	  data = alloca (*repeated_size);
5452	  count *= *repeated_size / size;
5453	  convsize = count * size;
5454	  *repeated_size -= convsize;
5455	}
5456      else
5457	*repeated_size -= size;
5458    }
5459
5460  desc = convert (core, item->type, count, data, desc + item->offset, convsize);
5461
5462  Elf_Type type = item->type;
5463  if (type == ELF_T_ADDR)
5464    type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
5465
5466  switch (item->format)
5467    {
5468    case 'd':
5469      assert (count == 1);
5470      switch (type)
5471	{
5472#define DO_TYPE(NAME, Name, hex, dec, max)				      \
5473	  case ELF_T_##NAME:						      \
5474	    colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN,	      \
5475				     0, item->name, max, dec, value.Name[0]); \
5476	    break
5477	  TYPES;
5478#undef DO_TYPE
5479	default:
5480	  abort ();
5481	}
5482      break;
5483
5484    case 'x':
5485      assert (count == 1);
5486      switch (type)
5487	{
5488#define DO_TYPE(NAME, Name, hex, dec, max)				      \
5489	  case ELF_T_##NAME:						      \
5490	    colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN,	      \
5491				     0, item->name, max, hex, value.Name[0]); \
5492	    break
5493	  TYPES;
5494#undef DO_TYPE
5495	default:
5496	  abort ();
5497	}
5498      break;
5499
5500    case 'b':
5501    case 'B':
5502      assert (size % sizeof (unsigned int) == 0);
5503      unsigned int nbits = count * size * 8;
5504      unsigned int pop = 0;
5505      for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
5506	pop += __builtin_popcount (*i);
5507      bool negate = pop > nbits / 2;
5508      const unsigned int bias = item->format == 'b';
5509
5510      {
5511	char printed[(negate ? nbits - pop : pop) * 16];
5512	char *p = printed;
5513	*p = '\0';
5514
5515	if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
5516	  {
5517	    assert (size == sizeof (unsigned int) * 2);
5518	    for (unsigned int *i = data;
5519		 (void *) i < data + count * size; i += 2)
5520	      {
5521		unsigned int w = i[1];
5522		i[1] = i[0];
5523		i[0] = w;
5524	      }
5525	  }
5526
5527	unsigned int lastbit = 0;
5528	for (const unsigned int *i = data;
5529	     (void *) i < data + count * size; ++i)
5530	  {
5531	    unsigned int bit = ((void *) i - data) * 8;
5532	    unsigned int w = negate ? ~*i : *i;
5533	    while (w != 0)
5534	      {
5535		int n = ffs (w);
5536		w >>= n;
5537		bit += n;
5538
5539		if (lastbit + 1 != bit)
5540		  p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
5541		else if (lastbit == 0)
5542		  p += sprintf (p, "%u", bit - bias);
5543
5544		lastbit = bit;
5545	      }
5546	  }
5547	if (lastbit > 0 && lastbit + 1 != nbits)
5548	  p += sprintf (p, "-%u", nbits - bias);
5549
5550	colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
5551				 4 + nbits * 4,
5552				 negate ? "~<%s>" : "<%s>", printed);
5553      }
5554      break;
5555
5556    case 'T':
5557    case (char) ('T'|0x80):
5558      assert (count == 2);
5559      Dwarf_Word sec;
5560      Dwarf_Word usec;
5561      size_t maxfmt = 7;
5562      switch (type)
5563	{
5564#define DO_TYPE(NAME, Name, hex, dec, max)				      \
5565	  case ELF_T_##NAME:						      \
5566	    sec = value.Name[0];					      \
5567	    usec = value.Name[1];					      \
5568	    maxfmt += max;						      \
5569	    break
5570	  TYPES;
5571#undef DO_TYPE
5572	default:
5573	  abort ();
5574	}
5575      if (unlikely (item->format == (char) ('T'|0x80)))
5576	{
5577	  /* This is a hack for an ill-considered 64-bit ABI where
5578	     tv_usec is actually a 32-bit field with 32 bits of padding
5579	     rounding out struct timeval.  We've already converted it as
5580	     a 64-bit field.  For little-endian, this just means the
5581	     high half is the padding; it's presumably zero, but should
5582	     be ignored anyway.  For big-endian, it means the 32-bit
5583	     field went into the high half of USEC.  */
5584	  GElf_Ehdr ehdr_mem;
5585	  GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
5586	  if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
5587	    usec >>= 32;
5588	  else
5589	    usec &= UINT32_MAX;
5590	}
5591      colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
5592			       maxfmt, "%" PRIu64 ".%.6" PRIu64, sec, usec);
5593      break;
5594
5595    case 'c':
5596      assert (count == 1);
5597      colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
5598			       1, "%c", value.Byte[0]);
5599      break;
5600
5601    case 's':
5602      colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
5603			       count, "%.*s", (int) count, value.Byte);
5604      break;
5605
5606    default:
5607      error (0, 0, "XXX not handling format '%c' for %s",
5608	     item->format, item->name);
5609      break;
5610    }
5611
5612#undef TYPES
5613
5614  return colno;
5615}
5616
5617
5618/* Sort items by group, and by layout offset within each group.  */
5619static int
5620compare_core_items (const void *a, const void *b)
5621{
5622  const Ebl_Core_Item *const *p1 = a;
5623  const Ebl_Core_Item *const *p2 = b;
5624  const Ebl_Core_Item *item1 = *p1;
5625  const Ebl_Core_Item *item2 = *p2;
5626
5627  return ((item1->group == item2->group ? 0
5628	   : strcmp (item1->group, item2->group))
5629	  ?: (int) item1->offset - (int) item2->offset);
5630}
5631
5632/* Sort item groups by layout offset of the first item in the group.  */
5633static int
5634compare_core_item_groups (const void *a, const void *b)
5635{
5636  const Ebl_Core_Item *const *const *p1 = a;
5637  const Ebl_Core_Item *const *const *p2 = b;
5638  const Ebl_Core_Item *const *group1 = *p1;
5639  const Ebl_Core_Item *const *group2 = *p2;
5640  const Ebl_Core_Item *item1 = *group1;
5641  const Ebl_Core_Item *item2 = *group2;
5642
5643  return (int) item1->offset - (int) item2->offset;
5644}
5645
5646static unsigned int
5647handle_core_items (Elf *core, const void *desc, size_t descsz,
5648		   const Ebl_Core_Item *items, size_t nitems)
5649{
5650  if (nitems == 0)
5651    return 0;
5652
5653  /* Sort to collect the groups together.  */
5654  const Ebl_Core_Item *sorted_items[nitems];
5655  for (size_t i = 0; i < nitems; ++i)
5656    sorted_items[i] = &items[i];
5657  qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
5658
5659  /* Collect the unique groups and sort them.  */
5660  const Ebl_Core_Item **groups[nitems];
5661  groups[0] = &sorted_items[0];
5662  size_t ngroups = 1;
5663  for (size_t i = 1; i < nitems; ++i)
5664    if (sorted_items[i]->group != sorted_items[i - 1]->group
5665	&& strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
5666      groups[ngroups++] = &sorted_items[i];
5667  qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
5668
5669  /* Write out all the groups.  */
5670  unsigned int colno = 0;
5671
5672  const void *last = desc;
5673  if (nitems == 1)
5674    {
5675      size_t size = descsz;
5676      colno = handle_core_item (core, sorted_items[0], desc, colno, &size);
5677      if (size == 0)
5678	return colno;
5679      desc += descsz - size;
5680      descsz = size;
5681    }
5682
5683  do
5684    {
5685      for (size_t i = 0; i < ngroups; ++i)
5686	{
5687	  for (const Ebl_Core_Item **item = groups[i];
5688	       (item < &sorted_items[nitems]
5689		&& ((*item)->group == groups[i][0]->group
5690		    || !strcmp ((*item)->group, groups[i][0]->group)));
5691	       ++item)
5692	    colno = handle_core_item (core, *item, desc, colno, NULL);
5693
5694	  /* Force a line break at the end of the group.  */
5695	  colno = ITEM_WRAP_COLUMN;
5696	}
5697
5698      if (descsz == 0)
5699	break;
5700
5701      /* This set of items consumed a certain amount of the note's data.
5702	 If there is more data there, we have another unit of the same size.
5703	 Loop to print that out too.  */
5704      const Ebl_Core_Item *item = &items[nitems - 1];
5705      size_t eltsz = item->offset + gelf_fsize (core, item->type,
5706						item->count ?: 1, EV_CURRENT);
5707
5708      int reps = -1;
5709      do
5710	{
5711	  ++reps;
5712	  desc += eltsz;
5713	  descsz -= eltsz;
5714	}
5715      while (descsz >= eltsz && !memcmp (desc, last, eltsz));
5716
5717      if (reps == 1)
5718	{
5719	  /* For just one repeat, print it unabridged twice.  */
5720	  desc -= eltsz;
5721	  descsz += eltsz;
5722	}
5723      else if (reps > 1)
5724	printf (gettext ("\n%*s... <repeats %u more times> ..."),
5725		ITEM_INDENT, "", reps);
5726
5727      last = desc;
5728    }
5729  while (descsz > 0);
5730
5731  return colno;
5732}
5733
5734static unsigned int
5735handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
5736		      unsigned int colno)
5737{
5738  desc += regloc->offset;
5739
5740  abort ();			/* XXX */
5741  return colno;
5742}
5743
5744
5745static unsigned int
5746handle_core_register (Ebl *ebl, Elf *core, int maxregname,
5747		      const Ebl_Register_Location *regloc, const void *desc,
5748		      unsigned int colno)
5749{
5750  if (regloc->bits % 8 != 0)
5751    return handle_bit_registers (regloc, desc, colno);
5752
5753  desc += regloc->offset;
5754
5755  for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
5756    {
5757      const char *pfx;
5758      const char *set;
5759      char name[16];
5760      int bits;
5761      int type;
5762      ssize_t n = ebl_register_info (ebl, reg, name, sizeof name,
5763				     &pfx, &set, &bits, &type);
5764      if (n <= 0)
5765	error (EXIT_FAILURE, 0,
5766	       gettext ("unable to handle register number %d"),
5767	       regloc->regno);
5768
5769#define TYPES								      \
5770      BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8, 4);			      \
5771      BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16, 6);			      \
5772      BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32, 11);		      \
5773      BITS (64, XWORD, "%20" PRId64, "  0x%.16" PRIx64, 20)
5774
5775#define BITS(bits, xtype, sfmt, ufmt, max)				\
5776      uint##bits##_t b##bits; int##bits##_t b##bits##s
5777      union { TYPES; uint64_t b128[2]; } value;
5778#undef	BITS
5779
5780      switch (type)
5781	{
5782	case DW_ATE_unsigned:
5783	case DW_ATE_signed:
5784	case DW_ATE_address:
5785	  switch (bits)
5786	    {
5787#define BITS(bits, xtype, sfmt, ufmt, max)				      \
5788	    case bits:							      \
5789	      desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0);	      \
5790	      if (type == DW_ATE_signed)				      \
5791		colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,    \
5792					 maxregname, name,		      \
5793					 max, sfmt, value.b##bits##s);	      \
5794	      else							      \
5795		colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,    \
5796					 maxregname, name,		      \
5797					 max, ufmt, value.b##bits);	      \
5798	      break
5799
5800	    TYPES;
5801
5802	    case 128:
5803	      assert (type == DW_ATE_unsigned);
5804	      desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
5805	      int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
5806	      colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
5807				       maxregname, name,
5808				       34, "0x%.16" PRIx64 "%.16" PRIx64,
5809				       value.b128[!be], value.b128[be]);
5810	      break;
5811
5812	    default:
5813	      abort ();
5814#undef	BITS
5815	    }
5816	  break;
5817
5818	default:
5819	  /* Print each byte in hex, the whole thing in native byte order.  */
5820	  assert (bits % 8 == 0);
5821	  const uint8_t *bytes = desc;
5822	  desc += bits / 8;
5823	  char hex[bits / 4 + 1];
5824	  hex[bits / 4] = '\0';
5825	  int incr = 1;
5826	  if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
5827	    {
5828	      bytes += bits / 8 - 1;
5829	      incr = -1;
5830	    }
5831	  size_t idx = 0;
5832	  for (char *h = hex; bits > 0; bits -= 8, idx += incr)
5833	    {
5834	      *h++ = "0123456789abcdef"[bytes[idx] >> 4];
5835	      *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
5836	    }
5837	  colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
5838				   maxregname, name,
5839				   2 + sizeof hex - 1, "0x%s", hex);
5840	  break;
5841	}
5842      desc += regloc->pad;
5843
5844#undef TYPES
5845    }
5846
5847  return colno;
5848}
5849
5850
5851struct register_info
5852{
5853  const Ebl_Register_Location *regloc;
5854  const char *set;
5855  char name[16];
5856  Dwarf_Half regno;
5857  uint8_t bits;
5858  uint8_t type;
5859};
5860
5861static int
5862register_bitpos (const struct register_info *r)
5863{
5864  return (r->regloc->offset * 8
5865	  + ((r->regno - r->regloc->regno)
5866	     * (r->regloc->bits + r->regloc->pad * 8)));
5867}
5868
5869static int
5870compare_sets_by_info (const struct register_info *r1,
5871		      const struct register_info *r2)
5872{
5873  return ((int) r2->bits - (int) r1->bits
5874	  ?: register_bitpos (r1) - register_bitpos (r2));
5875}
5876
5877/* Sort registers by set, and by size and layout offset within each set.  */
5878static int
5879compare_registers (const void *a, const void *b)
5880{
5881  const struct register_info *r1 = a;
5882  const struct register_info *r2 = b;
5883
5884  /* Unused elements sort last.  */
5885  if (r1->regloc == NULL)
5886    return r2->regloc == NULL ? 0 : 1;
5887  if (r2->regloc == NULL)
5888    return -1;
5889
5890  return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
5891	  ?: compare_sets_by_info (r1, r2));
5892}
5893
5894/* Sort register sets by layout offset of the first register in the set.  */
5895static int
5896compare_register_sets (const void *a, const void *b)
5897{
5898  const struct register_info *const *p1 = a;
5899  const struct register_info *const *p2 = b;
5900  return compare_sets_by_info (*p1, *p2);
5901}
5902
5903static unsigned int
5904handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
5905		       const Ebl_Register_Location *reglocs, size_t nregloc)
5906{
5907  if (nregloc == 0)
5908    return 0;
5909
5910  ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
5911  if (maxnreg <= 0)
5912    error (EXIT_FAILURE, 0,
5913	   gettext ("cannot register info: %s"), elf_errmsg (-1));
5914
5915  struct register_info regs[maxnreg];
5916  memset (regs, 0, sizeof regs);
5917
5918  /* Sort to collect the sets together.  */
5919  int maxreg = 0;
5920  for (size_t i = 0; i < nregloc; ++i)
5921    for (int reg = reglocs[i].regno;
5922	 reg < reglocs[i].regno + reglocs[i].count;
5923	 ++reg)
5924      {
5925	assert (reg < maxnreg);
5926	if (reg > maxreg)
5927	  maxreg = reg;
5928	struct register_info *info = &regs[reg];
5929
5930	const char *pfx;
5931	int bits;
5932	int type;
5933	ssize_t n = ebl_register_info (ebl, reg, info->name, sizeof info->name,
5934				       &pfx, &info->set, &bits, &type);
5935	if (n <= 0)
5936	  error (EXIT_FAILURE, 0,
5937		 gettext ("cannot register info: %s"), elf_errmsg (-1));
5938
5939	info->regloc = &reglocs[i];
5940	info->regno = reg;
5941	info->bits = bits;
5942	info->type = type;
5943      }
5944  qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
5945
5946  /* Collect the unique sets and sort them.  */
5947  inline bool same_set (const struct register_info *a,
5948			const struct register_info *b)
5949  {
5950    return (a < &regs[maxnreg] && a->regloc != NULL
5951	    && b < &regs[maxnreg] && b->regloc != NULL
5952	    && a->bits == b->bits
5953	    && (a->set == b->set || !strcmp (a->set, b->set)));
5954  }
5955  struct register_info *sets[maxreg + 1];
5956  sets[0] = &regs[0];
5957  size_t nsets = 1;
5958  for (int i = 1; i <= maxreg; ++i)
5959    if (regs[i].regloc != NULL && !same_set (&regs[i], &regs[i - 1]))
5960      sets[nsets++] = &regs[i];
5961  qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
5962
5963  /* Write out all the sets.  */
5964  unsigned int colno = 0;
5965  for (size_t i = 0; i < nsets; ++i)
5966    {
5967      /* Find the longest name of a register in this set.  */
5968      size_t maxname = 0;
5969      const struct register_info *end;
5970      for (end = sets[i]; same_set (sets[i], end); ++end)
5971	{
5972	  size_t len = strlen (end->name);
5973	  if (len > maxname)
5974	    maxname = len;
5975	}
5976
5977      for (const struct register_info *reg = sets[i];
5978	   reg < end;
5979	   reg += reg->regloc->count ?: 1)
5980	colno = handle_core_register (ebl, core, maxname,
5981				      reg->regloc, desc, colno);
5982
5983      /* Force a line break at the end of the group.  */
5984      colno = REGISTER_WRAP_COLUMN;
5985    }
5986
5987  return colno;
5988}
5989
5990static void
5991handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
5992{
5993  Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
5994  if (data == NULL)
5995  elf_error:
5996    error (EXIT_FAILURE, 0,
5997	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
5998
5999  const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
6000  for (size_t i = 0; i < nauxv; ++i)
6001    {
6002      GElf_auxv_t av_mem;
6003      GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
6004      if (av == NULL)
6005	goto elf_error;
6006
6007      const char *name;
6008      const char *fmt;
6009      if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
6010	{
6011	  /* Unknown type.  */
6012	  if (av->a_un.a_val == 0)
6013	    printf ("    %" PRIu64 "\n", av->a_type);
6014	  else
6015	    printf ("    %" PRIu64 ": %#" PRIx64 "\n",
6016		    av->a_type, av->a_un.a_val);
6017	}
6018      else
6019	switch (fmt[0])
6020	  {
6021	  case '\0':		/* Normally zero.  */
6022	    if (av->a_un.a_val == 0)
6023	      {
6024		printf ("    %s\n", name);
6025		break;
6026	      }
6027	    /* Fall through */
6028	  case 'x':		/* hex */
6029	  case 'p':		/* address */
6030	  case 's':		/* address of string */
6031	    printf ("    %s: %#" PRIx64 "\n", name, av->a_un.a_val);
6032	    break;
6033	  case 'u':
6034	    printf ("    %s: %" PRIu64 "\n", name, av->a_un.a_val);
6035	    break;
6036	  case 'd':
6037	    printf ("    %s: %" PRId64 "\n", name, av->a_un.a_val);
6038	    break;
6039
6040	  case 'b':
6041	    printf ("    %s: %#" PRIx64 "  ", name, av->a_un.a_val);
6042	    GElf_Xword bit = 1;
6043	    const char *pfx = "<";
6044	    for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
6045	      {
6046		if (av->a_un.a_val & bit)
6047		  {
6048		    printf ("%s%s", pfx, p);
6049		    pfx = " ";
6050		  }
6051		bit <<= 1;
6052	      }
6053	    printf (">\n");
6054	    break;
6055
6056	  default:
6057	    abort ();
6058	  }
6059    }
6060}
6061
6062static void
6063handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr, const void *desc)
6064{
6065  GElf_Word regs_offset;
6066  size_t nregloc;
6067  const Ebl_Register_Location *reglocs;
6068  size_t nitems;
6069  const Ebl_Core_Item *items;
6070
6071  if (! ebl_core_note (ebl, nhdr->n_type, nhdr->n_descsz,
6072		       &regs_offset, &nregloc, &reglocs, &nitems, &items))
6073    return;
6074
6075  /* Pass 0 for DESCSZ when there are registers in the note,
6076     so that the ITEMS array does not describe the whole thing.
6077     For non-register notes, the actual descsz might be a multiple
6078     of the unit size, not just exactly the unit size.  */
6079  unsigned int colno = handle_core_items (ebl->elf, desc,
6080					  nregloc == 0 ? nhdr->n_descsz : 0,
6081					  items, nitems);
6082  if (colno != 0)
6083    putchar_unlocked ('\n');
6084
6085  colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
6086				 reglocs, nregloc);
6087  if (colno != 0)
6088    putchar_unlocked ('\n');
6089}
6090
6091static void
6092handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
6093		   GElf_Off start, Elf_Data *data)
6094{
6095  fputs_unlocked (gettext ("  Owner          Data size  Type\n"), stdout);
6096
6097  if (data == NULL)
6098    goto bad_note;
6099
6100  size_t offset = 0;
6101  GElf_Nhdr nhdr;
6102  size_t name_offset;
6103  size_t desc_offset;
6104  while (offset < data->d_size
6105	 && (offset = gelf_getnote (data, offset,
6106				    &nhdr, &name_offset, &desc_offset)) > 0)
6107    {
6108      const char *name = data->d_buf + name_offset;
6109      const char *desc = data->d_buf + desc_offset;
6110
6111      char buf[100];
6112      char buf2[100];
6113      printf (gettext ("  %-13.*s  %9" PRId32 "  %s\n"),
6114	      (int) nhdr.n_namesz, name, nhdr.n_descsz,
6115	      ehdr->e_type == ET_CORE
6116	      ? ebl_core_note_type_name (ebl, nhdr.n_type,
6117					 buf, sizeof (buf))
6118	      : ebl_object_note_type_name (ebl, nhdr.n_type,
6119					   buf2, sizeof (buf2)));
6120
6121      /* Filter out invalid entries.  */
6122      if (memchr (name, '\0', nhdr.n_namesz) != NULL
6123	  /* XXX For now help broken Linux kernels.  */
6124	  || 1)
6125	{
6126	  if (ehdr->e_type == ET_CORE)
6127	    {
6128	      if (nhdr.n_type == NT_AUXV)
6129		handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
6130				  start + desc_offset);
6131	      else
6132		handle_core_note (ebl, &nhdr, desc);
6133	    }
6134	  else
6135	    ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc);
6136	}
6137    }
6138
6139  if (offset == data->d_size)
6140    return;
6141
6142 bad_note:
6143  error (EXIT_FAILURE, 0,
6144	 gettext ("cannot get content of note section: %s"),
6145	 elf_errmsg (-1));
6146}
6147
6148static void
6149handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
6150{
6151  /* If we have section headers, just look for SHT_NOTE sections.
6152     In a debuginfo file, the program headers are not reliable.  */
6153  if (shnum != 0)
6154    {
6155      /* Get the section header string table index.  */
6156      size_t shstrndx;
6157      if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
6158	error (EXIT_FAILURE, 0,
6159	       gettext ("cannot get section header string table index"));
6160
6161      Elf_Scn *scn = NULL;
6162      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
6163	{
6164	  GElf_Shdr shdr_mem;
6165	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
6166
6167	  if (shdr == NULL || shdr->sh_type != SHT_NOTE)
6168	    /* Not what we are looking for.  */
6169	    continue;
6170
6171	  printf (gettext ("\
6172\nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
6173		  elf_ndxscn (scn),
6174		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
6175		  shdr->sh_size, shdr->sh_offset);
6176
6177	  handle_notes_data (ebl, ehdr, shdr->sh_offset,
6178			     elf_getdata (scn, NULL));
6179	}
6180      return;
6181    }
6182
6183  /* We have to look through the program header to find the note
6184     sections.  There can be more than one.  */
6185  for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt)
6186    {
6187      GElf_Phdr mem;
6188      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
6189
6190      if (phdr == NULL || phdr->p_type != PT_NOTE)
6191	/* Not what we are looking for.  */
6192	continue;
6193
6194      printf (gettext ("\
6195\nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
6196	      phdr->p_filesz, phdr->p_offset);
6197
6198      handle_notes_data (ebl, ehdr, phdr->p_offset,
6199			 elf_getdata_rawchunk (ebl->elf,
6200					       phdr->p_offset, phdr->p_filesz,
6201					       ELF_T_NHDR));
6202    }
6203}
6204
6205
6206static void
6207hex_dump (const uint8_t *data, size_t len)
6208{
6209  size_t pos = 0;
6210  while (pos < len)
6211    {
6212      printf ("  0x%08Zx ", pos);
6213
6214      const size_t chunk = MIN (len - pos, 16);
6215
6216      for (size_t i = 0; i < chunk; ++i)
6217	if (i % 4 == 3)
6218	  printf ("%02x ", data[pos + i]);
6219	else
6220	  printf ("%02x", data[pos + i]);
6221
6222      if (chunk < 16)
6223	printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
6224
6225      for (size_t i = 0; i < chunk; ++i)
6226	{
6227	  unsigned char b = data[pos + i];
6228	  printf ("%c", isprint (b) ? b : '.');
6229	}
6230
6231      putchar ('\n');
6232      pos += chunk;
6233    }
6234}
6235
6236static void
6237dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
6238{
6239  if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
6240    printf (gettext ("\nSection [%Zu] '%s' has no data to dump.\n"),
6241	    elf_ndxscn (scn), name);
6242  else
6243    {
6244      Elf_Data *data = elf_rawdata (scn, NULL);
6245      if (data == NULL)
6246	error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
6247	       elf_ndxscn (scn), name, elf_errmsg (-1));
6248      else
6249	{
6250	  printf (gettext ("\nHex dump of section [%Zu] '%s', %" PRIu64
6251			   " bytes at offset %#0" PRIx64 ":\n"),
6252		  elf_ndxscn (scn), name,
6253		  shdr->sh_size, shdr->sh_offset);
6254	  hex_dump (data->d_buf, data->d_size);
6255	}
6256    }
6257}
6258
6259static void
6260print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
6261{
6262  if (shdr->sh_size == 0)
6263    printf (gettext ("\nSection [%Zu] '%s' is empty.\n"),
6264	    elf_ndxscn (scn), name);
6265
6266  Elf_Data *data = elf_rawdata (scn, NULL);
6267  if (data == NULL)
6268    error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
6269	   elf_ndxscn (scn), name, elf_errmsg (-1));
6270  else
6271    {
6272      printf (gettext ("\nString section [%Zu] '%s' contains %" PRIu64
6273		       " bytes at offset %#0" PRIx64 ":\n"),
6274	      elf_ndxscn (scn), name,
6275	      shdr->sh_size, shdr->sh_offset);
6276
6277      const char *start = data->d_buf;
6278      const char *const limit = start + data->d_size;
6279      do
6280	{
6281	  const char *end = memchr (start, '\0', limit - start);
6282	  const size_t pos = start - (const char *) data->d_buf;
6283	  if (unlikely (end == NULL))
6284	    {
6285	      printf ("  [%6Zx]- %.*s\n",
6286		      pos, (int) (limit - start), start);
6287	      break;
6288	    }
6289	  printf ("  [%6Zx]  %s\n", pos, start);
6290	  start = end + 1;
6291	} while (start < limit);
6292    }
6293}
6294
6295static void
6296for_each_section_argument (Elf *elf, const struct section_argument *list,
6297			   void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
6298					 const char *name))
6299{
6300  /* Get the section header string table index.  */
6301  size_t shstrndx;
6302  if (elf_getshstrndx (elf, &shstrndx) < 0)
6303    error (EXIT_FAILURE, 0,
6304	   gettext ("cannot get section header string table index"));
6305
6306  for (const struct section_argument *a = list; a != NULL; a = a->next)
6307    {
6308      Elf_Scn *scn;
6309      GElf_Shdr shdr_mem;
6310      const char *name = NULL;
6311
6312      char *endp = NULL;
6313      unsigned long int shndx = strtoul (a->arg, &endp, 0);
6314      if (endp != a->arg && *endp == '\0')
6315	{
6316	  scn = elf_getscn (elf, shndx);
6317	  if (scn == NULL)
6318	    {
6319	      error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
6320	      continue;
6321	    }
6322
6323	  if (gelf_getshdr (scn, &shdr_mem) == NULL)
6324	    error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
6325		   elf_errmsg (-1));
6326	  name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
6327	}
6328      else
6329	{
6330	  /* Need to look up the section by name.  */
6331	  scn = NULL;
6332	  while ((scn = elf_nextscn (elf, scn)) != NULL)
6333	    {
6334	      if (gelf_getshdr (scn, &shdr_mem) == NULL)
6335		continue;
6336	      name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
6337	      if (name == NULL)
6338		continue;
6339	      if (!strcmp (name, a->arg))
6340		break;
6341	    }
6342
6343	  if (unlikely (scn == NULL))
6344	    {
6345	      error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
6346	      continue;
6347	    }
6348	}
6349
6350      (*dump) (scn, &shdr_mem, name);
6351    }
6352}
6353
6354static void
6355dump_data (Ebl *ebl)
6356{
6357  for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
6358}
6359
6360static void
6361dump_strings (Ebl *ebl)
6362{
6363  for_each_section_argument (ebl->elf, string_sections, &print_string_section);
6364}
6365
6366static void
6367print_strings (Ebl *ebl)
6368{
6369  /* Get the section header string table index.  */
6370  size_t shstrndx;
6371  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
6372    error (EXIT_FAILURE, 0,
6373	   gettext ("cannot get section header string table index"));
6374
6375  Elf_Scn *scn;
6376  GElf_Shdr shdr_mem;
6377  const char *name;
6378  scn = NULL;
6379  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
6380    {
6381      if (gelf_getshdr (scn, &shdr_mem) == NULL)
6382	continue;
6383
6384      if (shdr_mem.sh_type != SHT_PROGBITS
6385	  || !(shdr_mem.sh_flags & SHF_STRINGS))
6386	continue;
6387
6388      name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
6389      if (name == NULL)
6390	continue;
6391
6392      print_string_section (scn, &shdr_mem, name);
6393    }
6394}
6395
6396static void
6397dump_archive_index (Elf *elf, const char *fname)
6398{
6399  size_t narsym;
6400  const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
6401  if (arsym == NULL)
6402    {
6403      int result = elf_errno ();
6404      if (unlikely (result != ELF_E_NO_INDEX))
6405	error (EXIT_FAILURE, 0,
6406	       gettext ("cannot get symbol index of archive '%s': %s"),
6407	       fname, elf_errmsg (result));
6408      else
6409	printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
6410      return;
6411    }
6412
6413  printf (gettext ("\nIndex of archive '%s' has %Zu entries:\n"),
6414	  fname, narsym);
6415
6416  size_t as_off = 0;
6417  for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
6418    {
6419      if (s->as_off != as_off)
6420	{
6421	  as_off = s->as_off;
6422
6423	  Elf *subelf;
6424	  if (unlikely (elf_rand (elf, as_off) == 0)
6425	      || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
6426			   == NULL))
6427#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
6428	    while (1)
6429#endif
6430	      error (EXIT_FAILURE, 0,
6431		     gettext ("cannot extract member at offset %Zu in '%s': %s"),
6432		     as_off, fname, elf_errmsg (-1));
6433
6434	  const Elf_Arhdr *h = elf_getarhdr (subelf);
6435
6436	  printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
6437
6438	  elf_end (subelf);
6439	}
6440
6441      printf ("\t%s\n", s->as_name);
6442    }
6443}
6444
6445#include "debugpred.h"
6446