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, ehdr, scn, shdr, dbg, false);
5968}
5969
5970static void
5971print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
5972			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5973{
5974  print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
5975}
5976
5977
5978static void
5979print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
5980			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5981{
5982  printf (gettext ("\
5983\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5984	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
5985	  (uint64_t) shdr->sh_offset);
5986
5987  if (shdr->sh_size == 0)
5988    return;
5989
5990  /* There is no functionality in libdw to read the information in the
5991     way it is represented here.  Hardcode the decoder.  */
5992  Elf_Data *data = elf_getdata (scn, NULL);
5993  if (unlikely (data == NULL || data->d_buf == NULL))
5994    {
5995      error (0, 0, gettext ("cannot get line data section data: %s"),
5996	     elf_errmsg (-1));
5997      return;
5998    }
5999
6000  const unsigned char *linep = (const unsigned char *) data->d_buf;
6001  const unsigned char *lineendp;
6002
6003  while (linep
6004	 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
6005    {
6006      size_t start_offset = linep - (const unsigned char *) data->d_buf;
6007
6008      printf (gettext ("\nTable at offset %Zu:\n"), start_offset);
6009
6010      Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
6011      unsigned int length = 4;
6012      if (unlikely (unit_length == 0xffffffff))
6013	{
6014	  if (unlikely (linep + 8 > lineendp))
6015	    {
6016	    invalid_data:
6017	      error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
6018		     elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
6019	      return;
6020	    }
6021	  unit_length = read_8ubyte_unaligned_inc (dbg, linep);
6022	  length = 8;
6023	}
6024
6025      /* Check whether we have enough room in the section.  */
6026      if (unit_length < 2 + length + 5 * 1
6027	  || unlikely (linep + unit_length > lineendp))
6028	goto invalid_data;
6029      lineendp = linep + unit_length;
6030
6031      /* The next element of the header is the version identifier.  */
6032      uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
6033
6034      /* Next comes the header length.  */
6035      Dwarf_Word header_length;
6036      if (length == 4)
6037	header_length = read_4ubyte_unaligned_inc (dbg, linep);
6038      else
6039	header_length = read_8ubyte_unaligned_inc (dbg, linep);
6040      //const unsigned char *header_start = linep;
6041
6042      /* Next the minimum instruction length.  */
6043      uint_fast8_t minimum_instr_len = *linep++;
6044
6045      /* Next the maximum operations per instruction, in version 4 format.  */
6046      uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++;
6047
6048	/* Then the flag determining the default value of the is_stmt
6049	   register.  */
6050      uint_fast8_t default_is_stmt = *linep++;
6051
6052      /* Now the line base.  */
6053      int_fast8_t line_base = *((const int_fast8_t *) linep);
6054      ++linep;
6055
6056      /* And the line range.  */
6057      uint_fast8_t line_range = *linep++;
6058
6059      /* The opcode base.  */
6060      uint_fast8_t opcode_base = *linep++;
6061
6062      /* Print what we got so far.  */
6063      printf (gettext ("\n"
6064		       " Length:                     %" PRIu64 "\n"
6065		       " DWARF version:              %" PRIuFAST16 "\n"
6066		       " Prologue length:            %" PRIu64 "\n"
6067		       " Minimum instruction length: %" PRIuFAST8 "\n"
6068		       " Maximum operations per instruction: %" PRIuFAST8 "\n"
6069		       " Initial value if '%s': %" PRIuFAST8 "\n"
6070		       " Line base:                  %" PRIdFAST8 "\n"
6071		       " Line range:                 %" PRIuFAST8 "\n"
6072		       " Opcode base:                %" PRIuFAST8 "\n"
6073		       "\n"
6074		       "Opcodes:\n"),
6075	      (uint64_t) unit_length, version, (uint64_t) header_length,
6076	      minimum_instr_len, max_ops_per_instr,
6077	      "is_stmt", default_is_stmt, line_base,
6078	      line_range, opcode_base);
6079
6080      if (unlikely (linep + opcode_base - 1 >= lineendp))
6081	{
6082	invalid_unit:
6083	  error (0, 0,
6084		 gettext ("invalid data at offset %tu in section [%zu] '%s'"),
6085		 linep - (const unsigned char *) data->d_buf,
6086		 elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
6087	  linep = lineendp;
6088	  continue;
6089	}
6090      int opcode_base_l10 = 1;
6091      unsigned int tmp = opcode_base;
6092      while (tmp > 10)
6093	{
6094	  tmp /= 10;
6095	  ++opcode_base_l10;
6096	}
6097      const uint8_t *standard_opcode_lengths = linep - 1;
6098      for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
6099	printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
6100			  "  [%*" PRIuFAST8 "]  %hhu arguments\n",
6101			  (int) linep[cnt - 1]),
6102		opcode_base_l10, cnt, linep[cnt - 1]);
6103      linep += opcode_base - 1;
6104      if (unlikely (linep >= lineendp))
6105	goto invalid_unit;
6106
6107      puts (gettext ("\nDirectory table:"));
6108      while (*linep != 0)
6109	{
6110	  unsigned char *endp = memchr (linep, '\0', lineendp - linep);
6111	  if (unlikely (endp == NULL))
6112	    goto invalid_unit;
6113
6114	  printf (" %s\n", (char *) linep);
6115
6116	  linep = endp + 1;
6117	}
6118      /* Skip the final NUL byte.  */
6119      ++linep;
6120
6121      if (unlikely (linep >= lineendp))
6122	goto invalid_unit;
6123      puts (gettext ("\nFile name table:\n"
6124		     " Entry Dir   Time      Size      Name"));
6125      for (unsigned int cnt = 1; *linep != 0; ++cnt)
6126	{
6127	  /* First comes the file name.  */
6128	  char *fname = (char *) linep;
6129	  unsigned char *endp = memchr (fname, '\0', lineendp - linep);
6130	  if (unlikely (endp == NULL))
6131	    goto invalid_unit;
6132	  linep = endp + 1;
6133
6134	  /* Then the index.  */
6135	  unsigned int diridx;
6136	  get_uleb128 (diridx, linep);
6137
6138	  /* Next comes the modification time.  */
6139	  unsigned int mtime;
6140	  get_uleb128 (mtime, linep);
6141
6142	  /* Finally the length of the file.  */
6143	  unsigned int fsize;
6144	  get_uleb128 (fsize, linep);
6145
6146	  printf (" %-5u %-5u %-9u %-9u %s\n",
6147		  cnt, diridx, mtime, fsize, fname);
6148	}
6149      /* Skip the final NUL byte.  */
6150      ++linep;
6151
6152      puts (gettext ("\nLine number statements:"));
6153      Dwarf_Word address = 0;
6154      unsigned int op_index = 0;
6155      size_t line = 1;
6156      uint_fast8_t is_stmt = default_is_stmt;
6157
6158      /* Default address value, in case we do not find the CU.  */
6159      size_t address_size
6160	= elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6161
6162      /* Determine the CU this block is for.  */
6163      Dwarf_Off cuoffset;
6164      Dwarf_Off ncuoffset = 0;
6165      size_t hsize;
6166      while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
6167			   NULL, NULL, NULL) == 0)
6168	{
6169	  Dwarf_Die cudie;
6170	  if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
6171	    continue;
6172	  Dwarf_Attribute stmt_list;
6173	  if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
6174	    continue;
6175	  Dwarf_Word lineoff;
6176	  if (dwarf_formudata (&stmt_list, &lineoff) != 0)
6177	    continue;
6178	  if (lineoff == start_offset)
6179	    {
6180	      /* Found the CU.  */
6181	      address_size = cudie.cu->address_size;
6182	      break;
6183	    }
6184	}
6185
6186      /* Apply the "operation advance" from a special opcode
6187	 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
6188      unsigned int op_addr_advance;
6189      bool show_op_index;
6190      inline void advance_pc (unsigned int op_advance)
6191      {
6192	op_addr_advance = minimum_instr_len * ((op_index + op_advance)
6193					       / max_ops_per_instr);
6194	address += op_advance;
6195	show_op_index = (op_index > 0 ||
6196			 (op_index + op_advance) % max_ops_per_instr > 0);
6197	op_index = (op_index + op_advance) % max_ops_per_instr;
6198      }
6199
6200      while (linep < lineendp)
6201	{
6202	  size_t offset = linep - (const unsigned char *) data->d_buf;
6203	  unsigned int u128;
6204	  int s128;
6205
6206	  /* Read the opcode.  */
6207	  unsigned int opcode = *linep++;
6208
6209	  printf (" [%6" PRIx64 "]", (uint64_t)offset);
6210	  /* Is this a special opcode?  */
6211	  if (likely (opcode >= opcode_base))
6212	    {
6213	      /* Yes.  Handling this is quite easy since the opcode value
6214		 is computed with
6215
6216		 opcode = (desired line increment - line_base)
6217			   + (line_range * address advance) + opcode_base
6218	      */
6219	      int line_increment = (line_base
6220				    + (opcode - opcode_base) % line_range);
6221
6222	      /* Perform the increments.  */
6223	      line += line_increment;
6224	      advance_pc ((opcode - opcode_base) / line_range);
6225
6226	      char *a = format_dwarf_addr (dwflmod, 0, address);
6227	      if (show_op_index)
6228		printf (gettext ("\
6229 special opcode %u: address+%u = %s, op_index = %u, line%+d = %zu\n"),
6230			opcode, op_addr_advance, a, op_index,
6231			line_increment, line);
6232	      else
6233		printf (gettext ("\
6234 special opcode %u: address+%u = %s, line%+d = %zu\n"),
6235			opcode, op_addr_advance, a, line_increment, line);
6236	      free (a);
6237	    }
6238	  else if (opcode == 0)
6239	    {
6240	      /* This an extended opcode.  */
6241	      if (unlikely (linep + 2 > lineendp))
6242		goto invalid_unit;
6243
6244	      /* The length.  */
6245	      unsigned int len = *linep++;
6246
6247	      if (unlikely (linep + len > lineendp))
6248		goto invalid_unit;
6249
6250	      /* The sub-opcode.  */
6251	      opcode = *linep++;
6252
6253	      printf (gettext (" extended opcode %u: "), opcode);
6254
6255	      switch (opcode)
6256		{
6257		case DW_LNE_end_sequence:
6258		  puts (gettext (" end of sequence"));
6259
6260		  /* Reset the registers we care about.  */
6261		  address = 0;
6262		  op_index = 0;
6263		  line = 1;
6264		  is_stmt = default_is_stmt;
6265		  break;
6266
6267		case DW_LNE_set_address:
6268		  op_index = 0;
6269		  if (address_size == 4)
6270		    address = read_4ubyte_unaligned_inc (dbg, linep);
6271		  else
6272		    address = read_8ubyte_unaligned_inc (dbg, linep);
6273		  {
6274		    char *a = format_dwarf_addr (dwflmod, 0, address);
6275		    printf (gettext (" set address to %s\n"), a);
6276		    free (a);
6277		  }
6278		  break;
6279
6280		case DW_LNE_define_file:
6281		  {
6282		    char *fname = (char *) linep;
6283		    unsigned char *endp = memchr (linep, '\0',
6284						  lineendp - linep);
6285		    if (unlikely (endp == NULL))
6286		      goto invalid_unit;
6287		    linep = endp + 1;
6288
6289		    unsigned int diridx;
6290		    get_uleb128 (diridx, linep);
6291		    Dwarf_Word mtime;
6292		    get_uleb128 (mtime, linep);
6293		    Dwarf_Word filelength;
6294		    get_uleb128 (filelength, linep);
6295
6296		    printf (gettext ("\
6297 define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
6298			    diridx, (uint64_t) mtime, (uint64_t) filelength,
6299			    fname);
6300		  }
6301		  break;
6302
6303		case DW_LNE_set_discriminator:
6304		  /* Takes one ULEB128 parameter, the discriminator.  */
6305		  if (unlikely (standard_opcode_lengths[opcode] != 1))
6306		    goto invalid_unit;
6307
6308		  get_uleb128 (u128, linep);
6309		  printf (gettext (" set discriminator to %u\n"), u128);
6310		  break;
6311
6312		default:
6313		  /* Unknown, ignore it.  */
6314		  puts (gettext (" unknown opcode"));
6315		  linep += len - 1;
6316		  break;
6317		}
6318	    }
6319	  else if (opcode <= DW_LNS_set_isa)
6320	    {
6321	      /* This is a known standard opcode.  */
6322	      switch (opcode)
6323		{
6324		case DW_LNS_copy:
6325		  /* Takes no argument.  */
6326		  puts (gettext (" copy"));
6327		  break;
6328
6329		case DW_LNS_advance_pc:
6330		  /* Takes one uleb128 parameter which is added to the
6331		     address.  */
6332		  get_uleb128 (u128, linep);
6333		  advance_pc (u128);
6334		  {
6335		    char *a = format_dwarf_addr (dwflmod, 0, address);
6336		    if (show_op_index)
6337		      printf (gettext ("\
6338 advance address by %u to %s, op_index to %u\n"),
6339			      op_addr_advance, a, op_index);
6340		    else
6341		      printf (gettext (" advance address by %u to %s\n"),
6342			      op_addr_advance, a);
6343		    free (a);
6344		  }
6345		  break;
6346
6347		case DW_LNS_advance_line:
6348		  /* Takes one sleb128 parameter which is added to the
6349		     line.  */
6350		  get_sleb128 (s128, linep);
6351		  line += s128;
6352		  printf (gettext ("\
6353 advance line by constant %d to %" PRId64 "\n"),
6354			  s128, (int64_t) line);
6355		  break;
6356
6357		case DW_LNS_set_file:
6358		  /* Takes one uleb128 parameter which is stored in file.  */
6359		  get_uleb128 (u128, linep);
6360		  printf (gettext (" set file to %" PRIu64 "\n"),
6361			  (uint64_t) u128);
6362		  break;
6363
6364		case DW_LNS_set_column:
6365		  /* Takes one uleb128 parameter which is stored in column.  */
6366		  if (unlikely (standard_opcode_lengths[opcode] != 1))
6367		    goto invalid_unit;
6368
6369		  get_uleb128 (u128, linep);
6370		  printf (gettext (" set column to %" PRIu64 "\n"),
6371			  (uint64_t) u128);
6372		  break;
6373
6374		case DW_LNS_negate_stmt:
6375		  /* Takes no argument.  */
6376		  is_stmt = 1 - is_stmt;
6377		  printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
6378			  "is_stmt", is_stmt);
6379		  break;
6380
6381		case DW_LNS_set_basic_block:
6382		  /* Takes no argument.  */
6383		  puts (gettext (" set basic block flag"));
6384		  break;
6385
6386		case DW_LNS_const_add_pc:
6387		  /* Takes no argument.  */
6388		  advance_pc ((255 - opcode_base) / line_range);
6389		  {
6390		    char *a = format_dwarf_addr (dwflmod, 0, address);
6391		    if (show_op_index)
6392		      printf (gettext ("\
6393 advance address by constant %u to %s, op_index to %u\n"),
6394			      op_addr_advance, a, op_index);
6395		    else
6396		      printf (gettext ("\
6397 advance address by constant %u to %s\n"),
6398			      op_addr_advance, a);
6399		    free (a);
6400		  }
6401		  break;
6402
6403		case DW_LNS_fixed_advance_pc:
6404		  /* Takes one 16 bit parameter which is added to the
6405		     address.  */
6406		  if (unlikely (standard_opcode_lengths[opcode] != 1))
6407		    goto invalid_unit;
6408
6409		  u128 = read_2ubyte_unaligned_inc (dbg, linep);
6410		  address += u128;
6411		  op_index = 0;
6412		  {
6413		    char *a = format_dwarf_addr (dwflmod, 0, address);
6414		    printf (gettext ("\
6415 advance address by fixed value %u to %s\n"),
6416			    u128, a);
6417		    free (a);
6418		  }
6419		  break;
6420
6421		case DW_LNS_set_prologue_end:
6422		  /* Takes no argument.  */
6423		  puts (gettext (" set prologue end flag"));
6424		  break;
6425
6426		case DW_LNS_set_epilogue_begin:
6427		  /* Takes no argument.  */
6428		  puts (gettext (" set epilogue begin flag"));
6429		  break;
6430
6431		case DW_LNS_set_isa:
6432		  /* Takes one uleb128 parameter which is stored in isa.  */
6433		  if (unlikely (standard_opcode_lengths[opcode] != 1))
6434		    goto invalid_unit;
6435
6436		  get_uleb128 (u128, linep);
6437		  printf (gettext (" set isa to %u\n"), u128);
6438		  break;
6439		}
6440	    }
6441	  else
6442	    {
6443	      /* This is a new opcode the generator but not we know about.
6444		 Read the parameters associated with it but then discard
6445		 everything.  Read all the parameters for this opcode.  */
6446	      printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
6447				" unknown opcode with %" PRIu8 " parameters:",
6448				standard_opcode_lengths[opcode]),
6449		      standard_opcode_lengths[opcode]);
6450	      for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
6451		{
6452		  get_uleb128 (u128, linep);
6453		  if (n != standard_opcode_lengths[opcode])
6454		    putc_unlocked (',', stdout);
6455		  printf (" %u", u128);
6456		}
6457
6458	      /* Next round, ignore this opcode.  */
6459	      continue;
6460	    }
6461	}
6462    }
6463
6464  /* There must only be one data block.  */
6465  assert (elf_getdata (scn, data) == NULL);
6466}
6467
6468
6469static void
6470print_debug_loc_section (Dwfl_Module *dwflmod,
6471			 Ebl *ebl, GElf_Ehdr *ehdr,
6472			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6473{
6474  Elf_Data *data = elf_rawdata (scn, NULL);
6475
6476  if (unlikely (data == NULL))
6477    {
6478      error (0, 0, gettext ("cannot get .debug_loc content: %s"),
6479	     elf_errmsg (-1));
6480      return;
6481    }
6482
6483  printf (gettext ("\
6484\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6485	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6486	  (uint64_t) shdr->sh_offset);
6487
6488  sort_listptr (&known_loclistptr, "loclistptr");
6489  size_t listptr_idx = 0;
6490
6491  uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6492  uint_fast8_t offset_size = 4;
6493
6494  bool first = true;
6495  unsigned char *readp = data->d_buf;
6496  unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
6497  while (readp < endp)
6498    {
6499      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
6500
6501      if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx,
6502				      &address_size, &offset_size,
6503				      offset, &readp, endp))
6504	continue;
6505
6506      if (unlikely (data->d_size - offset < address_size * 2))
6507	{
6508	  printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
6509	  break;
6510	}
6511
6512      Dwarf_Addr begin;
6513      Dwarf_Addr end;
6514      if (address_size == 8)
6515	{
6516	  begin = read_8ubyte_unaligned_inc (dbg, readp);
6517	  end = read_8ubyte_unaligned_inc (dbg, readp);
6518	}
6519      else
6520	{
6521	  begin = read_4ubyte_unaligned_inc (dbg, readp);
6522	  end = read_4ubyte_unaligned_inc (dbg, readp);
6523	  if (begin == (Dwarf_Addr) (uint32_t) -1)
6524	    begin = (Dwarf_Addr) -1l;
6525	}
6526
6527      if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
6528	{
6529	  char *b = format_dwarf_addr (dwflmod, address_size, end);
6530	  printf (gettext (" [%6tx]  base address %s\n"), offset, b);
6531	  free (b);
6532	}
6533      else if (begin == 0 && end == 0) /* End of list entry.  */
6534	{
6535	  if (first)
6536	    printf (gettext (" [%6tx]  empty list\n"), offset);
6537	  first = true;
6538	}
6539      else
6540	{
6541	  /* We have a location expression entry.  */
6542	  uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
6543
6544	  char *b = format_dwarf_addr (dwflmod, address_size, begin);
6545	  char *e = format_dwarf_addr (dwflmod, address_size, end);
6546
6547	  if (first)		/* First entry in a list.  */
6548	    printf (gettext (" [%6tx]  %s..%s"), offset, b, e);
6549	  else
6550	    printf (gettext ("           %s..%s"), b, e);
6551
6552	  free (b);
6553	  free (e);
6554
6555	  if (endp - readp <= (ptrdiff_t) len)
6556	    {
6557	      fputs (gettext ("   <INVALID DATA>\n"), stdout);
6558	      break;
6559	    }
6560
6561	  print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
6562		     3 /*XXX*/, address_size, offset_size, len, readp);
6563
6564	  first = false;
6565	  readp += len;
6566	}
6567    }
6568}
6569
6570struct mac_culist
6571{
6572  Dwarf_Die die;
6573  Dwarf_Off offset;
6574  Dwarf_Files *files;
6575  struct mac_culist *next;
6576};
6577
6578
6579static int
6580mac_compare (const void *p1, const void *p2)
6581{
6582  struct mac_culist *m1 = (struct mac_culist *) p1;
6583  struct mac_culist *m2 = (struct mac_culist *) p2;
6584
6585  if (m1->offset < m2->offset)
6586    return -1;
6587  if (m1->offset > m2->offset)
6588    return 1;
6589  return 0;
6590}
6591
6592
6593static void
6594print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6595			     Ebl *ebl, GElf_Ehdr *ehdr,
6596			     Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6597{
6598  printf (gettext ("\
6599\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6600	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6601	  (uint64_t) shdr->sh_offset);
6602  putc_unlocked ('\n', stdout);
6603
6604  /* There is no function in libdw to iterate over the raw content of
6605     the section but it is easy enough to do.  */
6606  Elf_Data *data = elf_getdata (scn, NULL);
6607  if (unlikely (data == NULL || data->d_buf == NULL))
6608    {
6609      error (0, 0, gettext ("cannot get macro information section data: %s"),
6610	     elf_errmsg (-1));
6611      return;
6612    }
6613
6614  /* Get the source file information for all CUs.  */
6615  Dwarf_Off offset;
6616  Dwarf_Off ncu = 0;
6617  size_t hsize;
6618  struct mac_culist *culist = NULL;
6619  size_t nculist = 0;
6620  while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
6621    {
6622      Dwarf_Die cudie;
6623      if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
6624	continue;
6625
6626      Dwarf_Attribute attr;
6627      if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
6628	continue;
6629
6630      Dwarf_Word macoff;
6631      if (dwarf_formudata (&attr, &macoff) != 0)
6632	continue;
6633
6634      struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
6635      newp->die = cudie;
6636      newp->offset = macoff;
6637      newp->files = NULL;
6638      newp->next = culist;
6639      culist = newp;
6640      ++nculist;
6641    }
6642
6643  /* Convert the list into an array for easier consumption.  */
6644  struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
6645							 * sizeof (*cus));
6646  /* Add sentinel.  */
6647  cus[nculist].offset = data->d_size;
6648  if (nculist > 0)
6649    {
6650      for (size_t cnt = nculist - 1; culist != NULL; --cnt)
6651	{
6652	  assert (cnt < nculist);
6653	  cus[cnt] = *culist;
6654	  culist = culist->next;
6655	}
6656
6657      /* Sort the array according to the offset in the .debug_macinfo
6658	 section.  Note we keep the sentinel at the end.  */
6659      qsort (cus, nculist, sizeof (*cus), mac_compare);
6660    }
6661
6662  const unsigned char *readp = (const unsigned char *) data->d_buf;
6663  const unsigned char *readendp = readp + data->d_size;
6664  int level = 1;
6665
6666  while (readp < readendp)
6667    {
6668      unsigned int opcode = *readp++;
6669      unsigned int u128;
6670      unsigned int u128_2;
6671      const unsigned char *endp;
6672
6673      switch (opcode)
6674	{
6675	case DW_MACINFO_define:
6676	case DW_MACINFO_undef:
6677	case DW_MACINFO_vendor_ext:
6678	  /*  For the first two opcodes the parameters are
6679		line, string
6680	      For the latter
6681		number, string.
6682	      We can treat these cases together.  */
6683	  get_uleb128 (u128, readp);
6684
6685	  endp = memchr (readp, '\0', readendp - readp);
6686	  if (unlikely (endp == NULL))
6687	    {
6688	      printf (gettext ("\
6689%*s*** non-terminated string at end of section"),
6690		      level, "");
6691	      return;
6692	    }
6693
6694	  if (opcode == DW_MACINFO_define)
6695	    printf ("%*s#define %s, line %u\n",
6696		    level, "", (char *) readp, u128);
6697	  else if (opcode == DW_MACINFO_undef)
6698	    printf ("%*s#undef %s, line %u\n",
6699		    level, "", (char *) readp, u128);
6700	  else
6701	    printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
6702
6703	  readp = endp + 1;
6704	  break;
6705
6706	case DW_MACINFO_start_file:
6707	  /* The two parameters are line and file index, in this order.  */
6708	  get_uleb128 (u128, readp);
6709	  get_uleb128 (u128_2, readp);
6710
6711	  /* Find the CU DIE for this file.  */
6712	  size_t macoff = readp - (const unsigned char *) data->d_buf;
6713	  const char *fname = "???";
6714	  if (macoff >= cus[0].offset)
6715	    {
6716	      while (macoff >= cus[1].offset)
6717		++cus;
6718
6719	      if (cus[0].files == NULL
6720		&& dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
6721		cus[0].files = (Dwarf_Files *) -1l;
6722
6723	      if (cus[0].files != (Dwarf_Files *) -1l)
6724		fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
6725			 ?: "???");
6726	    }
6727
6728	  printf ("%*sstart_file %u, [%u] %s\n",
6729		  level, "", u128, u128_2, fname);
6730	  ++level;
6731	  break;
6732
6733	case DW_MACINFO_end_file:
6734	  --level;
6735	  printf ("%*send_file\n", level, "");
6736	  /* Nothing more to do.  */
6737	  break;
6738
6739	default:
6740	  // XXX gcc seems to generate files with a trailing zero.
6741	  if (unlikely (opcode != 0 || readp != readendp))
6742	    printf ("%*s*** invalid opcode %u\n", level, "", opcode);
6743	  break;
6744	}
6745    }
6746}
6747
6748
6749/* Callback for printing global names.  */
6750static int
6751print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
6752		void *arg)
6753{
6754  int *np = (int *) arg;
6755
6756  printf (gettext (" [%5d] DIE offset: %6" PRId64
6757		   ", CU DIE offset: %6" PRId64 ", name: %s\n"),
6758	  (*np)++, global->die_offset, global->cu_offset, global->name);
6759
6760  return 0;
6761}
6762
6763
6764/* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
6765static void
6766print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6767			      Ebl *ebl, GElf_Ehdr *ehdr,
6768			      Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6769{
6770  printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6771	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6772	  (uint64_t) shdr->sh_offset);
6773
6774  int n = 0;
6775  (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
6776}
6777
6778/* Print the content of the DWARF string section '.debug_str'.  */
6779static void
6780print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6781			 Ebl *ebl, GElf_Ehdr *ehdr,
6782			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6783{
6784  const size_t sh_size = dbg->sectiondata[IDX_debug_str]->d_size;
6785
6786  /* Compute floor(log16(shdr->sh_size)).  */
6787  GElf_Addr tmp = sh_size;
6788  int digits = 1;
6789  while (tmp >= 16)
6790    {
6791      ++digits;
6792      tmp >>= 4;
6793    }
6794  digits = MAX (4, digits);
6795
6796  printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
6797		   " %*s  String\n"),
6798	  elf_ndxscn (scn),
6799	  section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset,
6800	  /* TRANS: the debugstr| prefix makes the string unique.  */
6801	  digits + 2, sgettext ("debugstr|Offset"));
6802
6803  Dwarf_Off offset = 0;
6804  while (offset < sh_size)
6805    {
6806      size_t len;
6807      const char *str = dwarf_getstring (dbg, offset, &len);
6808      if (unlikely (str == NULL))
6809	{
6810	  printf (gettext (" *** error while reading strings: %s\n"),
6811		  dwarf_errmsg (-1));
6812	  break;
6813	}
6814
6815      printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
6816
6817      offset += len + 1;
6818    }
6819}
6820
6821
6822/* Print the content of the call frame search table section
6823   '.eh_frame_hdr'.  */
6824static void
6825print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6826			       Ebl *ebl __attribute__ ((unused)),
6827			       GElf_Ehdr *ehdr __attribute__ ((unused)),
6828			       Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6829{
6830  printf (gettext ("\
6831\nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
6832	  elf_ndxscn (scn));
6833
6834  Elf_Data *data = elf_rawdata (scn, NULL);
6835
6836  if (unlikely (data == NULL))
6837    {
6838      error (0, 0, gettext ("cannot get %s content: %s"),
6839	     ".eh_frame_hdr", elf_errmsg (-1));
6840      return;
6841    }
6842
6843  const unsigned char *readp = data->d_buf;
6844  const unsigned char *const dataend = ((unsigned char *) data->d_buf
6845					+ data->d_size);
6846
6847  if (unlikely (readp + 4 > dataend))
6848    {
6849    invalid_data:
6850      error (0, 0, gettext ("invalid data"));
6851      return;
6852    }
6853
6854  unsigned int version = *readp++;
6855  unsigned int eh_frame_ptr_enc = *readp++;
6856  unsigned int fde_count_enc = *readp++;
6857  unsigned int table_enc = *readp++;
6858
6859  printf (" version:          %u\n"
6860	  " eh_frame_ptr_enc: %#x ",
6861	  version, eh_frame_ptr_enc);
6862  print_encoding_base ("", eh_frame_ptr_enc);
6863  printf (" fde_count_enc:    %#x ", fde_count_enc);
6864  print_encoding_base ("", fde_count_enc);
6865  printf (" table_enc:        %#x ", table_enc);
6866  print_encoding_base ("", table_enc);
6867
6868  uint64_t eh_frame_ptr = 0;
6869  if (eh_frame_ptr_enc != DW_EH_PE_omit)
6870    {
6871      readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
6872			    dbg);
6873      if (unlikely (readp == NULL))
6874	goto invalid_data;
6875
6876      printf (" eh_frame_ptr:     %#" PRIx64, eh_frame_ptr);
6877      if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
6878	printf (" (offset: %#" PRIx64 ")",
6879		/* +4 because of the 4 byte header of the section.  */
6880		(uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
6881
6882      putchar_unlocked ('\n');
6883    }
6884
6885  uint64_t fde_count = 0;
6886  if (fde_count_enc != DW_EH_PE_omit)
6887    {
6888      readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
6889      if (unlikely (readp == NULL))
6890	goto invalid_data;
6891
6892      printf (" fde_count:        %" PRIu64 "\n", fde_count);
6893    }
6894
6895  if (fde_count == 0 || table_enc == DW_EH_PE_omit)
6896    return;
6897
6898  puts (" Table:");
6899
6900  /* Optimize for the most common case.  */
6901  if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
6902    while (fde_count > 0 && readp + 8 <= dataend)
6903      {
6904	int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
6905	uint64_t initial_offset = ((uint64_t) shdr->sh_offset
6906				   + (int64_t) initial_location);
6907	int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
6908	// XXX Possibly print symbol name or section offset for initial_offset
6909	printf ("  %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
6910		" fde=[%6" PRIx64 "]\n",
6911		initial_location, initial_offset,
6912		address, address - (eh_frame_ptr + 4));
6913      }
6914  else
6915    while (0 && readp < dataend)
6916      {
6917
6918      }
6919}
6920
6921
6922/* Print the content of the exception handling table section
6923   '.eh_frame_hdr'.  */
6924static void
6925print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
6926			     Ebl *ebl __attribute__ ((unused)),
6927			     GElf_Ehdr *ehdr __attribute__ ((unused)),
6928			     Elf_Scn *scn,
6929			     GElf_Shdr *shdr __attribute__ ((unused)),
6930			     Dwarf *dbg __attribute__ ((unused)))
6931{
6932  printf (gettext ("\
6933\nException handling table section [%2zu] '.gcc_except_table':\n"),
6934	  elf_ndxscn (scn));
6935
6936  Elf_Data *data = elf_rawdata (scn, NULL);
6937
6938  if (unlikely (data == NULL))
6939    {
6940      error (0, 0, gettext ("cannot get %s content: %s"),
6941	     ".gcc_except_table", elf_errmsg (-1));
6942      return;
6943    }
6944
6945  const unsigned char *readp = data->d_buf;
6946  const unsigned char *const dataend = readp + data->d_size;
6947
6948  if (unlikely (readp + 1 > dataend))
6949    {
6950    invalid_data:
6951      error (0, 0, gettext ("invalid data"));
6952      return;
6953    }
6954  unsigned int lpstart_encoding = *readp++;
6955  printf (gettext (" LPStart encoding:    %#x "), lpstart_encoding);
6956  print_encoding_base ("", lpstart_encoding);
6957  if (lpstart_encoding != DW_EH_PE_omit)
6958    {
6959      uint64_t lpstart;
6960      readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
6961      printf (" LPStart:             %#" PRIx64 "\n", lpstart);
6962    }
6963
6964  if (unlikely (readp + 1 > dataend))
6965    goto invalid_data;
6966  unsigned int ttype_encoding = *readp++;
6967  printf (gettext (" TType encoding:      %#x "), ttype_encoding);
6968  print_encoding_base ("", ttype_encoding);
6969  const unsigned char *ttype_base = NULL;
6970  if (ttype_encoding != DW_EH_PE_omit)
6971    {
6972      unsigned int ttype_base_offset;
6973      get_uleb128 (ttype_base_offset, readp);
6974      printf (" TType base offset:   %#x\n", ttype_base_offset);
6975      ttype_base = readp + ttype_base_offset;
6976    }
6977
6978  if (unlikely (readp + 1 > dataend))
6979    goto invalid_data;
6980  unsigned int call_site_encoding = *readp++;
6981  printf (gettext (" Call site encoding:  %#x "), call_site_encoding);
6982  print_encoding_base ("", call_site_encoding);
6983  unsigned int call_site_table_len;
6984  get_uleb128 (call_site_table_len, readp);
6985
6986  const unsigned char *const action_table = readp + call_site_table_len;
6987  if (unlikely (action_table > dataend))
6988    goto invalid_data;
6989  unsigned int u = 0;
6990  unsigned int max_action = 0;
6991  while (readp < action_table)
6992    {
6993      if (u == 0)
6994	puts (gettext ("\n Call site table:"));
6995
6996      uint64_t call_site_start;
6997      readp = read_encoded (call_site_encoding, readp, dataend,
6998			    &call_site_start, dbg);
6999      uint64_t call_site_length;
7000      readp = read_encoded (call_site_encoding, readp, dataend,
7001			    &call_site_length, dbg);
7002      uint64_t landing_pad;
7003      readp = read_encoded (call_site_encoding, readp, dataend,
7004			    &landing_pad, dbg);
7005      unsigned int action;
7006      get_uleb128 (action, readp);
7007      max_action = MAX (action, max_action);
7008      printf (gettext (" [%4u] Call site start:   %#" PRIx64 "\n"
7009		       "        Call site length:  %" PRIu64 "\n"
7010		       "        Landing pad:       %#" PRIx64 "\n"
7011		       "        Action:            %u\n"),
7012	      u++, call_site_start, call_site_length, landing_pad, action);
7013    }
7014  assert (readp == action_table);
7015
7016  unsigned int max_ar_filter = 0;
7017  if (max_action > 0)
7018    {
7019      puts ("\n Action table:");
7020
7021      const unsigned char *const action_table_end
7022	= action_table + max_action + 1;
7023
7024      u = 0;
7025      do
7026	{
7027	  int ar_filter;
7028	  get_sleb128 (ar_filter, readp);
7029	  if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
7030	    max_ar_filter = ar_filter;
7031	  int ar_disp;
7032	  get_sleb128 (ar_disp, readp);
7033
7034	  printf (" [%4u] ar_filter:  % d\n"
7035		  "        ar_disp:    % -5d",
7036		  u, ar_filter, ar_disp);
7037	  if (abs (ar_disp) & 1)
7038	    printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
7039	  else if (ar_disp != 0)
7040	    puts (" -> ???");
7041	  else
7042	    putchar_unlocked ('\n');
7043	  ++u;
7044	}
7045      while (readp < action_table_end);
7046    }
7047
7048  if (max_ar_filter > 0)
7049    {
7050      puts ("\n TType table:");
7051
7052      // XXX Not *4, size of encoding;
7053      switch (ttype_encoding & 7)
7054	{
7055	case DW_EH_PE_udata2:
7056	case DW_EH_PE_sdata2:
7057	  readp = ttype_base - max_ar_filter * 2;
7058	  break;
7059	case DW_EH_PE_udata4:
7060	case DW_EH_PE_sdata4:
7061	  readp = ttype_base - max_ar_filter * 4;
7062	  break;
7063	case DW_EH_PE_udata8:
7064	case DW_EH_PE_sdata8:
7065	  readp = ttype_base - max_ar_filter * 8;
7066	  break;
7067	default:
7068	  error (1, 0, gettext ("invalid TType encoding"));
7069	}
7070
7071      do
7072	{
7073	  uint64_t ttype;
7074	  readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
7075				dbg);
7076	  printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
7077	}
7078      while (readp < ttype_base);
7079    }
7080}
7081
7082/* Print the content of the '.gdb_index' section.
7083   http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
7084*/
7085static void
7086print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
7087			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7088{
7089  printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
7090		   " contains %" PRId64 " bytes :\n"),
7091	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7092	  (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
7093
7094  Elf_Data *data = elf_rawdata (scn, NULL);
7095
7096  if (unlikely (data == NULL))
7097    {
7098      error (0, 0, gettext ("cannot get %s content: %s"),
7099	     ".gdb_index", elf_errmsg (-1));
7100      return;
7101    }
7102
7103  // .gdb_index is always in little endian.
7104  Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
7105  dbg = &dummy_dbg;
7106
7107  const unsigned char *readp = data->d_buf;
7108  const unsigned char *const dataend = readp + data->d_size;
7109
7110  if (unlikely (readp + 4 > dataend))
7111    {
7112    invalid_data:
7113      error (0, 0, gettext ("invalid data"));
7114      return;
7115    }
7116
7117  int32_t vers = read_4ubyte_unaligned (dbg, readp);
7118  printf (gettext (" Version:         %" PRId32 "\n"), vers);
7119
7120  // The only difference between version 4 and version 5 is the
7121  // hash used for generating the table.
7122  if (vers < 4 || vers > 5)
7123    {
7124      printf (gettext ("  unknown version, cannot parse section\n"));
7125      return;
7126    }
7127
7128  readp += 4;
7129  if (unlikely (readp + 4 > dataend))
7130    goto invalid_data;
7131
7132  uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
7133  printf (gettext (" CU offset:       %#" PRIx32 "\n"), cu_off);
7134
7135  readp += 4;
7136  if (unlikely (readp + 4 > dataend))
7137    goto invalid_data;
7138
7139  uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
7140  printf (gettext (" TU offset:       %#" PRIx32 "\n"), tu_off);
7141
7142  readp += 4;
7143  if (unlikely (readp + 4 > dataend))
7144    goto invalid_data;
7145
7146  uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
7147  printf (gettext (" address offset:  %#" PRIx32 "\n"), addr_off);
7148
7149  readp += 4;
7150  if (unlikely (readp + 4 > dataend))
7151    goto invalid_data;
7152
7153  uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
7154  printf (gettext (" symbol offset:   %#" PRIx32 "\n"), sym_off);
7155
7156  readp += 4;
7157  if (unlikely (readp + 4 > dataend))
7158    goto invalid_data;
7159
7160  uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
7161  printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
7162
7163  readp = data->d_buf + cu_off;
7164
7165  const unsigned char *nextp = data->d_buf + tu_off;
7166  size_t nr = (nextp - readp) / 16;
7167
7168  printf (gettext ("\n CU list at offset %#" PRIx32
7169		   " contains %zu entries:\n"),
7170	  cu_off, nr);
7171
7172  size_t n = 0;
7173  while (readp + 16 <= dataend && n < nr)
7174    {
7175      uint64_t off = read_8ubyte_unaligned (dbg, readp);
7176      readp += 8;
7177
7178      uint64_t len = read_8ubyte_unaligned (dbg, readp);
7179      readp += 8;
7180
7181      printf (" [%4zu] start: %0#8" PRIx64
7182	      ", length: %5" PRIu64 "\n", n, off, len);
7183      n++;
7184    }
7185
7186  readp = data->d_buf + tu_off;
7187  nextp = data->d_buf + addr_off;
7188  nr = (nextp - readp) / 24;
7189
7190  printf (gettext ("\n TU list at offset %#" PRIx32
7191		   " contains %zu entries:\n"),
7192	  tu_off, nr);
7193
7194  n = 0;
7195  while (readp + 24 <= dataend && n < nr)
7196    {
7197      uint64_t off = read_8ubyte_unaligned (dbg, readp);
7198      readp += 8;
7199
7200      uint64_t type = read_8ubyte_unaligned (dbg, readp);
7201      readp += 8;
7202
7203      uint64_t sig = read_8ubyte_unaligned (dbg, readp);
7204      readp += 8;
7205
7206      printf (" [%4zu] CU offset: %5" PRId64
7207	      ", type offset: %5" PRId64
7208	      ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
7209      n++;
7210    }
7211
7212  readp = data->d_buf + addr_off;
7213  nextp = data->d_buf + sym_off;
7214  nr = (nextp - readp) / 20;
7215
7216  printf (gettext ("\n Address list at offset %#" PRIx32
7217		   " contains %zu entries:\n"),
7218	  addr_off, nr);
7219
7220  n = 0;
7221  while (readp + 20 <= dataend && n < nr)
7222    {
7223      uint64_t low = read_8ubyte_unaligned (dbg, readp);
7224      readp += 8;
7225
7226      uint64_t high = read_8ubyte_unaligned (dbg, readp);
7227      readp += 8;
7228
7229      uint32_t idx = read_4ubyte_unaligned (dbg, readp);
7230      readp += 4;
7231
7232      char *l = format_dwarf_addr (dwflmod, 8, low);
7233      char *h = format_dwarf_addr (dwflmod, 8, high - 1);
7234      printf (" [%4zu] %s..%s, CU index: %5" PRId32 "\n",
7235	      n, l, h, idx);
7236      n++;
7237    }
7238
7239  readp = data->d_buf + sym_off;
7240  nextp = data->d_buf + const_off;
7241  nr = (nextp - readp) / 8;
7242
7243  printf (gettext ("\n Symbol table at offset %#" PRIx32
7244		   " contains %zu slots:\n"),
7245	  addr_off, nr);
7246
7247  n = 0;
7248  while (readp + 8 <= dataend && n < nr)
7249    {
7250      uint32_t name = read_4ubyte_unaligned (dbg, readp);
7251      readp += 4;
7252
7253      uint32_t vector = read_4ubyte_unaligned (dbg, readp);
7254      readp += 4;
7255
7256      if (name != 0 || vector != 0)
7257	{
7258	  const unsigned char *sym = data->d_buf + const_off + name;
7259	  if (unlikely (sym > dataend))
7260	    goto invalid_data;
7261
7262	  printf (" [%4zu] symbol: %s, CUs: ", n, sym);
7263
7264	  const unsigned char *readcus = data->d_buf + const_off + vector;
7265	  if (unlikely (readcus + 8 > dataend))
7266	    goto invalid_data;
7267
7268	  uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
7269	  while (cus--)
7270	    {
7271	      uint32_t cu;
7272	      readcus += 4;
7273	      cu = read_4ubyte_unaligned (dbg, readcus);
7274	      printf ("%" PRId32 "%s", cu, ((cus > 0) ? ", " : ""));
7275	    }
7276	  printf ("\n");
7277	}
7278      n++;
7279    }
7280}
7281
7282static void
7283print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
7284{
7285  /* Before we start the real work get a debug context descriptor.  */
7286  Dwarf_Addr dwbias;
7287  Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
7288  Dwarf dummy_dbg =
7289    {
7290      .elf = ebl->elf,
7291      .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
7292    };
7293  if (dbg == NULL)
7294    {
7295      if ((print_debug_sections & ~section_exception) != 0)
7296	error (0, 0, gettext ("cannot get debug context descriptor: %s"),
7297	       dwfl_errmsg (-1));
7298      if ((print_debug_sections & section_exception) == 0)
7299	return;
7300      dbg = &dummy_dbg;
7301    }
7302
7303  /* Get the section header string table index.  */
7304  size_t shstrndx;
7305  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
7306    error (EXIT_FAILURE, 0,
7307	   gettext ("cannot get section header string table index"));
7308
7309  /* Look through all the sections for the debugging sections to print.  */
7310  Elf_Scn *scn = NULL;
7311  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
7312    {
7313      GElf_Shdr shdr_mem;
7314      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
7315
7316      if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
7317	{
7318	  static const struct
7319	  {
7320	    const char *name;
7321	    enum section_e bitmask;
7322	    void (*fp) (Dwfl_Module *, Ebl *,
7323			GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
7324	  } debug_sections[] =
7325	    {
7326#define NEW_SECTION(name) \
7327	      { ".debug_" #name, section_##name, print_debug_##name##_section }
7328	      NEW_SECTION (abbrev),
7329	      NEW_SECTION (aranges),
7330	      NEW_SECTION (frame),
7331	      NEW_SECTION (info),
7332	      NEW_SECTION (types),
7333	      NEW_SECTION (line),
7334	      NEW_SECTION (loc),
7335	      NEW_SECTION (pubnames),
7336	      NEW_SECTION (str),
7337	      NEW_SECTION (macinfo),
7338	      NEW_SECTION (ranges),
7339	      { ".eh_frame", section_frame | section_exception,
7340		print_debug_frame_section },
7341	      { ".eh_frame_hdr", section_frame | section_exception,
7342		print_debug_frame_hdr_section },
7343	      { ".gcc_except_table", section_frame | section_exception,
7344		print_debug_exception_table },
7345	      { ".gdb_index", section_gdb_index, print_gdb_index_section }
7346	    };
7347	  const int ndebug_sections = (sizeof (debug_sections)
7348				       / sizeof (debug_sections[0]));
7349	  const char *name = elf_strptr (ebl->elf, shstrndx,
7350					 shdr->sh_name);
7351	  int n;
7352
7353	  for (n = 0; n < ndebug_sections; ++n)
7354	    if (strcmp (name, debug_sections[n].name) == 0
7355#if USE_ZLIB
7356		|| (name[0] == '.' && name[1] == 'z'
7357		    && debug_sections[n].name[1] == 'd'
7358		    && strcmp (&name[2], &debug_sections[n].name[1]) == 0)
7359#endif
7360		)
7361	      {
7362		if ((print_debug_sections | implicit_debug_sections)
7363		    & debug_sections[n].bitmask)
7364		  debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
7365		break;
7366	      }
7367	}
7368    }
7369
7370  reset_listptr (&known_loclistptr);
7371  reset_listptr (&known_rangelistptr);
7372}
7373
7374
7375#define ITEM_INDENT		4
7376#define ITEM_WRAP_COLUMN	150
7377#define REGISTER_WRAP_COLUMN	75
7378
7379/* Print "NAME: FORMAT", wrapping when FORMAT_MAX chars of FORMAT would
7380   make the line exceed ITEM_WRAP_COLUMN.  Unpadded numbers look better
7381   for the core items.  But we do not want the line breaks to depend on
7382   the particular values.  */
7383static unsigned int
7384__attribute__ ((format (printf, 7, 8)))
7385print_core_item (unsigned int colno, char sep, unsigned int wrap,
7386		 size_t name_width, const char *name,
7387		 size_t format_max, const char *format, ...)
7388{
7389  size_t len = strlen (name);
7390  if (name_width < len)
7391    name_width = len;
7392
7393  size_t n = name_width + sizeof ": " - 1 + format_max;
7394
7395  if (colno == 0)
7396    {
7397      printf ("%*s", ITEM_INDENT, "");
7398      colno = ITEM_INDENT + n;
7399    }
7400  else if (colno + 2 + n < wrap)
7401    {
7402      printf ("%c ", sep);
7403      colno += 2 + n;
7404    }
7405  else
7406    {
7407      printf ("\n%*s", ITEM_INDENT, "");
7408      colno = ITEM_INDENT + n;
7409    }
7410
7411  printf ("%s: %*s", name, (int) (name_width - len), "");
7412
7413  va_list ap;
7414  va_start (ap, format);
7415  vprintf (format, ap);
7416  va_end (ap);
7417
7418  return colno;
7419}
7420
7421static const void *
7422convert (Elf *core, Elf_Type type, uint_fast16_t count,
7423	 void *value, const void *data, size_t size)
7424{
7425  Elf_Data valuedata =
7426    {
7427      .d_type = type,
7428      .d_buf = value,
7429      .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
7430      .d_version = EV_CURRENT,
7431    };
7432  Elf_Data indata =
7433    {
7434      .d_type = type,
7435      .d_buf = (void *) data,
7436      .d_size = valuedata.d_size,
7437      .d_version = EV_CURRENT,
7438    };
7439
7440  Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
7441		 ? elf32_xlatetom : elf64_xlatetom)
7442    (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
7443  if (d == NULL)
7444    error (EXIT_FAILURE, 0,
7445	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
7446
7447  return data + indata.d_size;
7448}
7449
7450typedef uint8_t GElf_Byte;
7451
7452static unsigned int
7453handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
7454		  unsigned int colno, size_t *repeated_size)
7455{
7456  uint_fast16_t count = item->count ?: 1;
7457
7458#define TYPES								      \
7459  DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8, 4);			      \
7460  DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16, 6);			      \
7461  DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32, 11);			      \
7462  DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32, 11);			      \
7463  DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64, 20);		      \
7464  DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64, 20)
7465
7466#define DO_TYPE(NAME, Name, hex, dec, max) GElf_##Name Name[count]
7467  union { TYPES; } value;
7468#undef DO_TYPE
7469
7470  void *data = &value;
7471  size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
7472  size_t convsize = size;
7473  if (repeated_size != NULL)
7474    {
7475      if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
7476	{
7477	  data = alloca (*repeated_size);
7478	  count *= *repeated_size / size;
7479	  convsize = count * size;
7480	  *repeated_size -= convsize;
7481	}
7482      else if (item->count != 0 || item->format != '\n')
7483	*repeated_size -= size;
7484    }
7485
7486  convert (core, item->type, count, data, desc + item->offset, convsize);
7487
7488  Elf_Type type = item->type;
7489  if (type == ELF_T_ADDR)
7490    type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
7491
7492  switch (item->format)
7493    {
7494    case 'd':
7495      assert (count == 1);
7496      switch (type)
7497	{
7498#define DO_TYPE(NAME, Name, hex, dec, max)				      \
7499	  case ELF_T_##NAME:						      \
7500	    colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN,	      \
7501				     0, item->name, max, dec, value.Name[0]); \
7502	    break
7503	  TYPES;
7504#undef DO_TYPE
7505	default:
7506	  abort ();
7507	}
7508      break;
7509
7510    case 'x':
7511      assert (count == 1);
7512      switch (type)
7513	{
7514#define DO_TYPE(NAME, Name, hex, dec, max)				      \
7515	  case ELF_T_##NAME:						      \
7516	    colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN,	      \
7517				     0, item->name, max, hex, value.Name[0]); \
7518	    break
7519	  TYPES;
7520#undef DO_TYPE
7521	default:
7522	  abort ();
7523	}
7524      break;
7525
7526    case 'b':
7527    case 'B':
7528      assert (size % sizeof (unsigned int) == 0);
7529      unsigned int nbits = count * size * 8;
7530      unsigned int pop = 0;
7531      for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
7532	pop += __builtin_popcount (*i);
7533      bool negate = pop > nbits / 2;
7534      const unsigned int bias = item->format == 'b';
7535
7536      {
7537	char printed[(negate ? nbits - pop : pop) * 16];
7538	char *p = printed;
7539	*p = '\0';
7540
7541	if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
7542	  {
7543	    assert (size == sizeof (unsigned int) * 2);
7544	    for (unsigned int *i = data;
7545		 (void *) i < data + count * size; i += 2)
7546	      {
7547		unsigned int w = i[1];
7548		i[1] = i[0];
7549		i[0] = w;
7550	      }
7551	  }
7552
7553	unsigned int lastbit = 0;
7554	for (const unsigned int *i = data;
7555	     (void *) i < data + count * size; ++i)
7556	  {
7557	    unsigned int bit = ((void *) i - data) * 8;
7558	    unsigned int w = negate ? ~*i : *i;
7559	    unsigned int run = 0;
7560	    while (w != 0)
7561	      {
7562		int n = ffs (w);
7563		w >>= n;
7564		bit += n;
7565
7566		if (lastbit + 1 == bit)
7567		  ++run;
7568		else
7569		  {
7570		    if (lastbit == 0)
7571		      p += sprintf (p, "%u", bit - bias);
7572		    else if (run == 0)
7573		      p += sprintf (p, ",%u", bit - bias);
7574		    else
7575		      p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
7576		    run = 0;
7577		  }
7578
7579		lastbit = bit;
7580	      }
7581	  }
7582	if (lastbit > 0 && lastbit + 1 != nbits)
7583	  p += sprintf (p, "-%u", nbits - bias);
7584
7585	colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7586				 4 + nbits * 4,
7587				 negate ? "~<%s>" : "<%s>", printed);
7588      }
7589      break;
7590
7591    case 'T':
7592    case (char) ('T'|0x80):
7593      assert (count == 2);
7594      Dwarf_Word sec;
7595      Dwarf_Word usec;
7596      size_t maxfmt = 7;
7597      switch (type)
7598	{
7599#define DO_TYPE(NAME, Name, hex, dec, max)				      \
7600	  case ELF_T_##NAME:						      \
7601	    sec = value.Name[0];					      \
7602	    usec = value.Name[1];					      \
7603	    maxfmt += max;						      \
7604	    break
7605	  TYPES;
7606#undef DO_TYPE
7607	default:
7608	  abort ();
7609	}
7610      if (unlikely (item->format == (char) ('T'|0x80)))
7611	{
7612	  /* This is a hack for an ill-considered 64-bit ABI where
7613	     tv_usec is actually a 32-bit field with 32 bits of padding
7614	     rounding out struct timeval.  We've already converted it as
7615	     a 64-bit field.  For little-endian, this just means the
7616	     high half is the padding; it's presumably zero, but should
7617	     be ignored anyway.  For big-endian, it means the 32-bit
7618	     field went into the high half of USEC.  */
7619	  GElf_Ehdr ehdr_mem;
7620	  GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
7621	  if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
7622	    usec >>= 32;
7623	  else
7624	    usec &= UINT32_MAX;
7625	}
7626      colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7627			       maxfmt, "%" PRIu64 ".%.6" PRIu64, sec, usec);
7628      break;
7629
7630    case 'c':
7631      assert (count == 1);
7632      colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7633			       1, "%c", value.Byte[0]);
7634      break;
7635
7636    case 's':
7637      colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7638			       count, "%.*s", (int) count, value.Byte);
7639      break;
7640
7641    case '\n':
7642      /* This is a list of strings separated by '\n'.  */
7643      assert (item->count == 0);
7644      assert (repeated_size != NULL);
7645      assert (item->name == NULL);
7646      if (unlikely (item->offset >= *repeated_size))
7647	break;
7648
7649      const char *s = desc + item->offset;
7650      size = *repeated_size - item->offset;
7651      *repeated_size = 0;
7652      while (size > 0)
7653	{
7654	  const char *eol = memchr (s, '\n', size);
7655	  int len = size;
7656	  if (eol != NULL)
7657	    len = eol - s;
7658	  printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
7659	  if (eol == NULL)
7660	    break;
7661	  size -= eol + 1 - s;
7662	  s = eol + 1;
7663	}
7664
7665      colno = ITEM_WRAP_COLUMN;
7666      break;
7667
7668    default:
7669      error (0, 0, "XXX not handling format '%c' for %s",
7670	     item->format, item->name);
7671      break;
7672    }
7673
7674#undef TYPES
7675
7676  return colno;
7677}
7678
7679
7680/* Sort items by group, and by layout offset within each group.  */
7681static int
7682compare_core_items (const void *a, const void *b)
7683{
7684  const Ebl_Core_Item *const *p1 = a;
7685  const Ebl_Core_Item *const *p2 = b;
7686  const Ebl_Core_Item *item1 = *p1;
7687  const Ebl_Core_Item *item2 = *p2;
7688
7689  return ((item1->group == item2->group ? 0
7690	   : strcmp (item1->group, item2->group))
7691	  ?: (int) item1->offset - (int) item2->offset);
7692}
7693
7694/* Sort item groups by layout offset of the first item in the group.  */
7695static int
7696compare_core_item_groups (const void *a, const void *b)
7697{
7698  const Ebl_Core_Item *const *const *p1 = a;
7699  const Ebl_Core_Item *const *const *p2 = b;
7700  const Ebl_Core_Item *const *group1 = *p1;
7701  const Ebl_Core_Item *const *group2 = *p2;
7702  const Ebl_Core_Item *item1 = *group1;
7703  const Ebl_Core_Item *item2 = *group2;
7704
7705  return (int) item1->offset - (int) item2->offset;
7706}
7707
7708static unsigned int
7709handle_core_items (Elf *core, const void *desc, size_t descsz,
7710		   const Ebl_Core_Item *items, size_t nitems)
7711{
7712  if (nitems == 0)
7713    return 0;
7714
7715  /* Sort to collect the groups together.  */
7716  const Ebl_Core_Item *sorted_items[nitems];
7717  for (size_t i = 0; i < nitems; ++i)
7718    sorted_items[i] = &items[i];
7719  qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
7720
7721  /* Collect the unique groups and sort them.  */
7722  const Ebl_Core_Item **groups[nitems];
7723  groups[0] = &sorted_items[0];
7724  size_t ngroups = 1;
7725  for (size_t i = 1; i < nitems; ++i)
7726    if (sorted_items[i]->group != sorted_items[i - 1]->group
7727	&& strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
7728      groups[ngroups++] = &sorted_items[i];
7729  qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
7730
7731  /* Write out all the groups.  */
7732  unsigned int colno = 0;
7733
7734  const void *last = desc;
7735  if (nitems == 1)
7736    {
7737      size_t size = descsz;
7738      colno = handle_core_item (core, sorted_items[0], desc, colno, &size);
7739      if (size == 0)
7740	return colno;
7741      desc += descsz - size;
7742      descsz = size;
7743    }
7744
7745  do
7746    {
7747      for (size_t i = 0; i < ngroups; ++i)
7748	{
7749	  for (const Ebl_Core_Item **item = groups[i];
7750	       (item < &sorted_items[nitems]
7751		&& ((*item)->group == groups[i][0]->group
7752		    || !strcmp ((*item)->group, groups[i][0]->group)));
7753	       ++item)
7754	    colno = handle_core_item (core, *item, desc, colno, NULL);
7755
7756	  /* Force a line break at the end of the group.  */
7757	  colno = ITEM_WRAP_COLUMN;
7758	}
7759
7760      if (descsz == 0)
7761	break;
7762
7763      /* This set of items consumed a certain amount of the note's data.
7764	 If there is more data there, we have another unit of the same size.
7765	 Loop to print that out too.  */
7766      const Ebl_Core_Item *item = &items[nitems - 1];
7767      size_t eltsz = item->offset + gelf_fsize (core, item->type,
7768						item->count ?: 1, EV_CURRENT);
7769
7770      int reps = -1;
7771      do
7772	{
7773	  ++reps;
7774	  desc += eltsz;
7775	  descsz -= eltsz;
7776	}
7777      while (descsz >= eltsz && !memcmp (desc, last, eltsz));
7778
7779      if (reps == 1)
7780	{
7781	  /* For just one repeat, print it unabridged twice.  */
7782	  desc -= eltsz;
7783	  descsz += eltsz;
7784	}
7785      else if (reps > 1)
7786	printf (gettext ("\n%*s... <repeats %u more times> ..."),
7787		ITEM_INDENT, "", reps);
7788
7789      last = desc;
7790    }
7791  while (descsz > 0);
7792
7793  return colno;
7794}
7795
7796static unsigned int
7797handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
7798		      unsigned int colno)
7799{
7800  desc += regloc->offset;
7801
7802  abort ();			/* XXX */
7803  return colno;
7804}
7805
7806
7807static unsigned int
7808handle_core_register (Ebl *ebl, Elf *core, int maxregname,
7809		      const Ebl_Register_Location *regloc, const void *desc,
7810		      unsigned int colno)
7811{
7812  if (regloc->bits % 8 != 0)
7813    return handle_bit_registers (regloc, desc, colno);
7814
7815  desc += regloc->offset;
7816
7817  for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
7818    {
7819      char name[REGNAMESZ];
7820      int bits;
7821      int type;
7822      register_info (ebl, reg, regloc, name, &bits, &type);
7823
7824#define TYPES								      \
7825      BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8, 4);			      \
7826      BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16, 6);			      \
7827      BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32, 11);		      \
7828      BITS (64, XWORD, "%20" PRId64, "  0x%.16" PRIx64, 20)
7829
7830#define BITS(bits, xtype, sfmt, ufmt, max)				\
7831      uint##bits##_t b##bits; int##bits##_t b##bits##s
7832      union { TYPES; uint64_t b128[2]; } value;
7833#undef	BITS
7834
7835      switch (type)
7836	{
7837	case DW_ATE_unsigned:
7838	case DW_ATE_signed:
7839	case DW_ATE_address:
7840	  switch (bits)
7841	    {
7842#define BITS(bits, xtype, sfmt, ufmt, max)				      \
7843	    case bits:							      \
7844	      desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0);	      \
7845	      if (type == DW_ATE_signed)				      \
7846		colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,    \
7847					 maxregname, name,		      \
7848					 max, sfmt, value.b##bits##s);	      \
7849	      else							      \
7850		colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,    \
7851					 maxregname, name,		      \
7852					 max, ufmt, value.b##bits);	      \
7853	      break
7854
7855	    TYPES;
7856
7857	    case 128:
7858	      assert (type == DW_ATE_unsigned);
7859	      desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
7860	      int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
7861	      colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
7862				       maxregname, name,
7863				       34, "0x%.16" PRIx64 "%.16" PRIx64,
7864				       value.b128[!be], value.b128[be]);
7865	      break;
7866
7867	    default:
7868	      abort ();
7869#undef	BITS
7870	    }
7871	  break;
7872
7873	default:
7874	  /* Print each byte in hex, the whole thing in native byte order.  */
7875	  assert (bits % 8 == 0);
7876	  const uint8_t *bytes = desc;
7877	  desc += bits / 8;
7878	  char hex[bits / 4 + 1];
7879	  hex[bits / 4] = '\0';
7880	  int incr = 1;
7881	  if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
7882	    {
7883	      bytes += bits / 8 - 1;
7884	      incr = -1;
7885	    }
7886	  size_t idx = 0;
7887	  for (char *h = hex; bits > 0; bits -= 8, idx += incr)
7888	    {
7889	      *h++ = "0123456789abcdef"[bytes[idx] >> 4];
7890	      *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
7891	    }
7892	  colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
7893				   maxregname, name,
7894				   2 + sizeof hex - 1, "0x%s", hex);
7895	  break;
7896	}
7897      desc += regloc->pad;
7898
7899#undef TYPES
7900    }
7901
7902  return colno;
7903}
7904
7905
7906struct register_info
7907{
7908  const Ebl_Register_Location *regloc;
7909  const char *set;
7910  char name[REGNAMESZ];
7911  int regno;
7912  int bits;
7913  int type;
7914};
7915
7916static int
7917register_bitpos (const struct register_info *r)
7918{
7919  return (r->regloc->offset * 8
7920	  + ((r->regno - r->regloc->regno)
7921	     * (r->regloc->bits + r->regloc->pad * 8)));
7922}
7923
7924static int
7925compare_sets_by_info (const struct register_info *r1,
7926		      const struct register_info *r2)
7927{
7928  return ((int) r2->bits - (int) r1->bits
7929	  ?: register_bitpos (r1) - register_bitpos (r2));
7930}
7931
7932/* Sort registers by set, and by size and layout offset within each set.  */
7933static int
7934compare_registers (const void *a, const void *b)
7935{
7936  const struct register_info *r1 = a;
7937  const struct register_info *r2 = b;
7938
7939  /* Unused elements sort last.  */
7940  if (r1->regloc == NULL)
7941    return r2->regloc == NULL ? 0 : 1;
7942  if (r2->regloc == NULL)
7943    return -1;
7944
7945  return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
7946	  ?: compare_sets_by_info (r1, r2));
7947}
7948
7949/* Sort register sets by layout offset of the first register in the set.  */
7950static int
7951compare_register_sets (const void *a, const void *b)
7952{
7953  const struct register_info *const *p1 = a;
7954  const struct register_info *const *p2 = b;
7955  return compare_sets_by_info (*p1, *p2);
7956}
7957
7958static unsigned int
7959handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
7960		       const Ebl_Register_Location *reglocs, size_t nregloc)
7961{
7962  if (nregloc == 0)
7963    return 0;
7964
7965  ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
7966  if (maxnreg <= 0)
7967    {
7968      for (size_t i = 0; i < nregloc; ++i)
7969	if (maxnreg < reglocs[i].regno + reglocs[i].count)
7970	  maxnreg = reglocs[i].regno + reglocs[i].count;
7971      assert (maxnreg > 0);
7972    }
7973
7974  struct register_info regs[maxnreg];
7975  memset (regs, 0, sizeof regs);
7976
7977  /* Sort to collect the sets together.  */
7978  int maxreg = 0;
7979  for (size_t i = 0; i < nregloc; ++i)
7980    for (int reg = reglocs[i].regno;
7981	 reg < reglocs[i].regno + reglocs[i].count;
7982	 ++reg)
7983      {
7984	assert (reg < maxnreg);
7985	if (reg > maxreg)
7986	  maxreg = reg;
7987	struct register_info *info = &regs[reg];
7988	info->regloc = &reglocs[i];
7989	info->regno = reg;
7990	info->set = register_info (ebl, reg, &reglocs[i],
7991				   info->name, &info->bits, &info->type);
7992      }
7993  qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
7994
7995  /* Collect the unique sets and sort them.  */
7996  inline bool same_set (const struct register_info *a,
7997			const struct register_info *b)
7998  {
7999    return (a < &regs[maxnreg] && a->regloc != NULL
8000	    && b < &regs[maxnreg] && b->regloc != NULL
8001	    && a->bits == b->bits
8002	    && (a->set == b->set || !strcmp (a->set, b->set)));
8003  }
8004  struct register_info *sets[maxreg + 1];
8005  sets[0] = &regs[0];
8006  size_t nsets = 1;
8007  for (int i = 1; i <= maxreg; ++i)
8008    if (regs[i].regloc != NULL && !same_set (&regs[i], &regs[i - 1]))
8009      sets[nsets++] = &regs[i];
8010  qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
8011
8012  /* Write out all the sets.  */
8013  unsigned int colno = 0;
8014  for (size_t i = 0; i < nsets; ++i)
8015    {
8016      /* Find the longest name of a register in this set.  */
8017      size_t maxname = 0;
8018      const struct register_info *end;
8019      for (end = sets[i]; same_set (sets[i], end); ++end)
8020	{
8021	  size_t len = strlen (end->name);
8022	  if (len > maxname)
8023	    maxname = len;
8024	}
8025
8026      for (const struct register_info *reg = sets[i];
8027	   reg < end;
8028	   reg += reg->regloc->count ?: 1)
8029	colno = handle_core_register (ebl, core, maxname,
8030				      reg->regloc, desc, colno);
8031
8032      /* Force a line break at the end of the group.  */
8033      colno = REGISTER_WRAP_COLUMN;
8034    }
8035
8036  return colno;
8037}
8038
8039static void
8040handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
8041{
8042  Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
8043  if (data == NULL)
8044  elf_error:
8045    error (EXIT_FAILURE, 0,
8046	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
8047
8048  const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
8049  for (size_t i = 0; i < nauxv; ++i)
8050    {
8051      GElf_auxv_t av_mem;
8052      GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
8053      if (av == NULL)
8054	goto elf_error;
8055
8056      const char *name;
8057      const char *fmt;
8058      if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
8059	{
8060	  /* Unknown type.  */
8061	  if (av->a_un.a_val == 0)
8062	    printf ("    %" PRIu64 "\n", av->a_type);
8063	  else
8064	    printf ("    %" PRIu64 ": %#" PRIx64 "\n",
8065		    av->a_type, av->a_un.a_val);
8066	}
8067      else
8068	switch (fmt[0])
8069	  {
8070	  case '\0':		/* Normally zero.  */
8071	    if (av->a_un.a_val == 0)
8072	      {
8073		printf ("    %s\n", name);
8074		break;
8075	      }
8076	    /* Fall through */
8077	  case 'x':		/* hex */
8078	  case 'p':		/* address */
8079	  case 's':		/* address of string */
8080	    printf ("    %s: %#" PRIx64 "\n", name, av->a_un.a_val);
8081	    break;
8082	  case 'u':
8083	    printf ("    %s: %" PRIu64 "\n", name, av->a_un.a_val);
8084	    break;
8085	  case 'd':
8086	    printf ("    %s: %" PRId64 "\n", name, av->a_un.a_val);
8087	    break;
8088
8089	  case 'b':
8090	    printf ("    %s: %#" PRIx64 "  ", name, av->a_un.a_val);
8091	    GElf_Xword bit = 1;
8092	    const char *pfx = "<";
8093	    for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
8094	      {
8095		if (av->a_un.a_val & bit)
8096		  {
8097		    printf ("%s%s", pfx, p);
8098		    pfx = " ";
8099		  }
8100		bit <<= 1;
8101	      }
8102	    printf (">\n");
8103	    break;
8104
8105	  default:
8106	    abort ();
8107	  }
8108    }
8109}
8110
8111static void
8112handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
8113		  const char *name, const void *desc)
8114{
8115  GElf_Word regs_offset;
8116  size_t nregloc;
8117  const Ebl_Register_Location *reglocs;
8118  size_t nitems;
8119  const Ebl_Core_Item *items;
8120
8121  if (! ebl_core_note (ebl, nhdr, name,
8122		       &regs_offset, &nregloc, &reglocs, &nitems, &items))
8123    return;
8124
8125  /* Pass 0 for DESCSZ when there are registers in the note,
8126     so that the ITEMS array does not describe the whole thing.
8127     For non-register notes, the actual descsz might be a multiple
8128     of the unit size, not just exactly the unit size.  */
8129  unsigned int colno = handle_core_items (ebl->elf, desc,
8130					  nregloc == 0 ? nhdr->n_descsz : 0,
8131					  items, nitems);
8132  if (colno != 0)
8133    putchar_unlocked ('\n');
8134
8135  colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
8136				 reglocs, nregloc);
8137  if (colno != 0)
8138    putchar_unlocked ('\n');
8139}
8140
8141static void
8142handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
8143		   GElf_Off start, Elf_Data *data)
8144{
8145  fputs_unlocked (gettext ("  Owner          Data size  Type\n"), stdout);
8146
8147  if (data == NULL)
8148    goto bad_note;
8149
8150  size_t offset = 0;
8151  GElf_Nhdr nhdr;
8152  size_t name_offset;
8153  size_t desc_offset;
8154  while (offset < data->d_size
8155	 && (offset = gelf_getnote (data, offset,
8156				    &nhdr, &name_offset, &desc_offset)) > 0)
8157    {
8158      const char *name = data->d_buf + name_offset;
8159      const char *desc = data->d_buf + desc_offset;
8160
8161      char buf[100];
8162      char buf2[100];
8163      printf (gettext ("  %-13.*s  %9" PRId32 "  %s\n"),
8164	      (int) nhdr.n_namesz, name, nhdr.n_descsz,
8165	      ehdr->e_type == ET_CORE
8166	      ? ebl_core_note_type_name (ebl, nhdr.n_type,
8167					 buf, sizeof (buf))
8168	      : ebl_object_note_type_name (ebl, name, nhdr.n_type,
8169					   buf2, sizeof (buf2)));
8170
8171      /* Filter out invalid entries.  */
8172      if (memchr (name, '\0', nhdr.n_namesz) != NULL
8173	  /* XXX For now help broken Linux kernels.  */
8174	  || 1)
8175	{
8176	  if (ehdr->e_type == ET_CORE)
8177	    {
8178	      if (nhdr.n_type == NT_AUXV
8179		  && (nhdr.n_namesz == 4 /* Broken old Linux kernels.  */
8180		      || (nhdr.n_namesz == 5 && name[4] == '\0'))
8181		  && !memcmp (name, "CORE", 4))
8182		handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
8183				  start + desc_offset);
8184	      else
8185		handle_core_note (ebl, &nhdr, name, desc);
8186	    }
8187	  else
8188	    ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc);
8189	}
8190    }
8191
8192  if (offset == data->d_size)
8193    return;
8194
8195 bad_note:
8196  error (EXIT_FAILURE, 0,
8197	 gettext ("cannot get content of note section: %s"),
8198	 elf_errmsg (-1));
8199}
8200
8201static void
8202handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
8203{
8204  /* If we have section headers, just look for SHT_NOTE sections.
8205     In a debuginfo file, the program headers are not reliable.  */
8206  if (shnum != 0)
8207    {
8208      /* Get the section header string table index.  */
8209      size_t shstrndx;
8210      if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
8211	error (EXIT_FAILURE, 0,
8212	       gettext ("cannot get section header string table index"));
8213
8214      Elf_Scn *scn = NULL;
8215      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
8216	{
8217	  GElf_Shdr shdr_mem;
8218	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
8219
8220	  if (shdr == NULL || shdr->sh_type != SHT_NOTE)
8221	    /* Not what we are looking for.  */
8222	    continue;
8223
8224	  printf (gettext ("\
8225\nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
8226		  elf_ndxscn (scn),
8227		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
8228		  shdr->sh_size, shdr->sh_offset);
8229
8230	  handle_notes_data (ebl, ehdr, shdr->sh_offset,
8231			     elf_getdata (scn, NULL));
8232	}
8233      return;
8234    }
8235
8236  /* We have to look through the program header to find the note
8237     sections.  There can be more than one.  */
8238  for (size_t cnt = 0; cnt < phnum; ++cnt)
8239    {
8240      GElf_Phdr mem;
8241      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
8242
8243      if (phdr == NULL || phdr->p_type != PT_NOTE)
8244	/* Not what we are looking for.  */
8245	continue;
8246
8247      printf (gettext ("\
8248\nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
8249	      phdr->p_filesz, phdr->p_offset);
8250
8251      handle_notes_data (ebl, ehdr, phdr->p_offset,
8252			 elf_getdata_rawchunk (ebl->elf,
8253					       phdr->p_offset, phdr->p_filesz,
8254					       ELF_T_NHDR));
8255    }
8256}
8257
8258
8259static void
8260hex_dump (const uint8_t *data, size_t len)
8261{
8262  size_t pos = 0;
8263  while (pos < len)
8264    {
8265      printf ("  0x%08Zx ", pos);
8266
8267      const size_t chunk = MIN (len - pos, 16);
8268
8269      for (size_t i = 0; i < chunk; ++i)
8270	if (i % 4 == 3)
8271	  printf ("%02x ", data[pos + i]);
8272	else
8273	  printf ("%02x", data[pos + i]);
8274
8275      if (chunk < 16)
8276	printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
8277
8278      for (size_t i = 0; i < chunk; ++i)
8279	{
8280	  unsigned char b = data[pos + i];
8281	  printf ("%c", isprint (b) ? b : '.');
8282	}
8283
8284      putchar ('\n');
8285      pos += chunk;
8286    }
8287}
8288
8289static void
8290dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
8291{
8292  if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
8293    printf (gettext ("\nSection [%Zu] '%s' has no data to dump.\n"),
8294	    elf_ndxscn (scn), name);
8295  else
8296    {
8297      Elf_Data *data = elf_rawdata (scn, NULL);
8298      if (data == NULL)
8299	error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
8300	       elf_ndxscn (scn), name, elf_errmsg (-1));
8301      else
8302	{
8303	  printf (gettext ("\nHex dump of section [%Zu] '%s', %" PRIu64
8304			   " bytes at offset %#0" PRIx64 ":\n"),
8305		  elf_ndxscn (scn), name,
8306		  shdr->sh_size, shdr->sh_offset);
8307	  hex_dump (data->d_buf, data->d_size);
8308	}
8309    }
8310}
8311
8312static void
8313print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
8314{
8315  if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
8316    printf (gettext ("\nSection [%Zu] '%s' has no strings to dump.\n"),
8317	    elf_ndxscn (scn), name);
8318  else
8319    {
8320      Elf_Data *data = elf_rawdata (scn, NULL);
8321      if (data == NULL)
8322	error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
8323	       elf_ndxscn (scn), name, elf_errmsg (-1));
8324      else
8325	{
8326	  printf (gettext ("\nString section [%Zu] '%s' contains %" PRIu64
8327			   " bytes at offset %#0" PRIx64 ":\n"),
8328		  elf_ndxscn (scn), name,
8329		  shdr->sh_size, shdr->sh_offset);
8330
8331	  const char *start = data->d_buf;
8332	  const char *const limit = start + data->d_size;
8333	  do
8334	    {
8335	      const char *end = memchr (start, '\0', limit - start);
8336	      const size_t pos = start - (const char *) data->d_buf;
8337	      if (unlikely (end == NULL))
8338		{
8339		  printf ("  [%6Zx]- %.*s\n",
8340			  pos, (int) (limit - start), start);
8341		  break;
8342		}
8343	      printf ("  [%6Zx]  %s\n", pos, start);
8344	      start = end + 1;
8345	    } while (start < limit);
8346	}
8347    }
8348}
8349
8350static void
8351for_each_section_argument (Elf *elf, const struct section_argument *list,
8352			   void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
8353					 const char *name))
8354{
8355  /* Get the section header string table index.  */
8356  size_t shstrndx;
8357  if (elf_getshdrstrndx (elf, &shstrndx) < 0)
8358    error (EXIT_FAILURE, 0,
8359	   gettext ("cannot get section header string table index"));
8360
8361  for (const struct section_argument *a = list; a != NULL; a = a->next)
8362    {
8363      Elf_Scn *scn;
8364      GElf_Shdr shdr_mem;
8365      const char *name = NULL;
8366
8367      char *endp = NULL;
8368      unsigned long int shndx = strtoul (a->arg, &endp, 0);
8369      if (endp != a->arg && *endp == '\0')
8370	{
8371	  scn = elf_getscn (elf, shndx);
8372	  if (scn == NULL)
8373	    {
8374	      error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
8375	      continue;
8376	    }
8377
8378	  if (gelf_getshdr (scn, &shdr_mem) == NULL)
8379	    error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
8380		   elf_errmsg (-1));
8381	  name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
8382	}
8383      else
8384	{
8385	  /* Need to look up the section by name.  */
8386	  scn = NULL;
8387	  bool found = false;
8388	  while ((scn = elf_nextscn (elf, scn)) != NULL)
8389	    {
8390	      if (gelf_getshdr (scn, &shdr_mem) == NULL)
8391		continue;
8392	      name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
8393	      if (name == NULL)
8394		continue;
8395	      if (!strcmp (name, a->arg))
8396		{
8397		  found = true;
8398		  (*dump) (scn, &shdr_mem, name);
8399		}
8400	    }
8401
8402	  if (unlikely (!found) && !a->implicit)
8403	    error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
8404	}
8405    }
8406}
8407
8408static void
8409dump_data (Ebl *ebl)
8410{
8411  for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
8412}
8413
8414static void
8415dump_strings (Ebl *ebl)
8416{
8417  for_each_section_argument (ebl->elf, string_sections, &print_string_section);
8418}
8419
8420static void
8421print_strings (Ebl *ebl)
8422{
8423  /* Get the section header string table index.  */
8424  size_t shstrndx;
8425  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
8426    error (EXIT_FAILURE, 0,
8427	   gettext ("cannot get section header string table index"));
8428
8429  Elf_Scn *scn;
8430  GElf_Shdr shdr_mem;
8431  const char *name;
8432  scn = NULL;
8433  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
8434    {
8435      if (gelf_getshdr (scn, &shdr_mem) == NULL)
8436	continue;
8437
8438      if (shdr_mem.sh_type != SHT_PROGBITS
8439	  || !(shdr_mem.sh_flags & SHF_STRINGS))
8440	continue;
8441
8442      name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
8443      if (name == NULL)
8444	continue;
8445
8446      print_string_section (scn, &shdr_mem, name);
8447    }
8448}
8449
8450static void
8451dump_archive_index (Elf *elf, const char *fname)
8452{
8453  size_t narsym;
8454  const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
8455  if (arsym == NULL)
8456    {
8457      int result = elf_errno ();
8458      if (unlikely (result != ELF_E_NO_INDEX))
8459	error (EXIT_FAILURE, 0,
8460	       gettext ("cannot get symbol index of archive '%s': %s"),
8461	       fname, elf_errmsg (result));
8462      else
8463	printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
8464      return;
8465    }
8466
8467  printf (gettext ("\nIndex of archive '%s' has %Zu entries:\n"),
8468	  fname, narsym);
8469
8470  size_t as_off = 0;
8471  for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
8472    {
8473      if (s->as_off != as_off)
8474	{
8475	  as_off = s->as_off;
8476
8477	  Elf *subelf;
8478	  if (unlikely (elf_rand (elf, as_off) == 0)
8479	      || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
8480			   == NULL))
8481#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
8482	    while (1)
8483#endif
8484	      error (EXIT_FAILURE, 0,
8485		     gettext ("cannot extract member at offset %Zu in '%s': %s"),
8486		     as_off, fname, elf_errmsg (-1));
8487
8488	  const Elf_Arhdr *h = elf_getarhdr (subelf);
8489
8490	  printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
8491
8492	  elf_end (subelf);
8493	}
8494
8495      printf ("\t%s\n", s->as_name);
8496    }
8497}
8498
8499#include "debugpred.h"
8500