Imported Upstream version 0.155
[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 elfutils.
4    Written by Ulrich Drepper <drepper@redhat.com>, 1999.
5
6    This file is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    elfutils is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <argp.h>
24 #include <assert.h>
25 #include <ctype.h>
26 #include <dwarf.h>
27 #include <errno.h>
28 #include <error.h>
29 #include <fcntl.h>
30 #include <gelf.h>
31 #include <inttypes.h>
32 #include <langinfo.h>
33 #include <libdw.h>
34 #include <libdwfl.h>
35 #include <libintl.h>
36 #include <locale.h>
37 #include <stdarg.h>
38 #include <stdbool.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <time.h>
42 #include <unistd.h>
43 #include <sys/param.h>
44 #include <sys/stat.h>
45
46 #include <system.h>
47 #include "../libelf/libelfP.h"
48 #include "../libelf/common.h"
49 #include "../libebl/libeblP.h"
50 #include "../libdw/libdwP.h"
51 #include "../libdwfl/libdwflP.h"
52 #include "../libdw/memory-access.h"
53
54 #include "../libdw/known-dwarf.h"
55
56
57 /* Name and version of program.  */
58 static void print_version (FILE *stream, struct argp_state *state);
59 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
60
61 /* Bug report address.  */
62 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
63
64 /* Definitions of arguments for argp functions.  */
65 static const struct argp_option options[] =
66 {
67   { NULL, 0, NULL, 0, N_("ELF output selection:"), 0 },
68   { "all", 'a', NULL, 0,
69     N_("All these plus -p .strtab -p .dynstr -p .comment"), 0 },
70   { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
71   { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
72   { "histogram", 'I', NULL, 0,
73     N_("Display histogram of bucket list lengths"), 0 },
74   { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
75   { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
76   { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
77   { "section-headers", 'S', NULL, 0, N_("Display the sections' headers"), 0 },
78   { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
79   { "symbols", 's', NULL, 0, N_("Display the symbol table"), 0 },
80   { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
81   { "notes", 'n', NULL, 0, N_("Display the ELF notes"), 0 },
82   { "arch-specific", 'A', NULL, 0,
83     N_("Display architecture specific information, if any"), 0 },
84   { "exception", 'e', NULL, 0,
85     N_("Display sections for exception handling"), 0 },
86
87   { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 },
88   { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
89     N_("Display DWARF section content.  SECTION can be one of abbrev, "
90        "aranges, frame, gdb_index, info, loc, line, ranges, pubnames, str, "
91        "macinfo, macro or exception"), 0 },
92   { "hex-dump", 'x', "SECTION", 0,
93     N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
94   { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
95     N_("Print string contents of sections"), 0 },
96   { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
97   { "archive-index", 'c', NULL, 0,
98     N_("Display the symbol index of an archive"), 0 },
99
100   { NULL, 0, NULL, 0, N_("Output control:"), 0 },
101   { "numeric-addresses", 'N', NULL, 0,
102     N_("Do not find symbol names for addresses in DWARF data"), 0 },
103   { "wide", 'W', NULL, 0,
104     N_("Ignored for compatibility (lines always wide)"), 0 },
105   { NULL, 0, NULL, 0, NULL, 0 }
106 };
107
108 /* Short description of program.  */
109 static const char doc[] = N_("\
110 Print information from ELF file in human-readable form.");
111
112 /* Strings for arguments in help texts.  */
113 static const char args_doc[] = N_("FILE...");
114
115 /* Prototype for option handler.  */
116 static error_t parse_opt (int key, char *arg, struct argp_state *state);
117
118 /* Data structure to communicate with argp functions.  */
119 static struct argp argp =
120 {
121   options, parse_opt, args_doc, doc, NULL, NULL, NULL
122 };
123
124
125 /* Flags set by the option controlling the output.  */
126
127 /* True if dynamic segment should be printed.  */
128 static bool print_dynamic_table;
129
130 /* True if the file header should be printed.  */
131 static bool print_file_header;
132
133 /* True if the program headers should be printed.  */
134 static bool print_program_header;
135
136 /* True if relocations should be printed.  */
137 static bool print_relocations;
138
139 /* True if the section headers should be printed.  */
140 static bool print_section_header;
141
142 /* True if the symbol table should be printed.  */
143 static bool print_symbol_table;
144
145 /* True if the version information should be printed.  */
146 static bool print_version_info;
147
148 /* True if section groups should be printed.  */
149 static bool print_section_groups;
150
151 /* True if bucket list length histogram should be printed.  */
152 static bool print_histogram;
153
154 /* True if the architecture specific data should be printed.  */
155 static bool print_arch;
156
157 /* True if note section content should be printed.  */
158 static bool print_notes;
159
160 /* True if SHF_STRINGS section content should be printed.  */
161 static bool print_string_sections;
162
163 /* True if archive index should be printed.  */
164 static bool print_archive_index;
165
166 /* True if any of the control options except print_archive_index is set.  */
167 static bool any_control_option;
168
169 /* True if we should print addresses from DWARF in symbolic form.  */
170 static bool print_address_names = true;
171
172 /* Select printing of debugging sections.  */
173 static enum section_e
174 {
175   section_abbrev = 1,           /* .debug_abbrev  */
176   section_aranges = 2,          /* .debug_aranges  */
177   section_frame = 4,            /* .debug_frame or .eh_frame & al.  */
178   section_info = 8,             /* .debug_info, .debug_types  */
179   section_types = section_info,
180   section_line = 16,            /* .debug_line  */
181   section_loc = 32,             /* .debug_loc  */
182   section_pubnames = 64,        /* .debug_pubnames  */
183   section_str = 128,            /* .debug_str  */
184   section_macinfo = 256,        /* .debug_macinfo  */
185   section_ranges = 512,         /* .debug_ranges  */
186   section_exception = 1024,     /* .eh_frame & al.  */
187   section_gdb_index = 2048,     /* .gdb_index  */
188   section_macro = 4096,         /* .debug_macro  */
189   section_all = (section_abbrev | section_aranges | section_frame
190                  | section_info | section_line | section_loc
191                  | section_pubnames | section_str | section_macinfo
192                  | section_ranges | section_exception | section_gdb_index
193                  | section_macro)
194 } print_debug_sections, implicit_debug_sections;
195
196 /* Select hex dumping of sections.  */
197 static struct section_argument *dump_data_sections;
198 static struct section_argument **dump_data_sections_tail = &dump_data_sections;
199
200 /* Select string dumping of sections.  */
201 static struct section_argument *string_sections;
202 static struct section_argument **string_sections_tail = &string_sections;
203
204 struct section_argument
205 {
206   struct section_argument *next;
207   const char *arg;
208   bool implicit;
209 };
210
211 /* Numbers of sections and program headers in the file.  */
212 static size_t shnum;
213 static size_t phnum;
214
215
216 /* Declarations of local functions.  */
217 static void process_file (int fd, const char *fname, bool only_one);
218 static void process_elf_file (Dwfl_Module *dwflmod, int fd);
219 static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
220 static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
221 static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
222 static void print_scngrp (Ebl *ebl);
223 static void print_dynamic (Ebl *ebl);
224 static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
225 static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
226                                GElf_Shdr *shdr);
227 static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
228                                 GElf_Shdr *shdr);
229 static void print_symtab (Ebl *ebl, int type);
230 static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
231 static void print_verinfo (Ebl *ebl);
232 static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
233 static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
234 static void handle_versym (Ebl *ebl, Elf_Scn *scn,
235                            GElf_Shdr *shdr);
236 static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
237 static void handle_hash (Ebl *ebl);
238 static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
239 static void print_liblist (Ebl *ebl);
240 static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
241 static void dump_data (Ebl *ebl);
242 static void dump_strings (Ebl *ebl);
243 static void print_strings (Ebl *ebl);
244 static void dump_archive_index (Elf *, const char *);
245
246
247 int
248 main (int argc, char *argv[])
249 {
250   /* Set locale.  */
251   setlocale (LC_ALL, "");
252
253   /* Initialize the message catalog.  */
254   textdomain (PACKAGE_TARNAME);
255
256   /* Parse and process arguments.  */
257   int remaining;
258   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
259
260   /* Before we start tell the ELF library which version we are using.  */
261   elf_version (EV_CURRENT);
262
263   /* Now process all the files given at the command line.  */
264   bool only_one = remaining + 1 == argc;
265   do
266     {
267       /* Open the file.  */
268       int fd = open (argv[remaining], O_RDONLY);
269       if (fd == -1)
270         {
271           error (0, errno, gettext ("cannot open input file"));
272           continue;
273         }
274
275       process_file (fd, argv[remaining], only_one);
276
277       close (fd);
278     }
279   while (++remaining < argc);
280
281   return error_message_count != 0;
282 }
283
284
285 /* Handle program arguments.  */
286 static error_t
287 parse_opt (int key, char *arg,
288            struct argp_state *state __attribute__ ((unused)))
289 {
290   void add_dump_section (const char *name, bool implicit)
291   {
292     struct section_argument *a = xmalloc (sizeof *a);
293     a->arg = name;
294     a->next = NULL;
295     a->implicit = implicit;
296     struct section_argument ***tailp
297       = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
298     **tailp = a;
299     *tailp = &a->next;
300   }
301
302   switch (key)
303     {
304     case 'a':
305       print_file_header = true;
306       print_program_header = true;
307       print_relocations = true;
308       print_section_header = true;
309       print_symbol_table = true;
310       print_version_info = true;
311       print_dynamic_table = true;
312       print_section_groups = true;
313       print_histogram = true;
314       print_arch = true;
315       print_notes = true;
316       implicit_debug_sections |= section_exception;
317       add_dump_section (".strtab", true);
318       add_dump_section (".dynstr", true);
319       add_dump_section (".comment", true);
320       any_control_option = true;
321       break;
322     case 'A':
323       print_arch = true;
324       any_control_option = true;
325       break;
326     case 'd':
327       print_dynamic_table = true;
328       any_control_option = true;
329       break;
330     case 'e':
331       print_debug_sections |= section_exception;
332       any_control_option = true;
333       break;
334     case 'g':
335       print_section_groups = true;
336       any_control_option = true;
337       break;
338     case 'h':
339       print_file_header = true;
340       any_control_option = true;
341       break;
342     case 'I':
343       print_histogram = true;
344       any_control_option = true;
345       break;
346     case 'l':
347       print_program_header = true;
348       any_control_option = true;
349       break;
350     case 'n':
351       print_notes = true;
352       any_control_option = true;
353       break;
354     case 'r':
355       print_relocations = true;
356       any_control_option = true;
357      break;
358     case 'S':
359       print_section_header = true;
360       any_control_option = true;
361       break;
362     case 's':
363       print_symbol_table = true;
364       any_control_option = true;
365       break;
366     case 'V':
367       print_version_info = true;
368       any_control_option = true;
369       break;
370     case 'c':
371       print_archive_index = true;
372       break;
373     case 'w':
374       if (arg == NULL)
375         print_debug_sections = section_all;
376       else if (strcmp (arg, "abbrev") == 0)
377         print_debug_sections |= section_abbrev;
378       else if (strcmp (arg, "aranges") == 0)
379         print_debug_sections |= section_aranges;
380       else if (strcmp (arg, "ranges") == 0)
381         {
382           print_debug_sections |= section_ranges;
383           implicit_debug_sections |= section_info;
384         }
385       else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
386         print_debug_sections |= section_frame;
387       else if (strcmp (arg, "info") == 0)
388         print_debug_sections |= section_info;
389       else if (strcmp (arg, "loc") == 0)
390         {
391           print_debug_sections |= section_loc;
392           implicit_debug_sections |= section_info;
393         }
394       else if (strcmp (arg, "line") == 0)
395         print_debug_sections |= section_line;
396       else if (strcmp (arg, "pubnames") == 0)
397         print_debug_sections |= section_pubnames;
398       else if (strcmp (arg, "str") == 0)
399         print_debug_sections |= section_str;
400       else if (strcmp (arg, "macinfo") == 0)
401         print_debug_sections |= section_macinfo;
402       else if (strcmp (arg, "macro") == 0)
403         print_debug_sections |= section_macro;
404       else if (strcmp (arg, "exception") == 0)
405         print_debug_sections |= section_exception;
406       else if (strcmp (arg, "gdb_index") == 0)
407         print_debug_sections |= section_gdb_index;
408       else
409         {
410           fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
411                    arg);
412           argp_help (&argp, stderr, ARGP_HELP_SEE,
413                      program_invocation_short_name);
414           exit (1);
415         }
416       any_control_option = true;
417       break;
418     case 'p':
419       any_control_option = true;
420       if (arg == NULL)
421         {
422           print_string_sections = true;
423           break;
424         }
425       /* Fall through.  */
426     case 'x':
427       add_dump_section (arg, false);
428       any_control_option = true;
429       break;
430     case 'N':
431       print_address_names = false;
432       break;
433     case ARGP_KEY_NO_ARGS:
434       fputs (gettext ("Missing file name.\n"), stderr);
435       goto do_argp_help;
436     case ARGP_KEY_FINI:
437       if (! any_control_option && ! print_archive_index)
438         {
439           fputs (gettext ("No operation specified.\n"), stderr);
440         do_argp_help:
441           argp_help (&argp, stderr, ARGP_HELP_SEE,
442                      program_invocation_short_name);
443           exit (EXIT_FAILURE);
444         }
445       break;
446     case 'W':                   /* Ignored.  */
447       break;
448     default:
449       return ARGP_ERR_UNKNOWN;
450     }
451   return 0;
452 }
453
454
455 /* Print the version information.  */
456 static void
457 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
458 {
459   fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
460   fprintf (stream, gettext ("\
461 Copyright (C) %s Red Hat, Inc.\n\
462 This is free software; see the source for copying conditions.  There is NO\n\
463 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
464 "), "2012");
465   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
466 }
467
468
469 /* Check if the file is an archive, and if so dump its index.  */
470 static void
471 check_archive_index (int fd, const char *fname, bool only_one)
472 {
473   /* Create an `Elf' descriptor.  */
474   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
475   if (elf == NULL)
476     error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
477            elf_errmsg (-1));
478   else
479     {
480       if (elf_kind (elf) == ELF_K_AR)
481         {
482           if (!only_one)
483             printf ("\n%s:\n\n", fname);
484           dump_archive_index (elf, fname);
485         }
486       else
487         error (0, 0,
488                gettext ("'%s' is not an archive, cannot print archive index"),
489                fname);
490
491       /* Now we can close the descriptor.  */
492       if (elf_end (elf) != 0)
493         error (0, 0, gettext ("error while closing Elf descriptor: %s"),
494                elf_errmsg (-1));
495     }
496 }
497
498 /* Trivial callback used for checking if we opened an archive.  */
499 static int
500 count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
501                void **userdata __attribute__ ((unused)),
502                const char *name __attribute__ ((unused)),
503                Dwarf_Addr base __attribute__ ((unused)),
504                void *arg)
505 {
506   if (*(bool *) arg)
507     return DWARF_CB_ABORT;
508   *(bool *) arg = true;
509   return DWARF_CB_OK;
510 }
511
512 struct process_dwflmod_args
513 {
514   int fd;
515   bool only_one;
516 };
517
518 static int
519 process_dwflmod (Dwfl_Module *dwflmod,
520                  void **userdata __attribute__ ((unused)),
521                  const char *name __attribute__ ((unused)),
522                  Dwarf_Addr base __attribute__ ((unused)),
523                  void *arg)
524 {
525   const struct process_dwflmod_args *a = arg;
526
527   /* Print the file name.  */
528   if (!a->only_one)
529     {
530       const char *fname;
531       dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
532
533       printf ("\n%s:\n\n", fname);
534     }
535
536   process_elf_file (dwflmod, a->fd);
537
538   return DWARF_CB_OK;
539 }
540
541 /* Stub libdwfl callback, only the ELF handle already open is ever used.  */
542 static int
543 find_no_debuginfo (Dwfl_Module *mod __attribute__ ((unused)),
544                    void **userdata __attribute__ ((unused)),
545                    const char *modname __attribute__ ((unused)),
546                    Dwarf_Addr base __attribute__ ((unused)),
547                    const char *file_name __attribute__ ((unused)),
548                    const char *debuglink_file __attribute__ ((unused)),
549                    GElf_Word debuglink_crc __attribute__ ((unused)),
550                    char **debuginfo_file_name __attribute__ ((unused)))
551 {
552   return -1;
553 }
554
555 /* Process one input file.  */
556 static void
557 process_file (int fd, const char *fname, bool only_one)
558 {
559   if (print_archive_index)
560     check_archive_index (fd, fname, only_one);
561
562   if (!any_control_option)
563     return;
564
565   /* Duplicate an fd for dwfl_report_offline to swallow.  */
566   int dwfl_fd = dup (fd);
567   if (unlikely (dwfl_fd < 0))
568     error (EXIT_FAILURE, errno, "dup");
569
570   /* Use libdwfl in a trivial way to open the libdw handle for us.
571      This takes care of applying relocations to DWARF data in ET_REL files.  */
572   static const Dwfl_Callbacks callbacks =
573     {
574       .section_address = dwfl_offline_section_address,
575       .find_debuginfo = find_no_debuginfo
576     };
577   Dwfl *dwfl = dwfl_begin (&callbacks);
578   if (likely (dwfl != NULL))
579     /* Let 0 be the logical address of the file (or first in archive).  */
580     dwfl->offline_next_address = 0;
581   if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
582     {
583       struct stat64 st;
584       if (fstat64 (dwfl_fd, &st) != 0)
585         error (0, errno, gettext ("cannot stat input file"));
586       else if (unlikely (st.st_size == 0))
587         error (0, 0, gettext ("input file is empty"));
588       else
589         error (0, 0, gettext ("failed reading '%s': %s"),
590                fname, dwfl_errmsg (-1));
591       close (dwfl_fd);          /* Consumed on success, not on failure.  */
592     }
593   else
594     {
595       dwfl_report_end (dwfl, NULL, NULL);
596
597       if (only_one)
598         {
599           /* Clear ONLY_ONE if we have multiple modules, from an archive.  */
600           bool seen = false;
601           only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
602         }
603
604       /* Process the one or more modules gleaned from this file.  */
605       struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
606       dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
607     }
608   dwfl_end (dwfl);
609 }
610
611
612 /* Process one ELF file.  */
613 static void
614 process_elf_file (Dwfl_Module *dwflmod, int fd)
615 {
616   GElf_Addr dwflbias;
617   Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
618
619   GElf_Ehdr ehdr_mem;
620   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
621
622   if (ehdr == NULL)
623     {
624     elf_error:
625       error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
626       return;
627     }
628
629   Ebl *ebl = ebl_openbackend (elf);
630   if (unlikely (ebl == NULL))
631     {
632     ebl_error:
633       error (0, errno, gettext ("cannot create EBL handle"));
634       return;
635     }
636
637   /* Determine the number of sections.  */
638   if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
639     error (EXIT_FAILURE, 0,
640            gettext ("cannot determine number of sections: %s"),
641            elf_errmsg (-1));
642
643   /* Determine the number of phdrs.  */
644   if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
645     error (EXIT_FAILURE, 0,
646            gettext ("cannot determine number of program headers: %s"),
647            elf_errmsg (-1));
648
649   /* For an ET_REL file, libdwfl has adjusted the in-core shdrs
650      and may have applied relocation to some sections.
651      So we need to get a fresh Elf handle on the file to display those.  */
652   bool print_unrelocated = (print_section_header
653                             || print_relocations
654                             || dump_data_sections != NULL
655                             || print_notes);
656
657   Elf *pure_elf = NULL;
658   Ebl *pure_ebl = ebl;
659   if (ehdr->e_type == ET_REL && print_unrelocated)
660     {
661       /* Read the file afresh.  */
662       off64_t aroff = elf_getaroff (elf);
663       pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
664       if (aroff > 0)
665         {
666           /* Archive member.  */
667           (void) elf_rand (pure_elf, aroff);
668           Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
669           elf_end (pure_elf);
670           pure_elf = armem;
671         }
672       if (pure_elf == NULL)
673         goto elf_error;
674       pure_ebl = ebl_openbackend (pure_elf);
675       if (pure_ebl == NULL)
676         goto ebl_error;
677     }
678
679   if (print_file_header)
680     print_ehdr (ebl, ehdr);
681   if (print_section_header)
682     print_shdr (pure_ebl, ehdr);
683   if (print_program_header)
684     print_phdr (ebl, ehdr);
685   if (print_section_groups)
686     print_scngrp (ebl);
687   if (print_dynamic_table)
688     print_dynamic (ebl);
689   if (print_relocations)
690     print_relocs (pure_ebl, ehdr);
691   if (print_histogram)
692     handle_hash (ebl);
693   if (print_symbol_table)
694     print_symtab (ebl, SHT_DYNSYM);
695   if (print_version_info)
696     print_verinfo (ebl);
697   if (print_symbol_table)
698     print_symtab (ebl, SHT_SYMTAB);
699   if (print_arch)
700     print_liblist (ebl);
701   if (print_arch)
702     print_attributes (ebl, ehdr);
703   if (dump_data_sections != NULL)
704     dump_data (pure_ebl);
705   if (string_sections != NULL)
706     dump_strings (ebl);
707   if ((print_debug_sections | implicit_debug_sections) != 0)
708     print_debug (dwflmod, ebl, ehdr);
709   if (print_notes)
710     handle_notes (pure_ebl, ehdr);
711   if (print_string_sections)
712     print_strings (ebl);
713
714   ebl_closebackend (ebl);
715
716   if (pure_ebl != ebl)
717     {
718       ebl_closebackend (pure_ebl);
719       elf_end (pure_elf);
720     }
721 }
722
723
724 /* Print file type.  */
725 static void
726 print_file_type (unsigned short int e_type)
727 {
728   if (likely (e_type <= ET_CORE))
729     {
730       static const char *const knowntypes[] =
731       {
732         N_("NONE (None)"),
733         N_("REL (Relocatable file)"),
734         N_("EXEC (Executable file)"),
735         N_("DYN (Shared object file)"),
736         N_("CORE (Core file)")
737       };
738       puts (gettext (knowntypes[e_type]));
739     }
740   else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
741     printf (gettext ("OS Specific: (%x)\n"),  e_type);
742   else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
743     printf (gettext ("Processor Specific: (%x)\n"),  e_type);
744   else
745     puts ("???");
746 }
747
748
749 /* Print ELF header.  */
750 static void
751 print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
752 {
753   fputs_unlocked (gettext ("ELF Header:\n  Magic:  "), stdout);
754   for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
755     printf (" %02hhx", ehdr->e_ident[cnt]);
756
757   printf (gettext ("\n  Class:                             %s\n"),
758           ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
759           : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
760           : "\?\?\?");
761
762   printf (gettext ("  Data:                              %s\n"),
763           ehdr->e_ident[EI_DATA] == ELFDATA2LSB
764           ? "2's complement, little endian"
765           : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
766           ? "2's complement, big endian" : "\?\?\?");
767
768   printf (gettext ("  Ident Version:                     %hhd %s\n"),
769           ehdr->e_ident[EI_VERSION],
770           ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
771           : "(\?\?\?)");
772
773   char buf[512];
774   printf (gettext ("  OS/ABI:                            %s\n"),
775           ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
776
777   printf (gettext ("  ABI Version:                       %hhd\n"),
778           ehdr->e_ident[EI_ABIVERSION]);
779
780   fputs_unlocked (gettext ("  Type:                              "), stdout);
781   print_file_type (ehdr->e_type);
782
783   printf (gettext ("  Machine:                           %s\n"), ebl->name);
784
785   printf (gettext ("  Version:                           %d %s\n"),
786           ehdr->e_version,
787           ehdr->e_version  == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
788
789   printf (gettext ("  Entry point address:               %#" PRIx64 "\n"),
790           ehdr->e_entry);
791
792   printf (gettext ("  Start of program headers:          %" PRId64 " %s\n"),
793           ehdr->e_phoff, gettext ("(bytes into file)"));
794
795   printf (gettext ("  Start of section headers:          %" PRId64 " %s\n"),
796           ehdr->e_shoff, gettext ("(bytes into file)"));
797
798   printf (gettext ("  Flags:                             %s\n"),
799           ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
800
801   printf (gettext ("  Size of this header:               %" PRId16 " %s\n"),
802           ehdr->e_ehsize, gettext ("(bytes)"));
803
804   printf (gettext ("  Size of program header entries:    %" PRId16 " %s\n"),
805           ehdr->e_phentsize, gettext ("(bytes)"));
806
807   printf (gettext ("  Number of program headers entries: %" PRId16),
808           ehdr->e_phnum);
809   if (ehdr->e_phnum == PN_XNUM)
810     {
811       GElf_Shdr shdr_mem;
812       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
813       if (shdr != NULL)
814         printf (gettext (" (%" PRIu32 " in [0].sh_info)"),
815                 (uint32_t) shdr->sh_info);
816       else
817         fputs_unlocked (gettext (" ([0] not available)"), stdout);
818     }
819   fputc_unlocked ('\n', stdout);
820
821   printf (gettext ("  Size of section header entries:    %" PRId16 " %s\n"),
822           ehdr->e_shentsize, gettext ("(bytes)"));
823
824   printf (gettext ("  Number of section headers entries: %" PRId16),
825           ehdr->e_shnum);
826   if (ehdr->e_shnum == 0)
827     {
828       GElf_Shdr shdr_mem;
829       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
830       if (shdr != NULL)
831         printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
832                 (uint32_t) shdr->sh_size);
833       else
834         fputs_unlocked (gettext (" ([0] not available)"), stdout);
835     }
836   fputc_unlocked ('\n', stdout);
837
838   if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
839     {
840       GElf_Shdr shdr_mem;
841       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
842       if (shdr != NULL)
843         /* We managed to get the zeroth section.  */
844         snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
845                   (uint32_t) shdr->sh_link);
846       else
847         {
848           strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
849           buf[sizeof (buf) - 1] = '\0';
850         }
851
852       printf (gettext ("  Section header string table index: XINDEX%s\n\n"),
853               buf);
854     }
855   else
856     printf (gettext ("  Section header string table index: %" PRId16 "\n\n"),
857             ehdr->e_shstrndx);
858 }
859
860
861 static const char *
862 get_visibility_type (int value)
863 {
864   switch (value)
865     {
866     case STV_DEFAULT:
867       return "DEFAULT";
868     case STV_INTERNAL:
869       return "INTERNAL";
870     case STV_HIDDEN:
871       return "HIDDEN";
872     case STV_PROTECTED:
873       return "PROTECTED";
874     default:
875       return "???";
876     }
877 }
878
879
880 /* Print the section headers.  */
881 static void
882 print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
883 {
884   size_t cnt;
885   size_t shstrndx;
886
887   if (! print_file_header)
888     printf (gettext ("\
889 There are %d section headers, starting at offset %#" PRIx64 ":\n\
890 \n"),
891             ehdr->e_shnum, ehdr->e_shoff);
892
893   /* Get the section header string table index.  */
894   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
895     error (EXIT_FAILURE, 0,
896            gettext ("cannot get section header string table index"));
897
898   puts (gettext ("Section Headers:"));
899
900   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
901     puts (gettext ("[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al"));
902   else
903     puts (gettext ("[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al"));
904
905   for (cnt = 0; cnt < shnum; ++cnt)
906     {
907       Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
908
909       if (unlikely (scn == NULL))
910         error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
911                elf_errmsg (-1));
912
913       /* Get the section header.  */
914       GElf_Shdr shdr_mem;
915       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
916       if (unlikely (shdr == NULL))
917         error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
918                elf_errmsg (-1));
919
920       char flagbuf[20];
921       char *cp = flagbuf;
922       if (shdr->sh_flags & SHF_WRITE)
923         *cp++ = 'W';
924       if (shdr->sh_flags & SHF_ALLOC)
925         *cp++ = 'A';
926       if (shdr->sh_flags & SHF_EXECINSTR)
927         *cp++ = 'X';
928       if (shdr->sh_flags & SHF_MERGE)
929         *cp++ = 'M';
930       if (shdr->sh_flags & SHF_STRINGS)
931         *cp++ = 'S';
932       if (shdr->sh_flags & SHF_INFO_LINK)
933         *cp++ = 'I';
934       if (shdr->sh_flags & SHF_LINK_ORDER)
935         *cp++ = 'L';
936       if (shdr->sh_flags & SHF_OS_NONCONFORMING)
937         *cp++ = 'N';
938       if (shdr->sh_flags & SHF_GROUP)
939         *cp++ = 'G';
940       if (shdr->sh_flags & SHF_TLS)
941         *cp++ = 'T';
942       if (shdr->sh_flags & SHF_ORDERED)
943         *cp++ = 'O';
944       if (shdr->sh_flags & SHF_EXCLUDE)
945         *cp++ = 'E';
946       *cp = '\0';
947
948       char buf[128];
949       printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
950               " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
951               " %2" PRId64 "\n",
952               cnt,
953               elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
954               ?: "<corrupt>",
955               ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
956               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
957               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
958               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
959               shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
960               shdr->sh_addralign);
961     }
962
963   fputc_unlocked ('\n', stdout);
964 }
965
966
967 /* Print the program header.  */
968 static void
969 print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
970 {
971   if (ehdr->e_phnum == 0)
972     /* No program header, this is OK in relocatable objects.  */
973     return;
974
975   puts (gettext ("Program Headers:"));
976   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
977     puts (gettext ("\
978   Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"));
979   else
980     puts (gettext ("\
981   Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align"));
982
983   /* Process all program headers.  */
984   bool has_relro = false;
985   GElf_Addr relro_from = 0;
986   GElf_Addr relro_to = 0;
987   for (size_t cnt = 0; cnt < phnum; ++cnt)
988     {
989       char buf[128];
990       GElf_Phdr mem;
991       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
992
993       /* If for some reason the header cannot be returned show this.  */
994       if (unlikely (phdr == NULL))
995         {
996           puts ("  ???");
997           continue;
998         }
999
1000       printf ("  %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
1001               " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
1002               ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
1003               phdr->p_offset,
1004               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
1005               ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
1006               phdr->p_filesz,
1007               phdr->p_memsz,
1008               phdr->p_flags & PF_R ? 'R' : ' ',
1009               phdr->p_flags & PF_W ? 'W' : ' ',
1010               phdr->p_flags & PF_X ? 'E' : ' ',
1011               phdr->p_align);
1012
1013       if (phdr->p_type == PT_INTERP)
1014         {
1015           /* We can show the user the name of the interpreter.  */
1016           size_t maxsize;
1017           char *filedata = elf_rawfile (ebl->elf, &maxsize);
1018
1019           if (filedata != NULL && phdr->p_offset < maxsize)
1020             printf (gettext ("\t[Requesting program interpreter: %s]\n"),
1021                     filedata + phdr->p_offset);
1022         }
1023       else if (phdr->p_type == PT_GNU_RELRO)
1024         {
1025           has_relro = true;
1026           relro_from = phdr->p_vaddr;
1027           relro_to = relro_from + phdr->p_memsz;
1028         }
1029     }
1030
1031   if (ehdr->e_shnum == 0)
1032     /* No sections in the file.  Punt.  */
1033     return;
1034
1035   /* Get the section header string table index.  */
1036   size_t shstrndx;
1037   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1038     error (EXIT_FAILURE, 0,
1039            gettext ("cannot get section header string table index"));
1040
1041   puts (gettext ("\n Section to Segment mapping:\n  Segment Sections..."));
1042
1043   for (size_t cnt = 0; cnt < phnum; ++cnt)
1044     {
1045       /* Print the segment number.  */
1046       printf ("   %2.2zu     ", cnt);
1047
1048       GElf_Phdr phdr_mem;
1049       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
1050       /* This must not happen.  */
1051       if (unlikely (phdr == NULL))
1052         error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
1053                elf_errmsg (-1));
1054
1055       /* Iterate over the sections.  */
1056       bool in_relro = false;
1057       bool in_ro = false;
1058       for (size_t inner = 1; inner < shnum; ++inner)
1059         {
1060           Elf_Scn *scn = elf_getscn (ebl->elf, inner);
1061           /* This should not happen.  */
1062           if (unlikely (scn == NULL))
1063             error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
1064                    elf_errmsg (-1));
1065
1066           /* Get the section header.  */
1067           GElf_Shdr shdr_mem;
1068           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1069           if (unlikely (shdr == NULL))
1070             error (EXIT_FAILURE, 0,
1071                    gettext ("cannot get section header: %s"),
1072                    elf_errmsg (-1));
1073
1074           if (shdr->sh_size > 0
1075               /* Compare allocated sections by VMA, unallocated
1076                  sections by file offset.  */
1077               && (shdr->sh_flags & SHF_ALLOC
1078                   ? (shdr->sh_addr >= phdr->p_vaddr
1079                      && (shdr->sh_addr + shdr->sh_size
1080                          <= phdr->p_vaddr + phdr->p_memsz))
1081                   : (shdr->sh_offset >= phdr->p_offset
1082                      && (shdr->sh_offset + shdr->sh_size
1083                          <= phdr->p_offset + phdr->p_filesz))))
1084             {
1085               if (has_relro && !in_relro
1086                   && shdr->sh_addr >= relro_from
1087                   && shdr->sh_addr + shdr->sh_size <= relro_to)
1088                 {
1089                   fputs_unlocked (" [RELRO:", stdout);
1090                   in_relro = true;
1091                 }
1092               else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
1093                 {
1094                   fputs_unlocked ("]", stdout);
1095                   in_relro =  false;
1096                 }
1097               else if (has_relro && in_relro
1098                        && shdr->sh_addr + shdr->sh_size > relro_to)
1099                 fputs_unlocked ("] <RELRO:", stdout);
1100               else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
1101                 {
1102                   if (!in_ro)
1103                     {
1104                       fputs_unlocked (" [RO:", stdout);
1105                       in_ro = true;
1106                     }
1107                 }
1108               else
1109                 {
1110                   /* Determine the segment this section is part of.  */
1111                   size_t cnt2;
1112                   GElf_Phdr *phdr2 = NULL;
1113                   for (cnt2 = 0; cnt2 < phnum; ++cnt2)
1114                     {
1115                       GElf_Phdr phdr2_mem;
1116                       phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
1117
1118                       if (phdr2 != NULL && phdr2->p_type == PT_LOAD
1119                           && shdr->sh_addr >= phdr2->p_vaddr
1120                           && (shdr->sh_addr + shdr->sh_size
1121                               <= phdr2->p_vaddr + phdr2->p_memsz))
1122                         break;
1123                     }
1124
1125                   if (cnt2 < phnum)
1126                     {
1127                       if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
1128                         {
1129                           fputs_unlocked (" [RO:", stdout);
1130                           in_ro = true;
1131                         }
1132                       else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
1133                         {
1134                           fputs_unlocked ("]", stdout);
1135                           in_ro = false;
1136                         }
1137                     }
1138                 }
1139
1140               printf (" %s",
1141                       elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1142
1143               /* Signal that this sectin is only partially covered.  */
1144               if (has_relro && in_relro
1145                        && shdr->sh_addr + shdr->sh_size > relro_to)
1146                 {
1147                   fputs_unlocked (">", stdout);
1148                   in_relro =  false;
1149                 }
1150             }
1151         }
1152       if (in_relro || in_ro)
1153         fputs_unlocked ("]", stdout);
1154
1155       /* Finish the line.  */
1156       fputc_unlocked ('\n', stdout);
1157     }
1158 }
1159
1160
1161 static const char *
1162 section_name (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr)
1163 {
1164   return elf_strptr (ebl->elf, ehdr->e_shstrndx, shdr->sh_name) ?: "???";
1165 }
1166
1167
1168 static void
1169 handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1170 {
1171   /* Get the data of the section.  */
1172   Elf_Data *data = elf_getdata (scn, NULL);
1173
1174   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1175   GElf_Shdr symshdr_mem;
1176   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1177   Elf_Data *symdata = elf_getdata (symscn, NULL);
1178
1179   if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
1180       || symdata == NULL)
1181     return;
1182
1183   /* Get the section header string table index.  */
1184   size_t shstrndx;
1185   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1186     error (EXIT_FAILURE, 0,
1187            gettext ("cannot get section header string table index"));
1188
1189   Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
1190
1191   GElf_Sym sym_mem;
1192   printf ((grpref[0] & GRP_COMDAT)
1193           ? ngettext ("\
1194 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
1195                       "\
1196 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1197                       data->d_size / sizeof (Elf32_Word) - 1)
1198           : ngettext ("\
1199 \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
1200 \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1201                       data->d_size / sizeof (Elf32_Word) - 1),
1202           elf_ndxscn (scn),
1203           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1204           elf_strptr (ebl->elf, symshdr->sh_link,
1205                       gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name)
1206           ?: gettext ("<INVALID SYMBOL>"),
1207           data->d_size / sizeof (Elf32_Word) - 1);
1208
1209   for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1210     {
1211       GElf_Shdr grpshdr_mem;
1212       GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
1213                                          &grpshdr_mem);
1214
1215       const char *str;
1216       printf ("  [%2u] %s\n",
1217               grpref[cnt],
1218               grpshdr != NULL
1219               && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
1220               ? str : gettext ("<INVALID SECTION>"));
1221     }
1222 }
1223
1224
1225 static void
1226 print_scngrp (Ebl *ebl)
1227 {
1228   /* Find all relocation sections and handle them.  */
1229   Elf_Scn *scn = NULL;
1230
1231   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1232     {
1233        /* Handle the section if it is a symbol table.  */
1234       GElf_Shdr shdr_mem;
1235       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1236
1237       if (shdr != NULL && shdr->sh_type == SHT_GROUP)
1238         handle_scngrp (ebl, scn, shdr);
1239     }
1240 }
1241
1242
1243 static const struct flags
1244 {
1245   int mask;
1246   const char *str;
1247 } dt_flags[] =
1248   {
1249     { DF_ORIGIN, "ORIGIN" },
1250     { DF_SYMBOLIC, "SYMBOLIC" },
1251     { DF_TEXTREL, "TEXTREL" },
1252     { DF_BIND_NOW, "BIND_NOW" },
1253     { DF_STATIC_TLS, "STATIC_TLS" }
1254   };
1255 static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
1256
1257 static const struct flags dt_flags_1[] =
1258   {
1259     { DF_1_NOW, "NOW" },
1260     { DF_1_GLOBAL, "GLOBAL" },
1261     { DF_1_GROUP, "GROUP" },
1262     { DF_1_NODELETE, "NODELETE" },
1263     { DF_1_LOADFLTR, "LOADFLTR" },
1264     { DF_1_INITFIRST, "INITFIRST" },
1265     { DF_1_NOOPEN, "NOOPEN" },
1266     { DF_1_ORIGIN, "ORIGIN" },
1267     { DF_1_DIRECT, "DIRECT" },
1268     { DF_1_TRANS, "TRANS" },
1269     { DF_1_INTERPOSE, "INTERPOSE" },
1270     { DF_1_NODEFLIB, "NODEFLIB" },
1271     { DF_1_NODUMP, "NODUMP" },
1272     { DF_1_CONFALT, "CONFALT" },
1273     { DF_1_ENDFILTEE, "ENDFILTEE" },
1274     { DF_1_DISPRELDNE, "DISPRELDNE" },
1275     { DF_1_DISPRELPND, "DISPRELPND" },
1276   };
1277 static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
1278
1279 static const struct flags dt_feature_1[] =
1280   {
1281     { DTF_1_PARINIT, "PARINIT" },
1282     { DTF_1_CONFEXP, "CONFEXP" }
1283   };
1284 static const int ndt_feature_1 = (sizeof (dt_feature_1)
1285                                   / sizeof (dt_feature_1[0]));
1286
1287 static const struct flags dt_posflag_1[] =
1288   {
1289     { DF_P1_LAZYLOAD, "LAZYLOAD" },
1290     { DF_P1_GROUPPERM, "GROUPPERM" }
1291   };
1292 static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
1293                                   / sizeof (dt_posflag_1[0]));
1294
1295
1296 static void
1297 print_flags (int class, GElf_Xword d_val, const struct flags *flags,
1298                 int nflags)
1299 {
1300   bool first = true;
1301   int cnt;
1302
1303   for (cnt = 0; cnt < nflags; ++cnt)
1304     if (d_val & flags[cnt].mask)
1305       {
1306         if (!first)
1307           putchar_unlocked (' ');
1308         fputs_unlocked (flags[cnt].str, stdout);
1309         d_val &= ~flags[cnt].mask;
1310         first = false;
1311       }
1312
1313   if (d_val != 0)
1314     {
1315       if (!first)
1316         putchar_unlocked (' ');
1317       printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
1318     }
1319
1320   putchar_unlocked ('\n');
1321 }
1322
1323
1324 static void
1325 print_dt_flags (int class, GElf_Xword d_val)
1326 {
1327   print_flags (class, d_val, dt_flags, ndt_flags);
1328 }
1329
1330
1331 static void
1332 print_dt_flags_1 (int class, GElf_Xword d_val)
1333 {
1334   print_flags (class, d_val, dt_flags_1, ndt_flags_1);
1335 }
1336
1337
1338 static void
1339 print_dt_feature_1 (int class, GElf_Xword d_val)
1340 {
1341   print_flags (class, d_val, dt_feature_1, ndt_feature_1);
1342 }
1343
1344
1345 static void
1346 print_dt_posflag_1 (int class, GElf_Xword d_val)
1347 {
1348   print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
1349 }
1350
1351
1352 static void
1353 handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1354 {
1355   int class = gelf_getclass (ebl->elf);
1356   GElf_Shdr glink;
1357   Elf_Data *data;
1358   size_t cnt;
1359   size_t shstrndx;
1360
1361   /* Get the data of the section.  */
1362   data = elf_getdata (scn, NULL);
1363   if (data == NULL)
1364     return;
1365
1366   /* Get the section header string table index.  */
1367   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1368     error (EXIT_FAILURE, 0,
1369            gettext ("cannot get section header string table index"));
1370
1371   printf (ngettext ("\
1372 \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
1373                     "\
1374 \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
1375                     shdr->sh_size / shdr->sh_entsize),
1376           (unsigned long int) (shdr->sh_size / shdr->sh_entsize),
1377           class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
1378           shdr->sh_offset,
1379           (int) shdr->sh_link,
1380           elf_strptr (ebl->elf, shstrndx,
1381                       gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1382                                     &glink)->sh_name));
1383   fputs_unlocked (gettext ("  Type              Value\n"), stdout);
1384
1385   for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1386     {
1387       GElf_Dyn dynmem;
1388       GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
1389       if (dyn == NULL)
1390         break;
1391
1392       char buf[64];
1393       printf ("  %-17s ",
1394               ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
1395
1396       switch (dyn->d_tag)
1397         {
1398         case DT_NULL:
1399         case DT_DEBUG:
1400         case DT_BIND_NOW:
1401         case DT_TEXTREL:
1402           /* No further output.  */
1403           fputc_unlocked ('\n', stdout);
1404           break;
1405
1406         case DT_NEEDED:
1407           printf (gettext ("Shared library: [%s]\n"),
1408                   elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1409           break;
1410
1411         case DT_SONAME:
1412           printf (gettext ("Library soname: [%s]\n"),
1413                   elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1414           break;
1415
1416         case DT_RPATH:
1417           printf (gettext ("Library rpath: [%s]\n"),
1418                   elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1419           break;
1420
1421         case DT_RUNPATH:
1422           printf (gettext ("Library runpath: [%s]\n"),
1423                   elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1424           break;
1425
1426         case DT_PLTRELSZ:
1427         case DT_RELASZ:
1428         case DT_STRSZ:
1429         case DT_RELSZ:
1430         case DT_RELAENT:
1431         case DT_SYMENT:
1432         case DT_RELENT:
1433         case DT_PLTPADSZ:
1434         case DT_MOVEENT:
1435         case DT_MOVESZ:
1436         case DT_INIT_ARRAYSZ:
1437         case DT_FINI_ARRAYSZ:
1438         case DT_SYMINSZ:
1439         case DT_SYMINENT:
1440         case DT_GNU_CONFLICTSZ:
1441         case DT_GNU_LIBLISTSZ:
1442           printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
1443           break;
1444
1445         case DT_VERDEFNUM:
1446         case DT_VERNEEDNUM:
1447         case DT_RELACOUNT:
1448         case DT_RELCOUNT:
1449           printf ("%" PRId64 "\n", dyn->d_un.d_val);
1450           break;
1451
1452         case DT_PLTREL:;
1453           const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
1454                                                       NULL, 0);
1455           puts (tagname ?: "???");
1456           break;
1457
1458         case DT_FLAGS:
1459           print_dt_flags (class, dyn->d_un.d_val);
1460           break;
1461
1462         case DT_FLAGS_1:
1463           print_dt_flags_1 (class, dyn->d_un.d_val);
1464           break;
1465
1466         case DT_FEATURE_1:
1467           print_dt_feature_1 (class, dyn->d_un.d_val);
1468           break;
1469
1470         case DT_POSFLAG_1:
1471           print_dt_posflag_1 (class, dyn->d_un.d_val);
1472           break;
1473
1474         default:
1475           printf ("%#0*" PRIx64 "\n",
1476                   class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
1477           break;
1478         }
1479     }
1480 }
1481
1482
1483 /* Print the dynamic segment.  */
1484 static void
1485 print_dynamic (Ebl *ebl)
1486 {
1487   for (size_t i = 0; i < phnum; ++i)
1488     {
1489       GElf_Phdr phdr_mem;
1490       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
1491
1492       if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
1493         {
1494           Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
1495           GElf_Shdr shdr_mem;
1496           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1497           if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
1498             handle_dynamic (ebl, scn, shdr);
1499           break;
1500         }
1501     }
1502 }
1503
1504
1505 /* Print relocations.  */
1506 static void
1507 print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
1508 {
1509   /* Find all relocation sections and handle them.  */
1510   Elf_Scn *scn = NULL;
1511
1512   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1513     {
1514        /* Handle the section if it is a symbol table.  */
1515       GElf_Shdr shdr_mem;
1516       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1517
1518       if (likely (shdr != NULL))
1519         {
1520           if (shdr->sh_type == SHT_REL)
1521             handle_relocs_rel (ebl, ehdr, scn, shdr);
1522           else if (shdr->sh_type == SHT_RELA)
1523             handle_relocs_rela (ebl, ehdr, scn, shdr);
1524         }
1525     }
1526 }
1527
1528
1529 /* Handle a relocation section.  */
1530 static void
1531 handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1532 {
1533   int class = gelf_getclass (ebl->elf);
1534   int nentries = shdr->sh_size / shdr->sh_entsize;
1535
1536   /* Get the data of the section.  */
1537   Elf_Data *data = elf_getdata (scn, NULL);
1538   if (data == NULL)
1539     return;
1540
1541   /* Get the symbol table information.  */
1542   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1543   GElf_Shdr symshdr_mem;
1544   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1545   Elf_Data *symdata = elf_getdata (symscn, NULL);
1546
1547   /* Get the section header of the section the relocations are for.  */
1548   GElf_Shdr destshdr_mem;
1549   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1550                                       &destshdr_mem);
1551
1552   if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
1553     {
1554       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1555               shdr->sh_offset);
1556       return;
1557     }
1558
1559   /* Search for the optional extended section index table.  */
1560   Elf_Data *xndxdata = NULL;
1561   int xndxscnidx = elf_scnshndx (scn);
1562   if (unlikely (xndxscnidx > 0))
1563     xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
1564
1565   /* Get the section header string table index.  */
1566   size_t shstrndx;
1567   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1568     error (EXIT_FAILURE, 0,
1569            gettext ("cannot get section header string table index"));
1570
1571   if (shdr->sh_info != 0)
1572     printf (ngettext ("\
1573 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1574                     "\
1575 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1576                       nentries),
1577             elf_ndxscn (scn),
1578             elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1579             (unsigned int) shdr->sh_info,
1580             elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1581             shdr->sh_offset,
1582             nentries);
1583   else
1584     /* The .rel.dyn section does not refer to a specific section but
1585        instead of section index zero.  Do not try to print a section
1586        name.  */
1587     printf (ngettext ("\
1588 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1589                     "\
1590 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1591                       nentries),
1592             (unsigned int) elf_ndxscn (scn),
1593             elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1594             shdr->sh_offset,
1595             nentries);
1596   fputs_unlocked (class == ELFCLASS32
1597                   ? gettext ("\
1598   Offset      Type                 Value       Name\n")
1599                   : gettext ("\
1600   Offset              Type                 Value               Name\n"),
1601          stdout);
1602
1603   int is_statically_linked = 0;
1604   for (int cnt = 0; cnt < nentries; ++cnt)
1605     {
1606       GElf_Rel relmem;
1607       GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
1608       if (likely (rel != NULL))
1609         {
1610           char buf[128];
1611           GElf_Sym symmem;
1612           Elf32_Word xndx;
1613           GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1614                                             GELF_R_SYM (rel->r_info),
1615                                             &symmem, &xndx);
1616           if (unlikely (sym == NULL))
1617             {
1618               /* As a special case we have to handle relocations in static
1619                  executables.  This only happens for IRELATIVE relocations
1620                  (so far).  There is no symbol table.  */
1621               if (is_statically_linked == 0)
1622                 {
1623                   /* Find the program header and look for a PT_INTERP entry. */
1624                   is_statically_linked = -1;
1625                   if (ehdr->e_type == ET_EXEC)
1626                     {
1627                       is_statically_linked = 1;
1628
1629                       for (size_t inner = 0; inner < phnum; ++inner)
1630                         {
1631                           GElf_Phdr phdr_mem;
1632                           GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
1633                                                           &phdr_mem);
1634                           if (phdr != NULL && phdr->p_type == PT_INTERP)
1635                             {
1636                               is_statically_linked = -1;
1637                               break;
1638                             }
1639                         }
1640                     }
1641                 }
1642
1643               if (is_statically_linked > 0 && shdr->sh_link == 0)
1644                 printf ("\
1645   %#0*" PRIx64 "  %-20s %*s  %s\n",
1646                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1647                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1648                         /* Avoid the leading R_ which isn't carrying any
1649                            information.  */
1650                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1651                                                buf, sizeof (buf)) + 2
1652                         : gettext ("<INVALID RELOC>"),
1653                         class == ELFCLASS32 ? 10 : 18, "",
1654                         elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1655               else
1656                 printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
1657                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1658                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1659                         /* Avoid the leading R_ which isn't carrying any
1660                            information.  */
1661                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1662                                                buf, sizeof (buf)) + 2
1663                         : gettext ("<INVALID RELOC>"),
1664                         gettext ("INVALID SYMBOL"),
1665                         (long int) GELF_R_SYM (rel->r_info));
1666             }
1667           else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1668             printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
1669                     class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1670                     likely (ebl_reloc_type_check (ebl,
1671                                                   GELF_R_TYPE (rel->r_info)))
1672                     /* Avoid the leading R_ which isn't carrying any
1673                        information.  */
1674                     ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1675                                            buf, sizeof (buf)) + 2
1676                     : gettext ("<INVALID RELOC>"),
1677                     class == ELFCLASS32 ? 10 : 18, sym->st_value,
1678                     elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1679           else
1680             {
1681               destshdr = gelf_getshdr (elf_getscn (ebl->elf,
1682                                                    sym->st_shndx == SHN_XINDEX
1683                                                    ? xndx : sym->st_shndx),
1684                                        &destshdr_mem);
1685
1686               if (unlikely (destshdr == NULL))
1687                 printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
1688                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1689                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1690                         /* Avoid the leading R_ which isn't carrying any
1691                            information.  */
1692                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1693                                                buf, sizeof (buf)) + 2
1694                         : gettext ("<INVALID RELOC>"),
1695                         gettext ("INVALID SECTION"),
1696                         (long int) (sym->st_shndx == SHN_XINDEX
1697                                     ? xndx : sym->st_shndx));
1698               else
1699                 printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
1700                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1701                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1702                         /* Avoid the leading R_ which isn't carrying any
1703                            information.  */
1704                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1705                                                buf, sizeof (buf)) + 2
1706                         : gettext ("<INVALID RELOC>"),
1707                         class == ELFCLASS32 ? 10 : 18, sym->st_value,
1708                         elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1709             }
1710         }
1711     }
1712 }
1713
1714
1715 /* Handle a relocation section.  */
1716 static void
1717 handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1718 {
1719   int class = gelf_getclass (ebl->elf);
1720   int nentries = shdr->sh_size / shdr->sh_entsize;
1721
1722   /* Get the data of the section.  */
1723   Elf_Data *data = elf_getdata (scn, NULL);
1724   if (data == NULL)
1725     return;
1726
1727   /* Get the symbol table information.  */
1728   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1729   GElf_Shdr symshdr_mem;
1730   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1731   Elf_Data *symdata = elf_getdata (symscn, NULL);
1732
1733   /* Get the section header of the section the relocations are for.  */
1734   GElf_Shdr destshdr_mem;
1735   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1736                                       &destshdr_mem);
1737
1738   if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
1739     {
1740       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1741               shdr->sh_offset);
1742       return;
1743     }
1744
1745   /* Search for the optional extended section index table.  */
1746   Elf_Data *xndxdata = NULL;
1747   int xndxscnidx = elf_scnshndx (scn);
1748   if (unlikely (xndxscnidx > 0))
1749     xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
1750
1751   /* Get the section header string table index.  */
1752   size_t shstrndx;
1753   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1754     error (EXIT_FAILURE, 0,
1755            gettext ("cannot get section header string table index"));
1756
1757   printf (ngettext ("\
1758 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1759                     "\
1760 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1761                     nentries),
1762           elf_ndxscn (scn),
1763           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1764           (unsigned int) shdr->sh_info,
1765           elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1766           shdr->sh_offset,
1767           nentries);
1768   fputs_unlocked (class == ELFCLASS32
1769                   ? gettext ("\
1770   Offset      Type            Value       Addend Name\n")
1771                   : gettext ("\
1772   Offset              Type            Value               Addend Name\n"),
1773                   stdout);
1774
1775   int is_statically_linked = 0;
1776   for (int cnt = 0; cnt < nentries; ++cnt)
1777     {
1778       GElf_Rela relmem;
1779       GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
1780       if (likely (rel != NULL))
1781         {
1782           char buf[64];
1783           GElf_Sym symmem;
1784           Elf32_Word xndx;
1785           GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1786                                             GELF_R_SYM (rel->r_info),
1787                                             &symmem, &xndx);
1788
1789           if (unlikely (sym == NULL))
1790             {
1791               /* As a special case we have to handle relocations in static
1792                  executables.  This only happens for IRELATIVE relocations
1793                  (so far).  There is no symbol table.  */
1794               if (is_statically_linked == 0)
1795                 {
1796                   /* Find the program header and look for a PT_INTERP entry. */
1797                   is_statically_linked = -1;
1798                   if (ehdr->e_type == ET_EXEC)
1799                     {
1800                       is_statically_linked = 1;
1801
1802                       for (size_t inner = 0; inner < phnum; ++inner)
1803                         {
1804                           GElf_Phdr phdr_mem;
1805                           GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
1806                                                           &phdr_mem);
1807                           if (phdr != NULL && phdr->p_type == PT_INTERP)
1808                             {
1809                               is_statically_linked = -1;
1810                               break;
1811                             }
1812                         }
1813                     }
1814                 }
1815
1816               if (is_statically_linked > 0 && shdr->sh_link == 0)
1817                 printf ("\
1818   %#0*" PRIx64 "  %-15s %*s  %#6" PRIx64 " %s\n",
1819                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1820                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1821                         /* Avoid the leading R_ which isn't carrying any
1822                            information.  */
1823                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1824                                                buf, sizeof (buf)) + 2
1825                         : gettext ("<INVALID RELOC>"),
1826                         class == ELFCLASS32 ? 10 : 18, "",
1827                         rel->r_addend,
1828                         elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1829               else
1830                 printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
1831                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1832                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1833                         /* Avoid the leading R_ which isn't carrying any
1834                            information.  */
1835                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1836                                                buf, sizeof (buf)) + 2
1837                         : gettext ("<INVALID RELOC>"),
1838                         gettext ("INVALID SYMBOL"),
1839                         (long int) GELF_R_SYM (rel->r_info));
1840             }
1841           else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1842             printf ("\
1843   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
1844                     class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1845                     likely (ebl_reloc_type_check (ebl,
1846                                                   GELF_R_TYPE (rel->r_info)))
1847                     /* Avoid the leading R_ which isn't carrying any
1848                        information.  */
1849                     ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1850                                            buf, sizeof (buf)) + 2
1851                     : gettext ("<INVALID RELOC>"),
1852                     class == ELFCLASS32 ? 10 : 18, sym->st_value,
1853                     rel->r_addend,
1854                     elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1855           else
1856             {
1857               destshdr = gelf_getshdr (elf_getscn (ebl->elf,
1858                                                    sym->st_shndx == SHN_XINDEX
1859                                                    ? xndx : sym->st_shndx),
1860                                        &destshdr_mem);
1861
1862               if (unlikely (shdr == NULL))
1863                 printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
1864                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1865                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1866                         /* Avoid the leading R_ which isn't carrying any
1867                            information.  */
1868                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1869                                                buf, sizeof (buf)) + 2
1870                         : gettext ("<INVALID RELOC>"),
1871                         gettext ("INVALID SECTION"),
1872                         (long int) (sym->st_shndx == SHN_XINDEX
1873                                     ? xndx : sym->st_shndx));
1874               else
1875                 printf ("\
1876   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
1877                         class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1878                         ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1879                         /* Avoid the leading R_ which isn't carrying any
1880                            information.  */
1881                         ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1882                                                buf, sizeof (buf)) + 2
1883                         : gettext ("<INVALID RELOC>"),
1884                         class == ELFCLASS32 ? 10 : 18, sym->st_value,
1885                         rel->r_addend,
1886                         elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1887             }
1888         }
1889     }
1890 }
1891
1892
1893 /* Print the program header.  */
1894 static void
1895 print_symtab (Ebl *ebl, int type)
1896 {
1897   /* Find the symbol table(s).  For this we have to search through the
1898      section table.  */
1899   Elf_Scn *scn = NULL;
1900
1901   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1902     {
1903       /* Handle the section if it is a symbol table.  */
1904       GElf_Shdr shdr_mem;
1905       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1906
1907       if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
1908         handle_symtab (ebl, scn, shdr);
1909     }
1910 }
1911
1912
1913 static void
1914 handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1915 {
1916   Elf_Data *versym_data = NULL;
1917   Elf_Data *verneed_data = NULL;
1918   Elf_Data *verdef_data = NULL;
1919   Elf_Data *xndx_data = NULL;
1920   int class = gelf_getclass (ebl->elf);
1921   Elf32_Word verneed_stridx = 0;
1922   Elf32_Word verdef_stridx = 0;
1923
1924   /* Get the data of the section.  */
1925   Elf_Data *data = elf_getdata (scn, NULL);
1926   if (data == NULL)
1927     return;
1928
1929   /* Find out whether we have other sections we might need.  */
1930   Elf_Scn *runscn = NULL;
1931   while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
1932     {
1933       GElf_Shdr runshdr_mem;
1934       GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
1935
1936       if (likely (runshdr != NULL))
1937         {
1938           if (runshdr->sh_type == SHT_GNU_versym
1939               && runshdr->sh_link == elf_ndxscn (scn))
1940             /* Bingo, found the version information.  Now get the data.  */
1941             versym_data = elf_getdata (runscn, NULL);
1942           else if (runshdr->sh_type == SHT_GNU_verneed)
1943             {
1944               /* This is the information about the needed versions.  */
1945               verneed_data = elf_getdata (runscn, NULL);
1946               verneed_stridx = runshdr->sh_link;
1947             }
1948           else if (runshdr->sh_type == SHT_GNU_verdef)
1949             {
1950               /* This is the information about the defined versions.  */
1951               verdef_data = elf_getdata (runscn, NULL);
1952               verdef_stridx = runshdr->sh_link;
1953             }
1954           else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
1955               && runshdr->sh_link == elf_ndxscn (scn))
1956             /* Extended section index.  */
1957             xndx_data = elf_getdata (runscn, NULL);
1958         }
1959     }
1960
1961   /* Get the section header string table index.  */
1962   size_t shstrndx;
1963   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1964     error (EXIT_FAILURE, 0,
1965            gettext ("cannot get section header string table index"));
1966
1967   /* Now we can compute the number of entries in the section.  */
1968   unsigned int nsyms = data->d_size / (class == ELFCLASS32
1969                                        ? sizeof (Elf32_Sym)
1970                                        : sizeof (Elf64_Sym));
1971
1972   printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
1973                     "\nSymbol table [%2u] '%s' contains %u entries:\n",
1974                     nsyms),
1975           (unsigned int) elf_ndxscn (scn),
1976           elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
1977   GElf_Shdr glink;
1978   printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
1979                     " %lu local symbols  String table: [%2u] '%s'\n",
1980                     shdr->sh_info),
1981           (unsigned long int) shdr->sh_info,
1982           (unsigned int) shdr->sh_link,
1983           elf_strptr (ebl->elf, shstrndx,
1984                       gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1985                                     &glink)->sh_name));
1986
1987   fputs_unlocked (class == ELFCLASS32
1988                   ? gettext ("\
1989   Num:    Value   Size Type    Bind   Vis          Ndx Name\n")
1990                   : gettext ("\
1991   Num:            Value   Size Type    Bind   Vis          Ndx Name\n"),
1992                   stdout);
1993
1994   for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
1995     {
1996       char typebuf[64];
1997       char bindbuf[64];
1998       char scnbuf[64];
1999       Elf32_Word xndx;
2000       GElf_Sym sym_mem;
2001       GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
2002
2003       if (unlikely (sym == NULL))
2004         continue;
2005
2006       /* Determine the real section index.  */
2007       if (likely (sym->st_shndx != SHN_XINDEX))
2008         xndx = sym->st_shndx;
2009
2010       printf (gettext ("\
2011 %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
2012               cnt,
2013               class == ELFCLASS32 ? 8 : 16,
2014               sym->st_value,
2015               sym->st_size,
2016               ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
2017                                     typebuf, sizeof (typebuf)),
2018               ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
2019                                        bindbuf, sizeof (bindbuf)),
2020               get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
2021               ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
2022                                 sizeof (scnbuf), NULL, shnum),
2023               elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
2024
2025       if (versym_data != NULL)
2026         {
2027           /* Get the version information.  */
2028           GElf_Versym versym_mem;
2029           GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
2030
2031           if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
2032             {
2033               bool is_nobits = false;
2034               bool check_def = xndx != SHN_UNDEF;
2035
2036               if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
2037                 {
2038                   GElf_Shdr symshdr_mem;
2039                   GElf_Shdr *symshdr =
2040                     gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
2041
2042                   is_nobits = (symshdr != NULL
2043                                && symshdr->sh_type == SHT_NOBITS);
2044                 }
2045
2046               if (is_nobits || ! check_def)
2047                 {
2048                   /* We must test both.  */
2049                   GElf_Vernaux vernaux_mem;
2050                   GElf_Vernaux *vernaux = NULL;
2051                   size_t vn_offset = 0;
2052
2053                   GElf_Verneed verneed_mem;
2054                   GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
2055                                                            &verneed_mem);
2056                   while (verneed != NULL)
2057                     {
2058                       size_t vna_offset = vn_offset;
2059
2060                       vernaux = gelf_getvernaux (verneed_data,
2061                                                  vna_offset += verneed->vn_aux,
2062                                                  &vernaux_mem);
2063                       while (vernaux != NULL
2064                              && vernaux->vna_other != *versym
2065                              && vernaux->vna_next != 0)
2066                         {
2067                           /* Update the offset.  */
2068                           vna_offset += vernaux->vna_next;
2069
2070                           vernaux = (vernaux->vna_next == 0
2071                                      ? NULL
2072                                      : gelf_getvernaux (verneed_data,
2073                                                         vna_offset,
2074                                                         &vernaux_mem));
2075                         }
2076
2077                       /* Check whether we found the version.  */
2078                       if (vernaux != NULL && vernaux->vna_other == *versym)
2079                         /* Found it.  */
2080                         break;
2081
2082                       vn_offset += verneed->vn_next;
2083                       verneed = (verneed->vn_next == 0
2084                                  ? NULL
2085                                  : gelf_getverneed (verneed_data, vn_offset,
2086                                                     &verneed_mem));
2087                     }
2088
2089                   if (vernaux != NULL && vernaux->vna_other == *versym)
2090                     {
2091                       printf ("@%s (%u)",
2092                               elf_strptr (ebl->elf, verneed_stridx,
2093                                           vernaux->vna_name),
2094                               (unsigned int) vernaux->vna_other);
2095                       check_def = 0;
2096                     }
2097                   else if (unlikely (! is_nobits))
2098                     error (0, 0, gettext ("bad dynamic symbol"));
2099                   else
2100                     check_def = 1;
2101                 }
2102
2103               if (check_def && *versym != 0x8001)
2104                 {
2105                   /* We must test both.  */
2106                   size_t vd_offset = 0;
2107
2108                   GElf_Verdef verdef_mem;
2109                   GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
2110                                                         &verdef_mem);
2111                   while (verdef != NULL)
2112                     {
2113                       if (verdef->vd_ndx == (*versym & 0x7fff))
2114                         /* Found the definition.  */
2115                         break;
2116
2117                       vd_offset += verdef->vd_next;
2118                       verdef = (verdef->vd_next == 0
2119                                 ? NULL
2120                                 : gelf_getverdef (verdef_data, vd_offset,
2121                                                   &verdef_mem));
2122                     }
2123
2124                   if (verdef != NULL)
2125                     {
2126                       GElf_Verdaux verdaux_mem;
2127                       GElf_Verdaux *verdaux
2128                         = gelf_getverdaux (verdef_data,
2129                                            vd_offset + verdef->vd_aux,
2130                                            &verdaux_mem);
2131
2132                       if (verdaux != NULL)
2133                         printf ((*versym & 0x8000) ? "@%s" : "@@%s",
2134                                 elf_strptr (ebl->elf, verdef_stridx,
2135                                             verdaux->vda_name));
2136                     }
2137                 }
2138             }
2139         }
2140
2141       putchar_unlocked ('\n');
2142     }
2143 }
2144
2145
2146 /* Print version information.  */
2147 static void
2148 print_verinfo (Ebl *ebl)
2149 {
2150   /* Find the version information sections.  For this we have to
2151      search through the section table.  */
2152   Elf_Scn *scn = NULL;
2153
2154   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2155     {
2156       /* Handle the section if it is part of the versioning handling.  */
2157       GElf_Shdr shdr_mem;
2158       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2159
2160       if (likely (shdr != NULL))
2161         {
2162           if (shdr->sh_type == SHT_GNU_verneed)
2163             handle_verneed (ebl, scn, shdr);
2164           else if (shdr->sh_type == SHT_GNU_verdef)
2165             handle_verdef (ebl, scn, shdr);
2166           else if (shdr->sh_type == SHT_GNU_versym)
2167             handle_versym (ebl, scn, shdr);
2168         }
2169     }
2170 }
2171
2172
2173 static const char *
2174 get_ver_flags (unsigned int flags)
2175 {
2176   static char buf[32];
2177   char *endp;
2178
2179   if (flags == 0)
2180     return gettext ("none");
2181
2182   if (flags & VER_FLG_BASE)
2183     endp = stpcpy (buf, "BASE ");
2184   else
2185     endp = buf;
2186
2187   if (flags & VER_FLG_WEAK)
2188     {
2189       if (endp != buf)
2190         endp = stpcpy (endp, "| ");
2191
2192       endp = stpcpy (endp, "WEAK ");
2193     }
2194
2195   if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
2196     {
2197       strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
2198       buf[sizeof (buf) - 1] = '\0';
2199     }
2200
2201   return buf;
2202 }
2203
2204
2205 static void
2206 handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2207 {
2208   int class = gelf_getclass (ebl->elf);
2209
2210   /* Get the data of the section.  */
2211   Elf_Data *data = elf_getdata (scn, NULL);
2212   if (data == NULL)
2213     return;
2214
2215   /* Get the section header string table index.  */
2216   size_t shstrndx;
2217   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2218     error (EXIT_FAILURE, 0,
2219            gettext ("cannot get section header string table index"));
2220
2221   GElf_Shdr glink;
2222   printf (ngettext ("\
2223 \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
2224                     "\
2225 \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
2226                     shdr->sh_info),
2227           (unsigned int) elf_ndxscn (scn),
2228           elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
2229           class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2230           shdr->sh_offset,
2231           (unsigned int) shdr->sh_link,
2232           elf_strptr (ebl->elf, shstrndx,
2233                       gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2234                                     &glink)->sh_name));
2235
2236   unsigned int offset = 0;
2237   for (int cnt = shdr->sh_info; --cnt >= 0; )
2238     {
2239       /* Get the data at the next offset.  */
2240       GElf_Verneed needmem;
2241       GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
2242       if (unlikely (need == NULL))
2243         break;
2244
2245       printf (gettext ("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
2246               offset, (unsigned short int) need->vn_version,
2247               elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
2248               (unsigned short int) need->vn_cnt);
2249
2250       unsigned int auxoffset = offset + need->vn_aux;
2251       for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2252         {
2253           GElf_Vernaux auxmem;
2254           GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
2255           if (unlikely (aux == NULL))
2256             break;
2257
2258           printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
2259                   auxoffset,
2260                   elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
2261                   get_ver_flags (aux->vna_flags),
2262                   (unsigned short int) aux->vna_other);
2263
2264           auxoffset += aux->vna_next;
2265         }
2266
2267       /* Find the next offset.  */
2268       offset += need->vn_next;
2269     }
2270 }
2271
2272
2273 static void
2274 handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2275 {
2276   /* Get the data of the section.  */
2277   Elf_Data *data = elf_getdata (scn, NULL);
2278   if (data == NULL)
2279     return;
2280
2281   /* Get the section header string table index.  */
2282   size_t shstrndx;
2283   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2284     error (EXIT_FAILURE, 0,
2285            gettext ("cannot get section header string table index"));
2286
2287   int class = gelf_getclass (ebl->elf);
2288   GElf_Shdr glink;
2289   printf (ngettext ("\
2290 \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
2291                     "\
2292 \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
2293                     shdr->sh_info),
2294           (unsigned int) elf_ndxscn (scn),
2295           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2296           shdr->sh_info,
2297           class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2298           shdr->sh_offset,
2299           (unsigned int) shdr->sh_link,
2300           elf_strptr (ebl->elf, shstrndx,
2301                       gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2302                                     &glink)->sh_name));
2303
2304   unsigned int offset = 0;
2305   for (int cnt = shdr->sh_info; --cnt >= 0; )
2306     {
2307       /* Get the data at the next offset.  */
2308       GElf_Verdef defmem;
2309       GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
2310       if (unlikely (def == NULL))
2311         break;
2312
2313       unsigned int auxoffset = offset + def->vd_aux;
2314       GElf_Verdaux auxmem;
2315       GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
2316       if (unlikely (aux == NULL))
2317         break;
2318
2319       printf (gettext ("\
2320   %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"),
2321               offset, def->vd_version,
2322               get_ver_flags (def->vd_flags),
2323               def->vd_ndx,
2324               def->vd_cnt,
2325               elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2326
2327       auxoffset += aux->vda_next;
2328       for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
2329         {
2330           aux = gelf_getverdaux (data, auxoffset, &auxmem);
2331           if (unlikely (aux == NULL))
2332             break;
2333
2334           printf (gettext ("  %#06x: Parent %d: %s\n"),
2335                   auxoffset, cnt2,
2336                   elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2337
2338           auxoffset += aux->vda_next;
2339         }
2340
2341       /* Find the next offset.  */
2342       offset += def->vd_next;
2343     }
2344 }
2345
2346
2347 static void
2348 handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2349 {
2350   int class = gelf_getclass (ebl->elf);
2351   const char **vername;
2352   const char **filename;
2353
2354   /* Get the data of the section.  */
2355   Elf_Data *data = elf_getdata (scn, NULL);
2356   if (data == NULL)
2357     return;
2358
2359   /* Get the section header string table index.  */
2360   size_t shstrndx;
2361   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2362     error (EXIT_FAILURE, 0,
2363            gettext ("cannot get section header string table index"));
2364
2365   /* We have to find the version definition section and extract the
2366      version names.  */
2367   Elf_Scn *defscn = NULL;
2368   Elf_Scn *needscn = NULL;
2369
2370   Elf_Scn *verscn = NULL;
2371   while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
2372     {
2373       GElf_Shdr vershdr_mem;
2374       GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
2375
2376       if (likely (vershdr != NULL))
2377         {
2378           if (vershdr->sh_type == SHT_GNU_verdef)
2379             defscn = verscn;
2380           else if (vershdr->sh_type == SHT_GNU_verneed)
2381             needscn = verscn;
2382         }
2383     }
2384
2385   size_t nvername;
2386   if (defscn != NULL || needscn != NULL)
2387     {
2388       /* We have a version information (better should have).  Now get
2389          the version names.  First find the maximum version number.  */
2390       nvername = 0;
2391       if (defscn != NULL)
2392         {
2393           /* Run through the version definitions and find the highest
2394              index.  */
2395           unsigned int offset = 0;
2396           Elf_Data *defdata;
2397           GElf_Shdr defshdrmem;
2398           GElf_Shdr *defshdr;
2399
2400           defdata = elf_getdata (defscn, NULL);
2401           if (unlikely (defdata == NULL))
2402             return;
2403
2404           defshdr = gelf_getshdr (defscn, &defshdrmem);
2405           if (unlikely (defshdr == NULL))
2406             return;
2407
2408           for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
2409             {
2410               GElf_Verdef defmem;
2411               GElf_Verdef *def;
2412
2413               /* Get the data at the next offset.  */
2414               def = gelf_getverdef (defdata, offset, &defmem);
2415               if (unlikely (def == NULL))
2416                 break;
2417
2418               nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
2419
2420               offset += def->vd_next;
2421             }
2422         }
2423       if (needscn != NULL)
2424         {
2425           unsigned int offset = 0;
2426           Elf_Data *needdata;
2427           GElf_Shdr needshdrmem;
2428           GElf_Shdr *needshdr;
2429
2430           needdata = elf_getdata (needscn, NULL);
2431           if (unlikely (needdata == NULL))
2432             return;
2433
2434           needshdr = gelf_getshdr (needscn, &needshdrmem);
2435           if (unlikely (needshdr == NULL))
2436             return;
2437
2438           for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
2439             {
2440               GElf_Verneed needmem;
2441               GElf_Verneed *need;
2442               unsigned int auxoffset;
2443               int cnt2;
2444
2445               /* Get the data at the next offset.  */
2446               need = gelf_getverneed (needdata, offset, &needmem);
2447               if (unlikely (need == NULL))
2448                 break;
2449
2450               /* Run through the auxiliary entries.  */
2451               auxoffset = offset + need->vn_aux;
2452               for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
2453                 {
2454                   GElf_Vernaux auxmem;
2455                   GElf_Vernaux *aux;
2456
2457                   aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
2458                   if (unlikely (aux == NULL))
2459                     break;
2460
2461                   nvername = MAX (nvername,
2462                                   (size_t) (aux->vna_other & 0x7fff));
2463
2464                   auxoffset += aux->vna_next;
2465                 }
2466
2467               offset += need->vn_next;
2468             }
2469         }
2470
2471       /* This is the number of versions we know about.  */
2472       ++nvername;
2473
2474       /* Allocate the array.  */
2475       vername = (const char **) alloca (nvername * sizeof (const char *));
2476       filename = (const char **) alloca (nvername * sizeof (const char *));
2477
2478       /* Run through the data structures again and collect the strings.  */
2479       if (defscn != NULL)
2480         {
2481           /* Run through the version definitions and find the highest
2482              index.  */
2483           unsigned int offset = 0;
2484           Elf_Data *defdata;
2485           GElf_Shdr defshdrmem;
2486           GElf_Shdr *defshdr;
2487
2488           defdata = elf_getdata (defscn, NULL);
2489           if (unlikely (defdata == NULL))
2490             return;
2491
2492           defshdr = gelf_getshdr (defscn, &defshdrmem);
2493           if (unlikely (defshdr == NULL))
2494             return;
2495
2496           for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
2497             {
2498
2499               /* Get the data at the next offset.  */
2500               GElf_Verdef defmem;
2501               GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
2502               GElf_Verdaux auxmem;
2503               GElf_Verdaux *aux = gelf_getverdaux (defdata,
2504                                                    offset + def->vd_aux,
2505                                                    &auxmem);
2506               if (unlikely (def == NULL || aux == NULL))
2507                 break;
2508
2509               vername[def->vd_ndx & 0x7fff]
2510                 = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
2511               filename[def->vd_ndx & 0x7fff] = NULL;
2512
2513               offset += def->vd_next;
2514             }
2515         }
2516       if (needscn != NULL)
2517         {
2518           unsigned int offset = 0;
2519
2520           Elf_Data *needdata = elf_getdata (needscn, NULL);
2521           GElf_Shdr needshdrmem;
2522           GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
2523           if (unlikely (needdata == NULL || needshdr == NULL))
2524             return;
2525
2526           for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
2527             {
2528               /* Get the data at the next offset.  */
2529               GElf_Verneed needmem;
2530               GElf_Verneed *need = gelf_getverneed (needdata, offset,
2531                                                     &needmem);
2532               if (unlikely (need == NULL))
2533                 break;
2534
2535               /* Run through the auxiliary entries.  */
2536               unsigned int auxoffset = offset + need->vn_aux;
2537               for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2538                 {
2539                   GElf_Vernaux auxmem;
2540                   GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
2541                                                        &auxmem);
2542                   if (unlikely (aux == NULL))
2543                     break;
2544
2545                   vername[aux->vna_other & 0x7fff]
2546                     = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
2547                   filename[aux->vna_other & 0x7fff]
2548                     = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
2549
2550                   auxoffset += aux->vna_next;
2551                 }
2552
2553               offset += need->vn_next;
2554             }
2555         }
2556     }
2557   else
2558     {
2559       vername = NULL;
2560       nvername = 1;
2561       filename = NULL;
2562     }
2563
2564   /* Print the header.  */
2565   GElf_Shdr glink;
2566   printf (ngettext ("\
2567 \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
2568                     "\
2569 \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
2570                     shdr->sh_size / shdr->sh_entsize),
2571           (unsigned int) elf_ndxscn (scn),
2572           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2573           (int) (shdr->sh_size / shdr->sh_entsize),
2574           class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2575           shdr->sh_offset,
2576           (unsigned int) shdr->sh_link,
2577           elf_strptr (ebl->elf, shstrndx,
2578                       gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2579                                     &glink)->sh_name));
2580
2581   /* Now we can finally look at the actual contents of this section.  */
2582   for (unsigned int cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
2583     {
2584       if (cnt % 2 == 0)
2585         printf ("\n %4d:", cnt);
2586
2587       GElf_Versym symmem;
2588       GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
2589       if (sym == NULL)
2590         break;
2591
2592       switch (*sym)
2593         {
2594           ssize_t n;
2595         case 0:
2596           fputs_unlocked (gettext ("   0 *local*                     "),
2597                           stdout);
2598           break;
2599
2600         case 1:
2601           fputs_unlocked (gettext ("   1 *global*                    "),
2602                           stdout);
2603           break;
2604
2605         default:
2606           n = printf ("%4d%c%s",
2607                       *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
2608                       (unsigned int) (*sym & 0x7fff) < nvername
2609                       ? vername[*sym & 0x7fff] : "???");
2610           if ((unsigned int) (*sym & 0x7fff) < nvername
2611               && filename[*sym & 0x7fff] != NULL)
2612             n += printf ("(%s)", filename[*sym & 0x7fff]);
2613           printf ("%*s", MAX (0, 33 - (int) n), " ");
2614           break;
2615         }
2616     }
2617   putchar_unlocked ('\n');
2618 }
2619
2620
2621 static void
2622 print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
2623                  uint_fast32_t maxlength, Elf32_Word nbucket,
2624                  uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
2625 {
2626   uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
2627
2628   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2629     ++counts[lengths[cnt]];
2630
2631   GElf_Shdr glink;
2632   printf (ngettext ("\
2633 \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",
2634                     "\
2635 \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",
2636                     nbucket),
2637           (unsigned int) elf_ndxscn (scn),
2638           elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2639           (int) nbucket,
2640           gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
2641           shdr->sh_addr,
2642           shdr->sh_offset,
2643           (unsigned int) shdr->sh_link,
2644           elf_strptr (ebl->elf, shstrndx,
2645                       gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2646                                     &glink)->sh_name));
2647
2648   if (extrastr != NULL)
2649     fputs (extrastr, stdout);
2650
2651   if (likely (nbucket > 0))
2652     {
2653       uint64_t success = 0;
2654
2655       /* xgettext:no-c-format */
2656       fputs_unlocked (gettext ("\
2657  Length  Number  % of total  Coverage\n"), stdout);
2658       printf (gettext ("      0  %6" PRIu32 "      %5.1f%%\n"),
2659               counts[0], (counts[0] * 100.0) / nbucket);
2660
2661       uint64_t nzero_counts = 0;
2662       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
2663         {
2664           nzero_counts += counts[cnt] * cnt;
2665           printf (gettext ("\
2666 %7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
2667                   (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
2668                   (nzero_counts * 100.0) / nsyms);
2669         }
2670
2671       Elf32_Word acc = 0;
2672       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
2673         {
2674           acc += cnt;
2675           success += counts[cnt] * acc;
2676         }
2677
2678       printf (gettext ("\
2679  Average number of tests:   successful lookup: %f\n\
2680                           unsuccessful lookup: %f\n"),
2681               (double) success / (double) nzero_counts,
2682               (double) nzero_counts / (double) nbucket);
2683     }
2684
2685   free (counts);
2686 }
2687
2688
2689 /* This function handles the traditional System V-style hash table format.  */
2690 static void
2691 handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2692 {
2693   Elf_Data *data = elf_getdata (scn, NULL);
2694   if (unlikely (data == NULL))
2695     {
2696       error (0, 0, gettext ("cannot get data for section %d: %s"),
2697              (int) elf_ndxscn (scn), elf_errmsg (-1));
2698       return;
2699     }
2700
2701   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
2702   Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
2703   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
2704   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
2705
2706   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2707
2708   uint_fast32_t maxlength = 0;
2709   uint_fast32_t nsyms = 0;
2710   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2711     {
2712       Elf32_Word inner = bucket[cnt];
2713       while (inner > 0 && inner < nchain)
2714         {
2715           ++nsyms;
2716           if (maxlength < ++lengths[cnt])
2717             ++maxlength;
2718
2719           inner = chain[inner];
2720         }
2721     }
2722
2723   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
2724                    lengths, NULL);
2725
2726   free (lengths);
2727 }
2728
2729
2730 /* This function handles the incorrect, System V-style hash table
2731    format some 64-bit architectures use.  */
2732 static void
2733 handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2734 {
2735   Elf_Data *data = elf_getdata (scn, NULL);
2736   if (unlikely (data == NULL))
2737     {
2738       error (0, 0, gettext ("cannot get data for section %d: %s"),
2739              (int) elf_ndxscn (scn), elf_errmsg (-1));
2740       return;
2741     }
2742
2743   Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
2744   Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
2745   Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
2746   Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
2747
2748   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2749
2750   uint_fast32_t maxlength = 0;
2751   uint_fast32_t nsyms = 0;
2752   for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
2753     {
2754       Elf64_Xword inner = bucket[cnt];
2755       while (inner > 0 && inner < nchain)
2756         {
2757           ++nsyms;
2758           if (maxlength < ++lengths[cnt])
2759             ++maxlength;
2760
2761           inner = chain[inner];
2762         }
2763     }
2764
2765   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
2766                    lengths, NULL);
2767
2768   free (lengths);
2769 }
2770
2771
2772 /* This function handles the GNU-style hash table format.  */
2773 static void
2774 handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2775 {
2776   Elf_Data *data = elf_getdata (scn, NULL);
2777   if (unlikely (data == NULL))
2778     {
2779       error (0, 0, gettext ("cannot get data for section %d: %s"),
2780              (int) elf_ndxscn (scn), elf_errmsg (-1));
2781       return;
2782     }
2783
2784   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
2785   Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
2786
2787   /* Next comes the size of the bitmap.  It's measured in words for
2788      the architecture.  It's 32 bits for 32 bit archs, and 64 bits for
2789      64 bit archs.  */
2790   Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
2791   if (gelf_getclass (ebl->elf) == ELFCLASS64)
2792     bitmask_words *= 2;
2793
2794   Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
2795
2796   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2797
2798   Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
2799   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
2800   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
2801                                                     + nbucket];
2802
2803   /* Compute distribution of chain lengths.  */
2804   uint_fast32_t maxlength = 0;
2805   uint_fast32_t nsyms = 0;
2806   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2807     if (bucket[cnt] != 0)
2808       {
2809         Elf32_Word inner = bucket[cnt] - symbias;
2810         do
2811           {
2812             ++nsyms;
2813             if (maxlength < ++lengths[cnt])
2814               ++maxlength;
2815           }
2816         while ((chain[inner++] & 1) == 0);
2817       }
2818
2819   /* Count bits in bitmask.  */
2820   uint_fast32_t nbits = 0;
2821   for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
2822     {
2823       uint_fast32_t word = bitmask[cnt];
2824
2825       word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
2826       word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
2827       word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
2828       word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
2829       nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
2830     }
2831
2832   char *str;
2833   if (unlikely (asprintf (&str, gettext ("\
2834  Symbol Bias: %u\n\
2835  Bitmask Size: %zu bytes  %" PRIuFAST32 "%% bits set  2nd hash shift: %u\n"),
2836                           (unsigned int) symbias,
2837                           bitmask_words * sizeof (Elf32_Word),
2838                           ((nbits * 100 + 50)
2839                            / (uint_fast32_t) (bitmask_words
2840                                               * sizeof (Elf32_Word) * 8)),
2841                           (unsigned int) shift) == -1))
2842     error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
2843
2844   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
2845                    lengths, str);
2846
2847   free (str);
2848   free (lengths);
2849 }
2850
2851
2852 /* Find the symbol table(s).  For this we have to search through the
2853    section table.  */
2854 static void
2855 handle_hash (Ebl *ebl)
2856 {
2857   /* Get the section header string table index.  */
2858   size_t shstrndx;
2859   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2860     error (EXIT_FAILURE, 0,
2861            gettext ("cannot get section header string table index"));
2862
2863   Elf_Scn *scn = NULL;
2864   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2865     {
2866       /* Handle the section if it is a symbol table.  */
2867       GElf_Shdr shdr_mem;
2868       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2869
2870       if (likely (shdr != NULL))
2871         {
2872           if (shdr->sh_type == SHT_HASH)
2873             {
2874               if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
2875                 handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
2876               else
2877                 handle_sysv_hash (ebl, scn, shdr, shstrndx);
2878             }
2879           else if (shdr->sh_type == SHT_GNU_HASH)
2880             handle_gnu_hash (ebl, scn, shdr, shstrndx);
2881         }
2882     }
2883 }
2884
2885
2886 static void
2887 print_liblist (Ebl *ebl)
2888 {
2889   /* Find the library list sections.  For this we have to search
2890      through the section table.  */
2891   Elf_Scn *scn = NULL;
2892
2893   /* Get the section header string table index.  */
2894   size_t shstrndx;
2895   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2896     error (EXIT_FAILURE, 0,
2897            gettext ("cannot get section header string table index"));
2898
2899   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2900     {
2901       GElf_Shdr shdr_mem;
2902       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2903
2904       if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
2905         {
2906           int nentries = shdr->sh_size / shdr->sh_entsize;
2907           printf (ngettext ("\
2908 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2909                             "\
2910 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2911                             nentries),
2912                   elf_ndxscn (scn),
2913                   elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2914                   shdr->sh_offset,
2915                   nentries);
2916
2917           Elf_Data *data = elf_getdata (scn, NULL);
2918           if (data == NULL)
2919             return;
2920
2921           puts (gettext ("\
2922        Library                       Time Stamp          Checksum Version Flags"));
2923
2924           for (int cnt = 0; cnt < nentries; ++cnt)
2925             {
2926               GElf_Lib lib_mem;
2927               GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
2928               if (unlikely (lib == NULL))
2929                 continue;
2930
2931               time_t t = (time_t) lib->l_time_stamp;
2932               struct tm *tm = gmtime (&t);
2933               if (unlikely (tm == NULL))
2934                 continue;
2935
2936               printf ("  [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
2937                       cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
2938                       tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
2939                       tm->tm_hour, tm->tm_min, tm->tm_sec,
2940                       (unsigned int) lib->l_checksum,
2941                       (unsigned int) lib->l_version,
2942                       (unsigned int) lib->l_flags);
2943             }
2944         }
2945     }
2946 }
2947
2948 static void
2949 print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
2950 {
2951   /* Find the object attributes sections.  For this we have to search
2952      through the section table.  */
2953   Elf_Scn *scn = NULL;
2954
2955   /* Get the section header string table index.  */
2956   size_t shstrndx;
2957   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2958     error (EXIT_FAILURE, 0,
2959            gettext ("cannot get section header string table index"));
2960
2961   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2962     {
2963       GElf_Shdr shdr_mem;
2964       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2965
2966       if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
2967                            && (shdr->sh_type != SHT_ARM_ATTRIBUTES
2968                                || ehdr->e_machine != EM_ARM)))
2969         continue;
2970
2971       printf (gettext ("\
2972 \nObject attributes section [%2zu] '%s' of %" PRIu64
2973                        " bytes at offset %#0" PRIx64 ":\n"),
2974               elf_ndxscn (scn),
2975               elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2976               shdr->sh_size, shdr->sh_offset);
2977
2978       Elf_Data *data = elf_rawdata (scn, NULL);
2979       if (data == NULL)
2980         return;
2981
2982       const unsigned char *p = data->d_buf;
2983
2984       if (unlikely (*p++ != 'A'))
2985         return;
2986
2987       fputs_unlocked (gettext ("  Owner          Size\n"), stdout);
2988
2989       inline size_t left (void)
2990       {
2991         return (const unsigned char *) data->d_buf + data->d_size - p;
2992       }
2993
2994       while (left () >= 4)
2995         {
2996           uint32_t len;
2997           memcpy (&len, p, sizeof len);
2998
2999           if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3000             CONVERT (len);
3001
3002           if (unlikely (len > left ()))
3003             break;
3004
3005           const unsigned char *name = p + sizeof len;
3006           p += len;
3007
3008           unsigned const char *q = memchr (name, '\0', len);
3009           if (unlikely (q == NULL))
3010             continue;
3011           ++q;
3012
3013           printf (gettext ("  %-13s  %4" PRIu32 "\n"), name, len);
3014
3015           if (shdr->sh_type != SHT_GNU_ATTRIBUTES
3016               || (q - name == sizeof "gnu"
3017                   && !memcmp (name, "gnu", sizeof "gnu")))
3018             while (q < p)
3019               {
3020                 const unsigned char *const sub = q;
3021
3022                 unsigned int subsection_tag;
3023                 get_uleb128 (subsection_tag, q);
3024                 if (unlikely (q >= p))
3025                   break;
3026
3027                 uint32_t subsection_len;
3028                 if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
3029                   break;
3030
3031                 memcpy (&subsection_len, q, sizeof subsection_len);
3032
3033                 if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3034                   CONVERT (subsection_len);
3035
3036                 if (unlikely (p - sub < (ptrdiff_t) subsection_len))
3037                   break;
3038
3039                 const unsigned char *r = q + sizeof subsection_len;
3040                 q = sub + subsection_len;
3041
3042                 switch (subsection_tag)
3043                   {
3044                   default:
3045                     printf (gettext ("    %-4u %12" PRIu32 "\n"),
3046                             subsection_tag, subsection_len);
3047                     break;
3048
3049                   case 1:       /* Tag_File */
3050                     printf (gettext ("    File: %11" PRIu32 "\n"),
3051                             subsection_len);
3052
3053                     while (r < q)
3054                       {
3055                         unsigned int tag;
3056                         get_uleb128 (tag, r);
3057                         if (unlikely (r >= q))
3058                           break;
3059
3060                         uint64_t value = 0;
3061                         const char *string = NULL;
3062                         if (tag == 32 || (tag & 1) == 0)
3063                           {
3064                             get_uleb128 (value, r);
3065                             if (r > q)
3066                               break;
3067                           }
3068                         if (tag == 32 || (tag & 1) != 0)
3069                           {
3070                             r = memchr (r, '\0', q - r);
3071                             if (r == NULL)
3072                               break;
3073                             ++r;
3074                           }
3075
3076                         const char *tag_name = NULL;
3077                         const char *value_name = NULL;
3078                         ebl_check_object_attribute (ebl, (const char *) name,
3079                                                     tag, value,
3080                                                     &tag_name, &value_name);
3081
3082                         if (tag_name != NULL)
3083                           {
3084                             if (tag == 32)
3085                               printf (gettext ("      %s: %" PRId64 ", %s\n"),
3086                                       tag_name, value, string);
3087                             else if (string == NULL && value_name == NULL)
3088                               printf (gettext ("      %s: %" PRId64 "\n"),
3089                                       tag_name, value);
3090                             else
3091                               printf (gettext ("      %s: %s\n"),
3092                                       tag_name, string ?: value_name);
3093                           }
3094                         else
3095                           {
3096                             assert (tag != 32);
3097                             if (string == NULL)
3098                               printf (gettext ("      %u: %" PRId64 "\n"),
3099                                       tag, value);
3100                             else
3101                               printf (gettext ("      %u: %s\n"),
3102                                       tag, string);
3103                           }
3104                       }
3105                   }
3106               }
3107         }
3108     }
3109 }
3110
3111
3112 static char *
3113 format_dwarf_addr (Dwfl_Module *dwflmod,
3114                    int address_size, Dwarf_Addr address)
3115 {
3116   /* See if there is a name we can give for this address.  */
3117   GElf_Sym sym;
3118   const char *name = print_address_names
3119     ? dwfl_module_addrsym (dwflmod, address, &sym, NULL) : NULL;
3120   if (name != NULL)
3121     sym.st_value = address - sym.st_value;
3122
3123   /* Relativize the address.  */
3124   int n = dwfl_module_relocations (dwflmod);
3125   int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
3126
3127   /* In an ET_REL file there is a section name to refer to.  */
3128   const char *scn = (i < 0 ? NULL
3129                      : dwfl_module_relocation_info (dwflmod, i, NULL));
3130
3131   char *result;
3132   if ((name != NULL
3133        ? (sym.st_value != 0
3134           ? (scn != NULL
3135              ? (address_size == 0
3136                 ? asprintf (&result,
3137                             gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
3138                             scn, address, name, sym.st_value)
3139                 : asprintf (&result,
3140                             gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
3141                             scn, 2 + address_size * 2, address,
3142                             name, sym.st_value))
3143              : (address_size == 0
3144                 ? asprintf (&result,
3145                             gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
3146                             address, name, sym.st_value)
3147                 : asprintf (&result,
3148                             gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
3149                             2 + address_size * 2, address,
3150                             name, sym.st_value)))
3151           : (scn != NULL
3152              ? (address_size == 0
3153                 ? asprintf (&result,
3154                             gettext ("%s+%#" PRIx64 " <%s>"),
3155                             scn, address, name)
3156                 : asprintf (&result,
3157                             gettext ("%s+%#0*" PRIx64 " <%s>"),
3158                             scn, 2 + address_size * 2, address, name))
3159              : (address_size == 0
3160                 ? asprintf (&result,
3161                             gettext ("%#" PRIx64 " <%s>"),
3162                             address, name)
3163                 : asprintf (&result,
3164                             gettext ("%#0*" PRIx64 " <%s>"),
3165                             2 + address_size * 2, address, name))))
3166        : (scn != NULL
3167           ? (address_size == 0
3168              ? asprintf (&result,
3169                          gettext ("%s+%#" PRIx64),
3170                          scn, address)
3171              : asprintf (&result,
3172                          gettext ("%s+%#0*" PRIx64),
3173                          scn, 2 + address_size * 2, address))
3174           : (address_size == 0
3175              ? asprintf (&result,
3176                          "%#" PRIx64,
3177                          address)
3178              : asprintf (&result,
3179                          "%#0*" PRIx64,
3180                          2 + address_size * 2, address)))) < 0)
3181     error (EXIT_FAILURE, 0, _("memory exhausted"));
3182
3183   return result;
3184 }
3185
3186 static const char *
3187 dwarf_tag_string (unsigned int tag)
3188 {
3189   switch (tag)
3190     {
3191 #define ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
3192       ALL_KNOWN_DW_TAG
3193 #undef ONE_KNOWN_DW_TAG
3194     default:
3195       return NULL;
3196     }
3197 }
3198
3199
3200 static const char *
3201 dwarf_attr_string (unsigned int attrnum)
3202 {
3203   switch (attrnum)
3204     {
3205 #define ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
3206       ALL_KNOWN_DW_AT
3207 #undef ONE_KNOWN_DW_AT
3208     default:
3209       return NULL;
3210     }
3211 }
3212
3213
3214 static const char *
3215 dwarf_form_string (unsigned int form)
3216 {
3217   switch (form)
3218     {
3219 #define ONE_KNOWN_DW_FORM_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_FORM (NAME, CODE)
3220 #define ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
3221       ALL_KNOWN_DW_FORM
3222 #undef ONE_KNOWN_DW_FORM
3223 #undef ONE_KNOWN_DW_FORM_DESC
3224     default:
3225       return NULL;
3226     }
3227 }
3228
3229
3230 static const char *
3231 dwarf_lang_string (unsigned int lang)
3232 {
3233   switch (lang)
3234     {
3235 #define ONE_KNOWN_DW_LANG_DESC(NAME, CODE, DESC) case CODE: return #NAME;
3236       ALL_KNOWN_DW_LANG
3237 #undef ONE_KNOWN_DW_LANG_DESC
3238     default:
3239       return NULL;
3240     }
3241 }
3242
3243
3244 static const char *
3245 dwarf_inline_string (unsigned int code)
3246 {
3247   static const char *const known[] =
3248     {
3249 #define ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME,
3250       ALL_KNOWN_DW_INL
3251 #undef ONE_KNOWN_DW_INL
3252     };
3253
3254   if (likely (code < sizeof (known) / sizeof (known[0])))
3255     return known[code];
3256
3257   return NULL;
3258 }
3259
3260
3261 static const char *
3262 dwarf_encoding_string (unsigned int code)
3263 {
3264   static const char *const known[] =
3265     {
3266 #define ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
3267       ALL_KNOWN_DW_ATE
3268 #undef ONE_KNOWN_DW_ATE
3269     };
3270
3271   if (likely (code < sizeof (known) / sizeof (known[0])))
3272     return known[code];
3273
3274   return NULL;
3275 }
3276
3277
3278 static const char *
3279 dwarf_access_string (unsigned int code)
3280 {
3281   static const char *const known[] =
3282     {
3283 #define ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME,
3284       ALL_KNOWN_DW_ACCESS
3285 #undef ONE_KNOWN_DW_ACCESS
3286     };
3287
3288   if (likely (code < sizeof (known) / sizeof (known[0])))
3289     return known[code];
3290
3291   return NULL;
3292 }
3293
3294
3295 static const char *
3296 dwarf_visibility_string (unsigned int code)
3297 {
3298   static const char *const known[] =
3299     {
3300 #define ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
3301       ALL_KNOWN_DW_VIS
3302 #undef ONE_KNOWN_DW_VIS
3303     };
3304
3305   if (likely (code < sizeof (known) / sizeof (known[0])))
3306     return known[code];
3307
3308   return NULL;
3309 }
3310
3311
3312 static const char *
3313 dwarf_virtuality_string (unsigned int code)
3314 {
3315   static const char *const known[] =
3316     {
3317 #define ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
3318       ALL_KNOWN_DW_VIRTUALITY
3319 #undef ONE_KNOWN_DW_VIRTUALITY
3320     };
3321
3322   if (likely (code < sizeof (known) / sizeof (known[0])))
3323     return known[code];
3324
3325   return NULL;
3326 }
3327
3328
3329 static const char *
3330 dwarf_identifier_case_string (unsigned int code)
3331 {
3332   static const char *const known[] =
3333     {
3334 #define ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
3335       ALL_KNOWN_DW_ID
3336 #undef ONE_KNOWN_DW_ID
3337     };
3338
3339   if (likely (code < sizeof (known) / sizeof (known[0])))
3340     return known[code];
3341
3342   return NULL;
3343 }
3344
3345
3346 static const char *
3347 dwarf_calling_convention_string (unsigned int code)
3348 {
3349   static const char *const known[] =
3350     {
3351 #define ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
3352       ALL_KNOWN_DW_CC
3353 #undef ONE_KNOWN_DW_CC
3354     };
3355
3356   if (likely (code < sizeof (known) / sizeof (known[0])))
3357     return known[code];
3358
3359   return NULL;
3360 }
3361
3362
3363 static const char *
3364 dwarf_ordering_string (unsigned int code)
3365 {
3366   static const char *const known[] =
3367     {
3368 #define ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
3369       ALL_KNOWN_DW_ORD
3370 #undef ONE_KNOWN_DW_ORD
3371     };
3372
3373   if (likely (code < sizeof (known) / sizeof (known[0])))
3374     return known[code];
3375
3376   return NULL;
3377 }
3378
3379
3380 static const char *
3381 dwarf_discr_list_string (unsigned int code)
3382 {
3383   static const char *const known[] =
3384     {
3385 #define ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
3386       ALL_KNOWN_DW_DSC
3387 #undef ONE_KNOWN_DW_DSC
3388     };
3389
3390   if (likely (code < sizeof (known) / sizeof (known[0])))
3391     return known[code];
3392
3393   return NULL;
3394 }
3395
3396
3397 static const char *
3398 dwarf_locexpr_opcode_string (unsigned int code)
3399 {
3400   static const char *const known[] =
3401     {
3402       /* Normally we can't affort building huge table of 64K entries,
3403          most of them zero, just because there are a couple defined
3404          values at the far end.  In case of opcodes, it's OK.  */
3405 #define ONE_KNOWN_DW_OP_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_OP (NAME, CODE)
3406 #define ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
3407       ALL_KNOWN_DW_OP
3408 #undef ONE_KNOWN_DW_OP
3409 #undef ONE_KNOWN_DW_OP_DESC
3410     };
3411
3412   if (likely (code < sizeof (known) / sizeof (known[0])))
3413     return known[code];
3414
3415   return NULL;
3416 }
3417
3418
3419 /* Used by all dwarf_foo_name functions.  */
3420 static const char *
3421 string_or_unknown (const char *known, unsigned int code,
3422                    unsigned int lo_user, unsigned int hi_user,
3423                    bool print_unknown_num)
3424 {
3425   static char unknown_buf[20];
3426
3427   if (likely (known != NULL))
3428     return known;
3429
3430   if (lo_user != 0 && code >= lo_user && code <= hi_user)
3431     {
3432       snprintf (unknown_buf, sizeof unknown_buf, "lo_user+%#x",
3433                 code - lo_user);
3434       return unknown_buf;
3435     }
3436
3437   if (print_unknown_num)
3438     {
3439       snprintf (unknown_buf, sizeof unknown_buf, "??? (%#x)", code);
3440       return unknown_buf;
3441     }
3442
3443   return "???";
3444 }
3445
3446
3447 static const char *
3448 dwarf_tag_name (unsigned int tag)
3449 {
3450   const char *ret = dwarf_tag_string (tag);
3451   return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true);
3452 }
3453
3454 static const char *
3455 dwarf_attr_name (unsigned int attr)
3456 {
3457   const char *ret = dwarf_attr_string (attr);
3458   return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true);
3459 }
3460
3461
3462 static const char *
3463 dwarf_form_name (unsigned int form)
3464 {
3465   const char *ret = dwarf_form_string (form);
3466   return string_or_unknown (ret, form, 0, 0, true);
3467 }
3468
3469
3470 static const char *
3471 dwarf_lang_name (unsigned int lang)
3472 {
3473   const char *ret = dwarf_lang_string (lang);
3474   return string_or_unknown (ret, lang, DW_LANG_lo_user, DW_LANG_hi_user, false);
3475 }
3476
3477
3478 static const char *
3479 dwarf_inline_name (unsigned int code)
3480 {
3481   const char *ret = dwarf_inline_string (code);
3482   return string_or_unknown (ret, code, 0, 0, false);
3483 }
3484
3485
3486 static const char *
3487 dwarf_encoding_name (unsigned int code)
3488 {
3489   const char *ret = dwarf_encoding_string (code);
3490   return string_or_unknown (ret, code, DW_ATE_lo_user, DW_ATE_hi_user, false);
3491 }
3492
3493
3494 static const char *
3495 dwarf_access_name (unsigned int code)
3496 {
3497   const char *ret = dwarf_access_string (code);
3498   return string_or_unknown (ret, code, 0, 0, false);
3499 }
3500
3501
3502 static const char *
3503 dwarf_visibility_name (unsigned int code)
3504 {
3505   const char *ret = dwarf_visibility_string (code);
3506   return string_or_unknown (ret, code, 0, 0, false);
3507 }
3508
3509
3510 static const char *
3511 dwarf_virtuality_name (unsigned int code)
3512 {
3513   const char *ret = dwarf_virtuality_string (code);
3514   return string_or_unknown (ret, code, 0, 0, false);
3515 }
3516
3517
3518 static const char *
3519 dwarf_identifier_case_name (unsigned int code)
3520 {
3521   const char *ret = dwarf_identifier_case_string (code);
3522   return string_or_unknown (ret, code, 0, 0, false);
3523 }
3524
3525
3526 static const char *
3527 dwarf_calling_convention_name (unsigned int code)
3528 {
3529   const char *ret = dwarf_calling_convention_string (code);
3530   return string_or_unknown (ret, code, DW_CC_lo_user, DW_CC_hi_user, false);
3531 }
3532
3533
3534 static const char *
3535 dwarf_ordering_name (unsigned int code)
3536 {
3537   const char *ret = dwarf_ordering_string (code);
3538   return string_or_unknown (ret, code, 0, 0, false);
3539 }
3540
3541
3542 static const char *
3543 dwarf_discr_list_name (unsigned int code)
3544 {
3545   const char *ret = dwarf_discr_list_string (code);
3546   return string_or_unknown (ret, code, 0, 0, false);
3547 }
3548
3549
3550 static void
3551 print_block (size_t n, const void *block)
3552 {
3553   if (n == 0)
3554     puts (_("empty block"));
3555   else
3556     {
3557       printf (_("%zu byte block:"), n);
3558       const unsigned char *data = block;
3559       do
3560         printf (" %02x", *data++);
3561       while (--n > 0);
3562       putchar ('\n');
3563     }
3564 }
3565
3566 static void
3567 print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
3568            unsigned int vers, unsigned int addrsize, unsigned int offset_size,
3569            Dwarf_Word len, const unsigned char *data)
3570 {
3571   const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
3572
3573   if (len == 0)
3574     {
3575       printf ("%*s(empty)\n", indent, "");
3576       return;
3577     }
3578
3579 #define NEED(n)         if (len < (Dwarf_Word) (n)) goto invalid
3580 #define CONSUME(n)      NEED (n); else len -= (n)
3581
3582   Dwarf_Word offset = 0;
3583   while (len-- > 0)
3584     {
3585       uint_fast8_t op = *data++;
3586
3587       const char *op_name = dwarf_locexpr_opcode_string (op);
3588       if (unlikely (op_name == NULL))
3589         {
3590           static char buf[20];
3591           if (op >= DW_OP_lo_user)
3592             snprintf (buf, sizeof buf, "lo_user+%#x", op - DW_OP_lo_user);
3593           else
3594             snprintf (buf, sizeof buf, "??? (%#x)", op);
3595           op_name = buf;
3596         }
3597
3598       switch (op)
3599         {
3600         case DW_OP_addr:;
3601           /* Address operand.  */
3602           Dwarf_Word addr;
3603           NEED (addrsize);
3604           if (addrsize == 4)
3605             addr = read_4ubyte_unaligned (dbg, data);
3606           else
3607             {
3608               assert (addrsize == 8);
3609               addr = read_8ubyte_unaligned (dbg, data);
3610             }
3611           data += addrsize;
3612           CONSUME (addrsize);
3613
3614           char *a = format_dwarf_addr (dwflmod, 0, addr);
3615           printf ("%*s[%4" PRIuMAX "] %s %s\n",
3616                   indent, "", (uintmax_t) offset, op_name, a);
3617           free (a);
3618
3619           offset += 1 + addrsize;
3620           break;
3621
3622         case DW_OP_call_ref:
3623           /* Offset operand.  */
3624           NEED (ref_size);
3625           if (ref_size == 4)
3626             addr = read_4ubyte_unaligned (dbg, data);
3627           else
3628             {
3629               assert (ref_size == 8);
3630               addr = read_8ubyte_unaligned (dbg, data);
3631             }
3632           data += ref_size;
3633           CONSUME (ref_size);
3634
3635           printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
3636                   indent, "", (uintmax_t) offset,
3637                   op_name, (uintmax_t) addr);
3638           offset += 1 + ref_size;
3639           break;
3640
3641         case DW_OP_deref_size:
3642         case DW_OP_xderef_size:
3643         case DW_OP_pick:
3644         case DW_OP_const1u:
3645           // XXX value might be modified by relocation
3646           NEED (1);
3647           printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
3648                   indent, "", (uintmax_t) offset,
3649                   op_name, *((uint8_t *) data));
3650           ++data;
3651           --len;
3652           offset += 2;
3653           break;
3654
3655         case DW_OP_const2u:
3656           NEED (2);
3657           // XXX value might be modified by relocation
3658           printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
3659                   indent, "", (uintmax_t) offset,
3660                   op_name, read_2ubyte_unaligned (dbg, data));
3661           CONSUME (2);
3662           data += 2;
3663           offset += 3;
3664           break;
3665
3666         case DW_OP_const4u:
3667           NEED (4);
3668           // XXX value might be modified by relocation
3669           printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
3670                   indent, "", (uintmax_t) offset,
3671                   op_name, read_4ubyte_unaligned (dbg, data));
3672           CONSUME (4);
3673           data += 4;
3674           offset += 5;
3675           break;
3676
3677         case DW_OP_const8u:
3678           NEED (8);
3679           // XXX value might be modified by relocation
3680           printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
3681                   indent, "", (uintmax_t) offset,
3682                   op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
3683           CONSUME (8);
3684           data += 8;
3685           offset += 9;
3686           break;
3687
3688         case DW_OP_const1s:
3689           NEED (1);
3690           // XXX value might be modified by relocation
3691           printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
3692                   indent, "", (uintmax_t) offset,
3693                   op_name, *((int8_t *) data));
3694           ++data;
3695           --len;
3696           offset += 2;
3697           break;
3698
3699         case DW_OP_const2s:
3700           NEED (2);
3701           // XXX value might be modified by relocation
3702           printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
3703                   indent, "", (uintmax_t) offset,
3704                   op_name, read_2sbyte_unaligned (dbg, data));
3705           CONSUME (2);
3706           data += 2;
3707           offset += 3;
3708           break;
3709
3710         case DW_OP_const4s:
3711           NEED (4);
3712           // XXX value might be modified by relocation
3713           printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
3714                   indent, "", (uintmax_t) offset,
3715                   op_name, read_4sbyte_unaligned (dbg, data));
3716           CONSUME (4);
3717           data += 4;
3718           offset += 5;
3719           break;
3720
3721         case DW_OP_const8s:
3722           NEED (8);
3723           // XXX value might be modified by relocation
3724           printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
3725                   indent, "", (uintmax_t) offset,
3726                   op_name, read_8sbyte_unaligned (dbg, data));
3727           CONSUME (8);
3728           data += 8;
3729           offset += 9;
3730           break;
3731
3732         case DW_OP_piece:
3733         case DW_OP_regx:
3734         case DW_OP_plus_uconst:
3735         case DW_OP_constu:;
3736           const unsigned char *start = data;
3737           uint64_t uleb;
3738           NEED (1);
3739           get_uleb128 (uleb, data); /* XXX check overrun */
3740           printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
3741                   indent, "", (uintmax_t) offset, op_name, uleb);
3742           CONSUME (data - start);
3743           offset += 1 + (data - start);
3744           break;
3745
3746         case DW_OP_bit_piece:
3747           start = data;
3748           uint64_t uleb2;
3749           NEED (2);
3750           get_uleb128 (uleb, data); /* XXX check overrun */
3751           get_uleb128 (uleb2, data); /* XXX check overrun */
3752           printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
3753                   indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
3754           CONSUME (data - start);
3755           offset += 1 + (data - start);
3756           break;
3757
3758         case DW_OP_fbreg:
3759         case DW_OP_breg0 ... DW_OP_breg31:
3760         case DW_OP_consts:
3761           start = data;
3762           int64_t sleb;
3763           NEED (1);
3764           get_sleb128 (sleb, data); /* XXX check overrun */
3765           printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
3766                   indent, "", (uintmax_t) offset, op_name, sleb);
3767           CONSUME (data - start);
3768           offset += 1 + (data - start);
3769           break;
3770
3771         case DW_OP_bregx:
3772           start = data;
3773           NEED (2);
3774           get_uleb128 (uleb, data); /* XXX check overrun */
3775           get_sleb128 (sleb, data); /* XXX check overrun */
3776           printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
3777                   indent, "", (uintmax_t) offset, op_name, uleb, sleb);
3778           CONSUME (data - start);
3779           offset += 1 + (data - start);
3780           break;
3781
3782         case DW_OP_call2:
3783           NEED (2);
3784           printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
3785                   indent, "", (uintmax_t) offset, op_name,
3786                   read_2ubyte_unaligned (dbg, data));
3787           CONSUME (2);
3788           offset += 3;
3789           break;
3790
3791         case DW_OP_call4:
3792           NEED (4);
3793           printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
3794                   indent, "", (uintmax_t) offset, op_name,
3795                   read_4ubyte_unaligned (dbg, data));
3796           CONSUME (4);
3797           offset += 5;
3798           break;
3799
3800         case DW_OP_skip:
3801         case DW_OP_bra:
3802           NEED (2);
3803           printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
3804                   indent, "", (uintmax_t) offset, op_name,
3805                   (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
3806           CONSUME (2);
3807           data += 2;
3808           offset += 3;
3809           break;
3810
3811         case DW_OP_implicit_value:
3812           start = data;
3813           NEED (1);
3814           get_uleb128 (uleb, data); /* XXX check overrun */
3815           printf ("%*s[%4" PRIuMAX "] %s: ",
3816                   indent, "", (uintmax_t) offset, op_name);
3817           NEED (uleb);
3818           print_block (uleb, data);
3819           data += uleb;
3820           CONSUME (data - start);
3821           offset += 1 + (data - start);
3822           break;
3823
3824         case DW_OP_GNU_implicit_pointer:
3825           /* DIE offset operand.  */
3826           start = data;
3827           NEED (ref_size + 1);
3828           if (ref_size == 4)
3829             addr = read_4ubyte_unaligned (dbg, data);
3830           else
3831             {
3832               assert (ref_size == 8);
3833               addr = read_8ubyte_unaligned (dbg, data);
3834             }
3835           data += ref_size;
3836           /* Byte offset operand.  */
3837           get_sleb128 (sleb, data); /* XXX check overrun */
3838
3839           printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX ", %+" PRId64 "\n",
3840                   indent, "", (intmax_t) offset,
3841                   op_name, (uintmax_t) addr, sleb);
3842           CONSUME (data - start);
3843           offset += 1 + (data - start);
3844           break;
3845
3846         case DW_OP_GNU_entry_value:
3847           /* Size plus expression block.  */
3848           start = data;
3849           NEED (1);
3850           get_uleb128 (uleb, data); /* XXX check overrun */
3851           printf ("%*s[%4" PRIuMAX "] %s:\n",
3852                   indent, "", (uintmax_t) offset, op_name);
3853           NEED (uleb);
3854           print_ops (dwflmod, dbg, indent + 6, indent + 6, vers,
3855                      addrsize, offset_size, uleb, data);
3856           data += uleb;
3857           CONSUME (data - start);
3858           offset += 1 + (data - start);
3859           break;
3860
3861         case DW_OP_GNU_const_type:
3862           /* DIE offset, size plus block.  */
3863           start = data;
3864           NEED (2);
3865           get_uleb128 (uleb, data); /* XXX check overrun */
3866           uint8_t usize = *(uint8_t *) data++;
3867           NEED (usize);
3868           printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] ",
3869                   indent, "", (uintmax_t) offset, op_name, uleb);
3870           print_block (usize, data);
3871           data += usize;
3872           CONSUME (data - start);
3873           offset += 1 + (data - start);
3874           break;
3875
3876         case DW_OP_GNU_regval_type:
3877           start = data;
3878           NEED (2);
3879           get_uleb128 (uleb, data); /* XXX check overrun */
3880           get_uleb128 (uleb2, data); /* XXX check overrun */
3881           printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %#" PRIx64 "\n",
3882                   indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
3883           CONSUME (data - start);
3884           offset += 1 + (data - start);
3885           break;
3886
3887         case DW_OP_GNU_deref_type:
3888           start = data;
3889           NEED (2);
3890           usize = *(uint8_t *) data++;
3891           get_uleb128 (uleb, data); /* XXX check overrun */
3892           printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
3893                   indent, "", (uintmax_t) offset,
3894                   op_name, usize, uleb);
3895           CONSUME (data - start);
3896           offset += 1 + (data - start);
3897           break;
3898
3899         case DW_OP_GNU_convert:
3900         case DW_OP_GNU_reinterpret:
3901           start = data;
3902           NEED (1);
3903           get_uleb128 (uleb, data); /* XXX check overrun */
3904           printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
3905                   indent, "", (uintmax_t) offset, op_name, uleb);
3906           CONSUME (data - start);
3907           offset += 1 + (data - start);
3908           break;
3909
3910         case DW_OP_GNU_parameter_ref:
3911           /* 4 byte CU relative reference to the abstract optimized away
3912              DW_TAG_formal_parameter.  */
3913           NEED (4);
3914           printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
3915                   indent, "", (uintmax_t) offset, op_name,
3916                   (uintmax_t) read_4ubyte_unaligned (dbg, data));
3917           CONSUME (4);
3918           data += 4;
3919           offset += 5;
3920           break;
3921
3922         default:
3923           /* No Operand.  */
3924           printf ("%*s[%4" PRIuMAX "] %s\n",
3925                   indent, "", (uintmax_t) offset, op_name);
3926           ++offset;
3927           break;
3928         }
3929
3930       indent = indentrest;
3931       continue;
3932
3933     invalid:
3934       printf (gettext ("%*s[%4" PRIuMAX "] %s  <TRUNCATED>\n"),
3935               indent, "", (uintmax_t) offset, op_name);
3936       break;
3937     }
3938 }
3939
3940
3941 struct listptr
3942 {
3943   Dwarf_Off offset:(64 - 3);
3944   bool addr64:1;
3945   bool dwarf64:1;
3946   bool warned:1;
3947 };
3948
3949 #define listptr_offset_size(p)  ((p)->dwarf64 ? 8 : 4)
3950 #define listptr_address_size(p) ((p)->addr64 ? 8 : 4)
3951
3952 static int
3953 compare_listptr (const void *a, const void *b, void *arg)
3954 {
3955   const char *name = arg;
3956   struct listptr *p1 = (void *) a;
3957   struct listptr *p2 = (void *) b;
3958
3959   if (p1->offset < p2->offset)
3960     return -1;
3961   if (p1->offset > p2->offset)
3962     return 1;
3963
3964   if (!p1->warned && !p2->warned)
3965     {
3966       if (p1->addr64 != p2->addr64)
3967         {
3968           p1->warned = p2->warned = true;
3969           error (0, 0,
3970                  gettext ("%s %#" PRIx64 " used with different address sizes"),
3971                  name, (uint64_t) p1->offset);
3972         }
3973       if (p1->dwarf64 != p2->dwarf64)
3974         {
3975           p1->warned = p2->warned = true;
3976           error (0, 0,
3977                  gettext ("%s %#" PRIx64 " used with different offset sizes"),
3978                  name, (uint64_t) p1->offset);
3979         }
3980     }
3981
3982   return 0;
3983 }
3984
3985 struct listptr_table
3986 {
3987   size_t n;
3988   size_t alloc;
3989   struct listptr *table;
3990 };
3991
3992 static struct listptr_table known_loclistptr;
3993 static struct listptr_table known_rangelistptr;
3994
3995 static void
3996 reset_listptr (struct listptr_table *table)
3997 {
3998   free (table->table);
3999   table->table = NULL;
4000   table->n = table->alloc = 0;
4001 }
4002
4003 static void
4004 notice_listptr (enum section_e section, struct listptr_table *table,
4005                 uint_fast8_t address_size, uint_fast8_t offset_size,
4006                 Dwarf_Off offset)
4007 {
4008   if (print_debug_sections & section)
4009     {
4010       if (table->n == table->alloc)
4011         {
4012           if (table->alloc == 0)
4013             table->alloc = 128;
4014           else
4015             table->alloc *= 2;
4016           table->table = xrealloc (table->table,
4017                                    table->alloc * sizeof table->table[0]);
4018         }
4019
4020       struct listptr *p = &table->table[table->n++];
4021
4022       *p = (struct listptr)
4023         {
4024           .addr64 = address_size == 8,
4025           .dwarf64 = offset_size == 8,
4026           .offset = offset
4027         };
4028       assert (p->offset == offset);
4029     }
4030 }
4031
4032 static void
4033 sort_listptr (struct listptr_table *table, const char *name)
4034 {
4035   if (table->n > 0)
4036     qsort_r (table->table, table->n, sizeof table->table[0],
4037              &compare_listptr, (void *) name);
4038 }
4039
4040 static bool
4041 skip_listptr_hole (struct listptr_table *table, size_t *idxp,
4042                    uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
4043                    ptrdiff_t offset, unsigned char **readp, unsigned char *endp)
4044 {
4045   if (table->n == 0)
4046     return false;
4047
4048   while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
4049     ++*idxp;
4050
4051   struct listptr *p = &table->table[*idxp];
4052
4053   if (*idxp == table->n
4054       || p->offset >= (Dwarf_Off) (endp - *readp + offset))
4055     {
4056       *readp = endp;
4057       printf (gettext (" [%6tx]  <UNUSED GARBAGE IN REST OF SECTION>\n"),
4058               offset);
4059       return true;
4060     }
4061
4062   if (p->offset != (Dwarf_Off) offset)
4063     {
4064       *readp += p->offset - offset;
4065       printf (gettext (" [%6tx]  <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
4066               offset, (Dwarf_Off) p->offset - offset);
4067       return true;
4068     }
4069
4070   if (address_sizep != NULL)
4071     *address_sizep = listptr_address_size (p);
4072   if (offset_sizep != NULL)
4073     *offset_sizep = listptr_offset_size (p);
4074
4075   return false;
4076 }
4077
4078
4079 static void
4080 print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
4081                             Ebl *ebl, GElf_Ehdr *ehdr,
4082                             Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
4083 {
4084   const size_t sh_size = (dbg->sectiondata[IDX_debug_abbrev] ?
4085                           dbg->sectiondata[IDX_debug_abbrev]->d_size : 0);
4086
4087   printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
4088                    " [ Code]\n"),
4089           elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4090           (uint64_t) shdr->sh_offset);
4091
4092   Dwarf_Off offset = 0;
4093   while (offset < sh_size)
4094     {
4095       printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
4096               offset);
4097
4098       while (1)
4099         {
4100           size_t length;
4101           Dwarf_Abbrev abbrev;
4102
4103           int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
4104           if (res != 0)
4105             {
4106               if (unlikely (res < 0))
4107                 {
4108                   printf (gettext ("\
4109  *** error while reading abbreviation: %s\n"),
4110                           dwarf_errmsg (-1));
4111                   return;
4112                 }
4113
4114               /* This is the NUL byte at the end of the section.  */
4115               ++offset;
4116               break;
4117             }
4118
4119           /* We know these calls can never fail.  */
4120           unsigned int code = dwarf_getabbrevcode (&abbrev);
4121           unsigned int tag = dwarf_getabbrevtag (&abbrev);
4122           int has_children = dwarf_abbrevhaschildren (&abbrev);
4123
4124           printf (gettext (" [%5u] offset: %" PRId64
4125                            ", children: %s, tag: %s\n"),
4126                   code, (int64_t) offset,
4127                   has_children ? gettext ("yes") : gettext ("no"),
4128                   dwarf_tag_name (tag));
4129
4130           size_t cnt = 0;
4131           unsigned int name;
4132           unsigned int form;
4133           Dwarf_Off enoffset;
4134           while (dwarf_getabbrevattr (&abbrev, cnt,
4135                                       &name, &form, &enoffset) == 0)
4136             {
4137               printf ("          attr: %s, form: %s, offset: %#" PRIx64 "\n",
4138                       dwarf_attr_name (name), dwarf_form_name (form),
4139                       (uint64_t) enoffset);
4140
4141               ++cnt;
4142             }
4143
4144           offset += length;
4145         }
4146     }
4147 }
4148
4149
4150 /* Print content of DWARF .debug_aranges section.  We fortunately do
4151    not have to know a bit about the structure of the section, libdwarf
4152    takes care of it.  */
4153 static void
4154 print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
4155                              Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4156                              GElf_Shdr *shdr, Dwarf *dbg)
4157 {
4158   Dwarf_Aranges *aranges;
4159   size_t cnt;
4160   if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
4161     {
4162       error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
4163              dwarf_errmsg (-1));
4164       return;
4165     }
4166
4167   printf (ngettext ("\
4168 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
4169                     "\
4170 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
4171                     cnt),
4172           elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4173           (uint64_t) shdr->sh_offset, cnt);
4174
4175   /* Compute floor(log16(cnt)).  */
4176   size_t tmp = cnt;
4177   int digits = 1;
4178   while (tmp >= 16)
4179     {
4180       ++digits;
4181       tmp >>= 4;
4182     }
4183
4184   for (size_t n = 0; n < cnt; ++n)
4185     {
4186       Dwarf_Arange *runp = dwarf_onearange (aranges, n);
4187       if (unlikely (runp == NULL))
4188         {
4189           printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
4190           return;
4191         }
4192
4193       Dwarf_Addr start;
4194       Dwarf_Word length;
4195       Dwarf_Off offset;
4196
4197       if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
4198         printf (gettext (" [%*zu] ???\n"), digits, n);
4199       else
4200         printf (gettext (" [%*zu] start: %0#*" PRIx64
4201                          ", length: %5" PRIu64 ", CU DIE offset: %6"
4202                          PRId64 "\n"),
4203                 digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
4204                 (uint64_t) start, (uint64_t) length, (int64_t) offset);
4205     }
4206 }
4207
4208 /* Print content of DWARF .debug_ranges section.  */
4209 static void
4210 print_debug_ranges_section (Dwfl_Module *dwflmod,
4211                             Ebl *ebl, GElf_Ehdr *ehdr,
4212                             Elf_Scn *scn, GElf_Shdr *shdr,
4213                             Dwarf *dbg)
4214 {
4215   Elf_Data *data = elf_rawdata (scn, NULL);
4216
4217   if (unlikely (data == NULL))
4218     {
4219       error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
4220              elf_errmsg (-1));
4221       return;
4222     }
4223
4224   printf (gettext ("\
4225 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
4226           elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4227           (uint64_t) shdr->sh_offset);
4228
4229   sort_listptr (&known_rangelistptr, "rangelistptr");
4230   size_t listptr_idx = 0;
4231
4232   uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
4233
4234   bool first = true;
4235   unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
4236   unsigned char *readp = data->d_buf;
4237   while (readp < endp)
4238     {
4239       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
4240
4241       if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
4242                                       &address_size, NULL,
4243                                       offset, &readp, endp))
4244         continue;
4245
4246       if (unlikely (data->d_size - offset < address_size * 2))
4247         {
4248           printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
4249           break;
4250         }
4251
4252       Dwarf_Addr begin;
4253       Dwarf_Addr end;
4254       if (address_size == 8)
4255         {
4256           begin = read_8ubyte_unaligned_inc (dbg, readp);
4257           end = read_8ubyte_unaligned_inc (dbg, readp);
4258         }
4259       else
4260         {
4261           begin = read_4ubyte_unaligned_inc (dbg, readp);
4262           end = read_4ubyte_unaligned_inc (dbg, readp);
4263           if (begin == (Dwarf_Addr) (uint32_t) -1)
4264             begin = (Dwarf_Addr) -1l;
4265         }
4266
4267       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
4268         {
4269           char *b = format_dwarf_addr (dwflmod, address_size, end);
4270           printf (gettext (" [%6tx]  base address %s\n"), offset, b);
4271           free (b);
4272         }
4273       else if (begin == 0 && end == 0) /* End of list entry.  */
4274         {
4275           if (first)
4276             printf (gettext (" [%6tx]  empty list\n"), offset);
4277           first = true;
4278         }
4279       else
4280         {
4281           char *b = format_dwarf_addr (dwflmod, address_size, begin);
4282           char *e = format_dwarf_addr (dwflmod, address_size, end);
4283           /* We have an address range entry.  */
4284           if (first)            /* First address range entry in a list.  */
4285             printf (gettext (" [%6tx]  %s..%s\n"), offset, b, e);
4286           else
4287             printf (gettext ("           %s..%s\n"), b, e);
4288           free (b);
4289           free (e);
4290
4291           first = false;
4292         }
4293     }
4294 }
4295
4296 #define REGNAMESZ 16
4297 static const char *
4298 register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
4299                char name[REGNAMESZ], int *bits, int *type)
4300 {
4301   const char *set;
4302   const char *pfx;
4303   int ignore;
4304   ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
4305                                  bits ?: &ignore, type ?: &ignore);
4306   if (n <= 0)
4307     {
4308       if (loc != NULL)
4309         snprintf (name, REGNAMESZ, "reg%u", loc->regno);
4310       else
4311         snprintf (name, REGNAMESZ, "??? 0x%x", regno);
4312       if (bits != NULL)
4313         *bits = loc != NULL ? loc->bits : 0;
4314       if (type != NULL)
4315         *type = DW_ATE_unsigned;
4316       set = "??? unrecognized";
4317     }
4318   else
4319     {
4320       if (bits != NULL && *bits <= 0)
4321         *bits = loc != NULL ? loc->bits : 0;
4322       if (type != NULL && *type == DW_ATE_void)
4323         *type = DW_ATE_unsigned;
4324
4325     }
4326   return set;
4327 }
4328
4329 static void
4330 print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
4331                    Dwarf_Word vma_base, unsigned int code_align,
4332                    int data_align,
4333                    unsigned int version, unsigned int ptr_size,
4334                    Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
4335 {
4336   char regnamebuf[REGNAMESZ];
4337   const char *regname (unsigned int regno)
4338   {
4339     register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
4340     return regnamebuf;
4341   }
4342
4343   puts ("\n   Program:");
4344   Dwarf_Word pc = vma_base;
4345   while (readp < endp)
4346     {
4347       unsigned int opcode = *readp++;
4348
4349       if (opcode < DW_CFA_advance_loc)
4350         /* Extended opcode.  */
4351         switch (opcode)
4352           {
4353             uint64_t op1;
4354             int64_t sop1;
4355             uint64_t op2;
4356             int64_t sop2;
4357
4358           case DW_CFA_nop:
4359             puts ("     nop");
4360             break;
4361           case DW_CFA_set_loc:
4362             // XXX overflow check
4363             get_uleb128 (op1, readp);
4364             op1 += vma_base;
4365             printf ("     set_loc %" PRIu64 "\n", op1 * code_align);
4366             break;
4367           case DW_CFA_advance_loc1:
4368             printf ("     advance_loc1 %u to %#" PRIx64 "\n",
4369                     *readp, pc += *readp * code_align);
4370             ++readp;
4371             break;
4372           case DW_CFA_advance_loc2:
4373             op1 = read_2ubyte_unaligned_inc (dbg, readp);
4374             printf ("     advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
4375                     op1, pc += op1 * code_align);
4376             break;
4377           case DW_CFA_advance_loc4:
4378             op1 = read_4ubyte_unaligned_inc (dbg, readp);
4379             printf ("     advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
4380                     op1, pc += op1 * code_align);
4381             break;
4382           case DW_CFA_offset_extended:
4383             // XXX overflow check
4384             get_uleb128 (op1, readp);
4385             get_uleb128 (op2, readp);
4386             printf ("     offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
4387                     "\n",
4388                     op1, regname (op1), op2 * data_align);
4389             break;
4390           case DW_CFA_restore_extended:
4391             // XXX overflow check
4392             get_uleb128 (op1, readp);
4393             printf ("     restore_extended r%" PRIu64 " (%s)\n",
4394                     op1, regname (op1));
4395             break;
4396           case DW_CFA_undefined:
4397             // XXX overflow check
4398             get_uleb128 (op1, readp);
4399             printf ("     undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
4400             break;
4401           case DW_CFA_same_value:
4402             // XXX overflow check
4403             get_uleb128 (op1, readp);
4404             printf ("     same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
4405             break;
4406           case DW_CFA_register:
4407             // XXX overflow check
4408             get_uleb128 (op1, readp);
4409             get_uleb128 (op2, readp);
4410             printf ("     register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
4411                     op1, regname (op1), op2, regname (op2));
4412             break;
4413           case DW_CFA_remember_state:
4414             puts ("     remember_state");
4415             break;
4416           case DW_CFA_restore_state:
4417             puts ("     restore_state");
4418             break;
4419           case DW_CFA_def_cfa:
4420             // XXX overflow check
4421             get_uleb128 (op1, readp);
4422             get_uleb128 (op2, readp);
4423             printf ("     def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
4424                     op1, regname (op1), op2);
4425             break;
4426           case DW_CFA_def_cfa_register:
4427             // XXX overflow check
4428             get_uleb128 (op1, readp);
4429             printf ("     def_cfa_register r%" PRIu64 " (%s)\n",
4430                     op1, regname (op1));
4431             break;
4432           case DW_CFA_def_cfa_offset:
4433             // XXX overflow check
4434             get_uleb128 (op1, readp);
4435             printf ("     def_cfa_offset %" PRIu64 "\n", op1);
4436             break;
4437           case DW_CFA_def_cfa_expression:
4438             // XXX overflow check
4439             get_uleb128 (op1, readp);   /* Length of DW_FORM_block.  */
4440             printf ("     def_cfa_expression %" PRIu64 "\n", op1);
4441             print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op1, readp);
4442             readp += op1;
4443             break;
4444           case DW_CFA_expression:
4445             // XXX overflow check
4446             get_uleb128 (op1, readp);
4447             get_uleb128 (op2, readp);   /* Length of DW_FORM_block.  */
4448             printf ("     expression r%" PRIu64 " (%s) \n",
4449                     op1, regname (op1));
4450             print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op2, readp);
4451             readp += op2;
4452             break;
4453           case DW_CFA_offset_extended_sf:
4454             // XXX overflow check
4455             get_uleb128 (op1, readp);
4456             get_sleb128 (sop2, readp);
4457             printf ("     offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
4458                     PRId64 "\n",
4459                     op1, regname (op1), sop2 * data_align);
4460             break;
4461           case DW_CFA_def_cfa_sf:
4462             // XXX overflow check
4463             get_uleb128 (op1, readp);
4464             get_sleb128 (sop2, readp);
4465             printf ("     def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
4466                     op1, regname (op1), sop2 * data_align);
4467             break;
4468           case DW_CFA_def_cfa_offset_sf:
4469             // XXX overflow check
4470             get_sleb128 (sop1, readp);
4471             printf ("     def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
4472             break;
4473           case DW_CFA_val_offset:
4474             // XXX overflow check
4475             get_uleb128 (op1, readp);
4476             get_uleb128 (op2, readp);
4477             printf ("     val_offset %" PRIu64 " at offset %" PRIu64 "\n",
4478                     op1, op2 * data_align);
4479             break;
4480           case DW_CFA_val_offset_sf:
4481             // XXX overflow check
4482             get_uleb128 (op1, readp);
4483             get_sleb128 (sop2, readp);
4484             printf ("     val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
4485                     op1, sop2 * data_align);
4486             break;
4487           case DW_CFA_val_expression:
4488             // XXX overflow check
4489             get_uleb128 (op1, readp);
4490             get_uleb128 (op2, readp);   /* Length of DW_FORM_block.  */
4491             printf ("     val_expression r%" PRIu64 " (%s)\n",
4492                     op1, regname (op1));
4493             print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op2, readp);
4494             readp += op2;
4495             break;
4496           case DW_CFA_MIPS_advance_loc8:
4497             op1 = read_8ubyte_unaligned_inc (dbg, readp);
4498             printf ("     MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
4499                     op1, pc += op1 * code_align);
4500             break;
4501           case DW_CFA_GNU_window_save:
4502             puts ("     GNU_window_save");
4503             break;
4504           case DW_CFA_GNU_args_size:
4505             // XXX overflow check
4506             get_uleb128 (op1, readp);
4507             printf ("     args_size %" PRIu64 "\n", op1);
4508             break;
4509           default:
4510             printf ("     ??? (%u)\n", opcode);
4511             break;
4512           }
4513       else if (opcode < DW_CFA_offset)
4514         printf ("     advance_loc %u to %#" PRIx64 "\n",
4515                 opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
4516       else if (opcode < DW_CFA_restore)
4517         {
4518           uint64_t offset;
4519           // XXX overflow check
4520           get_uleb128 (offset, readp);
4521           printf ("     offset r%u (%s) at cfa%+" PRId64 "\n",
4522                   opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
4523         }
4524       else
4525         printf ("     restore r%u (%s)\n",
4526                 opcode & 0x3f, regname (opcode & 0x3f));
4527     }
4528 }
4529
4530
4531 static unsigned int
4532 encoded_ptr_size (int encoding, unsigned int ptr_size)
4533 {
4534   switch (encoding & 7)
4535     {
4536     case 2:
4537       return 2;
4538     case 3:
4539       return 4;
4540     case 4:
4541       return 8;
4542     default:
4543       return ptr_size;
4544     }
4545 }
4546
4547
4548 static unsigned int
4549 print_encoding (unsigned int val)
4550 {
4551   switch (val & 0xf)
4552     {
4553     case DW_EH_PE_absptr:
4554       fputs ("absptr", stdout);
4555       break;
4556     case DW_EH_PE_uleb128:
4557       fputs ("uleb128", stdout);
4558       break;
4559     case DW_EH_PE_udata2:
4560       fputs ("udata2", stdout);
4561       break;
4562     case DW_EH_PE_udata4:
4563       fputs ("udata4", stdout);
4564       break;
4565     case DW_EH_PE_udata8:
4566       fputs ("udata8", stdout);
4567       break;
4568     case DW_EH_PE_sleb128:
4569       fputs ("sleb128", stdout);
4570       break;
4571     case DW_EH_PE_sdata2:
4572       fputs ("sdata2", stdout);
4573       break;
4574     case DW_EH_PE_sdata4:
4575       fputs ("sdata4", stdout);
4576       break;
4577     case DW_EH_PE_sdata8:
4578       fputs ("sdata8", stdout);
4579       break;
4580     default:
4581       /* We did not use any of the bits after all.  */
4582       return val;
4583     }
4584
4585   return val & ~0xf;
4586 }
4587
4588
4589 static unsigned int
4590 print_relinfo (unsigned int val)
4591 {
4592   switch (val & 0x70)
4593     {
4594     case DW_EH_PE_pcrel:
4595       fputs ("pcrel", stdout);
4596       break;
4597     case DW_EH_PE_textrel:
4598       fputs ("textrel", stdout);
4599       break;
4600     case DW_EH_PE_datarel:
4601       fputs ("datarel", stdout);
4602       break;
4603     case DW_EH_PE_funcrel:
4604       fputs ("funcrel", stdout);
4605       break;
4606     case DW_EH_PE_aligned:
4607       fputs ("aligned", stdout);
4608       break;
4609     default:
4610       return val;
4611     }
4612
4613   return val & ~0x70;
4614 }
4615
4616
4617 static void
4618 print_encoding_base (const char *pfx, unsigned int fde_encoding)
4619 {
4620   printf ("(%s", pfx);
4621
4622   if (fde_encoding == DW_EH_PE_omit)
4623     puts ("omit)");
4624   else
4625     {
4626       unsigned int w = fde_encoding;
4627
4628       w = print_encoding (w);
4629
4630       if (w & 0x70)
4631         {
4632           if (w != fde_encoding)
4633             fputc_unlocked (' ', stdout);
4634
4635           w = print_relinfo (w);
4636         }
4637
4638       if (w != 0)
4639         printf ("%s%x", w != fde_encoding ? " " : "", w);
4640
4641       puts (")");
4642     }
4643 }
4644
4645
4646 static const unsigned char *
4647 read_encoded (unsigned int encoding, const unsigned char *readp,
4648               const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
4649 {
4650   if ((encoding & 0xf) == DW_EH_PE_absptr)
4651     encoding = gelf_getclass (dbg->elf) == ELFCLASS32
4652       ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
4653
4654   switch (encoding & 0xf)
4655     {
4656     case DW_EH_PE_uleb128:
4657       // XXX buffer overrun check
4658       get_uleb128 (*res, readp);
4659       break;
4660     case DW_EH_PE_sleb128:
4661       // XXX buffer overrun check
4662       get_sleb128 (*res, readp);
4663       break;
4664     case DW_EH_PE_udata2:
4665       if (readp + 2 > endp)
4666         goto invalid;
4667       *res = read_2ubyte_unaligned_inc (dbg, readp);
4668       break;
4669     case DW_EH_PE_udata4:
4670       if (readp + 4 > endp)
4671         goto invalid;
4672       *res = read_4ubyte_unaligned_inc (dbg, readp);
4673       break;
4674     case DW_EH_PE_udata8:
4675       if (readp + 8 > endp)
4676         goto invalid;
4677       *res = read_8ubyte_unaligned_inc (dbg, readp);
4678       break;
4679     case DW_EH_PE_sdata2:
4680       if (readp + 2 > endp)
4681         goto invalid;
4682       *res = read_2sbyte_unaligned_inc (dbg, readp);
4683       break;
4684     case DW_EH_PE_sdata4:
4685       if (readp + 4 > endp)
4686         goto invalid;
4687       *res = read_4sbyte_unaligned_inc (dbg, readp);
4688       break;
4689     case DW_EH_PE_sdata8:
4690       if (readp + 8 > endp)
4691         goto invalid;
4692       *res = read_8sbyte_unaligned_inc (dbg, readp);
4693       break;
4694     default:
4695     invalid:
4696       error (1, 0,
4697              gettext ("invalid encoding"));
4698     }
4699
4700   return readp;
4701 }
4702
4703
4704 static void
4705 print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
4706                            Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
4707 {
4708   size_t shstrndx;
4709   /* We know this call will succeed since it did in the caller.  */
4710   (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
4711   const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
4712
4713   Elf_Data *data = elf_rawdata (scn, NULL);
4714
4715   if (unlikely (data == NULL))
4716     {
4717       error (0, 0, gettext ("cannot get %s content: %s"),
4718              scnname, elf_errmsg (-1));
4719       return;
4720     }
4721   bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
4722
4723   if (is_eh_frame)
4724     printf (gettext ("\
4725 \nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
4726             elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
4727   else
4728     printf (gettext ("\
4729 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
4730             elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
4731
4732   struct cieinfo
4733   {
4734     ptrdiff_t cie_offset;
4735     const char *augmentation;
4736     unsigned int code_alignment_factor;
4737     unsigned int data_alignment_factor;
4738     uint8_t address_size;
4739     uint8_t fde_encoding;
4740     uint8_t lsda_encoding;
4741     struct cieinfo *next;
4742   } *cies = NULL;
4743
4744   const unsigned char *readp = data->d_buf;
4745   const unsigned char *const dataend = ((unsigned char *) data->d_buf
4746                                         + data->d_size);
4747   while (readp < dataend)
4748     {
4749       if (unlikely (readp + 4 > dataend))
4750         {
4751         invalid_data:
4752           error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
4753                      elf_ndxscn (scn), scnname);
4754               return;
4755         }
4756
4757       /* At the beginning there must be a CIE.  There can be multiple,
4758          hence we test tis in a loop.  */
4759       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
4760
4761       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
4762       unsigned int length = 4;
4763       if (unlikely (unit_length == 0xffffffff))
4764         {
4765           if (unlikely (readp + 8 > dataend))
4766             goto invalid_data;
4767
4768           unit_length = read_8ubyte_unaligned_inc (dbg, readp);
4769           length = 8;
4770         }
4771
4772       if (unlikely (unit_length == 0))
4773         {
4774           printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
4775           continue;
4776         }
4777
4778       unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
4779
4780       ptrdiff_t start = readp - (unsigned char *) data->d_buf;
4781       const unsigned char *const cieend = readp + unit_length;
4782       if (unlikely (cieend > dataend || readp + 8 > dataend))
4783         goto invalid_data;
4784
4785       Dwarf_Off cie_id;
4786       if (length == 4)
4787         {
4788           cie_id = read_4ubyte_unaligned_inc (dbg, readp);
4789           if (!is_eh_frame && cie_id == DW_CIE_ID_32)
4790             cie_id = DW_CIE_ID_64;
4791         }
4792       else
4793         cie_id = read_8ubyte_unaligned_inc (dbg, readp);
4794
4795       uint_fast8_t version = 2;
4796       unsigned int code_alignment_factor;
4797       int data_alignment_factor;
4798       unsigned int fde_encoding = 0;
4799       unsigned int lsda_encoding = 0;
4800       Dwarf_Word initial_location = 0;
4801       Dwarf_Word vma_base = 0;
4802
4803       if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
4804         {
4805           version = *readp++;
4806           const char *const augmentation = (const char *) readp;
4807           readp = memchr (readp, '\0', cieend - readp);
4808           if (unlikely (readp == NULL))
4809             goto invalid_data;
4810           ++readp;
4811
4812           uint_fast8_t segment_size = 0;
4813           if (version >= 4)
4814             {
4815               if (cieend - readp < 5)
4816                 goto invalid_data;
4817               ptr_size = *readp++;
4818               segment_size = *readp++;
4819             }
4820
4821           // XXX Check overflow
4822           get_uleb128 (code_alignment_factor, readp);
4823           // XXX Check overflow
4824           get_sleb128 (data_alignment_factor, readp);
4825
4826           /* In some variant for unwind data there is another field.  */
4827           if (strcmp (augmentation, "eh") == 0)
4828             readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
4829
4830           unsigned int return_address_register;
4831           if (unlikely (version == 1))
4832             return_address_register = *readp++;
4833           else
4834             // XXX Check overflow
4835             get_uleb128 (return_address_register, readp);
4836
4837           printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
4838                   "   CIE_id:                   %" PRIu64 "\n"
4839                   "   version:                  %u\n"
4840                   "   augmentation:             \"%s\"\n",
4841                   offset, (uint64_t) unit_length, (uint64_t) cie_id,
4842                   version, augmentation);
4843           if (version >= 4)
4844             printf ("   address_size:             %u\n"
4845                     "   segment_size:             %u\n",
4846                     ptr_size, segment_size);
4847           printf ("   code_alignment_factor:    %u\n"
4848                   "   data_alignment_factor:    %d\n"
4849                   "   return_address_register:  %u\n",
4850                   code_alignment_factor,
4851                   data_alignment_factor, return_address_register);
4852
4853           if (augmentation[0] == 'z')
4854             {
4855               unsigned int augmentationlen;
4856               get_uleb128 (augmentationlen, readp);
4857
4858               if (augmentationlen > (size_t) (dataend - readp))
4859                 error (1, 0, gettext ("invalid augmentation length"));
4860
4861               const char *hdr = "Augmentation data:";
4862               const char *cp = augmentation + 1;
4863               while (*cp != '\0')
4864                 {
4865                   printf ("   %-26s%#x ", hdr, *readp);
4866                   hdr = "";
4867
4868                   if (*cp == 'R')
4869                     {
4870                       fde_encoding = *readp++;
4871                       print_encoding_base (gettext ("FDE address encoding: "),
4872                                            fde_encoding);
4873                     }
4874                   else if (*cp == 'L')
4875                     {
4876                       lsda_encoding = *readp++;
4877                       print_encoding_base (gettext ("LSDA pointer encoding: "),
4878                                            lsda_encoding);
4879                     }
4880                   else if (*cp == 'P')
4881                     {
4882                       /* Personality.  This field usually has a relocation
4883                          attached pointing to __gcc_personality_v0.  */
4884                       const unsigned char *startp = readp;
4885                       unsigned int encoding = *readp++;
4886                       uint64_t val = 0;
4887                       readp = read_encoded (encoding, readp,
4888                                             readp - 1 + augmentationlen,
4889                                             &val, dbg);
4890
4891                       while (++startp < readp)
4892                         printf ("%#x ", *startp);
4893
4894                       putchar ('(');
4895                       print_encoding (encoding);
4896                       putchar (' ');
4897                       switch (encoding & 0xf)
4898                         {
4899                         case DW_EH_PE_sleb128:
4900                         case DW_EH_PE_sdata2:
4901                         case DW_EH_PE_sdata4:
4902                           printf ("%" PRId64 ")\n", val);
4903                           break;
4904                         default:
4905                           printf ("%#" PRIx64 ")\n", val);
4906                           break;
4907                         }
4908                     }
4909                   else
4910                     printf ("(%x)\n", *readp++);
4911
4912                   ++cp;
4913                 }
4914             }
4915
4916           if (likely (ptr_size == 4 || ptr_size == 8))
4917             {
4918               struct cieinfo *newp = alloca (sizeof (*newp));
4919               newp->cie_offset = offset;
4920               newp->augmentation = augmentation;
4921               newp->fde_encoding = fde_encoding;
4922               newp->lsda_encoding = lsda_encoding;
4923               newp->address_size = ptr_size;
4924               newp->code_alignment_factor = code_alignment_factor;
4925               newp->data_alignment_factor = data_alignment_factor;
4926               newp->next = cies;
4927               cies = newp;
4928             }
4929         }
4930       else
4931         {
4932           struct cieinfo *cie = cies;
4933           while (cie != NULL)
4934             if (is_eh_frame
4935                 ? start - (ptrdiff_t) cie_id == cie->cie_offset
4936                 : (ptrdiff_t) cie_id == cie->cie_offset)
4937               break;
4938             else
4939               cie = cie->next;
4940           if (unlikely (cie == NULL))
4941             {
4942               puts ("invalid CIE reference in FDE");
4943               return;
4944             }
4945
4946           /* Initialize from CIE data.  */
4947           fde_encoding = cie->fde_encoding;
4948           lsda_encoding = cie->lsda_encoding;
4949           ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
4950           code_alignment_factor = cie->code_alignment_factor;
4951           data_alignment_factor = cie->data_alignment_factor;
4952
4953           const unsigned char *base = readp;
4954           // XXX There are sometimes relocations for this value
4955           initial_location = read_ubyte_unaligned_inc (ptr_size, dbg, readp);
4956           Dwarf_Word address_range
4957             = read_ubyte_unaligned_inc (ptr_size, dbg, readp);
4958
4959           char *a = format_dwarf_addr (dwflmod, cie->address_size,
4960                                        initial_location);
4961           printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
4962                   "   CIE_pointer:              %" PRIu64 "\n"
4963                   "   initial_location:         %s",
4964                   offset, (uint64_t) unit_length,
4965                   cie->cie_offset, (uint64_t) cie_id, a);
4966           free (a);
4967           if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
4968             {
4969               vma_base = (((uint64_t) shdr->sh_offset
4970                            + (base - (const unsigned char *) data->d_buf)
4971                            + (uint64_t) initial_location)
4972                           & (ptr_size == 4
4973                              ? UINT64_C (0xffffffff)
4974                              : UINT64_C (0xffffffffffffffff)));
4975               printf (gettext (" (offset: %#" PRIx64 ")"),
4976                       (uint64_t) vma_base);
4977             }
4978
4979           printf ("\n   address_range:            %#" PRIx64,
4980                   (uint64_t) address_range);
4981           if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
4982             printf (gettext (" (end offset: %#" PRIx64 ")"),
4983                     ((uint64_t) vma_base + (uint64_t) address_range)
4984                     & (ptr_size == 4
4985                        ? UINT64_C (0xffffffff)
4986                        : UINT64_C (0xffffffffffffffff)));
4987           putchar ('\n');
4988
4989           if (cie->augmentation[0] == 'z')
4990             {
4991               unsigned int augmentationlen;
4992               get_uleb128 (augmentationlen, readp);
4993
4994               if (augmentationlen > 0)
4995                 {
4996                   const char *hdr = "Augmentation data:";
4997                   const char *cp = cie->augmentation + 1;
4998                   unsigned int u = 0;
4999                   while (*cp != '\0')
5000                     {
5001                       if (*cp == 'L')
5002                         {
5003                           uint64_t lsda_pointer;
5004                           const unsigned char *p
5005                             = read_encoded (lsda_encoding, &readp[u],
5006                                             &readp[augmentationlen],
5007                                             &lsda_pointer, dbg);
5008                           u = p - readp;
5009                           printf (gettext ("\
5010    %-26sLSDA pointer: %#" PRIx64 "\n"),
5011                                   hdr, lsda_pointer);
5012                           hdr = "";
5013                         }
5014                       ++cp;
5015                     }
5016
5017                   while (u < augmentationlen)
5018                     {
5019                       printf ("   %-26s%#x\n", hdr, readp[u++]);
5020                       hdr = "";
5021                     }
5022                 }
5023
5024               readp += augmentationlen;
5025             }
5026         }
5027
5028       /* Handle the initialization instructions.  */
5029       print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
5030                          data_alignment_factor, version, ptr_size,
5031                          dwflmod, ebl, dbg);
5032       readp = cieend;
5033     }
5034 }
5035
5036
5037 struct attrcb_args
5038 {
5039   Dwfl_Module *dwflmod;
5040   Dwarf *dbg;
5041   int level;
5042   bool silent;
5043   unsigned int version;
5044   unsigned int addrsize;
5045   unsigned int offset_size;
5046   Dwarf_Off cu_offset;
5047 };
5048
5049
5050 static int
5051 attr_callback (Dwarf_Attribute *attrp, void *arg)
5052 {
5053   struct attrcb_args *cbargs = (struct attrcb_args *) arg;
5054   const int level = cbargs->level;
5055
5056   unsigned int attr = dwarf_whatattr (attrp);
5057   if (unlikely (attr == 0))
5058     {
5059       if (!cbargs->silent)
5060         error (0, 0, gettext ("cannot get attribute code: %s"),
5061                dwarf_errmsg (-1));
5062       return DWARF_CB_ABORT;
5063     }
5064
5065   unsigned int form = dwarf_whatform (attrp);
5066   if (unlikely (form == 0))
5067     {
5068       if (!cbargs->silent)
5069         error (0, 0, gettext ("cannot get attribute form: %s"),
5070                dwarf_errmsg (-1));
5071       return DWARF_CB_ABORT;
5072     }
5073
5074   switch (form)
5075     {
5076     case DW_FORM_addr:
5077       if (!cbargs->silent)
5078         {
5079           Dwarf_Addr addr;
5080           if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
5081             {
5082             attrval_out:
5083               if (!cbargs->silent)
5084                 error (0, 0, gettext ("cannot get attribute value: %s"),
5085                        dwarf_errmsg (-1));
5086               return DWARF_CB_ABORT;
5087             }
5088           char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr);
5089           printf ("           %*s%-20s (%s) %s\n",
5090                   (int) (level * 2), "", dwarf_attr_name (attr),
5091                   dwarf_form_name (form), a);
5092           free (a);
5093         }
5094       break;
5095
5096     case DW_FORM_indirect:
5097     case DW_FORM_strp:
5098     case DW_FORM_string:
5099     case DW_FORM_GNU_strp_alt:
5100       if (cbargs->silent)
5101         break;
5102       const char *str = dwarf_formstring (attrp);
5103       if (unlikely (str == NULL))
5104         goto attrval_out;
5105       printf ("           %*s%-20s (%s) \"%s\"\n",
5106               (int) (level * 2), "", dwarf_attr_name (attr),
5107               dwarf_form_name (form), str);
5108       break;
5109
5110     case DW_FORM_ref_addr:
5111     case DW_FORM_ref_udata:
5112     case DW_FORM_ref8:
5113     case DW_FORM_ref4:
5114     case DW_FORM_ref2:
5115     case DW_FORM_ref1:
5116     case DW_FORM_GNU_ref_alt:
5117       if (cbargs->silent)
5118         break;
5119       Dwarf_Die ref;
5120       if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
5121         goto attrval_out;
5122
5123       printf ("           %*s%-20s (%s) [%6" PRIxMAX "]\n",
5124               (int) (level * 2), "", dwarf_attr_name (attr),
5125               dwarf_form_name (form), (uintmax_t) dwarf_dieoffset (&ref));
5126       break;
5127
5128     case DW_FORM_ref_sig8:
5129       if (cbargs->silent)
5130         break;
5131       printf ("           %*s%-20s (%s) {%6" PRIx64 "}\n",
5132               (int) (level * 2), "", dwarf_attr_name (attr),
5133               dwarf_form_name (form),
5134               (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
5135       break;
5136
5137     case DW_FORM_sec_offset:
5138     case DW_FORM_udata:
5139     case DW_FORM_sdata:
5140     case DW_FORM_data8:
5141     case DW_FORM_data4:
5142     case DW_FORM_data2:
5143     case DW_FORM_data1:;
5144       Dwarf_Word num;
5145       if (unlikely (dwarf_formudata (attrp, &num) != 0))
5146         goto attrval_out;
5147
5148       const char *valuestr = NULL;
5149       switch (attr)
5150         {
5151           /* This case can take either a constant or a loclistptr.  */
5152         case DW_AT_data_member_location:
5153           if (form != DW_FORM_sec_offset
5154               && (cbargs->version >= 4
5155                   || (form != DW_FORM_data4 && form != DW_FORM_data8)))
5156             {
5157               if (!cbargs->silent)
5158                 printf ("           %*s%-20s (%s) %" PRIxMAX "\n",
5159                         (int) (level * 2), "", dwarf_attr_name (attr),
5160                         dwarf_form_name (form), (uintmax_t) num);
5161               return DWARF_CB_OK;
5162             }
5163           /* else fallthrough */
5164
5165         /* These cases always take a loclistptr and no constant. */
5166         case DW_AT_location:
5167         case DW_AT_data_location:
5168         case DW_AT_vtable_elem_location:
5169         case DW_AT_string_length:
5170         case DW_AT_use_location:
5171         case DW_AT_frame_base:
5172         case DW_AT_return_addr:
5173         case DW_AT_static_link:
5174         case DW_AT_GNU_call_site_value:
5175         case DW_AT_GNU_call_site_data_value:
5176         case DW_AT_GNU_call_site_target:
5177         case DW_AT_GNU_call_site_target_clobbered:
5178           notice_listptr (section_loc, &known_loclistptr,
5179                           cbargs->addrsize, cbargs->offset_size, num);
5180           if (!cbargs->silent)
5181             printf ("           %*s%-20s (%s) location list [%6" PRIxMAX "]\n",
5182                     (int) (level * 2), "", dwarf_attr_name (attr),
5183                     dwarf_form_name (form), (uintmax_t) num);
5184           return DWARF_CB_OK;
5185
5186         case DW_AT_ranges:
5187           notice_listptr (section_ranges, &known_rangelistptr,
5188                           cbargs->addrsize, cbargs->offset_size, num);
5189           if (!cbargs->silent)
5190             printf ("           %*s%-20s (%s) range list [%6" PRIxMAX "]\n",
5191                     (int) (level * 2), "", dwarf_attr_name (attr),
5192                     dwarf_form_name (form), (uintmax_t) num);
5193           return DWARF_CB_OK;
5194
5195         case DW_AT_language:
5196           valuestr = dwarf_lang_name (num);
5197           break;
5198         case DW_AT_encoding:
5199           valuestr = dwarf_encoding_name (num);
5200           break;
5201         case DW_AT_accessibility:
5202           valuestr = dwarf_access_name (num);
5203           break;
5204         case DW_AT_visibility:
5205           valuestr = dwarf_visibility_name (num);
5206           break;
5207         case DW_AT_virtuality:
5208           valuestr = dwarf_virtuality_name (num);
5209           break;
5210         case DW_AT_identifier_case:
5211           valuestr = dwarf_identifier_case_name (num);
5212           break;
5213         case DW_AT_calling_convention:
5214           valuestr = dwarf_calling_convention_name (num);
5215           break;
5216         case DW_AT_inline:
5217           valuestr = dwarf_inline_name (num);
5218           break;
5219         case DW_AT_ordering:
5220           valuestr = dwarf_ordering_name (num);
5221           break;
5222         case DW_AT_discr_list:
5223           valuestr = dwarf_discr_list_name (num);
5224           break;
5225         default:
5226           /* Nothing.  */
5227           break;
5228         }
5229
5230       if (cbargs->silent)
5231         break;
5232
5233       if (valuestr == NULL)
5234         printf ("           %*s%-20s (%s) %" PRIuMAX "\n",
5235                 (int) (level * 2), "", dwarf_attr_name (attr),
5236                 dwarf_form_name (form), (uintmax_t) num);
5237       else
5238         printf ("           %*s%-20s (%s) %s (%" PRIuMAX ")\n",
5239                 (int) (level * 2), "", dwarf_attr_name (attr),
5240                 dwarf_form_name (form), valuestr, (uintmax_t) num);
5241       break;
5242
5243     case DW_FORM_flag:
5244       if (cbargs->silent)
5245         break;
5246       bool flag;
5247       if (unlikely (dwarf_formflag (attrp, &flag) != 0))
5248         goto attrval_out;
5249
5250       printf ("           %*s%-20s (%s) %s\n",
5251               (int) (level * 2), "", dwarf_attr_name (attr),
5252               dwarf_form_name (form), nl_langinfo (flag ? YESSTR : NOSTR));
5253       break;
5254
5255     case DW_FORM_flag_present:
5256       if (cbargs->silent)
5257         break;
5258       printf ("           %*s%-20s (%s) %s\n",
5259               (int) (level * 2), "", dwarf_attr_name (attr),
5260               dwarf_form_name (form), nl_langinfo (YESSTR));
5261       break;
5262
5263     case DW_FORM_exprloc:
5264     case DW_FORM_block4:
5265     case DW_FORM_block2:
5266     case DW_FORM_block1:
5267     case DW_FORM_block:
5268       if (cbargs->silent)
5269         break;
5270       Dwarf_Block block;
5271       if (unlikely (dwarf_formblock (attrp, &block) != 0))
5272         goto attrval_out;
5273
5274       printf ("           %*s%-20s (%s) ",
5275               (int) (level * 2), "", dwarf_attr_name (attr),
5276               dwarf_form_name (form));
5277
5278       switch (attr)
5279         {
5280         default:
5281           if (form != DW_FORM_exprloc)
5282             {
5283               print_block (block.length, block.data);
5284               break;
5285             }
5286           /* Fall through.  */
5287
5288         case DW_AT_location:
5289         case DW_AT_data_location:
5290         case DW_AT_data_member_location:
5291         case DW_AT_vtable_elem_location:
5292         case DW_AT_string_length:
5293         case DW_AT_use_location:
5294         case DW_AT_frame_base:
5295         case DW_AT_return_addr:
5296         case DW_AT_static_link:
5297         case DW_AT_allocated:
5298         case DW_AT_associated:
5299         case DW_AT_bit_size:
5300         case DW_AT_bit_offset:
5301         case DW_AT_bit_stride:
5302         case DW_AT_byte_size:
5303         case DW_AT_byte_stride:
5304         case DW_AT_count:
5305         case DW_AT_lower_bound:
5306         case DW_AT_upper_bound:
5307         case DW_AT_GNU_call_site_value:
5308         case DW_AT_GNU_call_site_data_value:
5309         case DW_AT_GNU_call_site_target:
5310         case DW_AT_GNU_call_site_target_clobbered:
5311           putchar ('\n');
5312           print_ops (cbargs->dwflmod, cbargs->dbg,
5313                      12 + level * 2, 12 + level * 2,
5314                      cbargs->version, cbargs->addrsize, cbargs->offset_size,
5315                      block.length, block.data);
5316           break;
5317         }
5318       break;
5319
5320     default:
5321       if (cbargs->silent)
5322         break;
5323       printf ("           %*s%-20s (form: %#x) ???\n",
5324               (int) (level * 2), "", dwarf_attr_name (attr),
5325               (int) form);
5326       break;
5327     }
5328
5329   return DWARF_CB_OK;
5330 }
5331
5332 static void
5333 print_debug_units (Dwfl_Module *dwflmod,
5334                    Ebl *ebl, GElf_Ehdr *ehdr,
5335                    Elf_Scn *scn, GElf_Shdr *shdr,
5336                    Dwarf *dbg, bool debug_types)
5337 {
5338   const bool silent = !(print_debug_sections & section_info);
5339   const char *secname = section_name (ebl, ehdr, shdr);
5340
5341   if (!silent)
5342     printf (gettext ("\
5343 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
5344             elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
5345
5346   /* If the section is empty we don't have to do anything.  */
5347   if (!silent && shdr->sh_size == 0)
5348     return;
5349
5350   int maxdies = 20;
5351   Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
5352
5353   Dwarf_Off offset = 0;
5354
5355   /* New compilation unit.  */
5356   size_t cuhl;
5357   Dwarf_Half version;
5358   Dwarf_Off abbroffset;
5359   uint8_t addrsize;
5360   uint8_t offsize;
5361   Dwarf_Off nextcu;
5362   uint64_t typesig;
5363   Dwarf_Off typeoff;
5364  next_cu:
5365   if (dwarf_next_unit (dbg, offset, &nextcu, &cuhl, &version,
5366                        &abbroffset, &addrsize, &offsize,
5367                        debug_types ? &typesig : NULL,
5368                        debug_types ? &typeoff : NULL) != 0)
5369     goto do_return;
5370
5371   if (!silent)
5372     {
5373       if (debug_types)
5374         printf (gettext (" Type unit at offset %" PRIu64 ":\n"
5375                          " Version: %" PRIu16 ", Abbreviation section offset: %"
5376                          PRIu64 ", Address size: %" PRIu8
5377                          ", Offset size: %" PRIu8
5378                          "\n Type signature: %#" PRIx64
5379                          ", Type offset: %#" PRIx64 "\n"),
5380                 (uint64_t) offset, version, abbroffset, addrsize, offsize,
5381                 typesig, (uint64_t) typeoff);
5382       else
5383         printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
5384                          " Version: %" PRIu16 ", Abbreviation section offset: %"
5385                          PRIu64 ", Address size: %" PRIu8
5386                          ", Offset size: %" PRIu8 "\n"),
5387                 (uint64_t) offset, version, abbroffset, addrsize, offsize);
5388     }
5389
5390   struct attrcb_args args =
5391     {
5392       .dwflmod = dwflmod,
5393       .dbg = dbg,
5394       .silent = silent,
5395       .version = version,
5396       .addrsize = addrsize,
5397       .offset_size = offsize,
5398       .cu_offset = offset
5399     };
5400
5401   offset += cuhl;
5402
5403   int level = 0;
5404
5405   if (unlikely ((debug_types ? dwarf_offdie_types : dwarf_offdie)
5406                 (dbg, offset, &dies[level]) == NULL))
5407     {
5408       if (!silent)
5409         error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
5410                               " in section '%s': %s"),
5411                (uint64_t) offset, secname, dwarf_errmsg (-1));
5412       goto do_return;
5413     }
5414
5415   do
5416     {
5417       offset = dwarf_dieoffset (&dies[level]);
5418       if (unlikely (offset == ~0ul))
5419         {
5420           if (!silent)
5421             error (0, 0, gettext ("cannot get DIE offset: %s"),
5422                    dwarf_errmsg (-1));
5423           goto do_return;
5424         }
5425
5426       int tag = dwarf_tag (&dies[level]);
5427       if (unlikely (tag == DW_TAG_invalid))
5428         {
5429           if (!silent)
5430             error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
5431                                   " in section '%s': %s"),
5432                    (uint64_t) offset, secname, dwarf_errmsg (-1));
5433           goto do_return;
5434         }
5435
5436       if (!silent)
5437         printf (" [%6" PRIx64 "]  %*s%s\n",
5438                 (uint64_t) offset, (int) (level * 2), "",
5439                 dwarf_tag_name (tag));
5440
5441       /* Print the attribute values.  */
5442       args.level = level;
5443       (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
5444
5445       /* Make room for the next level's DIE.  */
5446       if (level + 1 == maxdies)
5447         dies = (Dwarf_Die *) xrealloc (dies,
5448                                        (maxdies += 10)
5449                                        * sizeof (Dwarf_Die));
5450
5451       int res = dwarf_child (&dies[level], &dies[level + 1]);
5452       if (res > 0)
5453         {
5454           while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
5455             if (level-- == 0)
5456               break;
5457
5458           if (unlikely (res == -1))
5459             {
5460               if (!silent)
5461                 error (0, 0, gettext ("cannot get next DIE: %s\n"),
5462                        dwarf_errmsg (-1));
5463               goto do_return;
5464             }
5465         }
5466       else if (unlikely (res < 0))
5467         {
5468           if (!silent)
5469             error (0, 0, gettext ("cannot get next DIE: %s"),
5470                    dwarf_errmsg (-1));
5471           goto do_return;
5472         }
5473       else
5474         ++level;
5475     }
5476   while (level >= 0);
5477
5478   offset = nextcu;
5479   if (offset != 0)
5480      goto next_cu;
5481
5482  do_return:
5483   free (dies);
5484 }
5485
5486 static void
5487 print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
5488                           Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5489 {
5490   print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
5491 }
5492
5493 static void
5494 print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
5495                            Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5496 {
5497   print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
5498 }
5499
5500
5501 static void
5502 print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
5503                           Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5504 {
5505   printf (gettext ("\
5506 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5507           elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
5508           (uint64_t) shdr->sh_offset);
5509
5510   if (shdr->sh_size == 0)
5511     return;
5512
5513   /* There is no functionality in libdw to read the information in the
5514      way it is represented here.  Hardcode the decoder.  */
5515   Elf_Data *data = elf_getdata (scn, NULL);
5516   if (unlikely (data == NULL || data->d_buf == NULL))
5517     {
5518       error (0, 0, gettext ("cannot get line data section data: %s"),
5519              elf_errmsg (-1));
5520       return;
5521     }
5522
5523   const unsigned char *linep = (const unsigned char *) data->d_buf;
5524   const unsigned char *lineendp;
5525
5526   while (linep
5527          < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
5528     {
5529       size_t start_offset = linep - (const unsigned char *) data->d_buf;
5530
5531       printf (gettext ("\nTable at offset %Zu:\n"), start_offset);
5532
5533       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
5534       unsigned int length = 4;
5535       if (unlikely (unit_length == 0xffffffff))
5536         {
5537           if (unlikely (linep + 8 > lineendp))
5538             {
5539             invalid_data:
5540               error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
5541                      elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
5542               return;
5543             }
5544           unit_length = read_8ubyte_unaligned_inc (dbg, linep);
5545           length = 8;
5546         }
5547
5548       /* Check whether we have enough room in the section.  */
5549       if (unit_length < 2 + length + 5 * 1
5550           || unlikely (linep + unit_length > lineendp))
5551         goto invalid_data;
5552       lineendp = linep + unit_length;
5553
5554       /* The next element of the header is the version identifier.  */
5555       uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
5556
5557       /* Next comes the header length.  */
5558       Dwarf_Word header_length;
5559       if (length == 4)
5560         header_length = read_4ubyte_unaligned_inc (dbg, linep);
5561       else
5562         header_length = read_8ubyte_unaligned_inc (dbg, linep);
5563       //const unsigned char *header_start = linep;
5564
5565       /* Next the minimum instruction length.  */
5566       uint_fast8_t minimum_instr_len = *linep++;
5567
5568       /* Next the maximum operations per instruction, in version 4 format.  */
5569       uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++;
5570
5571         /* Then the flag determining the default value of the is_stmt
5572            register.  */
5573       uint_fast8_t default_is_stmt = *linep++;
5574
5575       /* Now the line base.  */
5576       int_fast8_t line_base = *((const int_fast8_t *) linep);
5577       ++linep;
5578
5579       /* And the line range.  */
5580       uint_fast8_t line_range = *linep++;
5581
5582       /* The opcode base.  */
5583       uint_fast8_t opcode_base = *linep++;
5584
5585       /* Print what we got so far.  */
5586       printf (gettext ("\n"
5587                        " Length:                     %" PRIu64 "\n"
5588                        " DWARF version:              %" PRIuFAST16 "\n"
5589                        " Prologue length:            %" PRIu64 "\n"
5590                        " Minimum instruction length: %" PRIuFAST8 "\n"
5591                        " Maximum operations per instruction: %" PRIuFAST8 "\n"
5592                        " Initial value if '%s': %" PRIuFAST8 "\n"
5593                        " Line base:                  %" PRIdFAST8 "\n"
5594                        " Line range:                 %" PRIuFAST8 "\n"
5595                        " Opcode base:                %" PRIuFAST8 "\n"
5596                        "\n"
5597                        "Opcodes:\n"),
5598               (uint64_t) unit_length, version, (uint64_t) header_length,
5599               minimum_instr_len, max_ops_per_instr,
5600               "is_stmt", default_is_stmt, line_base,
5601               line_range, opcode_base);
5602
5603       if (unlikely (linep + opcode_base - 1 >= lineendp))
5604         {
5605         invalid_unit:
5606           error (0, 0,
5607                  gettext ("invalid data at offset %tu in section [%zu] '%s'"),
5608                  linep - (const unsigned char *) data->d_buf,
5609                  elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
5610           linep = lineendp;
5611           continue;
5612         }
5613       int opcode_base_l10 = 1;
5614       unsigned int tmp = opcode_base;
5615       while (tmp > 10)
5616         {
5617           tmp /= 10;
5618           ++opcode_base_l10;
5619         }
5620       const uint8_t *standard_opcode_lengths = linep - 1;
5621       for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
5622         printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
5623                           "  [%*" PRIuFAST8 "]  %hhu arguments\n",
5624                           (int) linep[cnt - 1]),
5625                 opcode_base_l10, cnt, linep[cnt - 1]);
5626       linep += opcode_base - 1;
5627       if (unlikely (linep >= lineendp))
5628         goto invalid_unit;
5629
5630       puts (gettext ("\nDirectory table:"));
5631       while (*linep != 0)
5632         {
5633           unsigned char *endp = memchr (linep, '\0', lineendp - linep);
5634           if (unlikely (endp == NULL))
5635             goto invalid_unit;
5636
5637           printf (" %s\n", (char *) linep);
5638
5639           linep = endp + 1;
5640         }
5641       /* Skip the final NUL byte.  */
5642       ++linep;
5643
5644       if (unlikely (linep >= lineendp))
5645         goto invalid_unit;
5646       puts (gettext ("\nFile name table:\n"
5647                      " Entry Dir   Time      Size      Name"));
5648       for (unsigned int cnt = 1; *linep != 0; ++cnt)
5649         {
5650           /* First comes the file name.  */
5651           char *fname = (char *) linep;
5652           unsigned char *endp = memchr (fname, '\0', lineendp - linep);
5653           if (unlikely (endp == NULL))
5654             goto invalid_unit;
5655           linep = endp + 1;
5656
5657           /* Then the index.  */
5658           unsigned int diridx;
5659           get_uleb128 (diridx, linep);
5660
5661           /* Next comes the modification time.  */
5662           unsigned int mtime;
5663           get_uleb128 (mtime, linep);
5664
5665           /* Finally the length of the file.  */
5666           unsigned int fsize;
5667           get_uleb128 (fsize, linep);
5668
5669           printf (" %-5u %-5u %-9u %-9u %s\n",
5670                   cnt, diridx, mtime, fsize, fname);
5671         }
5672       /* Skip the final NUL byte.  */
5673       ++linep;
5674
5675       puts (gettext ("\nLine number statements:"));
5676       Dwarf_Word address = 0;
5677       unsigned int op_index = 0;
5678       size_t line = 1;
5679       uint_fast8_t is_stmt = default_is_stmt;
5680
5681       /* Default address value, in case we do not find the CU.  */
5682       size_t address_size
5683         = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5684
5685       /* Determine the CU this block is for.  */
5686       Dwarf_Off cuoffset;
5687       Dwarf_Off ncuoffset = 0;
5688       size_t hsize;
5689       while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
5690                            NULL, NULL, NULL) == 0)
5691         {
5692           Dwarf_Die cudie;
5693           if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
5694             continue;
5695           Dwarf_Attribute stmt_list;
5696           if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
5697             continue;
5698           Dwarf_Word lineoff;
5699           if (dwarf_formudata (&stmt_list, &lineoff) != 0)
5700             continue;
5701           if (lineoff == start_offset)
5702             {
5703               /* Found the CU.  */
5704               address_size = cudie.cu->address_size;
5705               break;
5706             }
5707         }
5708
5709       /* Apply the "operation advance" from a special opcode
5710          or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
5711       unsigned int op_addr_advance;
5712       bool show_op_index;
5713       inline void advance_pc (unsigned int op_advance)
5714       {
5715         op_addr_advance = minimum_instr_len * ((op_index + op_advance)
5716                                                / max_ops_per_instr);
5717         address += op_advance;
5718         show_op_index = (op_index > 0 ||
5719                          (op_index + op_advance) % max_ops_per_instr > 0);
5720         op_index = (op_index + op_advance) % max_ops_per_instr;
5721       }
5722
5723       while (linep < lineendp)
5724         {
5725           size_t offset = linep - (const unsigned char *) data->d_buf;
5726           unsigned int u128;
5727           int s128;
5728
5729           /* Read the opcode.  */
5730           unsigned int opcode = *linep++;
5731
5732           printf (" [%6" PRIx64 "]", (uint64_t)offset);
5733           /* Is this a special opcode?  */
5734           if (likely (opcode >= opcode_base))
5735             {
5736               /* Yes.  Handling this is quite easy since the opcode value
5737                  is computed with
5738
5739                  opcode = (desired line increment - line_base)
5740                            + (line_range * address advance) + opcode_base
5741               */
5742               int line_increment = (line_base
5743                                     + (opcode - opcode_base) % line_range);
5744
5745               /* Perform the increments.  */
5746               line += line_increment;
5747               advance_pc ((opcode - opcode_base) / line_range);
5748
5749               char *a = format_dwarf_addr (dwflmod, 0, address);
5750               if (show_op_index)
5751                 printf (gettext ("\
5752  special opcode %u: address+%u = %s, op_index = %u, line%+d = %zu\n"),
5753                         opcode, op_addr_advance, a, op_index,
5754                         line_increment, line);
5755               else
5756                 printf (gettext ("\
5757  special opcode %u: address+%u = %s, line%+d = %zu\n"),
5758                         opcode, op_addr_advance, a, line_increment, line);
5759               free (a);
5760             }
5761           else if (opcode == 0)
5762             {
5763               /* This an extended opcode.  */
5764               if (unlikely (linep + 2 > lineendp))
5765                 goto invalid_unit;
5766
5767               /* The length.  */
5768               unsigned int len = *linep++;
5769
5770               if (unlikely (linep + len > lineendp))
5771                 goto invalid_unit;
5772
5773               /* The sub-opcode.  */
5774               opcode = *linep++;
5775
5776               printf (gettext (" extended opcode %u: "), opcode);
5777
5778               switch (opcode)
5779                 {
5780                 case DW_LNE_end_sequence:
5781                   puts (gettext (" end of sequence"));
5782
5783                   /* Reset the registers we care about.  */
5784                   address = 0;
5785                   op_index = 0;
5786                   line = 1;
5787                   is_stmt = default_is_stmt;
5788                   break;
5789
5790                 case DW_LNE_set_address:
5791                   op_index = 0;
5792                   if (address_size == 4)
5793                     address = read_4ubyte_unaligned_inc (dbg, linep);
5794                   else
5795                     address = read_8ubyte_unaligned_inc (dbg, linep);
5796                   {
5797                     char *a = format_dwarf_addr (dwflmod, 0, address);
5798                     printf (gettext (" set address to %s\n"), a);
5799                     free (a);
5800                   }
5801                   break;
5802
5803                 case DW_LNE_define_file:
5804                   {
5805                     char *fname = (char *) linep;
5806                     unsigned char *endp = memchr (linep, '\0',
5807                                                   lineendp - linep);
5808                     if (unlikely (endp == NULL))
5809                       goto invalid_unit;
5810                     linep = endp + 1;
5811
5812                     unsigned int diridx;
5813                     get_uleb128 (diridx, linep);
5814                     Dwarf_Word mtime;
5815                     get_uleb128 (mtime, linep);
5816                     Dwarf_Word filelength;
5817                     get_uleb128 (filelength, linep);
5818
5819                     printf (gettext ("\
5820  define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
5821                             diridx, (uint64_t) mtime, (uint64_t) filelength,
5822                             fname);
5823                   }
5824                   break;
5825
5826                 case DW_LNE_set_discriminator:
5827                   /* Takes one ULEB128 parameter, the discriminator.  */
5828                   if (unlikely (standard_opcode_lengths[opcode] != 1))
5829                     goto invalid_unit;
5830
5831                   get_uleb128 (u128, linep);
5832                   printf (gettext (" set discriminator to %u\n"), u128);
5833                   break;
5834
5835                 default:
5836                   /* Unknown, ignore it.  */
5837                   puts (gettext (" unknown opcode"));
5838                   linep += len - 1;
5839                   break;
5840                 }
5841             }
5842           else if (opcode <= DW_LNS_set_isa)
5843             {
5844               /* This is a known standard opcode.  */
5845               switch (opcode)
5846                 {
5847                 case DW_LNS_copy:
5848                   /* Takes no argument.  */
5849                   puts (gettext (" copy"));
5850                   break;
5851
5852                 case DW_LNS_advance_pc:
5853                   /* Takes one uleb128 parameter which is added to the
5854                      address.  */
5855                   get_uleb128 (u128, linep);
5856                   advance_pc (u128);
5857                   {
5858                     char *a = format_dwarf_addr (dwflmod, 0, address);
5859                     if (show_op_index)
5860                       printf (gettext ("\
5861  advance address by %u to %s, op_index to %u\n"),
5862                               op_addr_advance, a, op_index);
5863                     else
5864                       printf (gettext (" advance address by %u to %s\n"),
5865                               op_addr_advance, a);
5866                     free (a);
5867                   }
5868                   break;
5869
5870                 case DW_LNS_advance_line:
5871                   /* Takes one sleb128 parameter which is added to the
5872                      line.  */
5873                   get_sleb128 (s128, linep);
5874                   line += s128;
5875                   printf (gettext ("\
5876  advance line by constant %d to %" PRId64 "\n"),
5877                           s128, (int64_t) line);
5878                   break;
5879
5880                 case DW_LNS_set_file:
5881                   /* Takes one uleb128 parameter which is stored in file.  */
5882                   get_uleb128 (u128, linep);
5883                   printf (gettext (" set file to %" PRIu64 "\n"),
5884                           (uint64_t) u128);
5885                   break;
5886
5887                 case DW_LNS_set_column:
5888                   /* Takes one uleb128 parameter which is stored in column.  */
5889                   if (unlikely (standard_opcode_lengths[opcode] != 1))
5890                     goto invalid_unit;
5891
5892                   get_uleb128 (u128, linep);
5893                   printf (gettext (" set column to %" PRIu64 "\n"),
5894                           (uint64_t) u128);
5895                   break;
5896
5897                 case DW_LNS_negate_stmt:
5898                   /* Takes no argument.  */
5899                   is_stmt = 1 - is_stmt;
5900                   printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
5901                           "is_stmt", is_stmt);
5902                   break;
5903
5904                 case DW_LNS_set_basic_block:
5905                   /* Takes no argument.  */
5906                   puts (gettext (" set basic block flag"));
5907                   break;
5908
5909                 case DW_LNS_const_add_pc:
5910                   /* Takes no argument.  */
5911                   advance_pc ((255 - opcode_base) / line_range);
5912                   {
5913                     char *a = format_dwarf_addr (dwflmod, 0, address);
5914                     if (show_op_index)
5915                       printf (gettext ("\
5916  advance address by constant %u to %s, op_index to %u\n"),
5917                               op_addr_advance, a, op_index);
5918                     else
5919                       printf (gettext ("\
5920  advance address by constant %u to %s\n"),
5921                               op_addr_advance, a);
5922                     free (a);
5923                   }
5924                   break;
5925
5926                 case DW_LNS_fixed_advance_pc:
5927                   /* Takes one 16 bit parameter which is added to the
5928                      address.  */
5929                   if (unlikely (standard_opcode_lengths[opcode] != 1))
5930                     goto invalid_unit;
5931
5932                   u128 = read_2ubyte_unaligned_inc (dbg, linep);
5933                   address += u128;
5934                   op_index = 0;
5935                   {
5936                     char *a = format_dwarf_addr (dwflmod, 0, address);
5937                     printf (gettext ("\
5938  advance address by fixed value %u to %s\n"),
5939                             u128, a);
5940                     free (a);
5941                   }
5942                   break;
5943
5944                 case DW_LNS_set_prologue_end:
5945                   /* Takes no argument.  */
5946                   puts (gettext (" set prologue end flag"));
5947                   break;
5948
5949                 case DW_LNS_set_epilogue_begin:
5950                   /* Takes no argument.  */
5951                   puts (gettext (" set epilogue begin flag"));
5952                   break;
5953
5954                 case DW_LNS_set_isa:
5955                   /* Takes one uleb128 parameter which is stored in isa.  */
5956                   if (unlikely (standard_opcode_lengths[opcode] != 1))
5957                     goto invalid_unit;
5958
5959                   get_uleb128 (u128, linep);
5960                   printf (gettext (" set isa to %u\n"), u128);
5961                   break;
5962                 }
5963             }
5964           else
5965             {
5966               /* This is a new opcode the generator but not we know about.
5967                  Read the parameters associated with it but then discard
5968                  everything.  Read all the parameters for this opcode.  */
5969               printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
5970                                 " unknown opcode with %" PRIu8 " parameters:",
5971                                 standard_opcode_lengths[opcode]),
5972                       standard_opcode_lengths[opcode]);
5973               for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
5974                 {
5975                   get_uleb128 (u128, linep);
5976                   if (n != standard_opcode_lengths[opcode])
5977                     putc_unlocked (',', stdout);
5978                   printf (" %u", u128);
5979                 }
5980
5981               /* Next round, ignore this opcode.  */
5982               continue;
5983             }
5984         }
5985     }
5986
5987   /* There must only be one data block.  */
5988   assert (elf_getdata (scn, data) == NULL);
5989 }
5990
5991
5992 static void
5993 print_debug_loc_section (Dwfl_Module *dwflmod,
5994                          Ebl *ebl, GElf_Ehdr *ehdr,
5995                          Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5996 {
5997   Elf_Data *data = elf_rawdata (scn, NULL);
5998
5999   if (unlikely (data == NULL))
6000     {
6001       error (0, 0, gettext ("cannot get .debug_loc content: %s"),
6002              elf_errmsg (-1));
6003       return;
6004     }
6005
6006   printf (gettext ("\
6007 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6008           elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6009           (uint64_t) shdr->sh_offset);
6010
6011   sort_listptr (&known_loclistptr, "loclistptr");
6012   size_t listptr_idx = 0;
6013
6014   uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6015   uint_fast8_t offset_size = 4;
6016
6017   bool first = true;
6018   unsigned char *readp = data->d_buf;
6019   unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
6020   while (readp < endp)
6021     {
6022       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
6023
6024       if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx,
6025                                       &address_size, &offset_size,
6026                                       offset, &readp, endp))
6027         continue;
6028
6029       if (unlikely (data->d_size - offset < address_size * 2))
6030         {
6031           printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
6032           break;
6033         }
6034
6035       Dwarf_Addr begin;
6036       Dwarf_Addr end;
6037       if (address_size == 8)
6038         {
6039           begin = read_8ubyte_unaligned_inc (dbg, readp);
6040           end = read_8ubyte_unaligned_inc (dbg, readp);
6041         }
6042       else
6043         {
6044           begin = read_4ubyte_unaligned_inc (dbg, readp);
6045           end = read_4ubyte_unaligned_inc (dbg, readp);
6046           if (begin == (Dwarf_Addr) (uint32_t) -1)
6047             begin = (Dwarf_Addr) -1l;
6048         }
6049
6050       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
6051         {
6052           char *b = format_dwarf_addr (dwflmod, address_size, end);
6053           printf (gettext (" [%6tx]  base address %s\n"), offset, b);
6054           free (b);
6055         }
6056       else if (begin == 0 && end == 0) /* End of list entry.  */
6057         {
6058           if (first)
6059             printf (gettext (" [%6tx]  empty list\n"), offset);
6060           first = true;
6061         }
6062       else
6063         {
6064           /* We have a location expression entry.  */
6065           uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
6066
6067           char *b = format_dwarf_addr (dwflmod, address_size, begin);
6068           char *e = format_dwarf_addr (dwflmod, address_size, end);
6069
6070           if (first)            /* First entry in a list.  */
6071             printf (gettext (" [%6tx]  %s..%s"), offset, b, e);
6072           else
6073             printf (gettext ("           %s..%s"), b, e);
6074
6075           free (b);
6076           free (e);
6077
6078           if (endp - readp <= (ptrdiff_t) len)
6079             {
6080               fputs (gettext ("   <INVALID DATA>\n"), stdout);
6081               break;
6082             }
6083
6084           print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
6085                      3 /*XXX*/, address_size, offset_size, len, readp);
6086
6087           first = false;
6088           readp += len;
6089         }
6090     }
6091 }
6092
6093 struct mac_culist
6094 {
6095   Dwarf_Die die;
6096   Dwarf_Off offset;
6097   Dwarf_Files *files;
6098   struct mac_culist *next;
6099 };
6100
6101
6102 static int
6103 mac_compare (const void *p1, const void *p2)
6104 {
6105   struct mac_culist *m1 = (struct mac_culist *) p1;
6106   struct mac_culist *m2 = (struct mac_culist *) p2;
6107
6108   if (m1->offset < m2->offset)
6109     return -1;
6110   if (m1->offset > m2->offset)
6111     return 1;
6112   return 0;
6113 }
6114
6115
6116 static void
6117 print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6118                              Ebl *ebl, GElf_Ehdr *ehdr,
6119                              Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6120 {
6121   printf (gettext ("\
6122 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6123           elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6124           (uint64_t) shdr->sh_offset);
6125   putc_unlocked ('\n', stdout);
6126
6127   /* There is no function in libdw to iterate over the raw content of
6128      the section but it is easy enough to do.  */
6129   Elf_Data *data = elf_getdata (scn, NULL);
6130   if (unlikely (data == NULL || data->d_buf == NULL))
6131     {
6132       error (0, 0, gettext ("cannot get macro information section data: %s"),
6133              elf_errmsg (-1));
6134       return;
6135     }
6136
6137   /* Get the source file information for all CUs.  */
6138   Dwarf_Off offset;
6139   Dwarf_Off ncu = 0;
6140   size_t hsize;
6141   struct mac_culist *culist = NULL;
6142   size_t nculist = 0;
6143   while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
6144     {
6145       Dwarf_Die cudie;
6146       if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
6147         continue;
6148
6149       Dwarf_Attribute attr;
6150       if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
6151         continue;
6152
6153       Dwarf_Word macoff;
6154       if (dwarf_formudata (&attr, &macoff) != 0)
6155         continue;
6156
6157       struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
6158       newp->die = cudie;
6159       newp->offset = macoff;
6160       newp->files = NULL;
6161       newp->next = culist;
6162       culist = newp;
6163       ++nculist;
6164     }
6165
6166   /* Convert the list into an array for easier consumption.  */
6167   struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
6168                                                          * sizeof (*cus));
6169   /* Add sentinel.  */
6170   cus[nculist].offset = data->d_size;
6171   if (nculist > 0)
6172     {
6173       for (size_t cnt = nculist - 1; culist != NULL; --cnt)
6174         {
6175           assert (cnt < nculist);
6176           cus[cnt] = *culist;
6177           culist = culist->next;
6178         }
6179
6180       /* Sort the array according to the offset in the .debug_macinfo
6181          section.  Note we keep the sentinel at the end.  */
6182       qsort (cus, nculist, sizeof (*cus), mac_compare);
6183     }
6184
6185   const unsigned char *readp = (const unsigned char *) data->d_buf;
6186   const unsigned char *readendp = readp + data->d_size;
6187   int level = 1;
6188
6189   while (readp < readendp)
6190     {
6191       unsigned int opcode = *readp++;
6192       unsigned int u128;
6193       unsigned int u128_2;
6194       const unsigned char *endp;
6195
6196       switch (opcode)
6197         {
6198         case DW_MACINFO_define:
6199         case DW_MACINFO_undef:
6200         case DW_MACINFO_vendor_ext:
6201           /*  For the first two opcodes the parameters are
6202                 line, string
6203               For the latter
6204                 number, string.
6205               We can treat these cases together.  */
6206           get_uleb128 (u128, readp);
6207
6208           endp = memchr (readp, '\0', readendp - readp);
6209           if (unlikely (endp == NULL))
6210             {
6211               printf (gettext ("\
6212 %*s*** non-terminated string at end of section"),
6213                       level, "");
6214               return;
6215             }
6216
6217           if (opcode == DW_MACINFO_define)
6218             printf ("%*s#define %s, line %u\n",
6219                     level, "", (char *) readp, u128);
6220           else if (opcode == DW_MACINFO_undef)
6221             printf ("%*s#undef %s, line %u\n",
6222                     level, "", (char *) readp, u128);
6223           else
6224             printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
6225
6226           readp = endp + 1;
6227           break;
6228
6229         case DW_MACINFO_start_file:
6230           /* The two parameters are line and file index, in this order.  */
6231           get_uleb128 (u128, readp);
6232           get_uleb128 (u128_2, readp);
6233
6234           /* Find the CU DIE for this file.  */
6235           size_t macoff = readp - (const unsigned char *) data->d_buf;
6236           const char *fname = "???";
6237           if (macoff >= cus[0].offset)
6238             {
6239               while (macoff >= cus[1].offset)
6240                 ++cus;
6241
6242               if (cus[0].files == NULL
6243                 && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
6244                 cus[0].files = (Dwarf_Files *) -1l;
6245
6246               if (cus[0].files != (Dwarf_Files *) -1l)
6247                 fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
6248                          ?: "???");
6249             }
6250
6251           printf ("%*sstart_file %u, [%u] %s\n",
6252                   level, "", u128, u128_2, fname);
6253           ++level;
6254           break;
6255
6256         case DW_MACINFO_end_file:
6257           --level;
6258           printf ("%*send_file\n", level, "");
6259           /* Nothing more to do.  */
6260           break;
6261
6262         default:
6263           // XXX gcc seems to generate files with a trailing zero.
6264           if (unlikely (opcode != 0 || readp != readendp))
6265             printf ("%*s*** invalid opcode %u\n", level, "", opcode);
6266           break;
6267         }
6268     }
6269 }
6270
6271
6272 static void
6273 print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6274                            Ebl *ebl, GElf_Ehdr *ehdr,
6275                            Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6276 {
6277   printf (gettext ("\
6278 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6279           elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6280           (uint64_t) shdr->sh_offset);
6281   putc_unlocked ('\n', stdout);
6282
6283   Elf_Data *data = elf_getdata (scn, NULL);
6284   if (unlikely (data == NULL || data->d_buf == NULL))
6285     {
6286       error (0, 0, gettext ("cannot get macro information section data: %s"),
6287              elf_errmsg (-1));
6288       return;
6289     }
6290
6291   /* Get the source file information for all CUs.  Uses same
6292      datastructure as macinfo.  But uses offset field to directly
6293      match .debug_line offset.  And just stored in a list.  */
6294   Dwarf_Off offset;
6295   Dwarf_Off ncu = 0;
6296   size_t hsize;
6297   struct mac_culist *culist = NULL;
6298   size_t nculist = 0;
6299   while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
6300     {
6301       Dwarf_Die cudie;
6302       if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
6303         continue;
6304
6305       Dwarf_Attribute attr;
6306       if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL)
6307         continue;
6308
6309       Dwarf_Word lineoff;
6310       if (dwarf_formudata (&attr, &lineoff) != 0)
6311         continue;
6312
6313       struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
6314       newp->die = cudie;
6315       newp->offset = lineoff;
6316       newp->files = NULL;
6317       newp->next = culist;
6318       culist = newp;
6319       ++nculist;
6320     }
6321
6322   const unsigned char *readp = (const unsigned char *) data->d_buf;
6323   const unsigned char *readendp = readp + data->d_size;
6324
6325   while (readp < readendp)
6326     {
6327       printf (gettext (" Offset:             0x%" PRIx64 "\n"),
6328               (uint64_t) (readp - (const unsigned char *) data->d_buf));
6329
6330       // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
6331       // optional vendor extension macro entry table.
6332       if (readp + 2 > readendp)
6333         {
6334         invalid_data:
6335           error (0, 0, gettext ("invalid data"));
6336           return;
6337         }
6338       const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
6339       printf (gettext (" Version:            %" PRIu16 "\n"), vers);
6340
6341       // Version 4 is the GNU extension for DWARF4.  DWARF5 will use version
6342       // 5 when it gets standardized.
6343       if (vers != 4)
6344         {
6345           printf (gettext ("  unknown version, cannot parse section\n"));
6346           return;
6347         }
6348
6349       if (readp + 1 > readendp)
6350         goto invalid_data;
6351       const unsigned char flag = *readp++;
6352       printf (gettext (" Flag:               0x%" PRIx8 "\n"), flag);
6353
6354       unsigned int offset_len = (flag & 0x01) ? 8 : 4;
6355       printf (gettext (" Offset length:      %" PRIu8 "\n"), offset_len);
6356       Dwarf_Off line_offset = -1;
6357       if (flag & 0x02)
6358         {
6359           if (offset_len == 8)
6360             line_offset = read_8ubyte_unaligned_inc (dbg, readp);
6361           else
6362             line_offset = read_4ubyte_unaligned_inc (dbg, readp);
6363           printf (gettext (" .debug_line offset: 0x%" PRIx64 "\n"),
6364                   line_offset);
6365         }
6366
6367       const unsigned char *vendor[DW_MACRO_GNU_hi_user - DW_MACRO_GNU_lo_user];
6368       if (flag & 0x04)
6369         {
6370           // 1 byte length, for each item, 1 byte opcode, uleb128 number
6371           // of arguments, for each argument 1 byte form code.
6372           if (readp + 1 > readendp)
6373             goto invalid_data;
6374           unsigned int tlen = *readp++;
6375           printf (gettext ("  extension opcode table, %" PRIu8 " items:\n"),
6376                   tlen);
6377           for (unsigned int i = 0; i < tlen; i++)
6378             {
6379               if (readp + 1 > readendp)
6380                 goto invalid_data;
6381               unsigned int opcode = *readp++;
6382               printf (gettext ("    [%" PRIx8 "]"), opcode);
6383               if (opcode < DW_MACRO_GNU_lo_user
6384                   || opcode > DW_MACRO_GNU_hi_user)
6385                 goto invalid_data;
6386               // Record the start of description for this vendor opcode.
6387               // uleb128 nr args, 1 byte per arg form.
6388               vendor[opcode - DW_MACRO_GNU_lo_user] = readp;
6389               if (readp + 1 > readendp)
6390                 goto invalid_data;
6391               unsigned int args = *readp++;
6392               if (args > 0)
6393                 {
6394                   printf (gettext (" %" PRIu8 " arguments:"), args);
6395                   while (args > 0)
6396                     {
6397                       if (readp + 1 > readendp)
6398                         goto invalid_data;
6399                       unsigned int form = *readp++;
6400                       printf (" %s", dwarf_form_string (form));
6401                       if (form != DW_FORM_data1
6402                           && form != DW_FORM_data2
6403                           && form != DW_FORM_data4
6404                           && form != DW_FORM_data8
6405                           && form != DW_FORM_sdata
6406                           && form != DW_FORM_udata
6407                           && form != DW_FORM_block
6408                           && form != DW_FORM_block1
6409                           && form != DW_FORM_block2
6410                           && form != DW_FORM_block4
6411                           && form != DW_FORM_flag
6412                           && form != DW_FORM_string
6413                           && form != DW_FORM_strp
6414                           && form != DW_FORM_sec_offset)
6415                         goto invalid_data;
6416                       args--;
6417                       if (args > 0)
6418                         putchar_unlocked (',');
6419                     }
6420                 }
6421               else
6422                 printf (gettext (" no arguments."));
6423               putchar_unlocked ('\n');
6424             }
6425         }
6426       putchar_unlocked ('\n');
6427
6428       int level = 1;
6429       if (readp + 1 > readendp)
6430         goto invalid_data;
6431       unsigned int opcode = *readp++;
6432       while (opcode != 0)
6433         {
6434           unsigned int u128;
6435           unsigned int u128_2;
6436           const unsigned char *endp;
6437           uint64_t off;
6438
6439           switch (opcode)
6440             {
6441             case DW_MACRO_GNU_start_file:
6442               get_uleb128 (u128, readp);
6443               get_uleb128 (u128_2, readp);
6444
6445               /* Find the CU DIE that matches this line offset.  */
6446               const char *fname = "???";
6447               if (line_offset != (Dwarf_Off) -1)
6448                 {
6449                   struct mac_culist *cu = culist;
6450                   while (cu != NULL && line_offset != cu->offset)
6451                     cu = cu->next;
6452                   if (cu != NULL)
6453                     {
6454                       if (cu->files == NULL
6455                           && dwarf_getsrcfiles (&cu->die, &cu->files,
6456                                                 NULL) != 0)
6457                         cu->files = (Dwarf_Files *) -1l;
6458
6459                       if (cu->files != (Dwarf_Files *) -1l)
6460                         fname = (dwarf_filesrc (cu->files, u128_2,
6461                                                 NULL, NULL) ?: "???");
6462                     }
6463                 }
6464               printf ("%*sstart_file %u, [%u] %s\n",
6465                       level, "", u128, u128_2, fname);
6466               ++level;
6467               break;
6468
6469             case DW_MACRO_GNU_end_file:
6470               --level;
6471               printf ("%*send_file\n", level, "");
6472               break;
6473
6474             case DW_MACRO_GNU_define:
6475               get_uleb128 (u128, readp);
6476               endp = memchr (readp, '\0', readendp - readp);
6477               if (endp == NULL)
6478                 goto invalid_data;
6479               printf ("%*s#define %s, line %u\n",
6480                       level, "", readp, u128);
6481               readp = endp + 1;
6482               break;
6483
6484             case DW_MACRO_GNU_undef:
6485               get_uleb128 (u128, readp);
6486               endp = memchr (readp, '\0', readendp - readp);
6487               if (endp == NULL)
6488                 goto invalid_data;
6489               printf ("%*s#undef %s, line %u\n",
6490                       level, "", readp, u128);
6491               readp = endp + 1;
6492               break;
6493
6494             case DW_MACRO_GNU_define_indirect:
6495               get_uleb128 (u128, readp);
6496               if (readp + offset_len > readendp)
6497                 goto invalid_data;
6498               if (offset_len == 8)
6499                 off = read_8ubyte_unaligned_inc (dbg, readp);
6500               else
6501                 off = read_4ubyte_unaligned_inc (dbg, readp);
6502               printf ("%*s#define %s, line %u (indirect)\n",
6503                       level, "", dwarf_getstring (dbg, off, NULL), u128);
6504               break;
6505
6506             case DW_MACRO_GNU_undef_indirect:
6507               get_uleb128 (u128, readp);
6508               if (readp + offset_len > readendp)
6509                 goto invalid_data;
6510               if (offset_len == 8)
6511                 off = read_8ubyte_unaligned_inc (dbg, readp);
6512               else
6513                 off = read_4ubyte_unaligned_inc (dbg, readp);
6514               printf ("%*s#undef %s, line %u (indirect)\n",
6515                       level, "", dwarf_getstring (dbg, off, NULL), u128);
6516               break;
6517
6518             case DW_MACRO_GNU_transparent_include:
6519               if (readp + offset_len > readendp)
6520                 goto invalid_data;
6521               if (offset_len == 8)
6522                 off = read_8ubyte_unaligned_inc (dbg, readp);
6523               else
6524                 off = read_4ubyte_unaligned_inc (dbg, readp);
6525               printf ("%*s#include offset 0x%" PRIx64 "\n",
6526                       level, "", off);
6527               break;
6528
6529             default:
6530               printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
6531               if (opcode < DW_MACRO_GNU_lo_user
6532                   || opcode > DW_MACRO_GNU_lo_user
6533                   || vendor[opcode - DW_MACRO_GNU_lo_user] == NULL)
6534                 goto invalid_data;
6535
6536               const unsigned char *op_desc;
6537               op_desc = vendor[opcode - DW_MACRO_GNU_lo_user];
6538
6539               // Just skip the arguments, we cannot really interpret them,
6540               // but print as much as we can.
6541               unsigned int args = *op_desc++;
6542               while (args > 0)
6543                 {
6544                   unsigned int form = *op_desc++;
6545                   Dwarf_Word val;
6546                   switch (form)
6547                     {
6548                     case DW_FORM_data1:
6549                       if (readp + 1 > readendp)
6550                         goto invalid_data;
6551                       val = *readp++;
6552                       printf (" %" PRIx8, (unsigned int) val);
6553                       break;
6554
6555                     case DW_FORM_data2:
6556                       if (readp + 2 > readendp)
6557                         goto invalid_data;
6558                       val = read_2ubyte_unaligned_inc (dbg, readp);
6559                       printf(" %" PRIx16, (unsigned int) val);
6560                       break;
6561
6562                     case DW_FORM_data4:
6563                       if (readp + 4 > readendp)
6564                         goto invalid_data;
6565                       val = read_4ubyte_unaligned_inc (dbg, readp);
6566                       printf (" %" PRIx32, (unsigned int) val);
6567                       break;
6568
6569                     case DW_FORM_data8:
6570                       if (readp + 8 > readendp)
6571                         goto invalid_data;
6572                       val = read_8ubyte_unaligned_inc (dbg, readp);
6573                       printf (" %" PRIx64, val);
6574                       break;
6575
6576                     case DW_FORM_sdata:
6577                       get_sleb128 (val, readp);
6578                       printf (" %" PRIx64, val);
6579                       break;
6580
6581                     case DW_FORM_udata:
6582                       get_uleb128 (val, readp);
6583                       printf (" %" PRIx64, val);
6584                       break;
6585
6586                     case DW_FORM_block:
6587                       get_uleb128 (val, readp);
6588                       printf (" block[%" PRIu64 "]", val);
6589                       if (readp + val > readendp)
6590                         goto invalid_data;
6591                       readp += val;
6592                       break;
6593
6594                     case DW_FORM_block1:
6595                       if (readp + 1 > readendp)
6596                         goto invalid_data;
6597                       val = *readp++;
6598                       printf (" block[%" PRIu64 "]", val);
6599                       if (readp + val > readendp)
6600                         goto invalid_data;
6601                       break;
6602
6603                     case DW_FORM_block2:
6604                       if (readp + 2 > readendp)
6605                         goto invalid_data;
6606                       val = read_2ubyte_unaligned_inc (dbg, readp);
6607                       printf (" block[%" PRIu64 "]", val);
6608                       if (readp + val > readendp)
6609                         goto invalid_data;
6610                       break;
6611
6612                     case DW_FORM_block4:
6613                       if (readp + 2 > readendp)
6614                         goto invalid_data;
6615                       val =read_4ubyte_unaligned_inc (dbg, readp);
6616                       printf (" block[%" PRIu64 "]", val);
6617                       if (readp + val > readendp)
6618                         goto invalid_data;
6619                       break;
6620
6621                     case DW_FORM_flag:
6622                       if (readp + 1 > readendp)
6623                         goto invalid_data;
6624                       val = *readp++;
6625                       printf (" %s", nl_langinfo (val != 0 ? YESSTR : NOSTR));
6626                       break;
6627
6628                     case DW_FORM_string:
6629                       endp = memchr (readp, '\0', readendp - readp);
6630                       if (endp == NULL)
6631                         goto invalid_data;
6632                       printf (" %s", readp);
6633                       readp = endp + 1;
6634                       break;
6635
6636                     case DW_FORM_strp:
6637                       if (readp + offset_len > readendp)
6638                         goto invalid_data;
6639                       if (offset_len == 8)
6640                         val = read_8ubyte_unaligned_inc (dbg, readp);
6641                       else
6642                         val = read_4ubyte_unaligned_inc (dbg, readp);
6643                       printf (" %s", dwarf_getstring (dbg, val, NULL));
6644                       break;
6645
6646                     case DW_FORM_sec_offset:
6647                       if (readp + offset_len > readendp)
6648                         goto invalid_data;
6649                       if (offset_len == 8)
6650                         val = read_8ubyte_unaligned_inc (dbg, readp);
6651                       else
6652                         val = read_4ubyte_unaligned_inc (dbg, readp);
6653                       printf (" %" PRIx64, val);
6654                       break;
6655
6656                       default:
6657                         error (0, 0, gettext ("vendor opcode not verified?"));
6658                         return;
6659                     }
6660
6661                   args--;
6662                   if (args > 0)
6663                     putchar_unlocked (',');
6664                 }
6665               putchar_unlocked ('\n');
6666             }
6667
6668           if (readp + 1 > readendp)
6669             goto invalid_data;
6670           opcode = *readp++;
6671           if (opcode == 0)
6672             putchar_unlocked ('\n');
6673         }
6674     }
6675 }
6676
6677
6678 /* Callback for printing global names.  */
6679 static int
6680 print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
6681                 void *arg)
6682 {
6683   int *np = (int *) arg;
6684
6685   printf (gettext (" [%5d] DIE offset: %6" PRId64
6686                    ", CU DIE offset: %6" PRId64 ", name: %s\n"),
6687           (*np)++, global->die_offset, global->cu_offset, global->name);
6688
6689   return 0;
6690 }
6691
6692
6693 /* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
6694 static void
6695 print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6696                               Ebl *ebl, GElf_Ehdr *ehdr,
6697                               Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6698 {
6699   printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6700           elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6701           (uint64_t) shdr->sh_offset);
6702
6703   int n = 0;
6704   (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
6705 }
6706
6707 /* Print the content of the DWARF string section '.debug_str'.  */
6708 static void
6709 print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6710                          Ebl *ebl, GElf_Ehdr *ehdr,
6711                          Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6712 {
6713   const size_t sh_size = (dbg->sectiondata[IDX_debug_str] ?
6714                           dbg->sectiondata[IDX_debug_str]->d_size : 0);
6715
6716   /* Compute floor(log16(shdr->sh_size)).  */
6717   GElf_Addr tmp = sh_size;
6718   int digits = 1;
6719   while (tmp >= 16)
6720     {
6721       ++digits;
6722       tmp >>= 4;
6723     }
6724   digits = MAX (4, digits);
6725
6726   printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
6727                    " %*s  String\n"),
6728           elf_ndxscn (scn),
6729           section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset,
6730           /* TRANS: the debugstr| prefix makes the string unique.  */
6731           digits + 2, sgettext ("debugstr|Offset"));
6732
6733   Dwarf_Off offset = 0;
6734   while (offset < sh_size)
6735     {
6736       size_t len;
6737       const char *str = dwarf_getstring (dbg, offset, &len);
6738       if (unlikely (str == NULL))
6739         {
6740           printf (gettext (" *** error while reading strings: %s\n"),
6741                   dwarf_errmsg (-1));
6742           break;
6743         }
6744
6745       printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
6746
6747       offset += len + 1;
6748     }
6749 }
6750
6751
6752 /* Print the content of the call frame search table section
6753    '.eh_frame_hdr'.  */
6754 static void
6755 print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6756                                Ebl *ebl __attribute__ ((unused)),
6757                                GElf_Ehdr *ehdr __attribute__ ((unused)),
6758                                Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6759 {
6760   printf (gettext ("\
6761 \nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
6762           elf_ndxscn (scn));
6763
6764   Elf_Data *data = elf_rawdata (scn, NULL);
6765
6766   if (unlikely (data == NULL))
6767     {
6768       error (0, 0, gettext ("cannot get %s content: %s"),
6769              ".eh_frame_hdr", elf_errmsg (-1));
6770       return;
6771     }
6772
6773   const unsigned char *readp = data->d_buf;
6774   const unsigned char *const dataend = ((unsigned char *) data->d_buf
6775                                         + data->d_size);
6776
6777   if (unlikely (readp + 4 > dataend))
6778     {
6779     invalid_data:
6780       error (0, 0, gettext ("invalid data"));
6781       return;
6782     }
6783
6784   unsigned int version = *readp++;
6785   unsigned int eh_frame_ptr_enc = *readp++;
6786   unsigned int fde_count_enc = *readp++;
6787   unsigned int table_enc = *readp++;
6788
6789   printf (" version:          %u\n"
6790           " eh_frame_ptr_enc: %#x ",
6791           version, eh_frame_ptr_enc);
6792   print_encoding_base ("", eh_frame_ptr_enc);
6793   printf (" fde_count_enc:    %#x ", fde_count_enc);
6794   print_encoding_base ("", fde_count_enc);
6795   printf (" table_enc:        %#x ", table_enc);
6796   print_encoding_base ("", table_enc);
6797
6798   uint64_t eh_frame_ptr = 0;
6799   if (eh_frame_ptr_enc != DW_EH_PE_omit)
6800     {
6801       readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
6802                             dbg);
6803       if (unlikely (readp == NULL))
6804         goto invalid_data;
6805
6806       printf (" eh_frame_ptr:     %#" PRIx64, eh_frame_ptr);
6807       if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
6808         printf (" (offset: %#" PRIx64 ")",
6809                 /* +4 because of the 4 byte header of the section.  */
6810                 (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
6811
6812       putchar_unlocked ('\n');
6813     }
6814
6815   uint64_t fde_count = 0;
6816   if (fde_count_enc != DW_EH_PE_omit)
6817     {
6818       readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
6819       if (unlikely (readp == NULL))
6820         goto invalid_data;
6821
6822       printf (" fde_count:        %" PRIu64 "\n", fde_count);
6823     }
6824
6825   if (fde_count == 0 || table_enc == DW_EH_PE_omit)
6826     return;
6827
6828   puts (" Table:");
6829
6830   /* Optimize for the most common case.  */
6831   if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
6832     while (fde_count > 0 && readp + 8 <= dataend)
6833       {
6834         int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
6835         uint64_t initial_offset = ((uint64_t) shdr->sh_offset
6836                                    + (int64_t) initial_location);
6837         int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
6838         // XXX Possibly print symbol name or section offset for initial_offset
6839         printf ("  %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
6840                 " fde=[%6" PRIx64 "]\n",
6841                 initial_location, initial_offset,
6842                 address, address - (eh_frame_ptr + 4));
6843       }
6844   else
6845     while (0 && readp < dataend)
6846       {
6847
6848       }
6849 }
6850
6851
6852 /* Print the content of the exception handling table section
6853    '.eh_frame_hdr'.  */
6854 static void
6855 print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
6856                              Ebl *ebl __attribute__ ((unused)),
6857                              GElf_Ehdr *ehdr __attribute__ ((unused)),
6858                              Elf_Scn *scn,
6859                              GElf_Shdr *shdr __attribute__ ((unused)),
6860                              Dwarf *dbg __attribute__ ((unused)))
6861 {
6862   printf (gettext ("\
6863 \nException handling table section [%2zu] '.gcc_except_table':\n"),
6864           elf_ndxscn (scn));
6865
6866   Elf_Data *data = elf_rawdata (scn, NULL);
6867
6868   if (unlikely (data == NULL))
6869     {
6870       error (0, 0, gettext ("cannot get %s content: %s"),
6871              ".gcc_except_table", elf_errmsg (-1));
6872       return;
6873     }
6874
6875   const unsigned char *readp = data->d_buf;
6876   const unsigned char *const dataend = readp + data->d_size;
6877
6878   if (unlikely (readp + 1 > dataend))
6879     {
6880     invalid_data:
6881       error (0, 0, gettext ("invalid data"));
6882       return;
6883     }
6884   unsigned int lpstart_encoding = *readp++;
6885   printf (gettext (" LPStart encoding:    %#x "), lpstart_encoding);
6886   print_encoding_base ("", lpstart_encoding);
6887   if (lpstart_encoding != DW_EH_PE_omit)
6888     {
6889       uint64_t lpstart;
6890       readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
6891       printf (" LPStart:             %#" PRIx64 "\n", lpstart);
6892     }
6893
6894   if (unlikely (readp + 1 > dataend))
6895     goto invalid_data;
6896   unsigned int ttype_encoding = *readp++;
6897   printf (gettext (" TType encoding:      %#x "), ttype_encoding);
6898   print_encoding_base ("", ttype_encoding);
6899   const unsigned char *ttype_base = NULL;
6900   if (ttype_encoding != DW_EH_PE_omit)
6901     {
6902       unsigned int ttype_base_offset;
6903       get_uleb128 (ttype_base_offset, readp);
6904       printf (" TType base offset:   %#x\n", ttype_base_offset);
6905       ttype_base = readp + ttype_base_offset;
6906     }
6907
6908   if (unlikely (readp + 1 > dataend))
6909     goto invalid_data;
6910   unsigned int call_site_encoding = *readp++;
6911   printf (gettext (" Call site encoding:  %#x "), call_site_encoding);
6912   print_encoding_base ("", call_site_encoding);
6913   unsigned int call_site_table_len;
6914   get_uleb128 (call_site_table_len, readp);
6915
6916   const unsigned char *const action_table = readp + call_site_table_len;
6917   if (unlikely (action_table > dataend))
6918     goto invalid_data;
6919   unsigned int u = 0;
6920   unsigned int max_action = 0;
6921   while (readp < action_table)
6922     {
6923       if (u == 0)
6924         puts (gettext ("\n Call site table:"));
6925
6926       uint64_t call_site_start;
6927       readp = read_encoded (call_site_encoding, readp, dataend,
6928                             &call_site_start, dbg);
6929       uint64_t call_site_length;
6930       readp = read_encoded (call_site_encoding, readp, dataend,
6931                             &call_site_length, dbg);
6932       uint64_t landing_pad;
6933       readp = read_encoded (call_site_encoding, readp, dataend,
6934                             &landing_pad, dbg);
6935       unsigned int action;
6936       get_uleb128 (action, readp);
6937       max_action = MAX (action, max_action);
6938       printf (gettext (" [%4u] Call site start:   %#" PRIx64 "\n"
6939                        "        Call site length:  %" PRIu64 "\n"
6940                        "        Landing pad:       %#" PRIx64 "\n"
6941                        "        Action:            %u\n"),
6942               u++, call_site_start, call_site_length, landing_pad, action);
6943     }
6944   assert (readp == action_table);
6945
6946   unsigned int max_ar_filter = 0;
6947   if (max_action > 0)
6948     {
6949       puts ("\n Action table:");
6950
6951       const unsigned char *const action_table_end
6952         = action_table + max_action + 1;
6953
6954       u = 0;
6955       do
6956         {
6957           int ar_filter;
6958           get_sleb128 (ar_filter, readp);
6959           if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
6960             max_ar_filter = ar_filter;
6961           int ar_disp;
6962           get_sleb128 (ar_disp, readp);
6963
6964           printf (" [%4u] ar_filter:  % d\n"
6965                   "        ar_disp:    % -5d",
6966                   u, ar_filter, ar_disp);
6967           if (abs (ar_disp) & 1)
6968             printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
6969           else if (ar_disp != 0)
6970             puts (" -> ???");
6971           else
6972             putchar_unlocked ('\n');
6973           ++u;
6974         }
6975       while (readp < action_table_end);
6976     }
6977
6978   if (max_ar_filter > 0)
6979     {
6980       puts ("\n TType table:");
6981
6982       // XXX Not *4, size of encoding;
6983       switch (ttype_encoding & 7)
6984         {
6985         case DW_EH_PE_udata2:
6986         case DW_EH_PE_sdata2:
6987           readp = ttype_base - max_ar_filter * 2;
6988           break;
6989         case DW_EH_PE_udata4:
6990         case DW_EH_PE_sdata4:
6991           readp = ttype_base - max_ar_filter * 4;
6992           break;
6993         case DW_EH_PE_udata8:
6994         case DW_EH_PE_sdata8:
6995           readp = ttype_base - max_ar_filter * 8;
6996           break;
6997         default:
6998           error (1, 0, gettext ("invalid TType encoding"));
6999         }
7000
7001       do
7002         {
7003           uint64_t ttype;
7004           readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
7005                                 dbg);
7006           printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
7007         }
7008       while (readp < ttype_base);
7009     }
7010 }
7011
7012 /* Print the content of the '.gdb_index' section.
7013    http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
7014 */
7015 static void
7016 print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
7017                          Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7018 {
7019   printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
7020                    " contains %" PRId64 " bytes :\n"),
7021           elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7022           (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
7023
7024   Elf_Data *data = elf_rawdata (scn, NULL);
7025
7026   if (unlikely (data == NULL))
7027     {
7028       error (0, 0, gettext ("cannot get %s content: %s"),
7029              ".gdb_index", elf_errmsg (-1));
7030       return;
7031     }
7032
7033   // .gdb_index is always in little endian.
7034   Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
7035   dbg = &dummy_dbg;
7036
7037   const unsigned char *readp = data->d_buf;
7038   const unsigned char *const dataend = readp + data->d_size;
7039
7040   if (unlikely (readp + 4 > dataend))
7041     {
7042     invalid_data:
7043       error (0, 0, gettext ("invalid data"));
7044       return;
7045     }
7046
7047   int32_t vers = read_4ubyte_unaligned (dbg, readp);
7048   printf (gettext (" Version:         %" PRId32 "\n"), vers);
7049
7050   // The only difference between version 4 and version 5 is the
7051   // hash used for generating the table.  Version 6 contains symbols
7052   // for inlined functions, older versions didn't.
7053   if (vers < 4 || vers > 7)
7054     {
7055       printf (gettext ("  unknown version, cannot parse section\n"));
7056       return;
7057     }
7058
7059   readp += 4;
7060   if (unlikely (readp + 4 > dataend))
7061     goto invalid_data;
7062
7063   uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
7064   printf (gettext (" CU offset:       %#" PRIx32 "\n"), cu_off);
7065
7066   readp += 4;
7067   if (unlikely (readp + 4 > dataend))
7068     goto invalid_data;
7069
7070   uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
7071   printf (gettext (" TU offset:       %#" PRIx32 "\n"), tu_off);
7072
7073   readp += 4;
7074   if (unlikely (readp + 4 > dataend))
7075     goto invalid_data;
7076
7077   uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
7078   printf (gettext (" address offset:  %#" PRIx32 "\n"), addr_off);
7079
7080   readp += 4;
7081   if (unlikely (readp + 4 > dataend))
7082     goto invalid_data;
7083
7084   uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
7085   printf (gettext (" symbol offset:   %#" PRIx32 "\n"), sym_off);
7086
7087   readp += 4;
7088   if (unlikely (readp + 4 > dataend))
7089     goto invalid_data;
7090
7091   uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
7092   printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
7093
7094   readp = data->d_buf + cu_off;
7095
7096   const unsigned char *nextp = data->d_buf + tu_off;
7097   size_t cu_nr = (nextp - readp) / 16;
7098
7099   printf (gettext ("\n CU list at offset %#" PRIx32
7100                    " contains %zu entries:\n"),
7101           cu_off, cu_nr);
7102
7103   size_t n = 0;
7104   while (readp + 16 <= dataend && n < cu_nr)
7105     {
7106       uint64_t off = read_8ubyte_unaligned (dbg, readp);
7107       readp += 8;
7108
7109       uint64_t len = read_8ubyte_unaligned (dbg, readp);
7110       readp += 8;
7111
7112       printf (" [%4zu] start: %0#8" PRIx64
7113               ", length: %5" PRIu64 "\n", n, off, len);
7114       n++;
7115     }
7116
7117   readp = data->d_buf + tu_off;
7118   nextp = data->d_buf + addr_off;
7119   size_t tu_nr = (nextp - readp) / 24;
7120
7121   printf (gettext ("\n TU list at offset %#" PRIx32
7122                    " contains %zu entries:\n"),
7123           tu_off, tu_nr);
7124
7125   n = 0;
7126   while (readp + 24 <= dataend && n < tu_nr)
7127     {
7128       uint64_t off = read_8ubyte_unaligned (dbg, readp);
7129       readp += 8;
7130
7131       uint64_t type = read_8ubyte_unaligned (dbg, readp);
7132       readp += 8;
7133
7134       uint64_t sig = read_8ubyte_unaligned (dbg, readp);
7135       readp += 8;
7136
7137       printf (" [%4zu] CU offset: %5" PRId64
7138               ", type offset: %5" PRId64
7139               ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
7140       n++;
7141     }
7142
7143   readp = data->d_buf + addr_off;
7144   nextp = data->d_buf + sym_off;
7145   size_t addr_nr = (nextp - readp) / 20;
7146
7147   printf (gettext ("\n Address list at offset %#" PRIx32
7148                    " contains %zu entries:\n"),
7149           addr_off, addr_nr);
7150
7151   n = 0;
7152   while (readp + 20 <= dataend && n < addr_nr)
7153     {
7154       uint64_t low = read_8ubyte_unaligned (dbg, readp);
7155       readp += 8;
7156
7157       uint64_t high = read_8ubyte_unaligned (dbg, readp);
7158       readp += 8;
7159
7160       uint32_t idx = read_4ubyte_unaligned (dbg, readp);
7161       readp += 4;
7162
7163       char *l = format_dwarf_addr (dwflmod, 8, low);
7164       char *h = format_dwarf_addr (dwflmod, 8, high - 1);
7165       printf (" [%4zu] %s..%s, CU index: %5" PRId32 "\n",
7166               n, l, h, idx);
7167       n++;
7168     }
7169
7170   readp = data->d_buf + sym_off;
7171   nextp = data->d_buf + const_off;
7172   size_t sym_nr = (nextp - readp) / 8;
7173
7174   printf (gettext ("\n Symbol table at offset %#" PRIx32
7175                    " contains %zu slots:\n"),
7176           addr_off, sym_nr);
7177
7178   n = 0;
7179   while (readp + 8 <= dataend && n < sym_nr)
7180     {
7181       uint32_t name = read_4ubyte_unaligned (dbg, readp);
7182       readp += 4;
7183
7184       uint32_t vector = read_4ubyte_unaligned (dbg, readp);
7185       readp += 4;
7186
7187       if (name != 0 || vector != 0)
7188         {
7189           const unsigned char *sym = data->d_buf + const_off + name;
7190           if (unlikely (sym > dataend))
7191             goto invalid_data;
7192
7193           printf (" [%4zu] symbol: %s, CUs: ", n, sym);
7194
7195           const unsigned char *readcus = data->d_buf + const_off + vector;
7196           if (unlikely (readcus + 8 > dataend))
7197             goto invalid_data;
7198
7199           uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
7200           while (cus--)
7201             {
7202               uint32_t cu_kind, cu, kind;
7203               bool is_static;
7204               readcus += 4;
7205               cu_kind = read_4ubyte_unaligned (dbg, readcus);
7206               cu = cu_kind & ((1 << 24) - 1);
7207               kind = (cu_kind >> 28) & 7;
7208               is_static = cu_kind & (1 << 31);
7209               if (cu > cu_nr - 1)
7210                 printf ("%" PRId32 "T", cu - (uint32_t) cu_nr);
7211               else
7212                 printf ("%" PRId32, cu);
7213               if (kind != 0)
7214                 {
7215                   printf (" (");
7216                   switch (kind)
7217                     {
7218                     case 1:
7219                       printf ("type");
7220                       break;
7221                     case 2:
7222                       printf ("var");
7223                       break;
7224                     case 3:
7225                       printf ("func");
7226                       break;
7227                     case 4:
7228                       printf ("other");
7229                       break;
7230                     default:
7231                       printf ("unknown-0x%" PRIx32, kind);
7232                       break;
7233                     }
7234                   printf (":%c)", (is_static ? 'S' : 'G'));
7235                 }
7236               if (cus > 0)
7237                 printf (", ");
7238             }
7239           printf ("\n");
7240         }
7241       n++;
7242     }
7243 }
7244
7245 static void
7246 print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
7247 {
7248   /* Before we start the real work get a debug context descriptor.  */
7249   Dwarf_Addr dwbias;
7250   Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
7251   Dwarf dummy_dbg =
7252     {
7253       .elf = ebl->elf,
7254       .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
7255     };
7256   if (dbg == NULL)
7257     {
7258       if ((print_debug_sections & ~section_exception) != 0)
7259         error (0, 0, gettext ("cannot get debug context descriptor: %s"),
7260                dwfl_errmsg (-1));
7261       if ((print_debug_sections & section_exception) == 0)
7262         return;
7263       dbg = &dummy_dbg;
7264     }
7265
7266   /* Get the section header string table index.  */
7267   size_t shstrndx;
7268   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
7269     error (EXIT_FAILURE, 0,
7270            gettext ("cannot get section header string table index"));
7271
7272   /* Look through all the sections for the debugging sections to print.  */
7273   Elf_Scn *scn = NULL;
7274   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
7275     {
7276       GElf_Shdr shdr_mem;
7277       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
7278
7279       if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
7280         {
7281           static const struct
7282           {
7283             const char *name;
7284             enum section_e bitmask;
7285             void (*fp) (Dwfl_Module *, Ebl *,
7286                         GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
7287           } debug_sections[] =
7288             {
7289 #define NEW_SECTION(name) \
7290               { ".debug_" #name, section_##name, print_debug_##name##_section }
7291               NEW_SECTION (abbrev),
7292               NEW_SECTION (aranges),
7293               NEW_SECTION (frame),
7294               NEW_SECTION (info),
7295               NEW_SECTION (types),
7296               NEW_SECTION (line),
7297               NEW_SECTION (loc),
7298               NEW_SECTION (pubnames),
7299               NEW_SECTION (str),
7300               NEW_SECTION (macinfo),
7301               NEW_SECTION (macro),
7302               NEW_SECTION (ranges),
7303               { ".eh_frame", section_frame | section_exception,
7304                 print_debug_frame_section },
7305               { ".eh_frame_hdr", section_frame | section_exception,
7306                 print_debug_frame_hdr_section },
7307               { ".gcc_except_table", section_frame | section_exception,
7308                 print_debug_exception_table },
7309               { ".gdb_index", section_gdb_index, print_gdb_index_section }
7310             };
7311           const int ndebug_sections = (sizeof (debug_sections)
7312                                        / sizeof (debug_sections[0]));
7313           const char *name = elf_strptr (ebl->elf, shstrndx,
7314                                          shdr->sh_name);
7315           int n;
7316
7317           for (n = 0; n < ndebug_sections; ++n)
7318             if (strcmp (name, debug_sections[n].name) == 0
7319 #if USE_ZLIB
7320                 || (name[0] == '.' && name[1] == 'z'
7321                     && debug_sections[n].name[1] == 'd'
7322                     && strcmp (&name[2], &debug_sections[n].name[1]) == 0)
7323 #endif
7324                 )
7325               {
7326                 if ((print_debug_sections | implicit_debug_sections)
7327                     & debug_sections[n].bitmask)
7328                   debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
7329                 break;
7330               }
7331         }
7332     }
7333
7334   reset_listptr (&known_loclistptr);
7335   reset_listptr (&known_rangelistptr);
7336 }
7337
7338
7339 #define ITEM_INDENT             4
7340 #define ITEM_WRAP_COLUMN        150
7341 #define REGISTER_WRAP_COLUMN    75
7342
7343 /* Print "NAME: FORMAT", wrapping when FORMAT_MAX chars of FORMAT would
7344    make the line exceed ITEM_WRAP_COLUMN.  Unpadded numbers look better
7345    for the core items.  But we do not want the line breaks to depend on
7346    the particular values.  */
7347 static unsigned int
7348 __attribute__ ((format (printf, 7, 8)))
7349 print_core_item (unsigned int colno, char sep, unsigned int wrap,
7350                  size_t name_width, const char *name,
7351                  size_t format_max, const char *format, ...)
7352 {
7353   size_t len = strlen (name);
7354   if (name_width < len)
7355     name_width = len;
7356
7357   size_t n = name_width + sizeof ": " - 1 + format_max;
7358
7359   if (colno == 0)
7360     {
7361       printf ("%*s", ITEM_INDENT, "");
7362       colno = ITEM_INDENT + n;
7363     }
7364   else if (colno + 2 + n < wrap)
7365     {
7366       printf ("%c ", sep);
7367       colno += 2 + n;
7368     }
7369   else
7370     {
7371       printf ("\n%*s", ITEM_INDENT, "");
7372       colno = ITEM_INDENT + n;
7373     }
7374
7375   printf ("%s: %*s", name, (int) (name_width - len), "");
7376
7377   va_list ap;
7378   va_start (ap, format);
7379   vprintf (format, ap);
7380   va_end (ap);
7381
7382   return colno;
7383 }
7384
7385 static const void *
7386 convert (Elf *core, Elf_Type type, uint_fast16_t count,
7387          void *value, const void *data, size_t size)
7388 {
7389   Elf_Data valuedata =
7390     {
7391       .d_type = type,
7392       .d_buf = value,
7393       .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
7394       .d_version = EV_CURRENT,
7395     };
7396   Elf_Data indata =
7397     {
7398       .d_type = type,
7399       .d_buf = (void *) data,
7400       .d_size = valuedata.d_size,
7401       .d_version = EV_CURRENT,
7402     };
7403
7404   Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
7405                  ? elf32_xlatetom : elf64_xlatetom)
7406     (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
7407   if (d == NULL)
7408     error (EXIT_FAILURE, 0,
7409            gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
7410
7411   return data + indata.d_size;
7412 }
7413
7414 typedef uint8_t GElf_Byte;
7415
7416 static unsigned int
7417 handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
7418                   unsigned int colno, size_t *repeated_size)
7419 {
7420   uint_fast16_t count = item->count ?: 1;
7421
7422 #define TYPES                                                                 \
7423   DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8, 4);                          \
7424   DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16, 6);                        \
7425   DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32, 11);                       \
7426   DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32, 11);                         \
7427   DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64, 20);                    \
7428   DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64, 20)
7429
7430 #define DO_TYPE(NAME, Name, hex, dec, max) GElf_##Name Name[count]
7431   union { TYPES; } value;
7432 #undef DO_TYPE
7433
7434   void *data = &value;
7435   size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
7436   size_t convsize = size;
7437   if (repeated_size != NULL)
7438     {
7439       if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
7440         {
7441           data = alloca (*repeated_size);
7442           count *= *repeated_size / size;
7443           convsize = count * size;
7444           *repeated_size -= convsize;
7445         }
7446       else if (item->count != 0 || item->format != '\n')
7447         *repeated_size -= size;
7448     }
7449
7450   convert (core, item->type, count, data, desc + item->offset, convsize);
7451
7452   Elf_Type type = item->type;
7453   if (type == ELF_T_ADDR)
7454     type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
7455
7456   switch (item->format)
7457     {
7458     case 'd':
7459       assert (count == 1);
7460       switch (type)
7461         {
7462 #define DO_TYPE(NAME, Name, hex, dec, max)                                    \
7463           case ELF_T_##NAME:                                                  \
7464             colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN,            \
7465                                      0, item->name, max, dec, value.Name[0]); \
7466             break
7467           TYPES;
7468 #undef DO_TYPE
7469         default:
7470           abort ();
7471         }
7472       break;
7473
7474     case 'x':
7475       assert (count == 1);
7476       switch (type)
7477         {
7478 #define DO_TYPE(NAME, Name, hex, dec, max)                                    \
7479           case ELF_T_##NAME:                                                  \
7480             colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN,            \
7481                                      0, item->name, max, hex, value.Name[0]); \
7482             break
7483           TYPES;
7484 #undef DO_TYPE
7485         default:
7486           abort ();
7487         }
7488       break;
7489
7490     case 'b':
7491     case 'B':
7492       assert (size % sizeof (unsigned int) == 0);
7493       unsigned int nbits = count * size * 8;
7494       unsigned int pop = 0;
7495       for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
7496         pop += __builtin_popcount (*i);
7497       bool negate = pop > nbits / 2;
7498       const unsigned int bias = item->format == 'b';
7499
7500       {
7501         char printed[(negate ? nbits - pop : pop) * 16];
7502         char *p = printed;
7503         *p = '\0';
7504
7505         if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
7506           {
7507             assert (size == sizeof (unsigned int) * 2);
7508             for (unsigned int *i = data;
7509                  (void *) i < data + count * size; i += 2)
7510               {
7511                 unsigned int w = i[1];
7512                 i[1] = i[0];
7513                 i[0] = w;
7514               }
7515           }
7516
7517         unsigned int lastbit = 0;
7518         for (const unsigned int *i = data;
7519              (void *) i < data + count * size; ++i)
7520           {
7521             unsigned int bit = ((void *) i - data) * 8;
7522             unsigned int w = negate ? ~*i : *i;
7523             unsigned int run = 0;
7524             while (w != 0)
7525               {
7526                 int n = ffs (w);
7527                 w >>= n;
7528                 bit += n;
7529
7530                 if (lastbit + 1 == bit)
7531                   ++run;
7532                 else
7533                   {
7534                     if (lastbit == 0)
7535                       p += sprintf (p, "%u", bit - bias);
7536                     else if (run == 0)
7537                       p += sprintf (p, ",%u", bit - bias);
7538                     else
7539                       p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
7540                     run = 0;
7541                   }
7542
7543                 lastbit = bit;
7544               }
7545           }
7546         if (lastbit > 0 && lastbit + 1 != nbits)
7547           p += sprintf (p, "-%u", nbits - bias);
7548
7549         colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7550                                  4 + nbits * 4,
7551                                  negate ? "~<%s>" : "<%s>", printed);
7552       }
7553       break;
7554
7555     case 'T':
7556     case (char) ('T'|0x80):
7557       assert (count == 2);
7558       Dwarf_Word sec;
7559       Dwarf_Word usec;
7560       size_t maxfmt = 7;
7561       switch (type)
7562         {
7563 #define DO_TYPE(NAME, Name, hex, dec, max)                                    \
7564           case ELF_T_##NAME:                                                  \
7565             sec = value.Name[0];                                              \
7566             usec = value.Name[1];                                             \
7567             maxfmt += max;                                                    \
7568             break
7569           TYPES;
7570 #undef DO_TYPE
7571         default:
7572           abort ();
7573         }
7574       if (unlikely (item->format == (char) ('T'|0x80)))
7575         {
7576           /* This is a hack for an ill-considered 64-bit ABI where
7577              tv_usec is actually a 32-bit field with 32 bits of padding
7578              rounding out struct timeval.  We've already converted it as
7579              a 64-bit field.  For little-endian, this just means the
7580              high half is the padding; it's presumably zero, but should
7581              be ignored anyway.  For big-endian, it means the 32-bit
7582              field went into the high half of USEC.  */
7583           GElf_Ehdr ehdr_mem;
7584           GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
7585           if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
7586             usec >>= 32;
7587           else
7588             usec &= UINT32_MAX;
7589         }
7590       colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7591                                maxfmt, "%" PRIu64 ".%.6" PRIu64, sec, usec);
7592       break;
7593
7594     case 'c':
7595       assert (count == 1);
7596       colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7597                                1, "%c", value.Byte[0]);
7598       break;
7599
7600     case 's':
7601       colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7602                                count, "%.*s", (int) count, value.Byte);
7603       break;
7604
7605     case '\n':
7606       /* This is a list of strings separated by '\n'.  */
7607       assert (item->count == 0);
7608       assert (repeated_size != NULL);
7609       assert (item->name == NULL);
7610       if (unlikely (item->offset >= *repeated_size))
7611         break;
7612
7613       const char *s = desc + item->offset;
7614       size = *repeated_size - item->offset;
7615       *repeated_size = 0;
7616       while (size > 0)
7617         {
7618           const char *eol = memchr (s, '\n', size);
7619           int len = size;
7620           if (eol != NULL)
7621             len = eol - s;
7622           printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
7623           if (eol == NULL)
7624             break;
7625           size -= eol + 1 - s;
7626           s = eol + 1;
7627         }
7628
7629       colno = ITEM_WRAP_COLUMN;
7630       break;
7631
7632     default:
7633       error (0, 0, "XXX not handling format '%c' for %s",
7634              item->format, item->name);
7635       break;
7636     }
7637
7638 #undef TYPES
7639
7640   return colno;
7641 }
7642
7643
7644 /* Sort items by group, and by layout offset within each group.  */
7645 static int
7646 compare_core_items (const void *a, const void *b)
7647 {
7648   const Ebl_Core_Item *const *p1 = a;
7649   const Ebl_Core_Item *const *p2 = b;
7650   const Ebl_Core_Item *item1 = *p1;
7651   const Ebl_Core_Item *item2 = *p2;
7652
7653   return ((item1->group == item2->group ? 0
7654            : strcmp (item1->group, item2->group))
7655           ?: (int) item1->offset - (int) item2->offset);
7656 }
7657
7658 /* Sort item groups by layout offset of the first item in the group.  */
7659 static int
7660 compare_core_item_groups (const void *a, const void *b)
7661 {
7662   const Ebl_Core_Item *const *const *p1 = a;
7663   const Ebl_Core_Item *const *const *p2 = b;
7664   const Ebl_Core_Item *const *group1 = *p1;
7665   const Ebl_Core_Item *const *group2 = *p2;
7666   const Ebl_Core_Item *item1 = *group1;
7667   const Ebl_Core_Item *item2 = *group2;
7668
7669   return (int) item1->offset - (int) item2->offset;
7670 }
7671
7672 static unsigned int
7673 handle_core_items (Elf *core, const void *desc, size_t descsz,
7674                    const Ebl_Core_Item *items, size_t nitems)
7675 {
7676   if (nitems == 0)
7677     return 0;
7678
7679   /* Sort to collect the groups together.  */
7680   const Ebl_Core_Item *sorted_items[nitems];
7681   for (size_t i = 0; i < nitems; ++i)
7682     sorted_items[i] = &items[i];
7683   qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
7684
7685   /* Collect the unique groups and sort them.  */
7686   const Ebl_Core_Item **groups[nitems];
7687   groups[0] = &sorted_items[0];
7688   size_t ngroups = 1;
7689   for (size_t i = 1; i < nitems; ++i)
7690     if (sorted_items[i]->group != sorted_items[i - 1]->group
7691         && strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
7692       groups[ngroups++] = &sorted_items[i];
7693   qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
7694
7695   /* Write out all the groups.  */
7696   unsigned int colno = 0;
7697
7698   const void *last = desc;
7699   if (nitems == 1)
7700     {
7701       size_t size = descsz;
7702       colno = handle_core_item (core, sorted_items[0], desc, colno, &size);
7703       if (size == 0)
7704         return colno;
7705       desc += descsz - size;
7706       descsz = size;
7707     }
7708
7709   do
7710     {
7711       for (size_t i = 0; i < ngroups; ++i)
7712         {
7713           for (const Ebl_Core_Item **item = groups[i];
7714                (item < &sorted_items[nitems]
7715                 && ((*item)->group == groups[i][0]->group
7716                     || !strcmp ((*item)->group, groups[i][0]->group)));
7717                ++item)
7718             colno = handle_core_item (core, *item, desc, colno, NULL);
7719
7720           /* Force a line break at the end of the group.  */
7721           colno = ITEM_WRAP_COLUMN;
7722         }
7723
7724       if (descsz == 0)
7725         break;
7726
7727       /* This set of items consumed a certain amount of the note's data.
7728          If there is more data there, we have another unit of the same size.
7729          Loop to print that out too.  */
7730       const Ebl_Core_Item *item = &items[nitems - 1];
7731       size_t eltsz = item->offset + gelf_fsize (core, item->type,
7732                                                 item->count ?: 1, EV_CURRENT);
7733
7734       int reps = -1;
7735       do
7736         {
7737           ++reps;
7738           desc += eltsz;
7739           descsz -= eltsz;
7740         }
7741       while (descsz >= eltsz && !memcmp (desc, last, eltsz));
7742
7743       if (reps == 1)
7744         {
7745           /* For just one repeat, print it unabridged twice.  */
7746           desc -= eltsz;
7747           descsz += eltsz;
7748         }
7749       else if (reps > 1)
7750         printf (gettext ("\n%*s... <repeats %u more times> ..."),
7751                 ITEM_INDENT, "", reps);
7752
7753       last = desc;
7754     }
7755   while (descsz > 0);
7756
7757   return colno;
7758 }
7759
7760 static unsigned int
7761 handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
7762                       unsigned int colno)
7763 {
7764   desc += regloc->offset;
7765
7766   abort ();                     /* XXX */
7767   return colno;
7768 }
7769
7770
7771 static unsigned int
7772 handle_core_register (Ebl *ebl, Elf *core, int maxregname,
7773                       const Ebl_Register_Location *regloc, const void *desc,
7774                       unsigned int colno)
7775 {
7776   if (regloc->bits % 8 != 0)
7777     return handle_bit_registers (regloc, desc, colno);
7778
7779   desc += regloc->offset;
7780
7781   for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
7782     {
7783       char name[REGNAMESZ];
7784       int bits;
7785       int type;
7786       register_info (ebl, reg, regloc, name, &bits, &type);
7787
7788 #define TYPES                                                                 \
7789       BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8, 4);                           \
7790       BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16, 6);                        \
7791       BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32, 11);                     \
7792       BITS (64, XWORD, "%20" PRId64, "  0x%.16" PRIx64, 20)
7793
7794 #define BITS(bits, xtype, sfmt, ufmt, max)                              \
7795       uint##bits##_t b##bits; int##bits##_t b##bits##s
7796       union { TYPES; uint64_t b128[2]; } value;
7797 #undef  BITS
7798
7799       switch (type)
7800         {
7801         case DW_ATE_unsigned:
7802         case DW_ATE_signed:
7803         case DW_ATE_address:
7804           switch (bits)
7805             {
7806 #define BITS(bits, xtype, sfmt, ufmt, max)                                    \
7807             case bits:                                                        \
7808               desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0);       \
7809               if (type == DW_ATE_signed)                                      \
7810                 colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,    \
7811                                          maxregname, name,                    \
7812                                          max, sfmt, value.b##bits##s);        \
7813               else                                                            \
7814                 colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,    \
7815                                          maxregname, name,                    \
7816                                          max, ufmt, value.b##bits);           \
7817               break
7818
7819             TYPES;
7820
7821             case 128:
7822               assert (type == DW_ATE_unsigned);
7823               desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
7824               int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
7825               colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
7826                                        maxregname, name,
7827                                        34, "0x%.16" PRIx64 "%.16" PRIx64,
7828                                        value.b128[!be], value.b128[be]);
7829               break;
7830
7831             default:
7832               abort ();
7833 #undef  BITS
7834             }
7835           break;
7836
7837         default:
7838           /* Print each byte in hex, the whole thing in native byte order.  */
7839           assert (bits % 8 == 0);
7840           const uint8_t *bytes = desc;
7841           desc += bits / 8;
7842           char hex[bits / 4 + 1];
7843           hex[bits / 4] = '\0';
7844           int incr = 1;
7845           if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
7846             {
7847               bytes += bits / 8 - 1;
7848               incr = -1;
7849             }
7850           size_t idx = 0;
7851           for (char *h = hex; bits > 0; bits -= 8, idx += incr)
7852             {
7853               *h++ = "0123456789abcdef"[bytes[idx] >> 4];
7854               *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
7855             }
7856           colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
7857                                    maxregname, name,
7858                                    2 + sizeof hex - 1, "0x%s", hex);
7859           break;
7860         }
7861       desc += regloc->pad;
7862
7863 #undef TYPES
7864     }
7865
7866   return colno;
7867 }
7868
7869
7870 struct register_info
7871 {
7872   const Ebl_Register_Location *regloc;
7873   const char *set;
7874   char name[REGNAMESZ];
7875   int regno;
7876   int bits;
7877   int type;
7878 };
7879
7880 static int
7881 register_bitpos (const struct register_info *r)
7882 {
7883   return (r->regloc->offset * 8
7884           + ((r->regno - r->regloc->regno)
7885              * (r->regloc->bits + r->regloc->pad * 8)));
7886 }
7887
7888 static int
7889 compare_sets_by_info (const struct register_info *r1,
7890                       const struct register_info *r2)
7891 {
7892   return ((int) r2->bits - (int) r1->bits
7893           ?: register_bitpos (r1) - register_bitpos (r2));
7894 }
7895
7896 /* Sort registers by set, and by size and layout offset within each set.  */
7897 static int
7898 compare_registers (const void *a, const void *b)
7899 {
7900   const struct register_info *r1 = a;
7901   const struct register_info *r2 = b;
7902
7903   /* Unused elements sort last.  */
7904   if (r1->regloc == NULL)
7905     return r2->regloc == NULL ? 0 : 1;
7906   if (r2->regloc == NULL)
7907     return -1;
7908
7909   return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
7910           ?: compare_sets_by_info (r1, r2));
7911 }
7912
7913 /* Sort register sets by layout offset of the first register in the set.  */
7914 static int
7915 compare_register_sets (const void *a, const void *b)
7916 {
7917   const struct register_info *const *p1 = a;
7918   const struct register_info *const *p2 = b;
7919   return compare_sets_by_info (*p1, *p2);
7920 }
7921
7922 static unsigned int
7923 handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
7924                        const Ebl_Register_Location *reglocs, size_t nregloc)
7925 {
7926   if (nregloc == 0)
7927     return 0;
7928
7929   ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
7930   if (maxnreg <= 0)
7931     {
7932       for (size_t i = 0; i < nregloc; ++i)
7933         if (maxnreg < reglocs[i].regno + reglocs[i].count)
7934           maxnreg = reglocs[i].regno + reglocs[i].count;
7935       assert (maxnreg > 0);
7936     }
7937
7938   struct register_info regs[maxnreg];
7939   memset (regs, 0, sizeof regs);
7940
7941   /* Sort to collect the sets together.  */
7942   int maxreg = 0;
7943   for (size_t i = 0; i < nregloc; ++i)
7944     for (int reg = reglocs[i].regno;
7945          reg < reglocs[i].regno + reglocs[i].count;
7946          ++reg)
7947       {
7948         assert (reg < maxnreg);
7949         if (reg > maxreg)
7950           maxreg = reg;
7951         struct register_info *info = &regs[reg];
7952         info->regloc = &reglocs[i];
7953         info->regno = reg;
7954         info->set = register_info (ebl, reg, &reglocs[i],
7955                                    info->name, &info->bits, &info->type);
7956       }
7957   qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
7958
7959   /* Collect the unique sets and sort them.  */
7960   inline bool same_set (const struct register_info *a,
7961                         const struct register_info *b)
7962   {
7963     return (a < &regs[maxnreg] && a->regloc != NULL
7964             && b < &regs[maxnreg] && b->regloc != NULL
7965             && a->bits == b->bits
7966             && (a->set == b->set || !strcmp (a->set, b->set)));
7967   }
7968   struct register_info *sets[maxreg + 1];
7969   sets[0] = &regs[0];
7970   size_t nsets = 1;
7971   for (int i = 1; i <= maxreg; ++i)
7972     if (regs[i].regloc != NULL && !same_set (&regs[i], &regs[i - 1]))
7973       sets[nsets++] = &regs[i];
7974   qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
7975
7976   /* Write out all the sets.  */
7977   unsigned int colno = 0;
7978   for (size_t i = 0; i < nsets; ++i)
7979     {
7980       /* Find the longest name of a register in this set.  */
7981       size_t maxname = 0;
7982       const struct register_info *end;
7983       for (end = sets[i]; same_set (sets[i], end); ++end)
7984         {
7985           size_t len = strlen (end->name);
7986           if (len > maxname)
7987             maxname = len;
7988         }
7989
7990       for (const struct register_info *reg = sets[i];
7991            reg < end;
7992            reg += reg->regloc->count ?: 1)
7993         colno = handle_core_register (ebl, core, maxname,
7994                                       reg->regloc, desc, colno);
7995
7996       /* Force a line break at the end of the group.  */
7997       colno = REGISTER_WRAP_COLUMN;
7998     }
7999
8000   return colno;
8001 }
8002
8003 static void
8004 handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
8005 {
8006   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
8007   if (data == NULL)
8008   elf_error:
8009     error (EXIT_FAILURE, 0,
8010            gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
8011
8012   const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
8013   for (size_t i = 0; i < nauxv; ++i)
8014     {
8015       GElf_auxv_t av_mem;
8016       GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
8017       if (av == NULL)
8018         goto elf_error;
8019
8020       const char *name;
8021       const char *fmt;
8022       if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
8023         {
8024           /* Unknown type.  */
8025           if (av->a_un.a_val == 0)
8026             printf ("    %" PRIu64 "\n", av->a_type);
8027           else
8028             printf ("    %" PRIu64 ": %#" PRIx64 "\n",
8029                     av->a_type, av->a_un.a_val);
8030         }
8031       else
8032         switch (fmt[0])
8033           {
8034           case '\0':            /* Normally zero.  */
8035             if (av->a_un.a_val == 0)
8036               {
8037                 printf ("    %s\n", name);
8038                 break;
8039               }
8040             /* Fall through */
8041           case 'x':             /* hex */
8042           case 'p':             /* address */
8043           case 's':             /* address of string */
8044             printf ("    %s: %#" PRIx64 "\n", name, av->a_un.a_val);
8045             break;
8046           case 'u':
8047             printf ("    %s: %" PRIu64 "\n", name, av->a_un.a_val);
8048             break;
8049           case 'd':
8050             printf ("    %s: %" PRId64 "\n", name, av->a_un.a_val);
8051             break;
8052
8053           case 'b':
8054             printf ("    %s: %#" PRIx64 "  ", name, av->a_un.a_val);
8055             GElf_Xword bit = 1;
8056             const char *pfx = "<";
8057             for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
8058               {
8059                 if (av->a_un.a_val & bit)
8060                   {
8061                     printf ("%s%s", pfx, p);
8062                     pfx = " ";
8063                   }
8064                 bit <<= 1;
8065               }
8066             printf (">\n");
8067             break;
8068
8069           default:
8070             abort ();
8071           }
8072     }
8073 }
8074
8075 static void
8076 handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
8077                   const char *name, const void *desc)
8078 {
8079   GElf_Word regs_offset;
8080   size_t nregloc;
8081   const Ebl_Register_Location *reglocs;
8082   size_t nitems;
8083   const Ebl_Core_Item *items;
8084
8085   if (! ebl_core_note (ebl, nhdr, name,
8086                        &regs_offset, &nregloc, &reglocs, &nitems, &items))
8087     return;
8088
8089   /* Pass 0 for DESCSZ when there are registers in the note,
8090      so that the ITEMS array does not describe the whole thing.
8091      For non-register notes, the actual descsz might be a multiple
8092      of the unit size, not just exactly the unit size.  */
8093   unsigned int colno = handle_core_items (ebl->elf, desc,
8094                                           nregloc == 0 ? nhdr->n_descsz : 0,
8095                                           items, nitems);
8096   if (colno != 0)
8097     putchar_unlocked ('\n');
8098
8099   colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
8100                                  reglocs, nregloc);
8101   if (colno != 0)
8102     putchar_unlocked ('\n');
8103 }
8104
8105 static void
8106 handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
8107                    GElf_Off start, Elf_Data *data)
8108 {
8109   fputs_unlocked (gettext ("  Owner          Data size  Type\n"), stdout);
8110
8111   if (data == NULL)
8112     goto bad_note;
8113
8114   size_t offset = 0;
8115   GElf_Nhdr nhdr;
8116   size_t name_offset;
8117   size_t desc_offset;
8118   while (offset < data->d_size
8119          && (offset = gelf_getnote (data, offset,
8120                                     &nhdr, &name_offset, &desc_offset)) > 0)
8121     {
8122       const char *name = data->d_buf + name_offset;
8123       const char *desc = data->d_buf + desc_offset;
8124
8125       char buf[100];
8126       char buf2[100];
8127       printf (gettext ("  %-13.*s  %9" PRId32 "  %s\n"),
8128               (int) nhdr.n_namesz, name, nhdr.n_descsz,
8129               ehdr->e_type == ET_CORE
8130               ? ebl_core_note_type_name (ebl, nhdr.n_type,
8131                                          buf, sizeof (buf))
8132               : ebl_object_note_type_name (ebl, name, nhdr.n_type,
8133                                            buf2, sizeof (buf2)));
8134
8135       /* Filter out invalid entries.  */
8136       if (memchr (name, '\0', nhdr.n_namesz) != NULL
8137           /* XXX For now help broken Linux kernels.  */
8138           || 1)
8139         {
8140           if (ehdr->e_type == ET_CORE)
8141             {
8142               if (nhdr.n_type == NT_AUXV
8143                   && (nhdr.n_namesz == 4 /* Broken old Linux kernels.  */
8144                       || (nhdr.n_namesz == 5 && name[4] == '\0'))
8145                   && !memcmp (name, "CORE", 4))
8146                 handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
8147                                   start + desc_offset);
8148               else
8149                 handle_core_note (ebl, &nhdr, name, desc);
8150             }
8151           else
8152             ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc);
8153         }
8154     }
8155
8156   if (offset == data->d_size)
8157     return;
8158
8159  bad_note:
8160   error (EXIT_FAILURE, 0,
8161          gettext ("cannot get content of note section: %s"),
8162          elf_errmsg (-1));
8163 }
8164
8165 static void
8166 handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
8167 {
8168   /* If we have section headers, just look for SHT_NOTE sections.
8169      In a debuginfo file, the program headers are not reliable.  */
8170   if (shnum != 0)
8171     {
8172       /* Get the section header string table index.  */
8173       size_t shstrndx;
8174       if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
8175         error (EXIT_FAILURE, 0,
8176                gettext ("cannot get section header string table index"));
8177
8178       Elf_Scn *scn = NULL;
8179       while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
8180         {
8181           GElf_Shdr shdr_mem;
8182           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
8183
8184           if (shdr == NULL || shdr->sh_type != SHT_NOTE)
8185             /* Not what we are looking for.  */
8186             continue;
8187
8188           printf (gettext ("\
8189 \nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
8190                   elf_ndxscn (scn),
8191                   elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
8192                   shdr->sh_size, shdr->sh_offset);
8193
8194           handle_notes_data (ebl, ehdr, shdr->sh_offset,
8195                              elf_getdata (scn, NULL));
8196         }
8197       return;
8198     }
8199
8200   /* We have to look through the program header to find the note
8201      sections.  There can be more than one.  */
8202   for (size_t cnt = 0; cnt < phnum; ++cnt)
8203     {
8204       GElf_Phdr mem;
8205       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
8206
8207       if (phdr == NULL || phdr->p_type != PT_NOTE)
8208         /* Not what we are looking for.  */
8209         continue;
8210
8211       printf (gettext ("\
8212 \nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
8213               phdr->p_filesz, phdr->p_offset);
8214
8215       handle_notes_data (ebl, ehdr, phdr->p_offset,
8216                          elf_getdata_rawchunk (ebl->elf,
8217                                                phdr->p_offset, phdr->p_filesz,
8218                                                ELF_T_NHDR));
8219     }
8220 }
8221
8222
8223 static void
8224 hex_dump (const uint8_t *data, size_t len)
8225 {
8226   size_t pos = 0;
8227   while (pos < len)
8228     {
8229       printf ("  0x%08Zx ", pos);
8230
8231       const size_t chunk = MIN (len - pos, 16);
8232
8233       for (size_t i = 0; i < chunk; ++i)
8234         if (i % 4 == 3)
8235           printf ("%02x ", data[pos + i]);
8236         else
8237           printf ("%02x", data[pos + i]);
8238
8239       if (chunk < 16)
8240         printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
8241
8242       for (size_t i = 0; i < chunk; ++i)
8243         {
8244           unsigned char b = data[pos + i];
8245           printf ("%c", isprint (b) ? b : '.');
8246         }
8247
8248       putchar ('\n');
8249       pos += chunk;
8250     }
8251 }
8252
8253 static void
8254 dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
8255 {
8256   if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
8257     printf (gettext ("\nSection [%Zu] '%s' has no data to dump.\n"),
8258             elf_ndxscn (scn), name);
8259   else
8260     {
8261       Elf_Data *data = elf_rawdata (scn, NULL);
8262       if (data == NULL)
8263         error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
8264                elf_ndxscn (scn), name, elf_errmsg (-1));
8265       else
8266         {
8267           printf (gettext ("\nHex dump of section [%Zu] '%s', %" PRIu64
8268                            " bytes at offset %#0" PRIx64 ":\n"),
8269                   elf_ndxscn (scn), name,
8270                   shdr->sh_size, shdr->sh_offset);
8271           hex_dump (data->d_buf, data->d_size);
8272         }
8273     }
8274 }
8275
8276 static void
8277 print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
8278 {
8279   if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
8280     printf (gettext ("\nSection [%Zu] '%s' has no strings to dump.\n"),
8281             elf_ndxscn (scn), name);
8282   else
8283     {
8284       Elf_Data *data = elf_rawdata (scn, NULL);
8285       if (data == NULL)
8286         error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
8287                elf_ndxscn (scn), name, elf_errmsg (-1));
8288       else
8289         {
8290           printf (gettext ("\nString section [%Zu] '%s' contains %" PRIu64
8291                            " bytes at offset %#0" PRIx64 ":\n"),
8292                   elf_ndxscn (scn), name,
8293                   shdr->sh_size, shdr->sh_offset);
8294
8295           const char *start = data->d_buf;
8296           const char *const limit = start + data->d_size;
8297           do
8298             {
8299               const char *end = memchr (start, '\0', limit - start);
8300               const size_t pos = start - (const char *) data->d_buf;
8301               if (unlikely (end == NULL))
8302                 {
8303                   printf ("  [%6Zx]- %.*s\n",
8304                           pos, (int) (limit - start), start);
8305                   break;
8306                 }
8307               printf ("  [%6Zx]  %s\n", pos, start);
8308               start = end + 1;
8309             } while (start < limit);
8310         }
8311     }
8312 }
8313
8314 static void
8315 for_each_section_argument (Elf *elf, const struct section_argument *list,
8316                            void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
8317                                          const char *name))
8318 {
8319   /* Get the section header string table index.  */
8320   size_t shstrndx;
8321   if (elf_getshdrstrndx (elf, &shstrndx) < 0)
8322     error (EXIT_FAILURE, 0,
8323            gettext ("cannot get section header string table index"));
8324
8325   for (const struct section_argument *a = list; a != NULL; a = a->next)
8326     {
8327       Elf_Scn *scn;
8328       GElf_Shdr shdr_mem;
8329       const char *name = NULL;
8330
8331       char *endp = NULL;
8332       unsigned long int shndx = strtoul (a->arg, &endp, 0);
8333       if (endp != a->arg && *endp == '\0')
8334         {
8335           scn = elf_getscn (elf, shndx);
8336           if (scn == NULL)
8337             {
8338               error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
8339               continue;
8340             }
8341
8342           if (gelf_getshdr (scn, &shdr_mem) == NULL)
8343             error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
8344                    elf_errmsg (-1));
8345           name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
8346         }
8347       else
8348         {
8349           /* Need to look up the section by name.  */
8350           scn = NULL;
8351           bool found = false;
8352           while ((scn = elf_nextscn (elf, scn)) != NULL)
8353             {
8354               if (gelf_getshdr (scn, &shdr_mem) == NULL)
8355                 continue;
8356               name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
8357               if (name == NULL)
8358                 continue;
8359               if (!strcmp (name, a->arg))
8360                 {
8361                   found = true;
8362                   (*dump) (scn, &shdr_mem, name);
8363                 }
8364             }
8365
8366           if (unlikely (!found) && !a->implicit)
8367             error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
8368         }
8369     }
8370 }
8371
8372 static void
8373 dump_data (Ebl *ebl)
8374 {
8375   for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
8376 }
8377
8378 static void
8379 dump_strings (Ebl *ebl)
8380 {
8381   for_each_section_argument (ebl->elf, string_sections, &print_string_section);
8382 }
8383
8384 static void
8385 print_strings (Ebl *ebl)
8386 {
8387   /* Get the section header string table index.  */
8388   size_t shstrndx;
8389   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
8390     error (EXIT_FAILURE, 0,
8391            gettext ("cannot get section header string table index"));
8392
8393   Elf_Scn *scn;
8394   GElf_Shdr shdr_mem;
8395   const char *name;
8396   scn = NULL;
8397   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
8398     {
8399       if (gelf_getshdr (scn, &shdr_mem) == NULL)
8400         continue;
8401
8402       if (shdr_mem.sh_type != SHT_PROGBITS
8403           || !(shdr_mem.sh_flags & SHF_STRINGS))
8404         continue;
8405
8406       name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
8407       if (name == NULL)
8408         continue;
8409
8410       print_string_section (scn, &shdr_mem, name);
8411     }
8412 }
8413
8414 static void
8415 dump_archive_index (Elf *elf, const char *fname)
8416 {
8417   size_t narsym;
8418   const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
8419   if (arsym == NULL)
8420     {
8421       int result = elf_errno ();
8422       if (unlikely (result != ELF_E_NO_INDEX))
8423         error (EXIT_FAILURE, 0,
8424                gettext ("cannot get symbol index of archive '%s': %s"),
8425                fname, elf_errmsg (result));
8426       else
8427         printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
8428       return;
8429     }
8430
8431   printf (gettext ("\nIndex of archive '%s' has %Zu entries:\n"),
8432           fname, narsym);
8433
8434   size_t as_off = 0;
8435   for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
8436     {
8437       if (s->as_off != as_off)
8438         {
8439           as_off = s->as_off;
8440
8441           Elf *subelf;
8442           if (unlikely (elf_rand (elf, as_off) == 0)
8443               || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
8444                            == NULL))
8445 #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
8446             while (1)
8447 #endif
8448               error (EXIT_FAILURE, 0,
8449                      gettext ("cannot extract member at offset %Zu in '%s': %s"),
8450                      as_off, fname, elf_errmsg (-1));
8451
8452           const Elf_Arhdr *h = elf_getarhdr (subelf);
8453
8454           printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
8455
8456           elf_end (subelf);
8457         }
8458
8459       printf ("\t%s\n", s->as_name);
8460     }
8461 }
8462
8463 #include "debugpred.h"