88766889b286397ef274348262ca0537e795a8cf
[platform/upstream/elfutils.git] / src / readelf.c
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.  */
64 static void print_version (FILE *stream, struct argp_state *state);
65 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
66
67 /* Bug report address.  */
68 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
69
70 /* Definitions of arguments for argp functions.  */
71 static 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.  */
115 static const char doc[] = N_("\
116 Print information from ELF file in human-readable form.");
117
118 /* Strings for arguments in help texts.  */
119 static const char args_doc[] = N_("FILE...");
120
121 /* Prototype for option handler.  */
122 static error_t parse_opt (int key, char *arg, struct argp_state *state);
123
124 /* Data structure to communicate with argp functions.  */
125 static 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.  */
134 static bool print_dynamic_table;
135
136 /* True if the file header should be printed.  */
137 static bool print_file_header;
138
139 /* True if the program headers should be printed.  */
140 static bool print_program_header;
141
142 /* True if relocations should be printed.  */
143 static bool print_relocations;
144
145 /* True if the section headers should be printed.  */
146 static bool print_section_header;
147
148 /* True if the symbol table should be printed.  */
149 static bool print_symbol_table;
150
151 /* True if the version information should be printed.  */
152 static bool print_version_info;
153
154 /* True if section groups should be printed.  */
155 static bool print_section_groups;
156
157 /* True if bucket list length histogram should be printed.  */
158 static bool print_histogram;
159
160 /* True if the architecture specific data should be printed.  */
161 static bool print_arch;
162
163 /* True if note section content should be printed.  */
164 static bool print_notes;
165
166 /* True if SHF_STRINGS section content should be printed.  */
167 static bool print_string_sections;
168
169 /* True if archive index should be printed.  */
170 static bool print_archive_index;
171
172 /* True if any of the control options except print_archive_index is set.  */
173 static bool any_control_option;
174
175 /* True if we should print addresses from DWARF in symbolic form.  */
176 static bool print_address_names = true;
177
178 /* Select printing of debugging sections.  */
179 static 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.  */
201 static struct section_argument *dump_data_sections;
202 static struct section_argument **dump_data_sections_tail = &dump_data_sections;
203
204 /* Select string dumping of sections.  */
205 static struct section_argument *string_sections;
206 static struct section_argument **string_sections_tail = &string_sections;
207
208 struct 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.  */
216 static size_t shnum;
217 static size_t phnum;
218
219
220 /* Declarations of local functions.  */
221 static void process_file (int fd, const char *fname, bool only_one);
222 static void process_elf_file (Dwfl_Module *dwflmod, int fd);
223 static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
224 static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
225 static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
226 static void print_scngrp (Ebl *ebl);
227 static void print_dynamic (Ebl *ebl);
228 static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
229 static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
230                                GElf_Shdr *shdr);
231 static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
232                                 GElf_Shdr *shdr);
233 static void print_symtab (Ebl *ebl, int type);
234 static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
235 static void print_verinfo (Ebl *ebl);
236 static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
237 static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
238 static void handle_versym (Ebl *ebl, Elf_Scn *scn,
239                            GElf_Shdr *shdr);
240 static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
241 static void handle_hash (Ebl *ebl);
242 static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
243 static void print_liblist (Ebl *ebl);
244 static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
245 static void dump_data (Ebl *ebl);
246 static void dump_strings (Ebl *ebl);
247 static void print_strings (Ebl *ebl);
248 static void dump_archive_index (Elf *, const char *);
249
250
251 int
252 main (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.  */
290 static error_t
291 parse_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.  */
458 static void
459 print_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 ("\
463 Copyright (C) %s Red Hat, Inc.\n\
464 This is free software; see the source for copying conditions.  There is NO\n\
465 warranty; 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.  */
472 static void
473 check_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.  */
501 static int
502 count_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
514 struct process_dwflmod_args
515 {
516   int fd;
517   bool only_one;
518 };
519
520 static int
521 process_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.  */
544 static int
545 find_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.  */
558 static void
559 process_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.  */
615 static void
616 process_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.  */
727 static void
728 print_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.  */
752 static void
753 print_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
863 static const char *
864 get_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.  */
883 static void
884 print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
885 {
886   size_t cnt;
887   size_t shstrndx;
888
889   if (! print_file_header)
890     printf (gettext ("\
891 There 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.  */
970 static void
971 print_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
1163 static const char *
1164 section_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
1170 static void
1171 handle_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
1227 static void
1228 print_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
1245 static 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   };
1257 static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
1258
1259 static 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   };
1279 static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
1280
1281 static const struct flags dt_feature_1[] =
1282   {
1283     { DTF_1_PARINIT, "PARINIT" },
1284     { DTF_1_CONFEXP, "CONFEXP" }
1285   };
1286 static const int ndt_feature_1 = (sizeof (dt_feature_1)
1287                                   / sizeof (dt_feature_1[0]));
1288
1289 static const struct flags dt_posflag_1[] =
1290   {
1291     { DF_P1_LAZYLOAD, "LAZYLOAD" },
1292     { DF_P1_GROUPPERM, "GROUPPERM" }
1293   };
1294 static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
1295                                   / sizeof (dt_posflag_1[0]));
1296
1297
1298 static void
1299 print_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
1326 static void
1327 print_dt_flags (int class, GElf_Xword d_val)
1328 {
1329   print_flags (class, d_val, dt_flags, ndt_flags);
1330 }
1331
1332
1333 static void
1334 print_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
1340 static void
1341 print_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
1347 static void
1348 print_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
1354 static void
1355 handle_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.  */
1486 static void
1487 print_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.  */
1508 static void
1509 print_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.  */
1532 static void
1533 handle_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.  */
1718 static void
1719 handle_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.  */
1896 static void
1897 print_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
1915 static void
1916 handle_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.  */
2149 static void
2150 print_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
2175 static const char *
2176 get_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
2207 static void
2208 handle_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
2275 static void
2276 handle_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
2349 static void
2350 handle_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
2623 static void
2624 print_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.  */
2692 static void
2693 handle_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.  */
2734 static void
2735 handle_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.  */
2775 static void
2776 handle_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.  */
2856 static void
2857 handle_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
2888 static void
2889 print_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
2950 static void
2951 print_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
3114 static char *
3115 format_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
3188 static const char *
3189 dwarf_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
3324 static const char *
3325 dwarf_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
3616 static const char *
3617 dwarf_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
3666 static const char *
3667 dwarf_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
3709 static const char *
3710 dwarf_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
3727 static const char *
3728 dwarf_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
3764 static const char *
3765 dwarf_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
3781 static const char *
3782 dwarf_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
3798 static const char *
3799 dwarf_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
3815 static const char *
3816 dwarf_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
3833 static const char *
3834 dwarf_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
3857 static const char *
3858 dwarf_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
3873 static const char *
3874 dwarf_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
3889 static void
3890 print_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
3905 static void
3906 print_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
4426 struct 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
4437 static int
4438 compare_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
4470 struct listptr_table
4471 {
4472   size_t n;
4473   size_t alloc;
4474   struct listptr *table;
4475 };
4476
4477 static struct listptr_table known_loclistptr;
4478 static struct listptr_table known_rangelistptr;
4479
4480 static void
4481 reset_listptr (struct listptr_table *table)
4482 {
4483   free (table->table);
4484   table->table = NULL;
4485   table->n = table->alloc = 0;
4486 }
4487
4488 static void
4489 notice_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
4517 static void
4518 sort_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
4525 static bool
4526 skip_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
4564 static void
4565 print_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.  */
4635 static void
4636 print_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.  */
4691 static void
4692 print_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
4779 static const char *
4780 register_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
4808 static void
4809 print_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
5010 static unsigned int
5011 encoded_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
5027 static unsigned int
5028 print_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
5068 static unsigned int
5069 print_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
5096 static void
5097 print_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
5125 static const unsigned char *
5126 read_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
5183 static void
5184 print_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
5516 struct 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
5529 static int
5530 attr_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
5809 static void
5810 print_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
5963 static void
5964 print_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
5970 static void
5971 print_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
5978 static void
5979 print_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
6469 static void
6470 print_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
6570 struct mac_culist
6571 {
6572   Dwarf_Die die;
6573   Dwarf_Off offset;
6574   Dwarf_Files *files;
6575   struct mac_culist *next;
6576 };
6577
6578
6579 static int
6580 mac_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
6593 static void
6594 print_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.  */
6750 static int
6751 print_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'.  */
6765 static void
6766 print_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'.  */
6779 static void
6780 print_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'.  */
6824 static void
6825 print_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'.  */
6924 static void
6925 print_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 */
7085 static void
7086 print_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
7282 static void
7283 print_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.  */
7383 static unsigned int
7384 __attribute__ ((format (printf, 7, 8)))
7385 print_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
7421 static const void *
7422 convert (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
7450 typedef uint8_t GElf_Byte;
7451
7452 static unsigned int
7453 handle_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.  */
7681 static int
7682 compare_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.  */
7695 static int
7696 compare_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
7708 static unsigned int
7709 handle_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
7796 static unsigned int
7797 handle_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
7807 static unsigned int
7808 handle_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
7906 struct 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
7916 static int
7917 register_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
7924 static int
7925 compare_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.  */
7933 static int
7934 compare_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.  */
7950 static int
7951 compare_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
7958 static unsigned int
7959 handle_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
8039 static void
8040 handle_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
8111 static void
8112 handle_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
8141 static void
8142 handle_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
8201 static void
8202 handle_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
8259 static void
8260 hex_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
8289 static void
8290 dump_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
8312 static void
8313 print_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
8350 static void
8351 for_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
8408 static void
8409 dump_data (Ebl *ebl)
8410 {
8411   for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
8412 }
8413
8414 static void
8415 dump_strings (Ebl *ebl)
8416 {
8417   for_each_section_argument (ebl->elf, string_sections, &print_string_section);
8418 }
8419
8420 static void
8421 print_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
8450 static void
8451 dump_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"