• 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 Red Hat, Inc.
3    Written by Ulrich Drepper <drepper@redhat.com>, 1999.
4 
5    This program is Open Source software; you can redistribute it and/or
6    modify it under the terms of the Open Software License version 1.0 as
7    published by the Open Source Initiative.
8 
9    You should have received a copy of the Open Software License along
10    with this program; if not, you may obtain a copy of the Open Software
11    License version 1.0 from http://www.opensource.org/licenses/osl.php or
12    by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13    3001 King Ranch Road, Ukiah, CA 95482.   */
14 
15 #ifdef HAVE_CONFIG_H
16 # include <config.h>
17 #endif
18 
19 #include <argp.h>
20 #include <assert.h>
21 #include <dwarf.h>
22 #include <errno.h>
23 #include <error.h>
24 #include <fcntl.h>
25 #include <gelf.h>
26 #include <inttypes.h>
27 #include <langinfo.h>
28 #include <libdw.h>
29 #include <libebl.h>
30 #include <libintl.h>
31 #include <locale.h>
32 #include <stdbool.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <time.h>
36 #include <unistd.h>
37 #include <sys/param.h>
38 
39 #include <system.h>
40 #include "../libdw/libdwP.h"
41 #include "../libdw/memory-access.h"
42 
43 
44 /* Name and version of program.  */
45 static void print_version (FILE *stream, struct argp_state *state);
46 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
47 
48 /* Definitions of arguments for argp functions.  */
49 static const struct argp_option options[] =
50 {
51   { NULL, 0, NULL, 0, N_("Output selection:") },
52   { "all", 'a', NULL, 0, N_("Equivalent to: -h -l") },
53   { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment") },
54   { "file-header", 'h', NULL, 0, N_("Display the ELF file header") },
55   { "histogram", 'I', NULL, 0,
56     N_("Display histogram of bucket list lengths") },
57   { "program-headers", 'l', NULL, 0, N_("Display the program headers") },
58   { "relocs", 'r', NULL, 0, N_("Display relocations") },
59   { "section-headers", 'S', NULL, 0, N_("Display the sections' header") },
60   { "symbols", 's', NULL, 0, N_("Display the symbol table") },
61   { "version-info", 'V', NULL, 0, N_("Display versioning information") },
62   { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
63     N_("Display DWARF section content.  SECTION can be one of abbrev, "
64        "aranges, frame, info, loc, line, pubnames, str, or macinfo.") },
65   { "notes", 'n', NULL, 0, N_("Display the core notes") },
66   { "arch-specific", 'A', NULL, 0,
67     N_("Display architecture specific information (if any)") },
68 
69   { NULL, 0, NULL, 0, N_("Output control:") },
70 
71   { NULL, 0, NULL, 0, NULL }
72 };
73 
74 /* Short description of program.  */
75 static const char doc[] = N_("\
76 Print information from ELF file in human-readable form.");
77 
78 /* Strings for arguments in help texts.  */
79 static const char args_doc[] = N_("FILE...");
80 
81 /* Prototype for option handler.  */
82 static error_t parse_opt (int key, char *arg, struct argp_state *state);
83 
84 /* Function to print some extra text in the help message.  */
85 static char *more_help (int key, const char *text, void *input);
86 
87 /* Data structure to communicate with argp functions.  */
88 static struct argp argp =
89 {
90   options, parse_opt, args_doc, doc, NULL, more_help
91 };
92 
93 
94 /* Flags set by the option controlling the output.  */
95 
96 /* True if any of the control options is set.  */
97 static bool any_control_option;
98 
99 /* True if dynamic segment should be printed.  */
100 static bool print_dynamic_table;
101 
102 /* True if the file header should be printed.  */
103 static bool print_file_header;
104 
105 /* True if the program headers should be printed.  */
106 static bool print_program_header;
107 
108 /* True if relocations should be printed.  */
109 static bool print_relocations;
110 
111 /* True if the section headers should be printed.  */
112 static bool print_section_header;
113 
114 /* True if the symbol table should be printed.  */
115 static bool print_symbol_table;
116 
117 /* True if the version information should be printed.  */
118 static bool print_version_info;
119 
120 /* True if section groups should be printed.  */
121 static bool print_section_groups;
122 
123 /* True if bucket list length histogram should be printed.  */
124 static bool print_histogram;
125 
126 /* True if the architecture specific data should be printed.  */
127 static bool print_arch;
128 
129 /* True if note section content should be printed.  */
130 static bool print_notes;
131 
132 /* Select printing of debugging sections.  */
133 static enum section_e
134 {
135   section_abbrev = 1,	/* .debug_abbrev  */
136   section_aranges = 2,	/* .debug_aranges  */
137   section_frame = 4,	/* .debug_frame or .eh_frame  */
138   section_info = 8,	/* .debug_info  */
139   section_line = 16,	/* .debug_line  */
140   section_loc = 32,	/* .debug_loc  */
141   section_pubnames = 64,/* .debug_pubnames  */
142   section_str = 128,	/* .debug_str  */
143   section_macinfo = 256,/* .debug_macinfo  */
144   section_all = (section_abbrev | section_aranges | section_frame
145 		 | section_info | section_line | section_loc
146 		 | section_pubnames | section_str | section_macinfo)
147 } print_debug_sections;
148 
149 /* Number of sections in the file.  */
150 static size_t shnum;
151 
152 
153 /* Declarations of local functions.  */
154 static void process_file (int fd, Elf *elf, const char *prefix,
155 			  const char *fname, bool only_one);
156 static void process_elf_file (Elf *elf, const char *prefix, const char *fname,
157 			      bool only_one);
158 static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
159 static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
160 static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
161 static void print_scngrp (Ebl *ebl, GElf_Ehdr *ehdr);
162 static void print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr);
163 static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
164 static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
165 			       GElf_Shdr *shdr);
166 static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
167 				GElf_Shdr *shdr);
168 static void print_symtab (Ebl *ebl, GElf_Ehdr *ehdr, int type);
169 static void handle_symtab (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
170 			   GElf_Shdr *shdr);
171 static void print_verinfo (Ebl *ebl, GElf_Ehdr *ehdr);
172 static void handle_verneed (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
173 			    GElf_Shdr *shdr);
174 static void handle_verdef (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
175 			   GElf_Shdr *shdr);
176 static void handle_versym (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
177 			   GElf_Shdr *shdr);
178 static void print_debug (Ebl *ebl, GElf_Ehdr *ehdr);
179 static void handle_hash (Ebl *ebl, GElf_Ehdr *ehdr);
180 static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
181 static void print_liblist (Ebl *ebl, GElf_Ehdr *ehdr);
182 
183 
184 int
main(int argc,char * argv[])185 main (int argc, char *argv[])
186 {
187   int remaining;
188   bool only_one;
189 
190   /* Set locale.  */
191   setlocale (LC_ALL, "");
192 
193   /* Initialize the message catalog.  */
194   textdomain (PACKAGE);
195 
196   /* Parse and process arguments.  */
197   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
198 
199   /* If no control option or no ELF file is given punt.  */
200   if ((any_control_option == 0 && print_debug_sections == 0)
201       || remaining >= argc)
202     {
203       argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
204 		 program_invocation_short_name);
205       exit (1);
206     }
207 
208   /* Before we start tell the ELF library which version we are using.  */
209   elf_version (EV_CURRENT);
210 
211   /* Now process all the files given at the command line.  */
212   only_one = remaining + 1 == argc;
213   do
214     {
215       int fd;
216       Elf *elf;
217 
218       /* Open the file.  */
219       fd = open (argv[remaining], O_RDONLY);
220       if (fd == -1)
221 	{
222 	  error (0, errno, gettext ("cannot open input file"));
223 	  continue;
224 	}
225 
226       /* Create an `Elf' descriptor.  */
227       elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
228       if (elf == NULL)
229 	error (0, 0, gettext ("cannot generate Elf descriptor: %s\n"),
230 	       elf_errmsg (-1));
231       else
232 	{
233 	  process_file (fd, elf, NULL, argv[remaining], only_one);
234 
235 	  /* Now we can close the descriptor.  */
236 	  if (elf_end (elf) != 0)
237 	    error (0, 0, gettext ("error while closing Elf descriptor: %s"),
238 		   elf_errmsg (-1));
239 	}
240 
241       close (fd);
242     }
243   while (++remaining < argc);
244 
245   return error_message_count != 0;
246 }
247 
248 
249 /* Handle program arguments.  */
250 static error_t
parse_opt(int key,char * arg,struct argp_state * state)251 parse_opt (int key, char *arg, struct argp_state *state)
252 {
253   switch (key)
254     {
255     case 'a':
256       print_file_header = true;
257       print_program_header = true;
258       print_relocations = true;
259       print_section_header = true;
260       print_symbol_table = true;
261       print_version_info = true;
262       print_dynamic_table = true;
263       print_section_groups = true;
264       print_histogram = true;
265       print_arch = true;
266       print_notes = true;
267       any_control_option = true;
268       break;
269     case 'A':
270       print_arch = true;
271       any_control_option = true;
272       break;
273     case 'd':
274       print_dynamic_table = true;
275       any_control_option = true;
276       break;
277     case 'g':
278       print_section_groups = true;
279       any_control_option = true;
280       break;
281     case 'h':
282       print_file_header = true;
283       any_control_option = true;
284       break;
285     case 'I':
286       print_histogram = true;
287       any_control_option = true;
288       break;
289     case 'l':
290       print_program_header = true;
291       any_control_option = true;
292       break;
293     case 'n':
294       print_notes = true;
295       any_control_option = true;
296       break;
297     case 'r':
298       print_relocations = true;
299       any_control_option = true;
300      break;
301     case 'S':
302       print_section_header = true;
303       any_control_option = true;
304       break;
305     case 's':
306       print_symbol_table = true;
307       any_control_option = true;
308       break;
309     case 'V':
310       print_version_info = true;
311       any_control_option = true;
312       break;
313     case 'w':
314       if (arg == NULL)
315 	print_debug_sections = section_all;
316       else if (strcmp (arg, "abbrev") == 0)
317 	print_debug_sections |= section_abbrev;
318       else if (strcmp (arg, "aranges") == 0)
319 	print_debug_sections |= section_aranges;
320       else if (strcmp (arg, "frame") == 0)
321 	print_debug_sections |= section_frame;
322       else if (strcmp (arg, "info") == 0)
323 	print_debug_sections |= section_info;
324       else if (strcmp (arg, "loc") == 0)
325 	print_debug_sections |= section_loc;
326       else if (strcmp (arg, "line") == 0)
327 	print_debug_sections |= section_line;
328       else if (strcmp (arg, "pubnames") == 0)
329 	print_debug_sections |= section_pubnames;
330       else if (strcmp (arg, "str") == 0)
331 	print_debug_sections |= section_str;
332       else if (strcmp (arg, "macinfo") == 0)
333 	print_debug_sections |= section_macinfo;
334       else
335 	{
336 	  fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
337 		   arg);
338 	  argp_help (&argp, stderr, ARGP_HELP_SEE,
339 		     program_invocation_short_name);
340 	  exit (1);
341 	}
342       break;
343     default:
344       return ARGP_ERR_UNKNOWN;
345     }
346   return 0;
347 }
348 
349 
350 static char *
more_help(int key,const char * text,void * input)351 more_help (int key, const char *text, void *input)
352 {
353   char *buf;
354 
355   switch (key)
356     {
357     case ARGP_KEY_HELP_EXTRA:
358       /* We print some extra information.  */
359       if (asprintf (&buf, gettext ("Please report bugs to %s.\n"),
360 		    PACKAGE_BUGREPORT) < 0)
361 	buf = NULL;
362       return buf;
363 
364     default:
365       break;
366     }
367   return (char *) text;
368 }
369 
370 
371 /* Print the version information.  */
372 static void
print_version(FILE * stream,struct argp_state * state)373 print_version (FILE *stream, struct argp_state *state)
374 {
375   fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, VERSION);
376   fprintf (stream, gettext ("\
377 Copyright (C) %s Red Hat, Inc.\n\
378 This is free software; see the source for copying conditions.  There is NO\n\
379 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
380 "), "2004");
381   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
382 }
383 
384 
385 /* Process one file.  */
386 static void
process_file(int fd,Elf * elf,const char * prefix,const char * fname,bool only_one)387 process_file (int fd, Elf *elf, const char *prefix, const char *fname,
388 	      bool only_one)
389 {
390   /* We can handle two types of files: ELF files and archives.  */
391   Elf_Kind kind = elf_kind (elf);
392   struct stat64 st;
393 
394   switch (kind)
395     {
396     case ELF_K_ELF:
397       /* Yes!  It's an ELF file.  */
398       process_elf_file (elf, prefix, fname, only_one);
399       break;
400 
401     case ELF_K_AR:
402       {
403 	Elf *subelf;
404 	Elf_Cmd cmd = ELF_C_READ_MMAP;
405 	size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
406 	size_t fname_len = strlen (fname) + 1;
407 	char new_prefix[prefix_len + 1 + fname_len];
408 	char *cp = new_prefix;
409 
410 	/* Create the full name of the file.  */
411 	if (prefix != NULL)
412 	  {
413 	    cp = mempcpy (cp, prefix, prefix_len);
414 	    *cp++ = ':';
415 	  }
416 	memcpy (cp, fname, fname_len);
417 
418 	/* It's an archive.  We process each file in it.  */
419 	while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
420 	  {
421 	    kind = elf_kind (subelf);
422 
423 	    /* Call this function recursively.  */
424 	    if (kind == ELF_K_ELF || kind == ELF_K_AR)
425 	      {
426 		Elf_Arhdr *arhdr = elf_getarhdr (subelf);
427 		assert (arhdr != NULL);
428 
429 		process_file (fd, subelf, new_prefix, arhdr->ar_name, false);
430 	      }
431 
432 	    /* Get next archive element.  */
433 	    cmd = elf_next (subelf);
434 	    if (elf_end (subelf) != 0)
435 	      error (0, 0,
436 		     gettext (" error while freeing sub-ELF descriptor: %s\n"),
437 		     elf_errmsg (-1));
438 	  }
439       }
440       break;
441 
442     default:
443       if (fstat64 (fd, &st) != 0)
444 	error (0, errno, gettext ("cannot stat input file"));
445       else if (st.st_size == 0)
446 	error (0, 0, gettext ("input file is empty"));
447       else
448 	/* We cannot do anything.  */
449 	error (0, 0, gettext ("\
450 Not an ELF file - it has the wrong magic bytes at the start"));
451       break;
452     }
453 }
454 
455 
456 /* Process one file.  */
457 static void
process_elf_file(Elf * elf,const char * prefix,const char * fname,bool only_one)458 process_elf_file (Elf *elf, const char *prefix, const char *fname,
459 		  bool only_one)
460 {
461   GElf_Ehdr ehdr_mem;
462   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
463   Ebl *ebl;
464 
465   /* Print the file name.  */
466   if (!only_one)
467     {
468       if (prefix != NULL)
469 	printf ("\n%s(%s):\n\n", prefix, fname);
470       else
471 	printf ("\n%s:\n\n", fname);
472     }
473 
474   if (ehdr == NULL)
475     {
476       error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
477       return;
478     }
479 
480   ebl = ebl_openbackend (elf);
481   if (ebl == NULL)
482     {
483       error (0, errno, gettext ("cannot create EBL handle"));
484       return;
485     }
486 
487   /* Determine the number of sections.  */
488   if (elf_getshnum (ebl->elf, &shnum) < 0)
489     error (EXIT_FAILURE, 0,
490 	   gettext ("cannot determine number of sections: %s"),
491 	   elf_errmsg (-1));
492 
493   if (print_file_header)
494     print_ehdr (ebl, ehdr);
495   if (print_section_header)
496     print_shdr (ebl, ehdr);
497   if (print_program_header)
498     print_phdr (ebl, ehdr);
499   if (print_section_groups)
500     print_scngrp (ebl, ehdr);
501   if (print_dynamic_table)
502     print_dynamic (ebl, ehdr);
503   if (print_relocations)
504     print_relocs (ebl, ehdr);
505   if (print_histogram)
506     handle_hash (ebl, ehdr);
507   if (print_symbol_table)
508     print_symtab (ebl, ehdr, SHT_DYNSYM);
509   if (print_version_info)
510     print_verinfo (ebl, ehdr);
511   if (print_symbol_table)
512     print_symtab (ebl, ehdr, SHT_SYMTAB);
513   if (print_arch)
514     print_liblist (ebl, ehdr);
515   if (print_debug_sections != 0)
516     print_debug (ebl, ehdr);
517   if (print_notes)
518     handle_notes (ebl, ehdr);
519 
520   ebl_closebackend (ebl);
521 }
522 
523 
524 /* Print file type.  */
525 static void
print_file_type(unsigned short int e_type)526 print_file_type (unsigned short int e_type)
527 {
528   if (e_type <= ET_CORE)
529     {
530       static const char *knowntypes[] =
531       {
532 	N_("NONE (None)"),
533 	N_("REL (Relocatable file)"),
534 	N_("EXEC (Executable file)"),
535 	N_("DYN (Shared object file)"),
536 	N_("CORE (Core file)")
537       };
538       puts (gettext (knowntypes[e_type]));
539     }
540   else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
541     printf (gettext ("OS Specific: (%x)\n"),  e_type);
542   else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
543     printf (gettext ("Processor Specific: (%x)\n"),  e_type);
544   else
545     puts ("???");
546 }
547 
548 
549 /* Print ELF header.  */
550 static void
print_ehdr(Ebl * ebl,GElf_Ehdr * ehdr)551 print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
552 {
553   char buf[512];
554   size_t cnt;
555 
556   fputs_unlocked (gettext ("ELF Header:\n  Magic:  "), stdout);
557   for (cnt = 0; cnt < EI_NIDENT; ++cnt)
558     printf (" %02hhx", ehdr->e_ident[cnt]);
559 
560   printf (gettext ("\n  Class:                             %s\n"),
561 	  ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
562 	  : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
563 	  : "\?\?\?");
564 
565   printf (gettext ("  Data:                              %s\n"),
566 	  ehdr->e_ident[EI_DATA] == ELFDATA2LSB
567 	  ? "2's complement, little endian"
568 	  : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
569 	  ? "2's complement, big endian" : "\?\?\?");
570 
571   printf (gettext ("  Version:                           %hhd %s\n"),
572 	  ehdr->e_ident[EI_VERSION],
573 	  ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
574 	  : "(\?\?\?)");
575 
576   printf (gettext ("  OS/ABI:                            %s\n"),
577 	  ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
578 
579   printf (gettext ("  ABI Version:                       %hhd\n"),
580 	  ehdr->e_ident[EI_ABIVERSION]);
581 
582   fputs_unlocked (gettext ("  Type:                              "), stdout);
583   print_file_type (ehdr->e_type);
584 
585   printf (gettext ("  Machine:                           %s\n"), ebl->name);
586 
587   printf (gettext ("  Version:                           %d %s\n"),
588 	  ehdr->e_version,
589 	  ehdr->e_version  == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
590 
591   printf (gettext ("  Entry point address:               %#" PRIx64 "\n"),
592 	  ehdr->e_entry);
593 
594   printf (gettext ("  Start of program headers:          %" PRId64 " %s\n"),
595 	  ehdr->e_phoff, gettext ("(bytes into file)"));
596 
597   printf (gettext ("  Start of section headers:          %" PRId64 " %s\n"),
598 	  ehdr->e_shoff, gettext ("(bytes into file)"));
599 
600   printf (gettext ("  Flags:                             %s\n"),
601 	  ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
602 
603   printf (gettext ("  Size of this header:               %" PRId16 " %s\n"),
604 	  ehdr->e_ehsize, gettext ("(bytes)"));
605 
606   printf (gettext ("  Size of program header entries:    %" PRId16 " %s\n"),
607 	  ehdr->e_phentsize, gettext ("(bytes)"));
608 
609   printf (gettext ("  Number of program headers entries: %" PRId16 "\n"),
610 	  ehdr->e_phnum);
611 
612   printf (gettext ("  Size of section header entries:    %" PRId16 " %s\n"),
613 	  ehdr->e_shentsize, gettext ("(bytes)"));
614 
615   printf (gettext ("  Number of section headers entries: %" PRId16),
616 	  ehdr->e_shnum);
617   if (ehdr->e_shnum == 0)
618     {
619       GElf_Shdr shdr_mem;
620       GElf_Shdr *shdr;
621 
622       shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
623       if (shdr != NULL)
624 	printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
625 		(uint32_t) shdr->sh_size);
626       else
627 	fputs_unlocked (gettext (" ([0] not available)"), stdout);
628     }
629   fputc_unlocked ('\n', stdout);
630 
631   if (ehdr->e_shstrndx == SHN_XINDEX)
632     {
633       GElf_Shdr shdr_mem;
634       GElf_Shdr *shdr;
635 
636       shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
637       if (shdr != NULL)
638 	/* We managed to get the zeroth section.  */
639 	snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
640 		  (uint32_t) shdr->sh_link);
641       else
642 	{
643 	  strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
644 	  buf[sizeof (buf) - 1] = '\0';
645 	}
646 
647       printf (gettext ("  Section header string table index: XINDEX%s\n\n"),
648 	      buf);
649     }
650   else
651     printf (gettext ("  Section header string table index: %" PRId16 "\n\n"),
652 	    ehdr->e_shstrndx);
653 }
654 
655 
656 static const char *
get_visibility_type(int value)657 get_visibility_type (int value)
658 {
659   switch (value)
660     {
661     case STV_DEFAULT:
662       return "DEFAULT";
663     case STV_INTERNAL:
664       return "INTERNAL";
665     case STV_HIDDEN:
666       return "HIDDEN";
667     case STV_PROTECTED:
668       return "PROTECTED";
669     default:
670       return "???";
671     }
672 }
673 
674 
675 /* Print the section headers.  */
676 static void
print_shdr(Ebl * ebl,GElf_Ehdr * ehdr)677 print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
678 {
679   size_t cnt;
680   size_t shstrndx;
681 
682   if (! print_file_header)
683     printf (gettext ("\
684 There are %d section headers, starting at offset %#" PRIx64 ":\n\
685 \n"),
686 	    ehdr->e_shnum, ehdr->e_shoff);
687 
688   /* Get the section header string table index.  */
689   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
690     error (EXIT_FAILURE, 0,
691 	   gettext ("cannot get section header string table index"));
692 
693   puts (gettext ("Section Headers:"));
694 
695   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
696     puts (gettext ("[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al"));
697   else
698     puts (gettext ("[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al"));
699 
700   for (cnt = 0; cnt < shnum; ++cnt)
701     {
702       char buf[128];
703       char flagbuf[20];
704       char *cp;
705       Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
706       GElf_Shdr shdr_mem;
707       GElf_Shdr *shdr;
708 
709       if (scn == NULL)
710 	error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
711 	       elf_errmsg (-1));
712 
713       /* Get the section header.  */
714       shdr = gelf_getshdr (scn, &shdr_mem);
715       if (shdr == NULL)
716 	error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
717 	       elf_errmsg (-1));
718 
719       cp = flagbuf;
720       if (shdr->sh_flags & SHF_WRITE)
721 	*cp++ = 'W';
722       if (shdr->sh_flags & SHF_ALLOC)
723 	*cp++ = 'A';
724       if (shdr->sh_flags & SHF_EXECINSTR)
725 	*cp++ = 'X';
726       if (shdr->sh_flags & SHF_MERGE)
727 	*cp++ = 'M';
728       if (shdr->sh_flags & SHF_STRINGS)
729 	*cp++ = 'S';
730       if (shdr->sh_flags & SHF_INFO_LINK)
731 	*cp++ = 'I';
732       if (shdr->sh_flags & SHF_LINK_ORDER)
733 	*cp++ = 'L';
734       if (shdr->sh_flags & SHF_OS_NONCONFORMING)
735 	*cp++ = 'N';
736       if (shdr->sh_flags & SHF_GROUP)
737 	*cp++ = 'G';
738       if (shdr->sh_flags & SHF_TLS)
739 	*cp++ = 'T';
740       if (shdr->sh_flags & SHF_ORDERED)
741 	*cp++ = 'O';
742       if (shdr->sh_flags & SHF_EXCLUDE)
743 	*cp++ = 'E';
744       *cp = '\0';
745 
746       printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
747 	      " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
748 	      " %2" PRId64 "\n",
749 	      cnt,
750 	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
751 	      ?: "<corrupt>",
752 	      ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
753 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
754 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
755 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
756 	      shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
757 	      shdr->sh_addralign);
758     }
759 
760   fputc_unlocked ('\n', stdout);
761 }
762 
763 
764 /* Print the program header.  */
765 static void
print_phdr(Ebl * ebl,GElf_Ehdr * ehdr)766 print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
767 {
768   size_t cnt;
769   size_t shstrndx;
770 
771   if (ehdr->e_phnum == 0)
772     /* No program header, this is OK in relocatable objects.  */
773     return;
774 
775   puts (gettext ("Program Headers:"));
776   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
777     puts (gettext ("\
778   Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"));
779   else
780     puts (gettext ("\
781   Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align"));
782 
783   /* Process all program headers.  */
784   bool has_relro = false;
785   GElf_Addr relro_from = 0;
786   GElf_Addr relro_to = 0;
787   for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
788     {
789       char buf[128];
790       GElf_Phdr mem;
791       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
792 
793       /* If for some reason the header cannot be returned show this.  */
794       if (phdr == NULL)
795 	{
796 	  puts ("  ???");
797 	  continue;
798 	}
799 
800       printf ("  %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
801 	      " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
802 	      ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
803 	      phdr->p_offset,
804 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
805 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
806 	      phdr->p_filesz,
807 	      phdr->p_memsz,
808 	      phdr->p_flags & PF_R ? 'R' : ' ',
809 	      phdr->p_flags & PF_W ? 'W' : ' ',
810 	      phdr->p_flags & PF_X ? 'E' : ' ',
811 	      phdr->p_align);
812 
813       if (phdr->p_type == PT_INTERP)
814 	{
815 	  /* We can show the user the name of the interpreter.  */
816 	  size_t maxsize;
817 	  char *filedata = elf_rawfile (ebl->elf, &maxsize);
818 
819 	  if (filedata != NULL && phdr->p_offset < maxsize)
820 	    printf (gettext ("\t[Requesting program interpreter: %s]\n"),
821 		    filedata + phdr->p_offset);
822 	}
823       else if (phdr->p_type == PT_GNU_RELRO)
824 	{
825 	  has_relro = true;
826 	  relro_from = phdr->p_vaddr;
827 	  relro_to = relro_from + phdr->p_memsz;
828 	}
829     }
830 
831   /* Get the section header string table index.  */
832   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
833     error (EXIT_FAILURE, 0,
834 	   gettext ("cannot get section header string table index"));
835 
836   puts (gettext ("\n Section to Segment mapping:\n  Segment Sections..."));
837 
838   for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
839     {
840       GElf_Phdr phdr_mem;
841       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
842       size_t inner;
843 
844       /* Print the segment number.  */
845       printf ("   %2.2zu     ", cnt);
846 
847       /* This must not happen.  */
848       if (phdr == NULL)
849 	error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
850 	       elf_errmsg (-1));
851 
852       /* Iterate over the sections.  */
853       bool in_relro = false;
854       for (inner = 1; inner < shnum; ++inner)
855 	{
856 	  Elf_Scn *scn = elf_getscn (ebl->elf, inner);
857 	  GElf_Shdr shdr_mem;
858 	  GElf_Shdr *shdr;
859 
860 	  /* It should not happen.  */
861 	  if (scn == NULL)
862 	    error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
863 		   elf_errmsg (-1));
864 
865 	  /* Get the section header.  */
866 	  shdr = gelf_getshdr (scn, &shdr_mem);
867 	  if (shdr == NULL)
868 	    error (EXIT_FAILURE, 0,
869 		   gettext ("cannot get section header: %s"),
870 		   elf_errmsg (-1));
871 
872 	  if (shdr->sh_size > 0
873 	      /* Compare allocated sections by VMA, unallocated
874 		 sections by file offset.  */
875 	      && (shdr->sh_flags & SHF_ALLOC
876 		  ? (shdr->sh_addr >= phdr->p_vaddr
877 		     && (shdr->sh_addr + shdr->sh_size
878 			 <= phdr->p_vaddr + phdr->p_memsz))
879 		  : (shdr->sh_offset >= phdr->p_offset
880 		     && (shdr->sh_offset + shdr->sh_size
881 			 <= phdr->p_offset + phdr->p_filesz))))
882 	    {
883 	      if (has_relro && !in_relro
884 		  && shdr->sh_addr >= relro_from
885 		  && shdr->sh_addr + shdr->sh_size <= relro_to)
886 		{
887 		  fputs_unlocked (" [RELRO:", stdout);
888 		  in_relro = true;
889 		}
890 	      else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
891 		{
892 		  fputs_unlocked ("]", stdout);
893 		  in_relro =  false;
894 		}
895 	      else if (has_relro && in_relro
896 		       && shdr->sh_addr + shdr->sh_size > relro_to)
897 		fputs_unlocked ("] <RELRO:", stdout);
898 
899 	      printf (" %s",
900 		      elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
901 
902 	      /* Signal that this sectin is only partially covered.  */
903 	      if (has_relro && in_relro
904 		       && shdr->sh_addr + shdr->sh_size > relro_to)
905 		{
906 		  fputs_unlocked (">", stdout);
907 		  in_relro =  false;
908 		}
909 	    }
910 	}
911       if (in_relro)
912 	fputs_unlocked ("]", stdout);
913 
914       /* Finish the line.  */
915       fputc_unlocked ('\n', stdout);
916     }
917 }
918 
919 
920 static void
handle_scngrp(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)921 handle_scngrp (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
922 {
923   Elf_Data *data;
924   Elf32_Word *grpref;
925   Elf_Scn *symscn;
926   GElf_Shdr symshdr_mem;
927   GElf_Shdr *symshdr;
928   Elf_Data *symdata;
929   GElf_Sym sym_mem;
930   size_t cnt;
931   size_t shstrndx;
932 
933   /* Get the data of the section.  */
934   data = elf_getdata (scn, NULL);
935 
936   symscn = elf_getscn (ebl->elf, shdr->sh_link);
937   symshdr = gelf_getshdr (symscn, &symshdr_mem);
938   symdata = elf_getdata (symscn, NULL);
939 
940   if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
941       || symdata == NULL)
942     return;
943 
944   /* Get the section header string table index.  */
945   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
946     error (EXIT_FAILURE, 0,
947 	   gettext ("cannot get section header string table index"));
948 
949   grpref = (Elf32_Word *) data->d_buf;
950 
951   printf ((grpref[0] & GRP_COMDAT)
952 	  ? ngettext ("\
953 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
954 		      "\
955 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
956 		      data->d_size / sizeof (Elf32_Word) - 1)
957 	  : ngettext ("\
958 \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
959 \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
960 		      data->d_size / sizeof (Elf32_Word) - 1),
961 	  elf_ndxscn (scn),
962 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
963 	  elf_strptr (ebl->elf, symshdr->sh_link,
964 		      gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name)
965 	  ?: gettext ("<INVALID SYMBOL>"),
966 	  data->d_size / sizeof (Elf32_Word) - 1);
967 
968   for (cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
969     {
970       GElf_Shdr grpshdr_mem;
971       GElf_Shdr *grpshdr;
972 
973       grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
974 			      &grpshdr_mem);
975 
976       if (grpshdr == NULL)
977 	printf (gettext ("  [%2u] <INVALID SECTION>\n"), grpref[cnt]);
978       else
979 	printf ("  [%2u] %s\n",
980 		grpref[cnt],
981 		elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name)
982 		?: gettext ("<INVALID SECTION>"));
983     }
984 }
985 
986 
987 static void
print_scngrp(Ebl * ebl,GElf_Ehdr * ehdr)988 print_scngrp (Ebl *ebl, GElf_Ehdr *ehdr)
989 {
990   /* Find all relocation sections and handle them.  */
991   Elf_Scn *scn = NULL;
992 
993   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
994     {
995        /* Handle the section if it is a symbol table.  */
996       GElf_Shdr shdr_mem;
997       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
998 
999       if (shdr != NULL && shdr->sh_type == SHT_GROUP)
1000 	handle_scngrp (ebl, ehdr, scn, shdr);
1001     }
1002 }
1003 
1004 
1005 static const struct flags
1006 {
1007   int mask;
1008   const char *str;
1009 } dt_flags[] =
1010   {
1011     { DF_ORIGIN, "ORIGIN" },
1012     { DF_SYMBOLIC, "SYMBOLIC" },
1013     { DF_TEXTREL, "TEXTREL" },
1014     { DF_BIND_NOW, "BIND_NOW" },
1015     { DF_STATIC_TLS, "STATIC_TLS" }
1016   };
1017 static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
1018 
1019 static const struct flags dt_flags_1[] =
1020   {
1021     { DF_1_NOW, "NOW" },
1022     { DF_1_GLOBAL, "GLOBAL" },
1023     { DF_1_GROUP, "GROUP" },
1024     { DF_1_NODELETE, "NODELETE" },
1025     { DF_1_LOADFLTR, "LOADFLTR" },
1026     { DF_1_INITFIRST, "INITFIRST" },
1027     { DF_1_NOOPEN, "NOOPEN" },
1028     { DF_1_ORIGIN, "ORIGIN" },
1029     { DF_1_DIRECT, "DIRECT" },
1030     { DF_1_TRANS, "TRANS" },
1031     { DF_1_INTERPOSE, "INTERPOSE" },
1032     { DF_1_NODEFLIB, "NODEFLIB" },
1033     { DF_1_NODUMP, "NODUMP" },
1034     { DF_1_CONFALT, "CONFALT" },
1035     { DF_1_ENDFILTEE, "ENDFILTEE" },
1036     { DF_1_DISPRELDNE, "DISPRELDNE" },
1037     { DF_1_DISPRELPND, "DISPRELPND" },
1038   };
1039 static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
1040 
1041 static const struct flags dt_feature_1[] =
1042   {
1043     { DTF_1_PARINIT, "PARINIT" },
1044     { DTF_1_CONFEXP, "CONFEXP" }
1045   };
1046 static const int ndt_feature_1 = (sizeof (dt_feature_1)
1047 				  / sizeof (dt_feature_1[0]));
1048 
1049 static const struct flags dt_posflag_1[] =
1050   {
1051     { DF_P1_LAZYLOAD, "LAZYLOAD" },
1052     { DF_P1_GROUPPERM, "GROUPPERM" }
1053   };
1054 static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
1055 				  / sizeof (dt_posflag_1[0]));
1056 
1057 
1058 static void
print_flags(int class,GElf_Xword d_val,const struct flags * flags,int nflags)1059 print_flags (int class, GElf_Xword d_val, const struct flags *flags,
1060 		int nflags)
1061 {
1062   bool first = true;
1063   int cnt;
1064 
1065   for (cnt = 0; cnt < nflags; ++cnt)
1066     if (d_val & flags[cnt].mask)
1067       {
1068 	if (!first)
1069 	  putchar_unlocked (' ');
1070 	fputs_unlocked (flags[cnt].str, stdout);
1071 	d_val &= ~flags[cnt].mask;
1072 	first = false;
1073       }
1074 
1075   if (d_val != 0)
1076     {
1077       if (!first)
1078 	putchar_unlocked (' ');
1079       printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
1080     }
1081 
1082   putchar_unlocked ('\n');
1083 }
1084 
1085 
1086 static void
print_dt_flags(int class,GElf_Xword d_val)1087 print_dt_flags (int class, GElf_Xword d_val)
1088 {
1089   print_flags (class, d_val, dt_flags, ndt_flags);
1090 }
1091 
1092 
1093 static void
print_dt_flags_1(int class,GElf_Xword d_val)1094 print_dt_flags_1 (int class, GElf_Xword d_val)
1095 {
1096   print_flags (class, d_val, dt_flags_1, ndt_flags_1);
1097 }
1098 
1099 
1100 static void
print_dt_feature_1(int class,GElf_Xword d_val)1101 print_dt_feature_1 (int class, GElf_Xword d_val)
1102 {
1103   print_flags (class, d_val, dt_feature_1, ndt_feature_1);
1104 }
1105 
1106 
1107 static void
print_dt_posflag_1(int class,GElf_Xword d_val)1108 print_dt_posflag_1 (int class, GElf_Xword d_val)
1109 {
1110   print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
1111 }
1112 
1113 
1114 static void
handle_dynamic(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)1115 handle_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1116 {
1117   int class = gelf_getclass (ebl->elf);
1118   GElf_Shdr glink;
1119   Elf_Data *data;
1120   size_t cnt;
1121   size_t shstrndx;
1122 
1123   /* Get the data of the section.  */
1124   data = elf_getdata (scn, NULL);
1125   if (data == NULL)
1126     return;
1127 
1128   /* Get the section header string table index.  */
1129   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
1130     error (EXIT_FAILURE, 0,
1131 	   gettext ("cannot get section header string table index"));
1132 
1133   printf (ngettext ("\
1134 \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
1135 		    "\
1136 \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
1137 		    shdr->sh_size / shdr->sh_entsize),
1138 	  (unsigned long int) (shdr->sh_size / shdr->sh_entsize),
1139 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
1140 	  shdr->sh_offset,
1141 	  (int) shdr->sh_link,
1142 	  elf_strptr (ebl->elf, shstrndx,
1143 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1144 				    &glink)->sh_name));
1145   fputs_unlocked (gettext ("  Type              Value\n"), stdout);
1146 
1147   for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1148     {
1149       char buf[64];
1150       GElf_Dyn dynmem;
1151       GElf_Dyn *dyn;
1152 
1153       dyn = gelf_getdyn (data, cnt, &dynmem);
1154       if (dyn == NULL)
1155 	break;
1156 
1157       printf ("  %-17s ",
1158 	      ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
1159 
1160       switch (dyn->d_tag)
1161 	{
1162 	case DT_NULL:
1163 	case DT_DEBUG:
1164 	case DT_BIND_NOW:
1165 	case DT_TEXTREL:
1166 	  /* No further output.  */
1167 	  fputc ('\n', stdout);
1168 	  break;
1169 
1170 	case DT_NEEDED:
1171 	  printf (gettext ("Shared library: [%s]\n"),
1172 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1173 	  break;
1174 
1175 	case DT_SONAME:
1176 	  printf (gettext ("Library soname: [%s]\n"),
1177 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1178 	  break;
1179 
1180 	case DT_RPATH:
1181 	  printf (gettext ("Library rpath: [%s]\n"),
1182 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1183 	  break;
1184 
1185 	case DT_RUNPATH:
1186 	  printf (gettext ("Library runpath: [%s]\n"),
1187 		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1188 	  break;
1189 
1190 	case DT_PLTRELSZ:
1191 	case DT_RELASZ:
1192 	case DT_STRSZ:
1193 	case DT_RELSZ:
1194 	case DT_RELAENT:
1195 	case DT_SYMENT:
1196 	case DT_RELENT:
1197 	case DT_PLTPADSZ:
1198 	case DT_MOVEENT:
1199 	case DT_MOVESZ:
1200 	case DT_INIT_ARRAYSZ:
1201 	case DT_FINI_ARRAYSZ:
1202 	case DT_SYMINSZ:
1203 	case DT_SYMINENT:
1204 	case DT_GNU_CONFLICTSZ:
1205 	case DT_GNU_LIBLISTSZ:
1206 	  printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
1207 	  break;
1208 
1209 	case DT_VERDEFNUM:
1210 	case DT_VERNEEDNUM:
1211 	case DT_RELACOUNT:
1212 	case DT_RELCOUNT:
1213 	  printf ("%" PRId64 "\n", dyn->d_un.d_val);
1214 	  break;
1215 
1216 	case DT_PLTREL:
1217 	  puts (ebl_dynamic_tag_name (ebl, dyn->d_un.d_val, NULL, 0));
1218 	  break;
1219 
1220 	case DT_FLAGS:
1221 	  print_dt_flags (class, dyn->d_un.d_val);
1222 	  break;
1223 
1224 	case DT_FLAGS_1:
1225 	  print_dt_flags_1 (class, dyn->d_un.d_val);
1226 	  break;
1227 
1228 	case DT_FEATURE_1:
1229 	  print_dt_feature_1 (class, dyn->d_un.d_val);
1230 	  break;
1231 
1232 	case DT_POSFLAG_1:
1233 	  print_dt_posflag_1 (class, dyn->d_un.d_val);
1234 	  break;
1235 
1236 	default:
1237 	  printf ("%#0*" PRIx64 "\n",
1238 		  class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
1239 	  break;
1240 	}
1241     }
1242 }
1243 
1244 
1245 /* Print the dynamic segment.  */
1246 static void
print_dynamic(Ebl * ebl,GElf_Ehdr * ehdr)1247 print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr)
1248 {
1249   /* Find all relocation sections and handle them.  */
1250   Elf_Scn *scn = NULL;
1251 
1252   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1253     {
1254        /* Handle the section if it is a symbol table.  */
1255       GElf_Shdr shdr_mem;
1256       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1257 
1258       if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
1259 	{
1260 	  handle_dynamic (ebl, ehdr, scn, shdr);
1261 	  break;
1262 	}
1263     }
1264 }
1265 
1266 
1267 /* Print relocations.  */
1268 static void
print_relocs(Ebl * ebl,GElf_Ehdr * ehdr)1269 print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
1270 {
1271   /* Find all relocation sections and handle them.  */
1272   Elf_Scn *scn = NULL;
1273 
1274   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1275     {
1276        /* Handle the section if it is a symbol table.  */
1277       GElf_Shdr shdr_mem;
1278       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1279 
1280       if (shdr != NULL)
1281 	{
1282 	  if (shdr->sh_type == SHT_REL)
1283 	    handle_relocs_rel (ebl, ehdr, scn, shdr);
1284 	  else if (shdr->sh_type == SHT_RELA)
1285 	    handle_relocs_rela (ebl, ehdr, scn, shdr);
1286 	}
1287     }
1288 }
1289 
1290 
1291 /* Handle a relocation section.  */
1292 static void
handle_relocs_rel(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)1293 handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1294 {
1295   int class = gelf_getclass (ebl->elf);
1296   int nentries = shdr->sh_size / shdr->sh_entsize;
1297   int cnt;
1298   Elf_Data *data;
1299   Elf_Scn *symscn;
1300   GElf_Shdr symshdr_mem;
1301   GElf_Shdr *symshdr;
1302   Elf_Data *symdata;
1303   GElf_Shdr destshdr_mem;
1304   GElf_Shdr *destshdr;
1305   Elf_Scn *xndxscn;
1306   Elf_Data *xndxdata = NULL;
1307   size_t shstrndx;
1308 
1309   /* Get the data of the section.  */
1310   data = elf_getdata (scn, NULL);
1311   if (data == NULL)
1312     return;
1313 
1314   /* Get the symbol table information.  */
1315   symscn = elf_getscn (ebl->elf, shdr->sh_link);
1316   symshdr = gelf_getshdr (symscn, &symshdr_mem);
1317   symdata = elf_getdata (symscn, NULL);
1318 
1319   /* Get the section header of the section the relocations are for.  */
1320   destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1321 			   &destshdr_mem);
1322 
1323   if (symshdr == NULL || symdata == NULL || destshdr == NULL)
1324     {
1325       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1326 	      shdr->sh_offset);
1327       return;
1328     }
1329 
1330   /* Search for the optional extended section index table.  */
1331   xndxscn = NULL;
1332   while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
1333     {
1334       GElf_Shdr xndxshdr_mem;
1335       GElf_Shdr *xndxshdr;
1336 
1337       xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
1338       if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
1339 	  && xndxshdr->sh_link == elf_ndxscn (symscn))
1340 	{
1341 	  /* Found it.  */
1342 	  xndxdata = elf_getdata (xndxscn, NULL);
1343 	  break;
1344 	}
1345     }
1346 
1347   /* Get the section header string table index.  */
1348   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
1349     error (EXIT_FAILURE, 0,
1350 	   gettext ("cannot get section header string table index"));
1351 
1352   if (shdr->sh_info != 0)
1353     printf (ngettext ("\
1354 \nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1355 		    "\
1356 \nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1357 		      nentries),
1358 	    (unsigned int) elf_ndxscn (scn),
1359 	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1360 	    (unsigned int) shdr->sh_info,
1361 	    elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1362 	    shdr->sh_offset,
1363 	    nentries);
1364   else
1365     /* The .rel.dyn section does not refer to a specific section but
1366        instead of section index zero.  Do not try to print a section
1367        name.  */
1368     printf (ngettext ("\
1369 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1370 		    "\
1371 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1372 		      nentries),
1373 	    (unsigned int) elf_ndxscn (scn),
1374 	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1375 	    shdr->sh_offset,
1376 	    nentries);
1377   fputs_unlocked (class == ELFCLASS32
1378 		  ? gettext ("\
1379   Offset      Type                 Value       Name\n")
1380 		  : gettext ("\
1381   Offset              Type                 Value               Name\n"),
1382 	 stdout);
1383 
1384   for (cnt = 0; cnt < nentries; ++cnt)
1385     {
1386       GElf_Rel relmem;
1387       GElf_Rel *rel;
1388 
1389       rel = gelf_getrel (data, cnt, &relmem);
1390       if (rel != NULL)
1391 	{
1392 	  char buf[128];
1393 	  GElf_Sym symmem;
1394 	  GElf_Sym *sym;
1395 	  Elf32_Word xndx;
1396 
1397 	  sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (rel->r_info),
1398 				  &symmem, &xndx);
1399 	  if (sym == NULL)
1400 	    printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
1401 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1402 		    ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1403 		    /* Avoid the leading R_ which isn't carrying any
1404 		       information.  */
1405 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1406 					   buf, sizeof (buf)) + 2
1407 		    : gettext ("<INVALID RELOC>"),
1408 		    gettext ("INVALID SYMBOL"),
1409 		    (long int) GELF_R_SYM (rel->r_info));
1410 	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1411 	    printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
1412 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1413 		    ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1414 		    /* Avoid the leading R_ which isn't carrying any
1415 		       information.  */
1416 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1417 					   buf, sizeof (buf)) + 2
1418 		    : gettext ("<INVALID RELOC>"),
1419 		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
1420 		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1421 	  else
1422 	    {
1423 	      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
1424 						   sym->st_shndx == SHN_XINDEX
1425 						   ? xndx : sym->st_shndx),
1426 				       &destshdr_mem);
1427 
1428 	      if (shdr == NULL)
1429 		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
1430 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1431 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1432 			/* Avoid the leading R_ which isn't carrying any
1433 			   information.  */
1434 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1435 					       buf, sizeof (buf)) + 2
1436 			: gettext ("<INVALID RELOC>"),
1437 			gettext ("INVALID SECTION"),
1438 			(long int) (sym->st_shndx == SHN_XINDEX
1439 				    ? xndx : sym->st_shndx));
1440 	      else
1441 		printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
1442 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1443 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1444 			/* Avoid the leading R_ which isn't carrying any
1445 			   information.  */
1446 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1447 					       buf, sizeof (buf)) + 2
1448 			: gettext ("<INVALID RELOC>"),
1449 			class == ELFCLASS32 ? 10 : 18, sym->st_value,
1450 			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1451 	    }
1452 	}
1453     }
1454 }
1455 
1456 
1457 /* Handle a relocation section.  */
1458 static void
handle_relocs_rela(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)1459 handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1460 {
1461   int class = gelf_getclass (ebl->elf);
1462   int nentries = shdr->sh_size / shdr->sh_entsize;
1463 
1464   /* Get the data of the section.  */
1465   Elf_Data *data = elf_getdata (scn, NULL);
1466   if (data == NULL)
1467     return;
1468 
1469   /* Get the symbol table information.  */
1470   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1471   GElf_Shdr symshdr_mem;
1472   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1473   Elf_Data *symdata = elf_getdata (symscn, NULL);
1474 
1475   /* Get the section header of the section the relocations are for.  */
1476   GElf_Shdr destshdr_mem;
1477   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1478 				      &destshdr_mem);
1479 
1480   if (symshdr == NULL || symdata == NULL || destshdr == NULL)
1481     {
1482       printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1483 	      shdr->sh_offset);
1484       return;
1485     }
1486 
1487   /* Search for the optional extended section index table.  */
1488   Elf_Data *xndxdata = NULL;
1489   Elf_Scn *xndxscn = NULL;
1490   while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
1491     {
1492       GElf_Shdr xndxshdr_mem;
1493       GElf_Shdr *xndxshdr;
1494 
1495       xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
1496       if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
1497 	  && xndxshdr->sh_link == elf_ndxscn (symscn))
1498 	{
1499 	  /* Found it.  */
1500 	  xndxdata = elf_getdata (xndxscn, NULL);
1501 	  break;
1502 	}
1503     }
1504 
1505   /* Get the section header string table index.  */
1506   size_t shstrndx;
1507   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
1508     error (EXIT_FAILURE, 0,
1509 	   gettext ("cannot get section header string table index"));
1510 
1511   printf (ngettext ("\
1512 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1513 		    "\
1514 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1515 		    nentries),
1516 	  elf_ndxscn (scn),
1517 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1518 	  (unsigned int) shdr->sh_info,
1519 	  elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1520 	  shdr->sh_offset,
1521 	  nentries);
1522   fputs_unlocked (class == ELFCLASS32
1523 		  ? gettext ("\
1524   Offset      Type            Value       Addend Name\n")
1525 		  : gettext ("\
1526   Offset              Type            Value               Addend Name\n"),
1527 		  stdout);
1528 
1529   for (int cnt = 0; cnt < nentries; ++cnt)
1530     {
1531       GElf_Rela relmem;
1532       GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
1533       if (rel != NULL)
1534 	{
1535 	  char buf[64];
1536 	  GElf_Sym symmem;
1537 	  GElf_Sym *sym;
1538 	  Elf32_Word xndx;
1539 
1540 	  sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (rel->r_info),
1541 				  &symmem, &xndx);
1542 
1543 	  if (sym == NULL)
1544 	    printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
1545 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1546 		    ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1547 		    /* Avoid the leading R_ which isn't carrying any
1548 		       information.  */
1549 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1550 					   buf, sizeof (buf)) + 2
1551 		    : gettext ("<INVALID RELOC>"),
1552 		    gettext ("INVALID SYMBOL"),
1553 		    (long int) GELF_R_SYM (rel->r_info));
1554 	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1555 	    printf ("\
1556   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  +%5" PRId64 " %s\n",
1557 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1558 		    ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1559 		    /* Avoid the leading R_ which isn't carrying any
1560 		       information.  */
1561 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1562 					   buf, sizeof (buf)) + 2
1563 		    : gettext ("<INVALID RELOC>"),
1564 		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
1565 		    rel->r_addend,
1566 		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1567 	  else
1568 	    {
1569 	      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
1570 						   sym->st_shndx == SHN_XINDEX
1571 						   ? xndx : sym->st_shndx),
1572 				       &destshdr_mem);
1573 
1574 	      if (shdr == NULL)
1575 		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
1576 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1577 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1578 			/* Avoid the leading R_ which isn't carrying any
1579 			   information.  */
1580 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1581 					       buf, sizeof (buf)) + 2
1582 			: gettext ("<INVALID RELOC>"),
1583 			gettext ("INVALID SECTION"),
1584 			(long int) (sym->st_shndx == SHN_XINDEX
1585 				    ? xndx : sym->st_shndx));
1586 	      else
1587 		printf ("\
1588   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  +%5" PRId64 " %s\n",
1589 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1590 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1591 			/* Avoid the leading R_ which isn't carrying any
1592 			   information.  */
1593 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1594 					       buf, sizeof (buf)) + 2
1595 			: gettext ("<INVALID RELOC>"),
1596 			class == ELFCLASS32 ? 10 : 18, sym->st_value,
1597 			rel->r_addend,
1598 			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1599 	    }
1600 	}
1601     }
1602 }
1603 
1604 
1605 /* Print the program header.  */
1606 static void
print_symtab(Ebl * ebl,GElf_Ehdr * ehdr,int type)1607 print_symtab (Ebl *ebl, GElf_Ehdr *ehdr, int type)
1608 {
1609   /* Find the symbol table(s).  For this we have to search through the
1610      section table.  */
1611   Elf_Scn *scn = NULL;
1612 
1613   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1614     {
1615       /* Handle the section if it is a symbol table.  */
1616       GElf_Shdr shdr_mem;
1617       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1618 
1619       if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
1620 	handle_symtab (ebl, ehdr, scn, shdr);
1621     }
1622 }
1623 
1624 
1625 static void
handle_symtab(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)1626 handle_symtab (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1627 {
1628   Elf_Data *versym_data = NULL;
1629   Elf_Data *verneed_data = NULL;
1630   Elf_Data *verdef_data = NULL;
1631   Elf_Data *xndx_data = NULL;
1632   Elf_Scn *runscn;
1633   Elf_Data *data;
1634   int class = gelf_getclass (ebl->elf);
1635   unsigned int nsyms;
1636   unsigned int cnt;
1637   Elf32_Word verneed_stridx = 0;
1638   Elf32_Word verdef_stridx = 0;
1639   GElf_Shdr glink;
1640   size_t shstrndx;
1641 
1642   /* Get the data of the section.  */
1643   data = elf_getdata (scn, NULL);
1644   if (data == NULL)
1645     return;
1646 
1647   /* Find out whether we have other sections we might need.  */
1648   runscn = NULL;
1649   while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
1650     {
1651       GElf_Shdr runshdr_mem;
1652       GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
1653 
1654       if (runshdr != NULL)
1655 	{
1656 	  if (runshdr->sh_type == SHT_GNU_versym
1657 	      && runshdr->sh_link == elf_ndxscn (scn))
1658 	    /* Bingo, found the version information.  Now get the data.  */
1659 	    versym_data = elf_getdata (runscn, NULL);
1660 	  else if (runshdr->sh_type == SHT_GNU_verneed)
1661 	    {
1662 	      /* This is the information about the needed versions.  */
1663 	      verneed_data = elf_getdata (runscn, NULL);
1664 	      verneed_stridx = runshdr->sh_link;
1665 	    }
1666 	  else if (runshdr->sh_type == SHT_GNU_verdef)
1667 	    {
1668 	      /* This is the information about the defined versions.  */
1669 	      verdef_data = elf_getdata (runscn, NULL);
1670 	      verdef_stridx = runshdr->sh_link;
1671 	    }
1672 	  else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
1673 	      && runshdr->sh_link == elf_ndxscn (scn))
1674 	    /* Extended section index.  */
1675 	    xndx_data = elf_getdata (runscn, NULL);
1676 	}
1677     }
1678 
1679   /* Get the section header string table index.  */
1680   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
1681     error (EXIT_FAILURE, 0,
1682 	   gettext ("cannot get section header string table index"));
1683 
1684   /* Now we can compute the number of entries in the section.  */
1685   nsyms = data->d_size / (class == ELFCLASS32
1686 			  ? sizeof (Elf32_Sym) : sizeof (Elf64_Sym));
1687 
1688   printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
1689 		    "\nSymbol table [%2u] '%s' contains %u entries:\n",
1690 		    nsyms),
1691 	  (unsigned int) elf_ndxscn (scn),
1692 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
1693   printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
1694 		    " %lu local symbols  String table: [%2u] '%s'\n",
1695 		    shdr->sh_info),
1696 	  (unsigned long int) shdr->sh_info,
1697 	  (unsigned int) shdr->sh_link,
1698 	  elf_strptr (ebl->elf, shstrndx,
1699 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1700 				    &glink)->sh_name));
1701 
1702   fputs_unlocked (class == ELFCLASS32
1703 		  ? gettext ("\
1704   Num:    Value   Size Type    Bind   Vis          Ndx Name\n")
1705 		  : gettext ("\
1706   Num:            Value   Size Type    Bind   Vis          Ndx Name\n"),
1707 		  stdout);
1708 
1709   for (cnt = 0; cnt < nsyms; ++cnt)
1710     {
1711       char typebuf[64];
1712       char bindbuf[64];
1713       char scnbuf[64];
1714       Elf32_Word xndx;
1715       GElf_Sym sym_mem;
1716       GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
1717 
1718       if (sym == NULL)
1719 	continue;
1720 
1721       /* Determine the real section index.  */
1722       if (sym->st_shndx != SHN_XINDEX)
1723 	xndx = sym->st_shndx;
1724 
1725       printf (gettext ("\
1726 %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
1727 	      cnt,
1728 	      class == ELFCLASS32 ? 8 : 16,
1729 	      sym->st_value,
1730 	      sym->st_size,
1731 	      ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
1732 				    typebuf, sizeof (typebuf)),
1733 	      ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
1734 				       bindbuf, sizeof (bindbuf)),
1735 	      get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
1736 	      ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
1737 				sizeof (scnbuf), NULL, shnum),
1738 	      elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
1739 
1740       if (versym_data != NULL)
1741 	{
1742 	  /* Get the version information.  */
1743 	  GElf_Versym versym_mem;
1744 	  GElf_Versym *versym;
1745 
1746 	  versym = gelf_getversym (versym_data, cnt, &versym_mem);
1747 
1748 	  if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
1749 	    {
1750 	      bool is_nobits = false;
1751 	      bool check_def = xndx != SHN_UNDEF;
1752 
1753 	      if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
1754 		{
1755 		  GElf_Shdr symshdr_mem;
1756 		  GElf_Shdr *symshdr =
1757 		    gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
1758 
1759 		  is_nobits = (symshdr != NULL
1760 			       && symshdr->sh_type == SHT_NOBITS);
1761 		}
1762 
1763 	      if (is_nobits || ! check_def)
1764 		{
1765 		  /* We must test both.  */
1766 		  GElf_Verneed verneed_mem;
1767 		  GElf_Verneed *verneed;
1768 		  GElf_Vernaux vernaux_mem;
1769 		  GElf_Vernaux *vernaux = NULL;
1770 		  size_t vn_offset = 0;
1771 
1772 		  verneed = gelf_getverneed (verneed_data, 0, &verneed_mem);
1773 		  while (verneed != NULL)
1774 		    {
1775 		      size_t vna_offset = vn_offset;
1776 
1777 		      vernaux = gelf_getvernaux (verneed_data,
1778 						 vna_offset += verneed->vn_aux,
1779 						 &vernaux_mem);
1780 		      while (vernaux != NULL
1781 			     && vernaux->vna_other != *versym
1782 			     && vernaux->vna_next != 0)
1783 			{
1784 			  /* Update the offset.  */
1785 			  vna_offset += vernaux->vna_next;
1786 
1787 			  vernaux = (vernaux->vna_next == 0
1788 				     ? NULL
1789 				     : gelf_getvernaux (verneed_data,
1790 							vna_offset,
1791 							&vernaux_mem));
1792 			}
1793 
1794 		      /* Check whether we found the version.  */
1795 		      if (vernaux != NULL && vernaux->vna_other == *versym)
1796 			/* Found it.  */
1797 			break;
1798 
1799 		      vn_offset += verneed->vn_next;
1800 		      verneed = (verneed->vn_next == 0
1801 				 ? NULL
1802 				 : gelf_getverneed (verneed_data, vn_offset,
1803 						    &verneed_mem));
1804 		    }
1805 
1806 		  if (vernaux != NULL && vernaux->vna_other == *versym)
1807 		    {
1808 		      printf ("@%s (%u)",
1809 			      elf_strptr (ebl->elf, verneed_stridx,
1810 					  vernaux->vna_name),
1811 			      (unsigned int) vernaux->vna_other);
1812 		      check_def = 0;
1813 		    }
1814 		  else if (! is_nobits)
1815 		    error (0, 0, gettext ("bad dynamic symbol"));
1816 		  else
1817 		    check_def = 1;
1818 		}
1819 
1820 	      if (check_def && *versym != 0x8001)
1821 		{
1822 		  /* We must test both.  */
1823 		  GElf_Verdef verdef_mem;
1824 		  GElf_Verdef *verdef;
1825 		  size_t vd_offset = 0;
1826 
1827 		  verdef = gelf_getverdef (verdef_data, 0, &verdef_mem);
1828 		  while (verdef != NULL)
1829 		    {
1830 		      if (verdef->vd_ndx == (*versym & 0x7fff))
1831 			/* Found the definition.  */
1832 			break;
1833 
1834 		      vd_offset += verdef->vd_next;
1835 		      verdef = (verdef->vd_next == 0
1836 				? NULL
1837 				: gelf_getverdef (verdef_data, vd_offset,
1838 						  &verdef_mem));
1839 		    }
1840 
1841 		  if (verdef != NULL)
1842 		    {
1843 		      GElf_Verdaux verdaux_mem;
1844 		      GElf_Verdaux *verdaux;
1845 
1846 		      verdaux = gelf_getverdaux (verdef_data,
1847 						 vd_offset + verdef->vd_aux,
1848 						 &verdaux_mem);
1849 
1850 		      if (verdaux != NULL)
1851 			printf ((*versym & 0x8000) ? "@%s" : "@@%s",
1852 				elf_strptr (ebl->elf, verdef_stridx,
1853 					    verdaux->vda_name));
1854 		    }
1855 		}
1856 	    }
1857 	}
1858 
1859       putchar ('\n');
1860     }
1861 }
1862 
1863 
1864 /* Print version information.  */
1865 static void
print_verinfo(Ebl * ebl,GElf_Ehdr * ehdr)1866 print_verinfo (Ebl *ebl, GElf_Ehdr *ehdr)
1867 {
1868   /* Find the version information sections.  For this we have to
1869      search through the section table.  */
1870   Elf_Scn *scn = NULL;
1871 
1872   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1873     {
1874       /* Handle the section if it is part of the versioning handling.  */
1875       GElf_Shdr shdr_mem;
1876       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1877 
1878       if (shdr != NULL)
1879 	{
1880 	  if (shdr->sh_type == SHT_GNU_verneed)
1881 	    handle_verneed (ebl, ehdr, scn, shdr);
1882 	  else if (shdr->sh_type == SHT_GNU_verdef)
1883 	    handle_verdef (ebl, ehdr, scn, shdr);
1884 	  else if (shdr->sh_type == SHT_GNU_versym)
1885 	    handle_versym (ebl, ehdr, scn, shdr);
1886 	}
1887     }
1888 }
1889 
1890 
1891 static const char *
get_ver_flags(unsigned int flags)1892 get_ver_flags (unsigned int flags)
1893 {
1894   static char buf[32];
1895   char *endp;
1896 
1897   if (flags == 0)
1898     return gettext ("none");
1899 
1900   if (flags & VER_FLG_BASE)
1901     endp = stpcpy (buf, "BASE ");
1902   else
1903     endp = buf;
1904 
1905   if (flags & VER_FLG_WEAK)
1906     {
1907       if (endp != buf)
1908         endp = stpcpy (endp, "| ");
1909 
1910       endp = stpcpy (endp, "WEAK ");
1911     }
1912 
1913   if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
1914     {
1915       strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
1916       buf[sizeof (buf) - 1] = '\0';
1917     }
1918 
1919   return buf;
1920 }
1921 
1922 
1923 static void
handle_verneed(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)1924 handle_verneed (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1925 {
1926   Elf_Data *data;
1927   int class = gelf_getclass (ebl->elf);
1928   GElf_Shdr glink;
1929   int cnt;
1930   unsigned int offset;
1931   size_t shstrndx;
1932 
1933   /* Get the data of the section.  */
1934   data = elf_getdata (scn, NULL);
1935   if (data == NULL)
1936     return;
1937 
1938   /* Get the section header string table index.  */
1939   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
1940     error (EXIT_FAILURE, 0,
1941 	   gettext ("cannot get section header string table index"));
1942 
1943   printf (ngettext ("\
1944 \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
1945 		    "\
1946 \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
1947 		    shdr->sh_info),
1948 	  (unsigned int) elf_ndxscn (scn),
1949 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
1950 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
1951 	  shdr->sh_offset,
1952 	  (unsigned int) shdr->sh_link,
1953 	  elf_strptr (ebl->elf, shstrndx,
1954 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1955 				    &glink)->sh_name));
1956 
1957   offset = 0;
1958   for (cnt = shdr->sh_info; --cnt >= 0; )
1959     {
1960       GElf_Verneed needmem;
1961       GElf_Verneed *need;
1962       unsigned int auxoffset;
1963       int cnt2;
1964 
1965       /* Get the data at the next offset.  */
1966       need = gelf_getverneed (data, offset, &needmem);
1967       if (need == NULL)
1968 	break;
1969 
1970       printf (gettext ("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
1971 	      offset, (unsigned short int) need->vn_version,
1972 	      elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
1973 	      (unsigned short int) need->vn_cnt);
1974 
1975       auxoffset = offset + need->vn_aux;
1976       for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
1977 	{
1978 	  GElf_Vernaux auxmem;
1979 	  GElf_Vernaux *aux;
1980 
1981 	  aux = gelf_getvernaux (data, auxoffset, &auxmem);
1982 	  if (aux == NULL)
1983 	    break;
1984 
1985 	  printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
1986 		  auxoffset,
1987 		  elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
1988 		  get_ver_flags (aux->vna_flags),
1989 		  (unsigned short int) aux->vna_other);
1990 
1991 	  auxoffset += aux->vna_next;
1992 	}
1993 
1994       /* Find the next offset.  */
1995       offset += need->vn_next;
1996     }
1997 }
1998 
1999 
2000 static void
handle_verdef(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)2001 handle_verdef (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
2002 {
2003   Elf_Data *data;
2004   int class = gelf_getclass (ebl->elf);
2005   GElf_Shdr glink;
2006   int cnt;
2007   unsigned int offset;
2008   size_t shstrndx;
2009 
2010   /* Get the data of the section.  */
2011   data = elf_getdata (scn, NULL);
2012   if (data == NULL)
2013     return;
2014 
2015   /* Get the section header string table index.  */
2016   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
2017     error (EXIT_FAILURE, 0,
2018 	   gettext ("cannot get section header string table index"));
2019 
2020   printf (ngettext ("\
2021 \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
2022 		    "\
2023 \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
2024 		    shdr->sh_info),
2025 	  (unsigned int) elf_ndxscn (scn),
2026 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2027 	  shdr->sh_info,
2028 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2029 	  shdr->sh_offset,
2030 	  (unsigned int) shdr->sh_link,
2031 	  elf_strptr (ebl->elf, shstrndx,
2032 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2033 				    &glink)->sh_name));
2034 
2035   offset = 0;
2036   for (cnt = shdr->sh_info; --cnt >= 0; )
2037     {
2038       GElf_Verdef defmem;
2039       GElf_Verdef *def;
2040       GElf_Verdaux auxmem;
2041       GElf_Verdaux *aux;
2042       unsigned int auxoffset;
2043       int cnt2;
2044 
2045       /* Get the data at the next offset.  */
2046       def = gelf_getverdef (data, offset, &defmem);
2047       if (def == NULL)
2048 	break;
2049 
2050       auxoffset = offset + def->vd_aux;
2051       aux = gelf_getverdaux (data, auxoffset, &auxmem);
2052       if (aux == NULL)
2053 	break;
2054 
2055       printf (gettext ("\
2056   %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"),
2057 	      offset, def->vd_version,
2058 	      get_ver_flags (def->vd_flags),
2059 	      def->vd_ndx,
2060 	      def->vd_cnt,
2061 	      elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2062 
2063       auxoffset += aux->vda_next;
2064       for (cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
2065 	{
2066 	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
2067 	  if (aux == NULL)
2068 	    break;
2069 
2070 	  printf (gettext ("  %#06x: Parent %d: %s\n"),
2071 		  auxoffset, cnt2,
2072 		  elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2073 
2074 	  auxoffset += aux->vda_next;
2075 	}
2076 
2077       /* Find the next offset.  */
2078       offset += def->vd_next;
2079     }
2080 }
2081 
2082 
2083 static void
handle_versym(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)2084 handle_versym (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
2085 {
2086   Elf_Data *data;
2087   int class = gelf_getclass (ebl->elf);
2088   Elf_Scn *verscn;
2089   GElf_Shdr glink;
2090   Elf_Scn *defscn;
2091   Elf_Scn *needscn;
2092   const char **vername;
2093   const char **filename;
2094   size_t nvername;
2095   unsigned int cnt;
2096   size_t shstrndx;
2097 
2098   /* Get the data of the section.  */
2099   data = elf_getdata (scn, NULL);
2100   if (data == NULL)
2101     return;
2102 
2103   /* Get the section header string table index.  */
2104   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
2105     error (EXIT_FAILURE, 0,
2106 	   gettext ("cannot get section header string table index"));
2107 
2108   /* We have to find the version definition section and extract the
2109      version names.  */
2110   defscn = NULL;
2111   needscn = NULL;
2112 
2113   verscn = NULL;
2114   while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
2115     {
2116       GElf_Shdr vershdr_mem;
2117       GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
2118 
2119       if (vershdr != NULL)
2120 	{
2121 	  if (vershdr->sh_type == SHT_GNU_verdef)
2122 	    defscn = verscn;
2123 	  else if (vershdr->sh_type == SHT_GNU_verneed)
2124 	    needscn = verscn;
2125 	}
2126     }
2127 
2128   if (defscn != NULL || needscn != NULL)
2129     {
2130       /* We have a version information (better should have).  Now get
2131 	 the version names.  First find the maximum version number.  */
2132       nvername = 0;
2133       if (defscn != NULL)
2134 	{
2135 	  /* Run through the version definitions and find the highest
2136 	     index.  */
2137 	  unsigned int offset = 0;
2138 	  Elf_Data *defdata;
2139 	  GElf_Shdr defshdrmem;
2140 	  GElf_Shdr *defshdr;
2141 
2142 	  defdata = elf_getdata (defscn, NULL);
2143 	  if (defdata == NULL)
2144 	    return;
2145 
2146 	  defshdr = gelf_getshdr (defscn, &defshdrmem);
2147 	  if (defshdr == NULL)
2148 	    return;
2149 
2150 	  for (cnt = 0; cnt < defshdr->sh_info; ++cnt)
2151 	    {
2152 	      GElf_Verdef defmem;
2153 	      GElf_Verdef *def;
2154 
2155 	      /* Get the data at the next offset.  */
2156 	      def = gelf_getverdef (defdata, offset, &defmem);
2157 	      if (def == NULL)
2158 		break;
2159 
2160 	      nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
2161 
2162 	      offset += def->vd_next;
2163 	    }
2164 	}
2165       if (needscn != NULL)
2166 	{
2167 	  unsigned int offset = 0;
2168 	  Elf_Data *needdata;
2169 	  GElf_Shdr needshdrmem;
2170 	  GElf_Shdr *needshdr;
2171 
2172 	  needdata = elf_getdata (needscn, NULL);
2173 	  if (needdata == NULL)
2174 	    return;
2175 
2176 	  needshdr = gelf_getshdr (needscn, &needshdrmem);
2177 	  if (needshdr == NULL)
2178 	    return;
2179 
2180 	  for (cnt = 0; cnt < needshdr->sh_info; ++cnt)
2181 	    {
2182 	      GElf_Verneed needmem;
2183 	      GElf_Verneed *need;
2184 	      unsigned int auxoffset;
2185 	      int cnt2;
2186 
2187 	      /* Get the data at the next offset.  */
2188 	      need = gelf_getverneed (needdata, offset, &needmem);
2189 	      if (need == NULL)
2190 		break;
2191 
2192 	      /* Run through the auxiliary entries.  */
2193 	      auxoffset = offset + need->vn_aux;
2194 	      for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
2195 		{
2196 		  GElf_Vernaux auxmem;
2197 		  GElf_Vernaux *aux;
2198 
2199 		  aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
2200 		  if (aux == NULL)
2201 		    break;
2202 
2203 		  nvername = MAX (nvername,
2204 				  (size_t) (aux->vna_other & 0x7fff));
2205 
2206 		  auxoffset += aux->vna_next;
2207 		}
2208 
2209 	      offset += need->vn_next;
2210 	    }
2211 	}
2212 
2213       /* This is the number of versions we know about.  */
2214       ++nvername;
2215 
2216       /* Allocate the array.  */
2217       vername = (const char **) alloca (nvername * sizeof (const char *));
2218       filename = (const char **) alloca (nvername * sizeof (const char *));
2219 
2220       /* Run through the data structures again and collect the strings.  */
2221       if (defscn != NULL)
2222 	{
2223 	  /* Run through the version definitions and find the highest
2224 	     index.  */
2225 	  unsigned int offset = 0;
2226 	  Elf_Data *defdata;
2227 	  GElf_Shdr defshdrmem;
2228 	  GElf_Shdr *defshdr;
2229 
2230 	  defdata = elf_getdata (defscn, NULL);
2231 	  if (defdata == NULL)
2232 	    return;
2233 
2234 	  defshdr = gelf_getshdr (defscn, &defshdrmem);
2235 	  if (defshdr == NULL)
2236 	    return;
2237 
2238 	  for (cnt = 0; cnt < defshdr->sh_info; ++cnt)
2239 	    {
2240 	      GElf_Verdef defmem;
2241 	      GElf_Verdef *def;
2242 	      GElf_Verdaux auxmem;
2243 	      GElf_Verdaux *aux;
2244 
2245 	      /* Get the data at the next offset.  */
2246 	      def = gelf_getverdef (defdata, offset, &defmem);
2247 	      if (def == NULL)
2248 		break;
2249 
2250 	      aux = gelf_getverdaux (defdata, offset + def->vd_aux, &auxmem);
2251 	      if (aux == NULL)
2252 		break;
2253 
2254 	      vername[def->vd_ndx & 0x7fff]
2255 		= elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
2256 	      filename[def->vd_ndx & 0x7fff] = NULL;
2257 
2258 	      offset += def->vd_next;
2259 	    }
2260 	}
2261       if (needscn != NULL)
2262 	{
2263 	  unsigned int offset = 0;
2264 	  Elf_Data *needdata;
2265 	  GElf_Shdr needshdrmem;
2266 	  GElf_Shdr *needshdr;
2267 
2268 	  needdata = elf_getdata (needscn, NULL);
2269 	  if (needdata == NULL)
2270 	    return;
2271 
2272 	  needshdr = gelf_getshdr (needscn, &needshdrmem);
2273 	  if (needshdr == NULL)
2274 	    return;
2275 
2276 	  for (cnt = 0; cnt < needshdr->sh_info; ++cnt)
2277 	    {
2278 	      GElf_Verneed needmem;
2279 	      GElf_Verneed *need;
2280 	      unsigned int auxoffset;
2281 	      int cnt2;
2282 
2283 	      /* Get the data at the next offset.  */
2284 	      need = gelf_getverneed (needdata, offset, &needmem);
2285 	      if (need == NULL)
2286 		break;
2287 
2288 	      /* Run through the auxiliary entries.  */
2289 	      auxoffset = offset + need->vn_aux;
2290 	      for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
2291 		{
2292 		  GElf_Vernaux auxmem;
2293 		  GElf_Vernaux *aux;
2294 
2295 		  aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
2296 		  if (aux == NULL)
2297 		    break;
2298 
2299 		  vername[aux->vna_other & 0x7fff]
2300 		    = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
2301 		  filename[aux->vna_other & 0x7fff]
2302 		    = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
2303 
2304 		  auxoffset += aux->vna_next;
2305 		}
2306 
2307 	      offset += need->vn_next;
2308 	    }
2309 	}
2310     }
2311   else
2312     {
2313       vername = NULL;
2314       nvername = 1;
2315       filename = NULL;
2316     }
2317 
2318   /* Print the header.  */
2319   printf (ngettext ("\
2320 \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
2321 		    "\
2322 \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
2323 		    shdr->sh_size / shdr->sh_entsize),
2324 	  (unsigned int) elf_ndxscn (scn),
2325 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2326 	  (int) (shdr->sh_size / shdr->sh_entsize),
2327 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2328 	  shdr->sh_offset,
2329 	  (unsigned int) shdr->sh_link,
2330 	  elf_strptr (ebl->elf, shstrndx,
2331 		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2332 				    &glink)->sh_name));
2333 
2334   /* Now we can finally look at the actual contents of this section.  */
2335   for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
2336     {
2337       GElf_Versym symmem;
2338       GElf_Versym *sym;
2339       ssize_t n;
2340 
2341       if (cnt % 2 == 0)
2342 	printf ("\n %4d:", cnt);
2343 
2344       sym = gelf_getversym (data, cnt, &symmem);
2345       if (sym == NULL)
2346 	break;
2347 
2348       switch (*sym)
2349 	{
2350 	case 0:
2351 	  fputs_unlocked (gettext ("   0 *local*                     "),
2352 			  stdout);
2353 	  break;
2354 
2355 	case 1:
2356 	  fputs_unlocked (gettext ("   1 *global*                    "),
2357 			  stdout);
2358 	  break;
2359 
2360 	default:
2361 	  n = printf ("%4d%c%s",
2362 		      *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
2363 		      (unsigned int) (*sym & 0x7fff) < nvername
2364 		      ? vername[*sym & 0x7fff] : "???");
2365 	  if ((unsigned int) (*sym & 0x7fff) < nvername
2366 	      && filename[*sym & 0x7fff] != NULL)
2367 	    n += printf ("(%s)", filename[*sym & 0x7fff]);
2368 	  printf ("%*s", MAX (0, 33 - (int) n), " ");
2369 	  break;
2370 	}
2371     }
2372   putchar ('\n');
2373 }
2374 
2375 
2376 static void
handle_hash(Ebl * ebl,GElf_Ehdr * ehdr)2377 handle_hash (Ebl *ebl, GElf_Ehdr *ehdr)
2378 {
2379   /* Find the symbol table(s).  For this we have to search through the
2380      section table.  */
2381   Elf_Scn *scn = NULL;
2382   size_t shstrndx;
2383 
2384   /* Get the section header string table index.  */
2385   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
2386     error (EXIT_FAILURE, 0,
2387 	   gettext ("cannot get section header string table index"));
2388 
2389   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2390     {
2391       /* Handle the section if it is a symbol table.  */
2392       GElf_Shdr shdr_mem;
2393       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2394 
2395       if (shdr != NULL && shdr->sh_type == SHT_HASH)
2396 	{
2397 	  Elf_Data *data = elf_getdata (scn, NULL);
2398 	  Elf32_Word nbucket;
2399 	  Elf32_Word nchain;
2400 	  Elf32_Word *bucket;
2401 	  Elf32_Word *chain;
2402 	  uint32_t *lengths;
2403 	  uint32_t *counts;
2404 	  Elf32_Word cnt;
2405 	  Elf32_Word maxlength = 0;
2406 	  Elf32_Word nsyms = 0;
2407 	  uint64_t nzero_counts = 0;
2408 	  GElf_Shdr glink;
2409 
2410 	  if (data == NULL)
2411 	    {
2412 	      error (0, 0, gettext ("cannot get data for section %d: %s"),
2413 		     (int) elf_ndxscn (scn), elf_errmsg (-1));
2414 	      continue;
2415 	    }
2416 
2417 	  nbucket = ((Elf32_Word *) data->d_buf)[0];
2418 	  nchain = ((Elf32_Word *) data->d_buf)[1];
2419 	  bucket = &((Elf32_Word *) data->d_buf)[2];
2420 	  chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
2421 
2422 	  printf (ngettext ("\
2423 \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",
2424 			    "\
2425 \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",
2426 			    nbucket),
2427 		  (unsigned int) elf_ndxscn (scn),
2428 		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2429 		  (int) nbucket,
2430 		  gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
2431 		  shdr->sh_addr,
2432 		  shdr->sh_offset,
2433 		  (unsigned int) shdr->sh_link,
2434 		  elf_strptr (ebl->elf, shstrndx,
2435 			      gelf_getshdr (elf_getscn (ebl->elf,
2436 							shdr->sh_link),
2437 					    &glink)->sh_name));
2438 
2439 	  lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2440 
2441 	  for (cnt = 0; cnt < nbucket; ++cnt)
2442 	    if (bucket[cnt] != 0)
2443 	      {
2444 		Elf32_Word inner;
2445 
2446 		inner = bucket[cnt];
2447 		while (inner > 0 && inner < nchain)
2448 		  {
2449 		    ++nsyms;
2450 		    if (maxlength < ++lengths[cnt])
2451 		      ++maxlength;
2452 
2453 		    inner = chain[inner];
2454 		  }
2455 	      }
2456 
2457 	  counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
2458 
2459 	  for (cnt = 0; cnt < nbucket; ++cnt)
2460 	    ++counts[lengths[cnt]];
2461 
2462 	  if (nbucket > 0)
2463 	    {
2464 	      uint64_t success = 0;
2465 	      Elf32_Word acc;
2466 
2467 	      puts (gettext (" Length  Number  % of total  Coverage"));
2468 	      printf (gettext ("      0  %6" PRIu32 "      %5.1f%%\n"),
2469 		      counts[0], (counts[0] * 100.0) / nbucket);
2470 
2471 	      for (cnt = 1; cnt <= maxlength; ++cnt)
2472 		{
2473 		  nzero_counts += counts[cnt] * cnt;
2474 		  printf (gettext ("\
2475 %7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
2476 			  (int) cnt,
2477 			  counts[cnt], (counts[cnt] * 100.0) / nbucket,
2478 			  (nzero_counts * 100.0) / nsyms);
2479 		}
2480 
2481 	      acc = 0;
2482 	      for (cnt = 1; cnt <= maxlength; ++cnt)
2483 		{
2484 		  acc += cnt;
2485 		  success += counts[cnt] * acc;
2486 		}
2487 
2488 	      printf (gettext ("\
2489  Average number of tests:   successful lookup: %f\n\
2490                           unsuccessful lookup: %f\n"),
2491 		      (double) success / (double) nzero_counts,
2492 		      (double) nzero_counts / (double) nbucket);
2493 	    }
2494 
2495 	  free (counts);
2496 	  free (lengths);
2497 	}
2498     }
2499 }
2500 
2501 
2502 static void
print_liblist(Ebl * ebl,GElf_Ehdr * ehdr)2503 print_liblist (Ebl *ebl, GElf_Ehdr *ehdr)
2504 {
2505   /* Find the library list sections.  For this we have to search
2506      through the section table.  */
2507   Elf_Scn *scn = NULL;
2508 
2509   /* Get the section header string table index.  */
2510   size_t shstrndx;
2511   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
2512     error (EXIT_FAILURE, 0,
2513 	   gettext ("cannot get section header string table index"));
2514 
2515   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2516     {
2517       GElf_Shdr shdr_mem;
2518       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2519 
2520       if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
2521 	{
2522 	  int nentries = shdr->sh_size / shdr->sh_entsize;
2523 	  printf (ngettext ("\
2524 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2525 			    "\
2526 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2527 			    nentries),
2528 		  elf_ndxscn (scn),
2529 		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2530 		  shdr->sh_offset,
2531 		  nentries);
2532 
2533 	  Elf_Data *data = elf_getdata (scn, NULL);
2534 	  if (data == NULL)
2535 	    return;
2536 
2537 	  puts (gettext ("\
2538        Library                       Time Stamp          Checksum Version Flags"));
2539 
2540 	  for (int cnt = 0; cnt < nentries; ++cnt)
2541 	    {
2542 	      GElf_Lib lib_mem;
2543 	      GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
2544 	      if (lib == NULL)
2545 		continue;
2546 
2547 	      time_t t = (time_t) lib->l_time_stamp;
2548 	      struct tm *tm = gmtime (&t);
2549 	      if (tm == NULL)
2550 		continue;
2551 
2552 	      printf ("  [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
2553 		      cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
2554 		      tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
2555 		      tm->tm_hour, tm->tm_min, tm->tm_sec,
2556 		      (unsigned int) lib->l_checksum,
2557 		      (unsigned int) lib->l_version,
2558 		      (unsigned int) lib->l_flags);
2559 	    }
2560 	}
2561     }
2562 }
2563 
2564 
2565 static const char *
dwarf_tag_string(unsigned int tag)2566 dwarf_tag_string (unsigned int tag)
2567 {
2568   static const char *known_tags[]  =
2569     {
2570       [DW_TAG_array_type] = "array_type",
2571       [DW_TAG_class_type] = "class_type",
2572       [DW_TAG_entry_point] = "entry_point",
2573       [DW_TAG_enumeration_type] = "enumeration_type",
2574       [DW_TAG_formal_parameter] = "formal_parameter",
2575       [DW_TAG_imported_declaration] = "imported_declaration",
2576       [DW_TAG_label] = "label",
2577       [DW_TAG_lexical_block] = "lexical_block",
2578       [DW_TAG_member] = "member",
2579       [DW_TAG_pointer_type] = "pointer_type",
2580       [DW_TAG_reference_type] = "reference_type",
2581       [DW_TAG_compile_unit] = "compile_unit",
2582       [DW_TAG_string_type] = "string_type",
2583       [DW_TAG_structure_type] = "structure_type",
2584       [DW_TAG_subroutine_type] = "subroutine_type",
2585       [DW_TAG_typedef] = "typedef",
2586       [DW_TAG_union_type] = "union_type",
2587       [DW_TAG_unspecified_parameters] = "unspecified_parameters",
2588       [DW_TAG_variant] = "variant",
2589       [DW_TAG_common_block] = "common_block",
2590       [DW_TAG_common_inclusion] = "common_inclusion",
2591       [DW_TAG_inheritance] = "inheritance",
2592       [DW_TAG_inlined_subroutine] = "inlined_subroutine",
2593       [DW_TAG_module] = "module",
2594       [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
2595       [DW_TAG_set_type] = "set_type",
2596       [DW_TAG_subrange_type] = "subrange_type",
2597       [DW_TAG_with_stmt] = "with_stmt",
2598       [DW_TAG_access_declaration] = "access_declaration",
2599       [DW_TAG_base_type] = "base_type",
2600       [DW_TAG_catch_block] = "catch_block",
2601       [DW_TAG_const_type] = "const_type",
2602       [DW_TAG_constant] = "constant",
2603       [DW_TAG_enumerator] = "enumerator",
2604       [DW_TAG_file_type] = "file_type",
2605       [DW_TAG_friend] = "friend",
2606       [DW_TAG_namelist] = "namelist",
2607       [DW_TAG_namelist_item] = "namelist_item",
2608       [DW_TAG_packed_type] = "packed_type",
2609       [DW_TAG_subprogram] = "subprogram",
2610       [DW_TAG_template_type_param] = "template_type_param",
2611       [DW_TAG_template_value_param] = "template_value_param",
2612       [DW_TAG_thrown_type] = "thrown_type",
2613       [DW_TAG_try_block] = "try_block",
2614       [DW_TAG_variant_part] = "variant_part",
2615       [DW_TAG_variable] = "variable",
2616       [DW_TAG_volatile_type] = "volatile_type",
2617     };
2618   const unsigned int nknown_tags = (sizeof (known_tags)
2619 				    / sizeof (known_tags[0]));
2620   static char buf[40];
2621   const char *result = NULL;
2622 
2623   if (tag < nknown_tags)
2624     result = known_tags[tag];
2625 
2626   if (result == NULL)
2627     /* There are a few known extensions.  */
2628     switch (tag)
2629       {
2630       case DW_TAG_MIPS_loop:
2631 	result = "MIPS_loop";
2632 	break;
2633 
2634       case DW_TAG_format_label:
2635 	result = "format_label";
2636 	break;
2637 
2638       case DW_TAG_function_template:
2639 	result = "function_template";
2640 	break;
2641 
2642       case DW_TAG_class_template:
2643 	result = "class_template";
2644 	break;
2645 
2646       default:
2647 	if (tag < DW_TAG_lo_user)
2648 	  snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag);
2649 	else
2650 	  snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag);
2651 	result = buf;
2652 	break;
2653       }
2654 
2655   return result;
2656 }
2657 
2658 
2659 static const char *
dwarf_attr_string(unsigned int attrnum)2660 dwarf_attr_string (unsigned int attrnum)
2661 {
2662   static const char *known_attrs[] =
2663     {
2664       [DW_AT_sibling] = "sibling",
2665       [DW_AT_location] = "location",
2666       [DW_AT_name] = "name",
2667       [DW_AT_ordering] = "ordering",
2668       [DW_AT_subscr_data] = "subscr_data",
2669       [DW_AT_byte_size] = "byte_size",
2670       [DW_AT_bit_offset] = "bit_offset",
2671       [DW_AT_bit_size] = "bit_size",
2672       [DW_AT_element_list] = "element_list",
2673       [DW_AT_stmt_list] = "stmt_list",
2674       [DW_AT_low_pc] = "low_pc",
2675       [DW_AT_high_pc] = "high_pc",
2676       [DW_AT_language] = "language",
2677       [DW_AT_member] = "member",
2678       [DW_AT_discr] = "discr",
2679       [DW_AT_discr_value] = "discr_value",
2680       [DW_AT_visibility] = "visibility",
2681       [DW_AT_import] = "import",
2682       [DW_AT_string_length] = "string_length",
2683       [DW_AT_common_reference] = "common_reference",
2684       [DW_AT_comp_dir] = "comp_dir",
2685       [DW_AT_const_value] = "const_value",
2686       [DW_AT_containing_type] = "containing_type",
2687       [DW_AT_default_value] = "default_value",
2688       [DW_AT_inline] = "inline",
2689       [DW_AT_is_optional] = "is_optional",
2690       [DW_AT_lower_bound] = "lower_bound",
2691       [DW_AT_producer] = "producer",
2692       [DW_AT_prototyped] = "prototyped",
2693       [DW_AT_return_addr] = "return_addr",
2694       [DW_AT_start_scope] = "start_scope",
2695       [DW_AT_stride_size] = "stride_size",
2696       [DW_AT_upper_bound] = "upper_bound",
2697       [DW_AT_abstract_origin] = "abstract_origin",
2698       [DW_AT_accessibility] = "accessibility",
2699       [DW_AT_address_class] = "address_class",
2700       [DW_AT_artificial] = "artificial",
2701       [DW_AT_base_types] = "base_types",
2702       [DW_AT_calling_convention] = "calling_convention",
2703       [DW_AT_count] = "count",
2704       [DW_AT_data_member_location] = "data_member_location",
2705       [DW_AT_decl_column] = "decl_column",
2706       [DW_AT_decl_file] = "decl_file",
2707       [DW_AT_decl_line] = "decl_line",
2708       [DW_AT_declaration] = "declaration",
2709       [DW_AT_discr_list] = "discr_list",
2710       [DW_AT_encoding] = "encoding",
2711       [DW_AT_external] = "external",
2712       [DW_AT_frame_base] = "frame_base",
2713       [DW_AT_friend] = "friend",
2714       [DW_AT_identifier_case] = "identifier_case",
2715       [DW_AT_macro_info] = "macro_info",
2716       [DW_AT_namelist_items] = "namelist_items",
2717       [DW_AT_priority] = "priority",
2718       [DW_AT_segment] = "segment",
2719       [DW_AT_specification] = "specification",
2720       [DW_AT_static_link] = "static_link",
2721       [DW_AT_type] = "type",
2722       [DW_AT_use_location] = "use_location",
2723       [DW_AT_variable_parameter] = "variable_parameter",
2724       [DW_AT_virtuality] = "virtuality",
2725       [DW_AT_vtable_elem_location] = "vtable_elem_location"
2726     };
2727   const unsigned int nknown_attrs = (sizeof (known_attrs)
2728 				     / sizeof (known_attrs[0]));
2729   static char buf[40];
2730   const char *result = NULL;
2731 
2732   if (attrnum < nknown_attrs)
2733     result = known_attrs[attrnum];
2734 
2735   if (result == NULL)
2736     /* There are a few known extensions.  */
2737     switch (attrnum)
2738       {
2739       case DW_AT_MIPS_fde:
2740 	result = "MIPS_fde";
2741 	break;
2742 
2743       case DW_AT_MIPS_loop_begin:
2744 	result = "MIPS_loop_begin";
2745 	break;
2746 
2747       case DW_AT_MIPS_tail_loop_begin:
2748 	result = "MIPS_tail_loop_begin";
2749 	break;
2750 
2751       case DW_AT_MIPS_epilog_begin:
2752 	result = "MIPS_epilog_begin";
2753 	break;
2754 
2755       case DW_AT_MIPS_loop_unroll_factor:
2756 	result = "MIPS_loop_unroll_factor";
2757 	break;
2758 
2759       case DW_AT_MIPS_software_pipeline_depth:
2760 	result = "MIPS_software_pipeline_depth";
2761 	break;
2762 
2763       case DW_AT_MIPS_linkage_name:
2764 	result = "MIPS_linkage_name";
2765 	break;
2766 
2767       case DW_AT_MIPS_stride:
2768 	result = "MIPS_stride";
2769 	break;
2770 
2771       case DW_AT_MIPS_abstract_name:
2772 	result = "MIPS_abstract_name";
2773 	break;
2774 
2775       case DW_AT_MIPS_clone_origin:
2776 	result = "MIPS_clone_origin";
2777 	break;
2778 
2779       case DW_AT_MIPS_has_inlines:
2780 	result = "MIPS_has_inlines";
2781 	break;
2782 
2783       case DW_AT_MIPS_stride_byte:
2784 	result = "MIPS_stride_byte";
2785 	break;
2786 
2787       case DW_AT_MIPS_stride_elem:
2788 	result = "MIPS_stride_elem";
2789 	break;
2790 
2791       case DW_AT_MIPS_ptr_dopetype:
2792 	result = "MIPS_ptr_dopetype";
2793 	break;
2794 
2795       case DW_AT_MIPS_allocatable_dopetype:
2796 	result = "MIPS_allocatable_dopetype";
2797 	break;
2798 
2799       case DW_AT_MIPS_assumed_shape_dopetype:
2800 	result = "MIPS_assumed_shape_dopetype";
2801 	break;
2802 
2803       case DW_AT_MIPS_assumed_size:
2804 	result = "MIPS_assumed_size";
2805 	break;
2806 
2807       case DW_AT_sf_names:
2808 	result = "sf_names";
2809 	break;
2810 
2811       case DW_AT_src_info:
2812 	result = "src_info";
2813 	break;
2814 
2815       case DW_AT_mac_info:
2816 	result = "mac_info";
2817 	break;
2818 
2819       case DW_AT_src_coords:
2820 	result = "src_coords";
2821 	break;
2822 
2823       case DW_AT_body_begin:
2824 	result = "body_begin";
2825 	break;
2826 
2827       case DW_AT_body_end:
2828 	result = "body_end";
2829 	break;
2830 
2831       default:
2832 	if (attrnum < DW_AT_lo_user)
2833 	  snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"),
2834 		    attrnum);
2835 	else
2836 	  snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"),
2837 		    attrnum);
2838 	result = buf;
2839 	break;
2840       }
2841 
2842   return result;
2843 }
2844 
2845 
2846 static const char *
dwarf_form_string(unsigned int form)2847 dwarf_form_string (unsigned int form)
2848 {
2849   static const char *known_forms[] =
2850     {
2851       [DW_FORM_addr] = "addr",
2852       [DW_FORM_block2] = "block2",
2853       [DW_FORM_block4] = "block4",
2854       [DW_FORM_data2] = "data2",
2855       [DW_FORM_data4] = "data4",
2856       [DW_FORM_data8] = "data8",
2857       [DW_FORM_string] = "string",
2858       [DW_FORM_block] = "block",
2859       [DW_FORM_block1] = "block1",
2860       [DW_FORM_data1] = "data1",
2861       [DW_FORM_flag] = "flag",
2862       [DW_FORM_sdata] = "sdata",
2863       [DW_FORM_strp] = "strp",
2864       [DW_FORM_udata] = "udata",
2865       [DW_FORM_ref_addr] = "ref_addr",
2866       [DW_FORM_ref1] = "ref1",
2867       [DW_FORM_ref2] = "ref2",
2868       [DW_FORM_ref4] = "ref4",
2869       [DW_FORM_ref8] = "ref8",
2870       [DW_FORM_ref_udata] = "ref_udata",
2871       [DW_FORM_indirect] = "indirect"
2872     };
2873   const unsigned int nknown_forms = (sizeof (known_forms)
2874 				     / sizeof (known_forms[0]));
2875   static char buf[40];
2876   const char *result = NULL;
2877 
2878   if (form < nknown_forms)
2879     result = known_forms[form];
2880 
2881   if (result == NULL)
2882     snprintf (buf, sizeof buf, gettext ("unknown form %" PRIx64),
2883 	      (uint64_t) form);
2884 
2885   return result;
2886 }
2887 
2888 
2889 static const char *
dwarf_lang_string(unsigned int lang)2890 dwarf_lang_string (unsigned int lang)
2891 {
2892   static const char *known[] =
2893     {
2894       [DW_LANG_C89] = "ISO C89",
2895       [DW_LANG_C] = "C",
2896       [DW_LANG_Ada83] = "Ada83",
2897       [DW_LANG_C_plus_plus ] = "C++",
2898       [DW_LANG_Cobol74] = "Cobol74",
2899       [DW_LANG_Cobol85] = "Cobol85",
2900       [DW_LANG_Fortran77] = "Fortran77",
2901       [DW_LANG_Fortran90] = "Fortran90",
2902       [DW_LANG_Pascal83] = "Pascal83",
2903       [DW_LANG_Modula2] = "Modula2",
2904       [DW_LANG_Java] = "Java",
2905       [DW_LANG_C99] = "ISO C99",
2906       [DW_LANG_Ada95] = "Ada95",
2907       [DW_LANG_Fortran95] = "Fortran95",
2908       [DW_LANG_PL1] = "PL1"
2909     };
2910 
2911   if (lang < sizeof (known) / sizeof (known[0]))
2912     return known[lang];
2913   else if (lang == DW_LANG_Mips_Assembler)
2914     /* This language tag is used for assembler in general.  */
2915     return "Assembler";
2916 
2917   if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user)
2918     {
2919       static char buf[100];
2920       snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user);
2921       return buf;
2922     }
2923 
2924   return "???";
2925 }
2926 
2927 
2928 static void
print_ops(Dwarf * dbg,int level,unsigned int addrsize,Dwarf_Word len,unsigned char * data)2929 print_ops (Dwarf *dbg, int level, unsigned int addrsize, Dwarf_Word len,
2930 	   unsigned char *data)
2931 {
2932   static const char *known[] =
2933     {
2934       [DW_OP_addr] = "addr",
2935       [DW_OP_deref] = "deref",
2936       [DW_OP_const1u] = "const1u",
2937       [DW_OP_const1s] = "const1s",
2938       [DW_OP_const2u] = "const2u",
2939       [DW_OP_const2s] = "const2s",
2940       [DW_OP_const4u] = "const4u",
2941       [DW_OP_const4s] = "const4s",
2942       [DW_OP_const8u] = "const8u",
2943       [DW_OP_const8s] = "const8s",
2944       [DW_OP_constu] = "constu",
2945       [DW_OP_consts] = "consts",
2946       [DW_OP_dup] = "dup",
2947       [DW_OP_drop] = "drop",
2948       [DW_OP_over] = "over",
2949       [DW_OP_pick] = "pick",
2950       [DW_OP_swap] = "swap",
2951       [DW_OP_rot] = "rot",
2952       [DW_OP_xderef] = "xderef",
2953       [DW_OP_abs] = "abs",
2954       [DW_OP_and] = "and",
2955       [DW_OP_div] = "div",
2956       [DW_OP_minus] = "minus",
2957       [DW_OP_mod] = "mod",
2958       [DW_OP_mul] = "mul",
2959       [DW_OP_neg] = "neg",
2960       [DW_OP_not] = "not",
2961       [DW_OP_or] = "or",
2962       [DW_OP_plus] = "plus",
2963       [DW_OP_plus_uconst] = "plus_uconst",
2964       [DW_OP_shl] = "shl",
2965       [DW_OP_shr] = "shr",
2966       [DW_OP_shra] = "shra",
2967       [DW_OP_xor] = "xor",
2968       [DW_OP_bra] = "bra",
2969       [DW_OP_eq] = "eq",
2970       [DW_OP_ge] = "ge",
2971       [DW_OP_gt] = "gt",
2972       [DW_OP_le] = "le",
2973       [DW_OP_lt] = "lt",
2974       [DW_OP_ne] = "ne",
2975       [DW_OP_skip] = "skip",
2976       [DW_OP_lit0] = "lit0",
2977       [DW_OP_lit1] = "lit1",
2978       [DW_OP_lit2] = "lit2",
2979       [DW_OP_lit3] = "lit3",
2980       [DW_OP_lit4] = "lit4",
2981       [DW_OP_lit5] = "lit5",
2982       [DW_OP_lit6] = "lit6",
2983       [DW_OP_lit7] = "lit7",
2984       [DW_OP_lit8] = "lit8",
2985       [DW_OP_lit9] = "lit9",
2986       [DW_OP_lit10] = "lit10",
2987       [DW_OP_lit11] = "lit11",
2988       [DW_OP_lit12] = "lit12",
2989       [DW_OP_lit13] = "lit13",
2990       [DW_OP_lit14] = "lit14",
2991       [DW_OP_lit15] = "lit15",
2992       [DW_OP_lit16] = "lit16",
2993       [DW_OP_lit17] = "lit17",
2994       [DW_OP_lit18] = "lit18",
2995       [DW_OP_lit19] = "lit19",
2996       [DW_OP_lit20] = "lit20",
2997       [DW_OP_lit21] = "lit21",
2998       [DW_OP_lit22] = "lit22",
2999       [DW_OP_lit23] = "lit23",
3000       [DW_OP_lit24] = "lit24",
3001       [DW_OP_lit25] = "lit25",
3002       [DW_OP_lit26] = "lit26",
3003       [DW_OP_lit27] = "lit27",
3004       [DW_OP_lit28] = "lit28",
3005       [DW_OP_lit29] = "lit29",
3006       [DW_OP_lit30] = "lit30",
3007       [DW_OP_lit31] = "lit31",
3008       [DW_OP_reg0] = "reg0",
3009       [DW_OP_reg1] = "reg1",
3010       [DW_OP_reg2] = "reg2",
3011       [DW_OP_reg3] = "reg3",
3012       [DW_OP_reg4] = "reg4",
3013       [DW_OP_reg5] = "reg5",
3014       [DW_OP_reg6] = "reg6",
3015       [DW_OP_reg7] = "reg7",
3016       [DW_OP_reg8] = "reg8",
3017       [DW_OP_reg9] = "reg9",
3018       [DW_OP_reg10] = "reg10",
3019       [DW_OP_reg11] = "reg11",
3020       [DW_OP_reg12] = "reg12",
3021       [DW_OP_reg13] = "reg13",
3022       [DW_OP_reg14] = "reg14",
3023       [DW_OP_reg15] = "reg15",
3024       [DW_OP_reg16] = "reg16",
3025       [DW_OP_reg17] = "reg17",
3026       [DW_OP_reg18] = "reg18",
3027       [DW_OP_reg19] = "reg19",
3028       [DW_OP_reg20] = "reg20",
3029       [DW_OP_reg21] = "reg21",
3030       [DW_OP_reg22] = "reg22",
3031       [DW_OP_reg23] = "reg23",
3032       [DW_OP_reg24] = "reg24",
3033       [DW_OP_reg25] = "reg25",
3034       [DW_OP_reg26] = "reg26",
3035       [DW_OP_reg27] = "reg27",
3036       [DW_OP_reg28] = "reg28",
3037       [DW_OP_reg29] = "reg29",
3038       [DW_OP_reg30] = "reg30",
3039       [DW_OP_reg31] = "reg31",
3040       [DW_OP_breg0] = "breg0",
3041       [DW_OP_breg1] = "breg1",
3042       [DW_OP_breg2] = "breg2",
3043       [DW_OP_breg3] = "breg3",
3044       [DW_OP_breg4] = "breg4",
3045       [DW_OP_breg5] = "breg5",
3046       [DW_OP_breg6] = "breg6",
3047       [DW_OP_breg7] = "breg7",
3048       [DW_OP_breg8] = "breg8",
3049       [DW_OP_breg9] = "breg9",
3050       [DW_OP_breg10] = "breg10",
3051       [DW_OP_breg11] = "breg11",
3052       [DW_OP_breg12] = "breg12",
3053       [DW_OP_breg13] = "breg13",
3054       [DW_OP_breg14] = "breg14",
3055       [DW_OP_breg15] = "breg15",
3056       [DW_OP_breg16] = "breg16",
3057       [DW_OP_breg17] = "breg17",
3058       [DW_OP_breg18] = "breg18",
3059       [DW_OP_breg19] = "breg19",
3060       [DW_OP_breg20] = "breg20",
3061       [DW_OP_breg21] = "breg21",
3062       [DW_OP_breg22] = "breg22",
3063       [DW_OP_breg23] = "breg23",
3064       [DW_OP_breg24] = "breg24",
3065       [DW_OP_breg25] = "breg25",
3066       [DW_OP_breg26] = "breg26",
3067       [DW_OP_breg27] = "breg27",
3068       [DW_OP_breg28] = "breg28",
3069       [DW_OP_breg29] = "breg29",
3070       [DW_OP_breg30] = "breg30",
3071       [DW_OP_breg31] = "breg31",
3072       [DW_OP_regx] = "regx",
3073       [DW_OP_fbreg] = "fbreg",
3074       [DW_OP_bregx] = "bregx",
3075       [DW_OP_piece] = "piece",
3076       [DW_OP_deref_size] = "deref_size",
3077       [DW_OP_xderef_size] = "xderef_size",
3078       [DW_OP_nop] = "nop",
3079       [DW_OP_push_object_address] = "push_object_address",
3080       [DW_OP_call2] = "call2",
3081       [DW_OP_call4] = "call4",
3082       [DW_OP_call_ref] = "call_ref",
3083     };
3084 
3085   Dwarf_Word offset = 0;
3086   while (len-- > 0)
3087     {
3088       size_t op = *((unsigned char *) data);
3089       ++data;
3090 
3091       switch (op)
3092 	{
3093 	case DW_OP_call_ref:
3094 	case DW_OP_addr:;
3095 	  /* Address operand.  */
3096 	  Dwarf_Word addr;
3097 	  if (addrsize == 4)
3098 	    addr = read_4ubyte_unaligned (dbg, data);
3099 	  else
3100 	    {
3101 	      assert (addrsize == 8);
3102 	      addr = read_8ubyte_unaligned (dbg, data);
3103 	    }
3104 	  data += addrsize;
3105 	  len -= addrsize;
3106 
3107 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRIuMAX "\n",
3108 		  (int) (20 + level * 2), "", (uintmax_t) offset,
3109 		  known[op] ?: "???", (uintmax_t) addr);
3110 	  offset += 1 + addrsize;
3111 	  break;
3112 
3113 	case DW_OP_deref_size:		/* XXX Correct?  */
3114 	case DW_OP_xderef_size:		/* XXX Correct?  */
3115 	case DW_OP_pick:
3116 	case DW_OP_const1u:
3117 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRIu8 "\n",
3118 		  (int) (20 + level * 2), "", (uintmax_t) offset,
3119 		  known[op] ?: "???", *((uint8_t *) data));
3120 	  ++data;
3121 	  --len;
3122 	  offset += 2;
3123 	  break;
3124 
3125 	case DW_OP_const2u:
3126 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRIu16 "\n",
3127 		  (int) (20 + level * 2), "", (uintmax_t) offset,
3128 		  known[op] ?: "???", read_2ubyte_unaligned (dbg, data));
3129 	  len -= 2;
3130 	  data += 2;
3131 	  offset += 3;
3132 	  break;
3133 
3134 	case DW_OP_const4u:
3135 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRIu32 "\n",
3136 		  (int) (20 + level * 2), "", (uintmax_t) offset,
3137 		  known[op] ?: "???", read_4ubyte_unaligned (dbg, data));
3138 	  len -= 4;
3139 	  data += 4;
3140 	  offset += 5;
3141 	  break;
3142 
3143 	case DW_OP_const8u:
3144 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRIu64 "\n",
3145 		  (int) (20 + level * 2), "", (uintmax_t) offset,
3146 		  known[op] ?: "???", read_8ubyte_unaligned (dbg, data));
3147 	  len -= 8;
3148 	  data += 8;
3149 	  offset += 9;
3150 	  break;
3151 
3152 	case DW_OP_const1s:
3153 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRId8 "\n",
3154 		  (int) (20 + level * 2), "", (uintmax_t) offset,
3155 		  known[op] ?: "???", *((int8_t *) data));
3156 	  ++data;
3157 	  --len;
3158 	  offset += 2;
3159 	  break;
3160 
3161 	case DW_OP_const2s:
3162 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRId16 "\n",
3163 		  (int) (20 + level * 2), "", (uintmax_t) offset,
3164 		  known[op] ?: "???", read_2sbyte_unaligned (dbg, data));
3165 	  len -= 2;
3166 	  data += 2;
3167 	  offset += 3;
3168 	  break;
3169 
3170 	case DW_OP_const4s:
3171 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRId32 "\n",
3172 		  (int) (20 + level * 2), "", (uintmax_t) offset,
3173 		  known[op] ?: "???", read_4sbyte_unaligned (dbg, data));
3174 	  len -= 4;
3175 	  data += 4;
3176 	  offset += 5;
3177 	  break;
3178 
3179 	case DW_OP_const8s:
3180 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRId64 "\n",
3181 		  (int) (20 + level * 2), "", (uintmax_t) offset,
3182 		  known[op] ?: "???", read_8sbyte_unaligned (dbg, data));
3183 	  len -= 8;
3184 	  data += 8;
3185 	  offset += 9;
3186 	  break;
3187 
3188 	case DW_OP_piece:		/* XXX Correct?  */
3189 	case DW_OP_regx:
3190 	case DW_OP_plus_uconst:
3191 	case DW_OP_constu:;
3192 	  unsigned char *start = data;
3193 	  unsigned int uleb;
3194 	  get_uleb128 (uleb, data);
3195 	  printf ("           %*s [%4" PRIuMAX "] %s %u\n",
3196 		  (int) (20 + level * 2), "", (uintmax_t) offset,
3197 		  known[op] ?: "???", uleb);
3198 	  len -= data - start;
3199 	  offset += 1 + (data - start);
3200 	  break;
3201 
3202 	case DW_OP_fbreg:
3203 	case DW_OP_breg0 ... DW_OP_breg31:
3204 	case DW_OP_consts:
3205 	  start = data;
3206 	  unsigned int sleb;
3207 	  get_sleb128 (sleb, data);
3208 	  printf ("           %*s [%4" PRIuMAX "] %s %d\n",
3209 		  (int) (20 + level * 2), "", (uintmax_t) offset,
3210 		  known[op] ?: "???", sleb);
3211 	  len -= data - start;
3212 	  offset += 1 + (data - start);
3213 	  break;
3214 
3215 	case DW_OP_bregx:
3216 	  start = data;
3217 	  get_uleb128 (uleb, data);
3218 	  get_sleb128 (sleb, data);
3219 	  printf ("           %*s [%4" PRIuMAX "] %s %u %d\n",
3220 		  (int) (20 + level * 2), "", (uintmax_t) offset,
3221 		  known[op] ?: "???", uleb, sleb);
3222 	  len -= data - start;
3223 	  offset += 1 + (data - start);
3224 	  break;
3225 
3226 	case DW_OP_call2:
3227 	case DW_OP_call4:
3228 	case DW_OP_skip:
3229 	case DW_OP_bra:
3230 	  printf ("           %*s [%4" PRIuMAX "] %s %" PRIuMAX "\n",
3231 		  (int) (20 + level * 2), "", (uintmax_t) offset,
3232 		  known[op] ?: "???",
3233 		  (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
3234 	  len -= 2;
3235 	  data += 2;
3236 	  offset += 3;
3237 	  break;
3238 
3239 	default:
3240 	  /* No Operand.  */
3241 	  printf ("           %*s [%4" PRIuMAX "] %s\n",
3242 		  (int) (20 + level * 2), "", (uintmax_t) offset,
3243 		  known[op] ?: "???");
3244 	  ++offset;
3245 	  break;
3246 	}
3247     }
3248 }
3249 
3250 
3251 static void
print_debug_abbrev_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)3252 print_debug_abbrev_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
3253 			    GElf_Shdr *shdr, Dwarf *dbg)
3254 {
3255   printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
3256 		   " [ Code]\n"),
3257 	  ".debug_abbrev", (uint64_t) shdr->sh_offset);
3258 
3259   Dwarf_Off offset = 0;
3260   while (1)
3261     {
3262       size_t length;
3263       Dwarf_Abbrev abbrev;
3264 
3265       if  (dwarf_offabbrev (dbg, offset, &length, &abbrev) != 0)
3266 	{
3267 	  printf (gettext (" *** error while reading abbreviation: %s\n"),
3268 		  dwarf_errmsg (-1));
3269 	  break;
3270 	}
3271 
3272       if (length == 1)
3273 	/* This is the NUL byte at the end of the section.  */
3274 	break;
3275 
3276       /* We know these calls can never fail.  */
3277       unsigned int code = dwarf_getabbrevcode (&abbrev);
3278       unsigned int tag = dwarf_getabbrevtag (&abbrev);
3279       int has_children = dwarf_abbrevhaschildren (&abbrev);
3280 
3281       printf (gettext (" [%5u] offset: %" PRId64
3282 		       ", children: %s, tag: %s\n"),
3283 	      code, (int64_t) offset,
3284 	      has_children ? gettext ("yes") : gettext ("no"),
3285 	      dwarf_tag_string (tag));
3286 
3287       size_t cnt = 0;
3288       unsigned int name;
3289       unsigned int form;
3290       Dwarf_Off enoffset;
3291       while (dwarf_getabbrevattr (&abbrev, cnt, &name, &form, &enoffset) == 0)
3292 	{
3293 	  printf ("          attr: %s, form: %s, offset: %#" PRIx64 "\n",
3294 		  dwarf_attr_string (name), dwarf_form_string (form),
3295 		  (uint64_t) enoffset);
3296 
3297 	  ++cnt;
3298 	}
3299 
3300       offset += length;
3301     }
3302 }
3303 
3304 
3305 /* Print content of DWARF .debug_aranges section.  We fortunately do
3306    not have to know a bit about the structure of the section, libdwarf
3307    takes care of it.  */
3308 static void
print_debug_aranges_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)3309 print_debug_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
3310 			     GElf_Shdr *shdr, Dwarf *dbg)
3311 {
3312   Dwarf_Aranges *aranges;
3313   size_t cnt;
3314   if (dwarf_getaranges (dbg, &aranges, &cnt) != 0)
3315     {
3316       error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
3317 	     dwarf_errmsg (-1));
3318       return;
3319     }
3320 
3321   printf (ngettext ("\
3322 \nDWARF section '%s' at offset %#" PRIx64 " contains %zu entry:\n",
3323 		    "\
3324 \nDWARF section '%s' at offset %#" PRIx64 " contains %zu entries:\n",
3325 		    cnt),
3326 	  ".debug_aranges", (uint64_t) shdr->sh_offset, cnt);
3327 
3328   /* Compute floor(log16(cnt)).  */
3329   size_t tmp = cnt;
3330   int digits = 1;
3331   while (tmp >= 16)
3332     {
3333       ++digits;
3334       tmp >>= 4;
3335     }
3336 
3337   for (size_t n = 0; n < cnt; ++n)
3338     {
3339       Dwarf_Arange *runp = dwarf_onearange (aranges, n);
3340       if (runp == NULL)
3341 	{
3342 	  printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
3343 	  return;
3344 	}
3345 
3346       Dwarf_Addr start;
3347       Dwarf_Word length;
3348       Dwarf_Off offset;
3349 
3350       if (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0)
3351 	printf (gettext (" [%*zu] ???\n"), digits, n);
3352       else
3353 	printf (gettext (" [%*zu] start: %0#*" PRIx64
3354 			 ", length: %5" PRIu64 ", CU DIE offset: %6"
3355 			 PRId64 "\n"),
3356 		digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
3357 		(uint64_t) start, (uint64_t) length, (int64_t) offset);
3358     }
3359 }
3360 
3361 
3362 static void
print_debug_frame_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)3363 print_debug_frame_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
3364 			   GElf_Shdr *shdr, Dwarf *dbg)
3365 {
3366 }
3367 
3368 
3369 struct attrcb_args
3370 {
3371   Dwarf *dbg;
3372   int level;
3373   unsigned int addrsize;
3374   Dwarf_Off cu_offset;
3375 };
3376 
3377 
3378 static int
attr_callback(Dwarf_Attribute * attrp,void * arg)3379 attr_callback (Dwarf_Attribute *attrp, void *arg)
3380 {
3381   struct attrcb_args *cbargs = (struct attrcb_args *) arg;
3382   const int level = cbargs->level;
3383 
3384   unsigned int attr = dwarf_whatattr (attrp);
3385   if (unlikely (attr == 0))
3386     {
3387       error (0, 0, gettext ("cannot get attribute code: %s"),
3388 	     dwarf_errmsg (-1));
3389       return DWARF_CB_ABORT;
3390     }
3391 
3392   unsigned int form = dwarf_whatform (attrp);
3393   if (unlikely (form == 0))
3394     {
3395       error (0, 0, gettext ("cannot get attribute form: %s"),
3396 	     dwarf_errmsg (-1));
3397       return DWARF_CB_ABORT;
3398     }
3399 
3400   switch (form)
3401     {
3402     case DW_FORM_addr:;
3403       Dwarf_Addr addr;
3404       if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
3405 	{
3406 	attrval_out:
3407 	  error (0, 0, gettext ("cannot get attribute value: %s"),
3408 		 dwarf_errmsg (-1));
3409 	  return DWARF_CB_ABORT;
3410 	}
3411       printf ("           %*s%-20s %#0*" PRIxMAX "\n",
3412 	      (int) (level * 2), "", dwarf_attr_string (attr),
3413 	      (int) (cbargs->addrsize * 2), (uintmax_t) addr);
3414       break;
3415 
3416     case DW_FORM_indirect:
3417     case DW_FORM_strp:
3418     case DW_FORM_string:;
3419       const char *str = dwarf_formstring (attrp);
3420       if (unlikely (str == NULL))
3421 	goto attrval_out;
3422       printf ("           %*s%-20s \"%s\"\n",
3423 	      (int) (level * 2), "", dwarf_attr_string (attr), str);
3424       break;
3425 
3426     case DW_FORM_ref_addr:
3427     case DW_FORM_ref_udata:
3428     case DW_FORM_ref8:
3429     case DW_FORM_ref4:
3430     case DW_FORM_ref2:
3431     case DW_FORM_ref1:;
3432       Dwarf_Off ref;
3433       if (unlikely (dwarf_formref (attrp, &ref) != 0))
3434 	goto attrval_out;
3435 
3436       printf ("           %*s%-20s [%6" PRIxMAX "]\n",
3437 	      (int) (level * 2), "", dwarf_attr_string (attr),
3438 	      (uintmax_t) (ref + cbargs->cu_offset));
3439       break;
3440 
3441     case DW_FORM_udata:
3442     case DW_FORM_sdata:
3443     case DW_FORM_data8:
3444     case DW_FORM_data4:
3445     case DW_FORM_data2:
3446     case DW_FORM_data1:;
3447       Dwarf_Word num;
3448       if (unlikely (dwarf_formudata (attrp, &num) != 0))
3449 	goto attrval_out;
3450 
3451       if (attr == DW_AT_language)
3452 	{
3453 	  printf ("           %*s%-20s %s (%d)\n",
3454 		  (int) (level * 2), "", dwarf_attr_string (attr),
3455 		  dwarf_lang_string (num), (int) num);
3456 	  break;
3457 	}
3458 
3459       printf ("           %*s%-20s %" PRIuMAX "\n",
3460 	      (int) (level * 2), "", dwarf_attr_string (attr),
3461 	      (uintmax_t) num);
3462       break;
3463 
3464     case DW_FORM_flag:;
3465       bool flag;
3466       if (unlikely (dwarf_formflag (attrp, &flag) != 0))
3467 	goto attrval_out;
3468 
3469       printf ("           %*s%-20s %s\n",
3470 	      (int) (level * 2), "", dwarf_attr_string (attr),
3471 	      nl_langinfo (flag ? YESSTR : NOSTR));
3472       break;
3473 
3474     case DW_FORM_block4:
3475     case DW_FORM_block2:
3476     case DW_FORM_block1:
3477     case DW_FORM_block:;
3478       Dwarf_Block block;
3479       if (unlikely (dwarf_formblock (attrp, &block) != 0))
3480 	goto attrval_out;
3481 
3482       printf ("           %*s%-20s %" PRIxMAX " byte block\n",
3483 	      (int) (level * 2), "", dwarf_attr_string (attr),
3484 	      (uintmax_t) block.length);
3485 
3486       if (attr == DW_AT_data_member_location)
3487 	print_ops (cbargs->dbg, level, cbargs->addrsize, block.length,
3488 		   block.data);
3489       break;
3490 
3491     default:
3492       printf ("           %*s%-20s [form: %d] ???\n",
3493 	      (int) (level * 2), "", dwarf_attr_string (attr),
3494 	      (int) form);
3495       break;
3496     }
3497 
3498   return DWARF_CB_OK;
3499 }
3500 
3501 
3502 static void
print_debug_info_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)3503 print_debug_info_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
3504 			  GElf_Shdr *shdr, Dwarf *dbg)
3505 {
3506   printf (gettext ("\
3507 \nDWARF section '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
3508 	  ".debug_info", (uint64_t) shdr->sh_offset);
3509 
3510   /* If the section is empty we don't have to do anything.  */
3511   if (shdr->sh_size == 0)
3512     return;
3513 
3514   size_t maxdies = 20;
3515   Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
3516 
3517   Dwarf_Off offset = 0;
3518 
3519   /* New compilation unit.  */
3520   size_t cuhl;
3521   //Dwarf_Half version;
3522   Dwarf_Off abbroffset;
3523   uint8_t addrsize;
3524   uint8_t offsize;
3525   Dwarf_Off nextcu;
3526  next_cu:
3527   if (dwarf_nextcu (dbg, offset, &nextcu, &cuhl, &abbroffset, &addrsize,
3528 		    &offsize) != 0)
3529     goto do_return;
3530 
3531   printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
3532 		   " Version: %" PRIu16 ", Abbreviation section offset: %"
3533 		   PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8 "\n"),
3534 	  (uint64_t) offset, /*version*/2, abbroffset, addrsize, offsize);
3535 
3536 
3537   struct attrcb_args args;
3538   args.dbg = dbg;
3539   args.addrsize = addrsize;
3540   args.cu_offset = offset;
3541 
3542   offset += cuhl;
3543 
3544   int level = 0;
3545 
3546   if (unlikely (dwarf_offdie (dbg, offset, &dies[level]) == NULL))
3547     {
3548       error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
3549 			    " in section '%s': %s"),
3550 	     (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
3551       goto do_return;
3552     }
3553 
3554   do
3555     {
3556       offset = dwarf_dieoffset (&dies[level]);
3557       if (offset == -1l)
3558 	{
3559 	  error (0, 0, gettext ("cannot get DIE offset: %s"),
3560 		 dwarf_errmsg (-1));
3561 	  goto do_return;
3562 	}
3563 
3564       int tag = dwarf_tag (&dies[level]);
3565       if (tag == DW_TAG_invalid)
3566 	{
3567 	  error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
3568 				" in section '%s': %s"),
3569 		 (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
3570 	  goto do_return;
3571 	}
3572 
3573       static const char *const lowtags[] =
3574 	{
3575 	  [DW_TAG_array_type] = "array_type",
3576 	  [DW_TAG_class_type] = "class_type",
3577 	  [DW_TAG_entry_point] = "entry_point",
3578 	  [DW_TAG_enumeration_type] = "enumeration_type",
3579 	  [DW_TAG_formal_parameter] = "formal_parameter",
3580 	  [DW_TAG_imported_declaration] = "imported_declaration",
3581 	  [DW_TAG_label] = "label",
3582 	  [DW_TAG_lexical_block] = "lexical_block",
3583 	  [DW_TAG_member] = "member",
3584 	  [DW_TAG_pointer_type] = "pointer_type",
3585 	  [DW_TAG_reference_type] = "reference_type",
3586 	  [DW_TAG_compile_unit] = "compile_unit",
3587 	  [DW_TAG_string_type] = "string_type",
3588 	  [DW_TAG_structure_type] = "structure_type",
3589 	  [DW_TAG_subroutine_type] = "subroutine_type",
3590 	  [DW_TAG_typedef] = "typedef",
3591 	  [DW_TAG_union_type] = "union_type",
3592 	  [DW_TAG_unspecified_parameters] = "unspecified_parameters",
3593 	  [DW_TAG_variant] = "variant",
3594 	  [DW_TAG_common_block] = "common_block",
3595 	  [DW_TAG_common_inclusion] = "common_inclusion",
3596 	  [DW_TAG_inheritance] = "inheritance",
3597 	  [DW_TAG_inlined_subroutine] = "inlined_subroutine",
3598 	  [DW_TAG_module] = "module",
3599 	  [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
3600 	  [DW_TAG_set_type] = "set_type",
3601 	  [DW_TAG_subrange_type] = "subrange_type",
3602 	  [DW_TAG_with_stmt] = "with_stmt",
3603 	  [DW_TAG_access_declaration] = "access_declaration",
3604 	  [DW_TAG_base_type] = "base_type",
3605 	  [DW_TAG_catch_block] = "catch_block",
3606 	  [DW_TAG_const_type] = "const_type",
3607 	  [DW_TAG_constant] = "constant",
3608 	  [DW_TAG_enumerator] = "enumerator",
3609 	  [DW_TAG_file_type] = "file_type",
3610 	  [DW_TAG_friend] = "friend",
3611 	  [DW_TAG_namelist] = "namelist",
3612 	  [DW_TAG_namelist_item] = "namelist_item",
3613 	  [DW_TAG_packed_type] = "packed_type",
3614 	  [DW_TAG_subprogram] = "subprogram",
3615 	  [DW_TAG_template_type_param] = "template_type_param",
3616 	  [DW_TAG_template_value_param] = "template_value_param",
3617 	  [DW_TAG_thrown_type] = "thrown_type",
3618 	  [DW_TAG_try_block] = "try_block",
3619 	  [DW_TAG_variant_part] = "variant_part",
3620 	  [DW_TAG_variable] = "variable",
3621 	  [DW_TAG_volatile_type] = "volatile_type"
3622 	};
3623 
3624       const char *tagstr;
3625       switch (tag)
3626 	{
3627 	case DW_TAG_lo_user:
3628 	  tagstr = "lo_user";
3629 	  break;
3630 
3631 	case DW_TAG_MIPS_loop:
3632 	  tagstr = "MIPS_loop";
3633 	  break;
3634 
3635 	case DW_TAG_format_label:
3636 	  tagstr = "format_label";
3637 	  break;
3638 
3639 	case DW_TAG_function_template:
3640 	  tagstr = "function_template";
3641 	  break;
3642 
3643 	case DW_TAG_class_template:
3644 	  tagstr = "class_template";
3645 	  break;
3646 	case DW_TAG_hi_user:
3647 	  tagstr = "hi_user";
3648 	  break;
3649 
3650 	default:
3651 	  if (tag < sizeof (lowtags) / sizeof (lowtags[0]))
3652 	    tagstr = lowtags[tag];
3653 	  else
3654 	    tagstr = "???";
3655 	  break;
3656 	}
3657 
3658       printf (" [%6" PRIx64 "]  %*s%s\n",
3659 	      (uint64_t) offset, (int) (level * 2), "", tagstr);
3660 
3661       /* Print the attribute values.  */
3662       args.level = level;
3663       (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
3664 
3665       /* Make room for the next level's DIE.  */
3666       if (level + 1 == maxdies)
3667 	dies = (Dwarf_Die *) xrealloc (dies,
3668 				       (maxdies += 10)
3669 				       * sizeof (Dwarf_Die));
3670 
3671       int res = dwarf_child (&dies[level], &dies[level + 1]);
3672       if (res > 0)
3673 	{
3674 	  while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
3675 	    if (level-- == 0)
3676 	      break;
3677 
3678 	  if (res == -1)
3679 	    {
3680 	      error (0, 0, gettext ("cannot get next DIE: %s\n"),
3681 		     dwarf_errmsg (-1));
3682 	      goto do_return;
3683 	    }
3684 	}
3685       else if (unlikely (res < 0))
3686 	{
3687 	  error (0, 0, gettext ("cannot get next DIE: %s"),
3688 		 dwarf_errmsg (-1));
3689 	  goto do_return;
3690 	}
3691       else
3692 	++level;
3693     }
3694   while (level >= 0);
3695 
3696   offset = nextcu;
3697   if (offset != 0)
3698      goto next_cu;
3699 
3700  do_return:
3701   free (dies);
3702 }
3703 
3704 
3705 static void
print_debug_line_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)3706 print_debug_line_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
3707 			  GElf_Shdr *shdr, Dwarf *dbg)
3708 {
3709   printf (gettext ("\
3710 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
3711 	  ".debug_line", (uint64_t) shdr->sh_offset);
3712 
3713   if (shdr->sh_size == 0)
3714     return;
3715 
3716   /* There is no functionality in libdw to read the information in the
3717      way it is represented here.  Hardcode the decoder.  */
3718   Elf_Data *data = elf_getdata (scn, NULL);
3719   if (data == NULL || data->d_buf == NULL)
3720     {
3721       error (0, 0, gettext ("cannot get line data section data: %s"),
3722 	     elf_errmsg (-1));
3723       return;
3724     }
3725 
3726   const unsigned char *linep = (const unsigned char *) data->d_buf;
3727   const unsigned char *lineendp;
3728 
3729   while (linep
3730 	 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
3731     {
3732       size_t start_offset = linep - (const unsigned char *) data->d_buf;
3733 
3734       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
3735       unsigned int length = 4;
3736       if (unlikely (unit_length == 0xffffffff))
3737 	{
3738 	  if (unlikely (linep + 8 > lineendp))
3739 	    {
3740 	    invalid_data:
3741 	      error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
3742 		     elf_ndxscn (scn), ".debug_line");
3743 	      return;
3744 	    }
3745 	  unit_length = read_8ubyte_unaligned_inc (dbg, linep);
3746 	  length = 8;
3747 	}
3748 
3749       /* Check whether we have enough room in the section.  */
3750       if (unit_length < 2 + length + 5 * 1
3751 	  || unlikely (linep + unit_length > lineendp))
3752 	goto invalid_data;
3753       lineendp = linep + unit_length;
3754 
3755       /* The next element of the header is the version identifier.  */
3756       uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
3757 
3758       /* Next comes the header length.  */
3759       Dwarf_Word header_length;
3760       if (length == 4)
3761 	header_length = read_4ubyte_unaligned_inc (dbg, linep);
3762       else
3763 	header_length = read_8ubyte_unaligned_inc (dbg, linep);
3764       //const unsigned char *header_start = linep;
3765 
3766       /* Next the minimum instruction length.  */
3767       uint_fast8_t minimum_instr_len = *linep++;
3768 
3769         /* Then the flag determining the default value of the is_stmt
3770 	   register.  */
3771       uint_fast8_t default_is_stmt = *linep++;
3772 
3773       /* Now the line base.  */
3774       int_fast8_t line_base = *((const int_fast8_t *) linep);
3775       ++linep;
3776 
3777       /* And the line range.  */
3778       uint_fast8_t line_range = *linep++;
3779 
3780       /* The opcode base.  */
3781       uint_fast8_t opcode_base = *linep++;
3782 
3783       /* Print what we got so far.  */
3784       printf (gettext ("\n"
3785 		       " Length:                     %" PRIu64 "\n"
3786 		       " DWARF version:              %" PRIuFAST16 "\n"
3787 		       " Prologue length:            %" PRIu64 "\n"
3788 		       " Minimum instruction length: %" PRIuFAST8 "\n"
3789 		       " Initial value if '%s': %" PRIuFAST8 "\n"
3790 		       " Line base:                  %" PRIdFAST8 "\n"
3791 		       " Line range:                 %" PRIuFAST8 "\n"
3792 		       " Opcode base:                %" PRIuFAST8 "\n"
3793 		       "\n"
3794 		       "Opcodes:\n"),
3795 	      (uint64_t) unit_length, version, (uint64_t) header_length,
3796 	      minimum_instr_len, "is_stmt", default_is_stmt, line_base,
3797 	      line_range, opcode_base);
3798 
3799       if (unlikely (linep + opcode_base - 1 >= lineendp))
3800 	goto invalid_data;
3801       int opcode_base_l10 = 1;
3802       unsigned int tmp = opcode_base;
3803       while (tmp > 10)
3804 	{
3805 	  tmp /= 10;
3806 	  ++opcode_base_l10;
3807 	}
3808       const uint8_t *standard_opcode_lengths = linep - 1;
3809       for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
3810 	printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
3811 			  "  [%*" PRIuFAST8 "]  %hhu arguments\n",
3812 			  (int) linep[cnt - 1]),
3813 		opcode_base_l10, cnt, linep[cnt - 1]);
3814       linep += opcode_base - 1;
3815       if (unlikely (linep >= lineendp))
3816 	goto invalid_data;
3817 
3818       puts (gettext ("\nDirectory table:"));
3819       while (*linep != 0)
3820 	{
3821 	  unsigned char *endp = memchr (linep, '\0', lineendp - linep);
3822 	  if (endp == NULL)
3823 	    goto invalid_data;
3824 
3825 	  printf (" %s\n", (char *) linep);
3826 
3827 	  linep = endp + 1;
3828 	}
3829       /* Skip the final NUL byte.  */
3830       ++linep;
3831 
3832       if (unlikely (linep >= lineendp))
3833 	goto invalid_data;
3834       puts (gettext ("\nFile name table:\n"
3835 		     " Entry Dir   Time      Size      Name"));
3836       for (unsigned int cnt = 1; *linep != 0; ++cnt)
3837 	{
3838 	  /* First comes the file name.  */
3839 	  char *fname = (char *) linep;
3840 	  unsigned char *endp = memchr (fname, '\0', lineendp - linep);
3841 	  if (endp == NULL)
3842 	    goto invalid_data;
3843 	  linep = endp + 1;
3844 
3845 	  /* Then the index.  */
3846 	  unsigned int diridx;
3847 	  get_uleb128 (diridx, linep);
3848 
3849 	  /* Next comes the modification time.  */
3850 	  unsigned int mtime;
3851 	  get_uleb128 (mtime, linep);
3852 
3853 	  /* Finally the length of the file.  */
3854 	  unsigned int fsize;
3855 	  get_uleb128 (fsize, linep);
3856 
3857 	  printf (" %-5u %-5u %-9u %-9u %s\n",
3858 		  cnt, diridx, mtime, fsize, fname);
3859 	}
3860       /* Skip the final NUL byte.  */
3861       ++linep;
3862 
3863       puts (gettext ("\nLine number statements:"));
3864       Dwarf_Word address = 0;
3865       size_t line = 1;
3866       uint_fast8_t is_stmt = default_is_stmt;
3867 
3868       /* Default address value, in case we do not find the CU.  */
3869       size_t address_size
3870 	= elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
3871 
3872       /* Determine the CU this block is for.  */
3873       Dwarf_Off cuoffset;
3874       Dwarf_Off ncuoffset = 0;
3875       size_t hsize;
3876       while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
3877 			   NULL, NULL, NULL) == 0)
3878 	{
3879 	  Dwarf_Die cudie;
3880 	  if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
3881 	    continue;
3882 	  Dwarf_Attribute stmt_list;
3883 	  if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
3884 	    continue;
3885 	  Dwarf_Word lineoff;
3886 	  if (dwarf_formudata (&stmt_list, &lineoff) != 0)
3887 	    continue;
3888 	  if (lineoff == start_offset)
3889 	    {
3890 	      /* Found the CU.  */
3891 	      address_size = cudie.cu->address_size;
3892 	      break;
3893 	    }
3894 	}
3895 
3896       while (linep < lineendp)
3897 	{
3898 	  unsigned int u128;
3899 	  int s128;
3900 
3901 	  /* Read the opcode.  */
3902 	  unsigned int opcode = *linep++;
3903 
3904 	  /* Is this a special opcode?  */
3905 	  if (likely (opcode >= opcode_base))
3906 	    {
3907 	      /* Yes.  Handling this is quite easy since the opcode value
3908 		 is computed with
3909 
3910 		 opcode = (desired line increment - line_base)
3911 		           + (line_range * address advance) + opcode_base
3912 	      */
3913 	      int line_increment = (line_base
3914 				    + (opcode - opcode_base) % line_range);
3915 	      unsigned int address_increment = (minimum_instr_len
3916 						* ((opcode - opcode_base)
3917 						   / line_range));
3918 
3919 	      /* Perform the increments.  */
3920 	      line += line_increment;
3921 	      address += address_increment;
3922 
3923 	      printf (gettext ("\
3924  special opcode %u: address+%u = %#" PRIx64 ", line%+d = %zu\n"),
3925 		      opcode, address_increment, (uint64_t) address,
3926 		      line_increment, line);
3927 	    }
3928 	  else if (opcode == 0)
3929 	    {
3930 	      /* This an extended opcode.  */
3931 	      if (unlikely (linep + 2 > lineendp))
3932 		goto invalid_data;
3933 
3934 	      /* The length.  */
3935 	      unsigned int len = *linep++;
3936 
3937 	      if (unlikely (linep + len > lineendp))
3938 		goto invalid_data;
3939 
3940 	      /* The sub-opcode.  */
3941 	      opcode = *linep++;
3942 
3943 	      printf (gettext (" extended opcode %u: "), opcode);
3944 
3945 	      switch (opcode)
3946 		{
3947 		case DW_LNE_end_sequence:
3948 		  puts (gettext ("end of sequence"));
3949 
3950 		  /* Reset the registers we care about.  */
3951 		  address = 0;
3952 		  line = 1;
3953 		  is_stmt = default_is_stmt;
3954 		  break;
3955 
3956 		case DW_LNE_set_address:
3957 		  if (address_size == 4)
3958 		    address = read_4ubyte_unaligned_inc (dbg, linep);
3959 		  else
3960 		    address = read_8ubyte_unaligned_inc (dbg, linep);
3961 		  printf (gettext ("set address to %#" PRIx64 "\n"),
3962 			  (uint64_t) address);
3963 		  break;
3964 
3965 		case DW_LNE_define_file:
3966 		  {
3967 		    char *fname = (char *) linep;
3968 		    unsigned char *endp = memchr (linep, '\0',
3969 						  lineendp - linep);
3970 		    if (endp == NULL)
3971 		      goto invalid_data;
3972 		    linep = endp + 1;
3973 
3974 		    unsigned int diridx;
3975 		    get_uleb128 (diridx, linep);
3976 		    Dwarf_Word mtime;
3977 		    get_uleb128 (mtime, linep);
3978 		    Dwarf_Word filelength;
3979 		    get_uleb128 (filelength, linep);
3980 
3981 		    printf (gettext ("\
3982 define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
3983 			    diridx, (uint64_t) mtime, (uint64_t) filelength,
3984 			    fname);
3985 		  }
3986 		  break;
3987 
3988 		default:
3989 		  /* Unknown, ignore it.  */
3990 		  puts (gettext ("unknown opcode"));
3991 		  linep += len - 1;
3992 		  break;
3993 		}
3994 	    }
3995 	  else if (opcode <= DW_LNS_set_epilog_begin)
3996 	    {
3997 	      /* This is a known standard opcode.  */
3998 	      switch (opcode)
3999 		{
4000 		case DW_LNS_copy:
4001 		  /* Takes no argument.  */
4002 		  puts (gettext (" copy"));
4003 		  break;
4004 
4005 		case DW_LNS_advance_pc:
4006 		  /* Takes one uleb128 parameter which is added to the
4007 		     address.  */
4008 		  get_uleb128 (u128, linep);
4009 		  address += minimum_instr_len * u128;
4010 		  printf (gettext ("\
4011  advance address by %u to %#" PRIx64 "\n"),
4012 			  u128, (uint64_t) address);
4013 		  break;
4014 
4015 		case DW_LNS_advance_line:
4016 		  /* Takes one sleb128 parameter which is added to the
4017 		     line.  */
4018 		  get_sleb128 (s128, linep);
4019 		  line += s128;
4020 		  printf (gettext ("\
4021  advance line by constant %d to %" PRId64 "\n"),
4022 			  s128, (int64_t) line);
4023 		  break;
4024 
4025 		case DW_LNS_set_file:
4026 		  /* Takes one uleb128 parameter which is stored in file.  */
4027 		  get_uleb128 (u128, linep);
4028 		  printf (gettext (" set file to %" PRIu64 "\n"),
4029 			  (uint64_t) u128);
4030 		  break;
4031 
4032 		case DW_LNS_set_column:
4033 		  /* Takes one uleb128 parameter which is stored in column.  */
4034 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
4035 		    goto invalid_data;
4036 
4037 		  get_uleb128 (u128, linep);
4038 		  printf (gettext (" set column to %" PRIu64 "\n"),
4039 			  (uint64_t) u128);
4040 		  break;
4041 
4042 		case DW_LNS_negate_stmt:
4043 		  /* Takes no argument.  */
4044 		  is_stmt = 1 - is_stmt;
4045 		  printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
4046 			  "is_stmt", is_stmt);
4047 		  break;
4048 
4049 		case DW_LNS_set_basic_block:
4050 		  /* Takes no argument.  */
4051 		  puts (gettext (" set basic block flag"));
4052 		  break;
4053 
4054 		case DW_LNS_const_add_pc:
4055 		  /* Takes no argument.  */
4056 		  u128 = (minimum_instr_len
4057 			  * ((255 - opcode_base) / line_range));
4058 		  address += u128;
4059 		  printf (gettext ("\
4060  advance address by constant %u to %#" PRIx64 "\n"),
4061 			  u128, (uint64_t) address);
4062 		  break;
4063 
4064 		case DW_LNS_fixed_advance_pc:
4065 		  /* Takes one 16 bit parameter which is added to the
4066 		     address.  */
4067 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
4068 		    goto invalid_data;
4069 
4070 		  u128 = read_2ubyte_unaligned_inc (dbg, linep);
4071 		  address += u128;
4072 		  printf (gettext ("\
4073  advance address by fixed value %u to %#" PRIx64 "\n"),
4074 			  u128, (uint64_t) address);
4075 		  break;
4076 
4077 		case DW_LNS_set_prologue_end:
4078 		  /* Takes no argument.  */
4079 		  puts (gettext (" set prologue end flag"));
4080 		  break;
4081 
4082 		case DW_LNS_set_epilog_begin:
4083 		  /* Takes no argument.  */
4084 		  puts (gettext (" set epilogue begin flag"));
4085 		  break;
4086 		}
4087 	    }
4088 	  else
4089 	    {
4090 	      /* This is a new opcode the generator but not we know about.
4091 		 Read the parameters associated with it but then discard
4092 		 everything.  Read all the parameters for this opcode.  */
4093 	      printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
4094 				" unknown opcode with %" PRIu8 " parameters:",
4095 				standard_opcode_lengths[opcode]),
4096 		      standard_opcode_lengths[opcode]);
4097 	      for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
4098 		{
4099 		  get_uleb128 (u128, linep);
4100 		  if (n != standard_opcode_lengths[opcode])
4101 		    putc_unlocked (',', stdout);
4102 		  printf (" %u", u128);
4103 		}
4104 
4105 	      /* Next round, ignore this opcode.  */
4106 	      continue;
4107 	    }
4108 	}
4109     }
4110 
4111   /* There must only be one data block.  */
4112   assert (elf_getdata (scn, data) == NULL);
4113 }
4114 
4115 
4116 static void
print_debug_loc_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)4117 print_debug_loc_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4118 			 GElf_Shdr *shdr, Dwarf *dbg)
4119 {
4120   printf (gettext ("\
4121 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
4122 	  ".debug_loc", (uint64_t) shdr->sh_offset);
4123 
4124   // XXX add something
4125 }
4126 
4127 
4128 struct mac_culist
4129 {
4130   Dwarf_Die die;
4131   Dwarf_Off offset;
4132   Dwarf_Files *files;
4133   struct mac_culist *next;
4134 };
4135 
4136 
4137 static int
mac_compare(const void * p1,const void * p2)4138 mac_compare (const void *p1, const void *p2)
4139 {
4140   struct mac_culist *m1 = (struct mac_culist *) p1;
4141   struct mac_culist *m2 = (struct mac_culist *) p2;
4142 
4143   if (m1->offset < m2->offset)
4144     return -1;
4145   if (m1->offset > m2->offset)
4146     return 1;
4147   return 0;
4148 }
4149 
4150 
4151 static void
print_debug_macinfo_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)4152 print_debug_macinfo_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4153 			 GElf_Shdr *shdr, Dwarf *dbg)
4154 {
4155   printf (gettext ("\
4156 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
4157 	  ".debug_macinfo", (uint64_t) shdr->sh_offset);
4158   putc_unlocked ('\n', stdout);
4159 
4160   /* There is no function in libdw to iterate over the raw content of
4161      the section but it is easy enough to do.  */
4162   Elf_Data *data = elf_getdata (scn, NULL);
4163   if (data == NULL || data->d_buf == NULL)
4164     {
4165       error (0, 0, gettext ("cannot get macro information section data: %s"),
4166 	     elf_errmsg (-1));
4167       return;
4168     }
4169 
4170   /* Get the source file information for all CUs.  */
4171   Dwarf_Off offset;
4172   Dwarf_Off ncu = 0;
4173   size_t hsize;
4174   struct mac_culist *culist = NULL;
4175   size_t nculist = 0;
4176   while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
4177     {
4178       Dwarf_Die cudie;
4179       if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
4180 	continue;
4181 
4182       Dwarf_Attribute attr;
4183       if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
4184 	continue;
4185 
4186       Dwarf_Word macoff;
4187       if (dwarf_formudata (&attr, &macoff) != 0)
4188 	continue;
4189 
4190       struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
4191       newp->die = cudie;
4192       newp->offset = macoff;
4193       newp->files = NULL;
4194       newp->next = culist;
4195       culist = newp;
4196       ++nculist;
4197     }
4198 
4199   /* Convert the list into an array for easier consumption.  */
4200   struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
4201 							 * sizeof (*cus));
4202   /* Add sentinel.  */
4203   cus[nculist].offset = data->d_size;
4204   if (nculist > 0)
4205     {
4206       for (size_t cnt = nculist - 1; culist != NULL; --cnt)
4207 	{
4208 	  assert (cnt < nculist);
4209 	  cus[cnt] = *culist;
4210 	  culist = culist->next;
4211 	}
4212 
4213       /* Sort the array according to the offset in the .debug_macinfo
4214 	 section.  Note we keep the sentinel at the end.  */
4215       qsort (cus, nculist, sizeof (*cus), mac_compare);
4216     }
4217 
4218   const unsigned char *readp = (const unsigned char *) data->d_buf;
4219   const unsigned char *readendp = readp + data->d_size;
4220   int level = 1;
4221 
4222   while (readp < readendp)
4223     {
4224       unsigned int opcode = *readp++;
4225       unsigned int u128;
4226       unsigned int u128_2;
4227       const unsigned char *endp;
4228 
4229       switch (opcode)
4230 	{
4231 	case DW_MACINFO_define:
4232 	case DW_MACINFO_undef:
4233 	case DW_MACINFO_vendor_ext:
4234 	  /*  For the first two opcodes the parameters are
4235 	        line, string
4236 	      For the latter
4237 	        number, string.
4238 	      We can treat these cases together.  */
4239 	  get_uleb128 (u128, readp);
4240 
4241 	  endp = memchr (readp, '\0', readendp - readp);
4242 	  if (endp == NULL)
4243 	    {
4244 	      printf (gettext ("\
4245 %*s*** non-terminated string at end of section"),
4246 		      level, "");
4247 	      return;
4248 	    }
4249 
4250 	  if (opcode == DW_MACINFO_define)
4251 	    printf ("%*s#define %s, line %u\n",
4252 		    level, "", (char *) readp, u128);
4253 	  else if (opcode == DW_MACINFO_undef)
4254 	    printf ("%*s#undef %s, line %u\n",
4255 		    level, "", (char *) readp, u128);
4256 	  else
4257 	    printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
4258 
4259 	  readp = endp + 1;
4260 	  break;
4261 
4262 	case DW_MACINFO_start_file:
4263 	  /* The two parameters are line and file index, in this order.  */
4264 	  get_uleb128 (u128, readp);
4265 	  get_uleb128 (u128_2, readp);
4266 
4267 	  /* Find the CU DIE for this file.  */
4268 	  ptrdiff_t macoff = readp - (const unsigned char *) data->d_buf;
4269 	  const char *fname = "???";
4270 	  if (macoff >= cus[0].offset)
4271 	    {
4272 	      while (macoff >= cus[1].offset)
4273 		++cus;
4274 
4275 	      if (cus[0].files == NULL
4276 		&& dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
4277 		cus[0].files = (Dwarf_Files *) -1l;
4278 
4279 	      if (cus[0].files != (Dwarf_Files *) -1l)
4280 		fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
4281 			 ?: "???");
4282 	    }
4283 
4284 	  printf ("%*sstart_file %u, [%u] %s\n",
4285 		  level, "", u128, u128_2, fname);
4286 	  ++level;
4287 	  break;
4288 
4289 	case DW_MACINFO_end_file:
4290 	  --level;
4291 	  printf ("%*send_file\n", level, "");
4292 	  /* Nothing more to do.  */
4293 	  break;
4294 
4295 	default:
4296 	  // XXX gcc seems to generate files with a trailing zero.
4297 	  if (opcode != 0 || readp != readendp)
4298 	    printf ("%*s*** invalid opcode %u\n", level, "", opcode);
4299 	  break;
4300 	}
4301     }
4302 }
4303 
4304 
4305 /* Callback for printing global names.  */
4306 static int
print_pubnames(Dwarf * dbg,Dwarf_Global * global,void * arg)4307 print_pubnames (Dwarf *dbg, Dwarf_Global *global, void *arg)
4308 {
4309   int *np = (int *) arg;
4310 
4311   printf (gettext (" [%5d] DIE offset: %6" PRId64
4312 		   ", CU DIE offset: %6" PRId64 ", name: %s\n"),
4313 	  (*np)++, global->die_offset, global->cu_offset, global->name);
4314 
4315   return 0;
4316 }
4317 
4318 
4319 /* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
4320 static void
print_debug_pubnames_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)4321 print_debug_pubnames_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4322 			      GElf_Shdr *shdr, Dwarf *dbg)
4323 {
4324   printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
4325 	  ".debug_pubnames", (uint64_t) shdr->sh_offset);
4326 
4327   int n = 0;
4328   (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
4329 }
4330 
4331 /* Print the content of the DWARF string section '.debug_str'.  */
4332 static void
print_debug_str_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)4333 print_debug_str_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4334 			 GElf_Shdr *shdr, Dwarf *dbg)
4335 {
4336   /* Compute floor(log16(shdr->sh_size)).  */
4337   GElf_Addr tmp = shdr->sh_size;
4338   int digits = 1;
4339   while (tmp >= 16)
4340     {
4341       ++digits;
4342       tmp >>= 4;
4343     }
4344   digits = MAX (4, digits);
4345 
4346   printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
4347 		   " %*s  String\n"),
4348 	  ".debug_str", (uint64_t) shdr->sh_offset,
4349 	  /* TRANS: the debugstr| prefix makes the string unique.  */
4350 	  digits + 2, sgettext ("debugstr|Offset"));
4351 
4352   Dwarf_Off offset = 0;
4353   while (offset < shdr->sh_size)
4354     {
4355       size_t len;
4356       const char *str = dwarf_getstring (dbg, offset, &len);
4357       if (str == NULL)
4358 	{
4359 	  printf (gettext (" *** error while reading strings: %s\n"),
4360 		  dwarf_errmsg (-1));
4361 	  break;
4362 	}
4363 
4364       printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
4365 
4366       offset += len + 1;
4367     }
4368 }
4369 
4370 
4371 static void
print_debug(Ebl * ebl,GElf_Ehdr * ehdr)4372 print_debug (Ebl *ebl, GElf_Ehdr *ehdr)
4373 {
4374   /* Find the version information sections.  For this we have to
4375      search through the section table.  */
4376   Dwarf *dbg;
4377   Elf_Scn *scn;
4378   size_t shstrndx;
4379 
4380   /* Before we start the real work get a debug context descriptor.  */
4381   dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
4382   if (dbg == NULL)
4383     {
4384       error (0, 0, gettext ("cannot get debug context descriptor: %s"),
4385 	     dwarf_errmsg (-1));
4386       return;
4387     }
4388 
4389   /* Get the section header string table index.  */
4390   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
4391     error (EXIT_FAILURE, 0,
4392 	   gettext ("cannot get section header string table index"));
4393 
4394   scn = NULL;
4395   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
4396     {
4397       /* Handle the section if it is part of the versioning handling.  */
4398       GElf_Shdr shdr_mem;
4399       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
4400 
4401       if (shdr != NULL || shdr->sh_type != SHT_PROGBITS)
4402 	{
4403 	  static const struct
4404 	  {
4405 	    const char *name;
4406 	    enum section_e bitmask;
4407 	    void (*fp) (Ebl *, GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
4408 	  } debug_sections[] =
4409 	    {
4410 #define NEW_SECTION(name) \
4411 	      { ".debug_" #name, section_##name, print_debug_##name##_section }
4412 	      NEW_SECTION (abbrev),
4413 	      NEW_SECTION (aranges),
4414 	      NEW_SECTION (frame),
4415 	      NEW_SECTION (info),
4416 	      NEW_SECTION (line),
4417 	      NEW_SECTION (loc),
4418 	      NEW_SECTION (pubnames),
4419 	      NEW_SECTION (str),
4420 	      NEW_SECTION (macinfo),
4421 	      { ".eh_frame", section_frame, print_debug_frame_section }
4422 	    };
4423 	  const int ndebug_sections = (sizeof (debug_sections)
4424 				       / sizeof (debug_sections[0]));
4425 	  const char *name = elf_strptr (ebl->elf, shstrndx,
4426 					 shdr->sh_name);
4427 	  int n;
4428 
4429 	  for (n = 0; n < ndebug_sections; ++n)
4430 	    if (strcmp (name, debug_sections[n].name) == 0)
4431 	      {
4432 		if (print_debug_sections & debug_sections[n].bitmask)
4433 		  debug_sections[n].fp (ebl, ehdr, scn, shdr, dbg);
4434 		break;
4435 	      }
4436 	}
4437     }
4438 
4439   /* We are done with the DWARF handling.  */
4440   dwarf_end (dbg);
4441 }
4442 
4443 
4444 static void
handle_notes(Ebl * ebl,GElf_Ehdr * ehdr)4445 handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
4446 {
4447   int class = gelf_getclass (ebl->elf);
4448   size_t cnt;
4449 
4450   /* We have to look through the program header to find the note
4451      sections.  There can be more than one.  */
4452   for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
4453     {
4454       GElf_Phdr mem;
4455       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
4456 
4457       if (phdr == NULL || phdr->p_type != PT_NOTE)
4458 	/* Not what we are looking for.  */
4459 	continue;
4460 
4461       printf (gettext ("\
4462 \nNote segment of %" PRId64 " bytes at offset %#0" PRIx64 ":\n"),
4463 	      phdr->p_filesz, phdr->p_offset);
4464 
4465       char *notemem = gelf_rawchunk (ebl->elf, phdr->p_offset, phdr->p_filesz);
4466       if (notemem == NULL)
4467 	error (EXIT_FAILURE, 0,
4468 	       gettext ("cannot get content of note section: %s"),
4469 	       elf_errmsg (-1));
4470 
4471       fputs_unlocked (gettext ("  Owner          Data size  Type\n"), stdout);
4472 
4473 
4474       /* Handle the note section content.  It consists of one or more
4475 	 entries each of which consists of five parts:
4476 
4477 	 - a 32-bit name length
4478 	 - a 32-bit descriptor length
4479 	 - a 32-bit type field
4480 	 - the NUL-terminated name, length as specified in the first field
4481 	 - the descriptor, length as specified in the second field
4482 
4483 	 The variable sized fields are padded to 32- or 64-bits
4484 	 depending on whether the file is a 32- or 64-bit ELF file.
4485       */
4486       size_t align = class == ELFCLASS32 ? 4 : 8;
4487 #define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1))
4488 
4489       size_t idx = 0;
4490       while (idx < phdr->p_filesz)
4491 	{
4492 	  /* XXX Handle 64-bit note section entries correctly.  */
4493 	  struct
4494 	  {
4495 	    uint32_t namesz;
4496 	    uint32_t descsz;
4497 	    uint32_t type;
4498 	    char name[0];
4499 	  } *noteentry = (__typeof (noteentry)) (notemem + idx);
4500 
4501 	  if (idx + 12 > phdr->p_filesz
4502 	      || (idx + 12 + ALIGNED_LEN (noteentry->namesz)
4503 		  + ALIGNED_LEN (noteentry->descsz) > phdr->p_filesz))
4504 	    /* This entry isn't completely contained in the note
4505 	       section.  Ignore it.  */
4506 	    break;
4507 
4508 	  char buf[100];
4509 	  char buf2[100];
4510 	  printf (gettext ("  %-13.*s  %9" PRId32 "  %s\n"),
4511 		  (int) noteentry->namesz, noteentry->name,
4512 		  noteentry->descsz,
4513 		  ehdr->e_type == ET_CORE
4514 		  ? ebl_core_note_type_name (ebl, noteentry->type,
4515 					     buf, sizeof (buf))
4516 		  : ebl_object_note_type_name (ebl, noteentry->type,
4517 					       buf2, sizeof (buf2)));
4518 
4519 	  /* Filter out invalid entries.  */
4520 	  if (memchr (noteentry->name, '\0', noteentry->namesz) != NULL
4521 	      /* XXX For now help broken Linux kernels.  */
4522 	      || 1)
4523 	    {
4524 	      if (ehdr->e_type == ET_CORE)
4525 		ebl_core_note (ebl, noteentry->name, noteentry->type,
4526 			       noteentry->descsz,
4527 			       &noteentry->name[ALIGNED_LEN (noteentry->namesz)]);
4528 	      else
4529 		ebl_object_note (ebl, noteentry->name, noteentry->type,
4530 				 noteentry->descsz,
4531 				 &noteentry->name[ALIGNED_LEN (noteentry->namesz)]);
4532 	    }
4533 
4534 	  /* Move to the next entry.  */
4535 	  idx += (12 + ALIGNED_LEN (noteentry->namesz)
4536 		  + ALIGNED_LEN (noteentry->descsz));
4537 	}
4538 
4539       gelf_freechunk (ebl->elf, notemem);
4540     }
4541 }
4542