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