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