1 /* Print information from ELF file in human-readable form.
2 Copyright (C) 1999-2012 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 1999.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 elfutils is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
43 #include <sys/param.h>
47 #include "../libelf/libelfP.h"
48 #include "../libelf/common.h"
49 #include "../libebl/libeblP.h"
50 #include "../libdw/libdwP.h"
51 #include "../libdwfl/libdwflP.h"
52 #include "../libdw/memory-access.h"
54 #include "../libdw/known-dwarf.h"
57 /* Name and version of program. */
58 static void print_version (FILE *stream, struct argp_state *state);
59 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
61 /* Bug report address. */
62 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
64 /* Definitions of arguments for argp functions. */
65 static const struct argp_option options[] =
67 { NULL, 0, NULL, 0, N_("ELF output selection:"), 0 },
68 { "all", 'a', NULL, 0,
69 N_("All these plus -p .strtab -p .dynstr -p .comment"), 0 },
70 { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
71 { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
72 { "histogram", 'I', NULL, 0,
73 N_("Display histogram of bucket list lengths"), 0 },
74 { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
75 { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
76 { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
77 { "section-headers", 'S', NULL, 0, N_("Display the sections' headers"), 0 },
78 { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
79 { "symbols", 's', NULL, 0, N_("Display the symbol table"), 0 },
80 { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
81 { "notes", 'n', NULL, 0, N_("Display the ELF notes"), 0 },
82 { "arch-specific", 'A', NULL, 0,
83 N_("Display architecture specific information, if any"), 0 },
84 { "exception", 'e', NULL, 0,
85 N_("Display sections for exception handling"), 0 },
87 { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 },
88 { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
89 N_("Display DWARF section content. SECTION can be one of abbrev, "
90 "aranges, frame, gdb_index, info, loc, line, ranges, pubnames, str, "
91 "macinfo, macro or exception"), 0 },
92 { "hex-dump", 'x', "SECTION", 0,
93 N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
94 { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
95 N_("Print string contents of sections"), 0 },
96 { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
97 { "archive-index", 'c', NULL, 0,
98 N_("Display the symbol index of an archive"), 0 },
100 { NULL, 0, NULL, 0, N_("Output control:"), 0 },
101 { "numeric-addresses", 'N', NULL, 0,
102 N_("Do not find symbol names for addresses in DWARF data"), 0 },
103 { "wide", 'W', NULL, 0,
104 N_("Ignored for compatibility (lines always wide)"), 0 },
105 { NULL, 0, NULL, 0, NULL, 0 }
108 /* Short description of program. */
109 static const char doc[] = N_("\
110 Print information from ELF file in human-readable form.");
112 /* Strings for arguments in help texts. */
113 static const char args_doc[] = N_("FILE...");
115 /* Prototype for option handler. */
116 static error_t parse_opt (int key, char *arg, struct argp_state *state);
118 /* Data structure to communicate with argp functions. */
119 static struct argp argp =
121 options, parse_opt, args_doc, doc, NULL, NULL, NULL
125 /* Flags set by the option controlling the output. */
127 /* True if dynamic segment should be printed. */
128 static bool print_dynamic_table;
130 /* True if the file header should be printed. */
131 static bool print_file_header;
133 /* True if the program headers should be printed. */
134 static bool print_program_header;
136 /* True if relocations should be printed. */
137 static bool print_relocations;
139 /* True if the section headers should be printed. */
140 static bool print_section_header;
142 /* True if the symbol table should be printed. */
143 static bool print_symbol_table;
145 /* True if the version information should be printed. */
146 static bool print_version_info;
148 /* True if section groups should be printed. */
149 static bool print_section_groups;
151 /* True if bucket list length histogram should be printed. */
152 static bool print_histogram;
154 /* True if the architecture specific data should be printed. */
155 static bool print_arch;
157 /* True if note section content should be printed. */
158 static bool print_notes;
160 /* True if SHF_STRINGS section content should be printed. */
161 static bool print_string_sections;
163 /* True if archive index should be printed. */
164 static bool print_archive_index;
166 /* True if any of the control options except print_archive_index is set. */
167 static bool any_control_option;
169 /* True if we should print addresses from DWARF in symbolic form. */
170 static bool print_address_names = true;
172 /* Select printing of debugging sections. */
173 static enum section_e
175 section_abbrev = 1, /* .debug_abbrev */
176 section_aranges = 2, /* .debug_aranges */
177 section_frame = 4, /* .debug_frame or .eh_frame & al. */
178 section_info = 8, /* .debug_info, .debug_types */
179 section_types = section_info,
180 section_line = 16, /* .debug_line */
181 section_loc = 32, /* .debug_loc */
182 section_pubnames = 64, /* .debug_pubnames */
183 section_str = 128, /* .debug_str */
184 section_macinfo = 256, /* .debug_macinfo */
185 section_ranges = 512, /* .debug_ranges */
186 section_exception = 1024, /* .eh_frame & al. */
187 section_gdb_index = 2048, /* .gdb_index */
188 section_macro = 4096, /* .debug_macro */
189 section_all = (section_abbrev | section_aranges | section_frame
190 | section_info | section_line | section_loc
191 | section_pubnames | section_str | section_macinfo
192 | section_ranges | section_exception | section_gdb_index
194 } print_debug_sections, implicit_debug_sections;
196 /* Select hex dumping of sections. */
197 static struct section_argument *dump_data_sections;
198 static struct section_argument **dump_data_sections_tail = &dump_data_sections;
200 /* Select string dumping of sections. */
201 static struct section_argument *string_sections;
202 static struct section_argument **string_sections_tail = &string_sections;
204 struct section_argument
206 struct section_argument *next;
211 /* Numbers of sections and program headers in the file. */
216 /* Declarations of local functions. */
217 static void process_file (int fd, const char *fname, bool only_one);
218 static void process_elf_file (Dwfl_Module *dwflmod, int fd);
219 static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
220 static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
221 static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
222 static void print_scngrp (Ebl *ebl);
223 static void print_dynamic (Ebl *ebl);
224 static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
225 static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
227 static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
229 static void print_symtab (Ebl *ebl, int type);
230 static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
231 static void print_verinfo (Ebl *ebl);
232 static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
233 static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
234 static void handle_versym (Ebl *ebl, Elf_Scn *scn,
236 static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
237 static void handle_hash (Ebl *ebl);
238 static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
239 static void print_liblist (Ebl *ebl);
240 static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
241 static void dump_data (Ebl *ebl);
242 static void dump_strings (Ebl *ebl);
243 static void print_strings (Ebl *ebl);
244 static void dump_archive_index (Elf *, const char *);
248 main (int argc, char *argv[])
251 setlocale (LC_ALL, "");
253 /* Initialize the message catalog. */
254 textdomain (PACKAGE_TARNAME);
256 /* Parse and process arguments. */
258 argp_parse (&argp, argc, argv, 0, &remaining, NULL);
260 /* Before we start tell the ELF library which version we are using. */
261 elf_version (EV_CURRENT);
263 /* Now process all the files given at the command line. */
264 bool only_one = remaining + 1 == argc;
268 int fd = open (argv[remaining], O_RDONLY);
271 error (0, errno, gettext ("cannot open input file"));
275 process_file (fd, argv[remaining], only_one);
279 while (++remaining < argc);
281 return error_message_count != 0;
285 /* Handle program arguments. */
287 parse_opt (int key, char *arg,
288 struct argp_state *state __attribute__ ((unused)))
290 void add_dump_section (const char *name, bool implicit)
292 struct section_argument *a = xmalloc (sizeof *a);
295 a->implicit = implicit;
296 struct section_argument ***tailp
297 = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
305 print_file_header = true;
306 print_program_header = true;
307 print_relocations = true;
308 print_section_header = true;
309 print_symbol_table = true;
310 print_version_info = true;
311 print_dynamic_table = true;
312 print_section_groups = true;
313 print_histogram = true;
316 implicit_debug_sections |= section_exception;
317 add_dump_section (".strtab", true);
318 add_dump_section (".dynstr", true);
319 add_dump_section (".comment", true);
320 any_control_option = true;
324 any_control_option = true;
327 print_dynamic_table = true;
328 any_control_option = true;
331 print_debug_sections |= section_exception;
332 any_control_option = true;
335 print_section_groups = true;
336 any_control_option = true;
339 print_file_header = true;
340 any_control_option = true;
343 print_histogram = true;
344 any_control_option = true;
347 print_program_header = true;
348 any_control_option = true;
352 any_control_option = true;
355 print_relocations = true;
356 any_control_option = true;
359 print_section_header = true;
360 any_control_option = true;
363 print_symbol_table = true;
364 any_control_option = true;
367 print_version_info = true;
368 any_control_option = true;
371 print_archive_index = true;
375 print_debug_sections = section_all;
376 else if (strcmp (arg, "abbrev") == 0)
377 print_debug_sections |= section_abbrev;
378 else if (strcmp (arg, "aranges") == 0)
379 print_debug_sections |= section_aranges;
380 else if (strcmp (arg, "ranges") == 0)
382 print_debug_sections |= section_ranges;
383 implicit_debug_sections |= section_info;
385 else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
386 print_debug_sections |= section_frame;
387 else if (strcmp (arg, "info") == 0)
388 print_debug_sections |= section_info;
389 else if (strcmp (arg, "loc") == 0)
391 print_debug_sections |= section_loc;
392 implicit_debug_sections |= section_info;
394 else if (strcmp (arg, "line") == 0)
395 print_debug_sections |= section_line;
396 else if (strcmp (arg, "pubnames") == 0)
397 print_debug_sections |= section_pubnames;
398 else if (strcmp (arg, "str") == 0)
399 print_debug_sections |= section_str;
400 else if (strcmp (arg, "macinfo") == 0)
401 print_debug_sections |= section_macinfo;
402 else if (strcmp (arg, "macro") == 0)
403 print_debug_sections |= section_macro;
404 else if (strcmp (arg, "exception") == 0)
405 print_debug_sections |= section_exception;
406 else if (strcmp (arg, "gdb_index") == 0)
407 print_debug_sections |= section_gdb_index;
410 fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
412 argp_help (&argp, stderr, ARGP_HELP_SEE,
413 program_invocation_short_name);
416 any_control_option = true;
419 any_control_option = true;
422 print_string_sections = true;
427 add_dump_section (arg, false);
428 any_control_option = true;
431 print_address_names = false;
433 case ARGP_KEY_NO_ARGS:
434 fputs (gettext ("Missing file name.\n"), stderr);
437 if (! any_control_option && ! print_archive_index)
439 fputs (gettext ("No operation specified.\n"), stderr);
441 argp_help (&argp, stderr, ARGP_HELP_SEE,
442 program_invocation_short_name);
446 case 'W': /* Ignored. */
449 return ARGP_ERR_UNKNOWN;
455 /* Print the version information. */
457 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
459 fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
460 fprintf (stream, gettext ("\
461 Copyright (C) %s Red Hat, Inc.\n\
462 This is free software; see the source for copying conditions. There is NO\n\
463 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
465 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
469 /* Check if the file is an archive, and if so dump its index. */
471 check_archive_index (int fd, const char *fname, bool only_one)
473 /* Create an `Elf' descriptor. */
474 Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
476 error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
480 if (elf_kind (elf) == ELF_K_AR)
483 printf ("\n%s:\n\n", fname);
484 dump_archive_index (elf, fname);
488 gettext ("'%s' is not an archive, cannot print archive index"),
491 /* Now we can close the descriptor. */
492 if (elf_end (elf) != 0)
493 error (0, 0, gettext ("error while closing Elf descriptor: %s"),
498 /* Trivial callback used for checking if we opened an archive. */
500 count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
501 void **userdata __attribute__ ((unused)),
502 const char *name __attribute__ ((unused)),
503 Dwarf_Addr base __attribute__ ((unused)),
507 return DWARF_CB_ABORT;
508 *(bool *) arg = true;
512 struct process_dwflmod_args
519 process_dwflmod (Dwfl_Module *dwflmod,
520 void **userdata __attribute__ ((unused)),
521 const char *name __attribute__ ((unused)),
522 Dwarf_Addr base __attribute__ ((unused)),
525 const struct process_dwflmod_args *a = arg;
527 /* Print the file name. */
531 dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
533 printf ("\n%s:\n\n", fname);
536 process_elf_file (dwflmod, a->fd);
541 /* Stub libdwfl callback, only the ELF handle already open is ever used. */
543 find_no_debuginfo (Dwfl_Module *mod __attribute__ ((unused)),
544 void **userdata __attribute__ ((unused)),
545 const char *modname __attribute__ ((unused)),
546 Dwarf_Addr base __attribute__ ((unused)),
547 const char *file_name __attribute__ ((unused)),
548 const char *debuglink_file __attribute__ ((unused)),
549 GElf_Word debuglink_crc __attribute__ ((unused)),
550 char **debuginfo_file_name __attribute__ ((unused)))
555 /* Process one input file. */
557 process_file (int fd, const char *fname, bool only_one)
559 if (print_archive_index)
560 check_archive_index (fd, fname, only_one);
562 if (!any_control_option)
565 /* Duplicate an fd for dwfl_report_offline to swallow. */
566 int dwfl_fd = dup (fd);
567 if (unlikely (dwfl_fd < 0))
568 error (EXIT_FAILURE, errno, "dup");
570 /* Use libdwfl in a trivial way to open the libdw handle for us.
571 This takes care of applying relocations to DWARF data in ET_REL files. */
572 static const Dwfl_Callbacks callbacks =
574 .section_address = dwfl_offline_section_address,
575 .find_debuginfo = find_no_debuginfo
577 Dwfl *dwfl = dwfl_begin (&callbacks);
578 if (likely (dwfl != NULL))
579 /* Let 0 be the logical address of the file (or first in archive). */
580 dwfl->offline_next_address = 0;
581 if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
584 if (fstat64 (dwfl_fd, &st) != 0)
585 error (0, errno, gettext ("cannot stat input file"));
586 else if (unlikely (st.st_size == 0))
587 error (0, 0, gettext ("input file is empty"));
589 error (0, 0, gettext ("failed reading '%s': %s"),
590 fname, dwfl_errmsg (-1));
591 close (dwfl_fd); /* Consumed on success, not on failure. */
595 dwfl_report_end (dwfl, NULL, NULL);
599 /* Clear ONLY_ONE if we have multiple modules, from an archive. */
601 only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
604 /* Process the one or more modules gleaned from this file. */
605 struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
606 dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
612 /* Process one ELF file. */
614 process_elf_file (Dwfl_Module *dwflmod, int fd)
617 Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
620 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
625 error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
629 Ebl *ebl = ebl_openbackend (elf);
630 if (unlikely (ebl == NULL))
633 error (0, errno, gettext ("cannot create EBL handle"));
637 /* Determine the number of sections. */
638 if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
639 error (EXIT_FAILURE, 0,
640 gettext ("cannot determine number of sections: %s"),
643 /* Determine the number of phdrs. */
644 if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
645 error (EXIT_FAILURE, 0,
646 gettext ("cannot determine number of program headers: %s"),
649 /* For an ET_REL file, libdwfl has adjusted the in-core shdrs
650 and may have applied relocation to some sections.
651 So we need to get a fresh Elf handle on the file to display those. */
652 bool print_unrelocated = (print_section_header
654 || dump_data_sections != NULL
657 Elf *pure_elf = NULL;
659 if (ehdr->e_type == ET_REL && print_unrelocated)
661 /* Read the file afresh. */
662 off64_t aroff = elf_getaroff (elf);
663 pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
666 /* Archive member. */
667 (void) elf_rand (pure_elf, aroff);
668 Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
672 if (pure_elf == NULL)
674 pure_ebl = ebl_openbackend (pure_elf);
675 if (pure_ebl == NULL)
679 if (print_file_header)
680 print_ehdr (ebl, ehdr);
681 if (print_section_header)
682 print_shdr (pure_ebl, ehdr);
683 if (print_program_header)
684 print_phdr (ebl, ehdr);
685 if (print_section_groups)
687 if (print_dynamic_table)
689 if (print_relocations)
690 print_relocs (pure_ebl, ehdr);
693 if (print_symbol_table)
694 print_symtab (ebl, SHT_DYNSYM);
695 if (print_version_info)
697 if (print_symbol_table)
698 print_symtab (ebl, SHT_SYMTAB);
702 print_attributes (ebl, ehdr);
703 if (dump_data_sections != NULL)
704 dump_data (pure_ebl);
705 if (string_sections != NULL)
707 if ((print_debug_sections | implicit_debug_sections) != 0)
708 print_debug (dwflmod, ebl, ehdr);
710 handle_notes (pure_ebl, ehdr);
711 if (print_string_sections)
714 ebl_closebackend (ebl);
718 ebl_closebackend (pure_ebl);
724 /* Print file type. */
726 print_file_type (unsigned short int e_type)
728 if (likely (e_type <= ET_CORE))
730 static const char *const knowntypes[] =
733 N_("REL (Relocatable file)"),
734 N_("EXEC (Executable file)"),
735 N_("DYN (Shared object file)"),
736 N_("CORE (Core file)")
738 puts (gettext (knowntypes[e_type]));
740 else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
741 printf (gettext ("OS Specific: (%x)\n"), e_type);
742 else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
743 printf (gettext ("Processor Specific: (%x)\n"), e_type);
749 /* Print ELF header. */
751 print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
753 fputs_unlocked (gettext ("ELF Header:\n Magic: "), stdout);
754 for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
755 printf (" %02hhx", ehdr->e_ident[cnt]);
757 printf (gettext ("\n Class: %s\n"),
758 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
759 : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
762 printf (gettext (" Data: %s\n"),
763 ehdr->e_ident[EI_DATA] == ELFDATA2LSB
764 ? "2's complement, little endian"
765 : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
766 ? "2's complement, big endian" : "\?\?\?");
768 printf (gettext (" Ident Version: %hhd %s\n"),
769 ehdr->e_ident[EI_VERSION],
770 ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
774 printf (gettext (" OS/ABI: %s\n"),
775 ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
777 printf (gettext (" ABI Version: %hhd\n"),
778 ehdr->e_ident[EI_ABIVERSION]);
780 fputs_unlocked (gettext (" Type: "), stdout);
781 print_file_type (ehdr->e_type);
783 printf (gettext (" Machine: %s\n"), ebl->name);
785 printf (gettext (" Version: %d %s\n"),
787 ehdr->e_version == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
789 printf (gettext (" Entry point address: %#" PRIx64 "\n"),
792 printf (gettext (" Start of program headers: %" PRId64 " %s\n"),
793 ehdr->e_phoff, gettext ("(bytes into file)"));
795 printf (gettext (" Start of section headers: %" PRId64 " %s\n"),
796 ehdr->e_shoff, gettext ("(bytes into file)"));
798 printf (gettext (" Flags: %s\n"),
799 ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
801 printf (gettext (" Size of this header: %" PRId16 " %s\n"),
802 ehdr->e_ehsize, gettext ("(bytes)"));
804 printf (gettext (" Size of program header entries: %" PRId16 " %s\n"),
805 ehdr->e_phentsize, gettext ("(bytes)"));
807 printf (gettext (" Number of program headers entries: %" PRId16),
809 if (ehdr->e_phnum == PN_XNUM)
812 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
814 printf (gettext (" (%" PRIu32 " in [0].sh_info)"),
815 (uint32_t) shdr->sh_info);
817 fputs_unlocked (gettext (" ([0] not available)"), stdout);
819 fputc_unlocked ('\n', stdout);
821 printf (gettext (" Size of section header entries: %" PRId16 " %s\n"),
822 ehdr->e_shentsize, gettext ("(bytes)"));
824 printf (gettext (" Number of section headers entries: %" PRId16),
826 if (ehdr->e_shnum == 0)
829 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
831 printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
832 (uint32_t) shdr->sh_size);
834 fputs_unlocked (gettext (" ([0] not available)"), stdout);
836 fputc_unlocked ('\n', stdout);
838 if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
841 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
843 /* We managed to get the zeroth section. */
844 snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
845 (uint32_t) shdr->sh_link);
848 strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
849 buf[sizeof (buf) - 1] = '\0';
852 printf (gettext (" Section header string table index: XINDEX%s\n\n"),
856 printf (gettext (" Section header string table index: %" PRId16 "\n\n"),
862 get_visibility_type (int value)
880 /* Print the section headers. */
882 print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
887 if (! print_file_header)
889 There are %d section headers, starting at offset %#" PRIx64 ":\n\
891 ehdr->e_shnum, ehdr->e_shoff);
893 /* Get the section header string table index. */
894 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
895 error (EXIT_FAILURE, 0,
896 gettext ("cannot get section header string table index"));
898 puts (gettext ("Section Headers:"));
900 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
901 puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
903 puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
905 for (cnt = 0; cnt < shnum; ++cnt)
907 Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
909 if (unlikely (scn == NULL))
910 error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
913 /* Get the section header. */
915 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
916 if (unlikely (shdr == NULL))
917 error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
922 if (shdr->sh_flags & SHF_WRITE)
924 if (shdr->sh_flags & SHF_ALLOC)
926 if (shdr->sh_flags & SHF_EXECINSTR)
928 if (shdr->sh_flags & SHF_MERGE)
930 if (shdr->sh_flags & SHF_STRINGS)
932 if (shdr->sh_flags & SHF_INFO_LINK)
934 if (shdr->sh_flags & SHF_LINK_ORDER)
936 if (shdr->sh_flags & SHF_OS_NONCONFORMING)
938 if (shdr->sh_flags & SHF_GROUP)
940 if (shdr->sh_flags & SHF_TLS)
942 if (shdr->sh_flags & SHF_ORDERED)
944 if (shdr->sh_flags & SHF_EXCLUDE)
949 printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
950 " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
953 elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
955 ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
956 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
957 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
958 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
959 shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
963 fputc_unlocked ('\n', stdout);
967 /* Print the program header. */
969 print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
971 if (ehdr->e_phnum == 0)
972 /* No program header, this is OK in relocatable objects. */
975 puts (gettext ("Program Headers:"));
976 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
978 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
981 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
983 /* Process all program headers. */
984 bool has_relro = false;
985 GElf_Addr relro_from = 0;
986 GElf_Addr relro_to = 0;
987 for (size_t cnt = 0; cnt < phnum; ++cnt)
991 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
993 /* If for some reason the header cannot be returned show this. */
994 if (unlikely (phdr == NULL))
1000 printf (" %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
1001 " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
1002 ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
1004 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
1005 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
1008 phdr->p_flags & PF_R ? 'R' : ' ',
1009 phdr->p_flags & PF_W ? 'W' : ' ',
1010 phdr->p_flags & PF_X ? 'E' : ' ',
1013 if (phdr->p_type == PT_INTERP)
1015 /* We can show the user the name of the interpreter. */
1017 char *filedata = elf_rawfile (ebl->elf, &maxsize);
1019 if (filedata != NULL && phdr->p_offset < maxsize)
1020 printf (gettext ("\t[Requesting program interpreter: %s]\n"),
1021 filedata + phdr->p_offset);
1023 else if (phdr->p_type == PT_GNU_RELRO)
1026 relro_from = phdr->p_vaddr;
1027 relro_to = relro_from + phdr->p_memsz;
1031 if (ehdr->e_shnum == 0)
1032 /* No sections in the file. Punt. */
1035 /* Get the section header string table index. */
1037 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1038 error (EXIT_FAILURE, 0,
1039 gettext ("cannot get section header string table index"));
1041 puts (gettext ("\n Section to Segment mapping:\n Segment Sections..."));
1043 for (size_t cnt = 0; cnt < phnum; ++cnt)
1045 /* Print the segment number. */
1046 printf (" %2.2zu ", cnt);
1049 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
1050 /* This must not happen. */
1051 if (unlikely (phdr == NULL))
1052 error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
1055 /* Iterate over the sections. */
1056 bool in_relro = false;
1058 for (size_t inner = 1; inner < shnum; ++inner)
1060 Elf_Scn *scn = elf_getscn (ebl->elf, inner);
1061 /* This should not happen. */
1062 if (unlikely (scn == NULL))
1063 error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
1066 /* Get the section header. */
1068 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1069 if (unlikely (shdr == NULL))
1070 error (EXIT_FAILURE, 0,
1071 gettext ("cannot get section header: %s"),
1074 if (shdr->sh_size > 0
1075 /* Compare allocated sections by VMA, unallocated
1076 sections by file offset. */
1077 && (shdr->sh_flags & SHF_ALLOC
1078 ? (shdr->sh_addr >= phdr->p_vaddr
1079 && (shdr->sh_addr + shdr->sh_size
1080 <= phdr->p_vaddr + phdr->p_memsz))
1081 : (shdr->sh_offset >= phdr->p_offset
1082 && (shdr->sh_offset + shdr->sh_size
1083 <= phdr->p_offset + phdr->p_filesz))))
1085 if (has_relro && !in_relro
1086 && shdr->sh_addr >= relro_from
1087 && shdr->sh_addr + shdr->sh_size <= relro_to)
1089 fputs_unlocked (" [RELRO:", stdout);
1092 else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
1094 fputs_unlocked ("]", stdout);
1097 else if (has_relro && in_relro
1098 && shdr->sh_addr + shdr->sh_size > relro_to)
1099 fputs_unlocked ("] <RELRO:", stdout);
1100 else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
1104 fputs_unlocked (" [RO:", stdout);
1110 /* Determine the segment this section is part of. */
1112 GElf_Phdr *phdr2 = NULL;
1113 for (cnt2 = 0; cnt2 < phnum; ++cnt2)
1115 GElf_Phdr phdr2_mem;
1116 phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
1118 if (phdr2 != NULL && phdr2->p_type == PT_LOAD
1119 && shdr->sh_addr >= phdr2->p_vaddr
1120 && (shdr->sh_addr + shdr->sh_size
1121 <= phdr2->p_vaddr + phdr2->p_memsz))
1127 if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
1129 fputs_unlocked (" [RO:", stdout);
1132 else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
1134 fputs_unlocked ("]", stdout);
1141 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1143 /* Signal that this sectin is only partially covered. */
1144 if (has_relro && in_relro
1145 && shdr->sh_addr + shdr->sh_size > relro_to)
1147 fputs_unlocked (">", stdout);
1152 if (in_relro || in_ro)
1153 fputs_unlocked ("]", stdout);
1155 /* Finish the line. */
1156 fputc_unlocked ('\n', stdout);
1162 section_name (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr)
1164 return elf_strptr (ebl->elf, ehdr->e_shstrndx, shdr->sh_name) ?: "???";
1169 handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1171 /* Get the data of the section. */
1172 Elf_Data *data = elf_getdata (scn, NULL);
1174 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1175 GElf_Shdr symshdr_mem;
1176 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1177 Elf_Data *symdata = elf_getdata (symscn, NULL);
1179 if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
1183 /* Get the section header string table index. */
1185 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1186 error (EXIT_FAILURE, 0,
1187 gettext ("cannot get section header string table index"));
1189 Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
1192 printf ((grpref[0] & GRP_COMDAT)
1194 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
1196 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1197 data->d_size / sizeof (Elf32_Word) - 1)
1199 \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
1200 \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1201 data->d_size / sizeof (Elf32_Word) - 1),
1203 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1204 elf_strptr (ebl->elf, symshdr->sh_link,
1205 gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name)
1206 ?: gettext ("<INVALID SYMBOL>"),
1207 data->d_size / sizeof (Elf32_Word) - 1);
1209 for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1211 GElf_Shdr grpshdr_mem;
1212 GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
1216 printf (" [%2u] %s\n",
1219 && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
1220 ? str : gettext ("<INVALID SECTION>"));
1226 print_scngrp (Ebl *ebl)
1228 /* Find all relocation sections and handle them. */
1229 Elf_Scn *scn = NULL;
1231 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1233 /* Handle the section if it is a symbol table. */
1235 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1237 if (shdr != NULL && shdr->sh_type == SHT_GROUP)
1238 handle_scngrp (ebl, scn, shdr);
1243 static const struct flags
1249 { DF_ORIGIN, "ORIGIN" },
1250 { DF_SYMBOLIC, "SYMBOLIC" },
1251 { DF_TEXTREL, "TEXTREL" },
1252 { DF_BIND_NOW, "BIND_NOW" },
1253 { DF_STATIC_TLS, "STATIC_TLS" }
1255 static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
1257 static const struct flags dt_flags_1[] =
1259 { DF_1_NOW, "NOW" },
1260 { DF_1_GLOBAL, "GLOBAL" },
1261 { DF_1_GROUP, "GROUP" },
1262 { DF_1_NODELETE, "NODELETE" },
1263 { DF_1_LOADFLTR, "LOADFLTR" },
1264 { DF_1_INITFIRST, "INITFIRST" },
1265 { DF_1_NOOPEN, "NOOPEN" },
1266 { DF_1_ORIGIN, "ORIGIN" },
1267 { DF_1_DIRECT, "DIRECT" },
1268 { DF_1_TRANS, "TRANS" },
1269 { DF_1_INTERPOSE, "INTERPOSE" },
1270 { DF_1_NODEFLIB, "NODEFLIB" },
1271 { DF_1_NODUMP, "NODUMP" },
1272 { DF_1_CONFALT, "CONFALT" },
1273 { DF_1_ENDFILTEE, "ENDFILTEE" },
1274 { DF_1_DISPRELDNE, "DISPRELDNE" },
1275 { DF_1_DISPRELPND, "DISPRELPND" },
1277 static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
1279 static const struct flags dt_feature_1[] =
1281 { DTF_1_PARINIT, "PARINIT" },
1282 { DTF_1_CONFEXP, "CONFEXP" }
1284 static const int ndt_feature_1 = (sizeof (dt_feature_1)
1285 / sizeof (dt_feature_1[0]));
1287 static const struct flags dt_posflag_1[] =
1289 { DF_P1_LAZYLOAD, "LAZYLOAD" },
1290 { DF_P1_GROUPPERM, "GROUPPERM" }
1292 static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
1293 / sizeof (dt_posflag_1[0]));
1297 print_flags (int class, GElf_Xword d_val, const struct flags *flags,
1303 for (cnt = 0; cnt < nflags; ++cnt)
1304 if (d_val & flags[cnt].mask)
1307 putchar_unlocked (' ');
1308 fputs_unlocked (flags[cnt].str, stdout);
1309 d_val &= ~flags[cnt].mask;
1316 putchar_unlocked (' ');
1317 printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
1320 putchar_unlocked ('\n');
1325 print_dt_flags (int class, GElf_Xword d_val)
1327 print_flags (class, d_val, dt_flags, ndt_flags);
1332 print_dt_flags_1 (int class, GElf_Xword d_val)
1334 print_flags (class, d_val, dt_flags_1, ndt_flags_1);
1339 print_dt_feature_1 (int class, GElf_Xword d_val)
1341 print_flags (class, d_val, dt_feature_1, ndt_feature_1);
1346 print_dt_posflag_1 (int class, GElf_Xword d_val)
1348 print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
1353 handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1355 int class = gelf_getclass (ebl->elf);
1361 /* Get the data of the section. */
1362 data = elf_getdata (scn, NULL);
1366 /* Get the section header string table index. */
1367 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1368 error (EXIT_FAILURE, 0,
1369 gettext ("cannot get section header string table index"));
1371 printf (ngettext ("\
1372 \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1374 \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1375 shdr->sh_size / shdr->sh_entsize),
1376 (unsigned long int) (shdr->sh_size / shdr->sh_entsize),
1377 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
1379 (int) shdr->sh_link,
1380 elf_strptr (ebl->elf, shstrndx,
1381 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1383 fputs_unlocked (gettext (" Type Value\n"), stdout);
1385 for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1388 GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
1394 ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
1402 /* No further output. */
1403 fputc_unlocked ('\n', stdout);
1407 printf (gettext ("Shared library: [%s]\n"),
1408 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1412 printf (gettext ("Library soname: [%s]\n"),
1413 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1417 printf (gettext ("Library rpath: [%s]\n"),
1418 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1422 printf (gettext ("Library runpath: [%s]\n"),
1423 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1436 case DT_INIT_ARRAYSZ:
1437 case DT_FINI_ARRAYSZ:
1440 case DT_GNU_CONFLICTSZ:
1441 case DT_GNU_LIBLISTSZ:
1442 printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
1449 printf ("%" PRId64 "\n", dyn->d_un.d_val);
1453 const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
1455 puts (tagname ?: "???");
1459 print_dt_flags (class, dyn->d_un.d_val);
1463 print_dt_flags_1 (class, dyn->d_un.d_val);
1467 print_dt_feature_1 (class, dyn->d_un.d_val);
1471 print_dt_posflag_1 (class, dyn->d_un.d_val);
1475 printf ("%#0*" PRIx64 "\n",
1476 class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
1483 /* Print the dynamic segment. */
1485 print_dynamic (Ebl *ebl)
1487 for (size_t i = 0; i < phnum; ++i)
1490 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
1492 if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
1494 Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
1496 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1497 if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
1498 handle_dynamic (ebl, scn, shdr);
1505 /* Print relocations. */
1507 print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
1509 /* Find all relocation sections and handle them. */
1510 Elf_Scn *scn = NULL;
1512 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1514 /* Handle the section if it is a symbol table. */
1516 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1518 if (likely (shdr != NULL))
1520 if (shdr->sh_type == SHT_REL)
1521 handle_relocs_rel (ebl, ehdr, scn, shdr);
1522 else if (shdr->sh_type == SHT_RELA)
1523 handle_relocs_rela (ebl, ehdr, scn, shdr);
1529 /* Handle a relocation section. */
1531 handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1533 int class = gelf_getclass (ebl->elf);
1534 int nentries = shdr->sh_size / shdr->sh_entsize;
1536 /* Get the data of the section. */
1537 Elf_Data *data = elf_getdata (scn, NULL);
1541 /* Get the symbol table information. */
1542 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1543 GElf_Shdr symshdr_mem;
1544 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1545 Elf_Data *symdata = elf_getdata (symscn, NULL);
1547 /* Get the section header of the section the relocations are for. */
1548 GElf_Shdr destshdr_mem;
1549 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1552 if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
1554 printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1559 /* Search for the optional extended section index table. */
1560 Elf_Data *xndxdata = NULL;
1561 int xndxscnidx = elf_scnshndx (scn);
1562 if (unlikely (xndxscnidx > 0))
1563 xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
1565 /* Get the section header string table index. */
1567 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1568 error (EXIT_FAILURE, 0,
1569 gettext ("cannot get section header string table index"));
1571 if (shdr->sh_info != 0)
1572 printf (ngettext ("\
1573 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1575 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1578 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1579 (unsigned int) shdr->sh_info,
1580 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1584 /* The .rel.dyn section does not refer to a specific section but
1585 instead of section index zero. Do not try to print a section
1587 printf (ngettext ("\
1588 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1590 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1592 (unsigned int) elf_ndxscn (scn),
1593 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1596 fputs_unlocked (class == ELFCLASS32
1598 Offset Type Value Name\n")
1600 Offset Type Value Name\n"),
1603 int is_statically_linked = 0;
1604 for (int cnt = 0; cnt < nentries; ++cnt)
1607 GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
1608 if (likely (rel != NULL))
1613 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1614 GELF_R_SYM (rel->r_info),
1616 if (unlikely (sym == NULL))
1618 /* As a special case we have to handle relocations in static
1619 executables. This only happens for IRELATIVE relocations
1620 (so far). There is no symbol table. */
1621 if (is_statically_linked == 0)
1623 /* Find the program header and look for a PT_INTERP entry. */
1624 is_statically_linked = -1;
1625 if (ehdr->e_type == ET_EXEC)
1627 is_statically_linked = 1;
1629 for (size_t inner = 0; inner < phnum; ++inner)
1632 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
1634 if (phdr != NULL && phdr->p_type == PT_INTERP)
1636 is_statically_linked = -1;
1643 if (is_statically_linked > 0 && shdr->sh_link == 0)
1645 %#0*" PRIx64 " %-20s %*s %s\n",
1646 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1647 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1648 /* Avoid the leading R_ which isn't carrying any
1650 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1651 buf, sizeof (buf)) + 2
1652 : gettext ("<INVALID RELOC>"),
1653 class == ELFCLASS32 ? 10 : 18, "",
1654 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1656 printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
1657 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1658 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1659 /* Avoid the leading R_ which isn't carrying any
1661 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1662 buf, sizeof (buf)) + 2
1663 : gettext ("<INVALID RELOC>"),
1664 gettext ("INVALID SYMBOL"),
1665 (long int) GELF_R_SYM (rel->r_info));
1667 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1668 printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
1669 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1670 likely (ebl_reloc_type_check (ebl,
1671 GELF_R_TYPE (rel->r_info)))
1672 /* Avoid the leading R_ which isn't carrying any
1674 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1675 buf, sizeof (buf)) + 2
1676 : gettext ("<INVALID RELOC>"),
1677 class == ELFCLASS32 ? 10 : 18, sym->st_value,
1678 elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1681 destshdr = gelf_getshdr (elf_getscn (ebl->elf,
1682 sym->st_shndx == SHN_XINDEX
1683 ? xndx : sym->st_shndx),
1686 if (unlikely (destshdr == NULL))
1687 printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
1688 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1689 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1690 /* Avoid the leading R_ which isn't carrying any
1692 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1693 buf, sizeof (buf)) + 2
1694 : gettext ("<INVALID RELOC>"),
1695 gettext ("INVALID SECTION"),
1696 (long int) (sym->st_shndx == SHN_XINDEX
1697 ? xndx : sym->st_shndx));
1699 printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
1700 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1701 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1702 /* Avoid the leading R_ which isn't carrying any
1704 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1705 buf, sizeof (buf)) + 2
1706 : gettext ("<INVALID RELOC>"),
1707 class == ELFCLASS32 ? 10 : 18, sym->st_value,
1708 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1715 /* Handle a relocation section. */
1717 handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1719 int class = gelf_getclass (ebl->elf);
1720 int nentries = shdr->sh_size / shdr->sh_entsize;
1722 /* Get the data of the section. */
1723 Elf_Data *data = elf_getdata (scn, NULL);
1727 /* Get the symbol table information. */
1728 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1729 GElf_Shdr symshdr_mem;
1730 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1731 Elf_Data *symdata = elf_getdata (symscn, NULL);
1733 /* Get the section header of the section the relocations are for. */
1734 GElf_Shdr destshdr_mem;
1735 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1738 if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
1740 printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1745 /* Search for the optional extended section index table. */
1746 Elf_Data *xndxdata = NULL;
1747 int xndxscnidx = elf_scnshndx (scn);
1748 if (unlikely (xndxscnidx > 0))
1749 xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
1751 /* Get the section header string table index. */
1753 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1754 error (EXIT_FAILURE, 0,
1755 gettext ("cannot get section header string table index"));
1757 printf (ngettext ("\
1758 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1760 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1763 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1764 (unsigned int) shdr->sh_info,
1765 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1768 fputs_unlocked (class == ELFCLASS32
1770 Offset Type Value Addend Name\n")
1772 Offset Type Value Addend Name\n"),
1775 int is_statically_linked = 0;
1776 for (int cnt = 0; cnt < nentries; ++cnt)
1779 GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
1780 if (likely (rel != NULL))
1785 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1786 GELF_R_SYM (rel->r_info),
1789 if (unlikely (sym == NULL))
1791 /* As a special case we have to handle relocations in static
1792 executables. This only happens for IRELATIVE relocations
1793 (so far). There is no symbol table. */
1794 if (is_statically_linked == 0)
1796 /* Find the program header and look for a PT_INTERP entry. */
1797 is_statically_linked = -1;
1798 if (ehdr->e_type == ET_EXEC)
1800 is_statically_linked = 1;
1802 for (size_t inner = 0; inner < phnum; ++inner)
1805 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
1807 if (phdr != NULL && phdr->p_type == PT_INTERP)
1809 is_statically_linked = -1;
1816 if (is_statically_linked > 0 && shdr->sh_link == 0)
1818 %#0*" PRIx64 " %-15s %*s %#6" PRIx64 " %s\n",
1819 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1820 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1821 /* Avoid the leading R_ which isn't carrying any
1823 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1824 buf, sizeof (buf)) + 2
1825 : gettext ("<INVALID RELOC>"),
1826 class == ELFCLASS32 ? 10 : 18, "",
1828 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1830 printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
1831 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1832 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1833 /* Avoid the leading R_ which isn't carrying any
1835 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1836 buf, sizeof (buf)) + 2
1837 : gettext ("<INVALID RELOC>"),
1838 gettext ("INVALID SYMBOL"),
1839 (long int) GELF_R_SYM (rel->r_info));
1841 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1843 %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
1844 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1845 likely (ebl_reloc_type_check (ebl,
1846 GELF_R_TYPE (rel->r_info)))
1847 /* Avoid the leading R_ which isn't carrying any
1849 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1850 buf, sizeof (buf)) + 2
1851 : gettext ("<INVALID RELOC>"),
1852 class == ELFCLASS32 ? 10 : 18, sym->st_value,
1854 elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1857 destshdr = gelf_getshdr (elf_getscn (ebl->elf,
1858 sym->st_shndx == SHN_XINDEX
1859 ? xndx : sym->st_shndx),
1862 if (unlikely (shdr == NULL))
1863 printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
1864 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1865 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1866 /* Avoid the leading R_ which isn't carrying any
1868 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1869 buf, sizeof (buf)) + 2
1870 : gettext ("<INVALID RELOC>"),
1871 gettext ("INVALID SECTION"),
1872 (long int) (sym->st_shndx == SHN_XINDEX
1873 ? xndx : sym->st_shndx));
1876 %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
1877 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1878 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1879 /* Avoid the leading R_ which isn't carrying any
1881 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1882 buf, sizeof (buf)) + 2
1883 : gettext ("<INVALID RELOC>"),
1884 class == ELFCLASS32 ? 10 : 18, sym->st_value,
1886 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1893 /* Print the program header. */
1895 print_symtab (Ebl *ebl, int type)
1897 /* Find the symbol table(s). For this we have to search through the
1899 Elf_Scn *scn = NULL;
1901 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1903 /* Handle the section if it is a symbol table. */
1905 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1907 if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
1908 handle_symtab (ebl, scn, shdr);
1914 handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1916 Elf_Data *versym_data = NULL;
1917 Elf_Data *verneed_data = NULL;
1918 Elf_Data *verdef_data = NULL;
1919 Elf_Data *xndx_data = NULL;
1920 int class = gelf_getclass (ebl->elf);
1921 Elf32_Word verneed_stridx = 0;
1922 Elf32_Word verdef_stridx = 0;
1924 /* Get the data of the section. */
1925 Elf_Data *data = elf_getdata (scn, NULL);
1929 /* Find out whether we have other sections we might need. */
1930 Elf_Scn *runscn = NULL;
1931 while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
1933 GElf_Shdr runshdr_mem;
1934 GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
1936 if (likely (runshdr != NULL))
1938 if (runshdr->sh_type == SHT_GNU_versym
1939 && runshdr->sh_link == elf_ndxscn (scn))
1940 /* Bingo, found the version information. Now get the data. */
1941 versym_data = elf_getdata (runscn, NULL);
1942 else if (runshdr->sh_type == SHT_GNU_verneed)
1944 /* This is the information about the needed versions. */
1945 verneed_data = elf_getdata (runscn, NULL);
1946 verneed_stridx = runshdr->sh_link;
1948 else if (runshdr->sh_type == SHT_GNU_verdef)
1950 /* This is the information about the defined versions. */
1951 verdef_data = elf_getdata (runscn, NULL);
1952 verdef_stridx = runshdr->sh_link;
1954 else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
1955 && runshdr->sh_link == elf_ndxscn (scn))
1956 /* Extended section index. */
1957 xndx_data = elf_getdata (runscn, NULL);
1961 /* Get the section header string table index. */
1963 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1964 error (EXIT_FAILURE, 0,
1965 gettext ("cannot get section header string table index"));
1967 /* Now we can compute the number of entries in the section. */
1968 unsigned int nsyms = data->d_size / (class == ELFCLASS32
1969 ? sizeof (Elf32_Sym)
1970 : sizeof (Elf64_Sym));
1972 printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
1973 "\nSymbol table [%2u] '%s' contains %u entries:\n",
1975 (unsigned int) elf_ndxscn (scn),
1976 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
1978 printf (ngettext (" %lu local symbol String table: [%2u] '%s'\n",
1979 " %lu local symbols String table: [%2u] '%s'\n",
1981 (unsigned long int) shdr->sh_info,
1982 (unsigned int) shdr->sh_link,
1983 elf_strptr (ebl->elf, shstrndx,
1984 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1987 fputs_unlocked (class == ELFCLASS32
1989 Num: Value Size Type Bind Vis Ndx Name\n")
1991 Num: Value Size Type Bind Vis Ndx Name\n"),
1994 for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
2001 GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
2003 if (unlikely (sym == NULL))
2006 /* Determine the real section index. */
2007 if (likely (sym->st_shndx != SHN_XINDEX))
2008 xndx = sym->st_shndx;
2011 %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
2013 class == ELFCLASS32 ? 8 : 16,
2016 ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
2017 typebuf, sizeof (typebuf)),
2018 ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
2019 bindbuf, sizeof (bindbuf)),
2020 get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
2021 ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
2022 sizeof (scnbuf), NULL, shnum),
2023 elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
2025 if (versym_data != NULL)
2027 /* Get the version information. */
2028 GElf_Versym versym_mem;
2029 GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
2031 if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
2033 bool is_nobits = false;
2034 bool check_def = xndx != SHN_UNDEF;
2036 if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
2038 GElf_Shdr symshdr_mem;
2039 GElf_Shdr *symshdr =
2040 gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
2042 is_nobits = (symshdr != NULL
2043 && symshdr->sh_type == SHT_NOBITS);
2046 if (is_nobits || ! check_def)
2048 /* We must test both. */
2049 GElf_Vernaux vernaux_mem;
2050 GElf_Vernaux *vernaux = NULL;
2051 size_t vn_offset = 0;
2053 GElf_Verneed verneed_mem;
2054 GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
2056 while (verneed != NULL)
2058 size_t vna_offset = vn_offset;
2060 vernaux = gelf_getvernaux (verneed_data,
2061 vna_offset += verneed->vn_aux,
2063 while (vernaux != NULL
2064 && vernaux->vna_other != *versym
2065 && vernaux->vna_next != 0)
2067 /* Update the offset. */
2068 vna_offset += vernaux->vna_next;
2070 vernaux = (vernaux->vna_next == 0
2072 : gelf_getvernaux (verneed_data,
2077 /* Check whether we found the version. */
2078 if (vernaux != NULL && vernaux->vna_other == *versym)
2082 vn_offset += verneed->vn_next;
2083 verneed = (verneed->vn_next == 0
2085 : gelf_getverneed (verneed_data, vn_offset,
2089 if (vernaux != NULL && vernaux->vna_other == *versym)
2092 elf_strptr (ebl->elf, verneed_stridx,
2094 (unsigned int) vernaux->vna_other);
2097 else if (unlikely (! is_nobits))
2098 error (0, 0, gettext ("bad dynamic symbol"));
2103 if (check_def && *versym != 0x8001)
2105 /* We must test both. */
2106 size_t vd_offset = 0;
2108 GElf_Verdef verdef_mem;
2109 GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
2111 while (verdef != NULL)
2113 if (verdef->vd_ndx == (*versym & 0x7fff))
2114 /* Found the definition. */
2117 vd_offset += verdef->vd_next;
2118 verdef = (verdef->vd_next == 0
2120 : gelf_getverdef (verdef_data, vd_offset,
2126 GElf_Verdaux verdaux_mem;
2127 GElf_Verdaux *verdaux
2128 = gelf_getverdaux (verdef_data,
2129 vd_offset + verdef->vd_aux,
2132 if (verdaux != NULL)
2133 printf ((*versym & 0x8000) ? "@%s" : "@@%s",
2134 elf_strptr (ebl->elf, verdef_stridx,
2135 verdaux->vda_name));
2141 putchar_unlocked ('\n');
2146 /* Print version information. */
2148 print_verinfo (Ebl *ebl)
2150 /* Find the version information sections. For this we have to
2151 search through the section table. */
2152 Elf_Scn *scn = NULL;
2154 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2156 /* Handle the section if it is part of the versioning handling. */
2158 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2160 if (likely (shdr != NULL))
2162 if (shdr->sh_type == SHT_GNU_verneed)
2163 handle_verneed (ebl, scn, shdr);
2164 else if (shdr->sh_type == SHT_GNU_verdef)
2165 handle_verdef (ebl, scn, shdr);
2166 else if (shdr->sh_type == SHT_GNU_versym)
2167 handle_versym (ebl, scn, shdr);
2174 get_ver_flags (unsigned int flags)
2176 static char buf[32];
2180 return gettext ("none");
2182 if (flags & VER_FLG_BASE)
2183 endp = stpcpy (buf, "BASE ");
2187 if (flags & VER_FLG_WEAK)
2190 endp = stpcpy (endp, "| ");
2192 endp = stpcpy (endp, "WEAK ");
2195 if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
2197 strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
2198 buf[sizeof (buf) - 1] = '\0';
2206 handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2208 int class = gelf_getclass (ebl->elf);
2210 /* Get the data of the section. */
2211 Elf_Data *data = elf_getdata (scn, NULL);
2215 /* Get the section header string table index. */
2217 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2218 error (EXIT_FAILURE, 0,
2219 gettext ("cannot get section header string table index"));
2222 printf (ngettext ("\
2223 \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2225 \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2227 (unsigned int) elf_ndxscn (scn),
2228 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
2229 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2231 (unsigned int) shdr->sh_link,
2232 elf_strptr (ebl->elf, shstrndx,
2233 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2236 unsigned int offset = 0;
2237 for (int cnt = shdr->sh_info; --cnt >= 0; )
2239 /* Get the data at the next offset. */
2240 GElf_Verneed needmem;
2241 GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
2242 if (unlikely (need == NULL))
2245 printf (gettext (" %#06x: Version: %hu File: %s Cnt: %hu\n"),
2246 offset, (unsigned short int) need->vn_version,
2247 elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
2248 (unsigned short int) need->vn_cnt);
2250 unsigned int auxoffset = offset + need->vn_aux;
2251 for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2253 GElf_Vernaux auxmem;
2254 GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
2255 if (unlikely (aux == NULL))
2258 printf (gettext (" %#06x: Name: %s Flags: %s Version: %hu\n"),
2260 elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
2261 get_ver_flags (aux->vna_flags),
2262 (unsigned short int) aux->vna_other);
2264 auxoffset += aux->vna_next;
2267 /* Find the next offset. */
2268 offset += need->vn_next;
2274 handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2276 /* Get the data of the section. */
2277 Elf_Data *data = elf_getdata (scn, NULL);
2281 /* Get the section header string table index. */
2283 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2284 error (EXIT_FAILURE, 0,
2285 gettext ("cannot get section header string table index"));
2287 int class = gelf_getclass (ebl->elf);
2289 printf (ngettext ("\
2290 \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2292 \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2294 (unsigned int) elf_ndxscn (scn),
2295 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2297 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2299 (unsigned int) shdr->sh_link,
2300 elf_strptr (ebl->elf, shstrndx,
2301 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2304 unsigned int offset = 0;
2305 for (int cnt = shdr->sh_info; --cnt >= 0; )
2307 /* Get the data at the next offset. */
2309 GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
2310 if (unlikely (def == NULL))
2313 unsigned int auxoffset = offset + def->vd_aux;
2314 GElf_Verdaux auxmem;
2315 GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
2316 if (unlikely (aux == NULL))
2320 %#06x: Version: %hd Flags: %s Index: %hd Cnt: %hd Name: %s\n"),
2321 offset, def->vd_version,
2322 get_ver_flags (def->vd_flags),
2325 elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2327 auxoffset += aux->vda_next;
2328 for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
2330 aux = gelf_getverdaux (data, auxoffset, &auxmem);
2331 if (unlikely (aux == NULL))
2334 printf (gettext (" %#06x: Parent %d: %s\n"),
2336 elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2338 auxoffset += aux->vda_next;
2341 /* Find the next offset. */
2342 offset += def->vd_next;
2348 handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2350 int class = gelf_getclass (ebl->elf);
2351 const char **vername;
2352 const char **filename;
2354 /* Get the data of the section. */
2355 Elf_Data *data = elf_getdata (scn, NULL);
2359 /* Get the section header string table index. */
2361 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2362 error (EXIT_FAILURE, 0,
2363 gettext ("cannot get section header string table index"));
2365 /* We have to find the version definition section and extract the
2367 Elf_Scn *defscn = NULL;
2368 Elf_Scn *needscn = NULL;
2370 Elf_Scn *verscn = NULL;
2371 while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
2373 GElf_Shdr vershdr_mem;
2374 GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
2376 if (likely (vershdr != NULL))
2378 if (vershdr->sh_type == SHT_GNU_verdef)
2380 else if (vershdr->sh_type == SHT_GNU_verneed)
2386 if (defscn != NULL || needscn != NULL)
2388 /* We have a version information (better should have). Now get
2389 the version names. First find the maximum version number. */
2393 /* Run through the version definitions and find the highest
2395 unsigned int offset = 0;
2397 GElf_Shdr defshdrmem;
2400 defdata = elf_getdata (defscn, NULL);
2401 if (unlikely (defdata == NULL))
2404 defshdr = gelf_getshdr (defscn, &defshdrmem);
2405 if (unlikely (defshdr == NULL))
2408 for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
2413 /* Get the data at the next offset. */
2414 def = gelf_getverdef (defdata, offset, &defmem);
2415 if (unlikely (def == NULL))
2418 nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
2420 offset += def->vd_next;
2423 if (needscn != NULL)
2425 unsigned int offset = 0;
2427 GElf_Shdr needshdrmem;
2428 GElf_Shdr *needshdr;
2430 needdata = elf_getdata (needscn, NULL);
2431 if (unlikely (needdata == NULL))
2434 needshdr = gelf_getshdr (needscn, &needshdrmem);
2435 if (unlikely (needshdr == NULL))
2438 for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
2440 GElf_Verneed needmem;
2442 unsigned int auxoffset;
2445 /* Get the data at the next offset. */
2446 need = gelf_getverneed (needdata, offset, &needmem);
2447 if (unlikely (need == NULL))
2450 /* Run through the auxiliary entries. */
2451 auxoffset = offset + need->vn_aux;
2452 for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
2454 GElf_Vernaux auxmem;
2457 aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
2458 if (unlikely (aux == NULL))
2461 nvername = MAX (nvername,
2462 (size_t) (aux->vna_other & 0x7fff));
2464 auxoffset += aux->vna_next;
2467 offset += need->vn_next;
2471 /* This is the number of versions we know about. */
2474 /* Allocate the array. */
2475 vername = (const char **) alloca (nvername * sizeof (const char *));
2476 filename = (const char **) alloca (nvername * sizeof (const char *));
2478 /* Run through the data structures again and collect the strings. */
2481 /* Run through the version definitions and find the highest
2483 unsigned int offset = 0;
2485 GElf_Shdr defshdrmem;
2488 defdata = elf_getdata (defscn, NULL);
2489 if (unlikely (defdata == NULL))
2492 defshdr = gelf_getshdr (defscn, &defshdrmem);
2493 if (unlikely (defshdr == NULL))
2496 for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
2499 /* Get the data at the next offset. */
2501 GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
2502 GElf_Verdaux auxmem;
2503 GElf_Verdaux *aux = gelf_getverdaux (defdata,
2504 offset + def->vd_aux,
2506 if (unlikely (def == NULL || aux == NULL))
2509 vername[def->vd_ndx & 0x7fff]
2510 = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
2511 filename[def->vd_ndx & 0x7fff] = NULL;
2513 offset += def->vd_next;
2516 if (needscn != NULL)
2518 unsigned int offset = 0;
2520 Elf_Data *needdata = elf_getdata (needscn, NULL);
2521 GElf_Shdr needshdrmem;
2522 GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
2523 if (unlikely (needdata == NULL || needshdr == NULL))
2526 for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
2528 /* Get the data at the next offset. */
2529 GElf_Verneed needmem;
2530 GElf_Verneed *need = gelf_getverneed (needdata, offset,
2532 if (unlikely (need == NULL))
2535 /* Run through the auxiliary entries. */
2536 unsigned int auxoffset = offset + need->vn_aux;
2537 for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2539 GElf_Vernaux auxmem;
2540 GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
2542 if (unlikely (aux == NULL))
2545 vername[aux->vna_other & 0x7fff]
2546 = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
2547 filename[aux->vna_other & 0x7fff]
2548 = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
2550 auxoffset += aux->vna_next;
2553 offset += need->vn_next;
2564 /* Print the header. */
2566 printf (ngettext ("\
2567 \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
2569 \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
2570 shdr->sh_size / shdr->sh_entsize),
2571 (unsigned int) elf_ndxscn (scn),
2572 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2573 (int) (shdr->sh_size / shdr->sh_entsize),
2574 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2576 (unsigned int) shdr->sh_link,
2577 elf_strptr (ebl->elf, shstrndx,
2578 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2581 /* Now we can finally look at the actual contents of this section. */
2582 for (unsigned int cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
2585 printf ("\n %4d:", cnt);
2588 GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
2596 fputs_unlocked (gettext (" 0 *local* "),
2601 fputs_unlocked (gettext (" 1 *global* "),
2606 n = printf ("%4d%c%s",
2607 *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
2608 (unsigned int) (*sym & 0x7fff) < nvername
2609 ? vername[*sym & 0x7fff] : "???");
2610 if ((unsigned int) (*sym & 0x7fff) < nvername
2611 && filename[*sym & 0x7fff] != NULL)
2612 n += printf ("(%s)", filename[*sym & 0x7fff]);
2613 printf ("%*s", MAX (0, 33 - (int) n), " ");
2617 putchar_unlocked ('\n');
2622 print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
2623 uint_fast32_t maxlength, Elf32_Word nbucket,
2624 uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
2626 uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
2628 for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2629 ++counts[lengths[cnt]];
2632 printf (ngettext ("\
2633 \nHistogram for bucket list length in section [%2u] '%s' (total of %d bucket):\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2635 \nHistogram for bucket list length in section [%2u] '%s' (total of %d buckets):\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2637 (unsigned int) elf_ndxscn (scn),
2638 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2640 gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
2643 (unsigned int) shdr->sh_link,
2644 elf_strptr (ebl->elf, shstrndx,
2645 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2648 if (extrastr != NULL)
2649 fputs (extrastr, stdout);
2651 if (likely (nbucket > 0))
2653 uint64_t success = 0;
2655 /* xgettext:no-c-format */
2656 fputs_unlocked (gettext ("\
2657 Length Number % of total Coverage\n"), stdout);
2658 printf (gettext (" 0 %6" PRIu32 " %5.1f%%\n"),
2659 counts[0], (counts[0] * 100.0) / nbucket);
2661 uint64_t nzero_counts = 0;
2662 for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
2664 nzero_counts += counts[cnt] * cnt;
2666 %7d %6" PRIu32 " %5.1f%% %5.1f%%\n"),
2667 (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
2668 (nzero_counts * 100.0) / nsyms);
2672 for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
2675 success += counts[cnt] * acc;
2679 Average number of tests: successful lookup: %f\n\
2680 unsuccessful lookup: %f\n"),
2681 (double) success / (double) nzero_counts,
2682 (double) nzero_counts / (double) nbucket);
2689 /* This function handles the traditional System V-style hash table format. */
2691 handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2693 Elf_Data *data = elf_getdata (scn, NULL);
2694 if (unlikely (data == NULL))
2696 error (0, 0, gettext ("cannot get data for section %d: %s"),
2697 (int) elf_ndxscn (scn), elf_errmsg (-1));
2701 Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
2702 Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
2703 Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
2704 Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
2706 uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2708 uint_fast32_t maxlength = 0;
2709 uint_fast32_t nsyms = 0;
2710 for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2712 Elf32_Word inner = bucket[cnt];
2713 while (inner > 0 && inner < nchain)
2716 if (maxlength < ++lengths[cnt])
2719 inner = chain[inner];
2723 print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
2730 /* This function handles the incorrect, System V-style hash table
2731 format some 64-bit architectures use. */
2733 handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2735 Elf_Data *data = elf_getdata (scn, NULL);
2736 if (unlikely (data == NULL))
2738 error (0, 0, gettext ("cannot get data for section %d: %s"),
2739 (int) elf_ndxscn (scn), elf_errmsg (-1));
2743 Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
2744 Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
2745 Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
2746 Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
2748 uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2750 uint_fast32_t maxlength = 0;
2751 uint_fast32_t nsyms = 0;
2752 for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
2754 Elf64_Xword inner = bucket[cnt];
2755 while (inner > 0 && inner < nchain)
2758 if (maxlength < ++lengths[cnt])
2761 inner = chain[inner];
2765 print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
2772 /* This function handles the GNU-style hash table format. */
2774 handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2776 Elf_Data *data = elf_getdata (scn, NULL);
2777 if (unlikely (data == NULL))
2779 error (0, 0, gettext ("cannot get data for section %d: %s"),
2780 (int) elf_ndxscn (scn), elf_errmsg (-1));
2784 Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
2785 Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
2787 /* Next comes the size of the bitmap. It's measured in words for
2788 the architecture. It's 32 bits for 32 bit archs, and 64 bits for
2790 Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
2791 if (gelf_getclass (ebl->elf) == ELFCLASS64)
2794 Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
2796 uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2798 Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
2799 Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
2800 Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
2803 /* Compute distribution of chain lengths. */
2804 uint_fast32_t maxlength = 0;
2805 uint_fast32_t nsyms = 0;
2806 for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2807 if (bucket[cnt] != 0)
2809 Elf32_Word inner = bucket[cnt] - symbias;
2813 if (maxlength < ++lengths[cnt])
2816 while ((chain[inner++] & 1) == 0);
2819 /* Count bits in bitmask. */
2820 uint_fast32_t nbits = 0;
2821 for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
2823 uint_fast32_t word = bitmask[cnt];
2825 word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
2826 word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
2827 word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
2828 word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
2829 nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
2833 if (unlikely (asprintf (&str, gettext ("\
2835 Bitmask Size: %zu bytes %" PRIuFAST32 "%% bits set 2nd hash shift: %u\n"),
2836 (unsigned int) symbias,
2837 bitmask_words * sizeof (Elf32_Word),
2839 / (uint_fast32_t) (bitmask_words
2840 * sizeof (Elf32_Word) * 8)),
2841 (unsigned int) shift) == -1))
2842 error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
2844 print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
2852 /* Find the symbol table(s). For this we have to search through the
2855 handle_hash (Ebl *ebl)
2857 /* Get the section header string table index. */
2859 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2860 error (EXIT_FAILURE, 0,
2861 gettext ("cannot get section header string table index"));
2863 Elf_Scn *scn = NULL;
2864 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2866 /* Handle the section if it is a symbol table. */
2868 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2870 if (likely (shdr != NULL))
2872 if (shdr->sh_type == SHT_HASH)
2874 if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
2875 handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
2877 handle_sysv_hash (ebl, scn, shdr, shstrndx);
2879 else if (shdr->sh_type == SHT_GNU_HASH)
2880 handle_gnu_hash (ebl, scn, shdr, shstrndx);
2887 print_liblist (Ebl *ebl)
2889 /* Find the library list sections. For this we have to search
2890 through the section table. */
2891 Elf_Scn *scn = NULL;
2893 /* Get the section header string table index. */
2895 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2896 error (EXIT_FAILURE, 0,
2897 gettext ("cannot get section header string table index"));
2899 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2902 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2904 if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
2906 int nentries = shdr->sh_size / shdr->sh_entsize;
2907 printf (ngettext ("\
2908 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2910 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2913 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2917 Elf_Data *data = elf_getdata (scn, NULL);
2922 Library Time Stamp Checksum Version Flags"));
2924 for (int cnt = 0; cnt < nentries; ++cnt)
2927 GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
2928 if (unlikely (lib == NULL))
2931 time_t t = (time_t) lib->l_time_stamp;
2932 struct tm *tm = gmtime (&t);
2933 if (unlikely (tm == NULL))
2936 printf (" [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
2937 cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
2938 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
2939 tm->tm_hour, tm->tm_min, tm->tm_sec,
2940 (unsigned int) lib->l_checksum,
2941 (unsigned int) lib->l_version,
2942 (unsigned int) lib->l_flags);
2949 print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
2951 /* Find the object attributes sections. For this we have to search
2952 through the section table. */
2953 Elf_Scn *scn = NULL;
2955 /* Get the section header string table index. */
2957 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2958 error (EXIT_FAILURE, 0,
2959 gettext ("cannot get section header string table index"));
2961 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2964 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2966 if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
2967 && (shdr->sh_type != SHT_ARM_ATTRIBUTES
2968 || ehdr->e_machine != EM_ARM)))
2972 \nObject attributes section [%2zu] '%s' of %" PRIu64
2973 " bytes at offset %#0" PRIx64 ":\n"),
2975 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2976 shdr->sh_size, shdr->sh_offset);
2978 Elf_Data *data = elf_rawdata (scn, NULL);
2982 const unsigned char *p = data->d_buf;
2984 if (unlikely (*p++ != 'A'))
2987 fputs_unlocked (gettext (" Owner Size\n"), stdout);
2989 inline size_t left (void)
2991 return (const unsigned char *) data->d_buf + data->d_size - p;
2994 while (left () >= 4)
2997 memcpy (&len, p, sizeof len);
2999 if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3002 if (unlikely (len > left ()))
3005 const unsigned char *name = p + sizeof len;
3008 unsigned const char *q = memchr (name, '\0', len);
3009 if (unlikely (q == NULL))
3013 printf (gettext (" %-13s %4" PRIu32 "\n"), name, len);
3015 if (shdr->sh_type != SHT_GNU_ATTRIBUTES
3016 || (q - name == sizeof "gnu"
3017 && !memcmp (name, "gnu", sizeof "gnu")))
3020 const unsigned char *const sub = q;
3022 unsigned int subsection_tag;
3023 get_uleb128 (subsection_tag, q);
3024 if (unlikely (q >= p))
3027 uint32_t subsection_len;
3028 if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
3031 memcpy (&subsection_len, q, sizeof subsection_len);
3033 if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3034 CONVERT (subsection_len);
3036 if (unlikely (p - sub < (ptrdiff_t) subsection_len))
3039 const unsigned char *r = q + sizeof subsection_len;
3040 q = sub + subsection_len;
3042 switch (subsection_tag)
3045 printf (gettext (" %-4u %12" PRIu32 "\n"),
3046 subsection_tag, subsection_len);
3049 case 1: /* Tag_File */
3050 printf (gettext (" File: %11" PRIu32 "\n"),
3056 get_uleb128 (tag, r);
3057 if (unlikely (r >= q))
3061 const char *string = NULL;
3062 if (tag == 32 || (tag & 1) == 0)
3064 get_uleb128 (value, r);
3068 if (tag == 32 || (tag & 1) != 0)
3070 r = memchr (r, '\0', q - r);
3076 const char *tag_name = NULL;
3077 const char *value_name = NULL;
3078 ebl_check_object_attribute (ebl, (const char *) name,
3080 &tag_name, &value_name);
3082 if (tag_name != NULL)
3085 printf (gettext (" %s: %" PRId64 ", %s\n"),
3086 tag_name, value, string);
3087 else if (string == NULL && value_name == NULL)
3088 printf (gettext (" %s: %" PRId64 "\n"),
3091 printf (gettext (" %s: %s\n"),
3092 tag_name, string ?: value_name);
3098 printf (gettext (" %u: %" PRId64 "\n"),
3101 printf (gettext (" %u: %s\n"),
3113 format_dwarf_addr (Dwfl_Module *dwflmod,
3114 int address_size, Dwarf_Addr address)
3116 /* See if there is a name we can give for this address. */
3118 const char *name = print_address_names
3119 ? dwfl_module_addrsym (dwflmod, address, &sym, NULL) : NULL;
3121 sym.st_value = address - sym.st_value;
3123 /* Relativize the address. */
3124 int n = dwfl_module_relocations (dwflmod);
3125 int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
3127 /* In an ET_REL file there is a section name to refer to. */
3128 const char *scn = (i < 0 ? NULL
3129 : dwfl_module_relocation_info (dwflmod, i, NULL));
3133 ? (sym.st_value != 0
3135 ? (address_size == 0
3136 ? asprintf (&result,
3137 gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
3138 scn, address, name, sym.st_value)
3139 : asprintf (&result,
3140 gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
3141 scn, 2 + address_size * 2, address,
3142 name, sym.st_value))
3143 : (address_size == 0
3144 ? asprintf (&result,
3145 gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
3146 address, name, sym.st_value)
3147 : asprintf (&result,
3148 gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
3149 2 + address_size * 2, address,
3150 name, sym.st_value)))
3152 ? (address_size == 0
3153 ? asprintf (&result,
3154 gettext ("%s+%#" PRIx64 " <%s>"),
3156 : asprintf (&result,
3157 gettext ("%s+%#0*" PRIx64 " <%s>"),
3158 scn, 2 + address_size * 2, address, name))
3159 : (address_size == 0
3160 ? asprintf (&result,
3161 gettext ("%#" PRIx64 " <%s>"),
3163 : asprintf (&result,
3164 gettext ("%#0*" PRIx64 " <%s>"),
3165 2 + address_size * 2, address, name))))
3167 ? (address_size == 0
3168 ? asprintf (&result,
3169 gettext ("%s+%#" PRIx64),
3171 : asprintf (&result,
3172 gettext ("%s+%#0*" PRIx64),
3173 scn, 2 + address_size * 2, address))
3174 : (address_size == 0
3175 ? asprintf (&result,
3178 : asprintf (&result,
3180 2 + address_size * 2, address)))) < 0)
3181 error (EXIT_FAILURE, 0, _("memory exhausted"));
3187 dwarf_tag_string (unsigned int tag)
3191 #define ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
3193 #undef ONE_KNOWN_DW_TAG
3201 dwarf_attr_string (unsigned int attrnum)
3205 #define ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
3207 #undef ONE_KNOWN_DW_AT
3215 dwarf_form_string (unsigned int form)
3219 #define ONE_KNOWN_DW_FORM_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_FORM (NAME, CODE)
3220 #define ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
3222 #undef ONE_KNOWN_DW_FORM
3223 #undef ONE_KNOWN_DW_FORM_DESC
3231 dwarf_lang_string (unsigned int lang)
3235 #define ONE_KNOWN_DW_LANG_DESC(NAME, CODE, DESC) case CODE: return #NAME;
3237 #undef ONE_KNOWN_DW_LANG_DESC
3245 dwarf_inline_string (unsigned int code)
3247 static const char *const known[] =
3249 #define ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME,
3251 #undef ONE_KNOWN_DW_INL
3254 if (likely (code < sizeof (known) / sizeof (known[0])))
3262 dwarf_encoding_string (unsigned int code)
3264 static const char *const known[] =
3266 #define ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
3268 #undef ONE_KNOWN_DW_ATE
3271 if (likely (code < sizeof (known) / sizeof (known[0])))
3279 dwarf_access_string (unsigned int code)
3281 static const char *const known[] =
3283 #define ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME,
3285 #undef ONE_KNOWN_DW_ACCESS
3288 if (likely (code < sizeof (known) / sizeof (known[0])))
3296 dwarf_visibility_string (unsigned int code)
3298 static const char *const known[] =
3300 #define ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
3302 #undef ONE_KNOWN_DW_VIS
3305 if (likely (code < sizeof (known) / sizeof (known[0])))
3313 dwarf_virtuality_string (unsigned int code)
3315 static const char *const known[] =
3317 #define ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
3318 ALL_KNOWN_DW_VIRTUALITY
3319 #undef ONE_KNOWN_DW_VIRTUALITY
3322 if (likely (code < sizeof (known) / sizeof (known[0])))
3330 dwarf_identifier_case_string (unsigned int code)
3332 static const char *const known[] =
3334 #define ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
3336 #undef ONE_KNOWN_DW_ID
3339 if (likely (code < sizeof (known) / sizeof (known[0])))
3347 dwarf_calling_convention_string (unsigned int code)
3349 static const char *const known[] =
3351 #define ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
3353 #undef ONE_KNOWN_DW_CC
3356 if (likely (code < sizeof (known) / sizeof (known[0])))
3364 dwarf_ordering_string (unsigned int code)
3366 static const char *const known[] =
3368 #define ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
3370 #undef ONE_KNOWN_DW_ORD
3373 if (likely (code < sizeof (known) / sizeof (known[0])))
3381 dwarf_discr_list_string (unsigned int code)
3383 static const char *const known[] =
3385 #define ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
3387 #undef ONE_KNOWN_DW_DSC
3390 if (likely (code < sizeof (known) / sizeof (known[0])))
3398 dwarf_locexpr_opcode_string (unsigned int code)
3400 static const char *const known[] =
3402 /* Normally we can't affort building huge table of 64K entries,
3403 most of them zero, just because there are a couple defined
3404 values at the far end. In case of opcodes, it's OK. */
3405 #define ONE_KNOWN_DW_OP_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_OP (NAME, CODE)
3406 #define ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
3408 #undef ONE_KNOWN_DW_OP
3409 #undef ONE_KNOWN_DW_OP_DESC
3412 if (likely (code < sizeof (known) / sizeof (known[0])))
3419 /* Used by all dwarf_foo_name functions. */
3421 string_or_unknown (const char *known, unsigned int code,
3422 unsigned int lo_user, unsigned int hi_user,
3423 bool print_unknown_num)
3425 static char unknown_buf[20];
3427 if (likely (known != NULL))
3430 if (lo_user != 0 && code >= lo_user && code <= hi_user)
3432 snprintf (unknown_buf, sizeof unknown_buf, "lo_user+%#x",
3437 if (print_unknown_num)
3439 snprintf (unknown_buf, sizeof unknown_buf, "??? (%#x)", code);
3448 dwarf_tag_name (unsigned int tag)
3450 const char *ret = dwarf_tag_string (tag);
3451 return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true);
3455 dwarf_attr_name (unsigned int attr)
3457 const char *ret = dwarf_attr_string (attr);
3458 return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true);
3463 dwarf_form_name (unsigned int form)
3465 const char *ret = dwarf_form_string (form);
3466 return string_or_unknown (ret, form, 0, 0, true);
3471 dwarf_lang_name (unsigned int lang)
3473 const char *ret = dwarf_lang_string (lang);
3474 return string_or_unknown (ret, lang, DW_LANG_lo_user, DW_LANG_hi_user, false);
3479 dwarf_inline_name (unsigned int code)
3481 const char *ret = dwarf_inline_string (code);
3482 return string_or_unknown (ret, code, 0, 0, false);
3487 dwarf_encoding_name (unsigned int code)
3489 const char *ret = dwarf_encoding_string (code);
3490 return string_or_unknown (ret, code, DW_ATE_lo_user, DW_ATE_hi_user, false);
3495 dwarf_access_name (unsigned int code)
3497 const char *ret = dwarf_access_string (code);
3498 return string_or_unknown (ret, code, 0, 0, false);
3503 dwarf_visibility_name (unsigned int code)
3505 const char *ret = dwarf_visibility_string (code);
3506 return string_or_unknown (ret, code, 0, 0, false);
3511 dwarf_virtuality_name (unsigned int code)
3513 const char *ret = dwarf_virtuality_string (code);
3514 return string_or_unknown (ret, code, 0, 0, false);
3519 dwarf_identifier_case_name (unsigned int code)
3521 const char *ret = dwarf_identifier_case_string (code);
3522 return string_or_unknown (ret, code, 0, 0, false);
3527 dwarf_calling_convention_name (unsigned int code)
3529 const char *ret = dwarf_calling_convention_string (code);
3530 return string_or_unknown (ret, code, DW_CC_lo_user, DW_CC_hi_user, false);
3535 dwarf_ordering_name (unsigned int code)
3537 const char *ret = dwarf_ordering_string (code);
3538 return string_or_unknown (ret, code, 0, 0, false);
3543 dwarf_discr_list_name (unsigned int code)
3545 const char *ret = dwarf_discr_list_string (code);
3546 return string_or_unknown (ret, code, 0, 0, false);
3551 print_block (size_t n, const void *block)
3554 puts (_("empty block"));
3557 printf (_("%zu byte block:"), n);
3558 const unsigned char *data = block;
3560 printf (" %02x", *data++);
3567 print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
3568 unsigned int vers, unsigned int addrsize, unsigned int offset_size,
3569 Dwarf_Word len, const unsigned char *data)
3571 const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
3575 printf ("%*s(empty)\n", indent, "");
3579 #define NEED(n) if (len < (Dwarf_Word) (n)) goto invalid
3580 #define CONSUME(n) NEED (n); else len -= (n)
3582 Dwarf_Word offset = 0;
3585 uint_fast8_t op = *data++;
3587 const char *op_name = dwarf_locexpr_opcode_string (op);
3588 if (unlikely (op_name == NULL))
3590 static char buf[20];
3591 if (op >= DW_OP_lo_user)
3592 snprintf (buf, sizeof buf, "lo_user+%#x", op - DW_OP_lo_user);
3594 snprintf (buf, sizeof buf, "??? (%#x)", op);
3601 /* Address operand. */
3605 addr = read_4ubyte_unaligned (dbg, data);
3608 assert (addrsize == 8);
3609 addr = read_8ubyte_unaligned (dbg, data);
3614 char *a = format_dwarf_addr (dwflmod, 0, addr);
3615 printf ("%*s[%4" PRIuMAX "] %s %s\n",
3616 indent, "", (uintmax_t) offset, op_name, a);
3619 offset += 1 + addrsize;
3622 case DW_OP_call_ref:
3623 /* Offset operand. */
3626 addr = read_4ubyte_unaligned (dbg, data);
3629 assert (ref_size == 8);
3630 addr = read_8ubyte_unaligned (dbg, data);
3635 printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
3636 indent, "", (uintmax_t) offset,
3637 op_name, (uintmax_t) addr);
3638 offset += 1 + ref_size;
3641 case DW_OP_deref_size:
3642 case DW_OP_xderef_size:
3645 // XXX value might be modified by relocation
3647 printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
3648 indent, "", (uintmax_t) offset,
3649 op_name, *((uint8_t *) data));
3657 // XXX value might be modified by relocation
3658 printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
3659 indent, "", (uintmax_t) offset,
3660 op_name, read_2ubyte_unaligned (dbg, data));
3668 // XXX value might be modified by relocation
3669 printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
3670 indent, "", (uintmax_t) offset,
3671 op_name, read_4ubyte_unaligned (dbg, data));
3679 // XXX value might be modified by relocation
3680 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
3681 indent, "", (uintmax_t) offset,
3682 op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
3690 // XXX value might be modified by relocation
3691 printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
3692 indent, "", (uintmax_t) offset,
3693 op_name, *((int8_t *) data));
3701 // XXX value might be modified by relocation
3702 printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
3703 indent, "", (uintmax_t) offset,
3704 op_name, read_2sbyte_unaligned (dbg, data));
3712 // XXX value might be modified by relocation
3713 printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
3714 indent, "", (uintmax_t) offset,
3715 op_name, read_4sbyte_unaligned (dbg, data));
3723 // XXX value might be modified by relocation
3724 printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
3725 indent, "", (uintmax_t) offset,
3726 op_name, read_8sbyte_unaligned (dbg, data));
3734 case DW_OP_plus_uconst:
3736 const unsigned char *start = data;
3739 get_uleb128 (uleb, data); /* XXX check overrun */
3740 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
3741 indent, "", (uintmax_t) offset, op_name, uleb);
3742 CONSUME (data - start);
3743 offset += 1 + (data - start);
3746 case DW_OP_bit_piece:
3750 get_uleb128 (uleb, data); /* XXX check overrun */
3751 get_uleb128 (uleb2, data); /* XXX check overrun */
3752 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
3753 indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
3754 CONSUME (data - start);
3755 offset += 1 + (data - start);
3759 case DW_OP_breg0 ... DW_OP_breg31:
3764 get_sleb128 (sleb, data); /* XXX check overrun */
3765 printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
3766 indent, "", (uintmax_t) offset, op_name, sleb);
3767 CONSUME (data - start);
3768 offset += 1 + (data - start);
3774 get_uleb128 (uleb, data); /* XXX check overrun */
3775 get_sleb128 (sleb, data); /* XXX check overrun */
3776 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
3777 indent, "", (uintmax_t) offset, op_name, uleb, sleb);
3778 CONSUME (data - start);
3779 offset += 1 + (data - start);
3784 printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
3785 indent, "", (uintmax_t) offset, op_name,
3786 read_2ubyte_unaligned (dbg, data));
3793 printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
3794 indent, "", (uintmax_t) offset, op_name,
3795 read_4ubyte_unaligned (dbg, data));
3803 printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
3804 indent, "", (uintmax_t) offset, op_name,
3805 (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
3811 case DW_OP_implicit_value:
3814 get_uleb128 (uleb, data); /* XXX check overrun */
3815 printf ("%*s[%4" PRIuMAX "] %s: ",
3816 indent, "", (uintmax_t) offset, op_name);
3818 print_block (uleb, data);
3820 CONSUME (data - start);
3821 offset += 1 + (data - start);
3824 case DW_OP_GNU_implicit_pointer:
3825 /* DIE offset operand. */
3827 NEED (ref_size + 1);
3829 addr = read_4ubyte_unaligned (dbg, data);
3832 assert (ref_size == 8);
3833 addr = read_8ubyte_unaligned (dbg, data);
3836 /* Byte offset operand. */
3837 get_sleb128 (sleb, data); /* XXX check overrun */
3839 printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX ", %+" PRId64 "\n",
3840 indent, "", (intmax_t) offset,
3841 op_name, (uintmax_t) addr, sleb);
3842 CONSUME (data - start);
3843 offset += 1 + (data - start);
3846 case DW_OP_GNU_entry_value:
3847 /* Size plus expression block. */
3850 get_uleb128 (uleb, data); /* XXX check overrun */
3851 printf ("%*s[%4" PRIuMAX "] %s:\n",
3852 indent, "", (uintmax_t) offset, op_name);
3854 print_ops (dwflmod, dbg, indent + 6, indent + 6, vers,
3855 addrsize, offset_size, uleb, data);
3857 CONSUME (data - start);
3858 offset += 1 + (data - start);
3861 case DW_OP_GNU_const_type:
3862 /* DIE offset, size plus block. */
3865 get_uleb128 (uleb, data); /* XXX check overrun */
3866 uint8_t usize = *(uint8_t *) data++;
3868 printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] ",
3869 indent, "", (uintmax_t) offset, op_name, uleb);
3870 print_block (usize, data);
3872 CONSUME (data - start);
3873 offset += 1 + (data - start);
3876 case DW_OP_GNU_regval_type:
3879 get_uleb128 (uleb, data); /* XXX check overrun */
3880 get_uleb128 (uleb2, data); /* XXX check overrun */
3881 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %#" PRIx64 "\n",
3882 indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
3883 CONSUME (data - start);
3884 offset += 1 + (data - start);
3887 case DW_OP_GNU_deref_type:
3890 usize = *(uint8_t *) data++;
3891 get_uleb128 (uleb, data); /* XXX check overrun */
3892 printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
3893 indent, "", (uintmax_t) offset,
3894 op_name, usize, uleb);
3895 CONSUME (data - start);
3896 offset += 1 + (data - start);
3899 case DW_OP_GNU_convert:
3900 case DW_OP_GNU_reinterpret:
3903 get_uleb128 (uleb, data); /* XXX check overrun */
3904 printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
3905 indent, "", (uintmax_t) offset, op_name, uleb);
3906 CONSUME (data - start);
3907 offset += 1 + (data - start);
3910 case DW_OP_GNU_parameter_ref:
3911 /* 4 byte CU relative reference to the abstract optimized away
3912 DW_TAG_formal_parameter. */
3914 printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
3915 indent, "", (uintmax_t) offset, op_name,
3916 (uintmax_t) read_4ubyte_unaligned (dbg, data));
3924 printf ("%*s[%4" PRIuMAX "] %s\n",
3925 indent, "", (uintmax_t) offset, op_name);
3930 indent = indentrest;
3934 printf (gettext ("%*s[%4" PRIuMAX "] %s <TRUNCATED>\n"),
3935 indent, "", (uintmax_t) offset, op_name);
3943 Dwarf_Off offset:(64 - 3);
3949 #define listptr_offset_size(p) ((p)->dwarf64 ? 8 : 4)
3950 #define listptr_address_size(p) ((p)->addr64 ? 8 : 4)
3953 compare_listptr (const void *a, const void *b, void *arg)
3955 const char *name = arg;
3956 struct listptr *p1 = (void *) a;
3957 struct listptr *p2 = (void *) b;
3959 if (p1->offset < p2->offset)
3961 if (p1->offset > p2->offset)
3964 if (!p1->warned && !p2->warned)
3966 if (p1->addr64 != p2->addr64)
3968 p1->warned = p2->warned = true;
3970 gettext ("%s %#" PRIx64 " used with different address sizes"),
3971 name, (uint64_t) p1->offset);
3973 if (p1->dwarf64 != p2->dwarf64)
3975 p1->warned = p2->warned = true;
3977 gettext ("%s %#" PRIx64 " used with different offset sizes"),
3978 name, (uint64_t) p1->offset);
3985 struct listptr_table
3989 struct listptr *table;
3992 static struct listptr_table known_loclistptr;
3993 static struct listptr_table known_rangelistptr;
3996 reset_listptr (struct listptr_table *table)
3998 free (table->table);
3999 table->table = NULL;
4000 table->n = table->alloc = 0;
4004 notice_listptr (enum section_e section, struct listptr_table *table,
4005 uint_fast8_t address_size, uint_fast8_t offset_size,
4008 if (print_debug_sections & section)
4010 if (table->n == table->alloc)
4012 if (table->alloc == 0)
4016 table->table = xrealloc (table->table,
4017 table->alloc * sizeof table->table[0]);
4020 struct listptr *p = &table->table[table->n++];
4022 *p = (struct listptr)
4024 .addr64 = address_size == 8,
4025 .dwarf64 = offset_size == 8,
4028 assert (p->offset == offset);
4033 sort_listptr (struct listptr_table *table, const char *name)
4036 qsort_r (table->table, table->n, sizeof table->table[0],
4037 &compare_listptr, (void *) name);
4041 skip_listptr_hole (struct listptr_table *table, size_t *idxp,
4042 uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
4043 ptrdiff_t offset, unsigned char **readp, unsigned char *endp)
4048 while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
4051 struct listptr *p = &table->table[*idxp];
4053 if (*idxp == table->n
4054 || p->offset >= (Dwarf_Off) (endp - *readp + offset))
4057 printf (gettext (" [%6tx] <UNUSED GARBAGE IN REST OF SECTION>\n"),
4062 if (p->offset != (Dwarf_Off) offset)
4064 *readp += p->offset - offset;
4065 printf (gettext (" [%6tx] <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
4066 offset, (Dwarf_Off) p->offset - offset);
4070 if (address_sizep != NULL)
4071 *address_sizep = listptr_address_size (p);
4072 if (offset_sizep != NULL)
4073 *offset_sizep = listptr_offset_size (p);
4080 print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
4081 Ebl *ebl, GElf_Ehdr *ehdr,
4082 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
4084 const size_t sh_size = (dbg->sectiondata[IDX_debug_abbrev] ?
4085 dbg->sectiondata[IDX_debug_abbrev]->d_size : 0);
4087 printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
4089 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4090 (uint64_t) shdr->sh_offset);
4092 Dwarf_Off offset = 0;
4093 while (offset < sh_size)
4095 printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
4101 Dwarf_Abbrev abbrev;
4103 int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
4106 if (unlikely (res < 0))
4109 *** error while reading abbreviation: %s\n"),
4114 /* This is the NUL byte at the end of the section. */
4119 /* We know these calls can never fail. */
4120 unsigned int code = dwarf_getabbrevcode (&abbrev);
4121 unsigned int tag = dwarf_getabbrevtag (&abbrev);
4122 int has_children = dwarf_abbrevhaschildren (&abbrev);
4124 printf (gettext (" [%5u] offset: %" PRId64
4125 ", children: %s, tag: %s\n"),
4126 code, (int64_t) offset,
4127 has_children ? gettext ("yes") : gettext ("no"),
4128 dwarf_tag_name (tag));
4134 while (dwarf_getabbrevattr (&abbrev, cnt,
4135 &name, &form, &enoffset) == 0)
4137 printf (" attr: %s, form: %s, offset: %#" PRIx64 "\n",
4138 dwarf_attr_name (name), dwarf_form_name (form),
4139 (uint64_t) enoffset);
4150 /* Print content of DWARF .debug_aranges section. We fortunately do
4151 not have to know a bit about the structure of the section, libdwarf
4152 takes care of it. */
4154 print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
4155 Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4156 GElf_Shdr *shdr, Dwarf *dbg)
4158 Dwarf_Aranges *aranges;
4160 if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
4162 error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
4167 printf (ngettext ("\
4168 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
4170 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
4172 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4173 (uint64_t) shdr->sh_offset, cnt);
4175 /* Compute floor(log16(cnt)). */
4184 for (size_t n = 0; n < cnt; ++n)
4186 Dwarf_Arange *runp = dwarf_onearange (aranges, n);
4187 if (unlikely (runp == NULL))
4189 printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
4197 if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
4198 printf (gettext (" [%*zu] ???\n"), digits, n);
4200 printf (gettext (" [%*zu] start: %0#*" PRIx64
4201 ", length: %5" PRIu64 ", CU DIE offset: %6"
4203 digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
4204 (uint64_t) start, (uint64_t) length, (int64_t) offset);
4208 /* Print content of DWARF .debug_ranges section. */
4210 print_debug_ranges_section (Dwfl_Module *dwflmod,
4211 Ebl *ebl, GElf_Ehdr *ehdr,
4212 Elf_Scn *scn, GElf_Shdr *shdr,
4215 Elf_Data *data = elf_rawdata (scn, NULL);
4217 if (unlikely (data == NULL))
4219 error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
4225 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
4226 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4227 (uint64_t) shdr->sh_offset);
4229 sort_listptr (&known_rangelistptr, "rangelistptr");
4230 size_t listptr_idx = 0;
4232 uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
4235 unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
4236 unsigned char *readp = data->d_buf;
4237 while (readp < endp)
4239 ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
4241 if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
4242 &address_size, NULL,
4243 offset, &readp, endp))
4246 if (unlikely (data->d_size - offset < address_size * 2))
4248 printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
4254 if (address_size == 8)
4256 begin = read_8ubyte_unaligned_inc (dbg, readp);
4257 end = read_8ubyte_unaligned_inc (dbg, readp);
4261 begin = read_4ubyte_unaligned_inc (dbg, readp);
4262 end = read_4ubyte_unaligned_inc (dbg, readp);
4263 if (begin == (Dwarf_Addr) (uint32_t) -1)
4264 begin = (Dwarf_Addr) -1l;
4267 if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
4269 char *b = format_dwarf_addr (dwflmod, address_size, end);
4270 printf (gettext (" [%6tx] base address %s\n"), offset, b);
4273 else if (begin == 0 && end == 0) /* End of list entry. */
4276 printf (gettext (" [%6tx] empty list\n"), offset);
4281 char *b = format_dwarf_addr (dwflmod, address_size, begin);
4282 char *e = format_dwarf_addr (dwflmod, address_size, end);
4283 /* We have an address range entry. */
4284 if (first) /* First address range entry in a list. */
4285 printf (gettext (" [%6tx] %s..%s\n"), offset, b, e);
4287 printf (gettext (" %s..%s\n"), b, e);
4296 #define REGNAMESZ 16
4298 register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
4299 char name[REGNAMESZ], int *bits, int *type)
4304 ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
4305 bits ?: &ignore, type ?: &ignore);
4309 snprintf (name, REGNAMESZ, "reg%u", loc->regno);
4311 snprintf (name, REGNAMESZ, "??? 0x%x", regno);
4313 *bits = loc != NULL ? loc->bits : 0;
4315 *type = DW_ATE_unsigned;
4316 set = "??? unrecognized";
4320 if (bits != NULL && *bits <= 0)
4321 *bits = loc != NULL ? loc->bits : 0;
4322 if (type != NULL && *type == DW_ATE_void)
4323 *type = DW_ATE_unsigned;
4330 print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
4331 Dwarf_Word vma_base, unsigned int code_align,
4333 unsigned int version, unsigned int ptr_size,
4334 Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
4336 char regnamebuf[REGNAMESZ];
4337 const char *regname (unsigned int regno)
4339 register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
4343 puts ("\n Program:");
4344 Dwarf_Word pc = vma_base;
4345 while (readp < endp)
4347 unsigned int opcode = *readp++;
4349 if (opcode < DW_CFA_advance_loc)
4350 /* Extended opcode. */
4361 case DW_CFA_set_loc:
4362 // XXX overflow check
4363 get_uleb128 (op1, readp);
4365 printf (" set_loc %" PRIu64 "\n", op1 * code_align);
4367 case DW_CFA_advance_loc1:
4368 printf (" advance_loc1 %u to %#" PRIx64 "\n",
4369 *readp, pc += *readp * code_align);
4372 case DW_CFA_advance_loc2:
4373 op1 = read_2ubyte_unaligned_inc (dbg, readp);
4374 printf (" advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
4375 op1, pc += op1 * code_align);
4377 case DW_CFA_advance_loc4:
4378 op1 = read_4ubyte_unaligned_inc (dbg, readp);
4379 printf (" advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
4380 op1, pc += op1 * code_align);
4382 case DW_CFA_offset_extended:
4383 // XXX overflow check
4384 get_uleb128 (op1, readp);
4385 get_uleb128 (op2, readp);
4386 printf (" offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
4388 op1, regname (op1), op2 * data_align);
4390 case DW_CFA_restore_extended:
4391 // XXX overflow check
4392 get_uleb128 (op1, readp);
4393 printf (" restore_extended r%" PRIu64 " (%s)\n",
4394 op1, regname (op1));
4396 case DW_CFA_undefined:
4397 // XXX overflow check
4398 get_uleb128 (op1, readp);
4399 printf (" undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
4401 case DW_CFA_same_value:
4402 // XXX overflow check
4403 get_uleb128 (op1, readp);
4404 printf (" same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
4406 case DW_CFA_register:
4407 // XXX overflow check
4408 get_uleb128 (op1, readp);
4409 get_uleb128 (op2, readp);
4410 printf (" register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
4411 op1, regname (op1), op2, regname (op2));
4413 case DW_CFA_remember_state:
4414 puts (" remember_state");
4416 case DW_CFA_restore_state:
4417 puts (" restore_state");
4419 case DW_CFA_def_cfa:
4420 // XXX overflow check
4421 get_uleb128 (op1, readp);
4422 get_uleb128 (op2, readp);
4423 printf (" def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
4424 op1, regname (op1), op2);
4426 case DW_CFA_def_cfa_register:
4427 // XXX overflow check
4428 get_uleb128 (op1, readp);
4429 printf (" def_cfa_register r%" PRIu64 " (%s)\n",
4430 op1, regname (op1));
4432 case DW_CFA_def_cfa_offset:
4433 // XXX overflow check
4434 get_uleb128 (op1, readp);
4435 printf (" def_cfa_offset %" PRIu64 "\n", op1);
4437 case DW_CFA_def_cfa_expression:
4438 // XXX overflow check
4439 get_uleb128 (op1, readp); /* Length of DW_FORM_block. */
4440 printf (" def_cfa_expression %" PRIu64 "\n", op1);
4441 print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op1, readp);
4444 case DW_CFA_expression:
4445 // XXX overflow check
4446 get_uleb128 (op1, readp);
4447 get_uleb128 (op2, readp); /* Length of DW_FORM_block. */
4448 printf (" expression r%" PRIu64 " (%s) \n",
4449 op1, regname (op1));
4450 print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op2, readp);
4453 case DW_CFA_offset_extended_sf:
4454 // XXX overflow check
4455 get_uleb128 (op1, readp);
4456 get_sleb128 (sop2, readp);
4457 printf (" offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
4459 op1, regname (op1), sop2 * data_align);
4461 case DW_CFA_def_cfa_sf:
4462 // XXX overflow check
4463 get_uleb128 (op1, readp);
4464 get_sleb128 (sop2, readp);
4465 printf (" def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
4466 op1, regname (op1), sop2 * data_align);
4468 case DW_CFA_def_cfa_offset_sf:
4469 // XXX overflow check
4470 get_sleb128 (sop1, readp);
4471 printf (" def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
4473 case DW_CFA_val_offset:
4474 // XXX overflow check
4475 get_uleb128 (op1, readp);
4476 get_uleb128 (op2, readp);
4477 printf (" val_offset %" PRIu64 " at offset %" PRIu64 "\n",
4478 op1, op2 * data_align);
4480 case DW_CFA_val_offset_sf:
4481 // XXX overflow check
4482 get_uleb128 (op1, readp);
4483 get_sleb128 (sop2, readp);
4484 printf (" val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
4485 op1, sop2 * data_align);
4487 case DW_CFA_val_expression:
4488 // XXX overflow check
4489 get_uleb128 (op1, readp);
4490 get_uleb128 (op2, readp); /* Length of DW_FORM_block. */
4491 printf (" val_expression r%" PRIu64 " (%s)\n",
4492 op1, regname (op1));
4493 print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op2, readp);
4496 case DW_CFA_MIPS_advance_loc8:
4497 op1 = read_8ubyte_unaligned_inc (dbg, readp);
4498 printf (" MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
4499 op1, pc += op1 * code_align);
4501 case DW_CFA_GNU_window_save:
4502 puts (" GNU_window_save");
4504 case DW_CFA_GNU_args_size:
4505 // XXX overflow check
4506 get_uleb128 (op1, readp);
4507 printf (" args_size %" PRIu64 "\n", op1);
4510 printf (" ??? (%u)\n", opcode);
4513 else if (opcode < DW_CFA_offset)
4514 printf (" advance_loc %u to %#" PRIx64 "\n",
4515 opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
4516 else if (opcode < DW_CFA_restore)
4519 // XXX overflow check
4520 get_uleb128 (offset, readp);
4521 printf (" offset r%u (%s) at cfa%+" PRId64 "\n",
4522 opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
4525 printf (" restore r%u (%s)\n",
4526 opcode & 0x3f, regname (opcode & 0x3f));
4532 encoded_ptr_size (int encoding, unsigned int ptr_size)
4534 switch (encoding & 7)
4549 print_encoding (unsigned int val)
4553 case DW_EH_PE_absptr:
4554 fputs ("absptr", stdout);
4556 case DW_EH_PE_uleb128:
4557 fputs ("uleb128", stdout);
4559 case DW_EH_PE_udata2:
4560 fputs ("udata2", stdout);
4562 case DW_EH_PE_udata4:
4563 fputs ("udata4", stdout);
4565 case DW_EH_PE_udata8:
4566 fputs ("udata8", stdout);
4568 case DW_EH_PE_sleb128:
4569 fputs ("sleb128", stdout);
4571 case DW_EH_PE_sdata2:
4572 fputs ("sdata2", stdout);
4574 case DW_EH_PE_sdata4:
4575 fputs ("sdata4", stdout);
4577 case DW_EH_PE_sdata8:
4578 fputs ("sdata8", stdout);
4581 /* We did not use any of the bits after all. */
4590 print_relinfo (unsigned int val)
4594 case DW_EH_PE_pcrel:
4595 fputs ("pcrel", stdout);
4597 case DW_EH_PE_textrel:
4598 fputs ("textrel", stdout);
4600 case DW_EH_PE_datarel:
4601 fputs ("datarel", stdout);
4603 case DW_EH_PE_funcrel:
4604 fputs ("funcrel", stdout);
4606 case DW_EH_PE_aligned:
4607 fputs ("aligned", stdout);
4618 print_encoding_base (const char *pfx, unsigned int fde_encoding)
4620 printf ("(%s", pfx);
4622 if (fde_encoding == DW_EH_PE_omit)
4626 unsigned int w = fde_encoding;
4628 w = print_encoding (w);
4632 if (w != fde_encoding)
4633 fputc_unlocked (' ', stdout);
4635 w = print_relinfo (w);
4639 printf ("%s%x", w != fde_encoding ? " " : "", w);
4646 static const unsigned char *
4647 read_encoded (unsigned int encoding, const unsigned char *readp,
4648 const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
4650 if ((encoding & 0xf) == DW_EH_PE_absptr)
4651 encoding = gelf_getclass (dbg->elf) == ELFCLASS32
4652 ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
4654 switch (encoding & 0xf)
4656 case DW_EH_PE_uleb128:
4657 // XXX buffer overrun check
4658 get_uleb128 (*res, readp);
4660 case DW_EH_PE_sleb128:
4661 // XXX buffer overrun check
4662 get_sleb128 (*res, readp);
4664 case DW_EH_PE_udata2:
4665 if (readp + 2 > endp)
4667 *res = read_2ubyte_unaligned_inc (dbg, readp);
4669 case DW_EH_PE_udata4:
4670 if (readp + 4 > endp)
4672 *res = read_4ubyte_unaligned_inc (dbg, readp);
4674 case DW_EH_PE_udata8:
4675 if (readp + 8 > endp)
4677 *res = read_8ubyte_unaligned_inc (dbg, readp);
4679 case DW_EH_PE_sdata2:
4680 if (readp + 2 > endp)
4682 *res = read_2sbyte_unaligned_inc (dbg, readp);
4684 case DW_EH_PE_sdata4:
4685 if (readp + 4 > endp)
4687 *res = read_4sbyte_unaligned_inc (dbg, readp);
4689 case DW_EH_PE_sdata8:
4690 if (readp + 8 > endp)
4692 *res = read_8sbyte_unaligned_inc (dbg, readp);
4697 gettext ("invalid encoding"));
4705 print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
4706 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
4709 /* We know this call will succeed since it did in the caller. */
4710 (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
4711 const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
4713 Elf_Data *data = elf_rawdata (scn, NULL);
4715 if (unlikely (data == NULL))
4717 error (0, 0, gettext ("cannot get %s content: %s"),
4718 scnname, elf_errmsg (-1));
4721 bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
4725 \nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
4726 elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
4729 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
4730 elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
4734 ptrdiff_t cie_offset;
4735 const char *augmentation;
4736 unsigned int code_alignment_factor;
4737 unsigned int data_alignment_factor;
4738 uint8_t address_size;
4739 uint8_t fde_encoding;
4740 uint8_t lsda_encoding;
4741 struct cieinfo *next;
4744 const unsigned char *readp = data->d_buf;
4745 const unsigned char *const dataend = ((unsigned char *) data->d_buf
4747 while (readp < dataend)
4749 if (unlikely (readp + 4 > dataend))
4752 error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
4753 elf_ndxscn (scn), scnname);
4757 /* At the beginning there must be a CIE. There can be multiple,
4758 hence we test tis in a loop. */
4759 ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
4761 Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
4762 unsigned int length = 4;
4763 if (unlikely (unit_length == 0xffffffff))
4765 if (unlikely (readp + 8 > dataend))
4768 unit_length = read_8ubyte_unaligned_inc (dbg, readp);
4772 if (unlikely (unit_length == 0))
4774 printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
4778 unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
4780 ptrdiff_t start = readp - (unsigned char *) data->d_buf;
4781 const unsigned char *const cieend = readp + unit_length;
4782 if (unlikely (cieend > dataend || readp + 8 > dataend))
4788 cie_id = read_4ubyte_unaligned_inc (dbg, readp);
4789 if (!is_eh_frame && cie_id == DW_CIE_ID_32)
4790 cie_id = DW_CIE_ID_64;
4793 cie_id = read_8ubyte_unaligned_inc (dbg, readp);
4795 uint_fast8_t version = 2;
4796 unsigned int code_alignment_factor;
4797 int data_alignment_factor;
4798 unsigned int fde_encoding = 0;
4799 unsigned int lsda_encoding = 0;
4800 Dwarf_Word initial_location = 0;
4801 Dwarf_Word vma_base = 0;
4803 if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
4806 const char *const augmentation = (const char *) readp;
4807 readp = memchr (readp, '\0', cieend - readp);
4808 if (unlikely (readp == NULL))
4812 uint_fast8_t segment_size = 0;
4815 if (cieend - readp < 5)
4817 ptr_size = *readp++;
4818 segment_size = *readp++;
4821 // XXX Check overflow
4822 get_uleb128 (code_alignment_factor, readp);
4823 // XXX Check overflow
4824 get_sleb128 (data_alignment_factor, readp);
4826 /* In some variant for unwind data there is another field. */
4827 if (strcmp (augmentation, "eh") == 0)
4828 readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
4830 unsigned int return_address_register;
4831 if (unlikely (version == 1))
4832 return_address_register = *readp++;
4834 // XXX Check overflow
4835 get_uleb128 (return_address_register, readp);
4837 printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
4838 " CIE_id: %" PRIu64 "\n"
4840 " augmentation: \"%s\"\n",
4841 offset, (uint64_t) unit_length, (uint64_t) cie_id,
4842 version, augmentation);
4844 printf (" address_size: %u\n"
4845 " segment_size: %u\n",
4846 ptr_size, segment_size);
4847 printf (" code_alignment_factor: %u\n"
4848 " data_alignment_factor: %d\n"
4849 " return_address_register: %u\n",
4850 code_alignment_factor,
4851 data_alignment_factor, return_address_register);
4853 if (augmentation[0] == 'z')
4855 unsigned int augmentationlen;
4856 get_uleb128 (augmentationlen, readp);
4858 if (augmentationlen > (size_t) (dataend - readp))
4859 error (1, 0, gettext ("invalid augmentation length"));
4861 const char *hdr = "Augmentation data:";
4862 const char *cp = augmentation + 1;
4865 printf (" %-26s%#x ", hdr, *readp);
4870 fde_encoding = *readp++;
4871 print_encoding_base (gettext ("FDE address encoding: "),
4874 else if (*cp == 'L')
4876 lsda_encoding = *readp++;
4877 print_encoding_base (gettext ("LSDA pointer encoding: "),
4880 else if (*cp == 'P')
4882 /* Personality. This field usually has a relocation
4883 attached pointing to __gcc_personality_v0. */
4884 const unsigned char *startp = readp;
4885 unsigned int encoding = *readp++;
4887 readp = read_encoded (encoding, readp,
4888 readp - 1 + augmentationlen,
4891 while (++startp < readp)
4892 printf ("%#x ", *startp);
4895 print_encoding (encoding);
4897 switch (encoding & 0xf)
4899 case DW_EH_PE_sleb128:
4900 case DW_EH_PE_sdata2:
4901 case DW_EH_PE_sdata4:
4902 printf ("%" PRId64 ")\n", val);
4905 printf ("%#" PRIx64 ")\n", val);
4910 printf ("(%x)\n", *readp++);
4916 if (likely (ptr_size == 4 || ptr_size == 8))
4918 struct cieinfo *newp = alloca (sizeof (*newp));
4919 newp->cie_offset = offset;
4920 newp->augmentation = augmentation;
4921 newp->fde_encoding = fde_encoding;
4922 newp->lsda_encoding = lsda_encoding;
4923 newp->address_size = ptr_size;
4924 newp->code_alignment_factor = code_alignment_factor;
4925 newp->data_alignment_factor = data_alignment_factor;
4932 struct cieinfo *cie = cies;
4935 ? start - (ptrdiff_t) cie_id == cie->cie_offset
4936 : (ptrdiff_t) cie_id == cie->cie_offset)
4940 if (unlikely (cie == NULL))
4942 puts ("invalid CIE reference in FDE");
4946 /* Initialize from CIE data. */
4947 fde_encoding = cie->fde_encoding;
4948 lsda_encoding = cie->lsda_encoding;
4949 ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
4950 code_alignment_factor = cie->code_alignment_factor;
4951 data_alignment_factor = cie->data_alignment_factor;
4953 const unsigned char *base = readp;
4954 // XXX There are sometimes relocations for this value
4955 initial_location = read_ubyte_unaligned_inc (ptr_size, dbg, readp);
4956 Dwarf_Word address_range
4957 = read_ubyte_unaligned_inc (ptr_size, dbg, readp);
4959 char *a = format_dwarf_addr (dwflmod, cie->address_size,
4961 printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
4962 " CIE_pointer: %" PRIu64 "\n"
4963 " initial_location: %s",
4964 offset, (uint64_t) unit_length,
4965 cie->cie_offset, (uint64_t) cie_id, a);
4967 if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
4969 vma_base = (((uint64_t) shdr->sh_offset
4970 + (base - (const unsigned char *) data->d_buf)
4971 + (uint64_t) initial_location)
4973 ? UINT64_C (0xffffffff)
4974 : UINT64_C (0xffffffffffffffff)));
4975 printf (gettext (" (offset: %#" PRIx64 ")"),
4976 (uint64_t) vma_base);
4979 printf ("\n address_range: %#" PRIx64,
4980 (uint64_t) address_range);
4981 if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
4982 printf (gettext (" (end offset: %#" PRIx64 ")"),
4983 ((uint64_t) vma_base + (uint64_t) address_range)
4985 ? UINT64_C (0xffffffff)
4986 : UINT64_C (0xffffffffffffffff)));
4989 if (cie->augmentation[0] == 'z')
4991 unsigned int augmentationlen;
4992 get_uleb128 (augmentationlen, readp);
4994 if (augmentationlen > 0)
4996 const char *hdr = "Augmentation data:";
4997 const char *cp = cie->augmentation + 1;
5003 uint64_t lsda_pointer;
5004 const unsigned char *p
5005 = read_encoded (lsda_encoding, &readp[u],
5006 &readp[augmentationlen],
5007 &lsda_pointer, dbg);
5010 %-26sLSDA pointer: %#" PRIx64 "\n"),
5017 while (u < augmentationlen)
5019 printf (" %-26s%#x\n", hdr, readp[u++]);
5024 readp += augmentationlen;
5028 /* Handle the initialization instructions. */
5029 print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
5030 data_alignment_factor, version, ptr_size,
5039 Dwfl_Module *dwflmod;
5043 unsigned int version;
5044 unsigned int addrsize;
5045 unsigned int offset_size;
5046 Dwarf_Off cu_offset;
5051 attr_callback (Dwarf_Attribute *attrp, void *arg)
5053 struct attrcb_args *cbargs = (struct attrcb_args *) arg;
5054 const int level = cbargs->level;
5056 unsigned int attr = dwarf_whatattr (attrp);
5057 if (unlikely (attr == 0))
5059 if (!cbargs->silent)
5060 error (0, 0, gettext ("cannot get attribute code: %s"),
5062 return DWARF_CB_ABORT;
5065 unsigned int form = dwarf_whatform (attrp);
5066 if (unlikely (form == 0))
5068 if (!cbargs->silent)
5069 error (0, 0, gettext ("cannot get attribute form: %s"),
5071 return DWARF_CB_ABORT;
5077 if (!cbargs->silent)
5080 if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
5083 if (!cbargs->silent)
5084 error (0, 0, gettext ("cannot get attribute value: %s"),
5086 return DWARF_CB_ABORT;
5088 char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr);
5089 printf (" %*s%-20s (%s) %s\n",
5090 (int) (level * 2), "", dwarf_attr_name (attr),
5091 dwarf_form_name (form), a);
5096 case DW_FORM_indirect:
5098 case DW_FORM_string:
5099 case DW_FORM_GNU_strp_alt:
5102 const char *str = dwarf_formstring (attrp);
5103 if (unlikely (str == NULL))
5105 printf (" %*s%-20s (%s) \"%s\"\n",
5106 (int) (level * 2), "", dwarf_attr_name (attr),
5107 dwarf_form_name (form), str);
5110 case DW_FORM_ref_addr:
5111 case DW_FORM_ref_udata:
5116 case DW_FORM_GNU_ref_alt:
5120 if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
5123 printf (" %*s%-20s (%s) [%6" PRIxMAX "]\n",
5124 (int) (level * 2), "", dwarf_attr_name (attr),
5125 dwarf_form_name (form), (uintmax_t) dwarf_dieoffset (&ref));
5128 case DW_FORM_ref_sig8:
5131 printf (" %*s%-20s (%s) {%6" PRIx64 "}\n",
5132 (int) (level * 2), "", dwarf_attr_name (attr),
5133 dwarf_form_name (form),
5134 (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
5137 case DW_FORM_sec_offset:
5143 case DW_FORM_data1:;
5145 if (unlikely (dwarf_formudata (attrp, &num) != 0))
5148 const char *valuestr = NULL;
5151 /* This case can take either a constant or a loclistptr. */
5152 case DW_AT_data_member_location:
5153 if (form != DW_FORM_sec_offset
5154 && (cbargs->version >= 4
5155 || (form != DW_FORM_data4 && form != DW_FORM_data8)))
5157 if (!cbargs->silent)
5158 printf (" %*s%-20s (%s) %" PRIxMAX "\n",
5159 (int) (level * 2), "", dwarf_attr_name (attr),
5160 dwarf_form_name (form), (uintmax_t) num);
5163 /* else fallthrough */
5165 /* These cases always take a loclistptr and no constant. */
5166 case DW_AT_location:
5167 case DW_AT_data_location:
5168 case DW_AT_vtable_elem_location:
5169 case DW_AT_string_length:
5170 case DW_AT_use_location:
5171 case DW_AT_frame_base:
5172 case DW_AT_return_addr:
5173 case DW_AT_static_link:
5174 case DW_AT_GNU_call_site_value:
5175 case DW_AT_GNU_call_site_data_value:
5176 case DW_AT_GNU_call_site_target:
5177 case DW_AT_GNU_call_site_target_clobbered:
5178 notice_listptr (section_loc, &known_loclistptr,
5179 cbargs->addrsize, cbargs->offset_size, num);
5180 if (!cbargs->silent)
5181 printf (" %*s%-20s (%s) location list [%6" PRIxMAX "]\n",
5182 (int) (level * 2), "", dwarf_attr_name (attr),
5183 dwarf_form_name (form), (uintmax_t) num);
5187 notice_listptr (section_ranges, &known_rangelistptr,
5188 cbargs->addrsize, cbargs->offset_size, num);
5189 if (!cbargs->silent)
5190 printf (" %*s%-20s (%s) range list [%6" PRIxMAX "]\n",
5191 (int) (level * 2), "", dwarf_attr_name (attr),
5192 dwarf_form_name (form), (uintmax_t) num);
5195 case DW_AT_language:
5196 valuestr = dwarf_lang_name (num);
5198 case DW_AT_encoding:
5199 valuestr = dwarf_encoding_name (num);
5201 case DW_AT_accessibility:
5202 valuestr = dwarf_access_name (num);
5204 case DW_AT_visibility:
5205 valuestr = dwarf_visibility_name (num);
5207 case DW_AT_virtuality:
5208 valuestr = dwarf_virtuality_name (num);
5210 case DW_AT_identifier_case:
5211 valuestr = dwarf_identifier_case_name (num);
5213 case DW_AT_calling_convention:
5214 valuestr = dwarf_calling_convention_name (num);
5217 valuestr = dwarf_inline_name (num);
5219 case DW_AT_ordering:
5220 valuestr = dwarf_ordering_name (num);
5222 case DW_AT_discr_list:
5223 valuestr = dwarf_discr_list_name (num);
5233 if (valuestr == NULL)
5234 printf (" %*s%-20s (%s) %" PRIuMAX "\n",
5235 (int) (level * 2), "", dwarf_attr_name (attr),
5236 dwarf_form_name (form), (uintmax_t) num);
5238 printf (" %*s%-20s (%s) %s (%" PRIuMAX ")\n",
5239 (int) (level * 2), "", dwarf_attr_name (attr),
5240 dwarf_form_name (form), valuestr, (uintmax_t) num);
5247 if (unlikely (dwarf_formflag (attrp, &flag) != 0))
5250 printf (" %*s%-20s (%s) %s\n",
5251 (int) (level * 2), "", dwarf_attr_name (attr),
5252 dwarf_form_name (form), nl_langinfo (flag ? YESSTR : NOSTR));
5255 case DW_FORM_flag_present:
5258 printf (" %*s%-20s (%s) %s\n",
5259 (int) (level * 2), "", dwarf_attr_name (attr),
5260 dwarf_form_name (form), nl_langinfo (YESSTR));
5263 case DW_FORM_exprloc:
5264 case DW_FORM_block4:
5265 case DW_FORM_block2:
5266 case DW_FORM_block1:
5271 if (unlikely (dwarf_formblock (attrp, &block) != 0))
5274 printf (" %*s%-20s (%s) ",
5275 (int) (level * 2), "", dwarf_attr_name (attr),
5276 dwarf_form_name (form));
5281 if (form != DW_FORM_exprloc)
5283 print_block (block.length, block.data);
5288 case DW_AT_location:
5289 case DW_AT_data_location:
5290 case DW_AT_data_member_location:
5291 case DW_AT_vtable_elem_location:
5292 case DW_AT_string_length:
5293 case DW_AT_use_location:
5294 case DW_AT_frame_base:
5295 case DW_AT_return_addr:
5296 case DW_AT_static_link:
5297 case DW_AT_allocated:
5298 case DW_AT_associated:
5299 case DW_AT_bit_size:
5300 case DW_AT_bit_offset:
5301 case DW_AT_bit_stride:
5302 case DW_AT_byte_size:
5303 case DW_AT_byte_stride:
5305 case DW_AT_lower_bound:
5306 case DW_AT_upper_bound:
5307 case DW_AT_GNU_call_site_value:
5308 case DW_AT_GNU_call_site_data_value:
5309 case DW_AT_GNU_call_site_target:
5310 case DW_AT_GNU_call_site_target_clobbered:
5312 print_ops (cbargs->dwflmod, cbargs->dbg,
5313 12 + level * 2, 12 + level * 2,
5314 cbargs->version, cbargs->addrsize, cbargs->offset_size,
5315 block.length, block.data);
5323 printf (" %*s%-20s (form: %#x) ???\n",
5324 (int) (level * 2), "", dwarf_attr_name (attr),
5333 print_debug_units (Dwfl_Module *dwflmod,
5334 Ebl *ebl, GElf_Ehdr *ehdr,
5335 Elf_Scn *scn, GElf_Shdr *shdr,
5336 Dwarf *dbg, bool debug_types)
5338 const bool silent = !(print_debug_sections & section_info);
5339 const char *secname = section_name (ebl, ehdr, shdr);
5343 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
5344 elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
5346 /* If the section is empty we don't have to do anything. */
5347 if (!silent && shdr->sh_size == 0)
5351 Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
5353 Dwarf_Off offset = 0;
5355 /* New compilation unit. */
5358 Dwarf_Off abbroffset;
5365 if (dwarf_next_unit (dbg, offset, &nextcu, &cuhl, &version,
5366 &abbroffset, &addrsize, &offsize,
5367 debug_types ? &typesig : NULL,
5368 debug_types ? &typeoff : NULL) != 0)
5374 printf (gettext (" Type unit at offset %" PRIu64 ":\n"
5375 " Version: %" PRIu16 ", Abbreviation section offset: %"
5376 PRIu64 ", Address size: %" PRIu8
5377 ", Offset size: %" PRIu8
5378 "\n Type signature: %#" PRIx64
5379 ", Type offset: %#" PRIx64 "\n"),
5380 (uint64_t) offset, version, abbroffset, addrsize, offsize,
5381 typesig, (uint64_t) typeoff);
5383 printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
5384 " Version: %" PRIu16 ", Abbreviation section offset: %"
5385 PRIu64 ", Address size: %" PRIu8
5386 ", Offset size: %" PRIu8 "\n"),
5387 (uint64_t) offset, version, abbroffset, addrsize, offsize);
5390 struct attrcb_args args =
5396 .addrsize = addrsize,
5397 .offset_size = offsize,
5405 if (unlikely ((debug_types ? dwarf_offdie_types : dwarf_offdie)
5406 (dbg, offset, &dies[level]) == NULL))
5409 error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
5410 " in section '%s': %s"),
5411 (uint64_t) offset, secname, dwarf_errmsg (-1));
5417 offset = dwarf_dieoffset (&dies[level]);
5418 if (unlikely (offset == ~0ul))
5421 error (0, 0, gettext ("cannot get DIE offset: %s"),
5426 int tag = dwarf_tag (&dies[level]);
5427 if (unlikely (tag == DW_TAG_invalid))
5430 error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
5431 " in section '%s': %s"),
5432 (uint64_t) offset, secname, dwarf_errmsg (-1));
5437 printf (" [%6" PRIx64 "] %*s%s\n",
5438 (uint64_t) offset, (int) (level * 2), "",
5439 dwarf_tag_name (tag));
5441 /* Print the attribute values. */
5443 (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
5445 /* Make room for the next level's DIE. */
5446 if (level + 1 == maxdies)
5447 dies = (Dwarf_Die *) xrealloc (dies,
5449 * sizeof (Dwarf_Die));
5451 int res = dwarf_child (&dies[level], &dies[level + 1]);
5454 while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
5458 if (unlikely (res == -1))
5461 error (0, 0, gettext ("cannot get next DIE: %s\n"),
5466 else if (unlikely (res < 0))
5469 error (0, 0, gettext ("cannot get next DIE: %s"),
5487 print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
5488 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5490 print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
5494 print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
5495 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5497 print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
5502 print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
5503 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5506 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5507 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
5508 (uint64_t) shdr->sh_offset);
5510 if (shdr->sh_size == 0)
5513 /* There is no functionality in libdw to read the information in the
5514 way it is represented here. Hardcode the decoder. */
5515 Elf_Data *data = elf_getdata (scn, NULL);
5516 if (unlikely (data == NULL || data->d_buf == NULL))
5518 error (0, 0, gettext ("cannot get line data section data: %s"),
5523 const unsigned char *linep = (const unsigned char *) data->d_buf;
5524 const unsigned char *lineendp;
5527 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
5529 size_t start_offset = linep - (const unsigned char *) data->d_buf;
5531 printf (gettext ("\nTable at offset %Zu:\n"), start_offset);
5533 Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
5534 unsigned int length = 4;
5535 if (unlikely (unit_length == 0xffffffff))
5537 if (unlikely (linep + 8 > lineendp))
5540 error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
5541 elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
5544 unit_length = read_8ubyte_unaligned_inc (dbg, linep);
5548 /* Check whether we have enough room in the section. */
5549 if (unit_length < 2 + length + 5 * 1
5550 || unlikely (linep + unit_length > lineendp))
5552 lineendp = linep + unit_length;
5554 /* The next element of the header is the version identifier. */
5555 uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
5557 /* Next comes the header length. */
5558 Dwarf_Word header_length;
5560 header_length = read_4ubyte_unaligned_inc (dbg, linep);
5562 header_length = read_8ubyte_unaligned_inc (dbg, linep);
5563 //const unsigned char *header_start = linep;
5565 /* Next the minimum instruction length. */
5566 uint_fast8_t minimum_instr_len = *linep++;
5568 /* Next the maximum operations per instruction, in version 4 format. */
5569 uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++;
5571 /* Then the flag determining the default value of the is_stmt
5573 uint_fast8_t default_is_stmt = *linep++;
5575 /* Now the line base. */
5576 int_fast8_t line_base = *((const int_fast8_t *) linep);
5579 /* And the line range. */
5580 uint_fast8_t line_range = *linep++;
5582 /* The opcode base. */
5583 uint_fast8_t opcode_base = *linep++;
5585 /* Print what we got so far. */
5586 printf (gettext ("\n"
5587 " Length: %" PRIu64 "\n"
5588 " DWARF version: %" PRIuFAST16 "\n"
5589 " Prologue length: %" PRIu64 "\n"
5590 " Minimum instruction length: %" PRIuFAST8 "\n"
5591 " Maximum operations per instruction: %" PRIuFAST8 "\n"
5592 " Initial value if '%s': %" PRIuFAST8 "\n"
5593 " Line base: %" PRIdFAST8 "\n"
5594 " Line range: %" PRIuFAST8 "\n"
5595 " Opcode base: %" PRIuFAST8 "\n"
5598 (uint64_t) unit_length, version, (uint64_t) header_length,
5599 minimum_instr_len, max_ops_per_instr,
5600 "is_stmt", default_is_stmt, line_base,
5601 line_range, opcode_base);
5603 if (unlikely (linep + opcode_base - 1 >= lineendp))
5607 gettext ("invalid data at offset %tu in section [%zu] '%s'"),
5608 linep - (const unsigned char *) data->d_buf,
5609 elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
5613 int opcode_base_l10 = 1;
5614 unsigned int tmp = opcode_base;
5620 const uint8_t *standard_opcode_lengths = linep - 1;
5621 for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
5622 printf (ngettext (" [%*" PRIuFAST8 "] %hhu argument\n",
5623 " [%*" PRIuFAST8 "] %hhu arguments\n",
5624 (int) linep[cnt - 1]),
5625 opcode_base_l10, cnt, linep[cnt - 1]);
5626 linep += opcode_base - 1;
5627 if (unlikely (linep >= lineendp))
5630 puts (gettext ("\nDirectory table:"));
5633 unsigned char *endp = memchr (linep, '\0', lineendp - linep);
5634 if (unlikely (endp == NULL))
5637 printf (" %s\n", (char *) linep);
5641 /* Skip the final NUL byte. */
5644 if (unlikely (linep >= lineendp))
5646 puts (gettext ("\nFile name table:\n"
5647 " Entry Dir Time Size Name"));
5648 for (unsigned int cnt = 1; *linep != 0; ++cnt)
5650 /* First comes the file name. */
5651 char *fname = (char *) linep;
5652 unsigned char *endp = memchr (fname, '\0', lineendp - linep);
5653 if (unlikely (endp == NULL))
5657 /* Then the index. */
5658 unsigned int diridx;
5659 get_uleb128 (diridx, linep);
5661 /* Next comes the modification time. */
5663 get_uleb128 (mtime, linep);
5665 /* Finally the length of the file. */
5667 get_uleb128 (fsize, linep);
5669 printf (" %-5u %-5u %-9u %-9u %s\n",
5670 cnt, diridx, mtime, fsize, fname);
5672 /* Skip the final NUL byte. */
5675 puts (gettext ("\nLine number statements:"));
5676 Dwarf_Word address = 0;
5677 unsigned int op_index = 0;
5679 uint_fast8_t is_stmt = default_is_stmt;
5681 /* Default address value, in case we do not find the CU. */
5683 = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5685 /* Determine the CU this block is for. */
5687 Dwarf_Off ncuoffset = 0;
5689 while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
5690 NULL, NULL, NULL) == 0)
5693 if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
5695 Dwarf_Attribute stmt_list;
5696 if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
5699 if (dwarf_formudata (&stmt_list, &lineoff) != 0)
5701 if (lineoff == start_offset)
5704 address_size = cudie.cu->address_size;
5709 /* Apply the "operation advance" from a special opcode
5710 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */
5711 unsigned int op_addr_advance;
5713 inline void advance_pc (unsigned int op_advance)
5715 op_addr_advance = minimum_instr_len * ((op_index + op_advance)
5716 / max_ops_per_instr);
5717 address += op_advance;
5718 show_op_index = (op_index > 0 ||
5719 (op_index + op_advance) % max_ops_per_instr > 0);
5720 op_index = (op_index + op_advance) % max_ops_per_instr;
5723 while (linep < lineendp)
5725 size_t offset = linep - (const unsigned char *) data->d_buf;
5729 /* Read the opcode. */
5730 unsigned int opcode = *linep++;
5732 printf (" [%6" PRIx64 "]", (uint64_t)offset);
5733 /* Is this a special opcode? */
5734 if (likely (opcode >= opcode_base))
5736 /* Yes. Handling this is quite easy since the opcode value
5739 opcode = (desired line increment - line_base)
5740 + (line_range * address advance) + opcode_base
5742 int line_increment = (line_base
5743 + (opcode - opcode_base) % line_range);
5745 /* Perform the increments. */
5746 line += line_increment;
5747 advance_pc ((opcode - opcode_base) / line_range);
5749 char *a = format_dwarf_addr (dwflmod, 0, address);
5752 special opcode %u: address+%u = %s, op_index = %u, line%+d = %zu\n"),
5753 opcode, op_addr_advance, a, op_index,
5754 line_increment, line);
5757 special opcode %u: address+%u = %s, line%+d = %zu\n"),
5758 opcode, op_addr_advance, a, line_increment, line);
5761 else if (opcode == 0)
5763 /* This an extended opcode. */
5764 if (unlikely (linep + 2 > lineendp))
5768 unsigned int len = *linep++;
5770 if (unlikely (linep + len > lineendp))
5773 /* The sub-opcode. */
5776 printf (gettext (" extended opcode %u: "), opcode);
5780 case DW_LNE_end_sequence:
5781 puts (gettext (" end of sequence"));
5783 /* Reset the registers we care about. */
5787 is_stmt = default_is_stmt;
5790 case DW_LNE_set_address:
5792 if (address_size == 4)
5793 address = read_4ubyte_unaligned_inc (dbg, linep);
5795 address = read_8ubyte_unaligned_inc (dbg, linep);
5797 char *a = format_dwarf_addr (dwflmod, 0, address);
5798 printf (gettext (" set address to %s\n"), a);
5803 case DW_LNE_define_file:
5805 char *fname = (char *) linep;
5806 unsigned char *endp = memchr (linep, '\0',
5808 if (unlikely (endp == NULL))
5812 unsigned int diridx;
5813 get_uleb128 (diridx, linep);
5815 get_uleb128 (mtime, linep);
5816 Dwarf_Word filelength;
5817 get_uleb128 (filelength, linep);
5820 define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
5821 diridx, (uint64_t) mtime, (uint64_t) filelength,
5826 case DW_LNE_set_discriminator:
5827 /* Takes one ULEB128 parameter, the discriminator. */
5828 if (unlikely (standard_opcode_lengths[opcode] != 1))
5831 get_uleb128 (u128, linep);
5832 printf (gettext (" set discriminator to %u\n"), u128);
5836 /* Unknown, ignore it. */
5837 puts (gettext (" unknown opcode"));
5842 else if (opcode <= DW_LNS_set_isa)
5844 /* This is a known standard opcode. */
5848 /* Takes no argument. */
5849 puts (gettext (" copy"));
5852 case DW_LNS_advance_pc:
5853 /* Takes one uleb128 parameter which is added to the
5855 get_uleb128 (u128, linep);
5858 char *a = format_dwarf_addr (dwflmod, 0, address);
5861 advance address by %u to %s, op_index to %u\n"),
5862 op_addr_advance, a, op_index);
5864 printf (gettext (" advance address by %u to %s\n"),
5865 op_addr_advance, a);
5870 case DW_LNS_advance_line:
5871 /* Takes one sleb128 parameter which is added to the
5873 get_sleb128 (s128, linep);
5876 advance line by constant %d to %" PRId64 "\n"),
5877 s128, (int64_t) line);
5880 case DW_LNS_set_file:
5881 /* Takes one uleb128 parameter which is stored in file. */
5882 get_uleb128 (u128, linep);
5883 printf (gettext (" set file to %" PRIu64 "\n"),
5887 case DW_LNS_set_column:
5888 /* Takes one uleb128 parameter which is stored in column. */
5889 if (unlikely (standard_opcode_lengths[opcode] != 1))
5892 get_uleb128 (u128, linep);
5893 printf (gettext (" set column to %" PRIu64 "\n"),
5897 case DW_LNS_negate_stmt:
5898 /* Takes no argument. */
5899 is_stmt = 1 - is_stmt;
5900 printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
5901 "is_stmt", is_stmt);
5904 case DW_LNS_set_basic_block:
5905 /* Takes no argument. */
5906 puts (gettext (" set basic block flag"));
5909 case DW_LNS_const_add_pc:
5910 /* Takes no argument. */
5911 advance_pc ((255 - opcode_base) / line_range);
5913 char *a = format_dwarf_addr (dwflmod, 0, address);
5916 advance address by constant %u to %s, op_index to %u\n"),
5917 op_addr_advance, a, op_index);
5920 advance address by constant %u to %s\n"),
5921 op_addr_advance, a);
5926 case DW_LNS_fixed_advance_pc:
5927 /* Takes one 16 bit parameter which is added to the
5929 if (unlikely (standard_opcode_lengths[opcode] != 1))
5932 u128 = read_2ubyte_unaligned_inc (dbg, linep);
5936 char *a = format_dwarf_addr (dwflmod, 0, address);
5938 advance address by fixed value %u to %s\n"),
5944 case DW_LNS_set_prologue_end:
5945 /* Takes no argument. */
5946 puts (gettext (" set prologue end flag"));
5949 case DW_LNS_set_epilogue_begin:
5950 /* Takes no argument. */
5951 puts (gettext (" set epilogue begin flag"));
5954 case DW_LNS_set_isa:
5955 /* Takes one uleb128 parameter which is stored in isa. */
5956 if (unlikely (standard_opcode_lengths[opcode] != 1))
5959 get_uleb128 (u128, linep);
5960 printf (gettext (" set isa to %u\n"), u128);
5966 /* This is a new opcode the generator but not we know about.
5967 Read the parameters associated with it but then discard
5968 everything. Read all the parameters for this opcode. */
5969 printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
5970 " unknown opcode with %" PRIu8 " parameters:",
5971 standard_opcode_lengths[opcode]),
5972 standard_opcode_lengths[opcode]);
5973 for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
5975 get_uleb128 (u128, linep);
5976 if (n != standard_opcode_lengths[opcode])
5977 putc_unlocked (',', stdout);
5978 printf (" %u", u128);
5981 /* Next round, ignore this opcode. */
5987 /* There must only be one data block. */
5988 assert (elf_getdata (scn, data) == NULL);
5993 print_debug_loc_section (Dwfl_Module *dwflmod,
5994 Ebl *ebl, GElf_Ehdr *ehdr,
5995 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5997 Elf_Data *data = elf_rawdata (scn, NULL);
5999 if (unlikely (data == NULL))
6001 error (0, 0, gettext ("cannot get .debug_loc content: %s"),
6007 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6008 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6009 (uint64_t) shdr->sh_offset);
6011 sort_listptr (&known_loclistptr, "loclistptr");
6012 size_t listptr_idx = 0;
6014 uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6015 uint_fast8_t offset_size = 4;
6018 unsigned char *readp = data->d_buf;
6019 unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
6020 while (readp < endp)
6022 ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
6024 if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx,
6025 &address_size, &offset_size,
6026 offset, &readp, endp))
6029 if (unlikely (data->d_size - offset < address_size * 2))
6031 printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
6037 if (address_size == 8)
6039 begin = read_8ubyte_unaligned_inc (dbg, readp);
6040 end = read_8ubyte_unaligned_inc (dbg, readp);
6044 begin = read_4ubyte_unaligned_inc (dbg, readp);
6045 end = read_4ubyte_unaligned_inc (dbg, readp);
6046 if (begin == (Dwarf_Addr) (uint32_t) -1)
6047 begin = (Dwarf_Addr) -1l;
6050 if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
6052 char *b = format_dwarf_addr (dwflmod, address_size, end);
6053 printf (gettext (" [%6tx] base address %s\n"), offset, b);
6056 else if (begin == 0 && end == 0) /* End of list entry. */
6059 printf (gettext (" [%6tx] empty list\n"), offset);
6064 /* We have a location expression entry. */
6065 uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
6067 char *b = format_dwarf_addr (dwflmod, address_size, begin);
6068 char *e = format_dwarf_addr (dwflmod, address_size, end);
6070 if (first) /* First entry in a list. */
6071 printf (gettext (" [%6tx] %s..%s"), offset, b, e);
6073 printf (gettext (" %s..%s"), b, e);
6078 if (endp - readp <= (ptrdiff_t) len)
6080 fputs (gettext (" <INVALID DATA>\n"), stdout);
6084 print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
6085 3 /*XXX*/, address_size, offset_size, len, readp);
6098 struct mac_culist *next;
6103 mac_compare (const void *p1, const void *p2)
6105 struct mac_culist *m1 = (struct mac_culist *) p1;
6106 struct mac_culist *m2 = (struct mac_culist *) p2;
6108 if (m1->offset < m2->offset)
6110 if (m1->offset > m2->offset)
6117 print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6118 Ebl *ebl, GElf_Ehdr *ehdr,
6119 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6122 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6123 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6124 (uint64_t) shdr->sh_offset);
6125 putc_unlocked ('\n', stdout);
6127 /* There is no function in libdw to iterate over the raw content of
6128 the section but it is easy enough to do. */
6129 Elf_Data *data = elf_getdata (scn, NULL);
6130 if (unlikely (data == NULL || data->d_buf == NULL))
6132 error (0, 0, gettext ("cannot get macro information section data: %s"),
6137 /* Get the source file information for all CUs. */
6141 struct mac_culist *culist = NULL;
6143 while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
6146 if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
6149 Dwarf_Attribute attr;
6150 if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
6154 if (dwarf_formudata (&attr, &macoff) != 0)
6157 struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
6159 newp->offset = macoff;
6161 newp->next = culist;
6166 /* Convert the list into an array for easier consumption. */
6167 struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
6170 cus[nculist].offset = data->d_size;
6173 for (size_t cnt = nculist - 1; culist != NULL; --cnt)
6175 assert (cnt < nculist);
6177 culist = culist->next;
6180 /* Sort the array according to the offset in the .debug_macinfo
6181 section. Note we keep the sentinel at the end. */
6182 qsort (cus, nculist, sizeof (*cus), mac_compare);
6185 const unsigned char *readp = (const unsigned char *) data->d_buf;
6186 const unsigned char *readendp = readp + data->d_size;
6189 while (readp < readendp)
6191 unsigned int opcode = *readp++;
6193 unsigned int u128_2;
6194 const unsigned char *endp;
6198 case DW_MACINFO_define:
6199 case DW_MACINFO_undef:
6200 case DW_MACINFO_vendor_ext:
6201 /* For the first two opcodes the parameters are
6205 We can treat these cases together. */
6206 get_uleb128 (u128, readp);
6208 endp = memchr (readp, '\0', readendp - readp);
6209 if (unlikely (endp == NULL))
6212 %*s*** non-terminated string at end of section"),
6217 if (opcode == DW_MACINFO_define)
6218 printf ("%*s#define %s, line %u\n",
6219 level, "", (char *) readp, u128);
6220 else if (opcode == DW_MACINFO_undef)
6221 printf ("%*s#undef %s, line %u\n",
6222 level, "", (char *) readp, u128);
6224 printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
6229 case DW_MACINFO_start_file:
6230 /* The two parameters are line and file index, in this order. */
6231 get_uleb128 (u128, readp);
6232 get_uleb128 (u128_2, readp);
6234 /* Find the CU DIE for this file. */
6235 size_t macoff = readp - (const unsigned char *) data->d_buf;
6236 const char *fname = "???";
6237 if (macoff >= cus[0].offset)
6239 while (macoff >= cus[1].offset)
6242 if (cus[0].files == NULL
6243 && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
6244 cus[0].files = (Dwarf_Files *) -1l;
6246 if (cus[0].files != (Dwarf_Files *) -1l)
6247 fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
6251 printf ("%*sstart_file %u, [%u] %s\n",
6252 level, "", u128, u128_2, fname);
6256 case DW_MACINFO_end_file:
6258 printf ("%*send_file\n", level, "");
6259 /* Nothing more to do. */
6263 // XXX gcc seems to generate files with a trailing zero.
6264 if (unlikely (opcode != 0 || readp != readendp))
6265 printf ("%*s*** invalid opcode %u\n", level, "", opcode);
6273 print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6274 Ebl *ebl, GElf_Ehdr *ehdr,
6275 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6278 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6279 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6280 (uint64_t) shdr->sh_offset);
6281 putc_unlocked ('\n', stdout);
6283 Elf_Data *data = elf_getdata (scn, NULL);
6284 if (unlikely (data == NULL || data->d_buf == NULL))
6286 error (0, 0, gettext ("cannot get macro information section data: %s"),
6291 /* Get the source file information for all CUs. Uses same
6292 datastructure as macinfo. But uses offset field to directly
6293 match .debug_line offset. And just stored in a list. */
6297 struct mac_culist *culist = NULL;
6299 while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
6302 if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
6305 Dwarf_Attribute attr;
6306 if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL)
6310 if (dwarf_formudata (&attr, &lineoff) != 0)
6313 struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
6315 newp->offset = lineoff;
6317 newp->next = culist;
6322 const unsigned char *readp = (const unsigned char *) data->d_buf;
6323 const unsigned char *readendp = readp + data->d_size;
6325 while (readp < readendp)
6327 printf (gettext (" Offset: 0x%" PRIx64 "\n"),
6328 (uint64_t) (readp - (const unsigned char *) data->d_buf));
6330 // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
6331 // optional vendor extension macro entry table.
6332 if (readp + 2 > readendp)
6335 error (0, 0, gettext ("invalid data"));
6338 const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
6339 printf (gettext (" Version: %" PRIu16 "\n"), vers);
6341 // Version 4 is the GNU extension for DWARF4. DWARF5 will use version
6342 // 5 when it gets standardized.
6345 printf (gettext (" unknown version, cannot parse section\n"));
6349 if (readp + 1 > readendp)
6351 const unsigned char flag = *readp++;
6352 printf (gettext (" Flag: 0x%" PRIx8 "\n"), flag);
6354 unsigned int offset_len = (flag & 0x01) ? 8 : 4;
6355 printf (gettext (" Offset length: %" PRIu8 "\n"), offset_len);
6356 Dwarf_Off line_offset = -1;
6359 if (offset_len == 8)
6360 line_offset = read_8ubyte_unaligned_inc (dbg, readp);
6362 line_offset = read_4ubyte_unaligned_inc (dbg, readp);
6363 printf (gettext (" .debug_line offset: 0x%" PRIx64 "\n"),
6367 const unsigned char *vendor[DW_MACRO_GNU_hi_user - DW_MACRO_GNU_lo_user];
6370 // 1 byte length, for each item, 1 byte opcode, uleb128 number
6371 // of arguments, for each argument 1 byte form code.
6372 if (readp + 1 > readendp)
6374 unsigned int tlen = *readp++;
6375 printf (gettext (" extension opcode table, %" PRIu8 " items:\n"),
6377 for (unsigned int i = 0; i < tlen; i++)
6379 if (readp + 1 > readendp)
6381 unsigned int opcode = *readp++;
6382 printf (gettext (" [%" PRIx8 "]"), opcode);
6383 if (opcode < DW_MACRO_GNU_lo_user
6384 || opcode > DW_MACRO_GNU_hi_user)
6386 // Record the start of description for this vendor opcode.
6387 // uleb128 nr args, 1 byte per arg form.
6388 vendor[opcode - DW_MACRO_GNU_lo_user] = readp;
6389 if (readp + 1 > readendp)
6391 unsigned int args = *readp++;
6394 printf (gettext (" %" PRIu8 " arguments:"), args);
6397 if (readp + 1 > readendp)
6399 unsigned int form = *readp++;
6400 printf (" %s", dwarf_form_string (form));
6401 if (form != DW_FORM_data1
6402 && form != DW_FORM_data2
6403 && form != DW_FORM_data4
6404 && form != DW_FORM_data8
6405 && form != DW_FORM_sdata
6406 && form != DW_FORM_udata
6407 && form != DW_FORM_block
6408 && form != DW_FORM_block1
6409 && form != DW_FORM_block2
6410 && form != DW_FORM_block4
6411 && form != DW_FORM_flag
6412 && form != DW_FORM_string
6413 && form != DW_FORM_strp
6414 && form != DW_FORM_sec_offset)
6418 putchar_unlocked (',');
6422 printf (gettext (" no arguments."));
6423 putchar_unlocked ('\n');
6426 putchar_unlocked ('\n');
6429 if (readp + 1 > readendp)
6431 unsigned int opcode = *readp++;
6435 unsigned int u128_2;
6436 const unsigned char *endp;
6441 case DW_MACRO_GNU_start_file:
6442 get_uleb128 (u128, readp);
6443 get_uleb128 (u128_2, readp);
6445 /* Find the CU DIE that matches this line offset. */
6446 const char *fname = "???";
6447 if (line_offset != (Dwarf_Off) -1)
6449 struct mac_culist *cu = culist;
6450 while (cu != NULL && line_offset != cu->offset)
6454 if (cu->files == NULL
6455 && dwarf_getsrcfiles (&cu->die, &cu->files,
6457 cu->files = (Dwarf_Files *) -1l;
6459 if (cu->files != (Dwarf_Files *) -1l)
6460 fname = (dwarf_filesrc (cu->files, u128_2,
6461 NULL, NULL) ?: "???");
6464 printf ("%*sstart_file %u, [%u] %s\n",
6465 level, "", u128, u128_2, fname);
6469 case DW_MACRO_GNU_end_file:
6471 printf ("%*send_file\n", level, "");
6474 case DW_MACRO_GNU_define:
6475 get_uleb128 (u128, readp);
6476 endp = memchr (readp, '\0', readendp - readp);
6479 printf ("%*s#define %s, line %u\n",
6480 level, "", readp, u128);
6484 case DW_MACRO_GNU_undef:
6485 get_uleb128 (u128, readp);
6486 endp = memchr (readp, '\0', readendp - readp);
6489 printf ("%*s#undef %s, line %u\n",
6490 level, "", readp, u128);
6494 case DW_MACRO_GNU_define_indirect:
6495 get_uleb128 (u128, readp);
6496 if (readp + offset_len > readendp)
6498 if (offset_len == 8)
6499 off = read_8ubyte_unaligned_inc (dbg, readp);
6501 off = read_4ubyte_unaligned_inc (dbg, readp);
6502 printf ("%*s#define %s, line %u (indirect)\n",
6503 level, "", dwarf_getstring (dbg, off, NULL), u128);
6506 case DW_MACRO_GNU_undef_indirect:
6507 get_uleb128 (u128, readp);
6508 if (readp + offset_len > readendp)
6510 if (offset_len == 8)
6511 off = read_8ubyte_unaligned_inc (dbg, readp);
6513 off = read_4ubyte_unaligned_inc (dbg, readp);
6514 printf ("%*s#undef %s, line %u (indirect)\n",
6515 level, "", dwarf_getstring (dbg, off, NULL), u128);
6518 case DW_MACRO_GNU_transparent_include:
6519 if (readp + offset_len > readendp)
6521 if (offset_len == 8)
6522 off = read_8ubyte_unaligned_inc (dbg, readp);
6524 off = read_4ubyte_unaligned_inc (dbg, readp);
6525 printf ("%*s#include offset 0x%" PRIx64 "\n",
6530 printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
6531 if (opcode < DW_MACRO_GNU_lo_user
6532 || opcode > DW_MACRO_GNU_lo_user
6533 || vendor[opcode - DW_MACRO_GNU_lo_user] == NULL)
6536 const unsigned char *op_desc;
6537 op_desc = vendor[opcode - DW_MACRO_GNU_lo_user];
6539 // Just skip the arguments, we cannot really interpret them,
6540 // but print as much as we can.
6541 unsigned int args = *op_desc++;
6544 unsigned int form = *op_desc++;
6549 if (readp + 1 > readendp)
6552 printf (" %" PRIx8, (unsigned int) val);
6556 if (readp + 2 > readendp)
6558 val = read_2ubyte_unaligned_inc (dbg, readp);
6559 printf(" %" PRIx16, (unsigned int) val);
6563 if (readp + 4 > readendp)
6565 val = read_4ubyte_unaligned_inc (dbg, readp);
6566 printf (" %" PRIx32, (unsigned int) val);
6570 if (readp + 8 > readendp)
6572 val = read_8ubyte_unaligned_inc (dbg, readp);
6573 printf (" %" PRIx64, val);
6577 get_sleb128 (val, readp);
6578 printf (" %" PRIx64, val);
6582 get_uleb128 (val, readp);
6583 printf (" %" PRIx64, val);
6587 get_uleb128 (val, readp);
6588 printf (" block[%" PRIu64 "]", val);
6589 if (readp + val > readendp)
6594 case DW_FORM_block1:
6595 if (readp + 1 > readendp)
6598 printf (" block[%" PRIu64 "]", val);
6599 if (readp + val > readendp)
6603 case DW_FORM_block2:
6604 if (readp + 2 > readendp)
6606 val = read_2ubyte_unaligned_inc (dbg, readp);
6607 printf (" block[%" PRIu64 "]", val);
6608 if (readp + val > readendp)
6612 case DW_FORM_block4:
6613 if (readp + 2 > readendp)
6615 val =read_4ubyte_unaligned_inc (dbg, readp);
6616 printf (" block[%" PRIu64 "]", val);
6617 if (readp + val > readendp)
6622 if (readp + 1 > readendp)
6625 printf (" %s", nl_langinfo (val != 0 ? YESSTR : NOSTR));
6628 case DW_FORM_string:
6629 endp = memchr (readp, '\0', readendp - readp);
6632 printf (" %s", readp);
6637 if (readp + offset_len > readendp)
6639 if (offset_len == 8)
6640 val = read_8ubyte_unaligned_inc (dbg, readp);
6642 val = read_4ubyte_unaligned_inc (dbg, readp);
6643 printf (" %s", dwarf_getstring (dbg, val, NULL));
6646 case DW_FORM_sec_offset:
6647 if (readp + offset_len > readendp)
6649 if (offset_len == 8)
6650 val = read_8ubyte_unaligned_inc (dbg, readp);
6652 val = read_4ubyte_unaligned_inc (dbg, readp);
6653 printf (" %" PRIx64, val);
6657 error (0, 0, gettext ("vendor opcode not verified?"));
6663 putchar_unlocked (',');
6665 putchar_unlocked ('\n');
6668 if (readp + 1 > readendp)
6672 putchar_unlocked ('\n');
6678 /* Callback for printing global names. */
6680 print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
6683 int *np = (int *) arg;
6685 printf (gettext (" [%5d] DIE offset: %6" PRId64
6686 ", CU DIE offset: %6" PRId64 ", name: %s\n"),
6687 (*np)++, global->die_offset, global->cu_offset, global->name);
6693 /* Print the known exported symbols in the DWARF section '.debug_pubnames'. */
6695 print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6696 Ebl *ebl, GElf_Ehdr *ehdr,
6697 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6699 printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6700 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6701 (uint64_t) shdr->sh_offset);
6704 (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
6707 /* Print the content of the DWARF string section '.debug_str'. */
6709 print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6710 Ebl *ebl, GElf_Ehdr *ehdr,
6711 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6713 const size_t sh_size = (dbg->sectiondata[IDX_debug_str] ?
6714 dbg->sectiondata[IDX_debug_str]->d_size : 0);
6716 /* Compute floor(log16(shdr->sh_size)). */
6717 GElf_Addr tmp = sh_size;
6724 digits = MAX (4, digits);
6726 printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
6729 section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset,
6730 /* TRANS: the debugstr| prefix makes the string unique. */
6731 digits + 2, sgettext ("debugstr|Offset"));
6733 Dwarf_Off offset = 0;
6734 while (offset < sh_size)
6737 const char *str = dwarf_getstring (dbg, offset, &len);
6738 if (unlikely (str == NULL))
6740 printf (gettext (" *** error while reading strings: %s\n"),
6745 printf (" [%*" PRIx64 "] \"%s\"\n", digits, (uint64_t) offset, str);
6752 /* Print the content of the call frame search table section
6755 print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6756 Ebl *ebl __attribute__ ((unused)),
6757 GElf_Ehdr *ehdr __attribute__ ((unused)),
6758 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6761 \nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
6764 Elf_Data *data = elf_rawdata (scn, NULL);
6766 if (unlikely (data == NULL))
6768 error (0, 0, gettext ("cannot get %s content: %s"),
6769 ".eh_frame_hdr", elf_errmsg (-1));
6773 const unsigned char *readp = data->d_buf;
6774 const unsigned char *const dataend = ((unsigned char *) data->d_buf
6777 if (unlikely (readp + 4 > dataend))
6780 error (0, 0, gettext ("invalid data"));
6784 unsigned int version = *readp++;
6785 unsigned int eh_frame_ptr_enc = *readp++;
6786 unsigned int fde_count_enc = *readp++;
6787 unsigned int table_enc = *readp++;
6789 printf (" version: %u\n"
6790 " eh_frame_ptr_enc: %#x ",
6791 version, eh_frame_ptr_enc);
6792 print_encoding_base ("", eh_frame_ptr_enc);
6793 printf (" fde_count_enc: %#x ", fde_count_enc);
6794 print_encoding_base ("", fde_count_enc);
6795 printf (" table_enc: %#x ", table_enc);
6796 print_encoding_base ("", table_enc);
6798 uint64_t eh_frame_ptr = 0;
6799 if (eh_frame_ptr_enc != DW_EH_PE_omit)
6801 readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
6803 if (unlikely (readp == NULL))
6806 printf (" eh_frame_ptr: %#" PRIx64, eh_frame_ptr);
6807 if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
6808 printf (" (offset: %#" PRIx64 ")",
6809 /* +4 because of the 4 byte header of the section. */
6810 (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
6812 putchar_unlocked ('\n');
6815 uint64_t fde_count = 0;
6816 if (fde_count_enc != DW_EH_PE_omit)
6818 readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
6819 if (unlikely (readp == NULL))
6822 printf (" fde_count: %" PRIu64 "\n", fde_count);
6825 if (fde_count == 0 || table_enc == DW_EH_PE_omit)
6830 /* Optimize for the most common case. */
6831 if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
6832 while (fde_count > 0 && readp + 8 <= dataend)
6834 int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
6835 uint64_t initial_offset = ((uint64_t) shdr->sh_offset
6836 + (int64_t) initial_location);
6837 int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
6838 // XXX Possibly print symbol name or section offset for initial_offset
6839 printf (" %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
6840 " fde=[%6" PRIx64 "]\n",
6841 initial_location, initial_offset,
6842 address, address - (eh_frame_ptr + 4));
6845 while (0 && readp < dataend)
6852 /* Print the content of the exception handling table section
6855 print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
6856 Ebl *ebl __attribute__ ((unused)),
6857 GElf_Ehdr *ehdr __attribute__ ((unused)),
6859 GElf_Shdr *shdr __attribute__ ((unused)),
6860 Dwarf *dbg __attribute__ ((unused)))
6863 \nException handling table section [%2zu] '.gcc_except_table':\n"),
6866 Elf_Data *data = elf_rawdata (scn, NULL);
6868 if (unlikely (data == NULL))
6870 error (0, 0, gettext ("cannot get %s content: %s"),
6871 ".gcc_except_table", elf_errmsg (-1));
6875 const unsigned char *readp = data->d_buf;
6876 const unsigned char *const dataend = readp + data->d_size;
6878 if (unlikely (readp + 1 > dataend))
6881 error (0, 0, gettext ("invalid data"));
6884 unsigned int lpstart_encoding = *readp++;
6885 printf (gettext (" LPStart encoding: %#x "), lpstart_encoding);
6886 print_encoding_base ("", lpstart_encoding);
6887 if (lpstart_encoding != DW_EH_PE_omit)
6890 readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
6891 printf (" LPStart: %#" PRIx64 "\n", lpstart);
6894 if (unlikely (readp + 1 > dataend))
6896 unsigned int ttype_encoding = *readp++;
6897 printf (gettext (" TType encoding: %#x "), ttype_encoding);
6898 print_encoding_base ("", ttype_encoding);
6899 const unsigned char *ttype_base = NULL;
6900 if (ttype_encoding != DW_EH_PE_omit)
6902 unsigned int ttype_base_offset;
6903 get_uleb128 (ttype_base_offset, readp);
6904 printf (" TType base offset: %#x\n", ttype_base_offset);
6905 ttype_base = readp + ttype_base_offset;
6908 if (unlikely (readp + 1 > dataend))
6910 unsigned int call_site_encoding = *readp++;
6911 printf (gettext (" Call site encoding: %#x "), call_site_encoding);
6912 print_encoding_base ("", call_site_encoding);
6913 unsigned int call_site_table_len;
6914 get_uleb128 (call_site_table_len, readp);
6916 const unsigned char *const action_table = readp + call_site_table_len;
6917 if (unlikely (action_table > dataend))
6920 unsigned int max_action = 0;
6921 while (readp < action_table)
6924 puts (gettext ("\n Call site table:"));
6926 uint64_t call_site_start;
6927 readp = read_encoded (call_site_encoding, readp, dataend,
6928 &call_site_start, dbg);
6929 uint64_t call_site_length;
6930 readp = read_encoded (call_site_encoding, readp, dataend,
6931 &call_site_length, dbg);
6932 uint64_t landing_pad;
6933 readp = read_encoded (call_site_encoding, readp, dataend,
6935 unsigned int action;
6936 get_uleb128 (action, readp);
6937 max_action = MAX (action, max_action);
6938 printf (gettext (" [%4u] Call site start: %#" PRIx64 "\n"
6939 " Call site length: %" PRIu64 "\n"
6940 " Landing pad: %#" PRIx64 "\n"
6942 u++, call_site_start, call_site_length, landing_pad, action);
6944 assert (readp == action_table);
6946 unsigned int max_ar_filter = 0;
6949 puts ("\n Action table:");
6951 const unsigned char *const action_table_end
6952 = action_table + max_action + 1;
6958 get_sleb128 (ar_filter, readp);
6959 if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
6960 max_ar_filter = ar_filter;
6962 get_sleb128 (ar_disp, readp);
6964 printf (" [%4u] ar_filter: % d\n"
6966 u, ar_filter, ar_disp);
6967 if (abs (ar_disp) & 1)
6968 printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
6969 else if (ar_disp != 0)
6972 putchar_unlocked ('\n');
6975 while (readp < action_table_end);
6978 if (max_ar_filter > 0)
6980 puts ("\n TType table:");
6982 // XXX Not *4, size of encoding;
6983 switch (ttype_encoding & 7)
6985 case DW_EH_PE_udata2:
6986 case DW_EH_PE_sdata2:
6987 readp = ttype_base - max_ar_filter * 2;
6989 case DW_EH_PE_udata4:
6990 case DW_EH_PE_sdata4:
6991 readp = ttype_base - max_ar_filter * 4;
6993 case DW_EH_PE_udata8:
6994 case DW_EH_PE_sdata8:
6995 readp = ttype_base - max_ar_filter * 8;
6998 error (1, 0, gettext ("invalid TType encoding"));
7004 readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
7006 printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
7008 while (readp < ttype_base);
7012 /* Print the content of the '.gdb_index' section.
7013 http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
7016 print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
7017 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7019 printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
7020 " contains %" PRId64 " bytes :\n"),
7021 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7022 (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
7024 Elf_Data *data = elf_rawdata (scn, NULL);
7026 if (unlikely (data == NULL))
7028 error (0, 0, gettext ("cannot get %s content: %s"),
7029 ".gdb_index", elf_errmsg (-1));
7033 // .gdb_index is always in little endian.
7034 Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
7037 const unsigned char *readp = data->d_buf;
7038 const unsigned char *const dataend = readp + data->d_size;
7040 if (unlikely (readp + 4 > dataend))
7043 error (0, 0, gettext ("invalid data"));
7047 int32_t vers = read_4ubyte_unaligned (dbg, readp);
7048 printf (gettext (" Version: %" PRId32 "\n"), vers);
7050 // The only difference between version 4 and version 5 is the
7051 // hash used for generating the table. Version 6 contains symbols
7052 // for inlined functions, older versions didn't.
7053 if (vers < 4 || vers > 7)
7055 printf (gettext (" unknown version, cannot parse section\n"));
7060 if (unlikely (readp + 4 > dataend))
7063 uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
7064 printf (gettext (" CU offset: %#" PRIx32 "\n"), cu_off);
7067 if (unlikely (readp + 4 > dataend))
7070 uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
7071 printf (gettext (" TU offset: %#" PRIx32 "\n"), tu_off);
7074 if (unlikely (readp + 4 > dataend))
7077 uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
7078 printf (gettext (" address offset: %#" PRIx32 "\n"), addr_off);
7081 if (unlikely (readp + 4 > dataend))
7084 uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
7085 printf (gettext (" symbol offset: %#" PRIx32 "\n"), sym_off);
7088 if (unlikely (readp + 4 > dataend))
7091 uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
7092 printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
7094 readp = data->d_buf + cu_off;
7096 const unsigned char *nextp = data->d_buf + tu_off;
7097 size_t cu_nr = (nextp - readp) / 16;
7099 printf (gettext ("\n CU list at offset %#" PRIx32
7100 " contains %zu entries:\n"),
7104 while (readp + 16 <= dataend && n < cu_nr)
7106 uint64_t off = read_8ubyte_unaligned (dbg, readp);
7109 uint64_t len = read_8ubyte_unaligned (dbg, readp);
7112 printf (" [%4zu] start: %0#8" PRIx64
7113 ", length: %5" PRIu64 "\n", n, off, len);
7117 readp = data->d_buf + tu_off;
7118 nextp = data->d_buf + addr_off;
7119 size_t tu_nr = (nextp - readp) / 24;
7121 printf (gettext ("\n TU list at offset %#" PRIx32
7122 " contains %zu entries:\n"),
7126 while (readp + 24 <= dataend && n < tu_nr)
7128 uint64_t off = read_8ubyte_unaligned (dbg, readp);
7131 uint64_t type = read_8ubyte_unaligned (dbg, readp);
7134 uint64_t sig = read_8ubyte_unaligned (dbg, readp);
7137 printf (" [%4zu] CU offset: %5" PRId64
7138 ", type offset: %5" PRId64
7139 ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
7143 readp = data->d_buf + addr_off;
7144 nextp = data->d_buf + sym_off;
7145 size_t addr_nr = (nextp - readp) / 20;
7147 printf (gettext ("\n Address list at offset %#" PRIx32
7148 " contains %zu entries:\n"),
7152 while (readp + 20 <= dataend && n < addr_nr)
7154 uint64_t low = read_8ubyte_unaligned (dbg, readp);
7157 uint64_t high = read_8ubyte_unaligned (dbg, readp);
7160 uint32_t idx = read_4ubyte_unaligned (dbg, readp);
7163 char *l = format_dwarf_addr (dwflmod, 8, low);
7164 char *h = format_dwarf_addr (dwflmod, 8, high - 1);
7165 printf (" [%4zu] %s..%s, CU index: %5" PRId32 "\n",
7170 readp = data->d_buf + sym_off;
7171 nextp = data->d_buf + const_off;
7172 size_t sym_nr = (nextp - readp) / 8;
7174 printf (gettext ("\n Symbol table at offset %#" PRIx32
7175 " contains %zu slots:\n"),
7179 while (readp + 8 <= dataend && n < sym_nr)
7181 uint32_t name = read_4ubyte_unaligned (dbg, readp);
7184 uint32_t vector = read_4ubyte_unaligned (dbg, readp);
7187 if (name != 0 || vector != 0)
7189 const unsigned char *sym = data->d_buf + const_off + name;
7190 if (unlikely (sym > dataend))
7193 printf (" [%4zu] symbol: %s, CUs: ", n, sym);
7195 const unsigned char *readcus = data->d_buf + const_off + vector;
7196 if (unlikely (readcus + 8 > dataend))
7199 uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
7202 uint32_t cu_kind, cu, kind;
7205 cu_kind = read_4ubyte_unaligned (dbg, readcus);
7206 cu = cu_kind & ((1 << 24) - 1);
7207 kind = (cu_kind >> 28) & 7;
7208 is_static = cu_kind & (1 << 31);
7210 printf ("%" PRId32 "T", cu - (uint32_t) cu_nr);
7212 printf ("%" PRId32, cu);
7231 printf ("unknown-0x%" PRIx32, kind);
7234 printf (":%c)", (is_static ? 'S' : 'G'));
7246 print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
7248 /* Before we start the real work get a debug context descriptor. */
7250 Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
7254 .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
7258 if ((print_debug_sections & ~section_exception) != 0)
7259 error (0, 0, gettext ("cannot get debug context descriptor: %s"),
7261 if ((print_debug_sections & section_exception) == 0)
7266 /* Get the section header string table index. */
7268 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
7269 error (EXIT_FAILURE, 0,
7270 gettext ("cannot get section header string table index"));
7272 /* Look through all the sections for the debugging sections to print. */
7273 Elf_Scn *scn = NULL;
7274 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
7277 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
7279 if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
7284 enum section_e bitmask;
7285 void (*fp) (Dwfl_Module *, Ebl *,
7286 GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
7287 } debug_sections[] =
7289 #define NEW_SECTION(name) \
7290 { ".debug_" #name, section_##name, print_debug_##name##_section }
7291 NEW_SECTION (abbrev),
7292 NEW_SECTION (aranges),
7293 NEW_SECTION (frame),
7295 NEW_SECTION (types),
7298 NEW_SECTION (pubnames),
7300 NEW_SECTION (macinfo),
7301 NEW_SECTION (macro),
7302 NEW_SECTION (ranges),
7303 { ".eh_frame", section_frame | section_exception,
7304 print_debug_frame_section },
7305 { ".eh_frame_hdr", section_frame | section_exception,
7306 print_debug_frame_hdr_section },
7307 { ".gcc_except_table", section_frame | section_exception,
7308 print_debug_exception_table },
7309 { ".gdb_index", section_gdb_index, print_gdb_index_section }
7311 const int ndebug_sections = (sizeof (debug_sections)
7312 / sizeof (debug_sections[0]));
7313 const char *name = elf_strptr (ebl->elf, shstrndx,
7317 for (n = 0; n < ndebug_sections; ++n)
7318 if (strcmp (name, debug_sections[n].name) == 0
7320 || (name[0] == '.' && name[1] == 'z'
7321 && debug_sections[n].name[1] == 'd'
7322 && strcmp (&name[2], &debug_sections[n].name[1]) == 0)
7326 if ((print_debug_sections | implicit_debug_sections)
7327 & debug_sections[n].bitmask)
7328 debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
7334 reset_listptr (&known_loclistptr);
7335 reset_listptr (&known_rangelistptr);
7339 #define ITEM_INDENT 4
7340 #define ITEM_WRAP_COLUMN 150
7341 #define REGISTER_WRAP_COLUMN 75
7343 /* Print "NAME: FORMAT", wrapping when FORMAT_MAX chars of FORMAT would
7344 make the line exceed ITEM_WRAP_COLUMN. Unpadded numbers look better
7345 for the core items. But we do not want the line breaks to depend on
7346 the particular values. */
7348 __attribute__ ((format (printf, 7, 8)))
7349 print_core_item (unsigned int colno, char sep, unsigned int wrap,
7350 size_t name_width, const char *name,
7351 size_t format_max, const char *format, ...)
7353 size_t len = strlen (name);
7354 if (name_width < len)
7357 size_t n = name_width + sizeof ": " - 1 + format_max;
7361 printf ("%*s", ITEM_INDENT, "");
7362 colno = ITEM_INDENT + n;
7364 else if (colno + 2 + n < wrap)
7366 printf ("%c ", sep);
7371 printf ("\n%*s", ITEM_INDENT, "");
7372 colno = ITEM_INDENT + n;
7375 printf ("%s: %*s", name, (int) (name_width - len), "");
7378 va_start (ap, format);
7379 vprintf (format, ap);
7386 convert (Elf *core, Elf_Type type, uint_fast16_t count,
7387 void *value, const void *data, size_t size)
7389 Elf_Data valuedata =
7393 .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
7394 .d_version = EV_CURRENT,
7399 .d_buf = (void *) data,
7400 .d_size = valuedata.d_size,
7401 .d_version = EV_CURRENT,
7404 Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
7405 ? elf32_xlatetom : elf64_xlatetom)
7406 (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
7408 error (EXIT_FAILURE, 0,
7409 gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
7411 return data + indata.d_size;
7414 typedef uint8_t GElf_Byte;
7417 handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
7418 unsigned int colno, size_t *repeated_size)
7420 uint_fast16_t count = item->count ?: 1;
7423 DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8, 4); \
7424 DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16, 6); \
7425 DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32, 11); \
7426 DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32, 11); \
7427 DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64, 20); \
7428 DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64, 20)
7430 #define DO_TYPE(NAME, Name, hex, dec, max) GElf_##Name Name[count]
7431 union { TYPES; } value;
7434 void *data = &value;
7435 size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
7436 size_t convsize = size;
7437 if (repeated_size != NULL)
7439 if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
7441 data = alloca (*repeated_size);
7442 count *= *repeated_size / size;
7443 convsize = count * size;
7444 *repeated_size -= convsize;
7446 else if (item->count != 0 || item->format != '\n')
7447 *repeated_size -= size;
7450 convert (core, item->type, count, data, desc + item->offset, convsize);
7452 Elf_Type type = item->type;
7453 if (type == ELF_T_ADDR)
7454 type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
7456 switch (item->format)
7459 assert (count == 1);
7462 #define DO_TYPE(NAME, Name, hex, dec, max) \
7463 case ELF_T_##NAME: \
7464 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, \
7465 0, item->name, max, dec, value.Name[0]); \
7475 assert (count == 1);
7478 #define DO_TYPE(NAME, Name, hex, dec, max) \
7479 case ELF_T_##NAME: \
7480 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, \
7481 0, item->name, max, hex, value.Name[0]); \
7492 assert (size % sizeof (unsigned int) == 0);
7493 unsigned int nbits = count * size * 8;
7494 unsigned int pop = 0;
7495 for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
7496 pop += __builtin_popcount (*i);
7497 bool negate = pop > nbits / 2;
7498 const unsigned int bias = item->format == 'b';
7501 char printed[(negate ? nbits - pop : pop) * 16];
7505 if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
7507 assert (size == sizeof (unsigned int) * 2);
7508 for (unsigned int *i = data;
7509 (void *) i < data + count * size; i += 2)
7511 unsigned int w = i[1];
7517 unsigned int lastbit = 0;
7518 for (const unsigned int *i = data;
7519 (void *) i < data + count * size; ++i)
7521 unsigned int bit = ((void *) i - data) * 8;
7522 unsigned int w = negate ? ~*i : *i;
7523 unsigned int run = 0;
7530 if (lastbit + 1 == bit)
7535 p += sprintf (p, "%u", bit - bias);
7537 p += sprintf (p, ",%u", bit - bias);
7539 p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
7546 if (lastbit > 0 && lastbit + 1 != nbits)
7547 p += sprintf (p, "-%u", nbits - bias);
7549 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7551 negate ? "~<%s>" : "<%s>", printed);
7556 case (char) ('T'|0x80):
7557 assert (count == 2);
7563 #define DO_TYPE(NAME, Name, hex, dec, max) \
7564 case ELF_T_##NAME: \
7565 sec = value.Name[0]; \
7566 usec = value.Name[1]; \
7574 if (unlikely (item->format == (char) ('T'|0x80)))
7576 /* This is a hack for an ill-considered 64-bit ABI where
7577 tv_usec is actually a 32-bit field with 32 bits of padding
7578 rounding out struct timeval. We've already converted it as
7579 a 64-bit field. For little-endian, this just means the
7580 high half is the padding; it's presumably zero, but should
7581 be ignored anyway. For big-endian, it means the 32-bit
7582 field went into the high half of USEC. */
7584 GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
7585 if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
7590 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7591 maxfmt, "%" PRIu64 ".%.6" PRIu64, sec, usec);
7595 assert (count == 1);
7596 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7597 1, "%c", value.Byte[0]);
7601 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7602 count, "%.*s", (int) count, value.Byte);
7606 /* This is a list of strings separated by '\n'. */
7607 assert (item->count == 0);
7608 assert (repeated_size != NULL);
7609 assert (item->name == NULL);
7610 if (unlikely (item->offset >= *repeated_size))
7613 const char *s = desc + item->offset;
7614 size = *repeated_size - item->offset;
7618 const char *eol = memchr (s, '\n', size);
7622 printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
7625 size -= eol + 1 - s;
7629 colno = ITEM_WRAP_COLUMN;
7633 error (0, 0, "XXX not handling format '%c' for %s",
7634 item->format, item->name);
7644 /* Sort items by group, and by layout offset within each group. */
7646 compare_core_items (const void *a, const void *b)
7648 const Ebl_Core_Item *const *p1 = a;
7649 const Ebl_Core_Item *const *p2 = b;
7650 const Ebl_Core_Item *item1 = *p1;
7651 const Ebl_Core_Item *item2 = *p2;
7653 return ((item1->group == item2->group ? 0
7654 : strcmp (item1->group, item2->group))
7655 ?: (int) item1->offset - (int) item2->offset);
7658 /* Sort item groups by layout offset of the first item in the group. */
7660 compare_core_item_groups (const void *a, const void *b)
7662 const Ebl_Core_Item *const *const *p1 = a;
7663 const Ebl_Core_Item *const *const *p2 = b;
7664 const Ebl_Core_Item *const *group1 = *p1;
7665 const Ebl_Core_Item *const *group2 = *p2;
7666 const Ebl_Core_Item *item1 = *group1;
7667 const Ebl_Core_Item *item2 = *group2;
7669 return (int) item1->offset - (int) item2->offset;
7673 handle_core_items (Elf *core, const void *desc, size_t descsz,
7674 const Ebl_Core_Item *items, size_t nitems)
7679 /* Sort to collect the groups together. */
7680 const Ebl_Core_Item *sorted_items[nitems];
7681 for (size_t i = 0; i < nitems; ++i)
7682 sorted_items[i] = &items[i];
7683 qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
7685 /* Collect the unique groups and sort them. */
7686 const Ebl_Core_Item **groups[nitems];
7687 groups[0] = &sorted_items[0];
7689 for (size_t i = 1; i < nitems; ++i)
7690 if (sorted_items[i]->group != sorted_items[i - 1]->group
7691 && strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
7692 groups[ngroups++] = &sorted_items[i];
7693 qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
7695 /* Write out all the groups. */
7696 unsigned int colno = 0;
7698 const void *last = desc;
7701 size_t size = descsz;
7702 colno = handle_core_item (core, sorted_items[0], desc, colno, &size);
7705 desc += descsz - size;
7711 for (size_t i = 0; i < ngroups; ++i)
7713 for (const Ebl_Core_Item **item = groups[i];
7714 (item < &sorted_items[nitems]
7715 && ((*item)->group == groups[i][0]->group
7716 || !strcmp ((*item)->group, groups[i][0]->group)));
7718 colno = handle_core_item (core, *item, desc, colno, NULL);
7720 /* Force a line break at the end of the group. */
7721 colno = ITEM_WRAP_COLUMN;
7727 /* This set of items consumed a certain amount of the note's data.
7728 If there is more data there, we have another unit of the same size.
7729 Loop to print that out too. */
7730 const Ebl_Core_Item *item = &items[nitems - 1];
7731 size_t eltsz = item->offset + gelf_fsize (core, item->type,
7732 item->count ?: 1, EV_CURRENT);
7741 while (descsz >= eltsz && !memcmp (desc, last, eltsz));
7745 /* For just one repeat, print it unabridged twice. */
7750 printf (gettext ("\n%*s... <repeats %u more times> ..."),
7751 ITEM_INDENT, "", reps);
7761 handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
7764 desc += regloc->offset;
7772 handle_core_register (Ebl *ebl, Elf *core, int maxregname,
7773 const Ebl_Register_Location *regloc, const void *desc,
7776 if (regloc->bits % 8 != 0)
7777 return handle_bit_registers (regloc, desc, colno);
7779 desc += regloc->offset;
7781 for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
7783 char name[REGNAMESZ];
7786 register_info (ebl, reg, regloc, name, &bits, &type);
7789 BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8, 4); \
7790 BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16, 6); \
7791 BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32, 11); \
7792 BITS (64, XWORD, "%20" PRId64, " 0x%.16" PRIx64, 20)
7794 #define BITS(bits, xtype, sfmt, ufmt, max) \
7795 uint##bits##_t b##bits; int##bits##_t b##bits##s
7796 union { TYPES; uint64_t b128[2]; } value;
7801 case DW_ATE_unsigned:
7803 case DW_ATE_address:
7806 #define BITS(bits, xtype, sfmt, ufmt, max) \
7808 desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0); \
7809 if (type == DW_ATE_signed) \
7810 colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, \
7812 max, sfmt, value.b##bits##s); \
7814 colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, \
7816 max, ufmt, value.b##bits); \
7822 assert (type == DW_ATE_unsigned);
7823 desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
7824 int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
7825 colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
7827 34, "0x%.16" PRIx64 "%.16" PRIx64,
7828 value.b128[!be], value.b128[be]);
7838 /* Print each byte in hex, the whole thing in native byte order. */
7839 assert (bits % 8 == 0);
7840 const uint8_t *bytes = desc;
7842 char hex[bits / 4 + 1];
7843 hex[bits / 4] = '\0';
7845 if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
7847 bytes += bits / 8 - 1;
7851 for (char *h = hex; bits > 0; bits -= 8, idx += incr)
7853 *h++ = "0123456789abcdef"[bytes[idx] >> 4];
7854 *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
7856 colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
7858 2 + sizeof hex - 1, "0x%s", hex);
7861 desc += regloc->pad;
7870 struct register_info
7872 const Ebl_Register_Location *regloc;
7874 char name[REGNAMESZ];
7881 register_bitpos (const struct register_info *r)
7883 return (r->regloc->offset * 8
7884 + ((r->regno - r->regloc->regno)
7885 * (r->regloc->bits + r->regloc->pad * 8)));
7889 compare_sets_by_info (const struct register_info *r1,
7890 const struct register_info *r2)
7892 return ((int) r2->bits - (int) r1->bits
7893 ?: register_bitpos (r1) - register_bitpos (r2));
7896 /* Sort registers by set, and by size and layout offset within each set. */
7898 compare_registers (const void *a, const void *b)
7900 const struct register_info *r1 = a;
7901 const struct register_info *r2 = b;
7903 /* Unused elements sort last. */
7904 if (r1->regloc == NULL)
7905 return r2->regloc == NULL ? 0 : 1;
7906 if (r2->regloc == NULL)
7909 return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
7910 ?: compare_sets_by_info (r1, r2));
7913 /* Sort register sets by layout offset of the first register in the set. */
7915 compare_register_sets (const void *a, const void *b)
7917 const struct register_info *const *p1 = a;
7918 const struct register_info *const *p2 = b;
7919 return compare_sets_by_info (*p1, *p2);
7923 handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
7924 const Ebl_Register_Location *reglocs, size_t nregloc)
7929 ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
7932 for (size_t i = 0; i < nregloc; ++i)
7933 if (maxnreg < reglocs[i].regno + reglocs[i].count)
7934 maxnreg = reglocs[i].regno + reglocs[i].count;
7935 assert (maxnreg > 0);
7938 struct register_info regs[maxnreg];
7939 memset (regs, 0, sizeof regs);
7941 /* Sort to collect the sets together. */
7943 for (size_t i = 0; i < nregloc; ++i)
7944 for (int reg = reglocs[i].regno;
7945 reg < reglocs[i].regno + reglocs[i].count;
7948 assert (reg < maxnreg);
7951 struct register_info *info = ®s[reg];
7952 info->regloc = ®locs[i];
7954 info->set = register_info (ebl, reg, ®locs[i],
7955 info->name, &info->bits, &info->type);
7957 qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
7959 /* Collect the unique sets and sort them. */
7960 inline bool same_set (const struct register_info *a,
7961 const struct register_info *b)
7963 return (a < ®s[maxnreg] && a->regloc != NULL
7964 && b < ®s[maxnreg] && b->regloc != NULL
7965 && a->bits == b->bits
7966 && (a->set == b->set || !strcmp (a->set, b->set)));
7968 struct register_info *sets[maxreg + 1];
7971 for (int i = 1; i <= maxreg; ++i)
7972 if (regs[i].regloc != NULL && !same_set (®s[i], ®s[i - 1]))
7973 sets[nsets++] = ®s[i];
7974 qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
7976 /* Write out all the sets. */
7977 unsigned int colno = 0;
7978 for (size_t i = 0; i < nsets; ++i)
7980 /* Find the longest name of a register in this set. */
7982 const struct register_info *end;
7983 for (end = sets[i]; same_set (sets[i], end); ++end)
7985 size_t len = strlen (end->name);
7990 for (const struct register_info *reg = sets[i];
7992 reg += reg->regloc->count ?: 1)
7993 colno = handle_core_register (ebl, core, maxname,
7994 reg->regloc, desc, colno);
7996 /* Force a line break at the end of the group. */
7997 colno = REGISTER_WRAP_COLUMN;
8004 handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
8006 Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
8009 error (EXIT_FAILURE, 0,
8010 gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
8012 const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
8013 for (size_t i = 0; i < nauxv; ++i)
8016 GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
8022 if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
8025 if (av->a_un.a_val == 0)
8026 printf (" %" PRIu64 "\n", av->a_type);
8028 printf (" %" PRIu64 ": %#" PRIx64 "\n",
8029 av->a_type, av->a_un.a_val);
8034 case '\0': /* Normally zero. */
8035 if (av->a_un.a_val == 0)
8037 printf (" %s\n", name);
8042 case 'p': /* address */
8043 case 's': /* address of string */
8044 printf (" %s: %#" PRIx64 "\n", name, av->a_un.a_val);
8047 printf (" %s: %" PRIu64 "\n", name, av->a_un.a_val);
8050 printf (" %s: %" PRId64 "\n", name, av->a_un.a_val);
8054 printf (" %s: %#" PRIx64 " ", name, av->a_un.a_val);
8056 const char *pfx = "<";
8057 for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
8059 if (av->a_un.a_val & bit)
8061 printf ("%s%s", pfx, p);
8076 handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
8077 const char *name, const void *desc)
8079 GElf_Word regs_offset;
8081 const Ebl_Register_Location *reglocs;
8083 const Ebl_Core_Item *items;
8085 if (! ebl_core_note (ebl, nhdr, name,
8086 ®s_offset, &nregloc, ®locs, &nitems, &items))
8089 /* Pass 0 for DESCSZ when there are registers in the note,
8090 so that the ITEMS array does not describe the whole thing.
8091 For non-register notes, the actual descsz might be a multiple
8092 of the unit size, not just exactly the unit size. */
8093 unsigned int colno = handle_core_items (ebl->elf, desc,
8094 nregloc == 0 ? nhdr->n_descsz : 0,
8097 putchar_unlocked ('\n');
8099 colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
8102 putchar_unlocked ('\n');
8106 handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
8107 GElf_Off start, Elf_Data *data)
8109 fputs_unlocked (gettext (" Owner Data size Type\n"), stdout);
8118 while (offset < data->d_size
8119 && (offset = gelf_getnote (data, offset,
8120 &nhdr, &name_offset, &desc_offset)) > 0)
8122 const char *name = data->d_buf + name_offset;
8123 const char *desc = data->d_buf + desc_offset;
8127 printf (gettext (" %-13.*s %9" PRId32 " %s\n"),
8128 (int) nhdr.n_namesz, name, nhdr.n_descsz,
8129 ehdr->e_type == ET_CORE
8130 ? ebl_core_note_type_name (ebl, nhdr.n_type,
8132 : ebl_object_note_type_name (ebl, name, nhdr.n_type,
8133 buf2, sizeof (buf2)));
8135 /* Filter out invalid entries. */
8136 if (memchr (name, '\0', nhdr.n_namesz) != NULL
8137 /* XXX For now help broken Linux kernels. */
8140 if (ehdr->e_type == ET_CORE)
8142 if (nhdr.n_type == NT_AUXV
8143 && (nhdr.n_namesz == 4 /* Broken old Linux kernels. */
8144 || (nhdr.n_namesz == 5 && name[4] == '\0'))
8145 && !memcmp (name, "CORE", 4))
8146 handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
8147 start + desc_offset);
8149 handle_core_note (ebl, &nhdr, name, desc);
8152 ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc);
8156 if (offset == data->d_size)
8160 error (EXIT_FAILURE, 0,
8161 gettext ("cannot get content of note section: %s"),
8166 handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
8168 /* If we have section headers, just look for SHT_NOTE sections.
8169 In a debuginfo file, the program headers are not reliable. */
8172 /* Get the section header string table index. */
8174 if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
8175 error (EXIT_FAILURE, 0,
8176 gettext ("cannot get section header string table index"));
8178 Elf_Scn *scn = NULL;
8179 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
8182 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
8184 if (shdr == NULL || shdr->sh_type != SHT_NOTE)
8185 /* Not what we are looking for. */
8189 \nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
8191 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
8192 shdr->sh_size, shdr->sh_offset);
8194 handle_notes_data (ebl, ehdr, shdr->sh_offset,
8195 elf_getdata (scn, NULL));
8200 /* We have to look through the program header to find the note
8201 sections. There can be more than one. */
8202 for (size_t cnt = 0; cnt < phnum; ++cnt)
8205 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
8207 if (phdr == NULL || phdr->p_type != PT_NOTE)
8208 /* Not what we are looking for. */
8212 \nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
8213 phdr->p_filesz, phdr->p_offset);
8215 handle_notes_data (ebl, ehdr, phdr->p_offset,
8216 elf_getdata_rawchunk (ebl->elf,
8217 phdr->p_offset, phdr->p_filesz,
8224 hex_dump (const uint8_t *data, size_t len)
8229 printf (" 0x%08Zx ", pos);
8231 const size_t chunk = MIN (len - pos, 16);
8233 for (size_t i = 0; i < chunk; ++i)
8235 printf ("%02x ", data[pos + i]);
8237 printf ("%02x", data[pos + i]);
8240 printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
8242 for (size_t i = 0; i < chunk; ++i)
8244 unsigned char b = data[pos + i];
8245 printf ("%c", isprint (b) ? b : '.');
8254 dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
8256 if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
8257 printf (gettext ("\nSection [%Zu] '%s' has no data to dump.\n"),
8258 elf_ndxscn (scn), name);
8261 Elf_Data *data = elf_rawdata (scn, NULL);
8263 error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
8264 elf_ndxscn (scn), name, elf_errmsg (-1));
8267 printf (gettext ("\nHex dump of section [%Zu] '%s', %" PRIu64
8268 " bytes at offset %#0" PRIx64 ":\n"),
8269 elf_ndxscn (scn), name,
8270 shdr->sh_size, shdr->sh_offset);
8271 hex_dump (data->d_buf, data->d_size);
8277 print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
8279 if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
8280 printf (gettext ("\nSection [%Zu] '%s' has no strings to dump.\n"),
8281 elf_ndxscn (scn), name);
8284 Elf_Data *data = elf_rawdata (scn, NULL);
8286 error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
8287 elf_ndxscn (scn), name, elf_errmsg (-1));
8290 printf (gettext ("\nString section [%Zu] '%s' contains %" PRIu64
8291 " bytes at offset %#0" PRIx64 ":\n"),
8292 elf_ndxscn (scn), name,
8293 shdr->sh_size, shdr->sh_offset);
8295 const char *start = data->d_buf;
8296 const char *const limit = start + data->d_size;
8299 const char *end = memchr (start, '\0', limit - start);
8300 const size_t pos = start - (const char *) data->d_buf;
8301 if (unlikely (end == NULL))
8303 printf (" [%6Zx]- %.*s\n",
8304 pos, (int) (limit - start), start);
8307 printf (" [%6Zx] %s\n", pos, start);
8309 } while (start < limit);
8315 for_each_section_argument (Elf *elf, const struct section_argument *list,
8316 void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
8319 /* Get the section header string table index. */
8321 if (elf_getshdrstrndx (elf, &shstrndx) < 0)
8322 error (EXIT_FAILURE, 0,
8323 gettext ("cannot get section header string table index"));
8325 for (const struct section_argument *a = list; a != NULL; a = a->next)
8329 const char *name = NULL;
8332 unsigned long int shndx = strtoul (a->arg, &endp, 0);
8333 if (endp != a->arg && *endp == '\0')
8335 scn = elf_getscn (elf, shndx);
8338 error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
8342 if (gelf_getshdr (scn, &shdr_mem) == NULL)
8343 error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
8345 name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
8349 /* Need to look up the section by name. */
8352 while ((scn = elf_nextscn (elf, scn)) != NULL)
8354 if (gelf_getshdr (scn, &shdr_mem) == NULL)
8356 name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
8359 if (!strcmp (name, a->arg))
8362 (*dump) (scn, &shdr_mem, name);
8366 if (unlikely (!found) && !a->implicit)
8367 error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
8373 dump_data (Ebl *ebl)
8375 for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
8379 dump_strings (Ebl *ebl)
8381 for_each_section_argument (ebl->elf, string_sections, &print_string_section);
8385 print_strings (Ebl *ebl)
8387 /* Get the section header string table index. */
8389 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
8390 error (EXIT_FAILURE, 0,
8391 gettext ("cannot get section header string table index"));
8397 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
8399 if (gelf_getshdr (scn, &shdr_mem) == NULL)
8402 if (shdr_mem.sh_type != SHT_PROGBITS
8403 || !(shdr_mem.sh_flags & SHF_STRINGS))
8406 name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
8410 print_string_section (scn, &shdr_mem, name);
8415 dump_archive_index (Elf *elf, const char *fname)
8418 const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
8421 int result = elf_errno ();
8422 if (unlikely (result != ELF_E_NO_INDEX))
8423 error (EXIT_FAILURE, 0,
8424 gettext ("cannot get symbol index of archive '%s': %s"),
8425 fname, elf_errmsg (result));
8427 printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
8431 printf (gettext ("\nIndex of archive '%s' has %Zu entries:\n"),
8435 for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
8437 if (s->as_off != as_off)
8442 if (unlikely (elf_rand (elf, as_off) == 0)
8443 || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
8445 #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
8448 error (EXIT_FAILURE, 0,
8449 gettext ("cannot extract member at offset %Zu in '%s': %s"),
8450 as_off, fname, elf_errmsg (-1));
8452 const Elf_Arhdr *h = elf_getarhdr (subelf);
8454 printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
8459 printf ("\t%s\n", s->as_name);
8463 #include "debugpred.h"