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