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