Line data Source code
1 : /* Print information from ELF file in human-readable form.
2 : Copyright (C) 1999-2018 Red Hat, Inc.
3 : This file is part of elfutils.
4 :
5 : This file is free software; you can redistribute it and/or modify
6 : it under the terms of the GNU General Public License as published by
7 : the Free Software Foundation; either version 3 of the License, or
8 : (at your option) any later version.
9 :
10 : elfutils is distributed in the hope that it will be useful, but
11 : WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : GNU General Public License for more details.
14 :
15 : You should have received a copy of the GNU General Public License
16 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 :
18 : #ifdef HAVE_CONFIG_H
19 : # include <config.h>
20 : #endif
21 :
22 : #include <argp.h>
23 : #include <assert.h>
24 : #include <ctype.h>
25 : #include <dwarf.h>
26 : #include <errno.h>
27 : #include <fcntl.h>
28 : #include <gelf.h>
29 : #include <inttypes.h>
30 : #include <langinfo.h>
31 : #include <libdw.h>
32 : #include <libdwfl.h>
33 : #include <libintl.h>
34 : #include <locale.h>
35 : #include <stdarg.h>
36 : #include <stdbool.h>
37 : #include <stdio.h>
38 : #include <stdio_ext.h>
39 : #include <stdlib.h>
40 : #include <string.h>
41 : #include <strings.h>
42 : #include <time.h>
43 : #include <unistd.h>
44 : #include <sys/stat.h>
45 : #include <signal.h>
46 :
47 : #include <libeu.h>
48 : #include <system.h>
49 : #include <printversion.h>
50 : #include "../libelf/libelfP.h"
51 : #include "../libelf/common.h"
52 : #include "../libebl/libeblP.h"
53 : #include "../libdwelf/libdwelf.h"
54 : #include "../libdw/libdwP.h"
55 : #include "../libdwfl/libdwflP.h"
56 : #include "../libdw/memory-access.h"
57 :
58 : #include "../libdw/known-dwarf.h"
59 :
60 : #ifdef __linux__
61 : #define CORE_SIGILL SIGILL
62 : #define CORE_SIGBUS SIGBUS
63 : #define CORE_SIGFPE SIGFPE
64 : #define CORE_SIGSEGV SIGSEGV
65 : #define CORE_SI_USER SI_USER
66 : #else
67 : /* We want the linux version of those as that is what shows up in the core files. */
68 : #define CORE_SIGILL 4 /* Illegal instruction (ANSI). */
69 : #define CORE_SIGBUS 7 /* BUS error (4.2 BSD). */
70 : #define CORE_SIGFPE 8 /* Floating-point exception (ANSI). */
71 : #define CORE_SIGSEGV 11 /* Segmentation violation (ANSI). */
72 : #define CORE_SI_USER 0 /* Sent by kill, sigsend. */
73 : #endif
74 :
75 : /* Name and version of program. */
76 : ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
77 :
78 : /* Bug report address. */
79 : ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
80 :
81 : /* argp key value for --elf-section, non-ascii. */
82 : #define ELF_INPUT_SECTION 256
83 :
84 : /* argp key value for --dwarf-skeleton, non-ascii. */
85 : #define DWARF_SKELETON 257
86 :
87 : /* Terrible hack for hooking unrelated skeleton/split compile units,
88 : see __libdw_link_skel_split in print_debug. */
89 : static bool do_not_close_dwfl = false;
90 :
91 : /* Definitions of arguments for argp functions. */
92 : static const struct argp_option options[] =
93 : {
94 : { NULL, 0, NULL, 0, N_("ELF input selection:"), 0 },
95 : { "elf-section", ELF_INPUT_SECTION, "SECTION", OPTION_ARG_OPTIONAL,
96 : N_("Use the named SECTION (default .gnu_debugdata) as (compressed) ELF "
97 : "input data"), 0 },
98 : { "dwarf-skeleton", DWARF_SKELETON, "FILE", 0,
99 : N_("Used with -w to find the skeleton Compile Units in FILE associated "
100 : "with the Split Compile units in a .dwo input file"), 0 },
101 : { NULL, 0, NULL, 0, N_("ELF output selection:"), 0 },
102 : { "all", 'a', NULL, 0,
103 : N_("All these plus -p .strtab -p .dynstr -p .comment"), 0 },
104 : { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
105 : { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
106 : { "histogram", 'I', NULL, 0,
107 : N_("Display histogram of bucket list lengths"), 0 },
108 : { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
109 : { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
110 : { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
111 : { "section-groups", 'g', NULL, 0, N_("Display the section groups"), 0 },
112 : { "section-headers", 'S', NULL, 0, N_("Display the sections' headers"), 0 },
113 : { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
114 : { "symbols", 's', "SECTION", OPTION_ARG_OPTIONAL,
115 : N_("Display the symbol table sections"), 0 },
116 : { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
117 : { "notes", 'n', NULL, 0, N_("Display the ELF notes"), 0 },
118 : { "arch-specific", 'A', NULL, 0,
119 : N_("Display architecture specific information, if any"), 0 },
120 : { "exception", 'e', NULL, 0,
121 : N_("Display sections for exception handling"), 0 },
122 :
123 : { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 },
124 : { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
125 : N_("Display DWARF section content. SECTION can be one of abbrev, addr, "
126 : "aranges, decodedaranges, frame, gdb_index, info, info+, loc, line, "
127 : "decodedline, ranges, pubnames, str, macinfo, macro or exception"), 0 },
128 : { "hex-dump", 'x', "SECTION", 0,
129 : N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
130 : { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
131 : N_("Print string contents of sections"), 0 },
132 : { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
133 : { "archive-index", 'c', NULL, 0,
134 : N_("Display the symbol index of an archive"), 0 },
135 :
136 : { NULL, 0, NULL, 0, N_("Output control:"), 0 },
137 : { "numeric-addresses", 'N', NULL, 0,
138 : N_("Do not find symbol names for addresses in DWARF data"), 0 },
139 : { "unresolved-address-offsets", 'U', NULL, 0,
140 : N_("Display just offsets instead of resolving values to addresses in DWARF data"), 0 },
141 : { "wide", 'W', NULL, 0,
142 : N_("Ignored for compatibility (lines always wide)"), 0 },
143 : { "decompress", 'z', NULL, 0,
144 : N_("Show compression information for compressed sections (when used with -S); decompress section before dumping data (when used with -p or -x)"), 0 },
145 : { NULL, 0, NULL, 0, NULL, 0 }
146 : };
147 :
148 : /* Short description of program. */
149 : static const char doc[] = N_("\
150 : Print information from ELF file in human-readable form.");
151 :
152 : /* Strings for arguments in help texts. */
153 : static const char args_doc[] = N_("FILE...");
154 :
155 : /* Prototype for option handler. */
156 : static error_t parse_opt (int key, char *arg, struct argp_state *state);
157 :
158 : /* Data structure to communicate with argp functions. */
159 : static struct argp argp =
160 : {
161 : options, parse_opt, args_doc, doc, NULL, NULL, NULL
162 : };
163 :
164 : /* If non-null, the section from which we should read to (compressed) ELF. */
165 : static const char *elf_input_section = NULL;
166 :
167 : /* If non-null, the file that contains the skeleton CUs. */
168 : static const char *dwarf_skeleton = NULL;
169 :
170 : /* Flags set by the option controlling the output. */
171 :
172 : /* True if dynamic segment should be printed. */
173 : static bool print_dynamic_table;
174 :
175 : /* True if the file header should be printed. */
176 : static bool print_file_header;
177 :
178 : /* True if the program headers should be printed. */
179 : static bool print_program_header;
180 :
181 : /* True if relocations should be printed. */
182 : static bool print_relocations;
183 :
184 : /* True if the section headers should be printed. */
185 : static bool print_section_header;
186 :
187 : /* True if the symbol table should be printed. */
188 : static bool print_symbol_table;
189 :
190 : /* A specific section name, or NULL to print all symbol tables. */
191 : static char *symbol_table_section;
192 :
193 : /* True if the version information should be printed. */
194 : static bool print_version_info;
195 :
196 : /* True if section groups should be printed. */
197 : static bool print_section_groups;
198 :
199 : /* True if bucket list length histogram should be printed. */
200 : static bool print_histogram;
201 :
202 : /* True if the architecture specific data should be printed. */
203 : static bool print_arch;
204 :
205 : /* True if note section content should be printed. */
206 : static bool print_notes;
207 :
208 : /* True if SHF_STRINGS section content should be printed. */
209 : static bool print_string_sections;
210 :
211 : /* True if archive index should be printed. */
212 : static bool print_archive_index;
213 :
214 : /* True if any of the control options except print_archive_index is set. */
215 : static bool any_control_option;
216 :
217 : /* True if we should print addresses from DWARF in symbolic form. */
218 : static bool print_address_names = true;
219 :
220 : /* True if we should print raw values instead of relativized addresses. */
221 : static bool print_unresolved_addresses = false;
222 :
223 : /* True if we should print the .debug_aranges section using libdw. */
224 : static bool decodedaranges = false;
225 :
226 : /* True if we should print the .debug_aranges section using libdw. */
227 : static bool decodedline = false;
228 :
229 : /* True if we want to show more information about compressed sections. */
230 : static bool print_decompress = false;
231 :
232 : /* True if we want to show split compile units for debug_info skeletons. */
233 : static bool show_split_units = false;
234 :
235 : /* Select printing of debugging sections. */
236 : static enum section_e
237 : {
238 : section_abbrev = 1, /* .debug_abbrev */
239 : section_aranges = 2, /* .debug_aranges */
240 : section_frame = 4, /* .debug_frame or .eh_frame & al. */
241 : section_info = 8, /* .debug_info, (implies .debug_types) */
242 : section_line = 16, /* .debug_line */
243 : section_loc = 32, /* .debug_loc */
244 : section_pubnames = 64, /* .debug_pubnames */
245 : section_str = 128, /* .debug_str */
246 : section_macinfo = 256, /* .debug_macinfo */
247 : section_ranges = 512, /* .debug_ranges */
248 : section_exception = 1024, /* .eh_frame & al. */
249 : section_gdb_index = 2048, /* .gdb_index */
250 : section_macro = 4096, /* .debug_macro */
251 : section_addr = 8192, /* .debug_addr */
252 : section_types = 16384, /* .debug_types (implied by .debug_info) */
253 : section_all = (section_abbrev | section_aranges | section_frame
254 : | section_info | section_line | section_loc
255 : | section_pubnames | section_str | section_macinfo
256 : | section_ranges | section_exception | section_gdb_index
257 : | section_macro | section_addr | section_types)
258 : } print_debug_sections, implicit_debug_sections;
259 :
260 : /* Select hex dumping of sections. */
261 : static struct section_argument *dump_data_sections;
262 : static struct section_argument **dump_data_sections_tail = &dump_data_sections;
263 :
264 : /* Select string dumping of sections. */
265 : static struct section_argument *string_sections;
266 : static struct section_argument **string_sections_tail = &string_sections;
267 :
268 : struct section_argument
269 : {
270 : struct section_argument *next;
271 : const char *arg;
272 : bool implicit;
273 : };
274 :
275 : /* Numbers of sections and program headers in the file. */
276 : static size_t shnum;
277 : static size_t phnum;
278 :
279 :
280 : /* Declarations of local functions. */
281 : static void process_file (int fd, const char *fname, bool only_one);
282 : static void process_elf_file (Dwfl_Module *dwflmod, int fd);
283 : static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
284 : static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
285 : static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
286 : static void print_scngrp (Ebl *ebl);
287 : static void print_dynamic (Ebl *ebl);
288 : static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
289 : static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
290 : GElf_Shdr *shdr);
291 : static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
292 : GElf_Shdr *shdr);
293 : static void print_symtab (Ebl *ebl, int type);
294 : static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
295 : static void print_verinfo (Ebl *ebl);
296 : static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
297 : static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
298 : static void handle_versym (Ebl *ebl, Elf_Scn *scn,
299 : GElf_Shdr *shdr);
300 : static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
301 : static void handle_hash (Ebl *ebl);
302 : static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
303 : static void print_liblist (Ebl *ebl);
304 : static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
305 : static void dump_data (Ebl *ebl);
306 : static void dump_strings (Ebl *ebl);
307 : static void print_strings (Ebl *ebl);
308 : static void dump_archive_index (Elf *, const char *);
309 :
310 :
311 : /* Looked up once with gettext in main. */
312 : static char *yes_str;
313 : static char *no_str;
314 :
315 : int
316 285 : main (int argc, char *argv[])
317 : {
318 : /* We use no threads here which can interfere with handling a stream. */
319 285 : (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
320 :
321 : /* Set locale. */
322 285 : setlocale (LC_ALL, "");
323 :
324 : /* Initialize the message catalog. */
325 285 : textdomain (PACKAGE_TARNAME);
326 :
327 : /* Look up once. */
328 285 : yes_str = gettext ("yes");
329 285 : no_str = gettext ("no");
330 :
331 : /* Parse and process arguments. */
332 : int remaining;
333 285 : argp_parse (&argp, argc, argv, 0, &remaining, NULL);
334 :
335 : /* Before we start tell the ELF library which version we are using. */
336 285 : elf_version (EV_CURRENT);
337 :
338 : /* Now process all the files given at the command line. */
339 285 : bool only_one = remaining + 1 == argc;
340 : do
341 : {
342 : /* Open the file. */
343 582 : int fd = open (argv[remaining], O_RDONLY);
344 291 : if (fd == -1)
345 : {
346 0 : error (0, errno, gettext ("cannot open input file"));
347 0 : continue;
348 : }
349 :
350 291 : process_file (fd, argv[remaining], only_one);
351 :
352 291 : close (fd);
353 : }
354 291 : while (++remaining < argc);
355 :
356 285 : return error_message_count != 0;
357 : }
358 :
359 :
360 : /* Handle program arguments. */
361 : static error_t
362 1775 : parse_opt (int key, char *arg,
363 : struct argp_state *state __attribute__ ((unused)))
364 : {
365 126 : void add_dump_section (const char *name, bool implicit)
366 : {
367 126 : struct section_argument *a = xmalloc (sizeof *a);
368 126 : a->arg = name;
369 126 : a->next = NULL;
370 126 : a->implicit = implicit;
371 126 : struct section_argument ***tailp
372 126 : = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
373 126 : **tailp = a;
374 126 : *tailp = &a->next;
375 126 : }
376 :
377 1775 : switch (key)
378 : {
379 40 : case 'a':
380 40 : print_file_header = true;
381 40 : print_program_header = true;
382 40 : print_relocations = true;
383 40 : print_section_header = true;
384 40 : print_symbol_table = true;
385 40 : print_version_info = true;
386 40 : print_dynamic_table = true;
387 40 : print_section_groups = true;
388 40 : print_histogram = true;
389 40 : print_arch = true;
390 40 : print_notes = true;
391 40 : implicit_debug_sections |= section_exception;
392 40 : add_dump_section (".strtab", true);
393 40 : add_dump_section (".dynstr", true);
394 40 : add_dump_section (".comment", true);
395 40 : any_control_option = true;
396 40 : break;
397 4 : case 'A':
398 4 : print_arch = true;
399 4 : any_control_option = true;
400 4 : break;
401 2 : case 'd':
402 2 : print_dynamic_table = true;
403 2 : any_control_option = true;
404 2 : break;
405 0 : case 'e':
406 0 : print_debug_sections |= section_exception;
407 0 : any_control_option = true;
408 0 : break;
409 9 : case 'g':
410 9 : print_section_groups = true;
411 9 : any_control_option = true;
412 9 : break;
413 0 : case 'h':
414 0 : print_file_header = true;
415 0 : any_control_option = true;
416 0 : break;
417 0 : case 'I':
418 0 : print_histogram = true;
419 0 : any_control_option = true;
420 0 : break;
421 0 : case 'l':
422 0 : print_program_header = true;
423 0 : any_control_option = true;
424 0 : break;
425 20 : case 'n':
426 20 : print_notes = true;
427 20 : any_control_option = true;
428 20 : break;
429 1 : case 'r':
430 1 : print_relocations = true;
431 1 : any_control_option = true;
432 1 : break;
433 88 : case 'S':
434 88 : print_section_header = true;
435 88 : any_control_option = true;
436 88 : break;
437 14 : case 's':
438 14 : print_symbol_table = true;
439 14 : any_control_option = true;
440 14 : symbol_table_section = arg;
441 14 : break;
442 0 : case 'V':
443 0 : print_version_info = true;
444 0 : any_control_option = true;
445 0 : break;
446 2 : case 'c':
447 2 : print_archive_index = true;
448 2 : break;
449 114 : case 'w':
450 114 : if (arg == NULL)
451 : {
452 39 : print_debug_sections = section_all;
453 39 : implicit_debug_sections = section_info;
454 39 : show_split_units = true;
455 : }
456 75 : else if (strcmp (arg, "abbrev") == 0)
457 0 : print_debug_sections |= section_abbrev;
458 75 : else if (strcmp (arg, "addr") == 0)
459 : {
460 2 : print_debug_sections |= section_addr;
461 2 : implicit_debug_sections |= section_info;
462 : }
463 73 : else if (strcmp (arg, "aranges") == 0)
464 3 : print_debug_sections |= section_aranges;
465 70 : else if (strcmp (arg, "decodedaranges") == 0)
466 : {
467 1 : print_debug_sections |= section_aranges;
468 1 : decodedaranges = true;
469 : }
470 69 : else if (strcmp (arg, "ranges") == 0)
471 : {
472 12 : print_debug_sections |= section_ranges;
473 12 : implicit_debug_sections |= section_info;
474 : }
475 57 : else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
476 2 : print_debug_sections |= section_frame;
477 55 : else if (strcmp (arg, "info") == 0)
478 : {
479 17 : print_debug_sections |= section_info;
480 17 : print_debug_sections |= section_types;
481 : }
482 38 : else if (strcmp (arg, "info+") == 0)
483 : {
484 2 : print_debug_sections |= section_info;
485 2 : print_debug_sections |= section_types;
486 2 : show_split_units = true;
487 : }
488 36 : else if (strcmp (arg, "loc") == 0)
489 : {
490 18 : print_debug_sections |= section_loc;
491 18 : implicit_debug_sections |= section_info;
492 : }
493 18 : else if (strcmp (arg, "line") == 0)
494 6 : print_debug_sections |= section_line;
495 12 : else if (strcmp (arg, "decodedline") == 0)
496 : {
497 4 : print_debug_sections |= section_line;
498 4 : decodedline = true;
499 : }
500 8 : else if (strcmp (arg, "pubnames") == 0)
501 0 : print_debug_sections |= section_pubnames;
502 8 : else if (strcmp (arg, "str") == 0)
503 : {
504 3 : print_debug_sections |= section_str;
505 : /* For mapping string offset tables to CUs. */
506 3 : implicit_debug_sections |= section_info;
507 : }
508 5 : else if (strcmp (arg, "macinfo") == 0)
509 0 : print_debug_sections |= section_macinfo;
510 5 : else if (strcmp (arg, "macro") == 0)
511 3 : print_debug_sections |= section_macro;
512 2 : else if (strcmp (arg, "exception") == 0)
513 0 : print_debug_sections |= section_exception;
514 2 : else if (strcmp (arg, "gdb_index") == 0)
515 2 : print_debug_sections |= section_gdb_index;
516 : else
517 : {
518 0 : fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
519 : arg);
520 0 : argp_help (&argp, stderr, ARGP_HELP_SEE,
521 : program_invocation_short_name);
522 0 : exit (1);
523 : }
524 114 : any_control_option = true;
525 114 : break;
526 1 : case 'p':
527 1 : any_control_option = true;
528 1 : if (arg == NULL)
529 : {
530 0 : print_string_sections = true;
531 0 : break;
532 : }
533 : FALLTHROUGH;
534 : case 'x':
535 6 : add_dump_section (arg, false);
536 6 : any_control_option = true;
537 6 : break;
538 2 : case 'N':
539 2 : print_address_names = false;
540 2 : break;
541 26 : case 'U':
542 26 : print_unresolved_addresses = true;
543 26 : break;
544 0 : case ARGP_KEY_NO_ARGS:
545 0 : fputs (gettext ("Missing file name.\n"), stderr);
546 0 : goto do_argp_help;
547 285 : case ARGP_KEY_FINI:
548 285 : if (! any_control_option && ! print_archive_index)
549 : {
550 0 : fputs (gettext ("No operation specified.\n"), stderr);
551 0 : do_argp_help:
552 0 : argp_help (&argp, stderr, ARGP_HELP_SEE,
553 : program_invocation_short_name);
554 0 : exit (EXIT_FAILURE);
555 : }
556 : break;
557 : case 'W': /* Ignored. */
558 : break;
559 13 : case 'z':
560 13 : print_decompress = true;
561 13 : break;
562 4 : case ELF_INPUT_SECTION:
563 4 : if (arg == NULL)
564 4 : elf_input_section = ".gnu_debugdata";
565 : else
566 0 : elf_input_section = arg;
567 : break;
568 5 : case DWARF_SKELETON:
569 5 : dwarf_skeleton = arg;
570 5 : break;
571 : default:
572 : return ARGP_ERR_UNKNOWN;
573 : }
574 : return 0;
575 : }
576 :
577 :
578 : /* Create a file descriptor to read the data from the
579 : elf_input_section given a file descriptor to an ELF file. */
580 : static int
581 4 : open_input_section (int fd)
582 : {
583 : size_t shnums;
584 : size_t cnt;
585 : size_t shstrndx;
586 4 : Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
587 4 : if (elf == NULL)
588 : {
589 0 : error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
590 : elf_errmsg (-1));
591 0 : return -1;
592 : }
593 :
594 4 : if (elf_getshdrnum (elf, &shnums) < 0)
595 : {
596 0 : error (0, 0, gettext ("cannot determine number of sections: %s"),
597 : elf_errmsg (-1));
598 0 : open_error:
599 0 : elf_end (elf);
600 0 : return -1;
601 : }
602 :
603 4 : if (elf_getshdrstrndx (elf, &shstrndx) < 0)
604 : {
605 0 : error (0, 0, gettext ("cannot get section header string table index"));
606 : goto open_error;
607 : }
608 :
609 178 : for (cnt = 0; cnt < shnums; ++cnt)
610 : {
611 91 : Elf_Scn *scn = elf_getscn (elf, cnt);
612 91 : if (scn == NULL)
613 : {
614 0 : error (0, 0, gettext ("cannot get section: %s"),
615 : elf_errmsg (-1));
616 0 : goto open_error;
617 : }
618 :
619 : GElf_Shdr shdr_mem;
620 91 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
621 91 : if (unlikely (shdr == NULL))
622 : {
623 0 : error (0, 0, gettext ("cannot get section header: %s"),
624 : elf_errmsg (-1));
625 : goto open_error;
626 : }
627 :
628 91 : const char *sname = elf_strptr (elf, shstrndx, shdr->sh_name);
629 91 : if (sname == NULL)
630 : {
631 0 : error (0, 0, gettext ("cannot get section name"));
632 : goto open_error;
633 : }
634 :
635 91 : if (strcmp (sname, elf_input_section) == 0)
636 : {
637 4 : Elf_Data *data = elf_rawdata (scn, NULL);
638 4 : if (data == NULL)
639 : {
640 0 : error (0, 0, gettext ("cannot get %s content: %s"),
641 : sname, elf_errmsg (-1));
642 : goto open_error;
643 : }
644 :
645 : /* Create (and immediately unlink) a temporary file to store
646 : section data in to create a file descriptor for it. */
647 4 : const char *tmpdir = getenv ("TMPDIR") ?: P_tmpdir;
648 : static const char suffix[] = "/readelfXXXXXX";
649 4 : int tmplen = strlen (tmpdir) + sizeof (suffix);
650 4 : char *tempname = alloca (tmplen);
651 4 : sprintf (tempname, "%s%s", tmpdir, suffix);
652 :
653 4 : int sfd = mkstemp (tempname);
654 4 : if (sfd == -1)
655 : {
656 0 : error (0, 0, gettext ("cannot create temp file '%s'"),
657 : tempname);
658 : goto open_error;
659 : }
660 4 : unlink (tempname);
661 :
662 4 : ssize_t size = data->d_size;
663 4 : if (write_retry (sfd, data->d_buf, size) != size)
664 : {
665 0 : error (0, 0, gettext ("cannot write section data"));
666 : goto open_error;
667 : }
668 :
669 4 : if (elf_end (elf) != 0)
670 : {
671 0 : error (0, 0, gettext ("error while closing Elf descriptor: %s"),
672 : elf_errmsg (-1));
673 0 : return -1;
674 : }
675 :
676 4 : if (lseek (sfd, 0, SEEK_SET) == -1)
677 : {
678 0 : error (0, 0, gettext ("error while rewinding file descriptor"));
679 0 : return -1;
680 : }
681 :
682 : return sfd;
683 : }
684 : }
685 :
686 : /* Named section not found. */
687 0 : if (elf_end (elf) != 0)
688 0 : error (0, 0, gettext ("error while closing Elf descriptor: %s"),
689 : elf_errmsg (-1));
690 : return -1;
691 : }
692 :
693 : /* Check if the file is an archive, and if so dump its index. */
694 : static void
695 2 : check_archive_index (int fd, const char *fname, bool only_one)
696 : {
697 : /* Create an `Elf' descriptor. */
698 2 : Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
699 2 : if (elf == NULL)
700 0 : error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
701 : elf_errmsg (-1));
702 : else
703 : {
704 2 : if (elf_kind (elf) == ELF_K_AR)
705 : {
706 2 : if (!only_one)
707 : printf ("\n%s:\n\n", fname);
708 2 : dump_archive_index (elf, fname);
709 : }
710 : else
711 : error (0, 0,
712 0 : gettext ("'%s' is not an archive, cannot print archive index"),
713 : fname);
714 :
715 : /* Now we can close the descriptor. */
716 2 : if (elf_end (elf) != 0)
717 0 : error (0, 0, gettext ("error while closing Elf descriptor: %s"),
718 : elf_errmsg (-1));
719 : }
720 2 : }
721 :
722 : /* Trivial callback used for checking if we opened an archive. */
723 : static int
724 277 : count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
725 : void **userdata __attribute__ ((unused)),
726 : const char *name __attribute__ ((unused)),
727 : Dwarf_Addr base __attribute__ ((unused)),
728 : void *arg)
729 : {
730 277 : if (*(bool *) arg)
731 : return DWARF_CB_ABORT;
732 277 : *(bool *) arg = true;
733 277 : return DWARF_CB_OK;
734 : }
735 :
736 : struct process_dwflmod_args
737 : {
738 : int fd;
739 : bool only_one;
740 : };
741 :
742 : static int
743 289 : process_dwflmod (Dwfl_Module *dwflmod,
744 : void **userdata __attribute__ ((unused)),
745 : const char *name __attribute__ ((unused)),
746 : Dwarf_Addr base __attribute__ ((unused)),
747 : void *arg)
748 : {
749 289 : const struct process_dwflmod_args *a = arg;
750 :
751 : /* Print the file name. */
752 289 : if (!a->only_one)
753 : {
754 : const char *fname;
755 12 : dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
756 :
757 24 : printf ("\n%s:\n\n", fname);
758 : }
759 :
760 289 : process_elf_file (dwflmod, a->fd);
761 :
762 289 : return DWARF_CB_OK;
763 : }
764 :
765 : /* Stub libdwfl callback, only the ELF handle already open is ever used.
766 : Only used for finding the alternate debug file if the Dwarf comes from
767 : the main file. We are not interested in separate debuginfo. */
768 : static int
769 35 : find_no_debuginfo (Dwfl_Module *mod,
770 : void **userdata,
771 : const char *modname,
772 : Dwarf_Addr base,
773 : const char *file_name,
774 : const char *debuglink_file,
775 : GElf_Word debuglink_crc,
776 : char **debuginfo_file_name)
777 : {
778 : Dwarf_Addr dwbias;
779 35 : dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
780 :
781 : /* We are only interested if the Dwarf has been setup on the main
782 : elf file but is only missing the alternate debug link. If dwbias
783 : hasn't even been setup, this is searching for separate debuginfo
784 : for the main elf. We don't care in that case. */
785 35 : if (dwbias == (Dwarf_Addr) -1)
786 : return -1;
787 :
788 5 : return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
789 : file_name, debuglink_file,
790 : debuglink_crc, debuginfo_file_name);
791 : }
792 :
793 : static Dwfl *
794 298 : create_dwfl (int fd, const char *fname)
795 : {
796 : /* Duplicate an fd for dwfl_report_offline to swallow. */
797 298 : int dwfl_fd = dup (fd);
798 298 : if (unlikely (dwfl_fd < 0))
799 0 : error (EXIT_FAILURE, errno, "dup");
800 :
801 : /* Use libdwfl in a trivial way to open the libdw handle for us.
802 : This takes care of applying relocations to DWARF data in ET_REL files. */
803 : static const Dwfl_Callbacks callbacks =
804 : {
805 : .section_address = dwfl_offline_section_address,
806 : .find_debuginfo = find_no_debuginfo
807 : };
808 298 : Dwfl *dwfl = dwfl_begin (&callbacks);
809 298 : if (likely (dwfl != NULL))
810 : /* Let 0 be the logical address of the file (or first in archive). */
811 298 : dwfl->offline_next_address = 0;
812 298 : if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
813 : {
814 : struct stat st;
815 0 : if (fstat (dwfl_fd, &st) != 0)
816 0 : error (0, errno, gettext ("cannot stat input file"));
817 0 : else if (unlikely (st.st_size == 0))
818 0 : error (0, 0, gettext ("input file is empty"));
819 : else
820 0 : error (0, 0, gettext ("failed reading '%s': %s"),
821 : fname, dwfl_errmsg (-1));
822 0 : close (dwfl_fd); /* Consumed on success, not on failure. */
823 0 : dwfl = NULL;
824 : }
825 : else
826 298 : dwfl_report_end (dwfl, NULL, NULL);
827 :
828 298 : return dwfl;
829 : }
830 :
831 : /* Process one input file. */
832 : static void
833 291 : process_file (int fd, const char *fname, bool only_one)
834 : {
835 291 : if (print_archive_index)
836 2 : check_archive_index (fd, fname, only_one);
837 :
838 291 : if (!any_control_option)
839 : return;
840 :
841 289 : if (elf_input_section != NULL)
842 : {
843 : /* Replace fname and fd with section content. */
844 4 : char *fnname = alloca (strlen (fname) + strlen (elf_input_section) + 2);
845 8 : sprintf (fnname, "%s:%s", fname, elf_input_section);
846 4 : fd = open_input_section (fd);
847 4 : if (fd == -1)
848 : {
849 0 : error (0, 0, gettext ("No such section '%s' in '%s'"),
850 : elf_input_section, fname);
851 : return;
852 : }
853 : fname = fnname;
854 : }
855 :
856 289 : Dwfl *dwfl = create_dwfl (fd, fname);
857 289 : if (dwfl != NULL)
858 : {
859 289 : if (only_one)
860 : {
861 : /* Clear ONLY_ONE if we have multiple modules, from an archive. */
862 277 : bool seen = false;
863 277 : only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
864 : }
865 :
866 : /* Process the one or more modules gleaned from this file. */
867 289 : struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
868 289 : dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
869 : }
870 : /* Terrible hack for hooking unrelated skeleton/split compile units,
871 : see __libdw_link_skel_split in print_debug. */
872 289 : if (! do_not_close_dwfl)
873 289 : dwfl_end (dwfl);
874 :
875 : /* Need to close the replaced fd if we created it. Caller takes
876 : care of original. */
877 289 : if (elf_input_section != NULL)
878 4 : close (fd);
879 : }
880 :
881 : /* Check whether there are any compressed sections in the ELF file. */
882 : static bool
883 95 : elf_contains_chdrs (Elf *elf)
884 : {
885 95 : Elf_Scn *scn = NULL;
886 788827 : while ((scn = elf_nextscn (elf, scn)) != NULL)
887 : {
888 : GElf_Shdr shdr_mem;
889 788643 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
890 788643 : if (shdr != NULL && (shdr->sh_flags & SHF_COMPRESSED) != 0)
891 6 : return true;
892 : }
893 : return false;
894 : }
895 :
896 : /* Process one ELF file. */
897 : static void
898 289 : process_elf_file (Dwfl_Module *dwflmod, int fd)
899 : {
900 : GElf_Addr dwflbias;
901 289 : Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
902 :
903 : GElf_Ehdr ehdr_mem;
904 289 : GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
905 :
906 289 : if (ehdr == NULL)
907 : {
908 0 : error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
909 0 : return;
910 : }
911 :
912 289 : Ebl *ebl = ebl_openbackend (elf);
913 289 : if (unlikely (ebl == NULL))
914 : {
915 0 : ebl_error:
916 0 : error (0, errno, gettext ("cannot create EBL handle"));
917 : return;
918 : }
919 :
920 : /* Determine the number of sections. */
921 289 : if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
922 0 : error (EXIT_FAILURE, 0,
923 0 : gettext ("cannot determine number of sections: %s"),
924 : elf_errmsg (-1));
925 :
926 : /* Determine the number of phdrs. */
927 289 : if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
928 0 : error (EXIT_FAILURE, 0,
929 0 : gettext ("cannot determine number of program headers: %s"),
930 : elf_errmsg (-1));
931 :
932 : /* For an ET_REL file, libdwfl has adjusted the in-core shdrs and
933 : may have applied relocation to some sections. If there are any
934 : compressed sections, any pass (or libdw/libdwfl) might have
935 : uncompressed them. So we need to get a fresh Elf handle on the
936 : file to display those. */
937 578 : bool print_unchanged = ((print_section_header
938 161 : || print_relocations
939 160 : || dump_data_sections != NULL
940 155 : || print_notes)
941 443 : && (ehdr->e_type == ET_REL
942 95 : || elf_contains_chdrs (ebl->elf)));
943 :
944 289 : Elf *pure_elf = NULL;
945 289 : Ebl *pure_ebl = ebl;
946 289 : if (print_unchanged)
947 : {
948 : /* Read the file afresh. */
949 65 : off_t aroff = elf_getaroff (elf);
950 65 : pure_elf = dwelf_elf_begin (fd);
951 65 : if (aroff > 0)
952 : {
953 : /* Archive member. */
954 0 : (void) elf_rand (pure_elf, aroff);
955 0 : Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
956 0 : elf_end (pure_elf);
957 0 : pure_elf = armem;
958 : }
959 65 : if (pure_elf == NULL)
960 : {
961 0 : error (0, 0, gettext ("cannot read ELF: %s"), elf_errmsg (-1));
962 : return;
963 : }
964 65 : pure_ebl = ebl_openbackend (pure_elf);
965 65 : if (pure_ebl == NULL)
966 : goto ebl_error;
967 : }
968 :
969 289 : if (print_file_header)
970 40 : print_ehdr (ebl, ehdr);
971 289 : if (print_section_header)
972 128 : print_shdr (pure_ebl, ehdr);
973 289 : if (print_program_header)
974 40 : print_phdr (ebl, ehdr);
975 289 : if (print_section_groups)
976 49 : print_scngrp (ebl);
977 289 : if (print_dynamic_table)
978 42 : print_dynamic (ebl);
979 289 : if (print_relocations)
980 41 : print_relocs (pure_ebl, ehdr);
981 289 : if (print_histogram)
982 40 : handle_hash (ebl);
983 289 : if (print_symbol_table)
984 54 : print_symtab (ebl, SHT_DYNSYM);
985 289 : if (print_version_info)
986 40 : print_verinfo (ebl);
987 289 : if (print_symbol_table)
988 54 : print_symtab (ebl, SHT_SYMTAB);
989 289 : if (print_arch)
990 44 : print_liblist (ebl);
991 289 : if (print_arch)
992 44 : print_attributes (ebl, ehdr);
993 289 : if (dump_data_sections != NULL)
994 5 : dump_data (pure_ebl);
995 289 : if (string_sections != NULL)
996 41 : dump_strings (ebl);
997 289 : if ((print_debug_sections | implicit_debug_sections) != 0)
998 145 : print_debug (dwflmod, ebl, ehdr);
999 289 : if (print_notes)
1000 60 : handle_notes (pure_ebl, ehdr);
1001 289 : if (print_string_sections)
1002 0 : print_strings (ebl);
1003 :
1004 289 : ebl_closebackend (ebl);
1005 :
1006 289 : if (pure_ebl != ebl)
1007 : {
1008 65 : ebl_closebackend (pure_ebl);
1009 65 : elf_end (pure_elf);
1010 : }
1011 : }
1012 :
1013 :
1014 : /* Print file type. */
1015 : static void
1016 40 : print_file_type (unsigned short int e_type)
1017 : {
1018 40 : if (likely (e_type <= ET_CORE))
1019 : {
1020 : static const char *const knowntypes[] =
1021 : {
1022 : N_("NONE (None)"),
1023 : N_("REL (Relocatable file)"),
1024 : N_("EXEC (Executable file)"),
1025 : N_("DYN (Shared object file)"),
1026 : N_("CORE (Core file)")
1027 : };
1028 40 : puts (gettext (knowntypes[e_type]));
1029 : }
1030 0 : else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
1031 0 : printf (gettext ("OS Specific: (%x)\n"), e_type);
1032 0 : else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
1033 0 : printf (gettext ("Processor Specific: (%x)\n"), e_type);
1034 : else
1035 0 : puts ("???");
1036 40 : }
1037 :
1038 :
1039 : /* Print ELF header. */
1040 : static void
1041 40 : print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
1042 : {
1043 40 : fputs_unlocked (gettext ("ELF Header:\n Magic: "), stdout);
1044 680 : for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
1045 1280 : printf (" %02hhx", ehdr->e_ident[cnt]);
1046 :
1047 120 : printf (gettext ("\n Class: %s\n"),
1048 40 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
1049 : : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
1050 34 : : "\?\?\?");
1051 :
1052 120 : printf (gettext (" Data: %s\n"),
1053 40 : ehdr->e_ident[EI_DATA] == ELFDATA2LSB
1054 : ? "2's complement, little endian"
1055 : : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
1056 12 : ? "2's complement, big endian" : "\?\?\?");
1057 :
1058 120 : printf (gettext (" Ident Version: %hhd %s\n"),
1059 40 : ehdr->e_ident[EI_VERSION],
1060 40 : ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
1061 : : "(\?\?\?)");
1062 :
1063 : char buf[512];
1064 80 : printf (gettext (" OS/ABI: %s\n"),
1065 40 : ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
1066 :
1067 80 : printf (gettext (" ABI Version: %hhd\n"),
1068 40 : ehdr->e_ident[EI_ABIVERSION]);
1069 :
1070 40 : fputs_unlocked (gettext (" Type: "), stdout);
1071 40 : print_file_type (ehdr->e_type);
1072 :
1073 80 : printf (gettext (" Machine: %s\n"), ebl->name);
1074 :
1075 80 : printf (gettext (" Version: %d %s\n"),
1076 : ehdr->e_version,
1077 40 : ehdr->e_version == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
1078 :
1079 80 : printf (gettext (" Entry point address: %#" PRIx64 "\n"),
1080 : ehdr->e_entry);
1081 :
1082 80 : printf (gettext (" Start of program headers: %" PRId64 " %s\n"),
1083 : ehdr->e_phoff, gettext ("(bytes into file)"));
1084 :
1085 80 : printf (gettext (" Start of section headers: %" PRId64 " %s\n"),
1086 : ehdr->e_shoff, gettext ("(bytes into file)"));
1087 :
1088 80 : printf (gettext (" Flags: %s\n"),
1089 : ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
1090 :
1091 120 : printf (gettext (" Size of this header: %" PRId16 " %s\n"),
1092 40 : ehdr->e_ehsize, gettext ("(bytes)"));
1093 :
1094 120 : printf (gettext (" Size of program header entries: %" PRId16 " %s\n"),
1095 40 : ehdr->e_phentsize, gettext ("(bytes)"));
1096 :
1097 80 : printf (gettext (" Number of program headers entries: %" PRId16),
1098 40 : ehdr->e_phnum);
1099 40 : if (ehdr->e_phnum == PN_XNUM)
1100 : {
1101 : GElf_Shdr shdr_mem;
1102 0 : GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
1103 0 : if (shdr != NULL)
1104 0 : printf (gettext (" (%" PRIu32 " in [0].sh_info)"),
1105 0 : (uint32_t) shdr->sh_info);
1106 : else
1107 0 : fputs_unlocked (gettext (" ([0] not available)"), stdout);
1108 : }
1109 80 : fputc_unlocked ('\n', stdout);
1110 :
1111 120 : printf (gettext (" Size of section header entries: %" PRId16 " %s\n"),
1112 40 : ehdr->e_shentsize, gettext ("(bytes)"));
1113 :
1114 80 : printf (gettext (" Number of section headers entries: %" PRId16),
1115 40 : ehdr->e_shnum);
1116 40 : if (ehdr->e_shnum == 0)
1117 : {
1118 : GElf_Shdr shdr_mem;
1119 0 : GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
1120 0 : if (shdr != NULL)
1121 0 : printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
1122 0 : (uint32_t) shdr->sh_size);
1123 : else
1124 0 : fputs_unlocked (gettext (" ([0] not available)"), stdout);
1125 : }
1126 80 : fputc_unlocked ('\n', stdout);
1127 :
1128 40 : if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
1129 : {
1130 : GElf_Shdr shdr_mem;
1131 0 : GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
1132 0 : if (shdr != NULL)
1133 : /* We managed to get the zeroth section. */
1134 0 : snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
1135 0 : (uint32_t) shdr->sh_link);
1136 : else
1137 : {
1138 0 : strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
1139 0 : buf[sizeof (buf) - 1] = '\0';
1140 : }
1141 :
1142 0 : printf (gettext (" Section header string table index: XINDEX%s\n\n"),
1143 : buf);
1144 : }
1145 : else
1146 40 : printf (gettext (" Section header string table index: %" PRId16 "\n\n"),
1147 : ehdr->e_shstrndx);
1148 40 : }
1149 :
1150 :
1151 : static const char *
1152 : get_visibility_type (int value)
1153 : {
1154 14879 : switch (value)
1155 : {
1156 : case STV_DEFAULT:
1157 : return "DEFAULT";
1158 0 : case STV_INTERNAL:
1159 : return "INTERNAL";
1160 76 : case STV_HIDDEN:
1161 : return "HIDDEN";
1162 0 : case STV_PROTECTED:
1163 : return "PROTECTED";
1164 0 : default:
1165 : return "???";
1166 : }
1167 : }
1168 :
1169 : static const char *
1170 : elf_ch_type_name (unsigned int code)
1171 : {
1172 12 : if (code == 0)
1173 : return "NONE";
1174 :
1175 12 : if (code == ELFCOMPRESS_ZLIB)
1176 : return "ZLIB";
1177 :
1178 : return "UNKNOWN";
1179 : }
1180 :
1181 : /* Print the section headers. */
1182 : static void
1183 128 : print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
1184 : {
1185 : size_t cnt;
1186 : size_t shstrndx;
1187 :
1188 128 : if (! print_file_header)
1189 : {
1190 : size_t sections;
1191 88 : if (unlikely (elf_getshdrnum (ebl->elf, §ions) < 0))
1192 0 : error (EXIT_FAILURE, 0,
1193 0 : gettext ("cannot get number of sections: %s"),
1194 : elf_errmsg (-1));
1195 :
1196 176 : printf (gettext ("\
1197 : There are %zd section headers, starting at offset %#" PRIx64 ":\n\
1198 : \n"),
1199 : sections, ehdr->e_shoff);
1200 : }
1201 :
1202 : /* Get the section header string table index. */
1203 128 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1204 0 : error (EXIT_FAILURE, 0,
1205 0 : gettext ("cannot get section header string table index: %s"),
1206 : elf_errmsg (-1));
1207 :
1208 128 : puts (gettext ("Section Headers:"));
1209 :
1210 128 : if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1211 52 : puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
1212 : else
1213 76 : puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
1214 :
1215 128 : if (print_decompress)
1216 : {
1217 8 : if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1218 4 : puts (gettext (" [Compression Size Al]"));
1219 : else
1220 4 : puts (gettext (" [Compression Size Al]"));
1221 : }
1222 :
1223 1576044 : for (cnt = 0; cnt < shnum; ++cnt)
1224 : {
1225 1576044 : Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
1226 :
1227 1576044 : if (unlikely (scn == NULL))
1228 0 : error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
1229 : elf_errmsg (-1));
1230 :
1231 : /* Get the section header. */
1232 : GElf_Shdr shdr_mem;
1233 1576044 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1234 1576044 : if (unlikely (shdr == NULL))
1235 0 : error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
1236 : elf_errmsg (-1));
1237 :
1238 : char flagbuf[20];
1239 1576044 : char *cp = flagbuf;
1240 1576044 : if (shdr->sh_flags & SHF_WRITE)
1241 724 : *cp++ = 'W';
1242 1576044 : if (shdr->sh_flags & SHF_ALLOC)
1243 1975 : *cp++ = 'A';
1244 1576044 : if (shdr->sh_flags & SHF_EXECINSTR)
1245 371 : *cp++ = 'X';
1246 1576044 : if (shdr->sh_flags & SHF_MERGE)
1247 132 : *cp++ = 'M';
1248 1576044 : if (shdr->sh_flags & SHF_STRINGS)
1249 128 : *cp++ = 'S';
1250 1576044 : if (shdr->sh_flags & SHF_INFO_LINK)
1251 138 : *cp++ = 'I';
1252 1576044 : if (shdr->sh_flags & SHF_LINK_ORDER)
1253 2 : *cp++ = 'L';
1254 1576044 : if (shdr->sh_flags & SHF_OS_NONCONFORMING)
1255 0 : *cp++ = 'N';
1256 1576044 : if (shdr->sh_flags & SHF_GROUP)
1257 0 : *cp++ = 'G';
1258 1576044 : if (shdr->sh_flags & SHF_TLS)
1259 8 : *cp++ = 'T';
1260 1576044 : if (shdr->sh_flags & SHF_COMPRESSED)
1261 12 : *cp++ = 'C';
1262 1576044 : if (shdr->sh_flags & SHF_ORDERED)
1263 0 : *cp++ = 'O';
1264 1576044 : if (shdr->sh_flags & SHF_EXCLUDE)
1265 0 : *cp++ = 'E';
1266 1576044 : *cp = '\0';
1267 :
1268 : const char *sname;
1269 : char buf[128];
1270 1576044 : sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "<corrupt>";
1271 6304176 : printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
1272 : " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
1273 : " %2" PRId64 "\n",
1274 : cnt, sname,
1275 1576044 : ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
1276 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
1277 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
1278 1576044 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
1279 : shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
1280 : shdr->sh_addralign);
1281 :
1282 1576044 : if (print_decompress)
1283 : {
1284 76 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1285 : {
1286 : GElf_Chdr chdr;
1287 12 : if (gelf_getchdr (scn, &chdr) != NULL)
1288 36 : printf (" [ELF %s (%" PRId32 ") %0*" PRIx64
1289 : " %2" PRId64 "]\n",
1290 : elf_ch_type_name (chdr.ch_type),
1291 : chdr.ch_type,
1292 12 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8,
1293 : chdr.ch_size, chdr.ch_addralign);
1294 : else
1295 0 : error (0, 0,
1296 0 : gettext ("bad compression header for section %zd: %s"),
1297 : elf_ndxscn (scn), elf_errmsg (-1));
1298 : }
1299 64 : else if (strncmp(".zdebug", sname, strlen (".zdebug")) == 0)
1300 : {
1301 : ssize_t size;
1302 12 : if ((size = dwelf_scn_gnu_compressed_size (scn)) >= 0)
1303 12 : printf (" [GNU ZLIB %0*zx ]\n",
1304 12 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, size);
1305 : else
1306 0 : error (0, 0,
1307 0 : gettext ("bad gnu compressed size for section %zd: %s"),
1308 : elf_ndxscn (scn), elf_errmsg (-1));
1309 : }
1310 : }
1311 : }
1312 :
1313 256 : fputc_unlocked ('\n', stdout);
1314 128 : }
1315 :
1316 :
1317 : /* Print the program header. */
1318 : static void
1319 40 : print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
1320 : {
1321 40 : if (phnum == 0)
1322 : /* No program header, this is OK in relocatable objects. */
1323 30 : return;
1324 :
1325 10 : puts (gettext ("Program Headers:"));
1326 10 : if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1327 0 : puts (gettext ("\
1328 : Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
1329 : else
1330 10 : puts (gettext ("\
1331 : Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
1332 :
1333 : /* Process all program headers. */
1334 : bool has_relro = false;
1335 : GElf_Addr relro_from = 0;
1336 : GElf_Addr relro_to = 0;
1337 110 : for (size_t cnt = 0; cnt < phnum; ++cnt)
1338 : {
1339 : char buf[128];
1340 : GElf_Phdr mem;
1341 110 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
1342 :
1343 : /* If for some reason the header cannot be returned show this. */
1344 110 : if (unlikely (phdr == NULL))
1345 : {
1346 0 : puts (" ???");
1347 0 : continue;
1348 : }
1349 :
1350 770 : printf (" %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
1351 : " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
1352 110 : ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
1353 : phdr->p_offset,
1354 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
1355 110 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
1356 : phdr->p_filesz,
1357 : phdr->p_memsz,
1358 110 : phdr->p_flags & PF_R ? 'R' : ' ',
1359 110 : phdr->p_flags & PF_W ? 'W' : ' ',
1360 110 : phdr->p_flags & PF_X ? 'E' : ' ',
1361 : phdr->p_align);
1362 :
1363 110 : if (phdr->p_type == PT_INTERP)
1364 : {
1365 : /* If we are sure the file offset is valid then we can show
1366 : the user the name of the interpreter. We check whether
1367 : there is a section at the file offset. Normally there
1368 : would be a section called ".interp". But in separate
1369 : .debug files it is a NOBITS section (and so doesn't match
1370 : with gelf_offscn). Which probably means the offset is
1371 : not valid another reason could be because the ELF file
1372 : just doesn't contain any section headers, in that case
1373 : just play it safe and don't display anything. */
1374 :
1375 6 : Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
1376 : GElf_Shdr shdr_mem;
1377 6 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1378 :
1379 : size_t maxsize;
1380 6 : char *filedata = elf_rawfile (ebl->elf, &maxsize);
1381 :
1382 6 : if (shdr != NULL && shdr->sh_type == SHT_PROGBITS
1383 6 : && filedata != NULL && phdr->p_offset < maxsize
1384 6 : && phdr->p_filesz <= maxsize - phdr->p_offset
1385 6 : && memchr (filedata + phdr->p_offset, '\0',
1386 : phdr->p_filesz) != NULL)
1387 6 : printf (gettext ("\t[Requesting program interpreter: %s]\n"),
1388 : filedata + phdr->p_offset);
1389 : }
1390 104 : else if (phdr->p_type == PT_GNU_RELRO)
1391 : {
1392 10 : has_relro = true;
1393 10 : relro_from = phdr->p_vaddr;
1394 10 : relro_to = relro_from + phdr->p_memsz;
1395 : }
1396 : }
1397 :
1398 : size_t sections;
1399 10 : if (unlikely (elf_getshdrnum (ebl->elf, §ions) < 0))
1400 0 : error (EXIT_FAILURE, 0,
1401 0 : gettext ("cannot get number of sections: %s"),
1402 : elf_errmsg (-1));
1403 :
1404 10 : if (sections == 0)
1405 : /* No sections in the file. Punt. */
1406 : return;
1407 :
1408 : /* Get the section header string table index. */
1409 : size_t shstrndx;
1410 10 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1411 : error (EXIT_FAILURE, 0,
1412 0 : gettext ("cannot get section header string table index"));
1413 :
1414 10 : puts (gettext ("\n Section to Segment mapping:\n Segment Sections..."));
1415 :
1416 120 : for (size_t cnt = 0; cnt < phnum; ++cnt)
1417 : {
1418 : /* Print the segment number. */
1419 110 : printf (" %2.2zu ", cnt);
1420 :
1421 : GElf_Phdr phdr_mem;
1422 110 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
1423 : /* This must not happen. */
1424 110 : if (unlikely (phdr == NULL))
1425 0 : error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
1426 : elf_errmsg (-1));
1427 :
1428 : /* Iterate over the sections. */
1429 : bool in_relro = false;
1430 : bool in_ro = false;
1431 3932 : for (size_t inner = 1; inner < shnum; ++inner)
1432 : {
1433 3932 : Elf_Scn *scn = elf_getscn (ebl->elf, inner);
1434 : /* This should not happen. */
1435 3932 : if (unlikely (scn == NULL))
1436 0 : error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
1437 : elf_errmsg (-1));
1438 :
1439 : /* Get the section header. */
1440 : GElf_Shdr shdr_mem;
1441 3932 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1442 3932 : if (unlikely (shdr == NULL))
1443 0 : error (EXIT_FAILURE, 0,
1444 0 : gettext ("cannot get section header: %s"),
1445 : elf_errmsg (-1));
1446 :
1447 3932 : if (shdr->sh_size > 0
1448 : /* Compare allocated sections by VMA, unallocated
1449 : sections by file offset. */
1450 7864 : && (shdr->sh_flags & SHF_ALLOC
1451 2914 : ? (shdr->sh_addr >= phdr->p_vaddr
1452 4716 : && (shdr->sh_addr + shdr->sh_size
1453 1802 : <= phdr->p_vaddr + phdr->p_memsz))
1454 1018 : : (shdr->sh_offset >= phdr->p_offset
1455 2036 : && (shdr->sh_offset + shdr->sh_size
1456 1018 : <= phdr->p_offset + phdr->p_filesz))))
1457 : {
1458 372 : if (has_relro && !in_relro
1459 266 : && shdr->sh_addr >= relro_from
1460 58 : && shdr->sh_addr + shdr->sh_size <= relro_to)
1461 : {
1462 38 : fputs_unlocked (" [RELRO:", stdout);
1463 38 : in_relro = true;
1464 : }
1465 334 : else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
1466 : {
1467 10 : fputs_unlocked ("]", stdout);
1468 10 : in_relro = false;
1469 : }
1470 324 : else if (has_relro && in_relro
1471 96 : && shdr->sh_addr + shdr->sh_size > relro_to)
1472 0 : fputs_unlocked ("] <RELRO:", stdout);
1473 324 : else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
1474 : {
1475 176 : if (!in_ro)
1476 : {
1477 30 : fputs_unlocked (" [RO:", stdout);
1478 30 : in_ro = true;
1479 : }
1480 : }
1481 : else
1482 : {
1483 : /* Determine the segment this section is part of. */
1484 : size_t cnt2;
1485 : GElf_Phdr phdr2_mem;
1486 : GElf_Phdr *phdr2 = NULL;
1487 560 : for (cnt2 = 0; cnt2 < phnum; ++cnt2)
1488 : {
1489 708 : phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
1490 :
1491 708 : if (phdr2 != NULL && phdr2->p_type == PT_LOAD
1492 516 : && shdr->sh_addr >= phdr2->p_vaddr
1493 1032 : && (shdr->sh_addr + shdr->sh_size
1494 516 : <= phdr2->p_vaddr + phdr2->p_memsz))
1495 : break;
1496 : }
1497 :
1498 148 : if (cnt2 < phnum)
1499 : {
1500 148 : if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
1501 : {
1502 26 : fputs_unlocked (" [RO:", stdout);
1503 26 : in_ro = true;
1504 : }
1505 122 : else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
1506 : {
1507 0 : fputs_unlocked ("]", stdout);
1508 0 : in_ro = false;
1509 : }
1510 : }
1511 : }
1512 :
1513 744 : printf (" %s",
1514 372 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1515 :
1516 : /* Signal that this sectin is only partially covered. */
1517 372 : if (has_relro && in_relro
1518 134 : && shdr->sh_addr + shdr->sh_size > relro_to)
1519 : {
1520 0 : fputs_unlocked (">", stdout);
1521 0 : in_relro = false;
1522 : }
1523 : }
1524 : }
1525 110 : if (in_relro || in_ro)
1526 84 : fputs_unlocked ("]", stdout);
1527 :
1528 : /* Finish the line. */
1529 220 : fputc_unlocked ('\n', stdout);
1530 : }
1531 : }
1532 :
1533 :
1534 : static const char *
1535 372 : section_name (Ebl *ebl, GElf_Shdr *shdr)
1536 : {
1537 : size_t shstrndx;
1538 372 : if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
1539 : return "???";
1540 372 : return elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "???";
1541 : }
1542 :
1543 :
1544 : static void
1545 16 : handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1546 : {
1547 : /* Get the data of the section. */
1548 16 : Elf_Data *data = elf_getdata (scn, NULL);
1549 :
1550 16 : Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1551 : GElf_Shdr symshdr_mem;
1552 16 : GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1553 16 : Elf_Data *symdata = elf_getdata (symscn, NULL);
1554 :
1555 16 : if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
1556 16 : || symdata == NULL)
1557 0 : return;
1558 :
1559 : /* Get the section header string table index. */
1560 : size_t shstrndx;
1561 16 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1562 : error (EXIT_FAILURE, 0,
1563 0 : gettext ("cannot get section header string table index"));
1564 :
1565 16 : Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
1566 :
1567 : GElf_Sym sym_mem;
1568 16 : GElf_Sym *sym = gelf_getsym (symdata, shdr->sh_info, &sym_mem);
1569 :
1570 80 : printf ((grpref[0] & GRP_COMDAT)
1571 4 : ? ngettext ("\
1572 : \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
1573 : "\
1574 : \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1575 : data->d_size / sizeof (Elf32_Word) - 1)
1576 12 : : ngettext ("\
1577 : \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
1578 : \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1579 : data->d_size / sizeof (Elf32_Word) - 1),
1580 : elf_ndxscn (scn),
1581 16 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1582 : (sym == NULL ? NULL
1583 16 : : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
1584 : ?: gettext ("<INVALID SYMBOL>"),
1585 16 : data->d_size / sizeof (Elf32_Word) - 1);
1586 :
1587 52 : for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1588 : {
1589 : GElf_Shdr grpshdr_mem;
1590 36 : GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
1591 : &grpshdr_mem);
1592 :
1593 : const char *str;
1594 72 : printf (" [%2u] %s\n",
1595 : grpref[cnt],
1596 : grpshdr != NULL
1597 36 : && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
1598 : ? str : gettext ("<INVALID SECTION>"));
1599 : }
1600 : }
1601 :
1602 :
1603 : static void
1604 49 : print_scngrp (Ebl *ebl)
1605 : {
1606 : /* Find all relocation sections and handle them. */
1607 49 : Elf_Scn *scn = NULL;
1608 :
1609 1349 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1610 : {
1611 : /* Handle the section if it is a symbol table. */
1612 : GElf_Shdr shdr_mem;
1613 1251 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1614 :
1615 1251 : if (shdr != NULL && shdr->sh_type == SHT_GROUP)
1616 : {
1617 16 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1618 : {
1619 0 : if (elf_compress (scn, 0, 0) < 0)
1620 0 : printf ("WARNING: %s [%zd]\n",
1621 : gettext ("Couldn't uncompress section"),
1622 : elf_ndxscn (scn));
1623 0 : shdr = gelf_getshdr (scn, &shdr_mem);
1624 0 : if (unlikely (shdr == NULL))
1625 0 : error (EXIT_FAILURE, 0,
1626 0 : gettext ("cannot get section [%zd] header: %s"),
1627 : elf_ndxscn (scn),
1628 : elf_errmsg (-1));
1629 : }
1630 16 : handle_scngrp (ebl, scn, shdr);
1631 : }
1632 : }
1633 49 : }
1634 :
1635 :
1636 : static const struct flags
1637 : {
1638 : int mask;
1639 : const char *str;
1640 : } dt_flags[] =
1641 : {
1642 : { DF_ORIGIN, "ORIGIN" },
1643 : { DF_SYMBOLIC, "SYMBOLIC" },
1644 : { DF_TEXTREL, "TEXTREL" },
1645 : { DF_BIND_NOW, "BIND_NOW" },
1646 : { DF_STATIC_TLS, "STATIC_TLS" }
1647 : };
1648 : static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
1649 :
1650 : static const struct flags dt_flags_1[] =
1651 : {
1652 : { DF_1_NOW, "NOW" },
1653 : { DF_1_GLOBAL, "GLOBAL" },
1654 : { DF_1_GROUP, "GROUP" },
1655 : { DF_1_NODELETE, "NODELETE" },
1656 : { DF_1_LOADFLTR, "LOADFLTR" },
1657 : { DF_1_INITFIRST, "INITFIRST" },
1658 : { DF_1_NOOPEN, "NOOPEN" },
1659 : { DF_1_ORIGIN, "ORIGIN" },
1660 : { DF_1_DIRECT, "DIRECT" },
1661 : { DF_1_TRANS, "TRANS" },
1662 : { DF_1_INTERPOSE, "INTERPOSE" },
1663 : { DF_1_NODEFLIB, "NODEFLIB" },
1664 : { DF_1_NODUMP, "NODUMP" },
1665 : { DF_1_CONFALT, "CONFALT" },
1666 : { DF_1_ENDFILTEE, "ENDFILTEE" },
1667 : { DF_1_DISPRELDNE, "DISPRELDNE" },
1668 : { DF_1_DISPRELPND, "DISPRELPND" },
1669 : };
1670 : static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
1671 :
1672 : static const struct flags dt_feature_1[] =
1673 : {
1674 : { DTF_1_PARINIT, "PARINIT" },
1675 : { DTF_1_CONFEXP, "CONFEXP" }
1676 : };
1677 : static const int ndt_feature_1 = (sizeof (dt_feature_1)
1678 : / sizeof (dt_feature_1[0]));
1679 :
1680 : static const struct flags dt_posflag_1[] =
1681 : {
1682 : { DF_P1_LAZYLOAD, "LAZYLOAD" },
1683 : { DF_P1_GROUPPERM, "GROUPPERM" }
1684 : };
1685 : static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
1686 : / sizeof (dt_posflag_1[0]));
1687 :
1688 :
1689 : static void
1690 10 : print_flags (int class, GElf_Xword d_val, const struct flags *flags,
1691 : int nflags)
1692 : {
1693 10 : bool first = true;
1694 : int cnt;
1695 :
1696 138 : for (cnt = 0; cnt < nflags; ++cnt)
1697 128 : if (d_val & flags[cnt].mask)
1698 : {
1699 22 : if (!first)
1700 : putchar_unlocked (' ');
1701 22 : fputs_unlocked (flags[cnt].str, stdout);
1702 22 : d_val &= ~flags[cnt].mask;
1703 22 : first = false;
1704 : }
1705 :
1706 10 : if (d_val != 0)
1707 : {
1708 10 : if (!first)
1709 : putchar_unlocked (' ');
1710 10 : printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
1711 : }
1712 :
1713 10 : putchar_unlocked ('\n');
1714 10 : }
1715 :
1716 :
1717 : static void
1718 : print_dt_flags (int class, GElf_Xword d_val)
1719 : {
1720 1 : print_flags (class, d_val, dt_flags, ndt_flags);
1721 : }
1722 :
1723 :
1724 : static void
1725 : print_dt_flags_1 (int class, GElf_Xword d_val)
1726 : {
1727 7 : print_flags (class, d_val, dt_flags_1, ndt_flags_1);
1728 : }
1729 :
1730 :
1731 : static void
1732 : print_dt_feature_1 (int class, GElf_Xword d_val)
1733 : {
1734 1 : print_flags (class, d_val, dt_feature_1, ndt_feature_1);
1735 : }
1736 :
1737 :
1738 : static void
1739 : print_dt_posflag_1 (int class, GElf_Xword d_val)
1740 : {
1741 1 : print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
1742 : }
1743 :
1744 :
1745 : static void
1746 12 : handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1747 : {
1748 12 : int class = gelf_getclass (ebl->elf);
1749 : GElf_Shdr glink_mem;
1750 : GElf_Shdr *glink;
1751 : Elf_Data *data;
1752 : size_t cnt;
1753 : size_t shstrndx;
1754 : size_t sh_entsize;
1755 :
1756 : /* Get the data of the section. */
1757 12 : data = elf_getdata (scn, NULL);
1758 12 : if (data == NULL)
1759 0 : return;
1760 :
1761 : /* Get the section header string table index. */
1762 12 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1763 : error (EXIT_FAILURE, 0,
1764 0 : gettext ("cannot get section header string table index"));
1765 :
1766 12 : sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT);
1767 :
1768 12 : glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
1769 12 : if (glink == NULL)
1770 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
1771 : elf_ndxscn (scn));
1772 :
1773 48 : printf (ngettext ("\
1774 : \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1775 : "\
1776 : \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1777 : shdr->sh_size / sh_entsize),
1778 12 : (unsigned long int) (shdr->sh_size / sh_entsize),
1779 : class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
1780 : shdr->sh_offset,
1781 12 : (int) shdr->sh_link,
1782 12 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
1783 12 : fputs_unlocked (gettext (" Type Value\n"), stdout);
1784 :
1785 448 : for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
1786 : {
1787 : GElf_Dyn dynmem;
1788 436 : GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
1789 436 : if (dyn == NULL)
1790 : break;
1791 :
1792 : char buf[64];
1793 872 : printf (" %-17s ",
1794 : ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
1795 :
1796 436 : switch (dyn->d_tag)
1797 : {
1798 66 : case DT_NULL:
1799 : case DT_DEBUG:
1800 : case DT_BIND_NOW:
1801 : case DT_TEXTREL:
1802 : /* No further output. */
1803 66 : fputc_unlocked ('\n', stdout);
1804 : break;
1805 :
1806 52 : case DT_NEEDED:
1807 104 : printf (gettext ("Shared library: [%s]\n"),
1808 52 : elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1809 : break;
1810 :
1811 3 : case DT_SONAME:
1812 6 : printf (gettext ("Library soname: [%s]\n"),
1813 3 : elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1814 : break;
1815 :
1816 1 : case DT_RPATH:
1817 2 : printf (gettext ("Library rpath: [%s]\n"),
1818 1 : elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1819 : break;
1820 :
1821 2 : case DT_RUNPATH:
1822 4 : printf (gettext ("Library runpath: [%s]\n"),
1823 2 : elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1824 : break;
1825 :
1826 91 : case DT_PLTRELSZ:
1827 : case DT_RELASZ:
1828 : case DT_STRSZ:
1829 : case DT_RELSZ:
1830 : case DT_RELAENT:
1831 : case DT_SYMENT:
1832 : case DT_RELENT:
1833 : case DT_PLTPADSZ:
1834 : case DT_MOVEENT:
1835 : case DT_MOVESZ:
1836 : case DT_INIT_ARRAYSZ:
1837 : case DT_FINI_ARRAYSZ:
1838 : case DT_SYMINSZ:
1839 : case DT_SYMINENT:
1840 : case DT_GNU_CONFLICTSZ:
1841 : case DT_GNU_LIBLISTSZ:
1842 91 : printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
1843 : break;
1844 :
1845 31 : case DT_VERDEFNUM:
1846 : case DT_VERNEEDNUM:
1847 : case DT_RELACOUNT:
1848 : case DT_RELCOUNT:
1849 31 : printf ("%" PRId64 "\n", dyn->d_un.d_val);
1850 : break;
1851 :
1852 12 : case DT_PLTREL:;
1853 12 : const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
1854 : NULL, 0);
1855 12 : puts (tagname ?: "???");
1856 12 : break;
1857 :
1858 1 : case DT_FLAGS:
1859 1 : print_dt_flags (class, dyn->d_un.d_val);
1860 : break;
1861 :
1862 7 : case DT_FLAGS_1:
1863 7 : print_dt_flags_1 (class, dyn->d_un.d_val);
1864 : break;
1865 :
1866 1 : case DT_FEATURE_1:
1867 1 : print_dt_feature_1 (class, dyn->d_un.d_val);
1868 : break;
1869 :
1870 1 : case DT_POSFLAG_1:
1871 1 : print_dt_posflag_1 (class, dyn->d_un.d_val);
1872 : break;
1873 :
1874 168 : default:
1875 168 : printf ("%#0*" PRIx64 "\n",
1876 : class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
1877 : break;
1878 : }
1879 : }
1880 : }
1881 :
1882 :
1883 : /* Print the dynamic segment. */
1884 : static void
1885 42 : print_dynamic (Ebl *ebl)
1886 : {
1887 98 : for (size_t i = 0; i < phnum; ++i)
1888 : {
1889 : GElf_Phdr phdr_mem;
1890 68 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
1891 :
1892 68 : if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
1893 : {
1894 12 : Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
1895 : GElf_Shdr shdr_mem;
1896 12 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1897 12 : if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
1898 12 : handle_dynamic (ebl, scn, shdr);
1899 : break;
1900 : }
1901 : }
1902 42 : }
1903 :
1904 :
1905 : /* Print relocations. */
1906 : static void
1907 41 : print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
1908 : {
1909 : /* Find all relocation sections and handle them. */
1910 41 : Elf_Scn *scn = NULL;
1911 :
1912 1117 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1913 : {
1914 : /* Handle the section if it is a symbol table. */
1915 : GElf_Shdr shdr_mem;
1916 1035 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1917 :
1918 1035 : if (likely (shdr != NULL))
1919 : {
1920 1035 : if (shdr->sh_type == SHT_REL)
1921 22 : handle_relocs_rel (ebl, ehdr, scn, shdr);
1922 1013 : else if (shdr->sh_type == SHT_RELA)
1923 168 : handle_relocs_rela (ebl, ehdr, scn, shdr);
1924 : }
1925 : }
1926 41 : }
1927 :
1928 :
1929 : /* Handle a relocation section. */
1930 : static void
1931 22 : handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1932 : {
1933 22 : int class = gelf_getclass (ebl->elf);
1934 22 : size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
1935 22 : int nentries = shdr->sh_size / sh_entsize;
1936 :
1937 : /* Get the data of the section. */
1938 22 : Elf_Data *data = elf_getdata (scn, NULL);
1939 22 : if (data == NULL)
1940 0 : return;
1941 :
1942 : /* Get the symbol table information. */
1943 22 : Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1944 : GElf_Shdr symshdr_mem;
1945 22 : GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1946 22 : Elf_Data *symdata = elf_getdata (symscn, NULL);
1947 :
1948 : /* Get the section header of the section the relocations are for. */
1949 : GElf_Shdr destshdr_mem;
1950 22 : GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1951 : &destshdr_mem);
1952 :
1953 22 : if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
1954 : {
1955 0 : printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1956 : shdr->sh_offset);
1957 : return;
1958 : }
1959 :
1960 : /* Search for the optional extended section index table. */
1961 22 : Elf_Data *xndxdata = NULL;
1962 22 : int xndxscnidx = elf_scnshndx (scn);
1963 22 : if (unlikely (xndxscnidx > 0))
1964 0 : xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
1965 :
1966 : /* Get the section header string table index. */
1967 : size_t shstrndx;
1968 22 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1969 : error (EXIT_FAILURE, 0,
1970 0 : gettext ("cannot get section header string table index"));
1971 :
1972 22 : if (shdr->sh_info != 0)
1973 66 : printf (ngettext ("\
1974 : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1975 : "\
1976 : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1977 : nentries),
1978 : elf_ndxscn (scn),
1979 22 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1980 22 : (unsigned int) shdr->sh_info,
1981 22 : elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1982 : shdr->sh_offset,
1983 : nentries);
1984 : else
1985 : /* The .rel.dyn section does not refer to a specific section but
1986 : instead of section index zero. Do not try to print a section
1987 : name. */
1988 0 : printf (ngettext ("\
1989 : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1990 : "\
1991 : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1992 : nentries),
1993 0 : (unsigned int) elf_ndxscn (scn),
1994 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1995 : shdr->sh_offset,
1996 : nentries);
1997 22 : fputs_unlocked (class == ELFCLASS32
1998 : ? gettext ("\
1999 : Offset Type Value Name\n")
2000 : : gettext ("\
2001 : Offset Type Value Name\n"),
2002 : stdout);
2003 :
2004 22 : int is_statically_linked = 0;
2005 6491 : for (int cnt = 0; cnt < nentries; ++cnt)
2006 : {
2007 : GElf_Rel relmem;
2008 6469 : GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
2009 6469 : if (likely (rel != NULL))
2010 : {
2011 : char buf[128];
2012 : GElf_Sym symmem;
2013 : Elf32_Word xndx;
2014 6469 : GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
2015 6469 : GELF_R_SYM (rel->r_info),
2016 : &symmem, &xndx);
2017 6469 : if (unlikely (sym == NULL))
2018 : {
2019 : /* As a special case we have to handle relocations in static
2020 : executables. This only happens for IRELATIVE relocations
2021 : (so far). There is no symbol table. */
2022 0 : if (is_statically_linked == 0)
2023 : {
2024 : /* Find the program header and look for a PT_INTERP entry. */
2025 0 : is_statically_linked = -1;
2026 0 : if (ehdr->e_type == ET_EXEC)
2027 : {
2028 : is_statically_linked = 1;
2029 :
2030 0 : for (size_t inner = 0; inner < phnum; ++inner)
2031 : {
2032 : GElf_Phdr phdr_mem;
2033 0 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
2034 : &phdr_mem);
2035 0 : if (phdr != NULL && phdr->p_type == PT_INTERP)
2036 : {
2037 0 : is_statically_linked = -1;
2038 0 : break;
2039 : }
2040 : }
2041 : }
2042 : }
2043 :
2044 0 : if (is_statically_linked > 0 && shdr->sh_link == 0)
2045 0 : printf ("\
2046 : %#0*" PRIx64 " %-20s %*s %s\n",
2047 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2048 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2049 : /* Avoid the leading R_ which isn't carrying any
2050 : information. */
2051 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2052 : buf, sizeof (buf)) + 2
2053 : : gettext ("<INVALID RELOC>"),
2054 : class == ELFCLASS32 ? 10 : 18, "",
2055 0 : elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
2056 : else
2057 0 : printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
2058 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2059 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2060 : /* Avoid the leading R_ which isn't carrying any
2061 : information. */
2062 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2063 : buf, sizeof (buf)) + 2
2064 : : gettext ("<INVALID RELOC>"),
2065 : gettext ("INVALID SYMBOL"),
2066 0 : (long int) GELF_R_SYM (rel->r_info));
2067 : }
2068 6469 : else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
2069 124 : printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
2070 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2071 31 : likely (ebl_reloc_type_check (ebl,
2072 : GELF_R_TYPE (rel->r_info)))
2073 : /* Avoid the leading R_ which isn't carrying any
2074 : information. */
2075 31 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2076 : buf, sizeof (buf)) + 2
2077 : : gettext ("<INVALID RELOC>"),
2078 : class == ELFCLASS32 ? 10 : 18, sym->st_value,
2079 62 : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
2080 : else
2081 : {
2082 : /* This is a relocation against a STT_SECTION symbol. */
2083 : GElf_Shdr secshdr_mem;
2084 : GElf_Shdr *secshdr;
2085 6438 : secshdr = gelf_getshdr (elf_getscn (ebl->elf,
2086 6438 : sym->st_shndx == SHN_XINDEX
2087 0 : ? xndx : sym->st_shndx),
2088 : &secshdr_mem);
2089 :
2090 6438 : if (unlikely (secshdr == NULL))
2091 0 : printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
2092 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2093 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2094 : /* Avoid the leading R_ which isn't carrying any
2095 : information. */
2096 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2097 : buf, sizeof (buf)) + 2
2098 : : gettext ("<INVALID RELOC>"),
2099 : gettext ("INVALID SECTION"),
2100 0 : (long int) (sym->st_shndx == SHN_XINDEX
2101 0 : ? xndx : sym->st_shndx));
2102 : else
2103 19314 : printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
2104 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2105 6438 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2106 : /* Avoid the leading R_ which isn't carrying any
2107 : information. */
2108 6438 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2109 : buf, sizeof (buf)) + 2
2110 : : gettext ("<INVALID RELOC>"),
2111 : class == ELFCLASS32 ? 10 : 18, sym->st_value,
2112 6438 : elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
2113 : }
2114 : }
2115 : }
2116 : }
2117 :
2118 :
2119 : /* Handle a relocation section. */
2120 : static void
2121 168 : handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
2122 : {
2123 168 : int class = gelf_getclass (ebl->elf);
2124 168 : size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
2125 168 : int nentries = shdr->sh_size / sh_entsize;
2126 :
2127 : /* Get the data of the section. */
2128 168 : Elf_Data *data = elf_getdata (scn, NULL);
2129 168 : if (data == NULL)
2130 0 : return;
2131 :
2132 : /* Get the symbol table information. */
2133 168 : Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2134 : GElf_Shdr symshdr_mem;
2135 168 : GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2136 168 : Elf_Data *symdata = elf_getdata (symscn, NULL);
2137 :
2138 : /* Get the section header of the section the relocations are for. */
2139 : GElf_Shdr destshdr_mem;
2140 168 : GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
2141 : &destshdr_mem);
2142 :
2143 168 : if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
2144 : {
2145 0 : printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
2146 : shdr->sh_offset);
2147 : return;
2148 : }
2149 :
2150 : /* Search for the optional extended section index table. */
2151 168 : Elf_Data *xndxdata = NULL;
2152 168 : int xndxscnidx = elf_scnshndx (scn);
2153 168 : if (unlikely (xndxscnidx > 0))
2154 0 : xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
2155 :
2156 : /* Get the section header string table index. */
2157 : size_t shstrndx;
2158 168 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2159 : error (EXIT_FAILURE, 0,
2160 0 : gettext ("cannot get section header string table index"));
2161 :
2162 168 : if (shdr->sh_info != 0)
2163 474 : printf (ngettext ("\
2164 : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2165 : "\
2166 : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2167 : nentries),
2168 : elf_ndxscn (scn),
2169 158 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2170 158 : (unsigned int) shdr->sh_info,
2171 158 : elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
2172 : shdr->sh_offset,
2173 : nentries);
2174 : else
2175 : /* The .rela.dyn section does not refer to a specific section but
2176 : instead of section index zero. Do not try to print a section
2177 : name. */
2178 30 : printf (ngettext ("\
2179 : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2180 : "\
2181 : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2182 : nentries),
2183 10 : (unsigned int) elf_ndxscn (scn),
2184 10 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2185 : shdr->sh_offset,
2186 : nentries);
2187 168 : fputs_unlocked (class == ELFCLASS32
2188 : ? gettext ("\
2189 : Offset Type Value Addend Name\n")
2190 : : gettext ("\
2191 : Offset Type Value Addend Name\n"),
2192 : stdout);
2193 :
2194 168 : int is_statically_linked = 0;
2195 38696 : for (int cnt = 0; cnt < nentries; ++cnt)
2196 : {
2197 : GElf_Rela relmem;
2198 38528 : GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
2199 38528 : if (likely (rel != NULL))
2200 : {
2201 : char buf[64];
2202 : GElf_Sym symmem;
2203 : Elf32_Word xndx;
2204 38528 : GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
2205 38528 : GELF_R_SYM (rel->r_info),
2206 : &symmem, &xndx);
2207 :
2208 38528 : if (unlikely (sym == NULL))
2209 : {
2210 : /* As a special case we have to handle relocations in static
2211 : executables. This only happens for IRELATIVE relocations
2212 : (so far). There is no symbol table. */
2213 0 : if (is_statically_linked == 0)
2214 : {
2215 : /* Find the program header and look for a PT_INTERP entry. */
2216 0 : is_statically_linked = -1;
2217 0 : if (ehdr->e_type == ET_EXEC)
2218 : {
2219 : is_statically_linked = 1;
2220 :
2221 0 : for (size_t inner = 0; inner < phnum; ++inner)
2222 : {
2223 : GElf_Phdr phdr_mem;
2224 0 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
2225 : &phdr_mem);
2226 0 : if (phdr != NULL && phdr->p_type == PT_INTERP)
2227 : {
2228 0 : is_statically_linked = -1;
2229 0 : break;
2230 : }
2231 : }
2232 : }
2233 : }
2234 :
2235 0 : if (is_statically_linked > 0 && shdr->sh_link == 0)
2236 0 : printf ("\
2237 : %#0*" PRIx64 " %-15s %*s %#6" PRIx64 " %s\n",
2238 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2239 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2240 : /* Avoid the leading R_ which isn't carrying any
2241 : information. */
2242 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2243 : buf, sizeof (buf)) + 2
2244 : : gettext ("<INVALID RELOC>"),
2245 : class == ELFCLASS32 ? 10 : 18, "",
2246 : rel->r_addend,
2247 0 : elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
2248 : else
2249 0 : printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
2250 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2251 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2252 : /* Avoid the leading R_ which isn't carrying any
2253 : information. */
2254 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2255 : buf, sizeof (buf)) + 2
2256 : : gettext ("<INVALID RELOC>"),
2257 : gettext ("INVALID SYMBOL"),
2258 0 : (long int) GELF_R_SYM (rel->r_info));
2259 : }
2260 38528 : else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
2261 82784 : printf ("\
2262 : %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
2263 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2264 20696 : likely (ebl_reloc_type_check (ebl,
2265 : GELF_R_TYPE (rel->r_info)))
2266 : /* Avoid the leading R_ which isn't carrying any
2267 : information. */
2268 20696 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2269 : buf, sizeof (buf)) + 2
2270 : : gettext ("<INVALID RELOC>"),
2271 : class == ELFCLASS32 ? 10 : 18, sym->st_value,
2272 : rel->r_addend,
2273 41392 : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
2274 : else
2275 : {
2276 : /* This is a relocation against a STT_SECTION symbol. */
2277 : GElf_Shdr secshdr_mem;
2278 : GElf_Shdr *secshdr;
2279 17832 : secshdr = gelf_getshdr (elf_getscn (ebl->elf,
2280 17832 : sym->st_shndx == SHN_XINDEX
2281 0 : ? xndx : sym->st_shndx),
2282 : &secshdr_mem);
2283 :
2284 17832 : if (unlikely (secshdr == NULL))
2285 0 : printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
2286 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2287 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2288 : /* Avoid the leading R_ which isn't carrying any
2289 : information. */
2290 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2291 : buf, sizeof (buf)) + 2
2292 : : gettext ("<INVALID RELOC>"),
2293 : gettext ("INVALID SECTION"),
2294 0 : (long int) (sym->st_shndx == SHN_XINDEX
2295 0 : ? xndx : sym->st_shndx));
2296 : else
2297 53496 : printf ("\
2298 : %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
2299 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2300 17832 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2301 : /* Avoid the leading R_ which isn't carrying any
2302 : information. */
2303 17832 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2304 : buf, sizeof (buf)) + 2
2305 : : gettext ("<INVALID RELOC>"),
2306 : class == ELFCLASS32 ? 10 : 18, sym->st_value,
2307 : rel->r_addend,
2308 17832 : elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
2309 : }
2310 : }
2311 : }
2312 : }
2313 :
2314 :
2315 : /* Print the program header. */
2316 : static void
2317 108 : print_symtab (Ebl *ebl, int type)
2318 : {
2319 : /* Find the symbol table(s). For this we have to search through the
2320 : section table. */
2321 108 : Elf_Scn *scn = NULL;
2322 :
2323 2976 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2324 : {
2325 : /* Handle the section if it is a symbol table. */
2326 : GElf_Shdr shdr_mem;
2327 2760 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2328 :
2329 2760 : if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
2330 : {
2331 64 : if (symbol_table_section != NULL)
2332 : {
2333 : /* Get the section header string table index. */
2334 : size_t shstrndx;
2335 : const char *sname;
2336 4 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2337 : error (EXIT_FAILURE, 0,
2338 0 : gettext ("cannot get section header string table index"));
2339 4 : sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
2340 4 : if (sname == NULL || strcmp (sname, symbol_table_section) != 0)
2341 2 : continue;
2342 : }
2343 :
2344 62 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
2345 : {
2346 0 : if (elf_compress (scn, 0, 0) < 0)
2347 0 : printf ("WARNING: %s [%zd]\n",
2348 : gettext ("Couldn't uncompress section"),
2349 : elf_ndxscn (scn));
2350 0 : shdr = gelf_getshdr (scn, &shdr_mem);
2351 0 : if (unlikely (shdr == NULL))
2352 0 : error (EXIT_FAILURE, 0,
2353 0 : gettext ("cannot get section [%zd] header: %s"),
2354 : elf_ndxscn (scn), elf_errmsg (-1));
2355 : }
2356 62 : handle_symtab (ebl, scn, shdr);
2357 : }
2358 : }
2359 108 : }
2360 :
2361 :
2362 : static void
2363 62 : handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2364 : {
2365 62 : Elf_Data *versym_data = NULL;
2366 62 : Elf_Data *verneed_data = NULL;
2367 62 : Elf_Data *verdef_data = NULL;
2368 62 : Elf_Data *xndx_data = NULL;
2369 62 : int class = gelf_getclass (ebl->elf);
2370 62 : Elf32_Word verneed_stridx = 0;
2371 62 : Elf32_Word verdef_stridx = 0;
2372 :
2373 : /* Get the data of the section. */
2374 62 : Elf_Data *data = elf_getdata (scn, NULL);
2375 62 : if (data == NULL)
2376 0 : return;
2377 :
2378 : /* Find out whether we have other sections we might need. */
2379 : Elf_Scn *runscn = NULL;
2380 1768 : while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
2381 : {
2382 : GElf_Shdr runshdr_mem;
2383 1706 : GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
2384 :
2385 1706 : if (likely (runshdr != NULL))
2386 : {
2387 1706 : if (runshdr->sh_type == SHT_GNU_versym
2388 27 : && runshdr->sh_link == elf_ndxscn (scn))
2389 : /* Bingo, found the version information. Now get the data. */
2390 17 : versym_data = elf_getdata (runscn, NULL);
2391 1689 : else if (runshdr->sh_type == SHT_GNU_verneed)
2392 : {
2393 : /* This is the information about the needed versions. */
2394 27 : verneed_data = elf_getdata (runscn, NULL);
2395 27 : verneed_stridx = runshdr->sh_link;
2396 : }
2397 1662 : else if (runshdr->sh_type == SHT_GNU_verdef)
2398 : {
2399 : /* This is the information about the defined versions. */
2400 8 : verdef_data = elf_getdata (runscn, NULL);
2401 8 : verdef_stridx = runshdr->sh_link;
2402 : }
2403 1654 : else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
2404 0 : && runshdr->sh_link == elf_ndxscn (scn))
2405 : /* Extended section index. */
2406 0 : xndx_data = elf_getdata (runscn, NULL);
2407 : }
2408 : }
2409 :
2410 : /* Get the section header string table index. */
2411 : size_t shstrndx;
2412 62 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2413 : error (EXIT_FAILURE, 0,
2414 0 : gettext ("cannot get section header string table index"));
2415 :
2416 : GElf_Shdr glink_mem;
2417 62 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2418 : &glink_mem);
2419 62 : if (glink == NULL)
2420 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
2421 : elf_ndxscn (scn));
2422 :
2423 : /* Now we can compute the number of entries in the section. */
2424 124 : unsigned int nsyms = data->d_size / (class == ELFCLASS32
2425 : ? sizeof (Elf32_Sym)
2426 62 : : sizeof (Elf64_Sym));
2427 :
2428 186 : printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
2429 : "\nSymbol table [%2u] '%s' contains %u entries:\n",
2430 : nsyms),
2431 62 : (unsigned int) elf_ndxscn (scn),
2432 62 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
2433 186 : printf (ngettext (" %lu local symbol String table: [%2u] '%s'\n",
2434 : " %lu local symbols String table: [%2u] '%s'\n",
2435 : shdr->sh_info),
2436 62 : (unsigned long int) shdr->sh_info,
2437 62 : (unsigned int) shdr->sh_link,
2438 62 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
2439 :
2440 62 : fputs_unlocked (class == ELFCLASS32
2441 : ? gettext ("\
2442 : Num: Value Size Type Bind Vis Ndx Name\n")
2443 : : gettext ("\
2444 : Num: Value Size Type Bind Vis Ndx Name\n"),
2445 : stdout);
2446 :
2447 14941 : for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
2448 : {
2449 : char typebuf[64];
2450 : char bindbuf[64];
2451 : char scnbuf[64];
2452 : Elf32_Word xndx;
2453 : GElf_Sym sym_mem;
2454 14879 : GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
2455 :
2456 14879 : if (unlikely (sym == NULL))
2457 0 : continue;
2458 :
2459 : /* Determine the real section index. */
2460 14879 : if (likely (sym->st_shndx != SHN_XINDEX))
2461 14879 : xndx = sym->st_shndx;
2462 :
2463 119032 : printf (gettext ("\
2464 : %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
2465 : cnt,
2466 : class == ELFCLASS32 ? 8 : 16,
2467 : sym->st_value,
2468 : sym->st_size,
2469 14879 : ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
2470 : typebuf, sizeof (typebuf)),
2471 14879 : ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
2472 : bindbuf, sizeof (bindbuf)),
2473 14879 : get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
2474 14879 : ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
2475 : sizeof (scnbuf), NULL, shnum),
2476 29758 : elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
2477 :
2478 14879 : if (versym_data != NULL)
2479 : {
2480 : /* Get the version information. */
2481 : GElf_Versym versym_mem;
2482 1387 : GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
2483 :
2484 1387 : if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
2485 : {
2486 1189 : bool is_nobits = false;
2487 1189 : bool check_def = xndx != SHN_UNDEF;
2488 :
2489 1189 : if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
2490 : {
2491 : GElf_Shdr symshdr_mem;
2492 1153 : GElf_Shdr *symshdr =
2493 1153 : gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
2494 :
2495 1153 : is_nobits = (symshdr != NULL
2496 1153 : && symshdr->sh_type == SHT_NOBITS);
2497 : }
2498 :
2499 1189 : if (is_nobits || ! check_def)
2500 : {
2501 : /* We must test both. */
2502 : GElf_Vernaux vernaux_mem;
2503 813 : GElf_Vernaux *vernaux = NULL;
2504 813 : size_t vn_offset = 0;
2505 :
2506 : GElf_Verneed verneed_mem;
2507 813 : GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
2508 : &verneed_mem);
2509 4057 : while (verneed != NULL)
2510 : {
2511 3244 : size_t vna_offset = vn_offset;
2512 :
2513 3244 : vernaux = gelf_getvernaux (verneed_data,
2514 3244 : vna_offset += verneed->vn_aux,
2515 : &vernaux_mem);
2516 10018 : while (vernaux != NULL
2517 6774 : && vernaux->vna_other != *versym
2518 5961 : && vernaux->vna_next != 0)
2519 : {
2520 : /* Update the offset. */
2521 3530 : vna_offset += vernaux->vna_next;
2522 :
2523 3530 : vernaux = (vernaux->vna_next == 0
2524 : ? NULL
2525 3530 : : gelf_getvernaux (verneed_data,
2526 : vna_offset,
2527 : &vernaux_mem));
2528 : }
2529 :
2530 : /* Check whether we found the version. */
2531 3244 : if (vernaux != NULL && vernaux->vna_other == *versym)
2532 : /* Found it. */
2533 : break;
2534 :
2535 2431 : vn_offset += verneed->vn_next;
2536 : verneed = (verneed->vn_next == 0
2537 : ? NULL
2538 2431 : : gelf_getverneed (verneed_data, vn_offset,
2539 : &verneed_mem));
2540 : }
2541 :
2542 813 : if (vernaux != NULL && vernaux->vna_other == *versym)
2543 : {
2544 2439 : printf ("@%s (%u)",
2545 : elf_strptr (ebl->elf, verneed_stridx,
2546 813 : vernaux->vna_name),
2547 : (unsigned int) vernaux->vna_other);
2548 813 : check_def = 0;
2549 : }
2550 0 : else if (unlikely (! is_nobits))
2551 0 : error (0, 0, gettext ("bad dynamic symbol"));
2552 : else
2553 : check_def = 1;
2554 : }
2555 :
2556 376 : if (check_def && *versym != 0x8001)
2557 : {
2558 : /* We must test both. */
2559 376 : size_t vd_offset = 0;
2560 :
2561 : GElf_Verdef verdef_mem;
2562 376 : GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
2563 : &verdef_mem);
2564 2848 : while (verdef != NULL)
2565 : {
2566 2472 : if (verdef->vd_ndx == (*versym & 0x7fff))
2567 : /* Found the definition. */
2568 : break;
2569 :
2570 2096 : vd_offset += verdef->vd_next;
2571 : verdef = (verdef->vd_next == 0
2572 : ? NULL
2573 2096 : : gelf_getverdef (verdef_data, vd_offset,
2574 : &verdef_mem));
2575 : }
2576 :
2577 376 : if (verdef != NULL)
2578 : {
2579 : GElf_Verdaux verdaux_mem;
2580 376 : GElf_Verdaux *verdaux
2581 376 : = gelf_getverdaux (verdef_data,
2582 376 : vd_offset + verdef->vd_aux,
2583 : &verdaux_mem);
2584 :
2585 376 : if (verdaux != NULL)
2586 376 : printf ((*versym & 0x8000) ? "@%s" : "@@%s",
2587 : elf_strptr (ebl->elf, verdef_stridx,
2588 376 : verdaux->vda_name));
2589 : }
2590 : }
2591 : }
2592 : }
2593 :
2594 14879 : putchar_unlocked ('\n');
2595 : }
2596 : }
2597 :
2598 :
2599 : /* Print version information. */
2600 : static void
2601 40 : print_verinfo (Ebl *ebl)
2602 : {
2603 : /* Find the version information sections. For this we have to
2604 : search through the section table. */
2605 40 : Elf_Scn *scn = NULL;
2606 :
2607 1081 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2608 : {
2609 : /* Handle the section if it is part of the versioning handling. */
2610 : GElf_Shdr shdr_mem;
2611 1001 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2612 :
2613 1001 : if (likely (shdr != NULL))
2614 : {
2615 1001 : if (shdr->sh_type == SHT_GNU_verneed)
2616 10 : handle_verneed (ebl, scn, shdr);
2617 991 : else if (shdr->sh_type == SHT_GNU_verdef)
2618 4 : handle_verdef (ebl, scn, shdr);
2619 987 : else if (shdr->sh_type == SHT_GNU_versym)
2620 10 : handle_versym (ebl, scn, shdr);
2621 : }
2622 : }
2623 40 : }
2624 :
2625 :
2626 : static const char *
2627 125 : get_ver_flags (unsigned int flags)
2628 : {
2629 : static char buf[32];
2630 : char *endp;
2631 :
2632 125 : if (flags == 0)
2633 120 : return gettext ("none");
2634 :
2635 5 : if (flags & VER_FLG_BASE)
2636 4 : endp = stpcpy (buf, "BASE ");
2637 : else
2638 : endp = buf;
2639 :
2640 5 : if (flags & VER_FLG_WEAK)
2641 : {
2642 1 : if (endp != buf)
2643 0 : endp = stpcpy (endp, "| ");
2644 :
2645 1 : endp = stpcpy (endp, "WEAK ");
2646 : }
2647 :
2648 5 : if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
2649 : {
2650 0 : strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
2651 0 : buf[sizeof (buf) - 1] = '\0';
2652 : }
2653 :
2654 : return buf;
2655 : }
2656 :
2657 :
2658 : static void
2659 10 : handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2660 : {
2661 10 : int class = gelf_getclass (ebl->elf);
2662 :
2663 : /* Get the data of the section. */
2664 10 : Elf_Data *data = elf_getdata (scn, NULL);
2665 10 : if (data == NULL)
2666 0 : return;
2667 :
2668 : /* Get the section header string table index. */
2669 : size_t shstrndx;
2670 10 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2671 : error (EXIT_FAILURE, 0,
2672 0 : gettext ("cannot get section header string table index"));
2673 :
2674 : GElf_Shdr glink_mem;
2675 10 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2676 : &glink_mem);
2677 10 : if (glink == NULL)
2678 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
2679 : elf_ndxscn (scn));
2680 :
2681 50 : printf (ngettext ("\
2682 : \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2683 : "\
2684 : \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2685 : shdr->sh_info),
2686 10 : (unsigned int) elf_ndxscn (scn),
2687 10 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
2688 : class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2689 : shdr->sh_offset,
2690 10 : (unsigned int) shdr->sh_link,
2691 10 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
2692 :
2693 10 : unsigned int offset = 0;
2694 47 : for (int cnt = shdr->sh_info; --cnt >= 0; )
2695 : {
2696 : /* Get the data at the next offset. */
2697 : GElf_Verneed needmem;
2698 37 : GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
2699 37 : if (unlikely (need == NULL))
2700 : break;
2701 :
2702 185 : printf (gettext (" %#06x: Version: %hu File: %s Cnt: %hu\n"),
2703 37 : offset, (unsigned short int) need->vn_version,
2704 74 : elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
2705 37 : (unsigned short int) need->vn_cnt);
2706 :
2707 37 : unsigned int auxoffset = offset + need->vn_aux;
2708 122 : for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2709 : {
2710 : GElf_Vernaux auxmem;
2711 85 : GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
2712 85 : if (unlikely (aux == NULL))
2713 : break;
2714 :
2715 425 : printf (gettext (" %#06x: Name: %s Flags: %s Version: %hu\n"),
2716 : auxoffset,
2717 170 : elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
2718 85 : get_ver_flags (aux->vna_flags),
2719 85 : (unsigned short int) aux->vna_other);
2720 :
2721 85 : if (aux->vna_next == 0)
2722 : break;
2723 :
2724 48 : auxoffset += aux->vna_next;
2725 : }
2726 :
2727 : /* Find the next offset. */
2728 37 : if (need->vn_next == 0)
2729 : break;
2730 :
2731 27 : offset += need->vn_next;
2732 : }
2733 : }
2734 :
2735 :
2736 : static void
2737 4 : handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2738 : {
2739 : /* Get the data of the section. */
2740 4 : Elf_Data *data = elf_getdata (scn, NULL);
2741 4 : if (data == NULL)
2742 0 : return;
2743 :
2744 : /* Get the section header string table index. */
2745 : size_t shstrndx;
2746 4 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2747 : error (EXIT_FAILURE, 0,
2748 0 : gettext ("cannot get section header string table index"));
2749 :
2750 : GElf_Shdr glink_mem;
2751 4 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2752 : &glink_mem);
2753 4 : if (glink == NULL)
2754 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
2755 : elf_ndxscn (scn));
2756 :
2757 4 : int class = gelf_getclass (ebl->elf);
2758 20 : printf (ngettext ("\
2759 : \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2760 : "\
2761 : \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2762 : shdr->sh_info),
2763 4 : (unsigned int) elf_ndxscn (scn),
2764 4 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2765 : shdr->sh_info,
2766 : class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2767 : shdr->sh_offset,
2768 4 : (unsigned int) shdr->sh_link,
2769 4 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
2770 :
2771 4 : unsigned int offset = 0;
2772 44 : for (int cnt = shdr->sh_info; --cnt >= 0; )
2773 : {
2774 : /* Get the data at the next offset. */
2775 : GElf_Verdef defmem;
2776 40 : GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
2777 40 : if (unlikely (def == NULL))
2778 : break;
2779 :
2780 40 : unsigned int auxoffset = offset + def->vd_aux;
2781 : GElf_Verdaux auxmem;
2782 40 : GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
2783 40 : if (unlikely (aux == NULL))
2784 : break;
2785 :
2786 280 : printf (gettext ("\
2787 : %#06x: Version: %hd Flags: %s Index: %hd Cnt: %hd Name: %s\n"),
2788 40 : offset, def->vd_version,
2789 40 : get_ver_flags (def->vd_flags),
2790 40 : def->vd_ndx,
2791 40 : def->vd_cnt,
2792 80 : elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2793 :
2794 40 : auxoffset += aux->vda_next;
2795 40 : for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
2796 : {
2797 32 : aux = gelf_getverdaux (data, auxoffset, &auxmem);
2798 32 : if (unlikely (aux == NULL))
2799 : break;
2800 :
2801 96 : printf (gettext (" %#06x: Parent %d: %s\n"),
2802 : auxoffset, cnt2,
2803 64 : elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2804 :
2805 32 : if (aux->vda_next == 0)
2806 : break;
2807 :
2808 0 : auxoffset += aux->vda_next;
2809 : }
2810 :
2811 : /* Find the next offset. */
2812 40 : if (def->vd_next == 0)
2813 : break;
2814 36 : offset += def->vd_next;
2815 : }
2816 : }
2817 :
2818 :
2819 : static void
2820 10 : handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2821 : {
2822 10 : int class = gelf_getclass (ebl->elf);
2823 : const char **vername;
2824 : const char **filename;
2825 :
2826 : /* Get the data of the section. */
2827 10 : Elf_Data *data = elf_getdata (scn, NULL);
2828 10 : if (data == NULL)
2829 0 : return;
2830 :
2831 : /* Get the section header string table index. */
2832 : size_t shstrndx;
2833 10 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2834 : error (EXIT_FAILURE, 0,
2835 0 : gettext ("cannot get section header string table index"));
2836 :
2837 : /* We have to find the version definition section and extract the
2838 : version names. */
2839 : Elf_Scn *defscn = NULL;
2840 : Elf_Scn *needscn = NULL;
2841 :
2842 : Elf_Scn *verscn = NULL;
2843 368 : while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
2844 : {
2845 : GElf_Shdr vershdr_mem;
2846 358 : GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
2847 :
2848 358 : if (likely (vershdr != NULL))
2849 : {
2850 358 : if (vershdr->sh_type == SHT_GNU_verdef)
2851 : defscn = verscn;
2852 354 : else if (vershdr->sh_type == SHT_GNU_verneed)
2853 10 : needscn = verscn;
2854 : }
2855 : }
2856 :
2857 : size_t nvername;
2858 10 : if (defscn != NULL || needscn != NULL)
2859 : {
2860 : /* We have a version information (better should have). Now get
2861 : the version names. First find the maximum version number. */
2862 10 : nvername = 0;
2863 10 : if (defscn != NULL)
2864 : {
2865 : /* Run through the version definitions and find the highest
2866 : index. */
2867 4 : unsigned int offset = 0;
2868 : Elf_Data *defdata;
2869 : GElf_Shdr defshdrmem;
2870 : GElf_Shdr *defshdr;
2871 :
2872 4 : defdata = elf_getdata (defscn, NULL);
2873 4 : if (unlikely (defdata == NULL))
2874 0 : return;
2875 :
2876 4 : defshdr = gelf_getshdr (defscn, &defshdrmem);
2877 4 : if (unlikely (defshdr == NULL))
2878 : return;
2879 :
2880 36 : for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
2881 : {
2882 : GElf_Verdef defmem;
2883 : GElf_Verdef *def;
2884 :
2885 : /* Get the data at the next offset. */
2886 40 : def = gelf_getverdef (defdata, offset, &defmem);
2887 40 : if (unlikely (def == NULL))
2888 : break;
2889 :
2890 40 : nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
2891 :
2892 40 : if (def->vd_next == 0)
2893 : break;
2894 36 : offset += def->vd_next;
2895 : }
2896 : }
2897 10 : if (needscn != NULL)
2898 : {
2899 10 : unsigned int offset = 0;
2900 : Elf_Data *needdata;
2901 : GElf_Shdr needshdrmem;
2902 : GElf_Shdr *needshdr;
2903 :
2904 10 : needdata = elf_getdata (needscn, NULL);
2905 10 : if (unlikely (needdata == NULL))
2906 0 : return;
2907 :
2908 10 : needshdr = gelf_getshdr (needscn, &needshdrmem);
2909 10 : if (unlikely (needshdr == NULL))
2910 : return;
2911 :
2912 27 : for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
2913 : {
2914 : GElf_Verneed needmem;
2915 : GElf_Verneed *need;
2916 : unsigned int auxoffset;
2917 : int cnt2;
2918 :
2919 : /* Get the data at the next offset. */
2920 37 : need = gelf_getverneed (needdata, offset, &needmem);
2921 37 : if (unlikely (need == NULL))
2922 : break;
2923 :
2924 : /* Run through the auxiliary entries. */
2925 37 : auxoffset = offset + need->vn_aux;
2926 122 : for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
2927 : {
2928 : GElf_Vernaux auxmem;
2929 : GElf_Vernaux *aux;
2930 :
2931 85 : aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
2932 85 : if (unlikely (aux == NULL))
2933 : break;
2934 :
2935 85 : nvername = MAX (nvername,
2936 : (size_t) (aux->vna_other & 0x7fff));
2937 :
2938 85 : if (aux->vna_next == 0)
2939 : break;
2940 48 : auxoffset += aux->vna_next;
2941 : }
2942 :
2943 37 : if (need->vn_next == 0)
2944 : break;
2945 27 : offset += need->vn_next;
2946 : }
2947 : }
2948 :
2949 : /* This is the number of versions we know about. */
2950 10 : ++nvername;
2951 :
2952 : /* Allocate the array. */
2953 10 : vername = (const char **) alloca (nvername * sizeof (const char *));
2954 20 : memset(vername, 0, nvername * sizeof (const char *));
2955 10 : filename = (const char **) alloca (nvername * sizeof (const char *));
2956 20 : memset(filename, 0, nvername * sizeof (const char *));
2957 :
2958 : /* Run through the data structures again and collect the strings. */
2959 10 : if (defscn != NULL)
2960 : {
2961 : /* Run through the version definitions and find the highest
2962 : index. */
2963 4 : unsigned int offset = 0;
2964 : Elf_Data *defdata;
2965 : GElf_Shdr defshdrmem;
2966 : GElf_Shdr *defshdr;
2967 :
2968 4 : defdata = elf_getdata (defscn, NULL);
2969 4 : if (unlikely (defdata == NULL))
2970 0 : return;
2971 :
2972 4 : defshdr = gelf_getshdr (defscn, &defshdrmem);
2973 4 : if (unlikely (defshdr == NULL))
2974 : return;
2975 :
2976 36 : for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
2977 : {
2978 :
2979 : /* Get the data at the next offset. */
2980 : GElf_Verdef defmem;
2981 40 : GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
2982 40 : if (unlikely (def == NULL))
2983 : break;
2984 :
2985 : GElf_Verdaux auxmem;
2986 40 : GElf_Verdaux *aux = gelf_getverdaux (defdata,
2987 40 : offset + def->vd_aux,
2988 : &auxmem);
2989 40 : if (unlikely (aux == NULL))
2990 : break;
2991 :
2992 40 : vername[def->vd_ndx & 0x7fff]
2993 80 : = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
2994 40 : filename[def->vd_ndx & 0x7fff] = NULL;
2995 :
2996 40 : if (def->vd_next == 0)
2997 : break;
2998 36 : offset += def->vd_next;
2999 : }
3000 : }
3001 10 : if (needscn != NULL)
3002 : {
3003 10 : unsigned int offset = 0;
3004 :
3005 10 : Elf_Data *needdata = elf_getdata (needscn, NULL);
3006 : GElf_Shdr needshdrmem;
3007 10 : GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
3008 10 : if (unlikely (needdata == NULL || needshdr == NULL))
3009 0 : return;
3010 :
3011 27 : for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
3012 : {
3013 : /* Get the data at the next offset. */
3014 : GElf_Verneed needmem;
3015 37 : GElf_Verneed *need = gelf_getverneed (needdata, offset,
3016 : &needmem);
3017 37 : if (unlikely (need == NULL))
3018 : break;
3019 :
3020 : /* Run through the auxiliary entries. */
3021 37 : unsigned int auxoffset = offset + need->vn_aux;
3022 122 : for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
3023 : {
3024 : GElf_Vernaux auxmem;
3025 85 : GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
3026 : &auxmem);
3027 85 : if (unlikely (aux == NULL))
3028 : break;
3029 :
3030 85 : vername[aux->vna_other & 0x7fff]
3031 170 : = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
3032 85 : filename[aux->vna_other & 0x7fff]
3033 170 : = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
3034 :
3035 85 : if (aux->vna_next == 0)
3036 : break;
3037 48 : auxoffset += aux->vna_next;
3038 : }
3039 :
3040 37 : if (need->vn_next == 0)
3041 : break;
3042 27 : offset += need->vn_next;
3043 : }
3044 : }
3045 : }
3046 : else
3047 : {
3048 : vername = NULL;
3049 : nvername = 1;
3050 : filename = NULL;
3051 : }
3052 :
3053 : GElf_Shdr glink_mem;
3054 10 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
3055 : &glink_mem);
3056 10 : size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_HALF, 1, EV_CURRENT);
3057 10 : if (glink == NULL)
3058 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
3059 : elf_ndxscn (scn));
3060 :
3061 : /* Print the header. */
3062 60 : printf (ngettext ("\
3063 : \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
3064 : "\
3065 : \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
3066 : shdr->sh_size / sh_entsize),
3067 10 : (unsigned int) elf_ndxscn (scn),
3068 10 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3069 10 : (int) (shdr->sh_size / sh_entsize),
3070 : class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
3071 : shdr->sh_offset,
3072 10 : (unsigned int) shdr->sh_link,
3073 10 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
3074 :
3075 : /* Now we can finally look at the actual contents of this section. */
3076 1310 : for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
3077 : {
3078 1300 : if (cnt % 2 == 0)
3079 : printf ("\n %4d:", cnt);
3080 :
3081 : GElf_Versym symmem;
3082 1300 : GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
3083 1300 : if (sym == NULL)
3084 : break;
3085 :
3086 1300 : switch (*sym)
3087 : {
3088 : ssize_t n;
3089 112 : case 0:
3090 112 : fputs_unlocked (gettext (" 0 *local* "),
3091 : stdout);
3092 : break;
3093 :
3094 12 : case 1:
3095 12 : fputs_unlocked (gettext (" 1 *global* "),
3096 : stdout);
3097 : break;
3098 :
3099 1176 : default:
3100 4704 : n = printf ("%4d%c%s",
3101 1176 : *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
3102 : (vername != NULL
3103 1176 : && (unsigned int) (*sym & 0x7fff) < nvername)
3104 1176 : ? vername[*sym & 0x7fff] : "???");
3105 1176 : if ((unsigned int) (*sym & 0x7fff) < nvername
3106 1176 : && filename != NULL && filename[*sym & 0x7fff] != NULL)
3107 1600 : n += printf ("(%s)", filename[*sym & 0x7fff]);
3108 1176 : printf ("%*s", MAX (0, 33 - (int) n), " ");
3109 : break;
3110 : }
3111 : }
3112 10 : putchar_unlocked ('\n');
3113 : }
3114 :
3115 :
3116 : static void
3117 10 : print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
3118 : uint_fast32_t maxlength, Elf32_Word nbucket,
3119 : uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
3120 : {
3121 10 : uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
3122 :
3123 326 : for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
3124 316 : ++counts[lengths[cnt]];
3125 :
3126 : GElf_Shdr glink_mem;
3127 10 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf,
3128 10 : shdr->sh_link),
3129 : &glink_mem);
3130 10 : if (glink == NULL)
3131 : {
3132 0 : error (0, 0, gettext ("invalid sh_link value in section %zu"),
3133 : elf_ndxscn (scn));
3134 0 : return;
3135 : }
3136 :
3137 60 : printf (ngettext ("\
3138 : \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",
3139 : "\
3140 : \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",
3141 : nbucket),
3142 10 : (unsigned int) elf_ndxscn (scn),
3143 10 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3144 : (int) nbucket,
3145 10 : gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
3146 : shdr->sh_addr,
3147 : shdr->sh_offset,
3148 10 : (unsigned int) shdr->sh_link,
3149 10 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
3150 :
3151 10 : if (extrastr != NULL)
3152 10 : fputs (extrastr, stdout);
3153 :
3154 10 : if (likely (nbucket > 0))
3155 : {
3156 10 : uint64_t success = 0;
3157 :
3158 : /* xgettext:no-c-format */
3159 10 : fputs_unlocked (gettext ("\
3160 : Length Number % of total Coverage\n"), stdout);
3161 20 : printf (gettext (" 0 %6" PRIu32 " %5.1f%%\n"),
3162 10 : counts[0], (counts[0] * 100.0) / nbucket);
3163 :
3164 10 : uint64_t nzero_counts = 0;
3165 47 : for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
3166 : {
3167 37 : nzero_counts += counts[cnt] * cnt;
3168 111 : printf (gettext ("\
3169 : %7d %6" PRIu32 " %5.1f%% %5.1f%%\n"),
3170 37 : (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
3171 37 : (nzero_counts * 100.0) / nsyms);
3172 : }
3173 :
3174 : Elf32_Word acc = 0;
3175 37 : for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
3176 : {
3177 37 : acc += cnt;
3178 37 : success += counts[cnt] * acc;
3179 : }
3180 :
3181 20 : printf (gettext ("\
3182 : Average number of tests: successful lookup: %f\n\
3183 : unsuccessful lookup: %f\n"),
3184 10 : (double) success / (double) nzero_counts,
3185 10 : (double) nzero_counts / (double) nbucket);
3186 : }
3187 :
3188 10 : free (counts);
3189 : }
3190 :
3191 :
3192 : /* This function handles the traditional System V-style hash table format. */
3193 : static void
3194 0 : handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
3195 : {
3196 0 : Elf_Data *data = elf_getdata (scn, NULL);
3197 0 : if (unlikely (data == NULL))
3198 : {
3199 0 : error (0, 0, gettext ("cannot get data for section %d: %s"),
3200 0 : (int) elf_ndxscn (scn), elf_errmsg (-1));
3201 : return;
3202 : }
3203 :
3204 0 : if (unlikely (data->d_size < 2 * sizeof (Elf32_Word)))
3205 : {
3206 0 : invalid_data:
3207 0 : error (0, 0, gettext ("invalid data in sysv.hash section %d"),
3208 0 : (int) elf_ndxscn (scn));
3209 : return;
3210 : }
3211 :
3212 0 : Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
3213 0 : Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
3214 :
3215 0 : uint64_t used_buf = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
3216 0 : if (used_buf > data->d_size)
3217 : goto invalid_data;
3218 :
3219 0 : Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
3220 0 : Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
3221 :
3222 0 : uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
3223 :
3224 0 : uint_fast32_t maxlength = 0;
3225 0 : uint_fast32_t nsyms = 0;
3226 0 : for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
3227 : {
3228 0 : Elf32_Word inner = bucket[cnt];
3229 0 : Elf32_Word chain_len = 0;
3230 0 : while (inner > 0 && inner < nchain)
3231 : {
3232 0 : ++nsyms;
3233 0 : ++chain_len;
3234 0 : if (chain_len > nchain)
3235 : {
3236 0 : error (0, 0, gettext ("invalid chain in sysv.hash section %d"),
3237 0 : (int) elf_ndxscn (scn));
3238 0 : free (lengths);
3239 0 : return;
3240 : }
3241 0 : if (maxlength < ++lengths[cnt])
3242 0 : ++maxlength;
3243 :
3244 0 : inner = chain[inner];
3245 : }
3246 : }
3247 :
3248 0 : print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
3249 : lengths, NULL);
3250 :
3251 0 : free (lengths);
3252 : }
3253 :
3254 :
3255 : /* This function handles the incorrect, System V-style hash table
3256 : format some 64-bit architectures use. */
3257 : static void
3258 0 : handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
3259 : {
3260 0 : Elf_Data *data = elf_getdata (scn, NULL);
3261 0 : if (unlikely (data == NULL))
3262 : {
3263 0 : error (0, 0, gettext ("cannot get data for section %d: %s"),
3264 0 : (int) elf_ndxscn (scn), elf_errmsg (-1));
3265 : return;
3266 : }
3267 :
3268 0 : if (unlikely (data->d_size < 2 * sizeof (Elf64_Xword)))
3269 : {
3270 0 : invalid_data:
3271 0 : error (0, 0, gettext ("invalid data in sysv.hash64 section %d"),
3272 0 : (int) elf_ndxscn (scn));
3273 : return;
3274 : }
3275 :
3276 0 : Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
3277 0 : Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
3278 :
3279 0 : uint64_t maxwords = data->d_size / sizeof (Elf64_Xword);
3280 0 : if (maxwords < 2
3281 0 : || maxwords - 2 < nbucket
3282 0 : || maxwords - 2 - nbucket < nchain)
3283 : goto invalid_data;
3284 :
3285 0 : Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
3286 0 : Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
3287 :
3288 0 : uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
3289 :
3290 0 : uint_fast32_t maxlength = 0;
3291 0 : uint_fast32_t nsyms = 0;
3292 0 : for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
3293 : {
3294 0 : Elf64_Xword inner = bucket[cnt];
3295 0 : Elf64_Xword chain_len = 0;
3296 0 : while (inner > 0 && inner < nchain)
3297 : {
3298 0 : ++nsyms;
3299 0 : ++chain_len;
3300 0 : if (chain_len > nchain)
3301 : {
3302 0 : error (0, 0, gettext ("invalid chain in sysv.hash64 section %d"),
3303 0 : (int) elf_ndxscn (scn));
3304 0 : free (lengths);
3305 0 : return;
3306 : }
3307 0 : if (maxlength < ++lengths[cnt])
3308 0 : ++maxlength;
3309 :
3310 0 : inner = chain[inner];
3311 : }
3312 : }
3313 :
3314 0 : print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
3315 : lengths, NULL);
3316 :
3317 0 : free (lengths);
3318 : }
3319 :
3320 :
3321 : /* This function handles the GNU-style hash table format. */
3322 : static void
3323 10 : handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
3324 : {
3325 10 : uint32_t *lengths = NULL;
3326 10 : Elf_Data *data = elf_getdata (scn, NULL);
3327 10 : if (unlikely (data == NULL))
3328 : {
3329 0 : error (0, 0, gettext ("cannot get data for section %d: %s"),
3330 0 : (int) elf_ndxscn (scn), elf_errmsg (-1));
3331 0 : return;
3332 : }
3333 :
3334 10 : if (unlikely (data->d_size < 4 * sizeof (Elf32_Word)))
3335 : {
3336 0 : invalid_data:
3337 0 : free (lengths);
3338 0 : error (0, 0, gettext ("invalid data in gnu.hash section %d"),
3339 0 : (int) elf_ndxscn (scn));
3340 : return;
3341 : }
3342 :
3343 10 : Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
3344 10 : Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
3345 :
3346 : /* Next comes the size of the bitmap. It's measured in words for
3347 : the architecture. It's 32 bits for 32 bit archs, and 64 bits for
3348 : 64 bit archs. There is always a bloom filter present, so zero is
3349 : an invalid value. */
3350 10 : Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
3351 10 : if (gelf_getclass (ebl->elf) == ELFCLASS64)
3352 10 : bitmask_words *= 2;
3353 :
3354 10 : if (bitmask_words == 0)
3355 : goto invalid_data;
3356 :
3357 10 : Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
3358 :
3359 : /* Is there still room for the sym chain?
3360 : Use uint64_t calculation to prevent 32bit overlow. */
3361 10 : uint64_t used_buf = (4ULL + bitmask_words + nbucket) * sizeof (Elf32_Word);
3362 10 : uint32_t max_nsyms = (data->d_size - used_buf) / sizeof (Elf32_Word);
3363 10 : if (used_buf > data->d_size)
3364 : goto invalid_data;
3365 :
3366 10 : lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
3367 :
3368 10 : Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
3369 10 : Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
3370 10 : Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
3371 10 : + nbucket];
3372 :
3373 : /* Compute distribution of chain lengths. */
3374 10 : uint_fast32_t maxlength = 0;
3375 10 : uint_fast32_t nsyms = 0;
3376 326 : for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
3377 316 : if (bucket[cnt] != 0)
3378 : {
3379 218 : Elf32_Word inner = bucket[cnt] - symbias;
3380 : do
3381 : {
3382 417 : ++nsyms;
3383 417 : if (maxlength < ++lengths[cnt])
3384 37 : ++maxlength;
3385 417 : if (inner >= max_nsyms)
3386 : goto invalid_data;
3387 : }
3388 417 : while ((chain[inner++] & 1) == 0);
3389 : }
3390 :
3391 : /* Count bits in bitmask. */
3392 : uint_fast32_t nbits = 0;
3393 112 : for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
3394 : {
3395 112 : uint_fast32_t word = bitmask[cnt];
3396 :
3397 112 : word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
3398 112 : word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
3399 112 : word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
3400 112 : word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
3401 112 : nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
3402 : }
3403 :
3404 : char *str;
3405 20 : if (unlikely (asprintf (&str, gettext ("\
3406 : Symbol Bias: %u\n\
3407 : Bitmask Size: %zu bytes %" PRIuFAST32 "%% bits set 2nd hash shift: %u\n"),
3408 : (unsigned int) symbias,
3409 : bitmask_words * sizeof (Elf32_Word),
3410 : ((nbits * 100 + 50)
3411 : / (uint_fast32_t) (bitmask_words
3412 : * sizeof (Elf32_Word) * 8)),
3413 : (unsigned int) shift) == -1))
3414 0 : error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
3415 :
3416 10 : print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
3417 : lengths, str);
3418 :
3419 10 : free (str);
3420 10 : free (lengths);
3421 : }
3422 :
3423 :
3424 : /* Find the symbol table(s). For this we have to search through the
3425 : section table. */
3426 : static void
3427 40 : handle_hash (Ebl *ebl)
3428 : {
3429 : /* Get the section header string table index. */
3430 : size_t shstrndx;
3431 40 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
3432 : error (EXIT_FAILURE, 0,
3433 0 : gettext ("cannot get section header string table index"));
3434 :
3435 : Elf_Scn *scn = NULL;
3436 1041 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3437 : {
3438 : /* Handle the section if it is a symbol table. */
3439 : GElf_Shdr shdr_mem;
3440 1001 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3441 :
3442 1001 : if (likely (shdr != NULL))
3443 : {
3444 1001 : if ((shdr->sh_type == SHT_HASH || shdr->sh_type == SHT_GNU_HASH)
3445 10 : && (shdr->sh_flags & SHF_COMPRESSED) != 0)
3446 : {
3447 0 : if (elf_compress (scn, 0, 0) < 0)
3448 0 : printf ("WARNING: %s [%zd]\n",
3449 : gettext ("Couldn't uncompress section"),
3450 : elf_ndxscn (scn));
3451 0 : shdr = gelf_getshdr (scn, &shdr_mem);
3452 0 : if (unlikely (shdr == NULL))
3453 0 : error (EXIT_FAILURE, 0,
3454 0 : gettext ("cannot get section [%zd] header: %s"),
3455 : elf_ndxscn (scn), elf_errmsg (-1));
3456 : }
3457 :
3458 1001 : if (shdr->sh_type == SHT_HASH)
3459 : {
3460 0 : if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
3461 0 : handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
3462 : else
3463 0 : handle_sysv_hash (ebl, scn, shdr, shstrndx);
3464 : }
3465 1001 : else if (shdr->sh_type == SHT_GNU_HASH)
3466 10 : handle_gnu_hash (ebl, scn, shdr, shstrndx);
3467 : }
3468 : }
3469 40 : }
3470 :
3471 :
3472 : static void
3473 44 : print_liblist (Ebl *ebl)
3474 : {
3475 : /* Find the library list sections. For this we have to search
3476 : through the section table. */
3477 44 : Elf_Scn *scn = NULL;
3478 :
3479 : /* Get the section header string table index. */
3480 : size_t shstrndx;
3481 44 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
3482 : error (EXIT_FAILURE, 0,
3483 0 : gettext ("cannot get section header string table index"));
3484 :
3485 1104 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3486 : {
3487 : GElf_Shdr shdr_mem;
3488 1060 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3489 :
3490 1060 : if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
3491 : {
3492 0 : size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_LIB, 1, EV_CURRENT);
3493 0 : int nentries = shdr->sh_size / sh_entsize;
3494 0 : printf (ngettext ("\
3495 : \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
3496 : "\
3497 : \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
3498 : nentries),
3499 : elf_ndxscn (scn),
3500 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3501 : shdr->sh_offset,
3502 : nentries);
3503 :
3504 0 : Elf_Data *data = elf_getdata (scn, NULL);
3505 0 : if (data == NULL)
3506 0 : return;
3507 :
3508 0 : puts (gettext ("\
3509 : Library Time Stamp Checksum Version Flags"));
3510 :
3511 0 : for (int cnt = 0; cnt < nentries; ++cnt)
3512 : {
3513 : GElf_Lib lib_mem;
3514 0 : GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
3515 0 : if (unlikely (lib == NULL))
3516 0 : continue;
3517 :
3518 0 : time_t t = (time_t) lib->l_time_stamp;
3519 0 : struct tm *tm = gmtime (&t);
3520 0 : if (unlikely (tm == NULL))
3521 0 : continue;
3522 :
3523 0 : printf (" [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
3524 0 : cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
3525 0 : tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
3526 : tm->tm_hour, tm->tm_min, tm->tm_sec,
3527 0 : (unsigned int) lib->l_checksum,
3528 0 : (unsigned int) lib->l_version,
3529 0 : (unsigned int) lib->l_flags);
3530 : }
3531 : }
3532 : }
3533 : }
3534 :
3535 : static void
3536 44 : print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
3537 : {
3538 : /* Find the object attributes sections. For this we have to search
3539 : through the section table. */
3540 44 : Elf_Scn *scn = NULL;
3541 :
3542 : /* Get the section header string table index. */
3543 : size_t shstrndx;
3544 44 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
3545 : error (EXIT_FAILURE, 0,
3546 0 : gettext ("cannot get section header string table index"));
3547 :
3548 1104 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3549 : {
3550 : GElf_Shdr shdr_mem;
3551 1060 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3552 :
3553 1060 : if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
3554 1057 : && (shdr->sh_type != SHT_ARM_ATTRIBUTES
3555 1 : || ehdr->e_machine != EM_ARM)))
3556 1056 : continue;
3557 :
3558 12 : printf (gettext ("\
3559 : \nObject attributes section [%2zu] '%s' of %" PRIu64
3560 : " bytes at offset %#0" PRIx64 ":\n"),
3561 : elf_ndxscn (scn),
3562 4 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3563 : shdr->sh_size, shdr->sh_offset);
3564 :
3565 4 : Elf_Data *data = elf_rawdata (scn, NULL);
3566 4 : if (unlikely (data == NULL || data->d_size == 0))
3567 0 : return;
3568 :
3569 4 : const unsigned char *p = data->d_buf;
3570 :
3571 : /* There is only one 'version', A. */
3572 4 : if (unlikely (*p++ != 'A'))
3573 : return;
3574 :
3575 4 : fputs_unlocked (gettext (" Owner Size\n"), stdout);
3576 :
3577 : inline size_t left (void)
3578 : {
3579 8 : return (const unsigned char *) data->d_buf + data->d_size - p;
3580 : }
3581 :
3582 : /* Loop over the sections. */
3583 8 : while (left () >= 4)
3584 : {
3585 : /* Section length. */
3586 : uint32_t len;
3587 4 : memcpy (&len, p, sizeof len);
3588 :
3589 4 : if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3590 4 : CONVERT (len);
3591 :
3592 4 : if (unlikely (len > left ()))
3593 : break;
3594 :
3595 : /* Section vendor name. */
3596 4 : const unsigned char *name = p + sizeof len;
3597 4 : p += len;
3598 :
3599 4 : unsigned const char *q = memchr (name, '\0', len);
3600 4 : if (unlikely (q == NULL))
3601 : break;
3602 4 : ++q;
3603 :
3604 8 : printf (gettext (" %-13s %4" PRIu32 "\n"), name, len);
3605 :
3606 8 : bool gnu_vendor = (q - name == sizeof "gnu"
3607 4 : && !memcmp (name, "gnu", sizeof "gnu"));
3608 :
3609 : /* Loop over subsections. */
3610 4 : if (shdr->sh_type != SHT_GNU_ATTRIBUTES
3611 3 : || gnu_vendor)
3612 8 : while (q < p)
3613 : {
3614 4 : const unsigned char *const sub = q;
3615 :
3616 : unsigned int subsection_tag;
3617 4 : get_uleb128 (subsection_tag, q, p);
3618 4 : if (unlikely (q >= p))
3619 : break;
3620 :
3621 : uint32_t subsection_len;
3622 4 : if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
3623 : break;
3624 :
3625 4 : memcpy (&subsection_len, q, sizeof subsection_len);
3626 :
3627 4 : if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3628 4 : CONVERT (subsection_len);
3629 :
3630 : /* Don't overflow, ptrdiff_t might be 32bits, but signed. */
3631 4 : if (unlikely (subsection_len == 0
3632 : || subsection_len >= (uint32_t) PTRDIFF_MAX
3633 : || p - sub < (ptrdiff_t) subsection_len))
3634 : break;
3635 :
3636 4 : const unsigned char *r = q + sizeof subsection_len;
3637 4 : q = sub + subsection_len;
3638 :
3639 4 : switch (subsection_tag)
3640 : {
3641 0 : default:
3642 : /* Unknown subsection, print and skip. */
3643 0 : printf (gettext (" %-4u %12" PRIu32 "\n"),
3644 : subsection_tag, subsection_len);
3645 : break;
3646 :
3647 4 : case 1: /* Tag_File */
3648 4 : printf (gettext (" File: %11" PRIu32 "\n"),
3649 : subsection_len);
3650 :
3651 26 : while (r < q)
3652 22 : {
3653 : unsigned int tag;
3654 22 : get_uleb128 (tag, r, q);
3655 22 : if (unlikely (r >= q))
3656 : break;
3657 :
3658 : /* GNU style tags have either a uleb128 value,
3659 : when lowest bit is not set, or a string
3660 : when the lowest bit is set.
3661 : "compatibility" (32) is special. It has
3662 : both a string and a uleb128 value. For
3663 : non-gnu we assume 6 till 31 only take ints.
3664 : XXX see arm backend, do we need a separate
3665 : hook? */
3666 22 : uint64_t value = 0;
3667 22 : const char *string = NULL;
3668 22 : if (tag == 32 || (tag & 1) == 0
3669 8 : || (! gnu_vendor && (tag > 5 && tag < 32)))
3670 : {
3671 21 : get_uleb128 (value, r, q);
3672 21 : if (r > q)
3673 : break;
3674 : }
3675 22 : if (tag == 32
3676 22 : || ((tag & 1) != 0
3677 8 : && (gnu_vendor
3678 8 : || (! gnu_vendor && tag > 32)))
3679 22 : || (! gnu_vendor && tag > 3 && tag < 6))
3680 : {
3681 1 : string = (const char *) r;
3682 1 : r = memchr (r, '\0', q - r);
3683 1 : if (r == NULL)
3684 : break;
3685 1 : ++r;
3686 : }
3687 :
3688 22 : const char *tag_name = NULL;
3689 22 : const char *value_name = NULL;
3690 22 : ebl_check_object_attribute (ebl, (const char *) name,
3691 : tag, value,
3692 : &tag_name, &value_name);
3693 :
3694 22 : if (tag_name != NULL)
3695 : {
3696 22 : if (tag == 32)
3697 0 : printf (gettext (" %s: %" PRId64 ", %s\n"),
3698 : tag_name, value, string);
3699 22 : else if (string == NULL && value_name == NULL)
3700 1 : printf (gettext (" %s: %" PRId64 "\n"),
3701 : tag_name, value);
3702 : else
3703 21 : printf (gettext (" %s: %s\n"),
3704 : tag_name, string ?: value_name);
3705 : }
3706 : else
3707 : {
3708 : /* For "gnu" vendor 32 "compatibility" has
3709 : already been handled above. */
3710 0 : assert (tag != 32
3711 : || strcmp ((const char *) name, "gnu"));
3712 0 : if (string == NULL)
3713 0 : printf (gettext (" %u: %" PRId64 "\n"),
3714 : tag, value);
3715 : else
3716 0 : printf (gettext (" %u: %s\n"),
3717 : tag, string);
3718 : }
3719 : }
3720 : }
3721 : }
3722 : }
3723 : }
3724 : }
3725 :
3726 :
3727 : void
3728 606854 : print_dwarf_addr (Dwfl_Module *dwflmod,
3729 : int address_size, Dwarf_Addr address, Dwarf_Addr raw)
3730 : {
3731 : /* See if there is a name we can give for this address. */
3732 : GElf_Sym sym;
3733 606854 : GElf_Off off = 0;
3734 1820534 : const char *name = (print_address_names && ! print_unresolved_addresses)
3735 606754 : ? dwfl_module_addrinfo (dwflmod, address, &off, &sym, NULL, NULL, NULL)
3736 1213608 : : NULL;
3737 :
3738 : const char *scn;
3739 606854 : if (print_unresolved_addresses)
3740 : {
3741 72 : address = raw;
3742 72 : scn = NULL;
3743 : }
3744 : else
3745 : {
3746 : /* Relativize the address. */
3747 606782 : int n = dwfl_module_relocations (dwflmod);
3748 606782 : int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
3749 :
3750 : /* In an ET_REL file there is a section name to refer to. */
3751 : scn = (i < 0 ? NULL
3752 605782 : : dwfl_module_relocation_info (dwflmod, i, NULL));
3753 : }
3754 :
3755 606854 : if ((name != NULL
3756 595739 : ? (off != 0
3757 : ? (scn != NULL
3758 : ? (address_size == 0
3759 294852 : ? printf ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">",
3760 : scn, address, name, off)
3761 1270143 : : printf ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">",
3762 423381 : scn, 2 + address_size * 2, address,
3763 : name, off))
3764 : : (address_size == 0
3765 338 : ? printf ("%#" PRIx64 " <%s+%#" PRIx64 ">",
3766 : address, name, off)
3767 1410 : : printf ("%#0*" PRIx64 " <%s+%#" PRIx64 ">",
3768 470 : 2 + address_size * 2, address,
3769 : name, off)))
3770 : : (scn != NULL
3771 : ? (address_size == 0
3772 12612 : ? printf ("%s+%#" PRIx64 " <%s>", scn, address, name)
3773 53142 : : printf ("%s+%#0*" PRIx64 " <%s>",
3774 17714 : scn, 2 + address_size * 2, address, name))
3775 : : (address_size == 0
3776 158 : ? printf ("%#" PRIx64 " <%s>", address, name)
3777 582 : : printf ("%#0*" PRIx64 " <%s>",
3778 194 : 2 + address_size * 2, address, name))))
3779 : : (scn != NULL
3780 : ? (address_size == 0
3781 11244 : ? printf ("%s+%#" PRIx64, scn, address)
3782 10666 : : printf ("%s+%#0*" PRIx64, scn, 2 + address_size * 2, address))
3783 : : (address_size == 0
3784 64 : ? printf ("%#" PRIx64, address)
3785 1809447 : : printf ("%#0*" PRIx64, 2 + address_size * 2, address)))) < 0)
3786 0 : error (EXIT_FAILURE, 0, _("sprintf failure"));
3787 606854 : }
3788 :
3789 :
3790 : static const char *
3791 771589 : dwarf_tag_string (unsigned int tag)
3792 : {
3793 771589 : switch (tag)
3794 : {
3795 : #define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
3796 0 : DWARF_ALL_KNOWN_DW_TAG
3797 : #undef DWARF_ONE_KNOWN_DW_TAG
3798 0 : default:
3799 0 : return NULL;
3800 : }
3801 : }
3802 :
3803 :
3804 : static const char *
3805 2705738 : dwarf_attr_string (unsigned int attrnum)
3806 : {
3807 2705738 : switch (attrnum)
3808 : {
3809 : #define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
3810 4379 : DWARF_ALL_KNOWN_DW_AT
3811 : #undef DWARF_ONE_KNOWN_DW_AT
3812 0 : default:
3813 0 : return NULL;
3814 : }
3815 : }
3816 :
3817 :
3818 : static const char *
3819 2705744 : dwarf_form_string (unsigned int form)
3820 : {
3821 2705744 : switch (form)
3822 : {
3823 : #define DWARF_ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
3824 21 : DWARF_ALL_KNOWN_DW_FORM
3825 : #undef DWARF_ONE_KNOWN_DW_FORM
3826 0 : default:
3827 0 : return NULL;
3828 : }
3829 : }
3830 :
3831 :
3832 : static const char *
3833 1152 : dwarf_lang_string (unsigned int lang)
3834 : {
3835 1152 : switch (lang)
3836 : {
3837 : #define DWARF_ONE_KNOWN_DW_LANG(NAME, CODE) case CODE: return #NAME;
3838 1 : DWARF_ALL_KNOWN_DW_LANG
3839 : #undef DWARF_ONE_KNOWN_DW_LANG
3840 0 : default:
3841 0 : return NULL;
3842 : }
3843 : }
3844 :
3845 :
3846 : static const char *
3847 : dwarf_inline_string (unsigned int code)
3848 : {
3849 : static const char *const known[] =
3850 : {
3851 : #define DWARF_ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME,
3852 : DWARF_ALL_KNOWN_DW_INL
3853 : #undef DWARF_ONE_KNOWN_DW_INL
3854 : };
3855 :
3856 2927 : if (likely (code < sizeof (known) / sizeof (known[0])))
3857 2927 : return known[code];
3858 :
3859 : return NULL;
3860 : }
3861 :
3862 :
3863 : static const char *
3864 : dwarf_encoding_string (unsigned int code)
3865 : {
3866 : static const char *const known[] =
3867 : {
3868 : #define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
3869 : DWARF_ALL_KNOWN_DW_ATE
3870 : #undef DWARF_ONE_KNOWN_DW_ATE
3871 : };
3872 :
3873 16426 : if (likely (code < sizeof (known) / sizeof (known[0])))
3874 16426 : return known[code];
3875 :
3876 : return NULL;
3877 : }
3878 :
3879 :
3880 : static const char *
3881 : dwarf_access_string (unsigned int code)
3882 : {
3883 : static const char *const known[] =
3884 : {
3885 : #define DWARF_ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME,
3886 : DWARF_ALL_KNOWN_DW_ACCESS
3887 : #undef DWARF_ONE_KNOWN_DW_ACCESS
3888 : };
3889 :
3890 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3891 0 : return known[code];
3892 :
3893 : return NULL;
3894 : }
3895 :
3896 :
3897 : static const char *
3898 : dwarf_defaulted_string (unsigned int code)
3899 : {
3900 : static const char *const known[] =
3901 : {
3902 : #define DWARF_ONE_KNOWN_DW_DEFAULTED(NAME, CODE) [CODE] = #NAME,
3903 : DWARF_ALL_KNOWN_DW_DEFAULTED
3904 : #undef DWARF_ONE_KNOWN_DW_DEFAULTED
3905 : };
3906 :
3907 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3908 0 : return known[code];
3909 :
3910 : return NULL;
3911 : }
3912 :
3913 :
3914 : static const char *
3915 : dwarf_visibility_string (unsigned int code)
3916 : {
3917 : static const char *const known[] =
3918 : {
3919 : #define DWARF_ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
3920 : DWARF_ALL_KNOWN_DW_VIS
3921 : #undef DWARF_ONE_KNOWN_DW_VIS
3922 : };
3923 :
3924 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3925 0 : return known[code];
3926 :
3927 : return NULL;
3928 : }
3929 :
3930 :
3931 : static const char *
3932 : dwarf_virtuality_string (unsigned int code)
3933 : {
3934 : static const char *const known[] =
3935 : {
3936 : #define DWARF_ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
3937 : DWARF_ALL_KNOWN_DW_VIRTUALITY
3938 : #undef DWARF_ONE_KNOWN_DW_VIRTUALITY
3939 : };
3940 :
3941 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3942 0 : return known[code];
3943 :
3944 : return NULL;
3945 : }
3946 :
3947 :
3948 : static const char *
3949 : dwarf_identifier_case_string (unsigned int code)
3950 : {
3951 : static const char *const known[] =
3952 : {
3953 : #define DWARF_ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
3954 : DWARF_ALL_KNOWN_DW_ID
3955 : #undef DWARF_ONE_KNOWN_DW_ID
3956 : };
3957 :
3958 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3959 0 : return known[code];
3960 :
3961 : return NULL;
3962 : }
3963 :
3964 :
3965 : static const char *
3966 : dwarf_calling_convention_string (unsigned int code)
3967 : {
3968 : static const char *const known[] =
3969 : {
3970 : #define DWARF_ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
3971 : DWARF_ALL_KNOWN_DW_CC
3972 : #undef DWARF_ONE_KNOWN_DW_CC
3973 : };
3974 :
3975 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3976 0 : return known[code];
3977 :
3978 : return NULL;
3979 : }
3980 :
3981 :
3982 : static const char *
3983 : dwarf_ordering_string (unsigned int code)
3984 : {
3985 : static const char *const known[] =
3986 : {
3987 : #define DWARF_ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
3988 : DWARF_ALL_KNOWN_DW_ORD
3989 : #undef DWARF_ONE_KNOWN_DW_ORD
3990 : };
3991 :
3992 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3993 0 : return known[code];
3994 :
3995 : return NULL;
3996 : }
3997 :
3998 :
3999 : static const char *
4000 : dwarf_discr_list_string (unsigned int code)
4001 : {
4002 : static const char *const known[] =
4003 : {
4004 : #define DWARF_ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
4005 : DWARF_ALL_KNOWN_DW_DSC
4006 : #undef DWARF_ONE_KNOWN_DW_DSC
4007 : };
4008 :
4009 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
4010 0 : return known[code];
4011 :
4012 : return NULL;
4013 : }
4014 :
4015 :
4016 : static const char *
4017 : dwarf_locexpr_opcode_string (unsigned int code)
4018 : {
4019 : static const char *const known[] =
4020 : {
4021 : /* Normally we can't affort building huge table of 64K entries,
4022 : most of them zero, just because there are a couple defined
4023 : values at the far end. In case of opcodes, it's OK. */
4024 : #define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
4025 : DWARF_ALL_KNOWN_DW_OP
4026 : #undef DWARF_ONE_KNOWN_DW_OP
4027 : };
4028 :
4029 381451 : if (likely (code < sizeof (known) / sizeof (known[0])))
4030 381451 : return known[code];
4031 :
4032 : return NULL;
4033 : }
4034 :
4035 :
4036 : static const char *
4037 : dwarf_unit_string (unsigned int type)
4038 : {
4039 8 : switch (type)
4040 : {
4041 : #define DWARF_ONE_KNOWN_DW_UT(NAME, CODE) case CODE: return #NAME;
4042 0 : DWARF_ALL_KNOWN_DW_UT
4043 : #undef DWARF_ONE_KNOWN_DW_UT
4044 0 : default:
4045 : return NULL;
4046 : }
4047 : }
4048 :
4049 :
4050 : static const char *
4051 14 : dwarf_range_list_encoding_string (unsigned int kind)
4052 : {
4053 14 : switch (kind)
4054 : {
4055 : #define DWARF_ONE_KNOWN_DW_RLE(NAME, CODE) case CODE: return #NAME;
4056 0 : DWARF_ALL_KNOWN_DW_RLE
4057 : #undef DWARF_ONE_KNOWN_DW_RLE
4058 0 : default:
4059 0 : return NULL;
4060 : }
4061 : }
4062 :
4063 :
4064 : static const char *
4065 89 : dwarf_loc_list_encoding_string (unsigned int kind)
4066 : {
4067 89 : switch (kind)
4068 : {
4069 : #define DWARF_ONE_KNOWN_DW_LLE(NAME, CODE) case CODE: return #NAME;
4070 0 : DWARF_ALL_KNOWN_DW_LLE
4071 : #undef DWARF_ONE_KNOWN_DW_LLE
4072 0 : default:
4073 0 : return NULL;
4074 : }
4075 : }
4076 :
4077 :
4078 : static const char *
4079 : dwarf_line_content_description_string (unsigned int kind)
4080 : {
4081 6 : switch (kind)
4082 : {
4083 : #define DWARF_ONE_KNOWN_DW_LNCT(NAME, CODE) case CODE: return #NAME;
4084 2 : DWARF_ALL_KNOWN_DW_LNCT
4085 : #undef DWARF_ONE_KNOWN_DW_LNCT
4086 0 : default:
4087 : return NULL;
4088 : }
4089 : }
4090 :
4091 :
4092 : /* Used by all dwarf_foo_name functions. */
4093 : static const char *
4094 6203693 : string_or_unknown (const char *known, unsigned int code,
4095 : unsigned int lo_user, unsigned int hi_user,
4096 : bool print_unknown_num)
4097 : {
4098 : static char unknown_buf[20];
4099 :
4100 6203693 : if (likely (known != NULL))
4101 : return known;
4102 :
4103 0 : if (lo_user != 0 && code >= lo_user && code <= hi_user)
4104 : {
4105 0 : snprintf (unknown_buf, sizeof unknown_buf, "lo_user+%#x",
4106 : code - lo_user);
4107 0 : return unknown_buf;
4108 : }
4109 :
4110 0 : if (print_unknown_num)
4111 : {
4112 0 : snprintf (unknown_buf, sizeof unknown_buf, "??? (%#x)", code);
4113 0 : return unknown_buf;
4114 : }
4115 :
4116 : return "???";
4117 : }
4118 :
4119 :
4120 : static const char *
4121 771589 : dwarf_tag_name (unsigned int tag)
4122 : {
4123 771589 : const char *ret = dwarf_tag_string (tag);
4124 771589 : return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true);
4125 : }
4126 :
4127 : static const char *
4128 2705738 : dwarf_attr_name (unsigned int attr)
4129 : {
4130 2705738 : const char *ret = dwarf_attr_string (attr);
4131 2705738 : return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true);
4132 : }
4133 :
4134 :
4135 : static const char *
4136 2705744 : dwarf_form_name (unsigned int form)
4137 : {
4138 2705744 : const char *ret = dwarf_form_string (form);
4139 2705744 : return string_or_unknown (ret, form, 0, 0, true);
4140 : }
4141 :
4142 :
4143 : static const char *
4144 1152 : dwarf_lang_name (unsigned int lang)
4145 : {
4146 1152 : const char *ret = dwarf_lang_string (lang);
4147 1152 : return string_or_unknown (ret, lang, DW_LANG_lo_user, DW_LANG_hi_user, false);
4148 : }
4149 :
4150 :
4151 : static const char *
4152 : dwarf_inline_name (unsigned int code)
4153 : {
4154 2927 : const char *ret = dwarf_inline_string (code);
4155 2927 : return string_or_unknown (ret, code, 0, 0, false);
4156 : }
4157 :
4158 :
4159 : static const char *
4160 : dwarf_encoding_name (unsigned int code)
4161 : {
4162 16426 : const char *ret = dwarf_encoding_string (code);
4163 16426 : return string_or_unknown (ret, code, DW_ATE_lo_user, DW_ATE_hi_user, false);
4164 : }
4165 :
4166 :
4167 : static const char *
4168 : dwarf_access_name (unsigned int code)
4169 : {
4170 0 : const char *ret = dwarf_access_string (code);
4171 0 : return string_or_unknown (ret, code, 0, 0, false);
4172 : }
4173 :
4174 :
4175 : static const char *
4176 : dwarf_defaulted_name (unsigned int code)
4177 : {
4178 0 : const char *ret = dwarf_defaulted_string (code);
4179 0 : return string_or_unknown (ret, code, 0, 0, false);
4180 : }
4181 :
4182 :
4183 : static const char *
4184 : dwarf_visibility_name (unsigned int code)
4185 : {
4186 0 : const char *ret = dwarf_visibility_string (code);
4187 0 : return string_or_unknown (ret, code, 0, 0, false);
4188 : }
4189 :
4190 :
4191 : static const char *
4192 : dwarf_virtuality_name (unsigned int code)
4193 : {
4194 0 : const char *ret = dwarf_virtuality_string (code);
4195 0 : return string_or_unknown (ret, code, 0, 0, false);
4196 : }
4197 :
4198 :
4199 : static const char *
4200 : dwarf_identifier_case_name (unsigned int code)
4201 : {
4202 0 : const char *ret = dwarf_identifier_case_string (code);
4203 0 : return string_or_unknown (ret, code, 0, 0, false);
4204 : }
4205 :
4206 :
4207 : static const char *
4208 : dwarf_calling_convention_name (unsigned int code)
4209 : {
4210 0 : const char *ret = dwarf_calling_convention_string (code);
4211 0 : return string_or_unknown (ret, code, DW_CC_lo_user, DW_CC_hi_user, false);
4212 : }
4213 :
4214 :
4215 : static const char *
4216 : dwarf_ordering_name (unsigned int code)
4217 : {
4218 0 : const char *ret = dwarf_ordering_string (code);
4219 0 : return string_or_unknown (ret, code, 0, 0, false);
4220 : }
4221 :
4222 :
4223 : static const char *
4224 : dwarf_discr_list_name (unsigned int code)
4225 : {
4226 0 : const char *ret = dwarf_discr_list_string (code);
4227 0 : return string_or_unknown (ret, code, 0, 0, false);
4228 : }
4229 :
4230 :
4231 : static const char *
4232 8 : dwarf_unit_name (unsigned int type)
4233 : {
4234 8 : const char *ret = dwarf_unit_string (type);
4235 8 : return string_or_unknown (ret, type, DW_UT_lo_user, DW_UT_hi_user, true);
4236 : }
4237 :
4238 :
4239 : static const char *
4240 14 : dwarf_range_list_encoding_name (unsigned int kind)
4241 : {
4242 14 : const char *ret = dwarf_range_list_encoding_string (kind);
4243 14 : return string_or_unknown (ret, kind, 0, 0, false);
4244 : }
4245 :
4246 :
4247 : static const char *
4248 89 : dwarf_loc_list_encoding_name (unsigned int kind)
4249 : {
4250 89 : const char *ret = dwarf_loc_list_encoding_string (kind);
4251 89 : return string_or_unknown (ret, kind, 0, 0, false);
4252 : }
4253 :
4254 :
4255 : static const char *
4256 6 : dwarf_line_content_description_name (unsigned int kind)
4257 : {
4258 6 : const char *ret = dwarf_line_content_description_string (kind);
4259 6 : return string_or_unknown (ret, kind, DW_LNCT_lo_user, DW_LNCT_hi_user,
4260 : false);
4261 : }
4262 :
4263 :
4264 : static void
4265 145 : print_block (size_t n, const void *block)
4266 : {
4267 145 : if (n == 0)
4268 0 : puts (_("empty block"));
4269 : else
4270 : {
4271 290 : printf (_("%zu byte block:"), n);
4272 145 : const unsigned char *data = block;
4273 : do
4274 4202 : printf (" %02x", *data++);
4275 2101 : while (--n > 0);
4276 : putchar ('\n');
4277 : }
4278 145 : }
4279 :
4280 : static void
4281 0 : print_bytes (size_t n, const unsigned char *bytes)
4282 : {
4283 0 : while (n-- > 0)
4284 : {
4285 0 : printf ("%02x", *bytes++);
4286 0 : if (n > 0)
4287 : printf (" ");
4288 : }
4289 0 : }
4290 :
4291 : static int
4292 68 : get_indexed_addr (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr)
4293 : {
4294 68 : if (cu == NULL)
4295 : return -1;
4296 :
4297 68 : Elf_Data *debug_addr = cu->dbg->sectiondata[IDX_debug_addr];
4298 68 : if (debug_addr == NULL)
4299 : return -1;
4300 :
4301 68 : Dwarf_Off base = __libdw_cu_addr_base (cu);
4302 68 : Dwarf_Word off = idx * cu->address_size;
4303 68 : if (base > debug_addr->d_size
4304 68 : || off > debug_addr->d_size - base
4305 68 : || cu->address_size > debug_addr->d_size - base - off)
4306 : return -1;
4307 :
4308 68 : const unsigned char *addrp = debug_addr->d_buf + base + off;
4309 68 : if (cu->address_size == 4)
4310 0 : *addr = read_4ubyte_unaligned (cu->dbg, addrp);
4311 : else
4312 68 : *addr = read_8ubyte_unaligned (cu->dbg, addrp);
4313 :
4314 : return 0;
4315 : }
4316 :
4317 : static void
4318 267230 : print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
4319 : unsigned int vers, unsigned int addrsize, unsigned int offset_size,
4320 : struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data)
4321 : {
4322 267230 : const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
4323 :
4324 267230 : if (len == 0)
4325 : {
4326 : printf ("%*s(empty)\n", indent, "");
4327 : return;
4328 : }
4329 :
4330 : #define NEED(n) if (len < (Dwarf_Word) (n)) goto invalid
4331 : #define CONSUME(n) NEED (n); else len -= (n)
4332 :
4333 : Dwarf_Word offset = 0;
4334 648681 : while (len-- > 0)
4335 : {
4336 381451 : uint_fast8_t op = *data++;
4337 :
4338 762902 : const char *op_name = dwarf_locexpr_opcode_string (op);
4339 381451 : if (unlikely (op_name == NULL))
4340 : {
4341 : static char buf[20];
4342 0 : if (op >= DW_OP_lo_user)
4343 0 : snprintf (buf, sizeof buf, "lo_user+%#x", op - DW_OP_lo_user);
4344 : else
4345 0 : snprintf (buf, sizeof buf, "??? (%#x)", op);
4346 : op_name = buf;
4347 : }
4348 :
4349 381451 : switch (op)
4350 : {
4351 7534 : case DW_OP_addr:;
4352 : /* Address operand. */
4353 : Dwarf_Word addr;
4354 7534 : NEED (addrsize);
4355 7534 : if (addrsize == 4)
4356 28 : addr = read_4ubyte_unaligned (dbg, data);
4357 7516 : else if (addrsize == 8)
4358 7534 : addr = read_8ubyte_unaligned (dbg, data);
4359 : else
4360 : goto invalid;
4361 7534 : data += addrsize;
4362 7534 : CONSUME (addrsize);
4363 :
4364 7534 : printf ("%*s[%2" PRIuMAX "] %s ",
4365 : indent, "", (uintmax_t) offset, op_name);
4366 7534 : print_dwarf_addr (dwflmod, 0, addr, addr);
4367 7534 : printf ("\n");
4368 :
4369 7534 : offset += 1 + addrsize;
4370 388985 : break;
4371 :
4372 0 : case DW_OP_call_ref:
4373 : case DW_OP_GNU_variable_value:
4374 : /* Offset operand. */
4375 0 : if (ref_size != 4 && ref_size != 8)
4376 : goto invalid; /* Cannot be used in CFA. */
4377 0 : NEED (ref_size);
4378 0 : if (ref_size == 4)
4379 0 : addr = read_4ubyte_unaligned (dbg, data);
4380 : else
4381 0 : addr = read_8ubyte_unaligned (dbg, data);
4382 0 : data += ref_size;
4383 0 : CONSUME (ref_size);
4384 : /* addr is a DIE offset, so format it as one. */
4385 0 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
4386 : indent, "", (uintmax_t) offset,
4387 : op_name, (uintmax_t) addr);
4388 0 : offset += 1 + ref_size;
4389 0 : break;
4390 :
4391 9477 : case DW_OP_deref_size:
4392 : case DW_OP_xderef_size:
4393 : case DW_OP_pick:
4394 : case DW_OP_const1u:
4395 : // XXX value might be modified by relocation
4396 9477 : NEED (1);
4397 18954 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 "\n",
4398 : indent, "", (uintmax_t) offset,
4399 9477 : op_name, *((uint8_t *) data));
4400 9477 : ++data;
4401 9477 : --len;
4402 9477 : offset += 2;
4403 9477 : break;
4404 :
4405 945 : case DW_OP_const2u:
4406 945 : NEED (2);
4407 : // XXX value might be modified by relocation
4408 2835 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu16 "\n",
4409 : indent, "", (uintmax_t) offset,
4410 1890 : op_name, read_2ubyte_unaligned (dbg, data));
4411 945 : CONSUME (2);
4412 945 : data += 2;
4413 945 : offset += 3;
4414 945 : break;
4415 :
4416 575 : case DW_OP_const4u:
4417 575 : NEED (4);
4418 : // XXX value might be modified by relocation
4419 1725 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu32 "\n",
4420 : indent, "", (uintmax_t) offset,
4421 1150 : op_name, read_4ubyte_unaligned (dbg, data));
4422 575 : CONSUME (4);
4423 575 : data += 4;
4424 575 : offset += 5;
4425 575 : break;
4426 :
4427 46 : case DW_OP_const8u:
4428 46 : NEED (8);
4429 : // XXX value might be modified by relocation
4430 138 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
4431 : indent, "", (uintmax_t) offset,
4432 92 : op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
4433 46 : CONSUME (8);
4434 46 : data += 8;
4435 46 : offset += 9;
4436 46 : break;
4437 :
4438 2105 : case DW_OP_const1s:
4439 2105 : NEED (1);
4440 : // XXX value might be modified by relocation
4441 4210 : printf ("%*s[%2" PRIuMAX "] %s %" PRId8 "\n",
4442 : indent, "", (uintmax_t) offset,
4443 2105 : op_name, *((int8_t *) data));
4444 2105 : ++data;
4445 2105 : --len;
4446 2105 : offset += 2;
4447 2105 : break;
4448 :
4449 3 : case DW_OP_const2s:
4450 3 : NEED (2);
4451 : // XXX value might be modified by relocation
4452 9 : printf ("%*s[%2" PRIuMAX "] %s %" PRId16 "\n",
4453 : indent, "", (uintmax_t) offset,
4454 6 : op_name, read_2sbyte_unaligned (dbg, data));
4455 3 : CONSUME (2);
4456 3 : data += 2;
4457 3 : offset += 3;
4458 3 : break;
4459 :
4460 0 : case DW_OP_const4s:
4461 0 : NEED (4);
4462 : // XXX value might be modified by relocation
4463 0 : printf ("%*s[%2" PRIuMAX "] %s %" PRId32 "\n",
4464 : indent, "", (uintmax_t) offset,
4465 0 : op_name, read_4sbyte_unaligned (dbg, data));
4466 0 : CONSUME (4);
4467 0 : data += 4;
4468 0 : offset += 5;
4469 0 : break;
4470 :
4471 0 : case DW_OP_const8s:
4472 0 : NEED (8);
4473 : // XXX value might be modified by relocation
4474 0 : printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
4475 : indent, "", (uintmax_t) offset,
4476 0 : op_name, read_8sbyte_unaligned (dbg, data));
4477 0 : CONSUME (8);
4478 0 : data += 8;
4479 0 : offset += 9;
4480 0 : break;
4481 :
4482 8030 : case DW_OP_piece:
4483 : case DW_OP_regx:
4484 : case DW_OP_plus_uconst:
4485 : case DW_OP_constu:;
4486 8030 : const unsigned char *start = data;
4487 : uint64_t uleb;
4488 8030 : NEED (1);
4489 8030 : get_uleb128 (uleb, data, data + len);
4490 8030 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
4491 : indent, "", (uintmax_t) offset, op_name, uleb);
4492 8030 : CONSUME (data - start);
4493 8030 : offset += 1 + (data - start);
4494 8030 : break;
4495 :
4496 2 : case DW_OP_addrx:
4497 : case DW_OP_GNU_addr_index:
4498 : case DW_OP_constx:
4499 : case DW_OP_GNU_const_index:;
4500 2 : start = data;
4501 2 : NEED (1);
4502 2 : get_uleb128 (uleb, data, data + len);
4503 2 : printf ("%*s[%2" PRIuMAX "] %s [%" PRIu64 "] ",
4504 : indent, "", (uintmax_t) offset, op_name, uleb);
4505 2 : CONSUME (data - start);
4506 2 : offset += 1 + (data - start);
4507 2 : if (get_indexed_addr (cu, uleb, &addr) != 0)
4508 : printf ("???\n");
4509 : else
4510 : {
4511 2 : print_dwarf_addr (dwflmod, 0, addr, addr);
4512 : printf ("\n");
4513 : }
4514 : break;
4515 :
4516 0 : case DW_OP_bit_piece:
4517 0 : start = data;
4518 : uint64_t uleb2;
4519 0 : NEED (1);
4520 0 : get_uleb128 (uleb, data, data + len);
4521 : NEED (1);
4522 0 : get_uleb128 (uleb2, data, data + len);
4523 0 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
4524 : indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
4525 0 : CONSUME (data - start);
4526 0 : offset += 1 + (data - start);
4527 0 : break;
4528 :
4529 68137 : case DW_OP_fbreg:
4530 : case DW_OP_breg0 ... DW_OP_breg31:
4531 : case DW_OP_consts:
4532 68137 : start = data;
4533 : int64_t sleb;
4534 68137 : NEED (1);
4535 68137 : get_sleb128 (sleb, data, data + len);
4536 68137 : printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
4537 : indent, "", (uintmax_t) offset, op_name, sleb);
4538 68137 : CONSUME (data - start);
4539 68137 : offset += 1 + (data - start);
4540 68137 : break;
4541 :
4542 0 : case DW_OP_bregx:
4543 0 : start = data;
4544 0 : NEED (1);
4545 0 : get_uleb128 (uleb, data, data + len);
4546 : NEED (1);
4547 0 : get_sleb128 (sleb, data, data + len);
4548 0 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
4549 : indent, "", (uintmax_t) offset, op_name, uleb, sleb);
4550 0 : CONSUME (data - start);
4551 0 : offset += 1 + (data - start);
4552 0 : break;
4553 :
4554 0 : case DW_OP_call2:
4555 0 : NEED (2);
4556 0 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx16 "]\n",
4557 : indent, "", (uintmax_t) offset, op_name,
4558 0 : read_2ubyte_unaligned (dbg, data));
4559 0 : CONSUME (2);
4560 0 : data += 2;
4561 0 : offset += 3;
4562 0 : break;
4563 :
4564 1 : case DW_OP_call4:
4565 1 : NEED (4);
4566 3 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx32 "]\n",
4567 : indent, "", (uintmax_t) offset, op_name,
4568 2 : read_4ubyte_unaligned (dbg, data));
4569 1 : CONSUME (4);
4570 1 : data += 4;
4571 1 : offset += 5;
4572 1 : break;
4573 :
4574 274 : case DW_OP_skip:
4575 : case DW_OP_bra:
4576 274 : NEED (2);
4577 274 : printf ("%*s[%2" PRIuMAX "] %s %" PRIuMAX "\n",
4578 : indent, "", (uintmax_t) offset, op_name,
4579 274 : (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
4580 274 : CONSUME (2);
4581 274 : data += 2;
4582 274 : offset += 3;
4583 274 : break;
4584 :
4585 128 : case DW_OP_implicit_value:
4586 128 : start = data;
4587 128 : NEED (1);
4588 128 : get_uleb128 (uleb, data, data + len);
4589 128 : printf ("%*s[%2" PRIuMAX "] %s: ",
4590 : indent, "", (uintmax_t) offset, op_name);
4591 128 : NEED (uleb);
4592 128 : print_block (uleb, data);
4593 128 : data += uleb;
4594 128 : CONSUME (data - start);
4595 128 : offset += 1 + (data - start);
4596 128 : break;
4597 :
4598 3538 : case DW_OP_implicit_pointer:
4599 : case DW_OP_GNU_implicit_pointer:
4600 : /* DIE offset operand. */
4601 3538 : start = data;
4602 3538 : NEED (ref_size);
4603 3538 : if (ref_size != 4 && ref_size != 8)
4604 : goto invalid; /* Cannot be used in CFA. */
4605 3538 : if (ref_size == 4)
4606 3538 : addr = read_4ubyte_unaligned (dbg, data);
4607 : else
4608 0 : addr = read_8ubyte_unaligned (dbg, data);
4609 3538 : data += ref_size;
4610 : /* Byte offset operand. */
4611 3538 : NEED (1);
4612 3538 : get_sleb128 (sleb, data, data + len);
4613 :
4614 7076 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
4615 : indent, "", (intmax_t) offset,
4616 : op_name, (uintmax_t) addr, sleb);
4617 3538 : CONSUME (data - start);
4618 3538 : offset += 1 + (data - start);
4619 3538 : break;
4620 :
4621 20865 : case DW_OP_entry_value:
4622 : case DW_OP_GNU_entry_value:
4623 : /* Size plus expression block. */
4624 20865 : start = data;
4625 20865 : NEED (1);
4626 20865 : get_uleb128 (uleb, data, data + len);
4627 20865 : printf ("%*s[%2" PRIuMAX "] %s:\n",
4628 : indent, "", (uintmax_t) offset, op_name);
4629 20865 : NEED (uleb);
4630 20865 : print_ops (dwflmod, dbg, indent + 5, indent + 5, vers,
4631 : addrsize, offset_size, cu, uleb, data);
4632 20865 : data += uleb;
4633 20865 : CONSUME (data - start);
4634 20865 : offset += 1 + (data - start);
4635 20865 : break;
4636 :
4637 1 : case DW_OP_const_type:
4638 : case DW_OP_GNU_const_type:
4639 : /* uleb128 CU relative DW_TAG_base_type DIE offset, 1-byte
4640 : unsigned size plus block. */
4641 1 : start = data;
4642 1 : NEED (1);
4643 1 : get_uleb128 (uleb, data, data + len);
4644 1 : if (! print_unresolved_addresses && cu != NULL)
4645 1 : uleb += cu->start;
4646 : NEED (1);
4647 1 : uint8_t usize = *(uint8_t *) data++;
4648 1 : NEED (usize);
4649 1 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] ",
4650 : indent, "", (uintmax_t) offset, op_name, uleb);
4651 1 : print_block (usize, data);
4652 1 : data += usize;
4653 1 : CONSUME (data - start);
4654 1 : offset += 1 + (data - start);
4655 1 : break;
4656 :
4657 0 : case DW_OP_regval_type:
4658 : case DW_OP_GNU_regval_type:
4659 : /* uleb128 register number, uleb128 CU relative
4660 : DW_TAG_base_type DIE offset. */
4661 0 : start = data;
4662 0 : NEED (1);
4663 0 : get_uleb128 (uleb, data, data + len);
4664 : NEED (1);
4665 0 : get_uleb128 (uleb2, data, data + len);
4666 0 : if (! print_unresolved_addresses && cu != NULL)
4667 0 : uleb2 += cu->start;
4668 0 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
4669 : indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
4670 0 : CONSUME (data - start);
4671 0 : offset += 1 + (data - start);
4672 0 : break;
4673 :
4674 6 : case DW_OP_deref_type:
4675 : case DW_OP_GNU_deref_type:
4676 : /* 1-byte unsigned size of value, uleb128 CU relative
4677 : DW_TAG_base_type DIE offset. */
4678 6 : start = data;
4679 6 : NEED (1);
4680 6 : usize = *(uint8_t *) data++;
4681 : NEED (1);
4682 6 : get_uleb128 (uleb, data, data + len);
4683 6 : if (! print_unresolved_addresses && cu != NULL)
4684 6 : uleb += cu->start;
4685 12 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
4686 : indent, "", (uintmax_t) offset,
4687 : op_name, usize, uleb);
4688 6 : CONSUME (data - start);
4689 6 : offset += 1 + (data - start);
4690 6 : break;
4691 :
4692 0 : case DW_OP_xderef_type:
4693 : /* 1-byte unsigned size of value, uleb128 base_type DIE offset. */
4694 0 : start = data;
4695 0 : NEED (1);
4696 0 : usize = *(uint8_t *) data++;
4697 : NEED (1);
4698 0 : get_uleb128 (uleb, data, data + len);
4699 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
4700 : indent, "", (uintmax_t) offset,
4701 : op_name, usize, uleb);
4702 0 : CONSUME (data - start);
4703 0 : offset += 1 + (data - start);
4704 0 : break;
4705 :
4706 306 : case DW_OP_convert:
4707 : case DW_OP_GNU_convert:
4708 : case DW_OP_reinterpret:
4709 : case DW_OP_GNU_reinterpret:
4710 : /* uleb128 CU relative offset to DW_TAG_base_type, or zero
4711 : for conversion to untyped. */
4712 306 : start = data;
4713 306 : NEED (1);
4714 306 : get_uleb128 (uleb, data, data + len);
4715 306 : if (uleb != 0 && ! print_unresolved_addresses && cu != NULL)
4716 205 : uleb += cu->start;
4717 306 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
4718 : indent, "", (uintmax_t) offset, op_name, uleb);
4719 306 : CONSUME (data - start);
4720 306 : offset += 1 + (data - start);
4721 306 : break;
4722 :
4723 22 : case DW_OP_GNU_parameter_ref:
4724 : /* 4 byte CU relative reference to the abstract optimized away
4725 : DW_TAG_formal_parameter. */
4726 22 : NEED (4);
4727 22 : uintmax_t param_off = (uintmax_t) read_4ubyte_unaligned (dbg, data);
4728 22 : if (! print_unresolved_addresses && cu != NULL)
4729 22 : param_off += cu->start;
4730 22 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
4731 : indent, "", (uintmax_t) offset, op_name, param_off);
4732 22 : CONSUME (4);
4733 22 : data += 4;
4734 22 : offset += 5;
4735 22 : break;
4736 :
4737 259456 : default:
4738 : /* No Operand. */
4739 259456 : printf ("%*s[%2" PRIuMAX "] %s\n",
4740 : indent, "", (uintmax_t) offset, op_name);
4741 259456 : ++offset;
4742 259456 : break;
4743 : }
4744 :
4745 381451 : indent = indentrest;
4746 381451 : continue;
4747 :
4748 0 : invalid:
4749 0 : printf (gettext ("%*s[%2" PRIuMAX "] %s <TRUNCATED>\n"),
4750 : indent, "", (uintmax_t) offset, op_name);
4751 : break;
4752 : }
4753 : }
4754 :
4755 :
4756 : struct listptr
4757 : {
4758 : Dwarf_Off offset:(64 - 3);
4759 : bool addr64:1;
4760 : bool dwarf64:1;
4761 : bool warned:1;
4762 : struct Dwarf_CU *cu;
4763 : unsigned int attr;
4764 : };
4765 :
4766 : #define listptr_offset_size(p) ((p)->dwarf64 ? 8 : 4)
4767 : #define listptr_address_size(p) ((p)->addr64 ? 8 : 4)
4768 :
4769 : static Dwarf_Addr
4770 56961 : cudie_base (Dwarf_Die *cudie)
4771 : {
4772 : Dwarf_Addr base;
4773 : /* Find the base address of the compilation unit. It will normally
4774 : be specified by DW_AT_low_pc. In DWARF-3 draft 4, the base
4775 : address could be overridden by DW_AT_entry_pc. It's been
4776 : removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc for
4777 : compilation units with discontinuous ranges. */
4778 56961 : if (unlikely (dwarf_lowpc (cudie, &base) != 0))
4779 : {
4780 : Dwarf_Attribute attr_mem;
4781 0 : if (dwarf_formaddr (dwarf_attr (cudie, DW_AT_entry_pc, &attr_mem),
4782 : &base) != 0)
4783 0 : base = 0;
4784 : }
4785 56961 : return base;
4786 : }
4787 :
4788 : static Dwarf_Addr
4789 56961 : listptr_base (struct listptr *p)
4790 : {
4791 113922 : Dwarf_Die cu = CUDIE (p->cu);
4792 56961 : return cudie_base (&cu);
4793 : }
4794 :
4795 : static int
4796 315410 : compare_listptr (const void *a, const void *b, void *arg)
4797 : {
4798 315410 : const char *name = arg;
4799 315410 : struct listptr *p1 = (void *) a;
4800 315410 : struct listptr *p2 = (void *) b;
4801 :
4802 315410 : if (p1->offset < p2->offset)
4803 : return -1;
4804 21297 : if (p1->offset > p2->offset)
4805 : return 1;
4806 :
4807 4268 : if (!p1->warned && !p2->warned)
4808 : {
4809 4268 : if (p1->addr64 != p2->addr64)
4810 : {
4811 0 : p1->warned = p2->warned = true;
4812 0 : error (0, 0,
4813 0 : gettext ("%s %#" PRIx64 " used with different address sizes"),
4814 : name, (uint64_t) p1->offset);
4815 : }
4816 4268 : if (p1->dwarf64 != p2->dwarf64)
4817 : {
4818 0 : p1->warned = p2->warned = true;
4819 0 : error (0, 0,
4820 0 : gettext ("%s %#" PRIx64 " used with different offset sizes"),
4821 0 : name, (uint64_t) p1->offset);
4822 : }
4823 4268 : if (listptr_base (p1) != listptr_base (p2))
4824 : {
4825 0 : p1->warned = p2->warned = true;
4826 0 : error (0, 0,
4827 0 : gettext ("%s %#" PRIx64 " used with different base addresses"),
4828 0 : name, (uint64_t) p1->offset);
4829 : }
4830 4268 : if (p1->attr != p2 ->attr)
4831 : {
4832 0 : p1->warned = p2->warned = true;
4833 0 : error (0, 0,
4834 0 : gettext ("%s %#" PRIx64
4835 : " used with different attribute %s and %s"),
4836 0 : name, (uint64_t) p1->offset, dwarf_attr_name (p2->attr),
4837 : dwarf_attr_name (p2->attr));
4838 : }
4839 : }
4840 :
4841 : return 0;
4842 : }
4843 :
4844 : struct listptr_table
4845 : {
4846 : size_t n;
4847 : size_t alloc;
4848 : struct listptr *table;
4849 : };
4850 :
4851 : static struct listptr_table known_locsptr;
4852 : static struct listptr_table known_loclistsptr;
4853 : static struct listptr_table known_rangelistptr;
4854 : static struct listptr_table known_rnglistptr;
4855 : static struct listptr_table known_addrbases;
4856 : static struct listptr_table known_stroffbases;
4857 :
4858 : static void
4859 : reset_listptr (struct listptr_table *table)
4860 : {
4861 870 : free (table->table);
4862 870 : table->table = NULL;
4863 870 : table->n = table->alloc = 0;
4864 : }
4865 :
4866 : /* Returns false if offset doesn't fit. See struct listptr. */
4867 : static bool
4868 52605 : notice_listptr (enum section_e section, struct listptr_table *table,
4869 : uint_fast8_t address_size, uint_fast8_t offset_size,
4870 : struct Dwarf_CU *cu, Dwarf_Off offset, unsigned int attr)
4871 : {
4872 52605 : if (print_debug_sections & section)
4873 : {
4874 52504 : if (table->n == table->alloc)
4875 : {
4876 175 : if (table->alloc == 0)
4877 81 : table->alloc = 128;
4878 : else
4879 94 : table->alloc *= 2;
4880 175 : table->table = xrealloc (table->table,
4881 175 : table->alloc * sizeof table->table[0]);
4882 : }
4883 :
4884 52504 : struct listptr *p = &table->table[table->n++];
4885 :
4886 105008 : *p = (struct listptr)
4887 : {
4888 52504 : .addr64 = address_size == 8,
4889 52504 : .dwarf64 = offset_size == 8,
4890 : .offset = offset,
4891 : .cu = cu,
4892 : .attr = attr
4893 : };
4894 :
4895 52504 : if (p->offset != offset)
4896 : {
4897 0 : table->n--;
4898 0 : return false;
4899 : }
4900 : }
4901 : return true;
4902 : }
4903 :
4904 : static void
4905 : sort_listptr (struct listptr_table *table, const char *name)
4906 : {
4907 85 : if (table->n > 0)
4908 81 : qsort_r (table->table, table->n, sizeof table->table[0],
4909 : &compare_listptr, (void *) name);
4910 : }
4911 :
4912 : static bool
4913 48419 : skip_listptr_hole (struct listptr_table *table, size_t *idxp,
4914 : uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
4915 : Dwarf_Addr *base, struct Dwarf_CU **cu, ptrdiff_t offset,
4916 : unsigned char **readp, unsigned char *endp,
4917 : unsigned int *attr)
4918 : {
4919 48419 : if (table->n == 0)
4920 : return false;
4921 :
4922 100822 : while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
4923 52403 : ++*idxp;
4924 :
4925 48419 : struct listptr *p = &table->table[*idxp];
4926 :
4927 48419 : if (*idxp == table->n
4928 48419 : || p->offset >= (Dwarf_Off) (endp - *readp + offset))
4929 : {
4930 0 : *readp = endp;
4931 0 : printf (gettext (" [%6tx] <UNUSED GARBAGE IN REST OF SECTION>\n"),
4932 : offset);
4933 : return true;
4934 : }
4935 :
4936 48419 : if (p->offset != (Dwarf_Off) offset)
4937 : {
4938 0 : *readp += p->offset - offset;
4939 0 : printf (gettext (" [%6tx] <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
4940 : offset, (Dwarf_Off) p->offset - offset);
4941 : return true;
4942 : }
4943 :
4944 48419 : if (address_sizep != NULL)
4945 48419 : *address_sizep = listptr_address_size (p);
4946 48419 : if (offset_sizep != NULL)
4947 39494 : *offset_sizep = listptr_offset_size (p);
4948 48419 : if (base != NULL)
4949 48419 : *base = listptr_base (p);
4950 48419 : if (cu != NULL)
4951 48419 : *cu = p->cu;
4952 48419 : if (attr != NULL)
4953 39494 : *attr = p->attr;
4954 :
4955 : return false;
4956 : }
4957 :
4958 : static Dwarf_Off
4959 : next_listptr_offset (struct listptr_table *table, size_t idx)
4960 : {
4961 : /* Note that multiple attributes could in theory point to the same loclist
4962 : offset, so make sure we pick one that is bigger than the current one.
4963 : The table is sorted on offset. */
4964 0 : Dwarf_Off offset = table->table[idx].offset;
4965 0 : while (++idx < table->n)
4966 : {
4967 0 : Dwarf_Off next = table->table[idx].offset;
4968 0 : if (next > offset)
4969 : return next;
4970 : }
4971 : return 0;
4972 : }
4973 :
4974 : /* Returns the listptr associated with the given index, or NULL. */
4975 : static struct listptr *
4976 : get_listptr (struct listptr_table *table, size_t idx)
4977 : {
4978 10 : if (idx >= table->n)
4979 : return NULL;
4980 5 : return &table->table[idx];
4981 : }
4982 :
4983 : /* Returns the next index, base address and CU associated with the
4984 : list unit offsets. If there is none false is returned, otherwise
4985 : true. Assumes the table has been sorted. */
4986 : static bool
4987 6 : listptr_cu (struct listptr_table *table, size_t *idxp,
4988 : Dwarf_Off start, Dwarf_Off end,
4989 : Dwarf_Addr *base, struct Dwarf_CU **cu)
4990 : {
4991 14 : while (*idxp < table->n
4992 14 : && table->table[*idxp].offset < start)
4993 8 : ++*idxp;
4994 :
4995 6 : if (*idxp < table->n
4996 6 : && table->table[*idxp].offset >= start
4997 6 : && table->table[*idxp].offset < end)
4998 : {
4999 6 : struct listptr *p = &table->table[*idxp];
5000 6 : *base = listptr_base (p);
5001 6 : *cu = p->cu;
5002 6 : ++*idxp;
5003 : return true;
5004 : }
5005 :
5006 : return false;
5007 : }
5008 :
5009 : static void
5010 40 : print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
5011 : Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
5012 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5013 : {
5014 80 : const size_t sh_size = (dbg->sectiondata[IDX_debug_abbrev] ?
5015 40 : dbg->sectiondata[IDX_debug_abbrev]->d_size : 0);
5016 :
5017 80 : printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
5018 : " [ Code]\n"),
5019 : elf_ndxscn (scn), section_name (ebl, shdr),
5020 40 : (uint64_t) shdr->sh_offset);
5021 :
5022 40 : Dwarf_Off offset = 0;
5023 40 : while (offset < sh_size)
5024 : {
5025 1087 : printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
5026 : offset);
5027 :
5028 : while (1)
5029 56639 : {
5030 : size_t length;
5031 : Dwarf_Abbrev abbrev;
5032 :
5033 57726 : int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
5034 57726 : if (res != 0)
5035 : {
5036 1087 : if (unlikely (res < 0))
5037 : {
5038 0 : printf (gettext ("\
5039 : *** error while reading abbreviation: %s\n"),
5040 : dwarf_errmsg (-1));
5041 0 : return;
5042 : }
5043 :
5044 : /* This is the NUL byte at the end of the section. */
5045 1087 : ++offset;
5046 1087 : break;
5047 : }
5048 :
5049 : /* We know these calls can never fail. */
5050 56639 : unsigned int code = dwarf_getabbrevcode (&abbrev);
5051 56639 : unsigned int tag = dwarf_getabbrevtag (&abbrev);
5052 56639 : int has_children = dwarf_abbrevhaschildren (&abbrev);
5053 :
5054 113278 : printf (gettext (" [%5u] offset: %" PRId64
5055 : ", children: %s, tag: %s\n"),
5056 : code, (int64_t) offset,
5057 : has_children ? yes_str : no_str,
5058 : dwarf_tag_name (tag));
5059 :
5060 56639 : size_t cnt = 0;
5061 : unsigned int name;
5062 : unsigned int form;
5063 : Dwarf_Sword data;
5064 : Dwarf_Off enoffset;
5065 332133 : while (dwarf_getabbrevattr_data (&abbrev, cnt, &name, &form,
5066 : &data, &enoffset) == 0)
5067 : {
5068 437710 : printf (" attr: %s, form: %s",
5069 : dwarf_attr_name (name), dwarf_form_name (form));
5070 218855 : if (form == DW_FORM_implicit_const)
5071 0 : printf (" (%" PRId64 ")", data);
5072 437710 : printf (", offset: %#" PRIx64 "\n", (uint64_t) enoffset);
5073 218855 : ++cnt;
5074 : }
5075 :
5076 56639 : offset += length;
5077 : }
5078 : }
5079 : }
5080 :
5081 :
5082 : static void
5083 2 : print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
5084 : Ebl *ebl, GElf_Ehdr *ehdr,
5085 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5086 : {
5087 4 : printf (gettext ("\
5088 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5089 : elf_ndxscn (scn), section_name (ebl, shdr),
5090 2 : (uint64_t) shdr->sh_offset);
5091 :
5092 2 : if (shdr->sh_size == 0)
5093 : return;
5094 :
5095 : /* We like to get the section from libdw to make sure they are relocated. */
5096 4 : Elf_Data *data = (dbg->sectiondata[IDX_debug_addr]
5097 2 : ?: elf_rawdata (scn, NULL));
5098 2 : if (unlikely (data == NULL))
5099 : {
5100 0 : error (0, 0, gettext ("cannot get .debug_addr section data: %s"),
5101 : elf_errmsg (-1));
5102 : return;
5103 : }
5104 :
5105 2 : size_t idx = 0;
5106 4 : sort_listptr (&known_addrbases, "addr_base");
5107 :
5108 2 : const unsigned char *start = (const unsigned char *) data->d_buf;
5109 2 : const unsigned char *readp = start;
5110 2 : const unsigned char *readendp = ((const unsigned char *) data->d_buf
5111 2 : + data->d_size);
5112 :
5113 8 : while (readp < readendp)
5114 : {
5115 : /* We cannot really know whether or not there is an header. The
5116 : DebugFission extension to DWARF4 doesn't add one. The DWARF5
5117 : .debug_addr variant does. Whether or not we have an header,
5118 : DW_AT_[GNU_]addr_base points at "index 0". So if the current
5119 : offset equals the CU addr_base then we can just start
5120 : printing addresses. If there is no CU with an exact match
5121 : then we'll try to parse the header first. */
5122 4 : Dwarf_Off off = (Dwarf_Off) (readp
5123 4 : - (const unsigned char *) data->d_buf);
5124 :
5125 4 : printf ("Table at offset %" PRIx64 " ", off);
5126 :
5127 8 : struct listptr *listptr = get_listptr (&known_addrbases, idx++);
5128 : const unsigned char *next_unitp;
5129 :
5130 : uint64_t unit_length;
5131 : uint16_t version;
5132 : uint8_t address_size;
5133 : uint8_t segment_size;
5134 4 : if (listptr == NULL)
5135 : {
5136 0 : error (0, 0, "Warning: No CU references .debug_addr after %" PRIx64,
5137 : off);
5138 :
5139 : /* We will have to assume it is just addresses to the end... */
5140 0 : address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5141 0 : next_unitp = readendp;
5142 : printf ("Unknown CU:\n");
5143 : }
5144 : else
5145 : {
5146 : Dwarf_Die cudie;
5147 4 : if (dwarf_cu_die (listptr->cu, &cudie,
5148 : NULL, NULL, NULL, NULL,
5149 : NULL, NULL) == NULL)
5150 0 : printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
5151 : else
5152 4 : printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
5153 :
5154 4 : if (listptr->offset == off)
5155 : {
5156 2 : address_size = listptr_address_size (listptr);
5157 2 : segment_size = 0;
5158 2 : version = 4;
5159 :
5160 : /* The addresses start here, but where do they end? */
5161 3 : listptr = get_listptr (&known_addrbases, idx);
5162 1 : if (listptr == NULL)
5163 : next_unitp = readendp;
5164 1 : else if (listptr->cu->version < 5)
5165 : {
5166 1 : next_unitp = start + listptr->offset;
5167 1 : if (listptr->offset < off || listptr->offset > data->d_size)
5168 : {
5169 0 : error (0, 0,
5170 : "Warning: Bad address base for next unit at %"
5171 : PRIx64, off);
5172 0 : next_unitp = readendp;
5173 : }
5174 : }
5175 : else
5176 : {
5177 : /* Tricky, we don't have a header for this unit, but
5178 : there is one for the next. We will have to
5179 : "guess" how big it is and subtract it from the
5180 : offset (because that points after the header). */
5181 0 : unsigned int offset_size = listptr_offset_size (listptr);
5182 0 : Dwarf_Off next_off = (listptr->offset
5183 0 : - (offset_size == 4 ? 4 : 12) /* len */
5184 : - 2 /* version */
5185 : - 1 /* address size */
5186 0 : - 1); /* segment selector size */
5187 0 : next_unitp = start + next_off;
5188 0 : if (next_off < off || next_off > data->d_size)
5189 : {
5190 0 : error (0, 0,
5191 : "Warning: Couldn't calculate .debug_addr "
5192 : " unit lenght at %" PRIx64, off);
5193 0 : next_unitp = readendp;
5194 : }
5195 : }
5196 2 : unit_length = (uint64_t) (next_unitp - readp);
5197 :
5198 : /* Pretend we have a header. */
5199 2 : printf ("\n");
5200 4 : printf (gettext (" Length: %8" PRIu64 "\n"),
5201 : unit_length);
5202 4 : printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
5203 4 : printf (gettext (" Address size: %8" PRIu64 "\n"),
5204 : (uint64_t) address_size);
5205 4 : printf (gettext (" Segment size: %8" PRIu64 "\n"),
5206 : (uint64_t) segment_size);
5207 : printf ("\n");
5208 : }
5209 : else
5210 : {
5211 : /* OK, we have to parse an header first. */
5212 2 : unit_length = read_4ubyte_unaligned_inc (dbg, readp);
5213 2 : if (unlikely (unit_length == 0xffffffff))
5214 : {
5215 0 : if (unlikely (readp > readendp - 8))
5216 : {
5217 0 : invalid_data:
5218 0 : error (0, 0, "Invalid data");
5219 0 : return;
5220 : }
5221 0 : unit_length = read_8ubyte_unaligned_inc (dbg, readp);
5222 : }
5223 2 : printf ("\n");
5224 4 : printf (gettext (" Length: %8" PRIu64 "\n"),
5225 : unit_length);
5226 :
5227 : /* We need at least 2-bytes (version) + 1-byte
5228 : (addr_size) + 1-byte (segment_size) = 4 bytes to
5229 : complete the header. And this unit cannot go beyond
5230 : the section data. */
5231 2 : if (readp > readendp - 4
5232 2 : || unit_length < 4
5233 2 : || unit_length > (uint64_t) (readendp - readp))
5234 : goto invalid_data;
5235 :
5236 2 : next_unitp = readp + unit_length;
5237 :
5238 2 : version = read_2ubyte_unaligned_inc (dbg, readp);
5239 4 : printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
5240 :
5241 2 : if (version != 5)
5242 : {
5243 0 : error (0, 0, gettext ("Unknown version"));
5244 0 : goto next_unit;
5245 : }
5246 :
5247 2 : address_size = *readp++;
5248 4 : printf (gettext (" Address size: %8" PRIu64 "\n"),
5249 : (uint64_t) address_size);
5250 :
5251 2 : if (address_size != 4 && address_size != 8)
5252 : {
5253 0 : error (0, 0, gettext ("unsupported address size"));
5254 : goto next_unit;
5255 : }
5256 :
5257 2 : segment_size = *readp++;
5258 4 : printf (gettext (" Segment size: %8" PRIu64 "\n"),
5259 : (uint64_t) segment_size);
5260 2 : printf ("\n");
5261 :
5262 2 : if (segment_size != 0)
5263 : {
5264 0 : error (0, 0, gettext ("unsupported segment size"));
5265 : goto next_unit;
5266 : }
5267 :
5268 2 : if (listptr->offset != (Dwarf_Off) (readp - start))
5269 : {
5270 : error (0, 0, "Address index doesn't start after header");
5271 : goto next_unit;
5272 : }
5273 : }
5274 : }
5275 :
5276 4 : int digits = 1;
5277 4 : size_t addresses = (next_unitp - readp) / address_size;
5278 12 : while (addresses >= 10)
5279 : {
5280 4 : ++digits;
5281 4 : addresses /= 10;
5282 : }
5283 :
5284 4 : unsigned int uidx = 0;
5285 4 : size_t index_offset = readp - (const unsigned char *) data->d_buf;
5286 : printf (" Addresses start at offset 0x%zx:\n", index_offset);
5287 76 : while (readp <= next_unitp - address_size)
5288 : {
5289 72 : Dwarf_Addr addr = read_addr_unaligned_inc (address_size, dbg,
5290 : readp);
5291 144 : printf (" [%*u] ", digits, uidx++);
5292 72 : print_dwarf_addr (dwflmod, address_size, addr, addr);
5293 : printf ("\n");
5294 : }
5295 4 : printf ("\n");
5296 :
5297 4 : if (readp != next_unitp)
5298 0 : error (0, 0, "extra %zd bytes at end of unit",
5299 0 : (size_t) (next_unitp - readp));
5300 :
5301 4 : next_unit:
5302 : readp = next_unitp;
5303 : }
5304 : }
5305 :
5306 : /* Print content of DWARF .debug_aranges section. We fortunately do
5307 : not have to know a bit about the structure of the section, libdwarf
5308 : takes care of it. */
5309 : static void
5310 1 : print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
5311 : GElf_Shdr *shdr, Dwarf *dbg)
5312 : {
5313 : Dwarf_Aranges *aranges;
5314 : size_t cnt;
5315 1 : if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
5316 : {
5317 0 : error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
5318 : dwarf_errmsg (-1));
5319 0 : return;
5320 : }
5321 :
5322 : GElf_Shdr glink_mem;
5323 : GElf_Shdr *glink;
5324 1 : glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
5325 1 : if (glink == NULL)
5326 : {
5327 0 : error (0, 0, gettext ("invalid sh_link value in section %zu"),
5328 : elf_ndxscn (scn));
5329 : return;
5330 : }
5331 :
5332 3 : printf (ngettext ("\
5333 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
5334 : "\
5335 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
5336 : cnt),
5337 : elf_ndxscn (scn), section_name (ebl, shdr),
5338 1 : (uint64_t) shdr->sh_offset, cnt);
5339 :
5340 : /* Compute floor(log16(cnt)). */
5341 1 : size_t tmp = cnt;
5342 1 : int digits = 1;
5343 1 : while (tmp >= 16)
5344 : {
5345 0 : ++digits;
5346 0 : tmp >>= 4;
5347 : }
5348 :
5349 5 : for (size_t n = 0; n < cnt; ++n)
5350 : {
5351 5 : Dwarf_Arange *runp = dwarf_onearange (aranges, n);
5352 5 : if (unlikely (runp == NULL))
5353 : {
5354 0 : printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
5355 0 : return;
5356 : }
5357 :
5358 : Dwarf_Addr start;
5359 : Dwarf_Word length;
5360 : Dwarf_Off offset;
5361 :
5362 5 : if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
5363 0 : printf (gettext (" [%*zu] ???\n"), digits, n);
5364 : else
5365 10 : printf (gettext (" [%*zu] start: %0#*" PRIx64
5366 : ", length: %5" PRIu64 ", CU DIE offset: %6"
5367 : PRId64 "\n"),
5368 5 : digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
5369 : (uint64_t) start, (uint64_t) length, (int64_t) offset);
5370 : }
5371 : }
5372 :
5373 :
5374 : /* Print content of DWARF .debug_aranges section. */
5375 : static void
5376 44 : print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
5377 : Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
5378 : GElf_Shdr *shdr, Dwarf *dbg)
5379 : {
5380 44 : if (decodedaranges)
5381 : {
5382 1 : print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg);
5383 1 : return;
5384 : }
5385 :
5386 86 : Elf_Data *data = (dbg->sectiondata[IDX_debug_aranges]
5387 43 : ?: elf_rawdata (scn, NULL));
5388 :
5389 43 : if (unlikely (data == NULL))
5390 : {
5391 0 : error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
5392 : elf_errmsg (-1));
5393 : return;
5394 : }
5395 :
5396 86 : printf (gettext ("\
5397 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5398 : elf_ndxscn (scn), section_name (ebl, shdr),
5399 43 : (uint64_t) shdr->sh_offset);
5400 :
5401 43 : const unsigned char *readp = data->d_buf;
5402 43 : const unsigned char *readendp = readp + data->d_size;
5403 :
5404 1170 : while (readp < readendp)
5405 : {
5406 1084 : const unsigned char *hdrstart = readp;
5407 1084 : size_t start_offset = hdrstart - (const unsigned char *) data->d_buf;
5408 :
5409 2168 : printf (gettext ("\nTable at offset %zu:\n"), start_offset);
5410 1084 : if (readp + 4 > readendp)
5411 : {
5412 0 : invalid_data:
5413 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
5414 : elf_ndxscn (scn), section_name (ebl, shdr));
5415 : return;
5416 : }
5417 :
5418 1104 : Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
5419 1084 : unsigned int length_bytes = 4;
5420 1084 : if (length == DWARF3_LENGTH_64_BIT)
5421 : {
5422 0 : if (readp + 8 > readendp)
5423 : goto invalid_data;
5424 0 : length = read_8ubyte_unaligned_inc (dbg, readp);
5425 0 : length_bytes = 8;
5426 : }
5427 :
5428 1084 : const unsigned char *nexthdr = readp + length;
5429 2168 : printf (gettext ("\n Length: %6" PRIu64 "\n"),
5430 : (uint64_t) length);
5431 :
5432 1084 : if (unlikely (length > (size_t) (readendp - readp)))
5433 : goto invalid_data;
5434 :
5435 1084 : if (length == 0)
5436 0 : continue;
5437 :
5438 1084 : if (readp + 2 > readendp)
5439 : goto invalid_data;
5440 1104 : uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, readp);
5441 2168 : printf (gettext (" DWARF version: %6" PRIuFAST16 "\n"),
5442 : version);
5443 1084 : if (version != 2)
5444 : {
5445 0 : error (0, 0, gettext ("unsupported aranges version"));
5446 : goto next_table;
5447 : }
5448 :
5449 : Dwarf_Word offset;
5450 1084 : if (readp + length_bytes > readendp)
5451 : goto invalid_data;
5452 1084 : if (length_bytes == 8)
5453 0 : offset = read_8ubyte_unaligned_inc (dbg, readp);
5454 : else
5455 1104 : offset = read_4ubyte_unaligned_inc (dbg, readp);
5456 2168 : printf (gettext (" CU offset: %6" PRIx64 "\n"),
5457 : (uint64_t) offset);
5458 :
5459 1084 : if (readp + 1 > readendp)
5460 : goto invalid_data;
5461 1084 : unsigned int address_size = *readp++;
5462 2168 : printf (gettext (" Address size: %6" PRIu64 "\n"),
5463 : (uint64_t) address_size);
5464 1084 : if (address_size != 4 && address_size != 8)
5465 : {
5466 0 : error (0, 0, gettext ("unsupported address size"));
5467 : goto next_table;
5468 : }
5469 :
5470 1084 : if (readp + 1 > readendp)
5471 : goto invalid_data;
5472 1084 : unsigned int segment_size = *readp++;
5473 2168 : printf (gettext (" Segment size: %6" PRIu64 "\n\n"),
5474 : (uint64_t) segment_size);
5475 1084 : if (segment_size != 0 && segment_size != 4 && segment_size != 8)
5476 : {
5477 0 : error (0, 0, gettext ("unsupported segment size"));
5478 : goto next_table;
5479 : }
5480 :
5481 : /* Round the address to the next multiple of 2*address_size. */
5482 2168 : readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
5483 1084 : % (2 * address_size));
5484 :
5485 3285 : while (readp < nexthdr)
5486 : {
5487 : Dwarf_Word range_address;
5488 : Dwarf_Word range_length;
5489 2201 : Dwarf_Word segment = 0;
5490 2201 : if (readp + 2 * address_size + segment_size > readendp)
5491 : goto invalid_data;
5492 2201 : if (address_size == 4)
5493 : {
5494 36 : range_address = read_4ubyte_unaligned_inc (dbg, readp);
5495 36 : range_length = read_4ubyte_unaligned_inc (dbg, readp);
5496 : }
5497 : else
5498 : {
5499 2203 : range_address = read_8ubyte_unaligned_inc (dbg, readp);
5500 2203 : range_length = read_8ubyte_unaligned_inc (dbg, readp);
5501 : }
5502 :
5503 2201 : if (segment_size == 4)
5504 0 : segment = read_4ubyte_unaligned_inc (dbg, readp);
5505 2201 : else if (segment_size == 8)
5506 0 : segment = read_8ubyte_unaligned_inc (dbg, readp);
5507 :
5508 2201 : if (range_address == 0 && range_length == 0 && segment == 0)
5509 : break;
5510 :
5511 1117 : printf (" ");
5512 1117 : print_dwarf_addr (dwflmod, address_size, range_address,
5513 : range_address);
5514 1117 : printf ("..");
5515 1117 : print_dwarf_addr (dwflmod, address_size,
5516 1117 : range_address + range_length - 1,
5517 : range_length);
5518 1117 : if (segment_size != 0)
5519 : printf (" (%" PRIx64 ")\n", (uint64_t) segment);
5520 : else
5521 : printf ("\n");
5522 : }
5523 :
5524 1084 : next_table:
5525 1084 : if (readp != nexthdr)
5526 : {
5527 0 : size_t padding = nexthdr - readp;
5528 0 : printf (gettext (" %zu padding bytes\n"), padding);
5529 0 : readp = nexthdr;
5530 : }
5531 : }
5532 : }
5533 :
5534 :
5535 : static bool is_split_dwarf (Dwarf *dbg, uint64_t *id, Dwarf_CU **split_cu);
5536 :
5537 : /* Returns true and sets cu and cu_base if the given Dwarf is a split
5538 : DWARF (.dwo) file. */
5539 : static bool
5540 0 : split_dwarf_cu_base (Dwarf *dbg, Dwarf_CU **cu, Dwarf_Addr *cu_base)
5541 : {
5542 : uint64_t id;
5543 0 : if (is_split_dwarf (dbg, &id, cu))
5544 : {
5545 : Dwarf_Die cudie;
5546 0 : if (dwarf_cu_info (*cu, NULL, NULL, &cudie, NULL, NULL, NULL, NULL) == 0)
5547 : {
5548 0 : *cu_base = cudie_base (&cudie);
5549 0 : return true;
5550 : }
5551 : }
5552 : return false;
5553 : }
5554 :
5555 : /* Print content of DWARF .debug_rnglists section. */
5556 : static void
5557 2 : print_debug_rnglists_section (Dwfl_Module *dwflmod,
5558 : Ebl *ebl,
5559 : GElf_Ehdr *ehdr __attribute__ ((unused)),
5560 : Elf_Scn *scn, GElf_Shdr *shdr,
5561 : Dwarf *dbg __attribute__((unused)))
5562 : {
5563 4 : printf (gettext ("\
5564 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5565 : elf_ndxscn (scn), section_name (ebl, shdr),
5566 2 : (uint64_t) shdr->sh_offset);
5567 :
5568 4 : Elf_Data *data =(dbg->sectiondata[IDX_debug_rnglists]
5569 2 : ?: elf_rawdata (scn, NULL));
5570 2 : if (unlikely (data == NULL))
5571 : {
5572 0 : error (0, 0, gettext ("cannot get .debug_rnglists content: %s"),
5573 : elf_errmsg (-1));
5574 0 : return;
5575 : }
5576 :
5577 : /* For the listptr to get the base address/CU. */
5578 4 : sort_listptr (&known_rnglistptr, "rnglistptr");
5579 2 : size_t listptr_idx = 0;
5580 :
5581 2 : const unsigned char *readp = data->d_buf;
5582 2 : const unsigned char *const dataend = ((unsigned char *) data->d_buf
5583 2 : + data->d_size);
5584 6 : while (readp < dataend)
5585 : {
5586 2 : if (unlikely (readp > dataend - 4))
5587 : {
5588 0 : invalid_data:
5589 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
5590 : elf_ndxscn (scn), section_name (ebl, shdr));
5591 0 : return;
5592 : }
5593 :
5594 2 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
5595 4 : printf (gettext ("Table at Offset 0x%" PRIx64 ":\n\n"),
5596 : (uint64_t) offset);
5597 :
5598 2 : uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
5599 2 : unsigned int offset_size = 4;
5600 2 : if (unlikely (unit_length == 0xffffffff))
5601 : {
5602 0 : if (unlikely (readp > dataend - 8))
5603 : goto invalid_data;
5604 :
5605 0 : unit_length = read_8ubyte_unaligned_inc (dbg, readp);
5606 0 : offset_size = 8;
5607 : }
5608 4 : printf (gettext (" Length: %8" PRIu64 "\n"), unit_length);
5609 :
5610 : /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
5611 : bytes to complete the header. And this unit cannot go beyond
5612 : the section data. */
5613 2 : if (readp > dataend - 8
5614 2 : || unit_length < 8
5615 2 : || unit_length > (uint64_t) (dataend - readp))
5616 : goto invalid_data;
5617 :
5618 2 : const unsigned char *nexthdr = readp + unit_length;
5619 :
5620 2 : uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
5621 4 : printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
5622 :
5623 2 : if (version != 5)
5624 : {
5625 0 : error (0, 0, gettext ("Unknown version"));
5626 : goto next_table;
5627 : }
5628 :
5629 2 : uint8_t address_size = *readp++;
5630 4 : printf (gettext (" Address size: %8" PRIu64 "\n"),
5631 : (uint64_t) address_size);
5632 :
5633 2 : if (address_size != 4 && address_size != 8)
5634 : {
5635 0 : error (0, 0, gettext ("unsupported address size"));
5636 : goto next_table;
5637 : }
5638 :
5639 2 : uint8_t segment_size = *readp++;
5640 4 : printf (gettext (" Segment size: %8" PRIu64 "\n"),
5641 : (uint64_t) segment_size);
5642 :
5643 2 : if (segment_size != 0 && segment_size != 4 && segment_size != 8)
5644 : {
5645 0 : error (0, 0, gettext ("unsupported segment size"));
5646 : goto next_table;
5647 : }
5648 :
5649 2 : uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
5650 4 : printf (gettext (" Offset entries: %8" PRIu64 "\n"),
5651 : (uint64_t) offset_entry_count);
5652 :
5653 : /* We need the CU that uses this unit to get the initial base address. */
5654 2 : Dwarf_Addr cu_base = 0;
5655 2 : struct Dwarf_CU *cu = NULL;
5656 2 : if (listptr_cu (&known_rnglistptr, &listptr_idx,
5657 : (Dwarf_Off) offset,
5658 2 : (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
5659 : &cu_base, &cu)
5660 0 : || split_dwarf_cu_base (dbg, &cu, &cu_base))
5661 2 : {
5662 : Dwarf_Die cudie;
5663 2 : if (dwarf_cu_die (cu, &cudie,
5664 : NULL, NULL, NULL, NULL,
5665 : NULL, NULL) == NULL)
5666 0 : printf (gettext (" Unknown CU base: "));
5667 : else
5668 2 : printf (gettext (" CU [%6" PRIx64 "] base: "),
5669 : dwarf_dieoffset (&cudie));
5670 2 : print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
5671 2 : printf ("\n");
5672 : }
5673 : else
5674 0 : printf (gettext (" Not associated with a CU.\n"));
5675 :
5676 2 : printf ("\n");
5677 :
5678 2 : const unsigned char *offset_array_start = readp;
5679 2 : if (offset_entry_count > 0)
5680 : {
5681 1 : uint64_t max_entries = (unit_length - 8) / offset_size;
5682 1 : if (offset_entry_count > max_entries)
5683 : {
5684 0 : error (0, 0,
5685 0 : gettext ("too many offset entries for unit length"));
5686 0 : offset_entry_count = max_entries;
5687 : }
5688 :
5689 2 : printf (gettext (" Offsets starting at 0x%" PRIx64 ":\n"),
5690 : (uint64_t) (offset_array_start
5691 1 : - (unsigned char *) data->d_buf));
5692 3 : for (uint32_t idx = 0; idx < offset_entry_count; idx++)
5693 : {
5694 2 : printf (" [%6" PRIu32 "] ", idx);
5695 2 : if (offset_size == 4)
5696 : {
5697 2 : uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
5698 : printf ("0x%" PRIx32 "\n", off);
5699 : }
5700 : else
5701 : {
5702 0 : uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
5703 : printf ("0x%" PRIx64 "\n", off);
5704 : }
5705 : }
5706 : printf ("\n");
5707 : }
5708 :
5709 2 : Dwarf_Addr base = cu_base;
5710 2 : bool start_of_list = true;
5711 18 : while (readp < nexthdr)
5712 : {
5713 14 : uint8_t kind = *readp++;
5714 : uint64_t op1, op2;
5715 :
5716 : /* Skip padding. */
5717 14 : if (start_of_list && kind == DW_RLE_end_of_list)
5718 0 : continue;
5719 :
5720 14 : if (start_of_list)
5721 : {
5722 4 : base = cu_base;
5723 12 : printf (" Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
5724 4 : (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
5725 4 : (uint64_t) (readp - offset_array_start - 1));
5726 4 : start_of_list = false;
5727 : }
5728 :
5729 28 : printf (" %s", dwarf_range_list_encoding_name (kind));
5730 14 : switch (kind)
5731 : {
5732 4 : case DW_RLE_end_of_list:
5733 4 : start_of_list = true;
5734 : printf ("\n\n");
5735 : break;
5736 :
5737 0 : case DW_RLE_base_addressx:
5738 0 : if ((uint64_t) (nexthdr - readp) < 1)
5739 : {
5740 0 : invalid_range:
5741 0 : error (0, 0, gettext ("invalid range list data"));
5742 : goto next_table;
5743 : }
5744 0 : get_uleb128 (op1, readp, nexthdr);
5745 0 : printf (" %" PRIx64 "\n", op1);
5746 0 : if (! print_unresolved_addresses)
5747 : {
5748 : Dwarf_Addr addr;
5749 0 : if (get_indexed_addr (cu, op1, &addr) != 0)
5750 : printf (" ???\n");
5751 : else
5752 : {
5753 0 : printf (" ");
5754 0 : print_dwarf_addr (dwflmod, address_size, addr, addr);
5755 : printf ("\n");
5756 : }
5757 : }
5758 : break;
5759 :
5760 0 : case DW_RLE_startx_endx:
5761 0 : if ((uint64_t) (nexthdr - readp) < 1)
5762 : goto invalid_range;
5763 0 : get_uleb128 (op1, readp, nexthdr);
5764 0 : if ((uint64_t) (nexthdr - readp) < 1)
5765 : goto invalid_range;
5766 0 : get_uleb128 (op2, readp, nexthdr);
5767 0 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
5768 0 : if (! print_unresolved_addresses)
5769 : {
5770 : Dwarf_Addr addr1;
5771 : Dwarf_Addr addr2;
5772 0 : if (get_indexed_addr (cu, op1, &addr1) != 0
5773 0 : || get_indexed_addr (cu, op2, &addr2) != 0)
5774 : {
5775 0 : printf (" ???..\n");
5776 : printf (" ???\n");
5777 : }
5778 : else
5779 : {
5780 0 : printf (" ");
5781 0 : print_dwarf_addr (dwflmod, address_size, addr1, addr1);
5782 0 : printf ("..\n ");
5783 0 : print_dwarf_addr (dwflmod, address_size,
5784 : addr2 - 1, addr2);
5785 : printf ("\n");
5786 : }
5787 : }
5788 : break;
5789 :
5790 0 : case DW_RLE_startx_length:
5791 0 : if ((uint64_t) (nexthdr - readp) < 1)
5792 : goto invalid_range;
5793 0 : get_uleb128 (op1, readp, nexthdr);
5794 0 : if ((uint64_t) (nexthdr - readp) < 1)
5795 : goto invalid_range;
5796 0 : get_uleb128 (op2, readp, nexthdr);
5797 0 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
5798 0 : if (! print_unresolved_addresses)
5799 : {
5800 : Dwarf_Addr addr1;
5801 : Dwarf_Addr addr2;
5802 0 : if (get_indexed_addr (cu, op1, &addr1) != 0)
5803 : {
5804 0 : printf (" ???..\n");
5805 : printf (" ???\n");
5806 : }
5807 : else
5808 : {
5809 0 : addr2 = addr1 + op2;
5810 0 : printf (" ");
5811 0 : print_dwarf_addr (dwflmod, address_size, addr1, addr1);
5812 0 : printf ("..\n ");
5813 0 : print_dwarf_addr (dwflmod, address_size,
5814 : addr2 - 1, addr2);
5815 : printf ("\n");
5816 : }
5817 : }
5818 : break;
5819 :
5820 4 : case DW_RLE_offset_pair:
5821 4 : if ((uint64_t) (nexthdr - readp) < 1)
5822 : goto invalid_range;
5823 4 : get_uleb128 (op1, readp, nexthdr);
5824 4 : if ((uint64_t) (nexthdr - readp) < 1)
5825 : goto invalid_range;
5826 4 : get_uleb128 (op2, readp, nexthdr);
5827 4 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
5828 4 : if (! print_unresolved_addresses)
5829 : {
5830 4 : op1 += base;
5831 4 : op2 += base;
5832 4 : printf (" ");
5833 4 : print_dwarf_addr (dwflmod, address_size, op1, op1);
5834 4 : printf ("..\n ");
5835 4 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
5836 : printf ("\n");
5837 : }
5838 : break;
5839 :
5840 2 : case DW_RLE_base_address:
5841 2 : if (address_size == 4)
5842 : {
5843 0 : if ((uint64_t) (nexthdr - readp) < 4)
5844 : goto invalid_range;
5845 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
5846 : }
5847 : else
5848 : {
5849 2 : if ((uint64_t) (nexthdr - readp) < 8)
5850 : goto invalid_range;
5851 2 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
5852 : }
5853 2 : base = op1;
5854 2 : printf (" 0x%" PRIx64 "\n", base);
5855 2 : if (! print_unresolved_addresses)
5856 : {
5857 2 : printf (" ");
5858 2 : print_dwarf_addr (dwflmod, address_size, base, base);
5859 : printf ("\n");
5860 : }
5861 : break;
5862 :
5863 0 : case DW_RLE_start_end:
5864 0 : if (address_size == 4)
5865 : {
5866 0 : if ((uint64_t) (nexthdr - readp) < 8)
5867 : goto invalid_range;
5868 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
5869 0 : op2 = read_4ubyte_unaligned_inc (dbg, readp);
5870 : }
5871 : else
5872 : {
5873 0 : if ((uint64_t) (nexthdr - readp) < 16)
5874 : goto invalid_range;
5875 0 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
5876 0 : op2 = read_8ubyte_unaligned_inc (dbg, readp);
5877 : }
5878 0 : printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
5879 0 : if (! print_unresolved_addresses)
5880 : {
5881 0 : printf (" ");
5882 0 : print_dwarf_addr (dwflmod, address_size, op1, op1);
5883 0 : printf ("..\n ");
5884 0 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
5885 : printf ("\n");
5886 : }
5887 : break;
5888 :
5889 4 : case DW_RLE_start_length:
5890 4 : if (address_size == 4)
5891 : {
5892 0 : if ((uint64_t) (nexthdr - readp) < 4)
5893 : goto invalid_range;
5894 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
5895 : }
5896 : else
5897 : {
5898 4 : if ((uint64_t) (nexthdr - readp) < 8)
5899 : goto invalid_range;
5900 4 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
5901 : }
5902 4 : if ((uint64_t) (nexthdr - readp) < 1)
5903 : goto invalid_range;
5904 4 : get_uleb128 (op2, readp, nexthdr);
5905 4 : printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
5906 4 : if (! print_unresolved_addresses)
5907 : {
5908 4 : op2 = op1 + op2;
5909 4 : printf (" ");
5910 4 : print_dwarf_addr (dwflmod, address_size, op1, op1);
5911 4 : printf ("..\n ");
5912 4 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
5913 : printf ("\n");
5914 : }
5915 : break;
5916 :
5917 : default:
5918 : goto invalid_range;
5919 : }
5920 : }
5921 :
5922 2 : next_table:
5923 2 : if (readp != nexthdr)
5924 : {
5925 0 : size_t padding = nexthdr - readp;
5926 0 : printf (gettext (" %zu padding bytes\n\n"), padding);
5927 0 : readp = nexthdr;
5928 : }
5929 : }
5930 : }
5931 :
5932 : /* Print content of DWARF .debug_ranges section. */
5933 : static void
5934 30 : print_debug_ranges_section (Dwfl_Module *dwflmod,
5935 : Ebl *ebl, GElf_Ehdr *ehdr,
5936 : Elf_Scn *scn, GElf_Shdr *shdr,
5937 : Dwarf *dbg)
5938 : {
5939 60 : Elf_Data *data = (dbg->sectiondata[IDX_debug_ranges]
5940 30 : ?: elf_rawdata (scn, NULL));
5941 30 : if (unlikely (data == NULL))
5942 : {
5943 0 : error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
5944 : elf_errmsg (-1));
5945 0 : return;
5946 : }
5947 :
5948 60 : printf (gettext ("\
5949 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5950 : elf_ndxscn (scn), section_name (ebl, shdr),
5951 30 : (uint64_t) shdr->sh_offset);
5952 :
5953 60 : sort_listptr (&known_rangelistptr, "rangelistptr");
5954 30 : size_t listptr_idx = 0;
5955 :
5956 30 : uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5957 :
5958 30 : bool first = true;
5959 30 : Dwarf_Addr base = 0;
5960 30 : unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
5961 30 : unsigned char *readp = data->d_buf;
5962 30 : Dwarf_CU *last_cu = NULL;
5963 38305 : while (readp < endp)
5964 : {
5965 38245 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
5966 38245 : Dwarf_CU *cu = last_cu;
5967 :
5968 38245 : if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
5969 : &address_size, NULL, &base, &cu,
5970 : offset, &readp, endp, NULL))
5971 0 : continue;
5972 :
5973 38245 : if (last_cu != cu)
5974 : {
5975 : Dwarf_Die cudie;
5976 588 : if (dwarf_cu_die (cu, &cudie,
5977 : NULL, NULL, NULL, NULL,
5978 : NULL, NULL) == NULL)
5979 0 : printf (gettext ("\n Unknown CU base: "));
5980 : else
5981 588 : printf (gettext ("\n CU [%6" PRIx64 "] base: "),
5982 : dwarf_dieoffset (&cudie));
5983 588 : print_dwarf_addr (dwflmod, address_size, base, base);
5984 588 : printf ("\n");
5985 : }
5986 38245 : last_cu = cu;
5987 :
5988 38245 : if (unlikely (data->d_size - offset < (size_t) address_size * 2))
5989 : {
5990 0 : printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
5991 0 : break;
5992 : }
5993 :
5994 : Dwarf_Addr begin;
5995 : Dwarf_Addr end;
5996 38245 : if (address_size == 8)
5997 : {
5998 38245 : begin = read_8ubyte_unaligned_inc (dbg, readp);
5999 38245 : end = read_8ubyte_unaligned_inc (dbg, readp);
6000 : }
6001 : else
6002 : {
6003 0 : begin = read_4ubyte_unaligned_inc (dbg, readp);
6004 0 : end = read_4ubyte_unaligned_inc (dbg, readp);
6005 0 : if (begin == (Dwarf_Addr) (uint32_t) -1)
6006 : begin = (Dwarf_Addr) -1l;
6007 : }
6008 :
6009 38245 : if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
6010 : {
6011 0 : printf (gettext (" [%6tx] base address\n "), offset);
6012 0 : print_dwarf_addr (dwflmod, address_size, end, end);
6013 0 : printf ("\n");
6014 0 : base = end;
6015 : }
6016 38245 : else if (begin == 0 && end == 0) /* End of list entry. */
6017 : {
6018 8925 : if (first)
6019 0 : printf (gettext (" [%6tx] empty list\n"), offset);
6020 : first = true;
6021 : }
6022 : else
6023 : {
6024 : /* We have an address range entry. */
6025 29320 : if (first) /* First address range entry in a list. */
6026 : printf (" [%6tx] ", offset);
6027 : else
6028 : printf (" ");
6029 :
6030 29320 : printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
6031 29320 : if (! print_unresolved_addresses)
6032 : {
6033 29310 : printf (" ");
6034 29310 : print_dwarf_addr (dwflmod, address_size, base + begin,
6035 : base + begin);
6036 29310 : printf ("..\n ");
6037 29310 : print_dwarf_addr (dwflmod, address_size,
6038 : base + end - 1, base + end);
6039 : printf ("\n");
6040 : }
6041 :
6042 : first = false;
6043 : }
6044 : }
6045 : }
6046 :
6047 : #define REGNAMESZ 16
6048 : static const char *
6049 9583 : register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
6050 : char name[REGNAMESZ], int *bits, int *type)
6051 : {
6052 : const char *set;
6053 : const char *pfx;
6054 : int ignore;
6055 9583 : ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
6056 : bits ?: &ignore, type ?: &ignore);
6057 9583 : if (n <= 0)
6058 : {
6059 0 : if (loc != NULL)
6060 0 : snprintf (name, REGNAMESZ, "reg%u", loc->regno);
6061 : else
6062 : snprintf (name, REGNAMESZ, "??? 0x%x", regno);
6063 0 : if (bits != NULL)
6064 0 : *bits = loc != NULL ? loc->bits : 0;
6065 0 : if (type != NULL)
6066 0 : *type = DW_ATE_unsigned;
6067 0 : set = "??? unrecognized";
6068 : }
6069 : else
6070 : {
6071 9583 : if (bits != NULL && *bits <= 0)
6072 0 : *bits = loc != NULL ? loc->bits : 0;
6073 9583 : if (type != NULL && *type == DW_ATE_void)
6074 0 : *type = DW_ATE_unsigned;
6075 :
6076 : }
6077 9583 : return set;
6078 : }
6079 :
6080 : static const unsigned char *
6081 28 : read_encoded (unsigned int encoding, const unsigned char *readp,
6082 : const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
6083 : {
6084 28 : if ((encoding & 0xf) == DW_EH_PE_absptr)
6085 0 : encoding = gelf_getclass (dbg->elf) == ELFCLASS32
6086 0 : ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
6087 :
6088 28 : switch (encoding & 0xf)
6089 : {
6090 0 : case DW_EH_PE_uleb128:
6091 0 : get_uleb128 (*res, readp, endp);
6092 : break;
6093 0 : case DW_EH_PE_sleb128:
6094 0 : get_sleb128 (*res, readp, endp);
6095 : break;
6096 0 : case DW_EH_PE_udata2:
6097 0 : if (readp + 2 > endp)
6098 : goto invalid;
6099 0 : *res = read_2ubyte_unaligned_inc (dbg, readp);
6100 : break;
6101 14 : case DW_EH_PE_udata4:
6102 14 : if (readp + 4 > endp)
6103 : goto invalid;
6104 14 : *res = read_4ubyte_unaligned_inc (dbg, readp);
6105 : break;
6106 0 : case DW_EH_PE_udata8:
6107 0 : if (readp + 8 > endp)
6108 : goto invalid;
6109 0 : *res = read_8ubyte_unaligned_inc (dbg, readp);
6110 : break;
6111 0 : case DW_EH_PE_sdata2:
6112 0 : if (readp + 2 > endp)
6113 : goto invalid;
6114 0 : *res = read_2sbyte_unaligned_inc (dbg, readp);
6115 : break;
6116 14 : case DW_EH_PE_sdata4:
6117 14 : if (readp + 4 > endp)
6118 : goto invalid;
6119 14 : *res = read_4sbyte_unaligned_inc (dbg, readp);
6120 : break;
6121 0 : case DW_EH_PE_sdata8:
6122 0 : if (readp + 8 > endp)
6123 : goto invalid;
6124 0 : *res = read_8sbyte_unaligned_inc (dbg, readp);
6125 : break;
6126 : default:
6127 0 : invalid:
6128 : error (1, 0,
6129 0 : gettext ("invalid encoding"));
6130 : }
6131 :
6132 28 : return readp;
6133 : }
6134 :
6135 :
6136 : static void
6137 4629 : print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
6138 : Dwarf_Word vma_base, unsigned int code_align,
6139 : int data_align,
6140 : unsigned int version, unsigned int ptr_size,
6141 : unsigned int encoding,
6142 : Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
6143 : {
6144 : char regnamebuf[REGNAMESZ];
6145 : const char *regname (unsigned int regno)
6146 : {
6147 8735 : register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
6148 : return regnamebuf;
6149 : }
6150 :
6151 4629 : puts ("\n Program:");
6152 4629 : Dwarf_Word pc = vma_base;
6153 85168 : while (readp < endp)
6154 : {
6155 75910 : unsigned int opcode = *readp++;
6156 :
6157 75910 : if (opcode < DW_CFA_advance_loc)
6158 : /* Extended opcode. */
6159 43824 : switch (opcode)
6160 : {
6161 : uint64_t op1;
6162 : int64_t sop1;
6163 : uint64_t op2;
6164 : int64_t sop2;
6165 :
6166 12882 : case DW_CFA_nop:
6167 12882 : puts (" nop");
6168 56706 : break;
6169 0 : case DW_CFA_set_loc:
6170 0 : if ((uint64_t) (endp - readp) < 1)
6171 : goto invalid;
6172 0 : readp = read_encoded (encoding, readp, endp, &op1, dbg);
6173 0 : printf (" set_loc %#" PRIx64 " to %#" PRIx64 "\n",
6174 0 : op1, pc = vma_base + op1);
6175 : break;
6176 1658 : case DW_CFA_advance_loc1:
6177 1658 : if ((uint64_t) (endp - readp) < 1)
6178 : goto invalid;
6179 3316 : printf (" advance_loc1 %u to %#" PRIx64 "\n",
6180 1658 : *readp, pc += *readp * code_align);
6181 1658 : ++readp;
6182 1658 : break;
6183 749 : case DW_CFA_advance_loc2:
6184 749 : if ((uint64_t) (endp - readp) < 2)
6185 : goto invalid;
6186 749 : op1 = read_2ubyte_unaligned_inc (dbg, readp);
6187 749 : printf (" advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
6188 749 : op1, pc += op1 * code_align);
6189 : break;
6190 24 : case DW_CFA_advance_loc4:
6191 24 : if ((uint64_t) (endp - readp) < 4)
6192 : goto invalid;
6193 48 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
6194 24 : printf (" advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
6195 24 : op1, pc += op1 * code_align);
6196 : break;
6197 4 : case DW_CFA_offset_extended:
6198 4 : if ((uint64_t) (endp - readp) < 1)
6199 : goto invalid;
6200 4 : get_uleb128 (op1, readp, endp);
6201 4 : if ((uint64_t) (endp - readp) < 1)
6202 : goto invalid;
6203 4 : get_uleb128 (op2, readp, endp);
6204 8 : printf (" offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
6205 : "\n",
6206 : op1, regname (op1), op2 * data_align);
6207 : break;
6208 0 : case DW_CFA_restore_extended:
6209 0 : if ((uint64_t) (endp - readp) < 1)
6210 : goto invalid;
6211 0 : get_uleb128 (op1, readp, endp);
6212 0 : printf (" restore_extended r%" PRIu64 " (%s)\n",
6213 : op1, regname (op1));
6214 : break;
6215 6 : case DW_CFA_undefined:
6216 6 : if ((uint64_t) (endp - readp) < 1)
6217 : goto invalid;
6218 6 : get_uleb128 (op1, readp, endp);
6219 12 : printf (" undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
6220 : break;
6221 0 : case DW_CFA_same_value:
6222 0 : if ((uint64_t) (endp - readp) < 1)
6223 : goto invalid;
6224 0 : get_uleb128 (op1, readp, endp);
6225 0 : printf (" same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
6226 : break;
6227 0 : case DW_CFA_register:
6228 0 : if ((uint64_t) (endp - readp) < 1)
6229 : goto invalid;
6230 0 : get_uleb128 (op1, readp, endp);
6231 0 : if ((uint64_t) (endp - readp) < 1)
6232 : goto invalid;
6233 0 : get_uleb128 (op2, readp, endp);
6234 0 : printf (" register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
6235 : op1, regname (op1), op2, regname (op2));
6236 : break;
6237 2619 : case DW_CFA_remember_state:
6238 2619 : puts (" remember_state");
6239 2619 : break;
6240 2619 : case DW_CFA_restore_state:
6241 2619 : puts (" restore_state");
6242 2619 : break;
6243 124 : case DW_CFA_def_cfa:
6244 124 : if ((uint64_t) (endp - readp) < 1)
6245 : goto invalid;
6246 124 : get_uleb128 (op1, readp, endp);
6247 124 : if ((uint64_t) (endp - readp) < 1)
6248 : goto invalid;
6249 124 : get_uleb128 (op2, readp, endp);
6250 248 : printf (" def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
6251 : op1, regname (op1), op2);
6252 : break;
6253 46 : case DW_CFA_def_cfa_register:
6254 46 : if ((uint64_t) (endp - readp) < 1)
6255 : goto invalid;
6256 46 : get_uleb128 (op1, readp, endp);
6257 92 : printf (" def_cfa_register r%" PRIu64 " (%s)\n",
6258 : op1, regname (op1));
6259 : break;
6260 23065 : case DW_CFA_def_cfa_offset:
6261 23065 : if ((uint64_t) (endp - readp) < 1)
6262 : goto invalid;
6263 23065 : get_uleb128 (op1, readp, endp);
6264 23065 : printf (" def_cfa_offset %" PRIu64 "\n", op1);
6265 : break;
6266 12 : case DW_CFA_def_cfa_expression:
6267 12 : if ((uint64_t) (endp - readp) < 1)
6268 : goto invalid;
6269 12 : get_uleb128 (op1, readp, endp); /* Length of DW_FORM_block. */
6270 24 : printf (" def_cfa_expression %" PRIu64 "\n", op1);
6271 12 : if ((uint64_t) (endp - readp) < op1)
6272 : {
6273 0 : invalid:
6274 0 : fputs (gettext (" <INVALID DATA>\n"), stdout);
6275 0 : return;
6276 : }
6277 12 : print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
6278 : op1, readp);
6279 12 : readp += op1;
6280 12 : break;
6281 0 : case DW_CFA_expression:
6282 0 : if ((uint64_t) (endp - readp) < 1)
6283 : goto invalid;
6284 0 : get_uleb128 (op1, readp, endp);
6285 0 : if ((uint64_t) (endp - readp) < 1)
6286 : goto invalid;
6287 0 : get_uleb128 (op2, readp, endp); /* Length of DW_FORM_block. */
6288 0 : printf (" expression r%" PRIu64 " (%s) \n",
6289 : op1, regname (op1));
6290 0 : if ((uint64_t) (endp - readp) < op2)
6291 : goto invalid;
6292 0 : print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
6293 : op2, readp);
6294 0 : readp += op2;
6295 0 : break;
6296 16 : case DW_CFA_offset_extended_sf:
6297 16 : if ((uint64_t) (endp - readp) < 1)
6298 : goto invalid;
6299 16 : get_uleb128 (op1, readp, endp);
6300 16 : if ((uint64_t) (endp - readp) < 1)
6301 : goto invalid;
6302 16 : get_sleb128 (sop2, readp, endp);
6303 32 : printf (" offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
6304 : PRId64 "\n",
6305 : op1, regname (op1), sop2 * data_align);
6306 : break;
6307 0 : case DW_CFA_def_cfa_sf:
6308 0 : if ((uint64_t) (endp - readp) < 1)
6309 : goto invalid;
6310 0 : get_uleb128 (op1, readp, endp);
6311 0 : if ((uint64_t) (endp - readp) < 1)
6312 : goto invalid;
6313 0 : get_sleb128 (sop2, readp, endp);
6314 0 : printf (" def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
6315 : op1, regname (op1), sop2 * data_align);
6316 : break;
6317 0 : case DW_CFA_def_cfa_offset_sf:
6318 0 : if ((uint64_t) (endp - readp) < 1)
6319 : goto invalid;
6320 0 : get_sleb128 (sop1, readp, endp);
6321 0 : printf (" def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
6322 : break;
6323 0 : case DW_CFA_val_offset:
6324 0 : if ((uint64_t) (endp - readp) < 1)
6325 : goto invalid;
6326 0 : get_uleb128 (op1, readp, endp);
6327 0 : if ((uint64_t) (endp - readp) < 1)
6328 : goto invalid;
6329 0 : get_uleb128 (op2, readp, endp);
6330 0 : printf (" val_offset %" PRIu64 " at offset %" PRIu64 "\n",
6331 : op1, op2 * data_align);
6332 : break;
6333 0 : case DW_CFA_val_offset_sf:
6334 0 : if ((uint64_t) (endp - readp) < 1)
6335 : goto invalid;
6336 0 : get_uleb128 (op1, readp, endp);
6337 0 : if ((uint64_t) (endp - readp) < 1)
6338 : goto invalid;
6339 0 : get_sleb128 (sop2, readp, endp);
6340 0 : printf (" val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
6341 : op1, sop2 * data_align);
6342 : break;
6343 0 : case DW_CFA_val_expression:
6344 0 : if ((uint64_t) (endp - readp) < 1)
6345 : goto invalid;
6346 0 : get_uleb128 (op1, readp, endp);
6347 0 : if ((uint64_t) (endp - readp) < 1)
6348 : goto invalid;
6349 0 : get_uleb128 (op2, readp, endp); /* Length of DW_FORM_block. */
6350 0 : printf (" val_expression r%" PRIu64 " (%s)\n",
6351 : op1, regname (op1));
6352 0 : if ((uint64_t) (endp - readp) < op2)
6353 : goto invalid;
6354 0 : print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0,
6355 : NULL, op2, readp);
6356 0 : readp += op2;
6357 0 : break;
6358 0 : case DW_CFA_MIPS_advance_loc8:
6359 0 : if ((uint64_t) (endp - readp) < 8)
6360 : goto invalid;
6361 0 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
6362 0 : printf (" MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
6363 0 : op1, pc += op1 * code_align);
6364 : break;
6365 0 : case DW_CFA_GNU_window_save:
6366 0 : puts (" GNU_window_save");
6367 0 : break;
6368 0 : case DW_CFA_GNU_args_size:
6369 0 : if ((uint64_t) (endp - readp) < 1)
6370 : goto invalid;
6371 0 : get_uleb128 (op1, readp, endp);
6372 0 : printf (" args_size %" PRIu64 "\n", op1);
6373 : break;
6374 0 : default:
6375 : printf (" ??? (%u)\n", opcode);
6376 : break;
6377 : }
6378 32086 : else if (opcode < DW_CFA_offset)
6379 23547 : printf (" advance_loc %u to %#" PRIx64 "\n",
6380 23547 : opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
6381 8539 : else if (opcode < DW_CFA_restore)
6382 : {
6383 : uint64_t offset;
6384 7281 : if ((uint64_t) (endp - readp) < 1)
6385 : goto invalid;
6386 7281 : get_uleb128 (offset, readp, endp);
6387 14562 : printf (" offset r%u (%s) at cfa%+" PRId64 "\n",
6388 : opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
6389 : }
6390 : else
6391 2516 : printf (" restore r%u (%s)\n",
6392 : opcode & 0x3f, regname (opcode & 0x3f));
6393 : }
6394 : }
6395 :
6396 :
6397 : static unsigned int
6398 4557 : encoded_ptr_size (int encoding, unsigned int ptr_size)
6399 : {
6400 4557 : switch (encoding & 7)
6401 : {
6402 : case DW_EH_PE_udata4:
6403 : return 4;
6404 0 : case DW_EH_PE_udata8:
6405 0 : return 8;
6406 44 : case 0:
6407 44 : return ptr_size;
6408 : }
6409 :
6410 0 : fprintf (stderr, "Unsupported pointer encoding: %#x, "
6411 : "assuming pointer size of %d.\n", encoding, ptr_size);
6412 0 : return ptr_size;
6413 : }
6414 :
6415 :
6416 : static unsigned int
6417 78 : print_encoding (unsigned int val)
6418 : {
6419 78 : switch (val & 0xf)
6420 : {
6421 0 : case DW_EH_PE_absptr:
6422 0 : fputs ("absptr", stdout);
6423 0 : break;
6424 0 : case DW_EH_PE_uleb128:
6425 0 : fputs ("uleb128", stdout);
6426 0 : break;
6427 0 : case DW_EH_PE_udata2:
6428 0 : fputs ("udata2", stdout);
6429 0 : break;
6430 14 : case DW_EH_PE_udata4:
6431 14 : fputs ("udata4", stdout);
6432 14 : break;
6433 0 : case DW_EH_PE_udata8:
6434 0 : fputs ("udata8", stdout);
6435 0 : break;
6436 0 : case DW_EH_PE_sleb128:
6437 0 : fputs ("sleb128", stdout);
6438 0 : break;
6439 0 : case DW_EH_PE_sdata2:
6440 0 : fputs ("sdata2", stdout);
6441 0 : break;
6442 64 : case DW_EH_PE_sdata4:
6443 64 : fputs ("sdata4", stdout);
6444 64 : break;
6445 0 : case DW_EH_PE_sdata8:
6446 0 : fputs ("sdata8", stdout);
6447 0 : break;
6448 : default:
6449 : /* We did not use any of the bits after all. */
6450 : return val;
6451 : }
6452 :
6453 78 : return val & ~0xf;
6454 : }
6455 :
6456 :
6457 : static unsigned int
6458 64 : print_relinfo (unsigned int val)
6459 : {
6460 64 : switch (val & 0x70)
6461 : {
6462 50 : case DW_EH_PE_pcrel:
6463 50 : fputs ("pcrel", stdout);
6464 50 : break;
6465 0 : case DW_EH_PE_textrel:
6466 0 : fputs ("textrel", stdout);
6467 0 : break;
6468 14 : case DW_EH_PE_datarel:
6469 14 : fputs ("datarel", stdout);
6470 14 : break;
6471 0 : case DW_EH_PE_funcrel:
6472 0 : fputs ("funcrel", stdout);
6473 0 : break;
6474 0 : case DW_EH_PE_aligned:
6475 0 : fputs ("aligned", stdout);
6476 0 : break;
6477 : default:
6478 : return val;
6479 : }
6480 :
6481 64 : return val & ~0x70;
6482 : }
6483 :
6484 :
6485 : static void
6486 78 : print_encoding_base (const char *pfx, unsigned int fde_encoding)
6487 : {
6488 78 : printf ("(%s", pfx);
6489 :
6490 78 : if (fde_encoding == DW_EH_PE_omit)
6491 0 : puts ("omit)");
6492 : else
6493 : {
6494 78 : unsigned int w = fde_encoding;
6495 :
6496 78 : w = print_encoding (w);
6497 :
6498 78 : if (w & 0x70)
6499 : {
6500 64 : if (w != fde_encoding)
6501 64 : fputc_unlocked (' ', stdout);
6502 :
6503 64 : w = print_relinfo (w);
6504 : }
6505 :
6506 78 : if (w != 0)
6507 0 : printf ("%s%x", w != fde_encoding ? " " : "", w);
6508 :
6509 78 : puts (")");
6510 : }
6511 78 : }
6512 :
6513 :
6514 : static void
6515 48 : print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
6516 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6517 : {
6518 : size_t shstrndx;
6519 : /* We know this call will succeed since it did in the caller. */
6520 48 : (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
6521 48 : const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
6522 :
6523 : /* Needed if we find PC-relative addresses. */
6524 : GElf_Addr bias;
6525 48 : if (dwfl_module_getelf (dwflmod, &bias) == NULL)
6526 : {
6527 0 : error (0, 0, gettext ("cannot get ELF: %s"), dwfl_errmsg (-1));
6528 0 : return;
6529 : }
6530 :
6531 48 : bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
6532 48 : Elf_Data *data = (is_eh_frame
6533 : ? elf_rawdata (scn, NULL)
6534 48 : : (dbg->sectiondata[IDX_debug_frame]
6535 22 : ?: elf_rawdata (scn, NULL)));
6536 :
6537 48 : if (unlikely (data == NULL))
6538 : {
6539 0 : error (0, 0, gettext ("cannot get %s content: %s"),
6540 : scnname, elf_errmsg (-1));
6541 : return;
6542 : }
6543 :
6544 48 : if (is_eh_frame)
6545 26 : printf (gettext ("\
6546 : \nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6547 26 : elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
6548 : else
6549 22 : printf (gettext ("\
6550 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6551 22 : elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
6552 :
6553 : struct cieinfo
6554 : {
6555 : ptrdiff_t cie_offset;
6556 : const char *augmentation;
6557 : unsigned int code_alignment_factor;
6558 : unsigned int data_alignment_factor;
6559 : uint8_t address_size;
6560 : uint8_t fde_encoding;
6561 : uint8_t lsda_encoding;
6562 : struct cieinfo *next;
6563 48 : } *cies = NULL;
6564 :
6565 48 : const unsigned char *readp = data->d_buf;
6566 48 : const unsigned char *const dataend = ((unsigned char *) data->d_buf
6567 48 : + data->d_size);
6568 4739 : while (readp < dataend)
6569 : {
6570 4643 : if (unlikely (readp + 4 > dataend))
6571 : {
6572 0 : invalid_data:
6573 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
6574 : elf_ndxscn (scn), scnname);
6575 : return;
6576 : }
6577 :
6578 : /* At the beginning there must be a CIE. There can be multiple,
6579 : hence we test tis in a loop. */
6580 4643 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
6581 :
6582 4687 : Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
6583 4643 : unsigned int length = 4;
6584 4643 : if (unlikely (unit_length == 0xffffffff))
6585 : {
6586 0 : if (unlikely (readp + 8 > dataend))
6587 : goto invalid_data;
6588 :
6589 0 : unit_length = read_8ubyte_unaligned_inc (dbg, readp);
6590 0 : length = 8;
6591 : }
6592 :
6593 4643 : if (unlikely (unit_length == 0))
6594 : {
6595 28 : printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
6596 14 : continue;
6597 : }
6598 :
6599 4629 : Dwarf_Word maxsize = dataend - readp;
6600 4629 : if (unlikely (unit_length > maxsize))
6601 : goto invalid_data;
6602 :
6603 4629 : unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6604 :
6605 4629 : ptrdiff_t start = readp - (unsigned char *) data->d_buf;
6606 4629 : const unsigned char *const cieend = readp + unit_length;
6607 4629 : if (unlikely (cieend > dataend))
6608 : goto invalid_data;
6609 :
6610 : Dwarf_Off cie_id;
6611 4629 : if (length == 4)
6612 : {
6613 4629 : if (unlikely (cieend - readp < 4))
6614 : goto invalid_data;
6615 4673 : cie_id = read_4ubyte_unaligned_inc (dbg, readp);
6616 4629 : if (!is_eh_frame && cie_id == DW_CIE_ID_32)
6617 34 : cie_id = DW_CIE_ID_64;
6618 : }
6619 : else
6620 : {
6621 0 : if (unlikely (cieend - readp < 8))
6622 : goto invalid_data;
6623 0 : cie_id = read_8ubyte_unaligned_inc (dbg, readp);
6624 : }
6625 :
6626 4629 : uint_fast8_t version = 2;
6627 : unsigned int code_alignment_factor;
6628 : int data_alignment_factor;
6629 4629 : unsigned int fde_encoding = 0;
6630 4629 : unsigned int lsda_encoding = 0;
6631 4629 : Dwarf_Word initial_location = 0;
6632 4629 : Dwarf_Word vma_base = 0;
6633 :
6634 4629 : if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
6635 : {
6636 72 : if (unlikely (cieend - readp < 2))
6637 : goto invalid_data;
6638 72 : version = *readp++;
6639 72 : const char *const augmentation = (const char *) readp;
6640 72 : readp = memchr (readp, '\0', cieend - readp);
6641 72 : if (unlikely (readp == NULL))
6642 : goto invalid_data;
6643 72 : ++readp;
6644 :
6645 72 : uint_fast8_t segment_size = 0;
6646 72 : if (version >= 4)
6647 : {
6648 0 : if (cieend - readp < 5)
6649 : goto invalid_data;
6650 0 : ptr_size = *readp++;
6651 0 : segment_size = *readp++;
6652 : }
6653 :
6654 72 : if (cieend - readp < 1)
6655 : goto invalid_data;
6656 72 : get_uleb128 (code_alignment_factor, readp, cieend);
6657 72 : if (cieend - readp < 1)
6658 : goto invalid_data;
6659 72 : get_sleb128 (data_alignment_factor, readp, cieend);
6660 :
6661 : /* In some variant for unwind data there is another field. */
6662 72 : if (strcmp (augmentation, "eh") == 0)
6663 0 : readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6664 :
6665 : unsigned int return_address_register;
6666 72 : if (cieend - readp < 1)
6667 : goto invalid_data;
6668 72 : if (unlikely (version == 1))
6669 60 : return_address_register = *readp++;
6670 : else
6671 12 : get_uleb128 (return_address_register, readp, cieend);
6672 :
6673 144 : printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
6674 : " CIE_id: %" PRIu64 "\n"
6675 : " version: %u\n"
6676 : " augmentation: \"%s\"\n",
6677 : offset, (uint64_t) unit_length, (uint64_t) cie_id,
6678 : version, augmentation);
6679 72 : if (version >= 4)
6680 0 : printf (" address_size: %u\n"
6681 : " segment_size: %u\n",
6682 : ptr_size, segment_size);
6683 72 : printf (" code_alignment_factor: %u\n"
6684 : " data_alignment_factor: %d\n"
6685 : " return_address_register: %u\n",
6686 : code_alignment_factor,
6687 : data_alignment_factor, return_address_register);
6688 :
6689 72 : if (augmentation[0] == 'z')
6690 : {
6691 : unsigned int augmentationlen;
6692 36 : get_uleb128 (augmentationlen, readp, cieend);
6693 :
6694 36 : if (augmentationlen > (size_t) (cieend - readp))
6695 : {
6696 0 : error (0, 0, gettext ("invalid augmentation length"));
6697 0 : readp = cieend;
6698 0 : continue;
6699 : }
6700 :
6701 36 : const char *hdr = "Augmentation data:";
6702 36 : const char *cp = augmentation + 1;
6703 108 : while (*cp != '\0' && cp < augmentation + augmentationlen + 1)
6704 : {
6705 72 : printf (" %-26s%#x ", hdr, *readp);
6706 36 : hdr = "";
6707 :
6708 36 : if (*cp == 'R')
6709 : {
6710 36 : fde_encoding = *readp++;
6711 36 : print_encoding_base (gettext ("FDE address encoding: "),
6712 : fde_encoding);
6713 : }
6714 0 : else if (*cp == 'L')
6715 : {
6716 0 : lsda_encoding = *readp++;
6717 0 : print_encoding_base (gettext ("LSDA pointer encoding: "),
6718 : lsda_encoding);
6719 : }
6720 0 : else if (*cp == 'P')
6721 : {
6722 : /* Personality. This field usually has a relocation
6723 : attached pointing to __gcc_personality_v0. */
6724 0 : const unsigned char *startp = readp;
6725 0 : unsigned int encoding = *readp++;
6726 0 : uint64_t val = 0;
6727 0 : readp = read_encoded (encoding, readp,
6728 0 : readp - 1 + augmentationlen,
6729 : &val, dbg);
6730 :
6731 0 : while (++startp < readp)
6732 0 : printf ("%#x ", *startp);
6733 :
6734 0 : putchar ('(');
6735 0 : print_encoding (encoding);
6736 0 : putchar (' ');
6737 0 : switch (encoding & 0xf)
6738 : {
6739 0 : case DW_EH_PE_sleb128:
6740 : case DW_EH_PE_sdata2:
6741 : case DW_EH_PE_sdata4:
6742 0 : printf ("%" PRId64 ")\n", val);
6743 : break;
6744 0 : default:
6745 0 : printf ("%#" PRIx64 ")\n", val);
6746 : break;
6747 : }
6748 : }
6749 : else
6750 0 : printf ("(%x)\n", *readp++);
6751 :
6752 36 : ++cp;
6753 : }
6754 : }
6755 :
6756 72 : if (likely (ptr_size == 4 || ptr_size == 8))
6757 : {
6758 72 : struct cieinfo *newp = alloca (sizeof (*newp));
6759 72 : newp->cie_offset = offset;
6760 72 : newp->augmentation = augmentation;
6761 72 : newp->fde_encoding = fde_encoding;
6762 72 : newp->lsda_encoding = lsda_encoding;
6763 72 : newp->address_size = ptr_size;
6764 72 : newp->code_alignment_factor = code_alignment_factor;
6765 72 : newp->data_alignment_factor = data_alignment_factor;
6766 72 : newp->next = cies;
6767 72 : cies = newp;
6768 : }
6769 : }
6770 : else
6771 : {
6772 : struct cieinfo *cie = cies;
6773 4557 : while (cie != NULL)
6774 9114 : if (is_eh_frame
6775 4519 : ? ((Dwarf_Off) start - cie_id) == (Dwarf_Off) cie->cie_offset
6776 38 : : cie_id == (Dwarf_Off) cie->cie_offset)
6777 : break;
6778 : else
6779 0 : cie = cie->next;
6780 4557 : if (unlikely (cie == NULL))
6781 : {
6782 0 : puts ("invalid CIE reference in FDE");
6783 0 : return;
6784 : }
6785 :
6786 : /* Initialize from CIE data. */
6787 4557 : fde_encoding = cie->fde_encoding;
6788 4557 : lsda_encoding = cie->lsda_encoding;
6789 4557 : ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
6790 4557 : code_alignment_factor = cie->code_alignment_factor;
6791 4557 : data_alignment_factor = cie->data_alignment_factor;
6792 :
6793 4557 : const unsigned char *base = readp;
6794 : // XXX There are sometimes relocations for this value
6795 4579 : initial_location = read_addr_unaligned_inc (ptr_size, dbg, readp);
6796 4557 : Dwarf_Word address_range
6797 4579 : = read_addr_unaligned_inc (ptr_size, dbg, readp);
6798 :
6799 : /* pcrel for an FDE address is relative to the runtime
6800 : address of the start_address field itself. Sign extend
6801 : if necessary to make sure the calculation is done on the
6802 : full 64 bit address even when initial_location only holds
6803 : the lower 32 bits. */
6804 4557 : Dwarf_Addr pc_start = initial_location;
6805 4557 : if (ptr_size == 4)
6806 4517 : pc_start = (uint64_t) (int32_t) pc_start;
6807 4557 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
6808 9026 : pc_start += ((uint64_t) shdr->sh_addr
6809 4513 : + (base - (const unsigned char *) data->d_buf)
6810 4513 : - bias);
6811 :
6812 9114 : printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
6813 : " CIE_pointer: %" PRIu64 "\n"
6814 : " initial_location: ",
6815 : offset, (uint64_t) unit_length,
6816 : cie->cie_offset, (uint64_t) cie_id);
6817 4557 : print_dwarf_addr (dwflmod, cie->address_size,
6818 : pc_start, initial_location);
6819 4557 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
6820 : {
6821 9026 : vma_base = (((uint64_t) shdr->sh_offset
6822 4513 : + (base - (const unsigned char *) data->d_buf)
6823 4513 : + (uint64_t) initial_location)
6824 : & (ptr_size == 4
6825 : ? UINT64_C (0xffffffff)
6826 4513 : : UINT64_C (0xffffffffffffffff)));
6827 4513 : printf (gettext (" (offset: %#" PRIx64 ")"),
6828 : (uint64_t) vma_base);
6829 : }
6830 :
6831 4557 : printf ("\n address_range: %#" PRIx64,
6832 : (uint64_t) address_range);
6833 4557 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
6834 4513 : printf (gettext (" (end offset: %#" PRIx64 ")"),
6835 4513 : ((uint64_t) vma_base + (uint64_t) address_range)
6836 : & (ptr_size == 4
6837 : ? UINT64_C (0xffffffff)
6838 4513 : : UINT64_C (0xffffffffffffffff)));
6839 4557 : putchar ('\n');
6840 :
6841 4557 : if (cie->augmentation[0] == 'z')
6842 : {
6843 : unsigned int augmentationlen;
6844 4513 : if (cieend - readp < 1)
6845 : goto invalid_data;
6846 4513 : get_uleb128 (augmentationlen, readp, cieend);
6847 :
6848 4513 : if (augmentationlen > (size_t) (cieend - readp))
6849 : {
6850 0 : error (0, 0, gettext ("invalid augmentation length"));
6851 0 : readp = cieend;
6852 0 : continue;
6853 : }
6854 :
6855 4513 : if (augmentationlen > 0)
6856 : {
6857 0 : const char *hdr = "Augmentation data:";
6858 0 : const char *cp = cie->augmentation + 1;
6859 0 : unsigned int u = 0;
6860 0 : while (*cp != '\0'
6861 0 : && cp < cie->augmentation + augmentationlen + 1)
6862 : {
6863 0 : if (*cp == 'L')
6864 : {
6865 : uint64_t lsda_pointer;
6866 0 : const unsigned char *p
6867 0 : = read_encoded (lsda_encoding, &readp[u],
6868 : &readp[augmentationlen],
6869 : &lsda_pointer, dbg);
6870 0 : u = p - readp;
6871 0 : printf (gettext ("\
6872 : %-26sLSDA pointer: %#" PRIx64 "\n"),
6873 : hdr, lsda_pointer);
6874 0 : hdr = "";
6875 : }
6876 0 : ++cp;
6877 : }
6878 :
6879 0 : while (u < augmentationlen)
6880 : {
6881 0 : printf (" %-26s%#x\n", hdr, readp[u++]);
6882 0 : hdr = "";
6883 : }
6884 : }
6885 :
6886 4513 : readp += augmentationlen;
6887 : }
6888 : }
6889 :
6890 : /* Handle the initialization instructions. */
6891 4629 : if (ptr_size != 4 && ptr_size !=8)
6892 : printf ("invalid CIE pointer size (%u), must be 4 or 8.\n", ptr_size);
6893 : else
6894 4629 : print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
6895 : data_alignment_factor, version, ptr_size,
6896 : fde_encoding, dwflmod, ebl, dbg);
6897 4629 : readp = cieend;
6898 : }
6899 : }
6900 :
6901 :
6902 : /* Returns the signedness (or false if it cannot be determined) and
6903 : the byte size (or zero if it cannot be gotten) of the given DIE
6904 : DW_AT_type attribute. Uses dwarf_peel_type and dwarf_aggregate_size. */
6905 : static void
6906 100273 : die_type_sign_bytes (Dwarf_Die *die, bool *is_signed, int *bytes)
6907 : {
6908 : Dwarf_Attribute attr;
6909 : Dwarf_Die type;
6910 :
6911 100273 : *bytes = 0;
6912 100273 : *is_signed = false;
6913 :
6914 100273 : if (dwarf_peel_type (dwarf_formref_die (dwarf_attr_integrate (die,
6915 : DW_AT_type,
6916 : &attr), &type),
6917 : &type) == 0)
6918 : {
6919 : Dwarf_Word val;
6920 414 : *is_signed = (dwarf_formudata (dwarf_attr (&type, DW_AT_encoding,
6921 : &attr), &val) == 0
6922 207 : && (val == DW_ATE_signed || val == DW_ATE_signed_char));
6923 :
6924 207 : if (dwarf_aggregate_size (&type, &val) == 0)
6925 207 : *bytes = val;
6926 : }
6927 100273 : }
6928 :
6929 : struct attrcb_args
6930 : {
6931 : Dwfl_Module *dwflmod;
6932 : Dwarf *dbg;
6933 : Dwarf_Die *die;
6934 : int level;
6935 : bool silent;
6936 : bool is_split;
6937 : unsigned int version;
6938 : unsigned int addrsize;
6939 : unsigned int offset_size;
6940 : struct Dwarf_CU *cu;
6941 : };
6942 :
6943 :
6944 : static int
6945 2491242 : attr_callback (Dwarf_Attribute *attrp, void *arg)
6946 : {
6947 2491242 : struct attrcb_args *cbargs = (struct attrcb_args *) arg;
6948 2491242 : const int level = cbargs->level;
6949 2491242 : Dwarf_Die *die = cbargs->die;
6950 2491242 : bool is_split = cbargs->is_split;
6951 :
6952 2491242 : unsigned int attr = dwarf_whatattr (attrp);
6953 2491242 : if (unlikely (attr == 0))
6954 : {
6955 0 : if (!cbargs->silent)
6956 0 : error (0, 0, gettext ("DIE [%" PRIx64 "] "
6957 : "cannot get attribute code: %s"),
6958 : dwarf_dieoffset (die), dwarf_errmsg (-1));
6959 : return DWARF_CB_ABORT;
6960 : }
6961 :
6962 2491242 : unsigned int form = dwarf_whatform (attrp);
6963 2491242 : if (unlikely (form == 0))
6964 : {
6965 0 : if (!cbargs->silent)
6966 0 : error (0, 0, gettext ("DIE [%" PRIx64 "] "
6967 : "cannot get attribute form: %s"),
6968 : dwarf_dieoffset (die), dwarf_errmsg (-1));
6969 : return DWARF_CB_ABORT;
6970 : }
6971 :
6972 2491242 : switch (form)
6973 : {
6974 39520 : case DW_FORM_addr:
6975 : case DW_FORM_addrx:
6976 : case DW_FORM_addrx1:
6977 : case DW_FORM_addrx2:
6978 : case DW_FORM_addrx3:
6979 : case DW_FORM_addrx4:
6980 : case DW_FORM_GNU_addr_index:
6981 39520 : if (!cbargs->silent)
6982 : {
6983 : Dwarf_Addr addr;
6984 39251 : if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
6985 : {
6986 0 : attrval_out:
6987 0 : if (!cbargs->silent)
6988 0 : error (0, 0, gettext ("DIE [%" PRIx64 "] "
6989 : "cannot get attribute '%s' (%s) value: "
6990 : "%s"),
6991 : dwarf_dieoffset (die),
6992 : dwarf_attr_name (attr),
6993 : dwarf_form_name (form),
6994 : dwarf_errmsg (-1));
6995 : /* Don't ABORT, it might be other attributes can be resolved. */
6996 0 : return DWARF_CB_OK;
6997 : }
6998 39251 : if (form != DW_FORM_addr )
6999 : {
7000 : Dwarf_Word word;
7001 8 : if (dwarf_formudata (attrp, &word) != 0)
7002 : goto attrval_out;
7003 16 : printf (" %*s%-20s (%s) [%" PRIx64 "] ",
7004 : (int) (level * 2), "", dwarf_attr_name (attr),
7005 : dwarf_form_name (form), word);
7006 : }
7007 : else
7008 39243 : printf (" %*s%-20s (%s) ",
7009 : (int) (level * 2), "", dwarf_attr_name (attr),
7010 : dwarf_form_name (form));
7011 39251 : print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr, addr);
7012 39251 : printf ("\n");
7013 : }
7014 2233489 : break;
7015 :
7016 463440 : case DW_FORM_indirect:
7017 : case DW_FORM_strp:
7018 : case DW_FORM_line_strp:
7019 : case DW_FORM_strx:
7020 : case DW_FORM_strx1:
7021 : case DW_FORM_strx2:
7022 : case DW_FORM_strx3:
7023 : case DW_FORM_strx4:
7024 : case DW_FORM_string:
7025 : case DW_FORM_GNU_strp_alt:
7026 : case DW_FORM_GNU_str_index:
7027 463440 : if (cbargs->silent)
7028 : break;
7029 462692 : const char *str = dwarf_formstring (attrp);
7030 462692 : if (unlikely (str == NULL))
7031 : goto attrval_out;
7032 462692 : printf (" %*s%-20s (%s) \"%s\"\n",
7033 : (int) (level * 2), "", dwarf_attr_name (attr),
7034 : dwarf_form_name (form), str);
7035 : break;
7036 :
7037 593335 : case DW_FORM_ref_addr:
7038 : case DW_FORM_ref_udata:
7039 : case DW_FORM_ref8:
7040 : case DW_FORM_ref4:
7041 : case DW_FORM_ref2:
7042 : case DW_FORM_ref1:
7043 : case DW_FORM_GNU_ref_alt:
7044 : case DW_FORM_ref_sup4:
7045 : case DW_FORM_ref_sup8:
7046 593335 : if (cbargs->silent)
7047 : break;
7048 : Dwarf_Die ref;
7049 592548 : if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
7050 : goto attrval_out;
7051 :
7052 1185096 : printf (" %*s%-20s (%s) ",
7053 : (int) (level * 2), "", dwarf_attr_name (attr),
7054 : dwarf_form_name (form));
7055 592548 : if (is_split)
7056 33 : printf ("{%6" PRIxMAX "}\n", (uintmax_t) dwarf_dieoffset (&ref));
7057 : else
7058 592515 : printf ("[%6" PRIxMAX "]\n", (uintmax_t) dwarf_dieoffset (&ref));
7059 : break;
7060 :
7061 4 : case DW_FORM_ref_sig8:
7062 4 : if (cbargs->silent)
7063 : break;
7064 8 : printf (" %*s%-20s (%s) {%6" PRIx64 "}\n",
7065 : (int) (level * 2), "", dwarf_attr_name (attr),
7066 : dwarf_form_name (form),
7067 8 : (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
7068 : break;
7069 :
7070 1239637 : case DW_FORM_sec_offset:
7071 : case DW_FORM_rnglistx:
7072 : case DW_FORM_loclistx:
7073 : case DW_FORM_implicit_const:
7074 : case DW_FORM_udata:
7075 : case DW_FORM_sdata:
7076 : case DW_FORM_data8: /* Note no data16 here, we see that as block. */
7077 : case DW_FORM_data4:
7078 : case DW_FORM_data2:
7079 : case DW_FORM_data1:;
7080 : Dwarf_Word num;
7081 1239637 : if (unlikely (dwarf_formudata (attrp, &num) != 0))
7082 : goto attrval_out;
7083 :
7084 1239637 : const char *valuestr = NULL;
7085 1239637 : bool as_hex_id = false;
7086 1239637 : switch (attr)
7087 : {
7088 : /* This case can take either a constant or a loclistptr. */
7089 205083 : case DW_AT_data_member_location:
7090 205083 : if (form != DW_FORM_sec_offset
7091 205083 : && (cbargs->version >= 4
7092 23806 : || (form != DW_FORM_data4 && form != DW_FORM_data8)))
7093 : {
7094 205083 : if (!cbargs->silent)
7095 205083 : printf (" %*s%-20s (%s) %" PRIxMAX "\n",
7096 : (int) (level * 2), "", dwarf_attr_name (attr),
7097 : dwarf_form_name (form), (uintmax_t) num);
7098 : return DWARF_CB_OK;
7099 : }
7100 : FALLTHROUGH;
7101 :
7102 : /* These cases always take a loclist[ptr] and no constant. */
7103 : case DW_AT_location:
7104 : case DW_AT_data_location:
7105 : case DW_AT_vtable_elem_location:
7106 : case DW_AT_string_length:
7107 : case DW_AT_use_location:
7108 : case DW_AT_frame_base:
7109 : case DW_AT_return_addr:
7110 : case DW_AT_static_link:
7111 : case DW_AT_segment:
7112 : case DW_AT_GNU_call_site_value:
7113 : case DW_AT_GNU_call_site_data_value:
7114 : case DW_AT_GNU_call_site_target:
7115 : case DW_AT_GNU_call_site_target_clobbered:
7116 : case DW_AT_GNU_locviews:
7117 : {
7118 : bool nlpt;
7119 41625 : if (cbargs->cu->version < 5)
7120 : {
7121 41554 : if (! cbargs->is_split)
7122 : {
7123 124602 : nlpt = notice_listptr (section_loc, &known_locsptr,
7124 41534 : cbargs->addrsize,
7125 41534 : cbargs->offset_size,
7126 : cbargs->cu, num, attr);
7127 : }
7128 : else
7129 : nlpt = true;
7130 : }
7131 : else
7132 : {
7133 : /* Only register for a real section offset. Otherwise
7134 : it is a DW_FORM_loclistx which is just an index
7135 : number and we should already have registered the
7136 : section offset for the index when we saw the
7137 : DW_AT_loclists_base CU attribute. */
7138 71 : if (form == DW_FORM_sec_offset)
7139 96 : nlpt = notice_listptr (section_loc, &known_loclistsptr,
7140 64 : cbargs->addrsize, cbargs->offset_size,
7141 : cbargs->cu, num, attr);
7142 : else
7143 : nlpt = true;
7144 :
7145 : }
7146 :
7147 41625 : if (!cbargs->silent)
7148 : {
7149 41444 : if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
7150 41437 : printf (" %*s%-20s (%s) location list [%6"
7151 : PRIxMAX "]%s\n",
7152 : (int) (level * 2), "", dwarf_attr_name (attr),
7153 : dwarf_form_name (form), (uintmax_t) num,
7154 : nlpt ? "" : " <WARNING offset too big>");
7155 : else
7156 7 : printf (" %*s%-20s (%s) location index [%6"
7157 : PRIxMAX "]\n",
7158 : (int) (level * 2), "", dwarf_attr_name (attr),
7159 : dwarf_form_name (form), (uintmax_t) num);
7160 : }
7161 : }
7162 : return DWARF_CB_OK;
7163 :
7164 5 : case DW_AT_loclists_base:
7165 4 : {
7166 15 : bool nlpt = notice_listptr (section_loc, &known_loclistsptr,
7167 10 : cbargs->addrsize, cbargs->offset_size,
7168 : cbargs->cu, num, attr);
7169 :
7170 5 : if (!cbargs->silent)
7171 1 : printf (" %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n",
7172 : (int) (level * 2), "", dwarf_attr_name (attr),
7173 : dwarf_form_name (form), (uintmax_t) num,
7174 : nlpt ? "" : " <WARNING offset too big>");
7175 : }
7176 : return DWARF_CB_OK;
7177 :
7178 11023 : case DW_AT_ranges:
7179 : case DW_AT_start_scope:
7180 : {
7181 : bool nlpt;
7182 11023 : if (cbargs->cu->version < 5)
7183 33021 : nlpt = notice_listptr (section_ranges, &known_rangelistptr,
7184 22014 : cbargs->addrsize, cbargs->offset_size,
7185 : cbargs->cu, num, attr);
7186 : else
7187 : {
7188 : /* Only register for a real section offset. Otherwise
7189 : it is a DW_FORM_rangelistx which is just an index
7190 : number and we should already have registered the
7191 : section offset for the index when we saw the
7192 : DW_AT_rnglists_base CU attribute. */
7193 16 : if (form == DW_FORM_sec_offset)
7194 30 : nlpt = notice_listptr (section_ranges, &known_rnglistptr,
7195 20 : cbargs->addrsize, cbargs->offset_size,
7196 : cbargs->cu, num, attr);
7197 : else
7198 : nlpt = true;
7199 : }
7200 :
7201 11023 : if (!cbargs->silent)
7202 : {
7203 10981 : if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
7204 10979 : printf (" %*s%-20s (%s) range list [%6"
7205 : PRIxMAX "]%s\n",
7206 : (int) (level * 2), "", dwarf_attr_name (attr),
7207 : dwarf_form_name (form), (uintmax_t) num,
7208 : nlpt ? "" : " <WARNING offset too big>");
7209 : else
7210 2 : printf (" %*s%-20s (%s) range index [%6"
7211 : PRIxMAX "]\n",
7212 : (int) (level * 2), "", dwarf_attr_name (attr),
7213 : dwarf_form_name (form), (uintmax_t) num);
7214 : }
7215 : }
7216 : return DWARF_CB_OK;
7217 :
7218 4 : case DW_AT_rnglists_base:
7219 2 : {
7220 12 : bool nlpt = notice_listptr (section_ranges, &known_rnglistptr,
7221 8 : cbargs->addrsize, cbargs->offset_size,
7222 : cbargs->cu, num, attr);
7223 4 : if (!cbargs->silent)
7224 2 : printf (" %*s%-20s (%s) range list [%6"
7225 : PRIxMAX "]%s\n",
7226 : (int) (level * 2), "", dwarf_attr_name (attr),
7227 : dwarf_form_name (form), (uintmax_t) num,
7228 : nlpt ? "" : " <WARNING offset too big>");
7229 : }
7230 : return DWARF_CB_OK;
7231 :
7232 13 : case DW_AT_addr_base:
7233 : case DW_AT_GNU_addr_base:
7234 8 : {
7235 39 : bool addrbase = notice_listptr (section_addr, &known_addrbases,
7236 13 : cbargs->addrsize,
7237 13 : cbargs->offset_size,
7238 : cbargs->cu, num, attr);
7239 13 : if (!cbargs->silent)
7240 5 : printf (" %*s%-20s (%s) address base [%6"
7241 : PRIxMAX "]%s\n",
7242 : (int) (level * 2), "", dwarf_attr_name (attr),
7243 : dwarf_form_name (form), (uintmax_t) num,
7244 : addrbase ? "" : " <WARNING offset too big>");
7245 : }
7246 : return DWARF_CB_OK;
7247 :
7248 0 : case DW_AT_str_offsets_base:
7249 0 : {
7250 0 : bool stroffbase = notice_listptr (section_str, &known_stroffbases,
7251 0 : cbargs->addrsize,
7252 0 : cbargs->offset_size,
7253 : cbargs->cu, num, attr);
7254 0 : if (!cbargs->silent)
7255 0 : printf (" %*s%-20s (%s) str offsets base [%6"
7256 : PRIxMAX "]%s\n",
7257 : (int) (level * 2), "", dwarf_attr_name (attr),
7258 : dwarf_form_name (form), (uintmax_t) num,
7259 : stroffbase ? "" : " <WARNING offset too big>");
7260 : }
7261 : return DWARF_CB_OK;
7262 :
7263 1152 : case DW_AT_language:
7264 1152 : valuestr = dwarf_lang_name (num);
7265 1152 : break;
7266 16426 : case DW_AT_encoding:
7267 32852 : valuestr = dwarf_encoding_name (num);
7268 16426 : break;
7269 0 : case DW_AT_accessibility:
7270 0 : valuestr = dwarf_access_name (num);
7271 0 : break;
7272 0 : case DW_AT_defaulted:
7273 0 : valuestr = dwarf_defaulted_name (num);
7274 0 : break;
7275 0 : case DW_AT_visibility:
7276 0 : valuestr = dwarf_visibility_name (num);
7277 0 : break;
7278 0 : case DW_AT_virtuality:
7279 0 : valuestr = dwarf_virtuality_name (num);
7280 0 : break;
7281 0 : case DW_AT_identifier_case:
7282 0 : valuestr = dwarf_identifier_case_name (num);
7283 0 : break;
7284 0 : case DW_AT_calling_convention:
7285 0 : valuestr = dwarf_calling_convention_name (num);
7286 0 : break;
7287 2927 : case DW_AT_inline:
7288 5854 : valuestr = dwarf_inline_name (num);
7289 2927 : break;
7290 0 : case DW_AT_ordering:
7291 0 : valuestr = dwarf_ordering_name (num);
7292 0 : break;
7293 0 : case DW_AT_discr_list:
7294 0 : valuestr = dwarf_discr_list_name (num);
7295 0 : break;
7296 363012 : case DW_AT_decl_file:
7297 : case DW_AT_call_file:
7298 363012 : {
7299 363012 : if (cbargs->silent)
7300 : break;
7301 :
7302 : /* Try to get the actual file, the current interface only
7303 : gives us full paths, but we only want to show the file
7304 : name for now. */
7305 : Dwarf_Die cudie;
7306 362591 : if (dwarf_cu_die (cbargs->cu, &cudie,
7307 : NULL, NULL, NULL, NULL, NULL, NULL) != NULL)
7308 : {
7309 : Dwarf_Files *files;
7310 : size_t nfiles;
7311 362591 : if (dwarf_getsrcfiles (&cudie, &files, &nfiles) == 0)
7312 : {
7313 362591 : valuestr = dwarf_filesrc (files, num, NULL, NULL);
7314 362591 : if (valuestr != NULL)
7315 : {
7316 362591 : char *filename = strrchr (valuestr, '/');
7317 362591 : if (filename != NULL)
7318 362591 : valuestr = filename + 1;
7319 : }
7320 : else
7321 0 : error (0, 0, gettext ("invalid file (%" PRId64 "): %s"),
7322 : num, dwarf_errmsg (-1));
7323 : }
7324 : else
7325 0 : error (0, 0, gettext ("no srcfiles for CU [%" PRIx64 "]"),
7326 : dwarf_dieoffset (&cudie));
7327 : }
7328 : else
7329 0 : error (0, 0, gettext ("couldn't get DWARF CU: %s"),
7330 : dwarf_errmsg (-1));
7331 362591 : if (valuestr == NULL)
7332 : valuestr = "???";
7333 : }
7334 362591 : break;
7335 13 : case DW_AT_GNU_dwo_id:
7336 13 : as_hex_id = true;
7337 13 : break;
7338 :
7339 : default:
7340 : /* Nothing. */
7341 : break;
7342 : }
7343 :
7344 981884 : if (cbargs->silent)
7345 : break;
7346 :
7347 : /* When highpc is in constant form it is relative to lowpc.
7348 : In that case also show the address. */
7349 : Dwarf_Addr highpc;
7350 980043 : if (attr == DW_AT_high_pc && dwarf_highpc (cbargs->die, &highpc) == 0)
7351 : {
7352 27334 : printf (" %*s%-20s (%s) %" PRIuMAX " (",
7353 : (int) (level * 2), "", dwarf_attr_name (attr),
7354 : dwarf_form_name (form), (uintmax_t) num);
7355 13667 : print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, highpc, highpc);
7356 : printf (")\n");
7357 : }
7358 : else
7359 : {
7360 966376 : if (as_hex_id)
7361 : {
7362 2 : printf (" %*s%-20s (%s) 0x%.16" PRIx64 "\n",
7363 : (int) (level * 2), "", dwarf_attr_name (attr),
7364 : dwarf_form_name (form), num);
7365 : }
7366 : else
7367 966374 : {
7368 966374 : Dwarf_Sword snum = 0;
7369 : bool is_signed;
7370 966374 : int bytes = 0;
7371 966374 : if (attr == DW_AT_const_value)
7372 100273 : die_type_sign_bytes (cbargs->die, &is_signed, &bytes);
7373 : else
7374 1732202 : is_signed = (form == DW_FORM_sdata
7375 866101 : || form == DW_FORM_implicit_const);
7376 :
7377 966374 : if (is_signed)
7378 144 : if (unlikely (dwarf_formsdata (attrp, &snum) != 0))
7379 : goto attrval_out;
7380 :
7381 966374 : if (valuestr == NULL)
7382 : {
7383 583581 : printf (" %*s%-20s (%s) ",
7384 : (int) (level * 2), "", dwarf_attr_name (attr),
7385 : dwarf_form_name (form));
7386 : }
7387 : else
7388 : {
7389 382793 : printf (" %*s%-20s (%s) %s (",
7390 : (int) (level * 2), "", dwarf_attr_name (attr),
7391 : dwarf_form_name (form), valuestr);
7392 : }
7393 :
7394 966374 : switch (bytes)
7395 : {
7396 2 : case 1:
7397 2 : if (is_signed)
7398 1 : printf ("%" PRId8, (int8_t) snum);
7399 : else
7400 1 : printf ("%" PRIu8, (uint8_t) num);
7401 : break;
7402 :
7403 2 : case 2:
7404 2 : if (is_signed)
7405 1 : printf ("%" PRId16, (int16_t) snum);
7406 : else
7407 1 : printf ("%" PRIu16, (uint16_t) num);
7408 : break;
7409 :
7410 123 : case 4:
7411 123 : if (is_signed)
7412 120 : printf ("%" PRId32, (int32_t) snum);
7413 : else
7414 3 : printf ("%" PRIu32, (uint32_t) num);
7415 : break;
7416 :
7417 80 : case 8:
7418 80 : if (is_signed)
7419 1 : printf ("%" PRId64, (int64_t) snum);
7420 : else
7421 79 : printf ("%" PRIu64, (uint64_t) num);
7422 : break;
7423 :
7424 966167 : default:
7425 966167 : if (is_signed)
7426 21 : printf ("%" PRIdMAX, (intmax_t) snum);
7427 : else
7428 966146 : printf ("%" PRIuMAX, (uintmax_t) num);
7429 : break;
7430 : }
7431 :
7432 : /* Make clear if we switched from a signed encoding to
7433 : an unsigned value. */
7434 966374 : if (attr == DW_AT_const_value
7435 100273 : && (form == DW_FORM_sdata || form == DW_FORM_implicit_const)
7436 1227 : && !is_signed)
7437 1219 : printf (" (%" PRIdMAX ")", (intmax_t) num);
7438 :
7439 966374 : if (valuestr == NULL)
7440 : printf ("\n");
7441 : else
7442 : printf (")\n");
7443 : }
7444 : }
7445 : break;
7446 :
7447 9122 : case DW_FORM_flag:
7448 9122 : if (cbargs->silent)
7449 : break;
7450 : bool flag;
7451 9048 : if (unlikely (dwarf_formflag (attrp, &flag) != 0))
7452 : goto attrval_out;
7453 :
7454 9048 : printf (" %*s%-20s (%s) %s\n",
7455 : (int) (level * 2), "", dwarf_attr_name (attr),
7456 9048 : dwarf_form_name (form), flag ? yes_str : no_str);
7457 : break;
7458 :
7459 63246 : case DW_FORM_flag_present:
7460 63246 : if (cbargs->silent)
7461 : break;
7462 62972 : printf (" %*s%-20s (%s) %s\n",
7463 : (int) (level * 2), "", dwarf_attr_name (attr),
7464 : dwarf_form_name (form), yes_str);
7465 : break;
7466 :
7467 82938 : case DW_FORM_exprloc:
7468 : case DW_FORM_block4:
7469 : case DW_FORM_block2:
7470 : case DW_FORM_block1:
7471 : case DW_FORM_block:
7472 : case DW_FORM_data16: /* DWARF5 calls this a constant class. */
7473 82938 : if (cbargs->silent)
7474 : break;
7475 : Dwarf_Block block;
7476 82809 : if (unlikely (dwarf_formblock (attrp, &block) != 0))
7477 : goto attrval_out;
7478 :
7479 165618 : printf (" %*s%-20s (%s) ",
7480 : (int) (level * 2), "", dwarf_attr_name (attr),
7481 : dwarf_form_name (form));
7482 :
7483 82809 : switch (attr)
7484 : {
7485 16 : default:
7486 16 : if (form != DW_FORM_exprloc)
7487 : {
7488 16 : print_block (block.length, block.data);
7489 16 : break;
7490 : }
7491 : FALLTHROUGH;
7492 :
7493 : case DW_AT_location:
7494 : case DW_AT_data_location:
7495 : case DW_AT_data_member_location:
7496 : case DW_AT_vtable_elem_location:
7497 : case DW_AT_string_length:
7498 : case DW_AT_use_location:
7499 : case DW_AT_frame_base:
7500 : case DW_AT_return_addr:
7501 : case DW_AT_static_link:
7502 : case DW_AT_allocated:
7503 : case DW_AT_associated:
7504 : case DW_AT_bit_size:
7505 : case DW_AT_bit_offset:
7506 : case DW_AT_bit_stride:
7507 : case DW_AT_byte_size:
7508 : case DW_AT_byte_stride:
7509 : case DW_AT_count:
7510 : case DW_AT_lower_bound:
7511 : case DW_AT_upper_bound:
7512 : case DW_AT_GNU_call_site_value:
7513 : case DW_AT_GNU_call_site_data_value:
7514 : case DW_AT_GNU_call_site_target:
7515 : case DW_AT_GNU_call_site_target_clobbered:
7516 82793 : if (form != DW_FORM_data16)
7517 : {
7518 82793 : putchar ('\n');
7519 165586 : print_ops (cbargs->dwflmod, cbargs->dbg,
7520 82793 : 12 + level * 2, 12 + level * 2,
7521 : cbargs->version, cbargs->addrsize, cbargs->offset_size,
7522 82793 : attrp->cu, block.length, block.data);
7523 : }
7524 : else
7525 0 : print_block (block.length, block.data);
7526 : break;
7527 : }
7528 : break;
7529 :
7530 0 : default:
7531 0 : if (cbargs->silent)
7532 : break;
7533 0 : printf (" %*s%-20s (%s) ???\n",
7534 : (int) (level * 2), "", dwarf_attr_name (attr),
7535 : dwarf_form_name (form));
7536 : break;
7537 : }
7538 :
7539 2233489 : return DWARF_CB_OK;
7540 : }
7541 :
7542 : static void
7543 95 : print_debug_units (Dwfl_Module *dwflmod,
7544 : Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
7545 : Elf_Scn *scn, GElf_Shdr *shdr,
7546 : Dwarf *dbg, bool debug_types)
7547 : {
7548 95 : const bool silent = !(print_debug_sections & section_info) && !debug_types;
7549 95 : const char *secname = section_name (ebl, shdr);
7550 :
7551 95 : if (!silent)
7552 60 : printf (gettext ("\
7553 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
7554 60 : elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
7555 :
7556 : /* If the section is empty we don't have to do anything. */
7557 95 : if (!silent && shdr->sh_size == 0)
7558 0 : return;
7559 :
7560 95 : int maxdies = 20;
7561 95 : Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
7562 :
7563 : /* New compilation unit. */
7564 : Dwarf_Half version;
7565 :
7566 : Dwarf_Die result;
7567 : Dwarf_Off abbroffset;
7568 : uint8_t addrsize;
7569 : uint8_t offsize;
7570 : uint64_t unit_id;
7571 : Dwarf_Off subdie_off;
7572 :
7573 : int unit_res;
7574 : Dwarf_CU *cu;
7575 : Dwarf_CU cu_mem;
7576 : uint8_t unit_type;
7577 : Dwarf_Die cudie;
7578 :
7579 : /* We cheat a little because we want to see only the CUs from .debug_info
7580 : or .debug_types. We know the Dwarf_CU struct layout. Set it up at
7581 : the end of .debug_info if we want .debug_types only. Check the returned
7582 : Dwarf_CU is still in the expected section. */
7583 95 : if (debug_types)
7584 : {
7585 1 : cu_mem.dbg = dbg;
7586 1 : cu_mem.end = dbg->sectiondata[IDX_debug_info]->d_size;
7587 1 : cu_mem.sec_idx = IDX_debug_info;
7588 1 : cu = &cu_mem;
7589 : }
7590 : else
7591 94 : cu = NULL;
7592 :
7593 : next_cu:
7594 1256 : unit_res = dwarf_get_units (dbg, cu, &cu, &version, &unit_type,
7595 : &cudie, NULL);
7596 1256 : if (unit_res == 1)
7597 : goto do_return;
7598 :
7599 1162 : if (unit_res == -1)
7600 : {
7601 0 : if (!silent)
7602 0 : error (0, 0, gettext ("cannot get next unit: %s"), dwarf_errmsg (-1));
7603 : goto do_return;
7604 : }
7605 :
7606 1162 : if (cu->sec_idx != (size_t) (debug_types ? IDX_debug_types : IDX_debug_info))
7607 : goto do_return;
7608 :
7609 1161 : dwarf_cu_die (cu, &result, NULL, &abbroffset, &addrsize, &offsize,
7610 : &unit_id, &subdie_off);
7611 :
7612 1161 : if (!silent)
7613 : {
7614 1112 : Dwarf_Off offset = cu->start;
7615 1112 : if (debug_types && version < 5)
7616 2 : {
7617 : Dwarf_Die typedie;
7618 : Dwarf_Off dieoffset;
7619 2 : dieoffset = dwarf_dieoffset (dwarf_offdie_types (dbg, subdie_off,
7620 : &typedie));
7621 4 : printf (gettext (" Type unit at offset %" PRIu64 ":\n"
7622 : " Version: %" PRIu16
7623 : ", Abbreviation section offset: %" PRIu64
7624 : ", Address size: %" PRIu8
7625 : ", Offset size: %" PRIu8
7626 : "\n Type signature: %#" PRIx64
7627 : ", Type offset: %#" PRIx64 " [%" PRIx64 "]\n"),
7628 : (uint64_t) offset, version, abbroffset, addrsize, offsize,
7629 : unit_id, (uint64_t) subdie_off, dieoffset);
7630 : }
7631 : else
7632 : {
7633 2220 : printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
7634 : " Version: %" PRIu16
7635 : ", Abbreviation section offset: %" PRIu64
7636 : ", Address size: %" PRIu8
7637 : ", Offset size: %" PRIu8 "\n"),
7638 : (uint64_t) offset, version, abbroffset, addrsize, offsize);
7639 :
7640 2215 : if (version >= 5 || (unit_type != DW_UT_compile
7641 1105 : && unit_type != DW_UT_partial))
7642 : {
7643 12 : printf (gettext (" Unit type: %s (%" PRIu8 ")"),
7644 : dwarf_unit_name (unit_type), unit_type);
7645 6 : if (unit_type == DW_UT_type
7646 6 : || unit_type == DW_UT_skeleton
7647 1 : || unit_type == DW_UT_split_compile
7648 1 : || unit_type == DW_UT_split_type)
7649 5 : printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
7650 6 : if (unit_type == DW_UT_type
7651 6 : || unit_type == DW_UT_split_type)
7652 : {
7653 : Dwarf_Die typedie;
7654 : Dwarf_Off dieoffset;
7655 0 : dwarf_cu_info (cu, NULL, NULL, NULL, &typedie,
7656 : NULL, NULL, NULL);
7657 0 : dieoffset = dwarf_dieoffset (&typedie);
7658 0 : printf (", Unit DIE off: %#" PRIx64 " [%" PRIx64 "]",
7659 : subdie_off, dieoffset);
7660 : }
7661 : printf ("\n");
7662 : }
7663 : }
7664 : }
7665 :
7666 1161 : if (version < 2 || version > 5
7667 1161 : || unit_type < DW_UT_compile || unit_type > DW_UT_split_type)
7668 : {
7669 0 : if (!silent)
7670 0 : error (0, 0, gettext ("unknown version (%d) or unit type (%d)"),
7671 : version, unit_type);
7672 : goto next_cu;
7673 : }
7674 :
7675 1161 : struct attrcb_args args =
7676 : {
7677 : .dwflmod = dwflmod,
7678 : .silent = silent,
7679 : .version = version,
7680 : .addrsize = addrsize,
7681 : .offset_size = offsize
7682 : };
7683 :
7684 1161 : bool is_split = false;
7685 1161 : int level = 0;
7686 1161 : dies[0] = cudie;
7687 1161 : args.cu = dies[0].cu;
7688 1161 : args.dbg = dbg;
7689 : args.is_split = is_split;
7690 :
7691 : /* We might return here again for the split CU subdie. */
7692 714773 : do_cu:
7693 : do
7694 : {
7695 715938 : Dwarf_Off offset = dwarf_dieoffset (&dies[level]);
7696 715938 : if (unlikely (offset == (Dwarf_Off) -1))
7697 : {
7698 0 : if (!silent)
7699 0 : error (0, 0, gettext ("cannot get DIE offset: %s"),
7700 : dwarf_errmsg (-1));
7701 : goto do_return;
7702 : }
7703 :
7704 715938 : int tag = dwarf_tag (&dies[level]);
7705 715938 : if (unlikely (tag == DW_TAG_invalid))
7706 : {
7707 0 : if (!silent)
7708 0 : error (0, 0, gettext ("cannot get tag of DIE at offset [%" PRIx64
7709 : "] in section '%s': %s"),
7710 : (uint64_t) offset, secname, dwarf_errmsg (-1));
7711 : goto do_return;
7712 : }
7713 :
7714 715938 : if (!silent)
7715 : {
7716 714950 : unsigned int code = dwarf_getabbrevcode (dies[level].abbrev);
7717 714950 : if (is_split)
7718 : printf (" {%6" PRIx64 "} ", (uint64_t) offset);
7719 : else
7720 : printf (" [%6" PRIx64 "] ", (uint64_t) offset);
7721 714950 : printf ("%*s%-20s abbrev: %u\n", (int) (level * 2), "",
7722 : dwarf_tag_name (tag), code);
7723 : }
7724 :
7725 : /* Print the attribute values. */
7726 715938 : args.level = level;
7727 715938 : args.die = &dies[level];
7728 715938 : (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
7729 :
7730 : /* Make room for the next level's DIE. */
7731 715938 : if (level + 1 == maxdies)
7732 0 : dies = (Dwarf_Die *) xrealloc (dies,
7733 0 : (maxdies += 10)
7734 : * sizeof (Dwarf_Die));
7735 :
7736 715938 : int res = dwarf_child (&dies[level], &dies[level + 1]);
7737 715938 : if (res > 0)
7738 : {
7739 715938 : while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
7740 101554 : if (level-- == 0)
7741 : break;
7742 :
7743 615549 : if (unlikely (res == -1))
7744 : {
7745 0 : if (!silent)
7746 0 : error (0, 0, gettext ("cannot get next DIE: %s\n"),
7747 : dwarf_errmsg (-1));
7748 : goto do_return;
7749 : }
7750 : }
7751 100389 : else if (unlikely (res < 0))
7752 : {
7753 0 : if (!silent)
7754 0 : error (0, 0, gettext ("cannot get next DIE: %s"),
7755 : dwarf_errmsg (-1));
7756 : goto do_return;
7757 : }
7758 : else
7759 : ++level;
7760 : }
7761 715938 : while (level >= 0);
7762 :
7763 : /* We might want to show the split compile unit if this was a skeleton.
7764 : We need to scan it if we are requesting printing .debug_ranges for
7765 : DWARF4 since GNU DebugFission uses "offsets" into the main ranges
7766 : section. */
7767 1165 : if (unit_type == DW_UT_skeleton
7768 13 : && ((!silent && show_split_units)
7769 10 : || (version < 5 && (print_debug_sections & section_ranges) != 0)))
7770 : {
7771 : Dwarf_Die subdie;
7772 5 : if (dwarf_cu_info (cu, NULL, NULL, NULL, &subdie, NULL, NULL, NULL) != 0
7773 5 : || dwarf_tag (&subdie) == DW_TAG_invalid)
7774 : {
7775 1 : if (!silent)
7776 : {
7777 : Dwarf_Attribute dwo_at;
7778 1 : const char *dwo_name =
7779 1 : (dwarf_formstring (dwarf_attr (&cudie, DW_AT_dwo_name,
7780 : &dwo_at))
7781 1 : ?: (dwarf_formstring (dwarf_attr (&cudie, DW_AT_GNU_dwo_name,
7782 : &dwo_at))
7783 0 : ?: "<unknown>"));
7784 2 : fprintf (stderr,
7785 : "Could not find split unit '%s', id: %" PRIx64 "\n",
7786 : dwo_name, unit_id);
7787 : }
7788 : }
7789 : else
7790 : {
7791 4 : Dwarf_CU *split_cu = subdie.cu;
7792 4 : dwarf_cu_die (split_cu, &result, NULL, &abbroffset,
7793 : &addrsize, &offsize, &unit_id, &subdie_off);
7794 4 : Dwarf_Off offset = cu->start;
7795 :
7796 4 : if (!silent)
7797 : {
7798 4 : printf (gettext (" Split compilation unit at offset %"
7799 : PRIu64 ":\n"
7800 : " Version: %" PRIu16
7801 : ", Abbreviation section offset: %" PRIu64
7802 : ", Address size: %" PRIu8
7803 : ", Offset size: %" PRIu8 "\n"),
7804 : (uint64_t) offset, version, abbroffset,
7805 : addrsize, offsize);
7806 4 : printf (gettext (" Unit type: %s (%" PRIu8 ")"),
7807 : dwarf_unit_name (unit_type), unit_type);
7808 4 : printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
7809 : printf ("\n");
7810 : }
7811 :
7812 4 : unit_type = DW_UT_split_compile;
7813 4 : is_split = true;
7814 4 : level = 0;
7815 4 : dies[0] = subdie;
7816 4 : args.cu = dies[0].cu;
7817 4 : args.dbg = split_cu->dbg;
7818 4 : args.is_split = is_split;
7819 4 : goto do_cu;
7820 : }
7821 : }
7822 :
7823 : /* And again... */
7824 : goto next_cu;
7825 :
7826 95 : do_return:
7827 95 : free (dies);
7828 : }
7829 :
7830 : static void
7831 17 : print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
7832 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7833 : {
7834 94 : print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
7835 17 : }
7836 :
7837 : static void
7838 1 : print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
7839 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7840 : {
7841 1 : print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
7842 1 : }
7843 :
7844 :
7845 : static void
7846 4 : print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
7847 : GElf_Ehdr *ehdr __attribute__ ((unused)),
7848 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7849 : {
7850 8 : printf (gettext ("\
7851 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n\n"),
7852 : elf_ndxscn (scn), section_name (ebl, shdr),
7853 4 : (uint64_t) shdr->sh_offset);
7854 :
7855 4 : size_t address_size
7856 4 : = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
7857 :
7858 : Dwarf_Lines *lines;
7859 : size_t nlines;
7860 4 : Dwarf_Off off, next_off = 0;
7861 4 : Dwarf_CU *cu = NULL;
7862 12 : while (dwarf_next_lines (dbg, off = next_off, &next_off, &cu, NULL, NULL,
7863 : &lines, &nlines) == 0)
7864 : {
7865 : Dwarf_Die cudie;
7866 8 : if (cu != NULL && dwarf_cu_info (cu, NULL, NULL, &cudie,
7867 : NULL, NULL, NULL, NULL) == 0)
7868 6 : printf (" CU [%" PRIx64 "] %s\n",
7869 : dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
7870 : else
7871 : {
7872 : /* DWARF5 lines can be independent of any CU, but they probably
7873 : are used by some CU. Determine the CU this block is for. */
7874 : Dwarf_Off cuoffset;
7875 2 : Dwarf_Off ncuoffset = 0;
7876 : size_t hsize;
7877 3 : while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
7878 : NULL, NULL, NULL) == 0)
7879 : {
7880 3 : if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
7881 0 : continue;
7882 : Dwarf_Attribute stmt_list;
7883 3 : if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
7884 0 : continue;
7885 : Dwarf_Word lineoff;
7886 3 : if (dwarf_formudata (&stmt_list, &lineoff) != 0)
7887 0 : continue;
7888 3 : if (lineoff == off)
7889 : {
7890 : /* Found the CU. */
7891 2 : cu = cudie.cu;
7892 2 : break;
7893 : }
7894 : }
7895 :
7896 2 : if (cu != NULL)
7897 2 : printf (" CU [%" PRIx64 "] %s\n",
7898 : dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
7899 : else
7900 : printf (" No CU\n");
7901 : }
7902 :
7903 8 : printf (" line:col SBPE* disc isa op address"
7904 : " (Statement Block Prologue Epilogue *End)\n");
7905 8 : const char *last_file = "";
7906 168 : for (size_t n = 0; n < nlines; n++)
7907 : {
7908 160 : Dwarf_Line *line = dwarf_onesrcline (lines, n);
7909 160 : if (line == NULL)
7910 : {
7911 0 : printf (" dwarf_onesrcline: %s\n", dwarf_errmsg (-1));
7912 0 : continue;
7913 : }
7914 : Dwarf_Word mtime, length;
7915 160 : const char *file = dwarf_linesrc (line, &mtime, &length);
7916 160 : if (file == NULL)
7917 : {
7918 0 : printf (" <%s> (mtime: ?, length: ?)\n", dwarf_errmsg (-1));
7919 0 : last_file = "";
7920 : }
7921 160 : else if (strcmp (last_file, file) != 0)
7922 : {
7923 40 : printf (" %s (mtime: %" PRIu64 ", length: %" PRIu64 ")\n",
7924 : file, mtime, length);
7925 20 : last_file = file;
7926 : }
7927 :
7928 : int lineno, colno;
7929 : bool statement, endseq, block, prologue_end, epilogue_begin;
7930 : unsigned int lineop, isa, disc;
7931 : Dwarf_Addr address;
7932 160 : dwarf_lineaddr (line, &address);
7933 160 : dwarf_lineno (line, &lineno);
7934 160 : dwarf_linecol (line, &colno);
7935 160 : dwarf_lineop_index (line, &lineop);
7936 160 : dwarf_linebeginstatement (line, &statement);
7937 160 : dwarf_lineendsequence (line, &endseq);
7938 160 : dwarf_lineblock (line, &block);
7939 160 : dwarf_lineprologueend (line, &prologue_end);
7940 160 : dwarf_lineepiloguebegin (line, &epilogue_begin);
7941 160 : dwarf_lineisa (line, &isa);
7942 160 : dwarf_linediscriminator (line, &disc);
7943 :
7944 : /* End sequence is special, it is one byte past. */
7945 1120 : printf (" %4d:%-3d %c%c%c%c%c %4d %3d %2d ",
7946 : lineno, colno,
7947 160 : (statement ? 'S' : ' '),
7948 160 : (block ? 'B' : ' '),
7949 160 : (prologue_end ? 'P' : ' '),
7950 160 : (epilogue_begin ? 'E' : ' '),
7951 160 : (endseq ? '*' : ' '),
7952 : disc, isa, lineop);
7953 320 : print_dwarf_addr (dwflmod, address_size,
7954 160 : address - (endseq ? 1 : 0), address);
7955 160 : printf ("\n");
7956 :
7957 160 : if (endseq)
7958 : printf("\n");
7959 : }
7960 : }
7961 4 : }
7962 :
7963 :
7964 : /* Print the value of a form.
7965 : Returns new value of readp, or readendp on failure. */
7966 : static const unsigned char *
7967 20 : print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
7968 : const unsigned char *readendp, unsigned int offset_len,
7969 : Dwarf_Off str_offsets_base)
7970 : {
7971 : Dwarf_Word val;
7972 : unsigned char *endp;
7973 : Elf_Data *data;
7974 : char *str;
7975 20 : switch (form)
7976 : {
7977 8 : case DW_FORM_data1:
7978 8 : if (readendp - readp < 1)
7979 : {
7980 0 : invalid_data:
7981 0 : error (0, 0, "invalid data");
7982 0 : return readendp;
7983 : }
7984 8 : val = *readp++;
7985 8 : printf (" %" PRIx8, (unsigned int) val);
7986 : break;
7987 :
7988 0 : case DW_FORM_data2:
7989 0 : if (readendp - readp < 2)
7990 : goto invalid_data;
7991 0 : val = read_2ubyte_unaligned_inc (dbg, readp);
7992 0 : printf(" %" PRIx16, (unsigned int) val);
7993 : break;
7994 :
7995 0 : case DW_FORM_data4:
7996 0 : if (readendp - readp < 4)
7997 : goto invalid_data;
7998 0 : val = read_4ubyte_unaligned_inc (dbg, readp);
7999 0 : printf (" %" PRIx32, (unsigned int) val);
8000 : break;
8001 :
8002 0 : case DW_FORM_data8:
8003 0 : if (readendp - readp < 8)
8004 : goto invalid_data;
8005 0 : val = read_8ubyte_unaligned_inc (dbg, readp);
8006 : printf (" %" PRIx64, val);
8007 : break;
8008 :
8009 0 : case DW_FORM_sdata:
8010 0 : if (readendp - readp < 1)
8011 : goto invalid_data;
8012 0 : get_sleb128 (val, readp, readendp);
8013 : printf (" %" PRIx64, val);
8014 : break;
8015 :
8016 0 : case DW_FORM_udata:
8017 0 : if (readendp - readp < 1)
8018 : goto invalid_data;
8019 0 : get_uleb128 (val, readp, readendp);
8020 : printf (" %" PRIx64, val);
8021 : break;
8022 :
8023 0 : case DW_FORM_block:
8024 0 : if (readendp - readp < 1)
8025 : goto invalid_data;
8026 0 : get_uleb128 (val, readp, readendp);
8027 0 : if ((size_t) (readendp - readp) < val)
8028 : goto invalid_data;
8029 0 : print_bytes (val, readp);
8030 0 : readp += val;
8031 0 : break;
8032 :
8033 0 : case DW_FORM_block1:
8034 0 : if (readendp - readp < 1)
8035 : goto invalid_data;
8036 0 : val = *readp++;
8037 0 : if ((size_t) (readendp - readp) < val)
8038 : goto invalid_data;
8039 0 : print_bytes (val, readp);
8040 0 : readp += val;
8041 0 : break;
8042 :
8043 0 : case DW_FORM_block2:
8044 0 : if (readendp - readp < 2)
8045 : goto invalid_data;
8046 0 : val = read_2ubyte_unaligned_inc (dbg, readp);
8047 0 : if ((size_t) (readendp - readp) < val)
8048 : goto invalid_data;
8049 0 : print_bytes (val, readp);
8050 0 : readp += val;
8051 0 : break;
8052 :
8053 0 : case DW_FORM_block4:
8054 0 : if (readendp - readp < 4)
8055 : goto invalid_data;
8056 0 : val = read_4ubyte_unaligned_inc (dbg, readp);
8057 0 : if ((size_t) (readendp - readp) < val)
8058 : goto invalid_data;
8059 0 : print_bytes (val, readp);
8060 0 : readp += val;
8061 0 : break;
8062 :
8063 0 : case DW_FORM_data16:
8064 0 : if (readendp - readp < 16)
8065 : goto invalid_data;
8066 0 : print_bytes (16, readp);
8067 0 : readp += 16;
8068 0 : break;
8069 :
8070 0 : case DW_FORM_flag:
8071 0 : if (readendp - readp < 1)
8072 : goto invalid_data;
8073 0 : val = *readp++;
8074 0 : printf ("%s", val != 0 ? yes_str : no_str);
8075 : break;
8076 :
8077 0 : case DW_FORM_string:
8078 0 : endp = memchr (readp, '\0', readendp - readp);
8079 0 : if (endp == NULL)
8080 : goto invalid_data;
8081 0 : printf ("%s", readp);
8082 0 : readp = endp + 1;
8083 0 : break;
8084 :
8085 12 : case DW_FORM_strp:
8086 : case DW_FORM_line_strp:
8087 : case DW_FORM_strp_sup:
8088 12 : if ((size_t) (readendp - readp) < offset_len)
8089 : goto invalid_data;
8090 12 : if (offset_len == 8)
8091 0 : val = read_8ubyte_unaligned_inc (dbg, readp);
8092 : else
8093 12 : val = read_4ubyte_unaligned_inc (dbg, readp);
8094 12 : if (form == DW_FORM_strp)
8095 0 : data = dbg->sectiondata[IDX_debug_str];
8096 12 : else if (form == DW_FORM_line_strp)
8097 12 : data = dbg->sectiondata[IDX_debug_line_str];
8098 : else /* form == DW_FORM_strp_sup */
8099 : {
8100 0 : Dwarf *alt = dwarf_getalt (dbg);
8101 0 : data = alt != NULL ? alt->sectiondata[IDX_debug_str] : NULL;
8102 : }
8103 12 : if (data == NULL || val >= data->d_size
8104 12 : || memchr (data->d_buf + val, '\0', data->d_size - val) == NULL)
8105 : str = "???";
8106 : else
8107 12 : str = (char *) data->d_buf + val;
8108 : printf ("%s (%" PRIu64 ")", str, val);
8109 : break;
8110 :
8111 0 : case DW_FORM_sec_offset:
8112 0 : if ((size_t) (readendp - readp) < offset_len)
8113 : goto invalid_data;
8114 0 : if (offset_len == 8)
8115 0 : val = read_8ubyte_unaligned_inc (dbg, readp);
8116 : else
8117 0 : val = read_4ubyte_unaligned_inc (dbg, readp);
8118 : printf ("[%" PRIx64 "]", val);
8119 : break;
8120 :
8121 0 : case DW_FORM_strx:
8122 : case DW_FORM_GNU_str_index:
8123 0 : if (readendp - readp < 1)
8124 : goto invalid_data;
8125 0 : get_uleb128 (val, readp, readendp);
8126 0 : strx_val:
8127 0 : data = dbg->sectiondata[IDX_debug_str_offsets];
8128 0 : if (data == NULL
8129 0 : || data->d_size - str_offsets_base < val)
8130 : str = "???";
8131 : else
8132 : {
8133 0 : const unsigned char *strreadp = data->d_buf + str_offsets_base + val;
8134 0 : const unsigned char *strreadendp = data->d_buf + data->d_size;
8135 0 : if ((size_t) (strreadendp - strreadp) < offset_len)
8136 : str = "???";
8137 : else
8138 : {
8139 : Dwarf_Off idx;
8140 0 : if (offset_len == 8)
8141 0 : idx = read_8ubyte_unaligned (dbg, strreadp);
8142 : else
8143 0 : idx = read_4ubyte_unaligned (dbg, strreadp);
8144 :
8145 0 : data = dbg->sectiondata[IDX_debug_str];
8146 0 : if (data == NULL || idx >= data->d_size
8147 0 : || memchr (data->d_buf + idx, '\0',
8148 : data->d_size - idx) == NULL)
8149 : str = "???";
8150 : else
8151 0 : str = (char *) data->d_buf + idx;
8152 : }
8153 : }
8154 : printf ("%s (%" PRIu64 ")", str, val);
8155 : break;
8156 :
8157 0 : case DW_FORM_strx1:
8158 0 : if (readendp - readp < 1)
8159 : goto invalid_data;
8160 0 : val = *readp++;
8161 0 : goto strx_val;
8162 :
8163 0 : case DW_FORM_strx2:
8164 0 : if (readendp - readp < 2)
8165 : goto invalid_data;
8166 0 : val = read_2ubyte_unaligned_inc (dbg, readp);
8167 0 : goto strx_val;
8168 :
8169 0 : case DW_FORM_strx3:
8170 0 : if (readendp - readp < 3)
8171 : goto invalid_data;
8172 0 : val = read_3ubyte_unaligned_inc (dbg, readp);
8173 0 : goto strx_val;
8174 :
8175 0 : case DW_FORM_strx4:
8176 0 : if (readendp - readp < 4)
8177 : goto invalid_data;
8178 0 : val = read_4ubyte_unaligned_inc (dbg, readp);
8179 0 : goto strx_val;
8180 :
8181 0 : default:
8182 0 : error (0, 0, gettext ("unknown form: %s"), dwarf_form_name (form));
8183 0 : return readendp;
8184 : }
8185 :
8186 20 : return readp;
8187 : }
8188 :
8189 : static void
8190 50 : print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
8191 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
8192 : {
8193 50 : if (decodedline)
8194 : {
8195 4 : print_decoded_line_section (dwflmod, ebl, ehdr, scn, shdr, dbg);
8196 4 : return;
8197 : }
8198 :
8199 92 : printf (gettext ("\
8200 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
8201 : elf_ndxscn (scn), section_name (ebl, shdr),
8202 46 : (uint64_t) shdr->sh_offset);
8203 :
8204 46 : if (shdr->sh_size == 0)
8205 : return;
8206 :
8207 : /* There is no functionality in libdw to read the information in the
8208 : way it is represented here. Hardcode the decoder. */
8209 92 : Elf_Data *data = (dbg->sectiondata[IDX_debug_line]
8210 46 : ?: elf_rawdata (scn, NULL));
8211 46 : if (unlikely (data == NULL))
8212 : {
8213 0 : error (0, 0, gettext ("cannot get line data section data: %s"),
8214 : elf_errmsg (-1));
8215 : return;
8216 : }
8217 :
8218 46 : const unsigned char *linep = (const unsigned char *) data->d_buf;
8219 : const unsigned char *lineendp;
8220 :
8221 1189 : while (linep
8222 1143 : < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
8223 : {
8224 1097 : size_t start_offset = linep - (const unsigned char *) data->d_buf;
8225 :
8226 2194 : printf (gettext ("\nTable at offset %zu:\n"), start_offset);
8227 :
8228 1097 : if (unlikely (linep + 4 > lineendp))
8229 : goto invalid_data;
8230 1122 : Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
8231 1097 : unsigned int length = 4;
8232 1097 : if (unlikely (unit_length == 0xffffffff))
8233 : {
8234 0 : if (unlikely (linep + 8 > lineendp))
8235 : {
8236 0 : invalid_data:
8237 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
8238 : elf_ndxscn (scn), section_name (ebl, shdr));
8239 : return;
8240 : }
8241 0 : unit_length = read_8ubyte_unaligned_inc (dbg, linep);
8242 0 : length = 8;
8243 : }
8244 :
8245 : /* Check whether we have enough room in the section. */
8246 1097 : if (unlikely (unit_length > (size_t) (lineendp - linep)))
8247 : goto invalid_data;
8248 1097 : lineendp = linep + unit_length;
8249 :
8250 : /* The next element of the header is the version identifier. */
8251 1097 : if ((size_t) (lineendp - linep) < 2)
8252 : goto invalid_data;
8253 1122 : uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
8254 :
8255 1097 : size_t address_size
8256 1097 : = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
8257 1097 : unsigned char segment_selector_size = 0;
8258 1097 : if (version > 4)
8259 : {
8260 2 : if ((size_t) (lineendp - linep) < 2)
8261 : goto invalid_data;
8262 2 : address_size = *linep++;
8263 2 : segment_selector_size = *linep++;
8264 : }
8265 :
8266 : /* Next comes the header length. */
8267 : Dwarf_Word header_length;
8268 1097 : if (length == 4)
8269 : {
8270 1097 : if ((size_t) (lineendp - linep) < 4)
8271 : goto invalid_data;
8272 1122 : header_length = read_4ubyte_unaligned_inc (dbg, linep);
8273 : }
8274 : else
8275 : {
8276 0 : if ((size_t) (lineendp - linep) < 8)
8277 : goto invalid_data;
8278 0 : header_length = read_8ubyte_unaligned_inc (dbg, linep);
8279 : }
8280 :
8281 : /* Next the minimum instruction length. */
8282 1097 : if ((size_t) (lineendp - linep) < 1)
8283 : goto invalid_data;
8284 1097 : uint_fast8_t minimum_instr_len = *linep++;
8285 :
8286 : /* Next the maximum operations per instruction, in version 4 format. */
8287 : uint_fast8_t max_ops_per_instr;
8288 1097 : if (version < 4)
8289 : max_ops_per_instr = 1;
8290 : else
8291 : {
8292 10 : if ((size_t) (lineendp - linep) < 1)
8293 : goto invalid_data;
8294 10 : max_ops_per_instr = *linep++;
8295 : }
8296 :
8297 : /* We need at least 4 more bytes. */
8298 1097 : if ((size_t) (lineendp - linep) < 4)
8299 : goto invalid_data;
8300 :
8301 : /* Then the flag determining the default value of the is_stmt
8302 : register. */
8303 1097 : uint_fast8_t default_is_stmt = *linep++;
8304 :
8305 : /* Now the line base. */
8306 1097 : int_fast8_t line_base = *linep++;
8307 :
8308 : /* And the line range. */
8309 1097 : uint_fast8_t line_range = *linep++;
8310 :
8311 : /* The opcode base. */
8312 1097 : uint_fast8_t opcode_base = *linep++;
8313 :
8314 : /* Print what we got so far. */
8315 2194 : printf (gettext ("\n"
8316 : " Length: %" PRIu64 "\n"
8317 : " DWARF version: %" PRIuFAST16 "\n"
8318 : " Prologue length: %" PRIu64 "\n"
8319 : " Address size: %zd\n"
8320 : " Segment selector size: %zd\n"
8321 : " Min instruction length: %" PRIuFAST8 "\n"
8322 : " Max operations per instruction: %" PRIuFAST8 "\n"
8323 : " Initial value if 'is_stmt': %" PRIuFAST8 "\n"
8324 : " Line base: %" PRIdFAST8 "\n"
8325 : " Line range: %" PRIuFAST8 "\n"
8326 : " Opcode base: %" PRIuFAST8 "\n"
8327 : "\n"
8328 : "Opcodes:\n"),
8329 : (uint64_t) unit_length, version, (uint64_t) header_length,
8330 : address_size, (size_t) segment_selector_size,
8331 : minimum_instr_len, max_ops_per_instr,
8332 : default_is_stmt, line_base,
8333 : line_range, opcode_base);
8334 :
8335 1097 : if (version < 2 || version > 5)
8336 : {
8337 0 : error (0, 0, gettext ("cannot handle .debug_line version: %u\n"),
8338 : (unsigned int) version);
8339 0 : linep = lineendp;
8340 0 : continue;
8341 : }
8342 :
8343 1097 : if (address_size != 4 && address_size != 8)
8344 : {
8345 0 : error (0, 0, gettext ("cannot handle address size: %u\n"),
8346 : (unsigned int) address_size);
8347 0 : linep = lineendp;
8348 0 : continue;
8349 : }
8350 :
8351 1097 : if (segment_selector_size != 0)
8352 : {
8353 0 : error (0, 0, gettext ("cannot handle segment selector size: %u\n"),
8354 : (unsigned int) segment_selector_size);
8355 0 : linep = lineendp;
8356 0 : continue;
8357 : }
8358 :
8359 1097 : if (unlikely (linep + opcode_base - 1 >= lineendp))
8360 : {
8361 0 : invalid_unit:
8362 0 : error (0, 0,
8363 0 : gettext ("invalid data at offset %tu in section [%zu] '%s'"),
8364 0 : linep - (const unsigned char *) data->d_buf,
8365 : elf_ndxscn (scn), section_name (ebl, shdr));
8366 0 : linep = lineendp;
8367 0 : continue;
8368 : }
8369 1097 : int opcode_base_l10 = 1;
8370 1097 : unsigned int tmp = opcode_base;
8371 3289 : while (tmp > 10)
8372 : {
8373 1095 : tmp /= 10;
8374 1095 : ++opcode_base_l10;
8375 : }
8376 1097 : const uint8_t *standard_opcode_lengths = linep - 1;
8377 14255 : for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
8378 26316 : printf (ngettext (" [%*" PRIuFAST8 "] %hhu argument\n",
8379 : " [%*" PRIuFAST8 "] %hhu arguments\n",
8380 : (int) linep[cnt - 1]),
8381 13158 : opcode_base_l10, cnt, linep[cnt - 1]);
8382 1097 : linep += opcode_base - 1;
8383 :
8384 1097 : if (unlikely (linep >= lineendp))
8385 : goto invalid_unit;
8386 :
8387 1097 : Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, NULL);
8388 :
8389 1097 : puts (gettext ("\nDirectory table:"));
8390 1097 : if (version > 4)
8391 : {
8392 : struct encpair { uint16_t desc; uint16_t form; };
8393 : struct encpair enc[256];
8394 :
8395 4 : printf (gettext (" ["));
8396 2 : if ((size_t) (lineendp - linep) < 1)
8397 : goto invalid_data;
8398 2 : unsigned char directory_entry_format_count = *linep++;
8399 6 : for (int i = 0; i < directory_entry_format_count; i++)
8400 : {
8401 : uint16_t desc, form;
8402 2 : if ((size_t) (lineendp - linep) < 1)
8403 : goto invalid_data;
8404 2 : get_uleb128 (desc, linep, lineendp);
8405 2 : if ((size_t) (lineendp - linep) < 1)
8406 : goto invalid_data;
8407 2 : get_uleb128 (form, linep, lineendp);
8408 :
8409 : enc[i].desc = desc;
8410 2 : enc[i].form = form;
8411 :
8412 4 : printf ("%s(%s)",
8413 : dwarf_line_content_description_name (desc),
8414 : dwarf_form_name (form));
8415 2 : if (i + 1 < directory_entry_format_count)
8416 : printf (", ");
8417 : }
8418 2 : printf ("]\n");
8419 :
8420 : uint64_t directories_count;
8421 2 : if ((size_t) (lineendp - linep) < 1)
8422 : goto invalid_data;
8423 2 : get_uleb128 (directories_count, linep, lineendp);
8424 :
8425 4 : if (directory_entry_format_count == 0
8426 2 : && directories_count != 0)
8427 : goto invalid_data;
8428 :
8429 4 : for (uint64_t i = 0; i < directories_count; i++)
8430 : {
8431 4 : printf (" %-5" PRIu64 " ", i);
8432 12 : for (int j = 0; j < directory_entry_format_count; j++)
8433 : {
8434 4 : linep = print_form_data (dbg, enc[j].form,
8435 : linep, lineendp, length,
8436 : str_offsets_base);
8437 4 : if (j + 1 < directory_entry_format_count)
8438 : printf (", ");
8439 : }
8440 4 : printf ("\n");
8441 4 : if (linep >= lineendp)
8442 : goto invalid_unit;
8443 : }
8444 : }
8445 : else
8446 : {
8447 8355 : while (linep < lineendp && *linep != 0)
8448 : {
8449 7260 : unsigned char *endp = memchr (linep, '\0', lineendp - linep);
8450 7260 : if (unlikely (endp == NULL))
8451 : goto invalid_unit;
8452 :
8453 14520 : printf (" %s\n", (char *) linep);
8454 :
8455 7260 : linep = endp + 1;
8456 : }
8457 2190 : if (linep >= lineendp || *linep != 0)
8458 : goto invalid_unit;
8459 : /* Skip the final NUL byte. */
8460 1095 : ++linep;
8461 : }
8462 :
8463 1097 : if (unlikely (linep >= lineendp))
8464 : goto invalid_unit;
8465 :
8466 1097 : puts (gettext ("\nFile name table:"));
8467 1097 : if (version > 4)
8468 : {
8469 : struct encpair { uint16_t desc; uint16_t form; };
8470 : struct encpair enc[256];
8471 :
8472 4 : printf (gettext (" ["));
8473 2 : if ((size_t) (lineendp - linep) < 1)
8474 : goto invalid_data;
8475 2 : unsigned char file_name_format_count = *linep++;
8476 8 : for (int i = 0; i < file_name_format_count; i++)
8477 : {
8478 : uint64_t desc, form;
8479 4 : if ((size_t) (lineendp - linep) < 1)
8480 : goto invalid_data;
8481 4 : get_uleb128 (desc, linep, lineendp);
8482 4 : if ((size_t) (lineendp - linep) < 1)
8483 : goto invalid_data;
8484 4 : get_uleb128 (form, linep, lineendp);
8485 :
8486 4 : if (! libdw_valid_user_form (form))
8487 : goto invalid_data;
8488 :
8489 : enc[i].desc = desc;
8490 4 : enc[i].form = form;
8491 :
8492 8 : printf ("%s(%s)",
8493 : dwarf_line_content_description_name (desc),
8494 : dwarf_form_name (form));
8495 4 : if (i + 1 < file_name_format_count)
8496 : printf (", ");
8497 : }
8498 2 : printf ("]\n");
8499 :
8500 : uint64_t file_name_count;
8501 2 : if ((size_t) (lineendp - linep) < 1)
8502 : goto invalid_data;
8503 2 : get_uleb128 (file_name_count, linep, lineendp);
8504 :
8505 4 : if (file_name_format_count == 0
8506 2 : && file_name_count != 0)
8507 : goto invalid_data;
8508 :
8509 8 : for (uint64_t i = 0; i < file_name_count; i++)
8510 : {
8511 8 : printf (" %-5" PRIu64 " ", i);
8512 32 : for (int j = 0; j < file_name_format_count; j++)
8513 : {
8514 16 : linep = print_form_data (dbg, enc[j].form,
8515 : linep, lineendp, length,
8516 : str_offsets_base);
8517 16 : if (j + 1 < file_name_format_count)
8518 : printf (", ");
8519 : }
8520 8 : printf ("\n");
8521 8 : if (linep >= lineendp)
8522 : goto invalid_unit;
8523 : }
8524 : }
8525 : else
8526 : {
8527 1095 : puts (gettext (" Entry Dir Time Size Name"));
8528 22867 : for (unsigned int cnt = 1; linep < lineendp && *linep != 0; ++cnt)
8529 : {
8530 : /* First comes the file name. */
8531 21772 : char *fname = (char *) linep;
8532 21772 : unsigned char *endp = memchr (fname, '\0', lineendp - linep);
8533 21772 : if (unlikely (endp == NULL))
8534 : goto invalid_unit;
8535 21772 : linep = endp + 1;
8536 :
8537 : /* Then the index. */
8538 : unsigned int diridx;
8539 21772 : if (lineendp - linep < 1)
8540 : goto invalid_unit;
8541 21772 : get_uleb128 (diridx, linep, lineendp);
8542 :
8543 : /* Next comes the modification time. */
8544 : unsigned int mtime;
8545 21772 : if (lineendp - linep < 1)
8546 : goto invalid_unit;
8547 21772 : get_uleb128 (mtime, linep, lineendp);
8548 :
8549 : /* Finally the length of the file. */
8550 : unsigned int fsize;
8551 21772 : if (lineendp - linep < 1)
8552 : goto invalid_unit;
8553 21772 : get_uleb128 (fsize, linep, lineendp);
8554 :
8555 21772 : printf (" %-5u %-5u %-9u %-9u %s\n",
8556 : cnt, diridx, mtime, fsize, fname);
8557 : }
8558 2190 : if (linep >= lineendp || *linep != '\0')
8559 : goto invalid_unit;
8560 : /* Skip the final NUL byte. */
8561 1095 : ++linep;
8562 : }
8563 :
8564 1097 : puts (gettext ("\nLine number statements:"));
8565 : Dwarf_Word address = 0;
8566 : unsigned int op_index = 0;
8567 1097 : size_t line = 1;
8568 1097 : uint_fast8_t is_stmt = default_is_stmt;
8569 :
8570 : /* Apply the "operation advance" from a special opcode
8571 : or DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */
8572 : unsigned int op_addr_advance;
8573 : bool show_op_index;
8574 : inline void advance_pc (unsigned int op_advance)
8575 : {
8576 301644 : op_addr_advance = minimum_instr_len * ((op_index + op_advance)
8577 150822 : / max_ops_per_instr);
8578 150822 : address += op_addr_advance;
8579 301644 : show_op_index = (op_index > 0 ||
8580 150822 : (op_index + op_advance) % max_ops_per_instr > 0);
8581 150822 : op_index = (op_index + op_advance) % max_ops_per_instr;
8582 : }
8583 :
8584 1097 : if (max_ops_per_instr == 0)
8585 : {
8586 0 : error (0, 0,
8587 0 : gettext ("invalid maximum operations per instruction is zero"));
8588 0 : linep = lineendp;
8589 0 : continue;
8590 : }
8591 :
8592 246103 : while (linep < lineendp)
8593 : {
8594 245006 : size_t offset = linep - (const unsigned char *) data->d_buf;
8595 : unsigned int u128;
8596 : int s128;
8597 :
8598 : /* Read the opcode. */
8599 245006 : unsigned int opcode = *linep++;
8600 :
8601 245006 : printf (" [%6" PRIx64 "]", (uint64_t)offset);
8602 : /* Is this a special opcode? */
8603 245006 : if (likely (opcode >= opcode_base))
8604 : {
8605 112220 : if (unlikely (line_range == 0))
8606 : goto invalid_unit;
8607 :
8608 : /* Yes. Handling this is quite easy since the opcode value
8609 : is computed with
8610 :
8611 : opcode = (desired line increment - line_base)
8612 : + (line_range * address advance) + opcode_base
8613 : */
8614 112220 : int line_increment = (line_base
8615 112220 : + (opcode - opcode_base) % line_range);
8616 :
8617 : /* Perform the increments. */
8618 112220 : line += line_increment;
8619 224440 : advance_pc ((opcode - opcode_base) / line_range);
8620 :
8621 224440 : printf (gettext (" special opcode %u: address+%u = "),
8622 : opcode, op_addr_advance);
8623 112220 : print_dwarf_addr (dwflmod, 0, address, address);
8624 112220 : if (show_op_index)
8625 0 : printf (gettext (", op_index = %u, line%+d = %zu\n"),
8626 : op_index, line_increment, line);
8627 : else
8628 112220 : printf (gettext (", line%+d = %zu\n"),
8629 : line_increment, line);
8630 : }
8631 132786 : else if (opcode == 0)
8632 : {
8633 : /* This an extended opcode. */
8634 13274 : if (unlikely (linep + 2 > lineendp))
8635 : goto invalid_unit;
8636 :
8637 : /* The length. */
8638 13274 : unsigned int len = *linep++;
8639 :
8640 13274 : if (unlikely (linep + len > lineendp))
8641 : goto invalid_unit;
8642 :
8643 : /* The sub-opcode. */
8644 13274 : opcode = *linep++;
8645 :
8646 26548 : printf (gettext (" extended opcode %u: "), opcode);
8647 :
8648 13274 : switch (opcode)
8649 : {
8650 1126 : case DW_LNE_end_sequence:
8651 1126 : puts (gettext (" end of sequence"));
8652 :
8653 : /* Reset the registers we care about. */
8654 : address = 0;
8655 : op_index = 0;
8656 1126 : line = 1;
8657 1126 : is_stmt = default_is_stmt;
8658 1126 : break;
8659 :
8660 1254 : case DW_LNE_set_address:
8661 : op_index = 0;
8662 1254 : if (unlikely ((size_t) (lineendp - linep) < address_size))
8663 : goto invalid_unit;
8664 1254 : if (address_size == 4)
8665 17 : address = read_4ubyte_unaligned_inc (dbg, linep);
8666 : else
8667 1256 : address = read_8ubyte_unaligned_inc (dbg, linep);
8668 : {
8669 2508 : printf (gettext (" set address to "));
8670 1254 : print_dwarf_addr (dwflmod, 0, address, address);
8671 : printf ("\n");
8672 : }
8673 : break;
8674 :
8675 0 : case DW_LNE_define_file:
8676 : {
8677 0 : char *fname = (char *) linep;
8678 0 : unsigned char *endp = memchr (linep, '\0',
8679 0 : lineendp - linep);
8680 0 : if (unlikely (endp == NULL))
8681 : goto invalid_unit;
8682 0 : linep = endp + 1;
8683 :
8684 : unsigned int diridx;
8685 0 : if (lineendp - linep < 1)
8686 : goto invalid_unit;
8687 0 : get_uleb128 (diridx, linep, lineendp);
8688 : Dwarf_Word mtime;
8689 0 : if (lineendp - linep < 1)
8690 : goto invalid_unit;
8691 0 : get_uleb128 (mtime, linep, lineendp);
8692 : Dwarf_Word filelength;
8693 0 : if (lineendp - linep < 1)
8694 : goto invalid_unit;
8695 0 : get_uleb128 (filelength, linep, lineendp);
8696 :
8697 0 : printf (gettext ("\
8698 : define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
8699 : diridx, (uint64_t) mtime, (uint64_t) filelength,
8700 : fname);
8701 : }
8702 : break;
8703 :
8704 10894 : case DW_LNE_set_discriminator:
8705 : /* Takes one ULEB128 parameter, the discriminator. */
8706 21788 : if (unlikely (standard_opcode_lengths[opcode] != 1
8707 : || lineendp - linep < 1))
8708 : goto invalid_unit;
8709 :
8710 10894 : get_uleb128 (u128, linep, lineendp);
8711 10894 : printf (gettext (" set discriminator to %u\n"), u128);
8712 : break;
8713 :
8714 0 : default:
8715 : /* Unknown, ignore it. */
8716 0 : puts (gettext (" unknown opcode"));
8717 0 : linep += len - 1;
8718 0 : break;
8719 : }
8720 : }
8721 119512 : else if (opcode <= DW_LNS_set_isa)
8722 : {
8723 : /* This is a known standard opcode. */
8724 119512 : switch (opcode)
8725 : {
8726 8383 : case DW_LNS_copy:
8727 : /* Takes no argument. */
8728 8383 : puts (gettext (" copy"));
8729 8383 : break;
8730 :
8731 12109 : case DW_LNS_advance_pc:
8732 : /* Takes one uleb128 parameter which is added to the
8733 : address. */
8734 12109 : if (lineendp - linep < 1)
8735 : goto invalid_unit;
8736 12109 : get_uleb128 (u128, linep, lineendp);
8737 12109 : advance_pc (u128);
8738 : {
8739 24218 : printf (gettext (" advance address by %u to "),
8740 : op_addr_advance);
8741 12109 : print_dwarf_addr (dwflmod, 0, address, address);
8742 12109 : if (show_op_index)
8743 0 : printf (gettext (", op_index to %u"), op_index);
8744 : printf ("\n");
8745 : }
8746 : break;
8747 :
8748 48704 : case DW_LNS_advance_line:
8749 : /* Takes one sleb128 parameter which is added to the
8750 : line. */
8751 48704 : if (lineendp - linep < 1)
8752 : goto invalid_unit;
8753 48704 : get_sleb128 (s128, linep, lineendp);
8754 48704 : line += s128;
8755 48704 : printf (gettext ("\
8756 : advance line by constant %d to %" PRId64 "\n"),
8757 : s128, (int64_t) line);
8758 : break;
8759 :
8760 19159 : case DW_LNS_set_file:
8761 : /* Takes one uleb128 parameter which is stored in file. */
8762 19159 : if (lineendp - linep < 1)
8763 : goto invalid_unit;
8764 19159 : get_uleb128 (u128, linep, lineendp);
8765 19159 : printf (gettext (" set file to %" PRIu64 "\n"),
8766 : (uint64_t) u128);
8767 : break;
8768 :
8769 131 : case DW_LNS_set_column:
8770 : /* Takes one uleb128 parameter which is stored in column. */
8771 262 : if (unlikely (standard_opcode_lengths[opcode] != 1
8772 : || lineendp - linep < 1))
8773 : goto invalid_unit;
8774 :
8775 131 : get_uleb128 (u128, linep, lineendp);
8776 131 : printf (gettext (" set column to %" PRIu64 "\n"),
8777 : (uint64_t) u128);
8778 : break;
8779 :
8780 4510 : case DW_LNS_negate_stmt:
8781 : /* Takes no argument. */
8782 4510 : is_stmt = 1 - is_stmt;
8783 4510 : printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
8784 : "is_stmt", is_stmt);
8785 : break;
8786 :
8787 0 : case DW_LNS_set_basic_block:
8788 : /* Takes no argument. */
8789 0 : puts (gettext (" set basic block flag"));
8790 0 : break;
8791 :
8792 26493 : case DW_LNS_const_add_pc:
8793 : /* Takes no argument. */
8794 :
8795 26493 : if (unlikely (line_range == 0))
8796 : goto invalid_unit;
8797 :
8798 52986 : advance_pc ((255 - opcode_base) / line_range);
8799 : {
8800 52986 : printf (gettext (" advance address by constant %u to "),
8801 : op_addr_advance);
8802 26493 : print_dwarf_addr (dwflmod, 0, address, address);
8803 26493 : if (show_op_index)
8804 0 : printf (gettext (", op_index to %u"), op_index);
8805 : printf ("\n");
8806 : }
8807 : break;
8808 :
8809 22 : case DW_LNS_fixed_advance_pc:
8810 : /* Takes one 16 bit parameter which is added to the
8811 : address. */
8812 44 : if (unlikely (standard_opcode_lengths[opcode] != 1
8813 : || lineendp - linep < 2))
8814 : goto invalid_unit;
8815 :
8816 22 : u128 = read_2ubyte_unaligned_inc (dbg, linep);
8817 22 : address += u128;
8818 : op_index = 0;
8819 : {
8820 44 : printf (gettext ("\
8821 : advance address by fixed value %u to \n"),
8822 : u128);
8823 22 : print_dwarf_addr (dwflmod, 0, address, address);
8824 : printf ("\n");
8825 : }
8826 : break;
8827 :
8828 1 : case DW_LNS_set_prologue_end:
8829 : /* Takes no argument. */
8830 1 : puts (gettext (" set prologue end flag"));
8831 1 : break;
8832 :
8833 0 : case DW_LNS_set_epilogue_begin:
8834 : /* Takes no argument. */
8835 0 : puts (gettext (" set epilogue begin flag"));
8836 0 : break;
8837 :
8838 0 : case DW_LNS_set_isa:
8839 : /* Takes one uleb128 parameter which is stored in isa. */
8840 0 : if (unlikely (standard_opcode_lengths[opcode] != 1
8841 : || lineendp - linep < 1))
8842 : goto invalid_unit;
8843 :
8844 0 : get_uleb128 (u128, linep, lineendp);
8845 0 : printf (gettext (" set isa to %u\n"), u128);
8846 : break;
8847 : }
8848 : }
8849 : else
8850 : {
8851 : /* This is a new opcode the generator but not we know about.
8852 : Read the parameters associated with it but then discard
8853 : everything. Read all the parameters for this opcode. */
8854 0 : printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
8855 : " unknown opcode with %" PRIu8 " parameters:",
8856 : standard_opcode_lengths[opcode]),
8857 0 : standard_opcode_lengths[opcode]);
8858 0 : for (int n = standard_opcode_lengths[opcode];
8859 0 : n > 0 && linep < lineendp; --n)
8860 : {
8861 0 : get_uleb128 (u128, linep, lineendp);
8862 0 : if (n != standard_opcode_lengths[opcode])
8863 0 : putc_unlocked (',', stdout);
8864 0 : printf (" %u", u128);
8865 : }
8866 :
8867 : /* Next round, ignore this opcode. */
8868 0 : continue;
8869 : }
8870 : }
8871 : }
8872 :
8873 : /* There must only be one data block. */
8874 46 : assert (elf_getdata (scn, data) == NULL);
8875 : }
8876 :
8877 :
8878 : static void
8879 3 : print_debug_loclists_section (Dwfl_Module *dwflmod,
8880 : Ebl *ebl,
8881 : GElf_Ehdr *ehdr __attribute__ ((unused)),
8882 : Elf_Scn *scn, GElf_Shdr *shdr,
8883 : Dwarf *dbg)
8884 : {
8885 6 : printf (gettext ("\
8886 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
8887 : elf_ndxscn (scn), section_name (ebl, shdr),
8888 3 : (uint64_t) shdr->sh_offset);
8889 :
8890 6 : Elf_Data *data = (dbg->sectiondata[IDX_debug_loclists]
8891 3 : ?: elf_rawdata (scn, NULL));
8892 3 : if (unlikely (data == NULL))
8893 : {
8894 0 : error (0, 0, gettext ("cannot get .debug_loclists content: %s"),
8895 : elf_errmsg (-1));
8896 0 : return;
8897 : }
8898 :
8899 : /* For the listptr to get the base address/CU. */
8900 6 : sort_listptr (&known_loclistsptr, "loclistsptr");
8901 3 : size_t listptr_idx = 0;
8902 :
8903 3 : const unsigned char *readp = data->d_buf;
8904 3 : const unsigned char *const dataend = ((unsigned char *) data->d_buf
8905 3 : + data->d_size);
8906 10 : while (readp < dataend)
8907 : {
8908 4 : if (unlikely (readp > dataend - 4))
8909 : {
8910 0 : invalid_data:
8911 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
8912 : elf_ndxscn (scn), section_name (ebl, shdr));
8913 0 : return;
8914 : }
8915 :
8916 4 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
8917 8 : printf (gettext ("Table at Offset 0x%" PRIx64 ":\n\n"),
8918 : (uint64_t) offset);
8919 :
8920 4 : uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
8921 4 : unsigned int offset_size = 4;
8922 4 : if (unlikely (unit_length == 0xffffffff))
8923 : {
8924 0 : if (unlikely (readp > dataend - 8))
8925 : goto invalid_data;
8926 :
8927 0 : unit_length = read_8ubyte_unaligned_inc (dbg, readp);
8928 0 : offset_size = 8;
8929 : }
8930 8 : printf (gettext (" Length: %8" PRIu64 "\n"), unit_length);
8931 :
8932 : /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
8933 : bytes to complete the header. And this unit cannot go beyond
8934 : the section data. */
8935 4 : if (readp > dataend - 8
8936 4 : || unit_length < 8
8937 4 : || unit_length > (uint64_t) (dataend - readp))
8938 : goto invalid_data;
8939 :
8940 4 : const unsigned char *nexthdr = readp + unit_length;
8941 :
8942 4 : uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
8943 8 : printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
8944 :
8945 4 : if (version != 5)
8946 : {
8947 0 : error (0, 0, gettext ("Unknown version"));
8948 : goto next_table;
8949 : }
8950 :
8951 4 : uint8_t address_size = *readp++;
8952 8 : printf (gettext (" Address size: %8" PRIu64 "\n"),
8953 : (uint64_t) address_size);
8954 :
8955 4 : if (address_size != 4 && address_size != 8)
8956 : {
8957 0 : error (0, 0, gettext ("unsupported address size"));
8958 : goto next_table;
8959 : }
8960 :
8961 4 : uint8_t segment_size = *readp++;
8962 8 : printf (gettext (" Segment size: %8" PRIu64 "\n"),
8963 : (uint64_t) segment_size);
8964 :
8965 4 : if (segment_size != 0)
8966 : {
8967 0 : error (0, 0, gettext ("unsupported segment size"));
8968 : goto next_table;
8969 : }
8970 :
8971 4 : uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
8972 8 : printf (gettext (" Offset entries: %8" PRIu64 "\n"),
8973 : (uint64_t) offset_entry_count);
8974 :
8975 : /* We need the CU that uses this unit to get the initial base address. */
8976 4 : Dwarf_Addr cu_base = 0;
8977 4 : struct Dwarf_CU *cu = NULL;
8978 4 : if (listptr_cu (&known_loclistsptr, &listptr_idx,
8979 : (Dwarf_Off) offset,
8980 4 : (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
8981 : &cu_base, &cu)
8982 0 : || split_dwarf_cu_base (dbg, &cu, &cu_base))
8983 4 : {
8984 : Dwarf_Die cudie;
8985 4 : if (dwarf_cu_die (cu, &cudie,
8986 : NULL, NULL, NULL, NULL,
8987 : NULL, NULL) == NULL)
8988 0 : printf (gettext (" Unknown CU base: "));
8989 : else
8990 4 : printf (gettext (" CU [%6" PRIx64 "] base: "),
8991 : dwarf_dieoffset (&cudie));
8992 4 : print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
8993 4 : printf ("\n");
8994 : }
8995 : else
8996 0 : printf (gettext (" Not associated with a CU.\n"));
8997 :
8998 4 : printf ("\n");
8999 :
9000 4 : const unsigned char *offset_array_start = readp;
9001 4 : if (offset_entry_count > 0)
9002 : {
9003 2 : uint64_t max_entries = (unit_length - 8) / offset_size;
9004 2 : if (offset_entry_count > max_entries)
9005 : {
9006 0 : error (0, 0,
9007 0 : gettext ("too many offset entries for unit length"));
9008 0 : offset_entry_count = max_entries;
9009 : }
9010 :
9011 4 : printf (gettext (" Offsets starting at 0x%" PRIx64 ":\n"),
9012 : (uint64_t) (offset_array_start
9013 2 : - (unsigned char *) data->d_buf));
9014 18 : for (uint32_t idx = 0; idx < offset_entry_count; idx++)
9015 : {
9016 16 : printf (" [%6" PRIu32 "] ", idx);
9017 16 : if (offset_size == 4)
9018 : {
9019 16 : uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
9020 : printf ("0x%" PRIx32 "\n", off);
9021 : }
9022 : else
9023 : {
9024 0 : uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
9025 : printf ("0x%" PRIx64 "\n", off);
9026 : }
9027 : }
9028 : printf ("\n");
9029 : }
9030 :
9031 4 : Dwarf_Addr base = cu_base;
9032 4 : bool start_of_list = true;
9033 97 : while (readp < nexthdr)
9034 : {
9035 89 : uint8_t kind = *readp++;
9036 : uint64_t op1, op2, len;
9037 :
9038 : /* Skip padding. */
9039 89 : if (start_of_list && kind == DW_LLE_end_of_list)
9040 0 : continue;
9041 :
9042 89 : if (start_of_list)
9043 : {
9044 32 : base = cu_base;
9045 96 : printf (" Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
9046 32 : (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
9047 32 : (uint64_t) (readp - offset_array_start - 1));
9048 32 : start_of_list = false;
9049 : }
9050 :
9051 178 : printf (" %s", dwarf_loc_list_encoding_name (kind));
9052 89 : switch (kind)
9053 : {
9054 32 : case DW_LLE_end_of_list:
9055 32 : start_of_list = true;
9056 : printf ("\n\n");
9057 : break;
9058 :
9059 0 : case DW_LLE_base_addressx:
9060 0 : if ((uint64_t) (nexthdr - readp) < 1)
9061 : {
9062 0 : invalid_entry:
9063 0 : error (0, 0, gettext ("invalid loclists data"));
9064 : goto next_table;
9065 : }
9066 0 : get_uleb128 (op1, readp, nexthdr);
9067 0 : printf (" %" PRIx64 "\n", op1);
9068 0 : if (! print_unresolved_addresses)
9069 : {
9070 : Dwarf_Addr addr;
9071 0 : if (get_indexed_addr (cu, op1, &addr) != 0)
9072 : printf (" ???\n");
9073 : else
9074 : {
9075 0 : printf (" ");
9076 0 : print_dwarf_addr (dwflmod, address_size, addr, addr);
9077 : printf ("\n");
9078 : }
9079 : }
9080 : break;
9081 :
9082 0 : case DW_LLE_startx_endx:
9083 0 : if ((uint64_t) (nexthdr - readp) < 1)
9084 : goto invalid_entry;
9085 0 : get_uleb128 (op1, readp, nexthdr);
9086 0 : if ((uint64_t) (nexthdr - readp) < 1)
9087 : goto invalid_entry;
9088 0 : get_uleb128 (op2, readp, nexthdr);
9089 0 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
9090 0 : if (! print_unresolved_addresses)
9091 : {
9092 : Dwarf_Addr addr1;
9093 : Dwarf_Addr addr2;
9094 0 : if (get_indexed_addr (cu, op1, &addr1) != 0
9095 0 : || get_indexed_addr (cu, op2, &addr2) != 0)
9096 : {
9097 0 : printf (" ???..\n");
9098 : printf (" ???\n");
9099 : }
9100 : else
9101 : {
9102 0 : printf (" ");
9103 0 : print_dwarf_addr (dwflmod, address_size, addr1, addr1);
9104 0 : printf ("..\n ");
9105 0 : print_dwarf_addr (dwflmod, address_size,
9106 : addr2 - 1, addr2);
9107 : printf ("\n");
9108 : }
9109 : }
9110 0 : if ((uint64_t) (nexthdr - readp) < 1)
9111 : goto invalid_entry;
9112 0 : get_uleb128 (len, readp, nexthdr);
9113 0 : if ((uint64_t) (nexthdr - readp) < len)
9114 : goto invalid_entry;
9115 0 : print_ops (dwflmod, dbg, 8, 8, version,
9116 : address_size, offset_size, cu, len, readp);
9117 0 : readp += len;
9118 0 : break;
9119 :
9120 26 : case DW_LLE_startx_length:
9121 26 : if ((uint64_t) (nexthdr - readp) < 1)
9122 : goto invalid_entry;
9123 26 : get_uleb128 (op1, readp, nexthdr);
9124 26 : if ((uint64_t) (nexthdr - readp) < 1)
9125 : goto invalid_entry;
9126 26 : get_uleb128 (op2, readp, nexthdr);
9127 26 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
9128 26 : if (! print_unresolved_addresses)
9129 : {
9130 : Dwarf_Addr addr1;
9131 : Dwarf_Addr addr2;
9132 26 : if (get_indexed_addr (cu, op1, &addr1) != 0)
9133 : {
9134 0 : printf (" ???..\n");
9135 : printf (" ???\n");
9136 : }
9137 : else
9138 : {
9139 26 : addr2 = addr1 + op2;
9140 26 : printf (" ");
9141 26 : print_dwarf_addr (dwflmod, address_size, addr1, addr1);
9142 26 : printf ("..\n ");
9143 26 : print_dwarf_addr (dwflmod, address_size,
9144 : addr2 - 1, addr2);
9145 : printf ("\n");
9146 : }
9147 : }
9148 26 : if ((uint64_t) (nexthdr - readp) < 1)
9149 : goto invalid_entry;
9150 26 : get_uleb128 (len, readp, nexthdr);
9151 26 : if ((uint64_t) (nexthdr - readp) < len)
9152 : goto invalid_entry;
9153 26 : print_ops (dwflmod, dbg, 8, 8, version,
9154 : address_size, offset_size, cu, len, readp);
9155 26 : readp += len;
9156 26 : break;
9157 :
9158 24 : case DW_LLE_offset_pair:
9159 24 : if ((uint64_t) (nexthdr - readp) < 1)
9160 : goto invalid_entry;
9161 24 : get_uleb128 (op1, readp, nexthdr);
9162 24 : if ((uint64_t) (nexthdr - readp) < 1)
9163 : goto invalid_entry;
9164 24 : get_uleb128 (op2, readp, nexthdr);
9165 24 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
9166 24 : if (! print_unresolved_addresses)
9167 : {
9168 24 : op1 += base;
9169 24 : op2 += base;
9170 24 : printf (" ");
9171 24 : print_dwarf_addr (dwflmod, address_size, op1, op1);
9172 24 : printf ("..\n ");
9173 24 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
9174 : printf ("\n");
9175 : }
9176 24 : if ((uint64_t) (nexthdr - readp) < 1)
9177 : goto invalid_entry;
9178 24 : get_uleb128 (len, readp, nexthdr);
9179 24 : if ((uint64_t) (nexthdr - readp) < len)
9180 : goto invalid_entry;
9181 24 : print_ops (dwflmod, dbg, 8, 8, version,
9182 : address_size, offset_size, cu, len, readp);
9183 24 : readp += len;
9184 24 : break;
9185 :
9186 0 : case DW_LLE_default_location:
9187 0 : if ((uint64_t) (nexthdr - readp) < 1)
9188 : goto invalid_entry;
9189 0 : get_uleb128 (len, readp, nexthdr);
9190 0 : if ((uint64_t) (nexthdr - readp) < len)
9191 : goto invalid_entry;
9192 0 : print_ops (dwflmod, dbg, 8, 8, version,
9193 : address_size, offset_size, cu, len, readp);
9194 0 : readp += len;
9195 0 : break;
9196 :
9197 5 : case DW_LLE_base_address:
9198 5 : if (address_size == 4)
9199 : {
9200 0 : if ((uint64_t) (nexthdr - readp) < 4)
9201 : goto invalid_entry;
9202 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
9203 : }
9204 : else
9205 : {
9206 5 : if ((uint64_t) (nexthdr - readp) < 8)
9207 : goto invalid_entry;
9208 5 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
9209 : }
9210 5 : base = op1;
9211 5 : printf (" 0x%" PRIx64 "\n", base);
9212 5 : if (! print_unresolved_addresses)
9213 : {
9214 5 : printf (" ");
9215 5 : print_dwarf_addr (dwflmod, address_size, base, base);
9216 : printf ("\n");
9217 : }
9218 : break;
9219 :
9220 0 : case DW_LLE_start_end:
9221 0 : if (address_size == 4)
9222 : {
9223 0 : if ((uint64_t) (nexthdr - readp) < 8)
9224 : goto invalid_entry;
9225 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
9226 0 : op2 = read_4ubyte_unaligned_inc (dbg, readp);
9227 : }
9228 : else
9229 : {
9230 0 : if ((uint64_t) (nexthdr - readp) < 16)
9231 : goto invalid_entry;
9232 0 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
9233 0 : op2 = read_8ubyte_unaligned_inc (dbg, readp);
9234 : }
9235 0 : printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
9236 0 : if (! print_unresolved_addresses)
9237 : {
9238 0 : printf (" ");
9239 0 : print_dwarf_addr (dwflmod, address_size, op1, op1);
9240 0 : printf ("..\n ");
9241 0 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
9242 : printf ("\n");
9243 : }
9244 0 : if ((uint64_t) (nexthdr - readp) < 1)
9245 : goto invalid_entry;
9246 0 : get_uleb128 (len, readp, nexthdr);
9247 0 : if ((uint64_t) (nexthdr - readp) < len)
9248 : goto invalid_entry;
9249 0 : print_ops (dwflmod, dbg, 8, 8, version,
9250 : address_size, offset_size, cu, len, readp);
9251 0 : readp += len;
9252 0 : break;
9253 :
9254 2 : case DW_LLE_start_length:
9255 2 : if (address_size == 4)
9256 : {
9257 0 : if ((uint64_t) (nexthdr - readp) < 4)
9258 : goto invalid_entry;
9259 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
9260 : }
9261 : else
9262 : {
9263 2 : if ((uint64_t) (nexthdr - readp) < 8)
9264 : goto invalid_entry;
9265 2 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
9266 : }
9267 2 : if ((uint64_t) (nexthdr - readp) < 1)
9268 : goto invalid_entry;
9269 2 : get_uleb128 (op2, readp, nexthdr);
9270 2 : printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
9271 2 : if (! print_unresolved_addresses)
9272 : {
9273 2 : op2 = op1 + op2;
9274 2 : printf (" ");
9275 2 : print_dwarf_addr (dwflmod, address_size, op1, op1);
9276 2 : printf ("..\n ");
9277 2 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
9278 : printf ("\n");
9279 : }
9280 2 : if ((uint64_t) (nexthdr - readp) < 1)
9281 : goto invalid_entry;
9282 2 : get_uleb128 (len, readp, nexthdr);
9283 2 : if ((uint64_t) (nexthdr - readp) < len)
9284 : goto invalid_entry;
9285 2 : print_ops (dwflmod, dbg, 8, 8, version,
9286 : address_size, offset_size, cu, len, readp);
9287 2 : readp += len;
9288 2 : break;
9289 :
9290 : default:
9291 : goto invalid_entry;
9292 : }
9293 : }
9294 :
9295 4 : next_table:
9296 4 : if (readp != nexthdr)
9297 : {
9298 0 : size_t padding = nexthdr - readp;
9299 0 : printf (gettext (" %zu padding bytes\n\n"), padding);
9300 0 : readp = nexthdr;
9301 : }
9302 : }
9303 : }
9304 :
9305 :
9306 : static void
9307 44 : print_debug_loc_section (Dwfl_Module *dwflmod,
9308 : Ebl *ebl, GElf_Ehdr *ehdr,
9309 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
9310 : {
9311 88 : Elf_Data *data = (dbg->sectiondata[IDX_debug_loc]
9312 44 : ?: elf_rawdata (scn, NULL));
9313 :
9314 44 : if (unlikely (data == NULL))
9315 : {
9316 0 : error (0, 0, gettext ("cannot get .debug_loc content: %s"),
9317 : elf_errmsg (-1));
9318 0 : return;
9319 : }
9320 :
9321 88 : printf (gettext ("\
9322 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
9323 : elf_ndxscn (scn), section_name (ebl, shdr),
9324 44 : (uint64_t) shdr->sh_offset);
9325 :
9326 88 : sort_listptr (&known_locsptr, "loclistptr");
9327 44 : size_t listptr_idx = 0;
9328 :
9329 44 : uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
9330 44 : uint_fast8_t offset_size = 4;
9331 :
9332 44 : bool first = true;
9333 44 : Dwarf_Addr base = 0;
9334 44 : unsigned char *readp = data->d_buf;
9335 44 : unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
9336 44 : Dwarf_CU *last_cu = NULL;
9337 203090 : while (readp < endp)
9338 : {
9339 203002 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
9340 203002 : Dwarf_CU *cu = last_cu;
9341 203002 : unsigned int attr = 0;
9342 :
9343 203002 : if (first && skip_listptr_hole (&known_locsptr, &listptr_idx,
9344 : &address_size, &offset_size, &base,
9345 : &cu, offset, &readp, endp, &attr))
9346 0 : continue;
9347 :
9348 203002 : if (last_cu != cu)
9349 : {
9350 : Dwarf_Die cudie;
9351 974 : if (dwarf_cu_die (cu, &cudie,
9352 : NULL, NULL, NULL, NULL,
9353 : NULL, NULL) == NULL)
9354 0 : printf (gettext ("\n Unknown CU base: "));
9355 : else
9356 974 : printf (gettext ("\n CU [%6" PRIx64 "] base: "),
9357 : dwarf_dieoffset (&cudie));
9358 974 : print_dwarf_addr (dwflmod, address_size, base, base);
9359 974 : printf ("\n");
9360 : }
9361 203002 : last_cu = cu;
9362 :
9363 203002 : if (attr == DW_AT_GNU_locviews)
9364 : {
9365 0 : Dwarf_Off next_off = next_listptr_offset (&known_locsptr,
9366 : listptr_idx);
9367 0 : const unsigned char *locp = readp;
9368 : const unsigned char *locendp;
9369 0 : if (next_off == 0
9370 0 : || next_off > (size_t) (endp
9371 0 : - (const unsigned char *) data->d_buf))
9372 : locendp = endp;
9373 : else
9374 0 : locendp = (const unsigned char *) data->d_buf + next_off;
9375 :
9376 0 : while (locp < locendp)
9377 : {
9378 : uint64_t v1, v2;
9379 0 : get_uleb128 (v1, locp, locendp);
9380 0 : if (locp >= locendp)
9381 : {
9382 0 : printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
9383 : break;
9384 : }
9385 0 : get_uleb128 (v2, locp, locendp);
9386 0 : if (first) /* First view pair in a list. */
9387 : printf (" [%6tx] ", offset);
9388 : else
9389 : printf (" ");
9390 0 : printf ("view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
9391 0 : first = false;
9392 : }
9393 :
9394 0 : first = true;
9395 0 : readp = (unsigned char *) locendp;
9396 0 : continue;
9397 : }
9398 :
9399 : /* GNU DebugFission encoded addresses as addrx. */
9400 203002 : bool is_debugfission = ((cu != NULL
9401 0 : || split_dwarf_cu_base (dbg, &cu, &base))
9402 406004 : && (cu->version < 5
9403 203002 : && cu->unit_type == DW_UT_split_compile));
9404 203002 : if (!is_debugfission
9405 202942 : && unlikely (data->d_size - offset < (size_t) address_size * 2))
9406 : {
9407 0 : invalid_data:
9408 0 : printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
9409 0 : break;
9410 : }
9411 :
9412 : Dwarf_Addr begin;
9413 : Dwarf_Addr end;
9414 203002 : bool use_base = true;
9415 203002 : if (is_debugfission)
9416 : {
9417 60 : const unsigned char *locp = readp;
9418 60 : const unsigned char *locendp = readp + data->d_size;
9419 60 : if (locp >= locendp)
9420 : goto invalid_data;
9421 :
9422 : Dwarf_Word idx;
9423 60 : unsigned char code = *locp++;
9424 60 : switch (code)
9425 : {
9426 20 : case DW_LLE_GNU_end_of_list_entry:
9427 20 : begin = 0;
9428 20 : end = 0;
9429 20 : break;
9430 :
9431 0 : case DW_LLE_GNU_base_address_selection_entry:
9432 0 : if (locp >= locendp)
9433 : goto invalid_data;
9434 0 : begin = (Dwarf_Addr) -1;
9435 0 : get_uleb128 (idx, locp, locendp);
9436 0 : if (get_indexed_addr (cu, idx, &end) != 0)
9437 0 : end = idx; /* ... */
9438 : break;
9439 :
9440 0 : case DW_LLE_GNU_start_end_entry:
9441 0 : if (locp >= locendp)
9442 : goto invalid_data;
9443 0 : get_uleb128 (idx, locp, locendp);
9444 0 : if (get_indexed_addr (cu, idx, &begin) != 0)
9445 0 : begin = idx; /* ... */
9446 0 : if (locp >= locendp)
9447 : goto invalid_data;
9448 0 : get_uleb128 (idx, locp, locendp);
9449 0 : if (get_indexed_addr (cu, idx, &end) != 0)
9450 0 : end = idx; /* ... */
9451 : use_base = false;
9452 : break;
9453 :
9454 40 : case DW_LLE_GNU_start_length_entry:
9455 40 : if (locp >= locendp)
9456 : goto invalid_data;
9457 40 : get_uleb128 (idx, locp, locendp);
9458 40 : if (get_indexed_addr (cu, idx, &begin) != 0)
9459 0 : begin = idx; /* ... */
9460 40 : if (locendp - locp < 4)
9461 : goto invalid_data;
9462 40 : end = read_4ubyte_unaligned_inc (dbg, locp);
9463 40 : end += begin;
9464 40 : use_base = false;
9465 40 : break;
9466 :
9467 : default:
9468 : goto invalid_data;
9469 : }
9470 :
9471 60 : readp = (unsigned char *) locp;
9472 : }
9473 202942 : else if (address_size == 8)
9474 : {
9475 202996 : begin = read_8ubyte_unaligned_inc (dbg, readp);
9476 202996 : end = read_8ubyte_unaligned_inc (dbg, readp);
9477 : }
9478 : else
9479 : {
9480 0 : begin = read_4ubyte_unaligned_inc (dbg, readp);
9481 0 : end = read_4ubyte_unaligned_inc (dbg, readp);
9482 0 : if (begin == (Dwarf_Addr) (uint32_t) -1)
9483 0 : begin = (Dwarf_Addr) -1l;
9484 : }
9485 :
9486 203002 : if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
9487 : {
9488 0 : printf (gettext (" [%6tx] base address\n "), offset);
9489 0 : print_dwarf_addr (dwflmod, address_size, end, end);
9490 0 : printf ("\n");
9491 0 : base = end;
9492 : }
9493 203002 : else if (begin == 0 && end == 0) /* End of list entry. */
9494 : {
9495 39494 : if (first)
9496 0 : printf (gettext (" [%6tx] empty list\n"), offset);
9497 : first = true;
9498 : }
9499 : else
9500 : {
9501 : /* We have a location expression entry. */
9502 163544 : uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
9503 :
9504 163508 : if (first) /* First entry in a list. */
9505 : printf (" [%6tx] ", offset);
9506 : else
9507 : printf (" ");
9508 :
9509 327016 : printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
9510 163508 : if (! print_unresolved_addresses)
9511 : {
9512 163478 : Dwarf_Addr dab = use_base ? base + begin : begin;
9513 163478 : Dwarf_Addr dae = use_base ? base + end : end;
9514 163478 : printf (" ");
9515 163478 : print_dwarf_addr (dwflmod, address_size, dab, dab);
9516 163478 : printf ("..\n ");
9517 163478 : print_dwarf_addr (dwflmod, address_size, dae - 1, dae);
9518 : printf ("\n");
9519 : }
9520 :
9521 163508 : if (endp - readp <= (ptrdiff_t) len)
9522 : {
9523 0 : fputs (gettext (" <INVALID DATA>\n"), stdout);
9524 0 : break;
9525 : }
9526 :
9527 327016 : print_ops (dwflmod, dbg, 11, 11,
9528 163508 : cu != NULL ? cu->version : 3,
9529 : address_size, offset_size, cu, len, readp);
9530 :
9531 163508 : first = false;
9532 163508 : readp += len;
9533 : }
9534 : }
9535 : }
9536 :
9537 : struct mac_culist
9538 : {
9539 : Dwarf_Die die;
9540 : Dwarf_Off offset;
9541 : Dwarf_Files *files;
9542 : struct mac_culist *next;
9543 : };
9544 :
9545 :
9546 : static int
9547 0 : mac_compare (const void *p1, const void *p2)
9548 : {
9549 0 : struct mac_culist *m1 = (struct mac_culist *) p1;
9550 0 : struct mac_culist *m2 = (struct mac_culist *) p2;
9551 :
9552 0 : if (m1->offset < m2->offset)
9553 : return -1;
9554 0 : if (m1->offset > m2->offset)
9555 : return 1;
9556 0 : return 0;
9557 : }
9558 :
9559 :
9560 : static void
9561 0 : print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
9562 : Ebl *ebl,
9563 : GElf_Ehdr *ehdr __attribute__ ((unused)),
9564 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
9565 : {
9566 0 : printf (gettext ("\
9567 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
9568 : elf_ndxscn (scn), section_name (ebl, shdr),
9569 0 : (uint64_t) shdr->sh_offset);
9570 0 : putc_unlocked ('\n', stdout);
9571 :
9572 : /* There is no function in libdw to iterate over the raw content of
9573 : the section but it is easy enough to do. */
9574 0 : Elf_Data *data = (dbg->sectiondata[IDX_debug_macinfo]
9575 0 : ?: elf_rawdata (scn, NULL));
9576 0 : if (unlikely (data == NULL))
9577 : {
9578 0 : error (0, 0, gettext ("cannot get macro information section data: %s"),
9579 : elf_errmsg (-1));
9580 0 : return;
9581 : }
9582 :
9583 : /* Get the source file information for all CUs. */
9584 : Dwarf_Off offset;
9585 0 : Dwarf_Off ncu = 0;
9586 : size_t hsize;
9587 0 : struct mac_culist *culist = NULL;
9588 0 : size_t nculist = 0;
9589 0 : while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
9590 : {
9591 : Dwarf_Die cudie;
9592 0 : if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
9593 0 : continue;
9594 :
9595 : Dwarf_Attribute attr;
9596 0 : if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
9597 0 : continue;
9598 :
9599 : Dwarf_Word macoff;
9600 0 : if (dwarf_formudata (&attr, &macoff) != 0)
9601 0 : continue;
9602 :
9603 0 : struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
9604 0 : newp->die = cudie;
9605 0 : newp->offset = macoff;
9606 0 : newp->files = NULL;
9607 0 : newp->next = culist;
9608 0 : culist = newp;
9609 0 : ++nculist;
9610 : }
9611 :
9612 : /* Convert the list into an array for easier consumption. */
9613 0 : struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
9614 : * sizeof (*cus));
9615 : /* Add sentinel. */
9616 0 : cus[nculist].offset = data->d_size;
9617 0 : cus[nculist].files = (Dwarf_Files *) -1l;
9618 0 : if (nculist > 0)
9619 : {
9620 0 : for (size_t cnt = nculist - 1; culist != NULL; --cnt)
9621 : {
9622 0 : assert (cnt < nculist);
9623 0 : cus[cnt] = *culist;
9624 0 : culist = culist->next;
9625 : }
9626 :
9627 : /* Sort the array according to the offset in the .debug_macinfo
9628 : section. Note we keep the sentinel at the end. */
9629 0 : qsort (cus, nculist, sizeof (*cus), mac_compare);
9630 : }
9631 :
9632 0 : const unsigned char *readp = (const unsigned char *) data->d_buf;
9633 0 : const unsigned char *readendp = readp + data->d_size;
9634 0 : int level = 1;
9635 :
9636 0 : while (readp < readendp)
9637 : {
9638 0 : unsigned int opcode = *readp++;
9639 : unsigned int u128;
9640 : unsigned int u128_2;
9641 : const unsigned char *endp;
9642 :
9643 0 : switch (opcode)
9644 : {
9645 0 : case DW_MACINFO_define:
9646 : case DW_MACINFO_undef:
9647 : case DW_MACINFO_vendor_ext:
9648 : /* For the first two opcodes the parameters are
9649 : line, string
9650 : For the latter
9651 : number, string.
9652 : We can treat these cases together. */
9653 0 : get_uleb128 (u128, readp, readendp);
9654 :
9655 0 : endp = memchr (readp, '\0', readendp - readp);
9656 0 : if (unlikely (endp == NULL))
9657 : {
9658 0 : printf (gettext ("\
9659 : %*s*** non-terminated string at end of section"),
9660 : level, "");
9661 : return;
9662 : }
9663 :
9664 0 : if (opcode == DW_MACINFO_define)
9665 0 : printf ("%*s#define %s, line %u\n",
9666 : level, "", (char *) readp, u128);
9667 0 : else if (opcode == DW_MACINFO_undef)
9668 0 : printf ("%*s#undef %s, line %u\n",
9669 : level, "", (char *) readp, u128);
9670 : else
9671 0 : printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
9672 :
9673 0 : readp = endp + 1;
9674 0 : break;
9675 :
9676 0 : case DW_MACINFO_start_file:
9677 : /* The two parameters are line and file index, in this order. */
9678 0 : get_uleb128 (u128, readp, readendp);
9679 0 : if (readendp - readp < 1)
9680 : {
9681 0 : printf (gettext ("\
9682 : %*s*** missing DW_MACINFO_start_file argument at end of section"),
9683 : level, "");
9684 : return;
9685 : }
9686 0 : get_uleb128 (u128_2, readp, readendp);
9687 :
9688 : /* Find the CU DIE for this file. */
9689 0 : size_t macoff = readp - (const unsigned char *) data->d_buf;
9690 0 : const char *fname = "???";
9691 0 : if (macoff >= cus[0].offset)
9692 : {
9693 0 : while (macoff >= cus[1].offset && cus[1].offset != data->d_size)
9694 0 : ++cus;
9695 :
9696 0 : if (cus[0].files == NULL
9697 0 : && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
9698 0 : cus[0].files = (Dwarf_Files *) -1l;
9699 :
9700 0 : if (cus[0].files != (Dwarf_Files *) -1l)
9701 0 : fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
9702 0 : ?: "???");
9703 : }
9704 :
9705 0 : printf ("%*sstart_file %u, [%u] %s\n",
9706 : level, "", u128, u128_2, fname);
9707 0 : ++level;
9708 0 : break;
9709 :
9710 0 : case DW_MACINFO_end_file:
9711 0 : --level;
9712 : printf ("%*send_file\n", level, "");
9713 : /* Nothing more to do. */
9714 : break;
9715 :
9716 0 : default:
9717 : // XXX gcc seems to generate files with a trailing zero.
9718 0 : if (unlikely (opcode != 0 || readp != readendp))
9719 : printf ("%*s*** invalid opcode %u\n", level, "", opcode);
9720 : break;
9721 : }
9722 : }
9723 : }
9724 :
9725 :
9726 : static void
9727 3 : print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
9728 : Ebl *ebl,
9729 : GElf_Ehdr *ehdr __attribute__ ((unused)),
9730 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
9731 : {
9732 6 : printf (gettext ("\
9733 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
9734 : elf_ndxscn (scn), section_name (ebl, shdr),
9735 3 : (uint64_t) shdr->sh_offset);
9736 6 : putc_unlocked ('\n', stdout);
9737 :
9738 3 : Elf_Data *data = elf_getdata (scn, NULL);
9739 3 : if (unlikely (data == NULL))
9740 : {
9741 0 : error (0, 0, gettext ("cannot get macro information section data: %s"),
9742 : elf_errmsg (-1));
9743 0 : return;
9744 : }
9745 :
9746 : /* Get the source file information for all CUs. Uses same
9747 : datastructure as macinfo. But uses offset field to directly
9748 : match .debug_line offset. And just stored in a list. */
9749 : Dwarf_Off offset;
9750 3 : Dwarf_Off ncu = 0;
9751 : size_t hsize;
9752 3 : struct mac_culist *culist = NULL;
9753 3 : size_t nculist = 0;
9754 10 : while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
9755 : {
9756 : Dwarf_Die cudie;
9757 4 : if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
9758 0 : continue;
9759 :
9760 : Dwarf_Attribute attr;
9761 4 : if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL)
9762 0 : continue;
9763 :
9764 : Dwarf_Word lineoff;
9765 4 : if (dwarf_formudata (&attr, &lineoff) != 0)
9766 0 : continue;
9767 :
9768 4 : struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
9769 4 : newp->die = cudie;
9770 4 : newp->offset = lineoff;
9771 4 : newp->files = NULL;
9772 4 : newp->next = culist;
9773 4 : culist = newp;
9774 4 : ++nculist;
9775 : }
9776 :
9777 3 : const unsigned char *readp = (const unsigned char *) data->d_buf;
9778 3 : const unsigned char *readendp = readp + data->d_size;
9779 :
9780 14 : while (readp < readendp)
9781 : {
9782 16 : printf (gettext (" Offset: 0x%" PRIx64 "\n"),
9783 8 : (uint64_t) (readp - (const unsigned char *) data->d_buf));
9784 :
9785 : // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
9786 : // optional vendor extension macro entry table.
9787 8 : if (readp + 2 > readendp)
9788 : {
9789 0 : invalid_data:
9790 0 : error (0, 0, gettext ("invalid data"));
9791 0 : return;
9792 : }
9793 8 : const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
9794 16 : printf (gettext (" Version: %" PRIu16 "\n"), vers);
9795 :
9796 : // Version 4 is the GNU extension for DWARF4. DWARF5 will use version
9797 : // 5 when it gets standardized.
9798 8 : if (vers != 4 && vers != 5)
9799 : {
9800 0 : printf (gettext (" unknown version, cannot parse section\n"));
9801 : return;
9802 : }
9803 :
9804 8 : if (readp + 1 > readendp)
9805 : goto invalid_data;
9806 8 : const unsigned char flag = *readp++;
9807 16 : printf (gettext (" Flag: 0x%" PRIx8), flag);
9808 8 : if (flag != 0)
9809 : {
9810 4 : printf (" (");
9811 4 : if ((flag & 0x01) != 0)
9812 : {
9813 0 : printf ("offset_size");
9814 0 : if ((flag & 0xFE) != 0)
9815 : printf (", ");
9816 : }
9817 4 : if ((flag & 0x02) != 0)
9818 : {
9819 4 : printf ("debug_line_offset");
9820 4 : if ((flag & 0xFC) != 0)
9821 : printf (", ");
9822 : }
9823 4 : if ((flag & 0x04) != 0)
9824 : {
9825 0 : printf ("operands_table");
9826 0 : if ((flag & 0xF8) != 0)
9827 : printf (", ");
9828 : }
9829 4 : if ((flag & 0xF8) != 0)
9830 : printf ("unknown");
9831 : printf (")");
9832 : }
9833 8 : printf ("\n");
9834 :
9835 8 : unsigned int offset_len = (flag & 0x01) ? 8 : 4;
9836 16 : printf (gettext (" Offset length: %" PRIu8 "\n"), offset_len);
9837 8 : Dwarf_Off line_offset = -1;
9838 8 : if (flag & 0x02)
9839 : {
9840 4 : if (offset_len == 8)
9841 0 : line_offset = read_8ubyte_unaligned_inc (dbg, readp);
9842 : else
9843 4 : line_offset = read_4ubyte_unaligned_inc (dbg, readp);
9844 4 : printf (gettext (" .debug_line offset: 0x%" PRIx64 "\n"),
9845 : line_offset);
9846 : }
9847 :
9848 4 : struct mac_culist *cu = NULL;
9849 4 : if (line_offset != (Dwarf_Off) -1)
9850 : {
9851 : cu = culist;
9852 5 : while (cu != NULL && line_offset != cu->offset)
9853 1 : cu = cu->next;
9854 : }
9855 :
9856 8 : Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, (cu != NULL
9857 : ? cu->die.cu
9858 : : NULL));
9859 :
9860 : const unsigned char *vendor[DW_MACRO_hi_user - DW_MACRO_lo_user + 1];
9861 8 : memset (vendor, 0, sizeof vendor);
9862 8 : if (flag & 0x04)
9863 : {
9864 : // 1 byte length, for each item, 1 byte opcode, uleb128 number
9865 : // of arguments, for each argument 1 byte form code.
9866 0 : if (readp + 1 > readendp)
9867 : goto invalid_data;
9868 0 : unsigned int tlen = *readp++;
9869 0 : printf (gettext (" extension opcode table, %" PRIu8 " items:\n"),
9870 : tlen);
9871 0 : for (unsigned int i = 0; i < tlen; i++)
9872 : {
9873 0 : if (readp + 1 > readendp)
9874 : goto invalid_data;
9875 0 : unsigned int opcode = *readp++;
9876 0 : printf (gettext (" [%" PRIx8 "]"), opcode);
9877 0 : if (opcode < DW_MACRO_lo_user
9878 0 : || opcode > DW_MACRO_hi_user)
9879 : goto invalid_data;
9880 : // Record the start of description for this vendor opcode.
9881 : // uleb128 nr args, 1 byte per arg form.
9882 0 : vendor[opcode - DW_MACRO_lo_user] = readp;
9883 0 : if (readp + 1 > readendp)
9884 : goto invalid_data;
9885 0 : unsigned int args = *readp++;
9886 0 : if (args > 0)
9887 : {
9888 0 : printf (gettext (" %" PRIu8 " arguments:"), args);
9889 0 : while (args > 0)
9890 : {
9891 0 : if (readp + 1 > readendp)
9892 : goto invalid_data;
9893 0 : unsigned int form = *readp++;
9894 0 : printf (" %s", dwarf_form_name (form));
9895 0 : if (! libdw_valid_user_form (form))
9896 : goto invalid_data;
9897 0 : args--;
9898 0 : if (args > 0)
9899 : putchar_unlocked (',');
9900 : }
9901 : }
9902 : else
9903 0 : printf (gettext (" no arguments."));
9904 0 : putchar_unlocked ('\n');
9905 : }
9906 : }
9907 8 : putchar_unlocked ('\n');
9908 :
9909 8 : int level = 1;
9910 8 : if (readp + 1 > readendp)
9911 : goto invalid_data;
9912 8 : unsigned int opcode = *readp++;
9913 743 : while (opcode != 0)
9914 : {
9915 : unsigned int u128;
9916 : unsigned int u128_2;
9917 : const unsigned char *endp;
9918 : uint64_t off;
9919 :
9920 727 : switch (opcode)
9921 : {
9922 6 : case DW_MACRO_start_file:
9923 6 : get_uleb128 (u128, readp, readendp);
9924 6 : if (readp >= readendp)
9925 : goto invalid_data;
9926 6 : get_uleb128 (u128_2, readp, readendp);
9927 :
9928 : /* Find the CU DIE that matches this line offset. */
9929 6 : const char *fname = "???";
9930 6 : if (cu != NULL)
9931 : {
9932 6 : if (cu->files == NULL
9933 4 : && dwarf_getsrcfiles (&cu->die, &cu->files,
9934 : NULL) != 0)
9935 0 : cu->files = (Dwarf_Files *) -1l;
9936 :
9937 6 : if (cu->files != (Dwarf_Files *) -1l)
9938 6 : fname = (dwarf_filesrc (cu->files, u128_2,
9939 6 : NULL, NULL) ?: "???");
9940 : }
9941 6 : printf ("%*sstart_file %u, [%u] %s\n",
9942 : level, "", u128, u128_2, fname);
9943 6 : ++level;
9944 6 : break;
9945 :
9946 6 : case DW_MACRO_end_file:
9947 6 : --level;
9948 : printf ("%*send_file\n", level, "");
9949 : break;
9950 :
9951 1 : case DW_MACRO_define:
9952 1 : get_uleb128 (u128, readp, readendp);
9953 1 : endp = memchr (readp, '\0', readendp - readp);
9954 1 : if (endp == NULL)
9955 : goto invalid_data;
9956 2 : printf ("%*s#define %s, line %u\n",
9957 : level, "", readp, u128);
9958 1 : readp = endp + 1;
9959 1 : break;
9960 :
9961 0 : case DW_MACRO_undef:
9962 0 : get_uleb128 (u128, readp, readendp);
9963 0 : endp = memchr (readp, '\0', readendp - readp);
9964 0 : if (endp == NULL)
9965 : goto invalid_data;
9966 0 : printf ("%*s#undef %s, line %u\n",
9967 : level, "", readp, u128);
9968 0 : readp = endp + 1;
9969 0 : break;
9970 :
9971 707 : case DW_MACRO_define_strp:
9972 707 : get_uleb128 (u128, readp, readendp);
9973 707 : if (readp + offset_len > readendp)
9974 : goto invalid_data;
9975 707 : if (offset_len == 8)
9976 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
9977 : else
9978 707 : off = read_4ubyte_unaligned_inc (dbg, readp);
9979 707 : printf ("%*s#define %s, line %u (indirect)\n",
9980 : level, "", dwarf_getstring (dbg, off, NULL), u128);
9981 : break;
9982 :
9983 1 : case DW_MACRO_undef_strp:
9984 1 : get_uleb128 (u128, readp, readendp);
9985 1 : if (readp + offset_len > readendp)
9986 : goto invalid_data;
9987 1 : if (offset_len == 8)
9988 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
9989 : else
9990 1 : off = read_4ubyte_unaligned_inc (dbg, readp);
9991 1 : printf ("%*s#undef %s, line %u (indirect)\n",
9992 : level, "", dwarf_getstring (dbg, off, NULL), u128);
9993 : break;
9994 :
9995 6 : case DW_MACRO_import:
9996 6 : if (readp + offset_len > readendp)
9997 : goto invalid_data;
9998 6 : if (offset_len == 8)
9999 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
10000 : else
10001 6 : off = read_4ubyte_unaligned_inc (dbg, readp);
10002 : printf ("%*s#include offset 0x%" PRIx64 "\n",
10003 : level, "", off);
10004 : break;
10005 :
10006 0 : case DW_MACRO_define_sup:
10007 0 : get_uleb128 (u128, readp, readendp);
10008 0 : if (readp + offset_len > readendp)
10009 : goto invalid_data;
10010 0 : printf ("%*s#define ", level, "");
10011 0 : readp = print_form_data (dbg, DW_FORM_strp_sup,
10012 : readp, readendp, offset_len,
10013 : str_offsets_base);
10014 : printf (", line %u (sup)\n", u128);
10015 : break;
10016 :
10017 0 : case DW_MACRO_undef_sup:
10018 0 : get_uleb128 (u128, readp, readendp);
10019 0 : if (readp + offset_len > readendp)
10020 : goto invalid_data;
10021 0 : printf ("%*s#undef ", level, "");
10022 0 : readp = print_form_data (dbg, DW_FORM_strp_sup,
10023 : readp, readendp, offset_len,
10024 : str_offsets_base);
10025 : printf (", line %u (sup)\n", u128);
10026 : break;
10027 :
10028 0 : case DW_MACRO_import_sup:
10029 0 : if (readp + offset_len > readendp)
10030 : goto invalid_data;
10031 0 : if (offset_len == 8)
10032 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
10033 : else
10034 0 : off = read_4ubyte_unaligned_inc (dbg, readp);
10035 : // XXX Needs support for reading from supplementary object file.
10036 : printf ("%*s#include offset 0x%" PRIx64 " (sup)\n",
10037 : level, "", off);
10038 : break;
10039 :
10040 0 : case DW_MACRO_define_strx:
10041 0 : get_uleb128 (u128, readp, readendp);
10042 0 : if (readp + offset_len > readendp)
10043 : goto invalid_data;
10044 0 : printf ("%*s#define ", level, "");
10045 0 : readp = print_form_data (dbg, DW_FORM_strx,
10046 : readp, readendp, offset_len,
10047 : str_offsets_base);
10048 : printf (", line %u (strx)\n", u128);
10049 : break;
10050 :
10051 0 : case DW_MACRO_undef_strx:
10052 0 : get_uleb128 (u128, readp, readendp);
10053 0 : if (readp + offset_len > readendp)
10054 : goto invalid_data;
10055 0 : printf ("%*s#undef ", level, "");
10056 0 : readp = print_form_data (dbg, DW_FORM_strx,
10057 : readp, readendp, offset_len,
10058 : str_offsets_base);
10059 : printf (", line %u (strx)\n", u128);
10060 : break;
10061 :
10062 0 : default:
10063 0 : printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
10064 0 : if (opcode < DW_MACRO_lo_user
10065 : || opcode > DW_MACRO_lo_user
10066 0 : || vendor[opcode - DW_MACRO_lo_user] == NULL)
10067 : goto invalid_data;
10068 :
10069 : const unsigned char *op_desc;
10070 0 : op_desc = vendor[opcode - DW_MACRO_lo_user];
10071 :
10072 : // Just skip the arguments, we cannot really interpret them,
10073 : // but print as much as we can.
10074 0 : unsigned int args = *op_desc++;
10075 0 : while (args > 0 && readp < readendp)
10076 0 : {
10077 0 : unsigned int form = *op_desc++;
10078 0 : readp = print_form_data (dbg, form, readp, readendp,
10079 : offset_len, str_offsets_base);
10080 0 : args--;
10081 0 : if (args > 0)
10082 : printf (", ");
10083 : }
10084 : putchar_unlocked ('\n');
10085 : }
10086 :
10087 727 : if (readp + 1 > readendp)
10088 : goto invalid_data;
10089 727 : opcode = *readp++;
10090 727 : if (opcode == 0)
10091 : putchar_unlocked ('\n');
10092 : }
10093 : }
10094 : }
10095 :
10096 :
10097 : /* Callback for printing global names. */
10098 : static int
10099 34 : print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
10100 : void *arg)
10101 : {
10102 34 : int *np = (int *) arg;
10103 :
10104 102 : printf (gettext (" [%5d] DIE offset: %6" PRId64
10105 : ", CU DIE offset: %6" PRId64 ", name: %s\n"),
10106 34 : (*np)++, global->die_offset, global->cu_offset, global->name);
10107 :
10108 34 : return 0;
10109 : }
10110 :
10111 :
10112 : /* Print the known exported symbols in the DWARF section '.debug_pubnames'. */
10113 : static void
10114 8 : print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10115 : Ebl *ebl,
10116 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10117 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10118 : {
10119 16 : printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
10120 : elf_ndxscn (scn), section_name (ebl, shdr),
10121 8 : (uint64_t) shdr->sh_offset);
10122 :
10123 8 : int n = 0;
10124 8 : (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
10125 8 : }
10126 :
10127 : /* Print the content of the DWARF string section '.debug_str'. */
10128 : static void
10129 45 : print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10130 : Ebl *ebl,
10131 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10132 : Elf_Scn *scn, GElf_Shdr *shdr,
10133 : Dwarf *dbg __attribute__ ((unused)))
10134 : {
10135 45 : Elf_Data *data = elf_rawdata (scn, NULL);
10136 45 : const size_t sh_size = data ? data->d_size : 0;
10137 :
10138 : /* Compute floor(log16(shdr->sh_size)). */
10139 45 : GElf_Addr tmp = sh_size;
10140 45 : int digits = 1;
10141 200 : while (tmp >= 16)
10142 : {
10143 110 : ++digits;
10144 110 : tmp >>= 4;
10145 : }
10146 45 : digits = MAX (4, digits);
10147 :
10148 135 : printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
10149 : " %*s String\n"),
10150 : elf_ndxscn (scn),
10151 45 : section_name (ebl, shdr), (uint64_t) shdr->sh_offset,
10152 : /* TRANS: the debugstr| prefix makes the string unique. */
10153 45 : digits + 2, sgettext ("debugstr|Offset"));
10154 :
10155 45 : Dwarf_Off offset = 0;
10156 61203 : while (offset < sh_size)
10157 : {
10158 : size_t len;
10159 61113 : const char *str = (const char *) data->d_buf + offset;
10160 61113 : const char *endp = memchr (str, '\0', sh_size - offset);
10161 61113 : if (unlikely (endp == NULL))
10162 : {
10163 0 : printf (gettext (" *** error, missing string terminator\n"));
10164 : break;
10165 : }
10166 :
10167 61113 : printf (" [%*" PRIx64 "] \"%s\"\n", digits, (uint64_t) offset, str);
10168 61113 : len = endp - str;
10169 61113 : offset += len + 1;
10170 : }
10171 45 : }
10172 :
10173 : static void
10174 4 : print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10175 : Ebl *ebl,
10176 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10177 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10178 : {
10179 8 : printf (gettext ("\
10180 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
10181 : elf_ndxscn (scn), section_name (ebl, shdr),
10182 4 : (uint64_t) shdr->sh_offset);
10183 :
10184 4 : if (shdr->sh_size == 0)
10185 : return;
10186 :
10187 : /* We like to get the section from libdw to make sure they are relocated. */
10188 8 : Elf_Data *data = (dbg->sectiondata[IDX_debug_str_offsets]
10189 4 : ?: elf_rawdata (scn, NULL));
10190 4 : if (unlikely (data == NULL))
10191 : {
10192 0 : error (0, 0, gettext ("cannot get .debug_str_offsets section data: %s"),
10193 : elf_errmsg (-1));
10194 : return;
10195 : }
10196 :
10197 4 : size_t idx = 0;
10198 8 : sort_listptr (&known_stroffbases, "str_offsets");
10199 :
10200 4 : const unsigned char *start = (const unsigned char *) data->d_buf;
10201 4 : const unsigned char *readp = start;
10202 4 : const unsigned char *readendp = ((const unsigned char *) data->d_buf
10203 4 : + data->d_size);
10204 :
10205 12 : while (readp < readendp)
10206 : {
10207 : /* Most string offset tables will have a header. For split
10208 : dwarf unit GNU DebugFission didn't add one. But they were
10209 : also only defined for split units (main or skeleton units
10210 : didn't have indirect strings). So if we don't have a
10211 : DW_AT_str_offsets_base at all and this is offset zero, then
10212 : just start printing offsets immediately, if this is a .dwo
10213 : section. */
10214 4 : Dwarf_Off off = (Dwarf_Off) (readp
10215 4 : - (const unsigned char *) data->d_buf);
10216 :
10217 4 : printf ("Table at offset %" PRIx64 " ", off);
10218 :
10219 4 : struct listptr *listptr = get_listptr (&known_stroffbases, idx++);
10220 0 : const unsigned char *next_unitp = readendp;
10221 : uint8_t offset_size;
10222 : bool has_header;
10223 0 : if (listptr == NULL)
10224 : {
10225 : /* This can happen for .dwo files. There is only an header
10226 : in the case this is a version 5 split DWARF file. */
10227 : Dwarf_CU *cu;
10228 : uint8_t unit_type;
10229 4 : if (dwarf_get_units (dbg, NULL, &cu, NULL, &unit_type,
10230 : NULL, NULL) != 0)
10231 : {
10232 0 : error (0, 0, "Warning: Cannot find any DWARF unit.");
10233 : /* Just guess some values. */
10234 0 : has_header = false;
10235 0 : offset_size = 4;
10236 : }
10237 4 : else if (off == 0
10238 4 : && (unit_type == DW_UT_split_type
10239 4 : || unit_type == DW_UT_split_compile))
10240 : {
10241 4 : has_header = cu->version > 4;
10242 4 : offset_size = cu->offset_size;
10243 : }
10244 : else
10245 : {
10246 0 : error (0, 0,
10247 : "Warning: No CU references .debug_str_offsets after %"
10248 : PRIx64, off);
10249 0 : has_header = cu->version > 4;
10250 0 : offset_size = cu->offset_size;
10251 : }
10252 4 : printf ("\n");
10253 : }
10254 : else
10255 : {
10256 : /* This must be DWARF5, since GNU DebugFission didn't define
10257 : DW_AT_str_offsets_base. */
10258 0 : has_header = true;
10259 :
10260 : Dwarf_Die cudie;
10261 0 : if (dwarf_cu_die (listptr->cu, &cudie,
10262 : NULL, NULL, NULL, NULL,
10263 : NULL, NULL) == NULL)
10264 0 : printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
10265 : else
10266 0 : printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
10267 : }
10268 :
10269 4 : if (has_header)
10270 : {
10271 : uint64_t unit_length;
10272 : uint16_t version;
10273 : uint16_t padding;
10274 :
10275 2 : unit_length = read_4ubyte_unaligned_inc (dbg, readp);
10276 2 : if (unlikely (unit_length == 0xffffffff))
10277 : {
10278 0 : if (unlikely (readp > readendp - 8))
10279 : {
10280 0 : invalid_data:
10281 : error (0, 0, "Invalid data");
10282 : return;
10283 : }
10284 0 : unit_length = read_8ubyte_unaligned_inc (dbg, readp);
10285 0 : offset_size = 8;
10286 : }
10287 : else
10288 : offset_size = 4;
10289 :
10290 2 : printf ("\n");
10291 4 : printf (gettext (" Length: %8" PRIu64 "\n"),
10292 : unit_length);
10293 4 : printf (gettext (" Offset size: %8" PRIu8 "\n"),
10294 : offset_size);
10295 :
10296 : /* We need at least 2-bytes (version) + 2-bytes (padding) =
10297 : 4 bytes to complete the header. And this unit cannot go
10298 : beyond the section data. */
10299 2 : if (readp > readendp - 4
10300 2 : || unit_length < 4
10301 2 : || unit_length > (uint64_t) (readendp - readp))
10302 : goto invalid_data;
10303 :
10304 2 : next_unitp = readp + unit_length;
10305 :
10306 2 : version = read_2ubyte_unaligned_inc (dbg, readp);
10307 4 : printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
10308 :
10309 2 : if (version != 5)
10310 : {
10311 0 : error (0, 0, gettext ("Unknown version"));
10312 : goto next_unit;
10313 : }
10314 :
10315 2 : padding = read_2ubyte_unaligned_inc (dbg, readp);
10316 4 : printf (gettext (" Padding: %8" PRIx16 "\n"), padding);
10317 :
10318 2 : if (listptr != NULL
10319 0 : && listptr->offset != (Dwarf_Off) (readp - start))
10320 : {
10321 : error (0, 0, "String offsets index doesn't start after header");
10322 : goto next_unit;
10323 : }
10324 :
10325 : printf ("\n");
10326 : }
10327 :
10328 4 : int digits = 1;
10329 4 : size_t offsets = (next_unitp - readp) / offset_size;
10330 12 : while (offsets >= 10)
10331 : {
10332 4 : ++digits;
10333 4 : offsets /= 10;
10334 : }
10335 :
10336 4 : unsigned int uidx = 0;
10337 4 : size_t index_offset = readp - (const unsigned char *) data->d_buf;
10338 : printf (" Offsets start at 0x%zx:\n", index_offset);
10339 64 : while (readp <= next_unitp - offset_size)
10340 : {
10341 : Dwarf_Word offset;
10342 60 : if (offset_size == 4)
10343 60 : offset = read_4ubyte_unaligned_inc (dbg, readp);
10344 : else
10345 0 : offset = read_8ubyte_unaligned_inc (dbg, readp);
10346 60 : const char *str = dwarf_getstring (dbg, offset, NULL);
10347 120 : printf (" [%*u] [%*" PRIx64 "] \"%s\"\n",
10348 60 : digits, uidx++, (int) offset_size * 2, offset, str ?: "???");
10349 : }
10350 4 : printf ("\n");
10351 :
10352 4 : if (readp != next_unitp)
10353 0 : error (0, 0, "extra %zd bytes at end of unit",
10354 0 : (size_t) (next_unitp - readp));
10355 :
10356 4 : next_unit:
10357 : readp = next_unitp;
10358 : }
10359 : }
10360 :
10361 :
10362 : /* Print the content of the call frame search table section
10363 : '.eh_frame_hdr'. */
10364 : static void
10365 14 : print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10366 : Ebl *ebl __attribute__ ((unused)),
10367 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10368 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10369 : {
10370 28 : printf (gettext ("\
10371 : \nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
10372 : elf_ndxscn (scn));
10373 :
10374 14 : Elf_Data *data = elf_rawdata (scn, NULL);
10375 :
10376 14 : if (unlikely (data == NULL))
10377 : {
10378 0 : error (0, 0, gettext ("cannot get %s content: %s"),
10379 : ".eh_frame_hdr", elf_errmsg (-1));
10380 0 : return;
10381 : }
10382 :
10383 14 : const unsigned char *readp = data->d_buf;
10384 14 : const unsigned char *const dataend = ((unsigned char *) data->d_buf
10385 14 : + data->d_size);
10386 :
10387 14 : if (unlikely (readp + 4 > dataend))
10388 : {
10389 0 : invalid_data:
10390 0 : error (0, 0, gettext ("invalid data"));
10391 : return;
10392 : }
10393 :
10394 14 : unsigned int version = *readp++;
10395 14 : unsigned int eh_frame_ptr_enc = *readp++;
10396 14 : unsigned int fde_count_enc = *readp++;
10397 14 : unsigned int table_enc = *readp++;
10398 :
10399 14 : printf (" version: %u\n"
10400 : " eh_frame_ptr_enc: %#x ",
10401 : version, eh_frame_ptr_enc);
10402 14 : print_encoding_base ("", eh_frame_ptr_enc);
10403 14 : printf (" fde_count_enc: %#x ", fde_count_enc);
10404 14 : print_encoding_base ("", fde_count_enc);
10405 14 : printf (" table_enc: %#x ", table_enc);
10406 14 : print_encoding_base ("", table_enc);
10407 :
10408 14 : uint64_t eh_frame_ptr = 0;
10409 14 : if (eh_frame_ptr_enc != DW_EH_PE_omit)
10410 : {
10411 14 : readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
10412 : dbg);
10413 14 : if (unlikely (readp == NULL))
10414 : goto invalid_data;
10415 :
10416 28 : printf (" eh_frame_ptr: %#" PRIx64, eh_frame_ptr);
10417 14 : if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
10418 14 : printf (" (offset: %#" PRIx64 ")",
10419 : /* +4 because of the 4 byte header of the section. */
10420 14 : (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
10421 :
10422 : putchar_unlocked ('\n');
10423 : }
10424 :
10425 14 : uint64_t fde_count = 0;
10426 14 : if (fde_count_enc != DW_EH_PE_omit)
10427 : {
10428 14 : readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
10429 14 : if (unlikely (readp == NULL))
10430 : goto invalid_data;
10431 :
10432 14 : printf (" fde_count: %" PRIu64 "\n", fde_count);
10433 : }
10434 :
10435 14 : if (fde_count == 0 || table_enc == DW_EH_PE_omit)
10436 : return;
10437 :
10438 14 : puts (" Table:");
10439 :
10440 : /* Optimize for the most common case. */
10441 14 : if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
10442 4420 : while (fde_count > 0 && readp + 8 <= dataend)
10443 : {
10444 4406 : int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
10445 8812 : uint64_t initial_offset = ((uint64_t) shdr->sh_offset
10446 4406 : + (int64_t) initial_location);
10447 4406 : int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
10448 : // XXX Possibly print symbol name or section offset for initial_offset
10449 4406 : printf (" %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
10450 : " fde=[%6" PRIx64 "]\n",
10451 : initial_location, initial_offset,
10452 4406 : address, address - (eh_frame_ptr + 4));
10453 : }
10454 : else
10455 : while (0 && readp < dataend)
10456 : {
10457 :
10458 : }
10459 : }
10460 :
10461 :
10462 : /* Print the content of the exception handling table section
10463 : '.eh_frame_hdr'. */
10464 : static void
10465 0 : print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
10466 : Ebl *ebl __attribute__ ((unused)),
10467 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10468 : Elf_Scn *scn,
10469 : GElf_Shdr *shdr __attribute__ ((unused)),
10470 : Dwarf *dbg __attribute__ ((unused)))
10471 : {
10472 0 : printf (gettext ("\
10473 : \nException handling table section [%2zu] '.gcc_except_table':\n"),
10474 : elf_ndxscn (scn));
10475 :
10476 0 : Elf_Data *data = elf_rawdata (scn, NULL);
10477 :
10478 0 : if (unlikely (data == NULL))
10479 : {
10480 0 : error (0, 0, gettext ("cannot get %s content: %s"),
10481 : ".gcc_except_table", elf_errmsg (-1));
10482 0 : return;
10483 : }
10484 :
10485 0 : const unsigned char *readp = data->d_buf;
10486 0 : const unsigned char *const dataend = readp + data->d_size;
10487 :
10488 0 : if (unlikely (readp + 1 > dataend))
10489 : {
10490 0 : invalid_data:
10491 0 : error (0, 0, gettext ("invalid data"));
10492 : return;
10493 : }
10494 0 : unsigned int lpstart_encoding = *readp++;
10495 0 : printf (gettext (" LPStart encoding: %#x "), lpstart_encoding);
10496 0 : print_encoding_base ("", lpstart_encoding);
10497 0 : if (lpstart_encoding != DW_EH_PE_omit)
10498 : {
10499 : uint64_t lpstart;
10500 0 : readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
10501 0 : printf (" LPStart: %#" PRIx64 "\n", lpstart);
10502 : }
10503 :
10504 0 : if (unlikely (readp + 1 > dataend))
10505 : goto invalid_data;
10506 0 : unsigned int ttype_encoding = *readp++;
10507 0 : printf (gettext (" TType encoding: %#x "), ttype_encoding);
10508 0 : print_encoding_base ("", ttype_encoding);
10509 0 : const unsigned char *ttype_base = NULL;
10510 0 : if (ttype_encoding != DW_EH_PE_omit)
10511 : {
10512 : unsigned int ttype_base_offset;
10513 0 : get_uleb128 (ttype_base_offset, readp, dataend);
10514 0 : printf (" TType base offset: %#x\n", ttype_base_offset);
10515 0 : if ((size_t) (dataend - readp) > ttype_base_offset)
10516 0 : ttype_base = readp + ttype_base_offset;
10517 : }
10518 :
10519 0 : if (unlikely (readp + 1 > dataend))
10520 : goto invalid_data;
10521 0 : unsigned int call_site_encoding = *readp++;
10522 0 : printf (gettext (" Call site encoding: %#x "), call_site_encoding);
10523 0 : print_encoding_base ("", call_site_encoding);
10524 : unsigned int call_site_table_len;
10525 0 : get_uleb128 (call_site_table_len, readp, dataend);
10526 :
10527 0 : const unsigned char *const action_table = readp + call_site_table_len;
10528 0 : if (unlikely (action_table > dataend))
10529 : goto invalid_data;
10530 : unsigned int u = 0;
10531 : unsigned int max_action = 0;
10532 0 : while (readp < action_table)
10533 : {
10534 0 : if (u == 0)
10535 0 : puts (gettext ("\n Call site table:"));
10536 :
10537 : uint64_t call_site_start;
10538 0 : readp = read_encoded (call_site_encoding, readp, dataend,
10539 : &call_site_start, dbg);
10540 : uint64_t call_site_length;
10541 0 : readp = read_encoded (call_site_encoding, readp, dataend,
10542 : &call_site_length, dbg);
10543 : uint64_t landing_pad;
10544 0 : readp = read_encoded (call_site_encoding, readp, dataend,
10545 : &landing_pad, dbg);
10546 : unsigned int action;
10547 0 : get_uleb128 (action, readp, dataend);
10548 0 : max_action = MAX (action, max_action);
10549 0 : printf (gettext (" [%4u] Call site start: %#" PRIx64 "\n"
10550 : " Call site length: %" PRIu64 "\n"
10551 : " Landing pad: %#" PRIx64 "\n"
10552 : " Action: %u\n"),
10553 : u++, call_site_start, call_site_length, landing_pad, action);
10554 : }
10555 0 : if (readp != action_table)
10556 : goto invalid_data;
10557 :
10558 0 : unsigned int max_ar_filter = 0;
10559 0 : if (max_action > 0)
10560 : {
10561 0 : puts ("\n Action table:");
10562 :
10563 0 : size_t maxdata = (size_t) (dataend - action_table);
10564 0 : if (max_action > maxdata || maxdata - max_action < 1)
10565 : {
10566 0 : invalid_action_table:
10567 0 : fputs (gettext (" <INVALID DATA>\n"), stdout);
10568 0 : return;
10569 : }
10570 :
10571 0 : const unsigned char *const action_table_end
10572 0 : = action_table + max_action + 1;
10573 :
10574 0 : u = 0;
10575 : do
10576 : {
10577 : int ar_filter;
10578 0 : get_sleb128 (ar_filter, readp, action_table_end);
10579 0 : if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
10580 0 : max_ar_filter = ar_filter;
10581 : int ar_disp;
10582 0 : if (readp >= action_table_end)
10583 : goto invalid_action_table;
10584 0 : get_sleb128 (ar_disp, readp, action_table_end);
10585 :
10586 0 : printf (" [%4u] ar_filter: % d\n"
10587 : " ar_disp: % -5d",
10588 : u, ar_filter, ar_disp);
10589 0 : if (abs (ar_disp) & 1)
10590 0 : printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
10591 0 : else if (ar_disp != 0)
10592 0 : puts (" -> ???");
10593 : else
10594 : putchar_unlocked ('\n');
10595 0 : ++u;
10596 : }
10597 0 : while (readp < action_table_end);
10598 : }
10599 :
10600 0 : if (max_ar_filter > 0 && ttype_base != NULL)
10601 : {
10602 : unsigned char dsize;
10603 0 : puts ("\n TType table:");
10604 :
10605 : // XXX Not *4, size of encoding;
10606 : switch (ttype_encoding & 7)
10607 : {
10608 : case DW_EH_PE_udata2:
10609 : case DW_EH_PE_sdata2:
10610 : dsize = 2;
10611 : break;
10612 : case DW_EH_PE_udata4:
10613 : case DW_EH_PE_sdata4:
10614 : dsize = 4;
10615 : break;
10616 : case DW_EH_PE_udata8:
10617 : case DW_EH_PE_sdata8:
10618 : dsize = 8;
10619 : break;
10620 0 : default:
10621 0 : dsize = 0;
10622 0 : error (1, 0, gettext ("invalid TType encoding"));
10623 : }
10624 :
10625 0 : if (max_ar_filter
10626 0 : > (size_t) (ttype_base - (const unsigned char *) data->d_buf) / dsize)
10627 : goto invalid_data;
10628 :
10629 0 : readp = ttype_base - max_ar_filter * dsize;
10630 : do
10631 : {
10632 : uint64_t ttype;
10633 0 : readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
10634 : dbg);
10635 0 : printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
10636 : }
10637 0 : while (readp < ttype_base);
10638 : }
10639 : }
10640 :
10641 : /* Print the content of the '.gdb_index' section.
10642 : http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
10643 : */
10644 : static void
10645 2 : print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
10646 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10647 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10648 : {
10649 4 : printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
10650 : " contains %" PRId64 " bytes :\n"),
10651 : elf_ndxscn (scn), section_name (ebl, shdr),
10652 2 : (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
10653 :
10654 2 : Elf_Data *data = elf_rawdata (scn, NULL);
10655 :
10656 2 : if (unlikely (data == NULL))
10657 : {
10658 0 : error (0, 0, gettext ("cannot get %s content: %s"),
10659 : ".gdb_index", elf_errmsg (-1));
10660 0 : return;
10661 : }
10662 :
10663 : // .gdb_index is always in little endian.
10664 2 : Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
10665 2 : dbg = &dummy_dbg;
10666 :
10667 2 : const unsigned char *readp = data->d_buf;
10668 2 : const unsigned char *const dataend = readp + data->d_size;
10669 :
10670 2 : if (unlikely (readp + 4 > dataend))
10671 : {
10672 0 : invalid_data:
10673 0 : error (0, 0, gettext ("invalid data"));
10674 : return;
10675 : }
10676 :
10677 2 : int32_t vers = read_4ubyte_unaligned (dbg, readp);
10678 4 : printf (gettext (" Version: %" PRId32 "\n"), vers);
10679 :
10680 : // The only difference between version 4 and version 5 is the
10681 : // hash used for generating the table. Version 6 contains symbols
10682 : // for inlined functions, older versions didn't. Version 7 adds
10683 : // symbol kinds. Version 8 just indicates that it correctly includes
10684 : // TUs for symbols.
10685 2 : if (vers < 4 || vers > 8)
10686 : {
10687 0 : printf (gettext (" unknown version, cannot parse section\n"));
10688 : return;
10689 : }
10690 :
10691 2 : readp += 4;
10692 2 : if (unlikely (readp + 4 > dataend))
10693 : goto invalid_data;
10694 :
10695 2 : uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
10696 4 : printf (gettext (" CU offset: %#" PRIx32 "\n"), cu_off);
10697 :
10698 2 : readp += 4;
10699 2 : if (unlikely (readp + 4 > dataend))
10700 : goto invalid_data;
10701 :
10702 2 : uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
10703 4 : printf (gettext (" TU offset: %#" PRIx32 "\n"), tu_off);
10704 :
10705 2 : readp += 4;
10706 2 : if (unlikely (readp + 4 > dataend))
10707 : goto invalid_data;
10708 :
10709 2 : uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
10710 4 : printf (gettext (" address offset: %#" PRIx32 "\n"), addr_off);
10711 :
10712 2 : readp += 4;
10713 2 : if (unlikely (readp + 4 > dataend))
10714 : goto invalid_data;
10715 :
10716 2 : uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
10717 4 : printf (gettext (" symbol offset: %#" PRIx32 "\n"), sym_off);
10718 :
10719 2 : readp += 4;
10720 2 : if (unlikely (readp + 4 > dataend))
10721 : goto invalid_data;
10722 :
10723 2 : uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
10724 4 : printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
10725 :
10726 2 : if (unlikely ((size_t) (dataend - (const unsigned char *) data->d_buf)
10727 : < const_off))
10728 : goto invalid_data;
10729 :
10730 2 : readp = data->d_buf + cu_off;
10731 :
10732 2 : const unsigned char *nextp = data->d_buf + tu_off;
10733 2 : if (tu_off >= data->d_size)
10734 : goto invalid_data;
10735 :
10736 2 : size_t cu_nr = (nextp - readp) / 16;
10737 :
10738 4 : printf (gettext ("\n CU list at offset %#" PRIx32
10739 : " contains %zu entries:\n"),
10740 : cu_off, cu_nr);
10741 :
10742 2 : size_t n = 0;
10743 8 : while (dataend - readp >= 16 && n < cu_nr)
10744 : {
10745 4 : uint64_t off = read_8ubyte_unaligned (dbg, readp);
10746 4 : readp += 8;
10747 :
10748 4 : uint64_t len = read_8ubyte_unaligned (dbg, readp);
10749 4 : readp += 8;
10750 :
10751 4 : printf (" [%4zu] start: %0#8" PRIx64
10752 : ", length: %5" PRIu64 "\n", n, off, len);
10753 4 : n++;
10754 : }
10755 :
10756 2 : readp = data->d_buf + tu_off;
10757 2 : nextp = data->d_buf + addr_off;
10758 2 : if (addr_off >= data->d_size)
10759 : goto invalid_data;
10760 :
10761 2 : size_t tu_nr = (nextp - readp) / 24;
10762 :
10763 4 : printf (gettext ("\n TU list at offset %#" PRIx32
10764 : " contains %zu entries:\n"),
10765 : tu_off, tu_nr);
10766 :
10767 2 : n = 0;
10768 6 : while (dataend - readp >= 24 && n < tu_nr)
10769 : {
10770 2 : uint64_t off = read_8ubyte_unaligned (dbg, readp);
10771 2 : readp += 8;
10772 :
10773 2 : uint64_t type = read_8ubyte_unaligned (dbg, readp);
10774 2 : readp += 8;
10775 :
10776 2 : uint64_t sig = read_8ubyte_unaligned (dbg, readp);
10777 2 : readp += 8;
10778 :
10779 2 : printf (" [%4zu] CU offset: %5" PRId64
10780 : ", type offset: %5" PRId64
10781 : ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
10782 2 : n++;
10783 : }
10784 :
10785 2 : readp = data->d_buf + addr_off;
10786 2 : nextp = data->d_buf + sym_off;
10787 2 : if (sym_off >= data->d_size)
10788 : goto invalid_data;
10789 :
10790 2 : size_t addr_nr = (nextp - readp) / 20;
10791 :
10792 4 : printf (gettext ("\n Address list at offset %#" PRIx32
10793 : " contains %zu entries:\n"),
10794 : addr_off, addr_nr);
10795 :
10796 2 : n = 0;
10797 8 : while (dataend - readp >= 20 && n < addr_nr)
10798 : {
10799 4 : uint64_t low = read_8ubyte_unaligned (dbg, readp);
10800 4 : readp += 8;
10801 :
10802 4 : uint64_t high = read_8ubyte_unaligned (dbg, readp);
10803 4 : readp += 8;
10804 :
10805 4 : uint32_t idx = read_4ubyte_unaligned (dbg, readp);
10806 4 : readp += 4;
10807 :
10808 4 : printf (" [%4zu] ", n);
10809 4 : print_dwarf_addr (dwflmod, 8, low, low);
10810 4 : printf ("..");
10811 4 : print_dwarf_addr (dwflmod, 8, high - 1, high);
10812 4 : printf (", CU index: %5" PRId32 "\n", idx);
10813 4 : n++;
10814 : }
10815 :
10816 2 : const unsigned char *const_start = data->d_buf + const_off;
10817 2 : if (const_off >= data->d_size)
10818 : goto invalid_data;
10819 :
10820 2 : readp = data->d_buf + sym_off;
10821 2 : nextp = const_start;
10822 2 : size_t sym_nr = (nextp - readp) / 8;
10823 :
10824 4 : printf (gettext ("\n Symbol table at offset %#" PRIx32
10825 : " contains %zu slots:\n"),
10826 : addr_off, sym_nr);
10827 :
10828 2 : n = 0;
10829 2052 : while (dataend - readp >= 8 && n < sym_nr)
10830 : {
10831 2048 : uint32_t name = read_4ubyte_unaligned (dbg, readp);
10832 2048 : readp += 4;
10833 :
10834 2048 : uint32_t vector = read_4ubyte_unaligned (dbg, readp);
10835 2048 : readp += 4;
10836 :
10837 2048 : if (name != 0 || vector != 0)
10838 : {
10839 14 : const unsigned char *sym = const_start + name;
10840 28 : if (unlikely ((size_t) (dataend - const_start) < name
10841 : || memchr (sym, '\0', dataend - sym) == NULL))
10842 : goto invalid_data;
10843 :
10844 14 : printf (" [%4zu] symbol: %s, CUs: ", n, sym);
10845 :
10846 14 : const unsigned char *readcus = const_start + vector;
10847 14 : if (unlikely ((size_t) (dataend - const_start) < vector))
10848 : goto invalid_data;
10849 14 : uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
10850 44 : while (cus--)
10851 : {
10852 : uint32_t cu_kind, cu, kind;
10853 : bool is_static;
10854 16 : readcus += 4;
10855 16 : if (unlikely (readcus + 4 > dataend))
10856 : goto invalid_data;
10857 16 : cu_kind = read_4ubyte_unaligned (dbg, readcus);
10858 16 : cu = cu_kind & ((1 << 24) - 1);
10859 16 : kind = (cu_kind >> 28) & 7;
10860 16 : is_static = cu_kind & (1U << 31);
10861 16 : if (cu > cu_nr - 1)
10862 2 : printf ("%" PRId32 "T", cu - (uint32_t) cu_nr);
10863 : else
10864 : printf ("%" PRId32, cu);
10865 16 : if (kind != 0)
10866 : {
10867 8 : printf (" (");
10868 8 : switch (kind)
10869 : {
10870 3 : case 1:
10871 : printf ("type");
10872 : break;
10873 2 : case 2:
10874 : printf ("var");
10875 : break;
10876 3 : case 3:
10877 : printf ("func");
10878 : break;
10879 0 : case 4:
10880 : printf ("other");
10881 : break;
10882 0 : default:
10883 : printf ("unknown-0x%" PRIx32, kind);
10884 : break;
10885 : }
10886 8 : printf (":%c)", (is_static ? 'S' : 'G'));
10887 : }
10888 16 : if (cus > 0)
10889 : printf (", ");
10890 : }
10891 : printf ("\n");
10892 : }
10893 2048 : n++;
10894 : }
10895 : }
10896 :
10897 : /* Returns true and sets split DWARF CU id if there is a split compile
10898 : unit in the given Dwarf, and no non-split units are found (before it). */
10899 : static bool
10900 117 : is_split_dwarf (Dwarf *dbg, uint64_t *id, Dwarf_CU **split_cu)
10901 : {
10902 117 : Dwarf_CU *cu = NULL;
10903 234 : while (dwarf_get_units (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
10904 : {
10905 : uint8_t unit_type;
10906 117 : if (dwarf_cu_info (cu, NULL, &unit_type, NULL, NULL,
10907 : id, NULL, NULL) != 0)
10908 117 : return false;
10909 :
10910 117 : if (unit_type != DW_UT_split_compile && unit_type != DW_UT_split_type)
10911 : return false;
10912 :
10913 : /* We really only care about the split compile unit, the types
10914 : should be fine and self sufficient. Also they don't have an
10915 : id that we can match with a skeleton unit. */
10916 9 : if (unit_type == DW_UT_split_compile)
10917 : {
10918 9 : *split_cu = cu;
10919 9 : return true;
10920 : }
10921 : }
10922 :
10923 : return false;
10924 : }
10925 :
10926 : /* Check that there is one and only one Dwfl_Module, return in arg. */
10927 : static int
10928 9 : getone_dwflmod (Dwfl_Module *dwflmod,
10929 : void **userdata __attribute__ ((unused)),
10930 : const char *name __attribute__ ((unused)),
10931 : Dwarf_Addr base __attribute__ ((unused)),
10932 : void *arg)
10933 : {
10934 9 : Dwfl_Module **m = (Dwfl_Module **) arg;
10935 9 : if (*m != NULL)
10936 : return DWARF_CB_ABORT;
10937 9 : *m = dwflmod;
10938 9 : return DWARF_CB_OK;
10939 : }
10940 :
10941 : static void
10942 145 : print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
10943 : {
10944 : /* Used for skeleton file, if necessary for split DWARF. */
10945 145 : Dwfl *skel_dwfl = NULL;
10946 145 : Dwfl_Module *skel_mod = NULL;
10947 145 : char *skel_name = NULL;
10948 145 : Dwarf *split_dbg = NULL;
10949 145 : Dwarf_CU *split_cu = NULL;
10950 :
10951 : /* Before we start the real work get a debug context descriptor. */
10952 : Dwarf_Addr dwbias;
10953 145 : Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
10954 435 : Dwarf dummy_dbg =
10955 : {
10956 145 : .elf = ebl->elf,
10957 145 : .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
10958 : };
10959 145 : if (dbg == NULL)
10960 : {
10961 28 : if ((print_debug_sections & ~section_exception) != 0)
10962 0 : error (0, 0, gettext ("cannot get debug context descriptor: %s"),
10963 : dwfl_errmsg (-1));
10964 : dbg = &dummy_dbg;
10965 : }
10966 : else
10967 : {
10968 : /* If we are asked about a split dwarf (.dwo) file, use the user
10969 : provided, or find the corresponding skeleton file. If we got
10970 : a skeleton file, replace the given dwflmod and dbg, with one
10971 : derived from the skeleton file to provide enough context. */
10972 : uint64_t split_id;
10973 117 : if (is_split_dwarf (dbg, &split_id, &split_cu))
10974 : {
10975 9 : if (dwarf_skeleton != NULL)
10976 9 : skel_name = strdup (dwarf_skeleton);
10977 : else
10978 : {
10979 : /* Replace file.dwo with file.o and see if that matches. */
10980 : const char *fname;
10981 0 : dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL,
10982 : &fname, NULL);
10983 0 : if (fname != NULL)
10984 : {
10985 0 : size_t flen = strlen (fname);
10986 0 : if (flen > 4 && strcmp (".dwo", fname + flen - 4) == 0)
10987 : {
10988 0 : skel_name = strdup (fname);
10989 0 : if (skel_name != NULL)
10990 : {
10991 0 : skel_name[flen - 3] = 'o';
10992 0 : skel_name[flen - 2] = '\0';
10993 : }
10994 : }
10995 : }
10996 : }
10997 :
10998 9 : if (skel_name != NULL)
10999 : {
11000 9 : int skel_fd = open (skel_name, O_RDONLY);
11001 9 : if (skel_fd == -1)
11002 0 : fprintf (stderr, "Warning: Couldn't open DWARF skeleton file"
11003 : " '%s'\n", skel_name);
11004 : else
11005 9 : skel_dwfl = create_dwfl (skel_fd, skel_name);
11006 :
11007 9 : if (skel_dwfl != NULL)
11008 : {
11009 9 : if (dwfl_getmodules (skel_dwfl, &getone_dwflmod,
11010 : &skel_mod, 0) != 0)
11011 : {
11012 0 : fprintf (stderr, "Warning: Bad DWARF skeleton,"
11013 : " multiple modules '%s'\n", skel_name);
11014 0 : dwfl_end (skel_dwfl);
11015 0 : skel_mod = NULL;
11016 : }
11017 : }
11018 0 : else if (skel_fd != -1)
11019 0 : fprintf (stderr, "Warning: Couldn't create skeleton dwfl for"
11020 : " '%s': %s\n", skel_name, dwfl_errmsg (-1));
11021 :
11022 9 : if (skel_mod != NULL)
11023 : {
11024 9 : Dwarf *skel_dbg = dwfl_module_getdwarf (skel_mod, &dwbias);
11025 9 : if (skel_dbg != NULL)
11026 : {
11027 : /* First check the skeleton CU DIE, only fetch
11028 : the split DIE if we know the id matches to
11029 : not unnecessary search for any split DIEs we
11030 : don't need. */
11031 9 : Dwarf_CU *cu = NULL;
11032 22 : while (dwarf_get_units (skel_dbg, cu, &cu,
11033 : NULL, NULL, NULL, NULL) == 0)
11034 : {
11035 : uint8_t unit_type;
11036 : uint64_t skel_id;
11037 13 : if (dwarf_cu_info (cu, NULL, &unit_type, NULL, NULL,
11038 : &skel_id, NULL, NULL) == 0
11039 13 : && unit_type == DW_UT_skeleton
11040 13 : && split_id == skel_id)
11041 : {
11042 : Dwarf_Die subdie;
11043 9 : if (dwarf_cu_info (cu, NULL, NULL, NULL,
11044 : &subdie,
11045 : NULL, NULL, NULL) == 0
11046 9 : && dwarf_tag (&subdie) != DW_TAG_invalid)
11047 : {
11048 9 : split_dbg = dwarf_cu_getdwarf (subdie.cu);
11049 9 : if (split_dbg == NULL)
11050 0 : fprintf (stderr,
11051 : "Warning: Couldn't get split_dbg:"
11052 : " %s\n", dwarf_errmsg (-1));
11053 9 : break;
11054 : }
11055 : else
11056 : {
11057 : /* Everything matches up, but not
11058 : according to libdw. Which means
11059 : the user knew better. So...
11060 : Terrible hack... We can never
11061 : destroy the underlying dwfl
11062 : because it would free the wrong
11063 : Dwarfs... So we leak memory...*/
11064 0 : if (cu->split == NULL
11065 0 : && dwarf_skeleton != NULL)
11066 : {
11067 0 : do_not_close_dwfl = true;
11068 0 : __libdw_link_skel_split (cu, split_cu);
11069 0 : split_dbg = dwarf_cu_getdwarf (split_cu);
11070 0 : break;
11071 : }
11072 : else
11073 0 : fprintf (stderr, "Warning: Couldn't get"
11074 : " skeleton subdie: %s\n",
11075 : dwarf_errmsg (-1));
11076 : }
11077 : }
11078 : }
11079 9 : if (split_dbg == NULL)
11080 0 : fprintf (stderr, "Warning: '%s' didn't contain a skeleton for split id %" PRIx64 "\n", skel_name, split_id);
11081 : }
11082 : else
11083 0 : fprintf (stderr, "Warning: Couldn't get skeleton DWARF:"
11084 : " %s\n", dwfl_errmsg (-1));
11085 : }
11086 : }
11087 :
11088 9 : if (split_dbg != NULL)
11089 : {
11090 9 : dbg = split_dbg;
11091 9 : dwflmod = skel_mod;
11092 : }
11093 0 : else if (skel_name == NULL)
11094 0 : fprintf (stderr,
11095 : "Warning: split DWARF file, but no skeleton found.\n");
11096 : }
11097 108 : else if (dwarf_skeleton != NULL)
11098 0 : fprintf (stderr, "Warning: DWARF skeleton given,"
11099 : " but not a split DWARF file\n");
11100 : }
11101 :
11102 : /* Get the section header string table index. */
11103 : size_t shstrndx;
11104 145 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
11105 : error (EXIT_FAILURE, 0,
11106 0 : gettext ("cannot get section header string table index"));
11107 :
11108 : /* If the .debug_info section is listed as implicitly required then
11109 : we must make sure to handle it before handling any other debug
11110 : section. Various other sections depend on the CU DIEs being
11111 : scanned (silently) first. */
11112 145 : bool implicit_info = (implicit_debug_sections & section_info) != 0;
11113 145 : bool explicit_info = (print_debug_sections & section_info) != 0;
11114 145 : if (implicit_info)
11115 : {
11116 : Elf_Scn *scn = NULL;
11117 1514 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
11118 : {
11119 : GElf_Shdr shdr_mem;
11120 1514 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
11121 :
11122 1514 : if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
11123 : {
11124 620 : const char *name = elf_strptr (ebl->elf, shstrndx,
11125 620 : shdr->sh_name);
11126 620 : if (name == NULL)
11127 0 : continue;
11128 :
11129 620 : if (strcmp (name, ".debug_info") == 0
11130 558 : || strcmp (name, ".debug_info.dwo") == 0
11131 549 : || strcmp (name, ".zdebug_info") == 0
11132 543 : || strcmp (name, ".zdebug_info.dwo") == 0)
11133 : {
11134 77 : print_debug_info_section (dwflmod, ebl, ehdr,
11135 : scn, shdr, dbg);
11136 77 : break;
11137 : }
11138 : }
11139 : }
11140 77 : print_debug_sections &= ~section_info;
11141 77 : implicit_debug_sections &= ~section_info;
11142 : }
11143 :
11144 : /* Look through all the sections for the debugging sections to print. */
11145 : Elf_Scn *scn = NULL;
11146 4398 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
11147 : {
11148 : GElf_Shdr shdr_mem;
11149 4253 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
11150 :
11151 4253 : if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
11152 : {
11153 : static const struct
11154 : {
11155 : const char *name;
11156 : enum section_e bitmask;
11157 : void (*fp) (Dwfl_Module *, Ebl *,
11158 : GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
11159 : } debug_sections[] =
11160 : {
11161 : #define NEW_SECTION(name) \
11162 : { ".debug_" #name, section_##name, print_debug_##name##_section }
11163 : NEW_SECTION (abbrev),
11164 : NEW_SECTION (addr),
11165 : NEW_SECTION (aranges),
11166 : NEW_SECTION (frame),
11167 : NEW_SECTION (info),
11168 : NEW_SECTION (types),
11169 : NEW_SECTION (line),
11170 : NEW_SECTION (loc),
11171 : /* loclists is loc for DWARF5. */
11172 : { ".debug_loclists", section_loc,
11173 : print_debug_loclists_section },
11174 : NEW_SECTION (pubnames),
11175 : NEW_SECTION (str),
11176 : /* A DWARF5 specialised debug string section. */
11177 : { ".debug_line_str", section_str,
11178 : print_debug_str_section },
11179 : /* DWARF5 string offsets table. */
11180 : { ".debug_str_offsets", section_str,
11181 : print_debug_str_offsets_section },
11182 : NEW_SECTION (macinfo),
11183 : NEW_SECTION (macro),
11184 : NEW_SECTION (ranges),
11185 : /* rnglists is ranges for DWARF5. */
11186 : { ".debug_rnglists", section_ranges,
11187 : print_debug_rnglists_section },
11188 : { ".eh_frame", section_frame | section_exception,
11189 : print_debug_frame_section },
11190 : { ".eh_frame_hdr", section_frame | section_exception,
11191 : print_debug_frame_hdr_section },
11192 : { ".gcc_except_table", section_frame | section_exception,
11193 : print_debug_exception_table },
11194 : { ".gdb_index", section_gdb_index, print_gdb_index_section }
11195 : };
11196 2073 : const int ndebug_sections = (sizeof (debug_sections)
11197 : / sizeof (debug_sections[0]));
11198 2073 : const char *name = elf_strptr (ebl->elf, shstrndx,
11199 2073 : shdr->sh_name);
11200 2073 : if (name == NULL)
11201 0 : continue;
11202 :
11203 : int n;
11204 30604 : for (n = 0; n < ndebug_sections; ++n)
11205 : {
11206 31566 : size_t dbglen = strlen (debug_sections[n].name);
11207 31566 : size_t scnlen = strlen (name);
11208 31566 : if ((strncmp (name, debug_sections[n].name, dbglen) == 0
11209 964 : && (dbglen == scnlen
11210 138 : || (scnlen == dbglen + 4
11211 121 : && strstr (name, ".dwo") == name + dbglen)))
11212 30686 : || (name[0] == '.' && name[1] == 'z'
11213 566 : && debug_sections[n].name[1] == 'd'
11214 566 : && strncmp (&name[2], &debug_sections[n].name[1],
11215 : dbglen - 1) == 0
11216 82 : && (scnlen == dbglen + 1
11217 0 : || (scnlen == dbglen + 5
11218 0 : && strstr (name, ".dwo") == name + dbglen + 1))))
11219 : {
11220 1924 : if ((print_debug_sections | implicit_debug_sections)
11221 962 : & debug_sections[n].bitmask)
11222 357 : debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
11223 : break;
11224 : }
11225 : }
11226 : }
11227 : }
11228 :
11229 145 : dwfl_end (skel_dwfl);
11230 145 : free (skel_name);
11231 :
11232 : /* Turn implicit and/or explicit back on in case we go over another file. */
11233 145 : if (implicit_info)
11234 77 : implicit_debug_sections |= section_info;
11235 145 : if (explicit_info)
11236 59 : print_debug_sections |= section_info;
11237 :
11238 145 : reset_listptr (&known_locsptr);
11239 145 : reset_listptr (&known_loclistsptr);
11240 145 : reset_listptr (&known_rangelistptr);
11241 145 : reset_listptr (&known_rnglistptr);
11242 145 : reset_listptr (&known_addrbases);
11243 145 : reset_listptr (&known_stroffbases);
11244 145 : }
11245 :
11246 :
11247 : #define ITEM_INDENT 4
11248 : #define WRAP_COLUMN 75
11249 :
11250 : /* Print "NAME: FORMAT", wrapping when output text would make the line
11251 : exceed WRAP_COLUMN. Unpadded numbers look better for the core items
11252 : but this function is also used for registers which should be printed
11253 : aligned. Fortunately registers output uses fixed fields width (such
11254 : as %11d) for the alignment.
11255 :
11256 : Line breaks should not depend on the particular values although that
11257 : may happen in some cases of the core items. */
11258 :
11259 : static unsigned int
11260 : __attribute__ ((format (printf, 6, 7)))
11261 821 : print_core_item (unsigned int colno, char sep, unsigned int wrap,
11262 : size_t name_width, const char *name, const char *format, ...)
11263 : {
11264 821 : size_t len = strlen (name);
11265 821 : if (name_width < len)
11266 397 : name_width = len;
11267 :
11268 : char *out;
11269 : va_list ap;
11270 821 : va_start (ap, format);
11271 821 : int out_len = vasprintf (&out, format, ap);
11272 821 : va_end (ap);
11273 821 : if (out_len == -1)
11274 0 : error (EXIT_FAILURE, 0, _("memory exhausted"));
11275 :
11276 821 : size_t n = name_width + sizeof ": " - 1 + out_len;
11277 :
11278 821 : if (colno == 0)
11279 : {
11280 51 : printf ("%*s", ITEM_INDENT, "");
11281 51 : colno = ITEM_INDENT + n;
11282 : }
11283 770 : else if (colno + 2 + n < wrap)
11284 : {
11285 936 : printf ("%c ", sep);
11286 468 : colno += 2 + n;
11287 : }
11288 : else
11289 : {
11290 302 : printf ("\n%*s", ITEM_INDENT, "");
11291 302 : colno = ITEM_INDENT + n;
11292 : }
11293 :
11294 1642 : printf ("%s: %*s%s", name, (int) (name_width - len), "", out);
11295 :
11296 821 : free (out);
11297 :
11298 821 : return colno;
11299 : }
11300 :
11301 : static const void *
11302 931 : convert (Elf *core, Elf_Type type, uint_fast16_t count,
11303 : void *value, const void *data, size_t size)
11304 : {
11305 1862 : Elf_Data valuedata =
11306 : {
11307 : .d_type = type,
11308 : .d_buf = value,
11309 931 : .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
11310 : .d_version = EV_CURRENT,
11311 : };
11312 931 : Elf_Data indata =
11313 : {
11314 : .d_type = type,
11315 : .d_buf = (void *) data,
11316 : .d_size = valuedata.d_size,
11317 : .d_version = EV_CURRENT,
11318 : };
11319 :
11320 1862 : Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
11321 1862 : ? elf32_xlatetom : elf64_xlatetom)
11322 931 : (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
11323 931 : if (d == NULL)
11324 0 : error (EXIT_FAILURE, 0,
11325 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
11326 :
11327 931 : return data + indata.d_size;
11328 : }
11329 :
11330 : typedef uint8_t GElf_Byte;
11331 :
11332 : static unsigned int
11333 400 : handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
11334 : unsigned int colno, size_t *repeated_size)
11335 : {
11336 400 : uint_fast16_t count = item->count ?: 1;
11337 : /* Ebl_Core_Item count is always a small number.
11338 : Make sure the backend didn't put in some large bogus value. */
11339 62 : assert (count < 128);
11340 :
11341 : #define TYPES \
11342 : DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8); \
11343 : DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16); \
11344 : DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32); \
11345 : DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32); \
11346 : DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64); \
11347 : DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64)
11348 :
11349 : #define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name
11350 : typedef union { TYPES; } value_t;
11351 400 : void *data = alloca (count * sizeof (value_t));
11352 : #undef DO_TYPE
11353 :
11354 : #define DO_TYPE(NAME, Name, hex, dec) \
11355 : GElf_##Name *value_##Name __attribute__((unused)) = data
11356 400 : TYPES;
11357 : #undef DO_TYPE
11358 :
11359 400 : size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
11360 400 : size_t convsize = size;
11361 400 : if (repeated_size != NULL)
11362 : {
11363 1 : if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
11364 : {
11365 0 : data = alloca (*repeated_size);
11366 0 : count *= *repeated_size / size;
11367 0 : convsize = count * size;
11368 0 : *repeated_size -= convsize;
11369 : }
11370 1 : else if (item->count != 0 || item->format != '\n')
11371 0 : *repeated_size -= size;
11372 : }
11373 :
11374 400 : convert (core, item->type, count, data, desc + item->offset, convsize);
11375 :
11376 400 : Elf_Type type = item->type;
11377 400 : if (type == ELF_T_ADDR)
11378 1 : type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
11379 :
11380 400 : switch (item->format)
11381 : {
11382 193 : case 'd':
11383 193 : assert (count == 1);
11384 193 : switch (type)
11385 : {
11386 : #define DO_TYPE(NAME, Name, hex, dec) \
11387 : case ELF_T_##NAME: \
11388 : colno = print_core_item (colno, ',', WRAP_COLUMN, \
11389 : 0, item->name, dec, value_##Name[0]); \
11390 : break
11391 27 : TYPES;
11392 : #undef DO_TYPE
11393 0 : default:
11394 0 : abort ();
11395 : }
11396 : break;
11397 :
11398 111 : case 'x':
11399 111 : assert (count == 1);
11400 111 : switch (type)
11401 : {
11402 : #define DO_TYPE(NAME, Name, hex, dec) \
11403 : case ELF_T_##NAME: \
11404 : colno = print_core_item (colno, ',', WRAP_COLUMN, \
11405 : 0, item->name, hex, value_##Name[0]); \
11406 : break
11407 0 : TYPES;
11408 : #undef DO_TYPE
11409 0 : default:
11410 0 : abort ();
11411 : }
11412 : break;
11413 :
11414 22 : case 'b':
11415 : case 'B':
11416 22 : assert (size % sizeof (unsigned int) == 0);
11417 22 : unsigned int nbits = count * size * 8;
11418 22 : unsigned int pop = 0;
11419 56 : for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
11420 34 : pop += __builtin_popcount (*i);
11421 22 : bool negate = pop > nbits / 2;
11422 22 : const unsigned int bias = item->format == 'b';
11423 :
11424 44 : {
11425 22 : char printed[(negate ? nbits - pop : pop) * 16 + 1];
11426 22 : char *p = printed;
11427 22 : *p = '\0';
11428 :
11429 : if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
11430 : {
11431 : assert (size == sizeof (unsigned int) * 2);
11432 : for (unsigned int *i = data;
11433 : (void *) i < data + count * size; i += 2)
11434 : {
11435 : unsigned int w = i[1];
11436 : i[1] = i[0];
11437 : i[0] = w;
11438 : }
11439 : }
11440 :
11441 22 : unsigned int lastbit = 0;
11442 22 : unsigned int run = 0;
11443 78 : for (const unsigned int *i = data;
11444 34 : (void *) i < data + count * size; ++i)
11445 : {
11446 34 : unsigned int bit = ((void *) i - data) * 8;
11447 34 : unsigned int w = negate ? ~*i : *i;
11448 34 : while (w != 0)
11449 : {
11450 : /* Note that a right shift equal to (or greater than)
11451 : the number of bits of w is undefined behaviour. In
11452 : particular when the least significant bit is bit 32
11453 : (w = 0x8000000) then w >>= n is undefined. So
11454 : explicitly handle that case separately. */
11455 0 : unsigned int n = ffs (w);
11456 0 : if (n < sizeof (w) * 8)
11457 0 : w >>= n;
11458 : else
11459 : w = 0;
11460 0 : bit += n;
11461 :
11462 0 : if (lastbit != 0 && lastbit + 1 == bit)
11463 0 : ++run;
11464 : else
11465 : {
11466 0 : if (lastbit == 0)
11467 0 : p += sprintf (p, "%u", bit - bias);
11468 0 : else if (run == 0)
11469 0 : p += sprintf (p, ",%u", bit - bias);
11470 : else
11471 0 : p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
11472 : run = 0;
11473 : }
11474 :
11475 : lastbit = bit;
11476 : }
11477 : }
11478 22 : if (lastbit > 0 && run > 0 && lastbit + 1 != nbits)
11479 0 : p += sprintf (p, "-%u", lastbit - bias);
11480 :
11481 22 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
11482 : negate ? "~<%s>" : "<%s>", printed);
11483 : }
11484 22 : break;
11485 :
11486 44 : case 'T':
11487 : case (char) ('T'|0x80):
11488 44 : assert (count == 2);
11489 : Dwarf_Word sec;
11490 : Dwarf_Word usec;
11491 44 : switch (type)
11492 : {
11493 : #define DO_TYPE(NAME, Name, hex, dec) \
11494 : case ELF_T_##NAME: \
11495 : sec = value_##Name[0]; \
11496 : usec = value_##Name[1]; \
11497 : break
11498 0 : TYPES;
11499 : #undef DO_TYPE
11500 0 : default:
11501 0 : abort ();
11502 : }
11503 44 : if (unlikely (item->format == (char) ('T'|0x80)))
11504 : {
11505 : /* This is a hack for an ill-considered 64-bit ABI where
11506 : tv_usec is actually a 32-bit field with 32 bits of padding
11507 : rounding out struct timeval. We've already converted it as
11508 : a 64-bit field. For little-endian, this just means the
11509 : high half is the padding; it's presumably zero, but should
11510 : be ignored anyway. For big-endian, it means the 32-bit
11511 : field went into the high half of USEC. */
11512 : GElf_Ehdr ehdr_mem;
11513 0 : GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
11514 0 : if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
11515 0 : usec >>= 32;
11516 : else
11517 0 : usec &= UINT32_MAX;
11518 : }
11519 44 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
11520 : "%" PRIu64 ".%.6" PRIu64, sec, usec);
11521 44 : break;
11522 :
11523 9 : case 'c':
11524 9 : assert (count == 1);
11525 9 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
11526 9 : "%c", value_Byte[0]);
11527 9 : break;
11528 :
11529 18 : case 's':
11530 18 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
11531 : "%.*s", (int) count, value_Byte);
11532 18 : break;
11533 :
11534 1 : case '\n':
11535 : /* This is a list of strings separated by '\n'. */
11536 1 : assert (item->count == 0);
11537 1 : assert (repeated_size != NULL);
11538 1 : assert (item->name == NULL);
11539 1 : if (unlikely (item->offset >= *repeated_size))
11540 : break;
11541 :
11542 1 : const char *s = desc + item->offset;
11543 1 : size = *repeated_size - item->offset;
11544 1 : *repeated_size = 0;
11545 49 : while (size > 0)
11546 : {
11547 48 : const char *eol = memchr (s, '\n', size);
11548 48 : int len = size;
11549 48 : if (eol != NULL)
11550 47 : len = eol - s;
11551 48 : printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
11552 48 : if (eol == NULL)
11553 : break;
11554 47 : size -= eol + 1 - s;
11555 47 : s = eol + 1;
11556 : }
11557 :
11558 : colno = WRAP_COLUMN;
11559 : break;
11560 :
11561 : case 'h':
11562 : break;
11563 :
11564 0 : default:
11565 0 : error (0, 0, "XXX not handling format '%c' for %s",
11566 : item->format, item->name);
11567 : break;
11568 : }
11569 :
11570 : #undef TYPES
11571 :
11572 400 : return colno;
11573 : }
11574 :
11575 :
11576 : /* Sort items by group, and by layout offset within each group. */
11577 : static int
11578 895 : compare_core_items (const void *a, const void *b)
11579 : {
11580 895 : const Ebl_Core_Item *const *p1 = a;
11581 895 : const Ebl_Core_Item *const *p2 = b;
11582 895 : const Ebl_Core_Item *item1 = *p1;
11583 895 : const Ebl_Core_Item *item2 = *p2;
11584 :
11585 895 : return ((item1->group == item2->group ? 0
11586 895 : : strcmp (item1->group, item2->group))
11587 432 : ?: (int) item1->offset - (int) item2->offset);
11588 : }
11589 :
11590 : /* Sort item groups by layout offset of the first item in the group. */
11591 : static int
11592 139 : compare_core_item_groups (const void *a, const void *b)
11593 : {
11594 139 : const Ebl_Core_Item *const *const *p1 = a;
11595 139 : const Ebl_Core_Item *const *const *p2 = b;
11596 139 : const Ebl_Core_Item *const *group1 = *p1;
11597 139 : const Ebl_Core_Item *const *group2 = *p2;
11598 139 : const Ebl_Core_Item *item1 = *group1;
11599 139 : const Ebl_Core_Item *item2 = *group2;
11600 :
11601 139 : return (int) item1->offset - (int) item2->offset;
11602 : }
11603 :
11604 : static unsigned int
11605 37 : handle_core_items (Elf *core, const void *desc, size_t descsz,
11606 : const Ebl_Core_Item *items, size_t nitems)
11607 : {
11608 37 : if (nitems == 0)
11609 : return 0;
11610 34 : unsigned int colno = 0;
11611 :
11612 : /* FORMAT '\n' makes sense to be present only as a single item as it
11613 : processes all the data of a note. FORMATs 'b' and 'B' have a special case
11614 : if present as a single item but they can be also processed with other
11615 : items below. */
11616 34 : if (nitems == 1 && (items[0].format == '\n' || items[0].format == 'b'
11617 8 : || items[0].format == 'B'))
11618 : {
11619 1 : assert (items[0].offset == 0);
11620 1 : size_t size = descsz;
11621 1 : colno = handle_core_item (core, items, desc, colno, &size);
11622 : /* If SIZE is not zero here there is some remaining data. But we do not
11623 : know how to process it anyway. */
11624 : return colno;
11625 : }
11626 391 : for (size_t i = 0; i < nitems; ++i)
11627 391 : assert (items[i].format != '\n');
11628 :
11629 : /* Sort to collect the groups together. */
11630 33 : const Ebl_Core_Item *sorted_items[nitems];
11631 424 : for (size_t i = 0; i < nitems; ++i)
11632 391 : sorted_items[i] = &items[i];
11633 33 : qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
11634 :
11635 : /* Collect the unique groups and sort them. */
11636 33 : const Ebl_Core_Item **groups[nitems];
11637 33 : groups[0] = &sorted_items[0];
11638 33 : size_t ngroups = 1;
11639 391 : for (size_t i = 1; i < nitems; ++i)
11640 358 : if (sorted_items[i]->group != sorted_items[i - 1]->group
11641 75 : && strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
11642 75 : groups[ngroups++] = &sorted_items[i];
11643 33 : qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
11644 :
11645 : /* Write out all the groups. */
11646 33 : const void *last = desc;
11647 : do
11648 : {
11649 145 : for (size_t i = 0; i < ngroups; ++i)
11650 : {
11651 619 : for (const Ebl_Core_Item **item = groups[i];
11652 509 : (item < &sorted_items[nitems]
11653 474 : && ((*item)->group == groups[i][0]->group
11654 75 : || !strcmp ((*item)->group, groups[i][0]->group)));
11655 399 : ++item)
11656 399 : colno = handle_core_item (core, *item, desc, colno, NULL);
11657 :
11658 : /* Force a line break at the end of the group. */
11659 110 : colno = WRAP_COLUMN;
11660 : }
11661 :
11662 35 : if (descsz == 0)
11663 : break;
11664 :
11665 : /* This set of items consumed a certain amount of the note's data.
11666 : If there is more data there, we have another unit of the same size.
11667 : Loop to print that out too. */
11668 20 : const Ebl_Core_Item *item = &items[nitems - 1];
11669 40 : size_t eltsz = item->offset + gelf_fsize (core, item->type,
11670 20 : item->count ?: 1, EV_CURRENT);
11671 :
11672 20 : int reps = -1;
11673 : do
11674 : {
11675 20 : ++reps;
11676 20 : desc += eltsz;
11677 20 : descsz -= eltsz;
11678 : }
11679 20 : while (descsz >= eltsz && !memcmp (desc, last, eltsz));
11680 :
11681 20 : if (reps == 1)
11682 : {
11683 : /* For just one repeat, print it unabridged twice. */
11684 : desc -= eltsz;
11685 : descsz += eltsz;
11686 : }
11687 20 : else if (reps > 1)
11688 0 : printf (gettext ("\n%*s... <repeats %u more times> ..."),
11689 : ITEM_INDENT, "", reps);
11690 :
11691 20 : last = desc;
11692 : }
11693 20 : while (descsz > 0);
11694 :
11695 : return colno;
11696 : }
11697 :
11698 : static unsigned int
11699 : handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
11700 : unsigned int colno)
11701 : {
11702 0 : desc += regloc->offset;
11703 :
11704 0 : abort (); /* XXX */
11705 : return colno;
11706 : }
11707 :
11708 :
11709 : static unsigned int
11710 162 : handle_core_register (Ebl *ebl, Elf *core, int maxregname,
11711 : const Ebl_Register_Location *regloc, const void *desc,
11712 : unsigned int colno)
11713 : {
11714 162 : if (regloc->bits % 8 != 0)
11715 0 : return handle_bit_registers (regloc, desc, colno);
11716 :
11717 162 : desc += regloc->offset;
11718 :
11719 586 : for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
11720 : {
11721 : char name[REGNAMESZ];
11722 : int bits;
11723 : int type;
11724 424 : register_info (ebl, reg, regloc, name, &bits, &type);
11725 :
11726 : #define TYPES \
11727 : BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8); \
11728 : BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16); \
11729 : BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32); \
11730 : BITS (64, XWORD, "%20" PRId64, " 0x%.16" PRIx64)
11731 :
11732 : #define BITS(bits, xtype, sfmt, ufmt) \
11733 : uint##bits##_t b##bits; int##bits##_t b##bits##s
11734 : union { TYPES; uint64_t b128[2]; } value;
11735 : #undef BITS
11736 :
11737 424 : switch (type)
11738 : {
11739 336 : case DW_ATE_unsigned:
11740 : case DW_ATE_signed:
11741 : case DW_ATE_address:
11742 336 : switch (bits)
11743 : {
11744 : #define BITS(bits, xtype, sfmt, ufmt) \
11745 : case bits: \
11746 : desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0); \
11747 : if (type == DW_ATE_signed) \
11748 : colno = print_core_item (colno, ' ', WRAP_COLUMN, \
11749 : maxregname, name, \
11750 : sfmt, value.b##bits##s); \
11751 : else \
11752 : colno = print_core_item (colno, ' ', WRAP_COLUMN, \
11753 : maxregname, name, \
11754 : ufmt, value.b##bits); \
11755 : break
11756 :
11757 0 : TYPES;
11758 :
11759 48 : case 128:
11760 48 : assert (type == DW_ATE_unsigned);
11761 48 : desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
11762 48 : int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
11763 96 : colno = print_core_item (colno, ' ', WRAP_COLUMN,
11764 : maxregname, name,
11765 : "0x%.16" PRIx64 "%.16" PRIx64,
11766 48 : value.b128[!be], value.b128[be]);
11767 48 : break;
11768 :
11769 0 : default:
11770 0 : abort ();
11771 : #undef BITS
11772 : }
11773 : break;
11774 :
11775 88 : default:
11776 : /* Print each byte in hex, the whole thing in native byte order. */
11777 88 : assert (bits % 8 == 0);
11778 88 : const uint8_t *bytes = desc;
11779 88 : desc += bits / 8;
11780 88 : char hex[bits / 4 + 1];
11781 88 : hex[bits / 4] = '\0';
11782 88 : int incr = 1;
11783 88 : if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
11784 : {
11785 48 : bytes += bits / 8 - 1;
11786 48 : incr = -1;
11787 : }
11788 88 : size_t idx = 0;
11789 872 : for (char *h = hex; bits > 0; bits -= 8, idx += incr)
11790 : {
11791 784 : *h++ = "0123456789abcdef"[bytes[idx] >> 4];
11792 784 : *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
11793 : }
11794 88 : colno = print_core_item (colno, ' ', WRAP_COLUMN,
11795 : maxregname, name, "0x%s", hex);
11796 : break;
11797 : }
11798 424 : desc += regloc->pad;
11799 :
11800 : #undef TYPES
11801 : }
11802 :
11803 : return colno;
11804 : }
11805 :
11806 :
11807 : struct register_info
11808 : {
11809 : const Ebl_Register_Location *regloc;
11810 : const char *set;
11811 : char name[REGNAMESZ];
11812 : int regno;
11813 : int bits;
11814 : int type;
11815 : };
11816 :
11817 : static int
11818 : register_bitpos (const struct register_info *r)
11819 : {
11820 2066 : return (r->regloc->offset * 8
11821 4132 : + ((r->regno - r->regloc->regno)
11822 2066 : * (r->regloc->bits + r->regloc->pad * 8)));
11823 : }
11824 :
11825 : static int
11826 1062 : compare_sets_by_info (const struct register_info *r1,
11827 : const struct register_info *r2)
11828 : {
11829 1062 : return ((int) r2->bits - (int) r1->bits
11830 3128 : ?: register_bitpos (r1) - register_bitpos (r2));
11831 : }
11832 :
11833 : /* Sort registers by set, and by size and layout offset within each set. */
11834 : static int
11835 4595 : compare_registers (const void *a, const void *b)
11836 : {
11837 4595 : const struct register_info *r1 = a;
11838 4595 : const struct register_info *r2 = b;
11839 :
11840 : /* Unused elements sort last. */
11841 4595 : if (r1->regloc == NULL)
11842 3309 : return r2->regloc == NULL ? 0 : 1;
11843 1286 : if (r2->regloc == NULL)
11844 : return -1;
11845 :
11846 1121 : return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
11847 79 : ?: compare_sets_by_info (r1, r2));
11848 : }
11849 :
11850 : /* Sort register sets by layout offset of the first register in the set. */
11851 : static int
11852 20 : compare_register_sets (const void *a, const void *b)
11853 : {
11854 20 : const struct register_info *const *p1 = a;
11855 20 : const struct register_info *const *p2 = b;
11856 20 : return compare_sets_by_info (*p1, *p2);
11857 : }
11858 :
11859 : static unsigned int
11860 37 : handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
11861 : const Ebl_Register_Location *reglocs, size_t nregloc)
11862 : {
11863 37 : if (nregloc == 0)
11864 : return 0;
11865 :
11866 18 : ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
11867 18 : if (maxnreg <= 0)
11868 : {
11869 0 : for (size_t i = 0; i < nregloc; ++i)
11870 0 : if (maxnreg < reglocs[i].regno + reglocs[i].count)
11871 0 : maxnreg = reglocs[i].regno + reglocs[i].count;
11872 0 : assert (maxnreg > 0);
11873 : }
11874 :
11875 18 : struct register_info regs[maxnreg];
11876 36 : memset (regs, 0, sizeof regs);
11877 :
11878 : /* Sort to collect the sets together. */
11879 18 : int maxreg = 0;
11880 180 : for (size_t i = 0; i < nregloc; ++i)
11881 748 : for (int reg = reglocs[i].regno;
11882 586 : reg < reglocs[i].regno + reglocs[i].count;
11883 424 : ++reg)
11884 : {
11885 424 : assert (reg < maxnreg);
11886 424 : if (reg > maxreg)
11887 230 : maxreg = reg;
11888 424 : struct register_info *info = ®s[reg];
11889 424 : info->regloc = ®locs[i];
11890 424 : info->regno = reg;
11891 848 : info->set = register_info (ebl, reg, ®locs[i],
11892 424 : info->name, &info->bits, &info->type);
11893 : }
11894 18 : qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
11895 :
11896 : /* Collect the unique sets and sort them. */
11897 864 : inline bool same_set (const struct register_info *a,
11898 : const struct register_info *b)
11899 : {
11900 1728 : return (a < ®s[maxnreg] && a->regloc != NULL
11901 864 : && b < ®s[maxnreg] && b->regloc != NULL
11902 846 : && a->bits == b->bits
11903 1692 : && (a->set == b->set || !strcmp (a->set, b->set)));
11904 : }
11905 18 : struct register_info *sets[maxreg + 1];
11906 18 : sets[0] = ®s[0];
11907 18 : size_t nsets = 1;
11908 1279 : for (int i = 1; i <= maxreg; ++i)
11909 1261 : if (regs[i].regloc != NULL && !same_set (®s[i], ®s[i - 1]))
11910 16 : sets[nsets++] = ®s[i];
11911 18 : qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
11912 :
11913 : /* Write out all the sets. */
11914 18 : unsigned int colno = 0;
11915 52 : for (size_t i = 0; i < nsets; ++i)
11916 : {
11917 : /* Find the longest name of a register in this set. */
11918 34 : size_t maxname = 0;
11919 : const struct register_info *end;
11920 458 : for (end = sets[i]; same_set (sets[i], end); ++end)
11921 : {
11922 424 : size_t len = strlen (end->name);
11923 424 : if (len > maxname)
11924 52 : maxname = len;
11925 : }
11926 :
11927 196 : for (const struct register_info *reg = sets[i];
11928 : reg < end;
11929 162 : reg += reg->regloc->count ?: 1)
11930 162 : colno = handle_core_register (ebl, core, maxname,
11931 : reg->regloc, desc, colno);
11932 :
11933 : /* Force a line break at the end of the group. */
11934 34 : colno = WRAP_COLUMN;
11935 : }
11936 :
11937 : return colno;
11938 : }
11939 :
11940 : static void
11941 9 : handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
11942 : {
11943 9 : Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
11944 9 : if (data == NULL)
11945 0 : elf_error:
11946 0 : error (EXIT_FAILURE, 0,
11947 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
11948 :
11949 9 : const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
11950 177 : for (size_t i = 0; i < nauxv; ++i)
11951 : {
11952 : GElf_auxv_t av_mem;
11953 168 : GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
11954 168 : if (av == NULL)
11955 : goto elf_error;
11956 :
11957 : const char *name;
11958 : const char *fmt;
11959 168 : if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
11960 : {
11961 : /* Unknown type. */
11962 0 : if (av->a_un.a_val == 0)
11963 0 : printf (" %" PRIu64 "\n", av->a_type);
11964 : else
11965 0 : printf (" %" PRIu64 ": %#" PRIx64 "\n",
11966 : av->a_type, av->a_un.a_val);
11967 : }
11968 : else
11969 168 : switch (fmt[0])
11970 : {
11971 9 : case '\0': /* Normally zero. */
11972 9 : if (av->a_un.a_val == 0)
11973 : {
11974 9 : printf (" %s\n", name);
11975 : break;
11976 : }
11977 : FALLTHROUGH;
11978 : case 'x': /* hex */
11979 : case 'p': /* address */
11980 : case 's': /* address of string */
11981 74 : printf (" %s: %#" PRIx64 "\n", name, av->a_un.a_val);
11982 : break;
11983 81 : case 'u':
11984 81 : printf (" %s: %" PRIu64 "\n", name, av->a_un.a_val);
11985 : break;
11986 0 : case 'd':
11987 0 : printf (" %s: %" PRId64 "\n", name, av->a_un.a_val);
11988 : break;
11989 :
11990 4 : case 'b':
11991 8 : printf (" %s: %#" PRIx64 " ", name, av->a_un.a_val);
11992 4 : GElf_Xword bit = 1;
11993 4 : const char *pfx = "<";
11994 110 : for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
11995 : {
11996 106 : if (av->a_un.a_val & bit)
11997 : {
11998 77 : printf ("%s%s", pfx, p);
11999 77 : pfx = " ";
12000 : }
12001 106 : bit <<= 1;
12002 : }
12003 : printf (">\n");
12004 : break;
12005 :
12006 0 : default:
12007 0 : abort ();
12008 : }
12009 : }
12010 9 : }
12011 :
12012 : static bool
12013 : buf_has_data (unsigned char const *ptr, unsigned char const *end, size_t sz)
12014 : {
12015 195 : return ptr < end && (size_t) (end - ptr) >= sz;
12016 : }
12017 :
12018 : static bool
12019 18 : buf_read_int (Elf *core, unsigned char const **ptrp, unsigned char const *end,
12020 : int *retp)
12021 : {
12022 36 : if (! buf_has_data (*ptrp, end, 4))
12023 : return false;
12024 :
12025 18 : *ptrp = convert (core, ELF_T_WORD, 1, retp, *ptrp, 4);
12026 18 : return true;
12027 : }
12028 :
12029 : static bool
12030 177 : buf_read_ulong (Elf *core, unsigned char const **ptrp, unsigned char const *end,
12031 : uint64_t *retp)
12032 : {
12033 177 : size_t sz = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
12034 354 : if (! buf_has_data (*ptrp, end, sz))
12035 : return false;
12036 :
12037 : union
12038 : {
12039 : uint64_t u64;
12040 : uint32_t u32;
12041 : } u;
12042 :
12043 177 : *ptrp = convert (core, ELF_T_ADDR, 1, &u, *ptrp, sz);
12044 :
12045 177 : if (sz == 4)
12046 93 : *retp = u.u32;
12047 : else
12048 84 : *retp = u.u64;
12049 : return true;
12050 : }
12051 :
12052 : static void
12053 6 : handle_siginfo_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
12054 : {
12055 6 : Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
12056 6 : if (data == NULL)
12057 0 : error (EXIT_FAILURE, 0,
12058 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
12059 :
12060 6 : unsigned char const *ptr = data->d_buf;
12061 6 : unsigned char const *const end = data->d_buf + data->d_size;
12062 :
12063 : /* Siginfo head is three ints: signal number, error number, origin
12064 : code. */
12065 : int si_signo, si_errno, si_code;
12066 6 : if (! buf_read_int (core, &ptr, end, &si_signo)
12067 6 : || ! buf_read_int (core, &ptr, end, &si_errno)
12068 6 : || ! buf_read_int (core, &ptr, end, &si_code))
12069 : {
12070 0 : fail:
12071 0 : printf (" Not enough data in NT_SIGINFO note.\n");
12072 0 : return;
12073 : }
12074 :
12075 : /* Next is a pointer-aligned union of structures. On 64-bit
12076 : machines, that implies a word of padding. */
12077 6 : if (gelf_getclass (core) == ELFCLASS64)
12078 3 : ptr += 4;
12079 :
12080 12 : printf (" si_signo: %d, si_errno: %d, si_code: %d\n",
12081 : si_signo, si_errno, si_code);
12082 :
12083 6 : if (si_code > 0)
12084 6 : switch (si_signo)
12085 : {
12086 6 : case CORE_SIGILL:
12087 : case CORE_SIGFPE:
12088 : case CORE_SIGSEGV:
12089 : case CORE_SIGBUS:
12090 : {
12091 : uint64_t addr;
12092 6 : if (! buf_read_ulong (core, &ptr, end, &addr))
12093 : goto fail;
12094 12 : printf (" fault address: %#" PRIx64 "\n", addr);
12095 6 : break;
12096 : }
12097 : default:
12098 : ;
12099 : }
12100 0 : else if (si_code == CORE_SI_USER)
12101 : {
12102 : int pid, uid;
12103 0 : if (! buf_read_int (core, &ptr, end, &pid)
12104 0 : || ! buf_read_int (core, &ptr, end, &uid))
12105 : goto fail;
12106 0 : printf (" sender PID: %d, sender UID: %d\n", pid, uid);
12107 : }
12108 : }
12109 :
12110 : static void
12111 6 : handle_file_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
12112 : {
12113 6 : Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
12114 6 : if (data == NULL)
12115 0 : error (EXIT_FAILURE, 0,
12116 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
12117 :
12118 6 : unsigned char const *ptr = data->d_buf;
12119 6 : unsigned char const *const end = data->d_buf + data->d_size;
12120 :
12121 : uint64_t count, page_size;
12122 6 : if (! buf_read_ulong (core, &ptr, end, &count)
12123 6 : || ! buf_read_ulong (core, &ptr, end, &page_size))
12124 : {
12125 0 : fail:
12126 0 : printf (" Not enough data in NT_FILE note.\n");
12127 0 : return;
12128 : }
12129 :
12130 6 : size_t addrsize = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
12131 6 : uint64_t maxcount = (size_t) (end - ptr) / (3 * addrsize);
12132 6 : if (count > maxcount)
12133 : goto fail;
12134 :
12135 : /* Where file names are stored. */
12136 6 : unsigned char const *const fstart = ptr + 3 * count * addrsize;
12137 6 : char const *fptr = (char *) fstart;
12138 :
12139 12 : printf (" %" PRId64 " files:\n", count);
12140 59 : for (uint64_t i = 0; i < count; ++i)
12141 : {
12142 : uint64_t mstart, mend, moffset;
12143 53 : if (! buf_read_ulong (core, &ptr, fstart, &mstart)
12144 53 : || ! buf_read_ulong (core, &ptr, fstart, &mend)
12145 53 : || ! buf_read_ulong (core, &ptr, fstart, &moffset))
12146 : goto fail;
12147 :
12148 53 : const char *fnext = memchr (fptr, '\0', (char *) end - fptr);
12149 53 : if (fnext == NULL)
12150 : goto fail;
12151 :
12152 106 : int ct = printf (" %08" PRIx64 "-%08" PRIx64
12153 : " %08" PRIx64 " %" PRId64,
12154 : mstart, mend, moffset * page_size, mend - mstart);
12155 106 : printf ("%*s%s\n", ct > 50 ? 3 : 53 - ct, "", fptr);
12156 :
12157 53 : fptr = fnext + 1;
12158 : }
12159 : }
12160 :
12161 : static void
12162 38 : handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
12163 : const char *name, const void *desc)
12164 : {
12165 : GElf_Word regs_offset;
12166 : size_t nregloc;
12167 : const Ebl_Register_Location *reglocs;
12168 : size_t nitems;
12169 : const Ebl_Core_Item *items;
12170 :
12171 38 : if (! ebl_core_note (ebl, nhdr, name, desc,
12172 : ®s_offset, &nregloc, ®locs, &nitems, &items))
12173 1 : return;
12174 :
12175 : /* Pass 0 for DESCSZ when there are registers in the note,
12176 : so that the ITEMS array does not describe the whole thing.
12177 : For non-register notes, the actual descsz might be a multiple
12178 : of the unit size, not just exactly the unit size. */
12179 93 : unsigned int colno = handle_core_items (ebl->elf, desc,
12180 56 : nregloc == 0 ? nhdr->n_descsz : 0,
12181 : items, nitems);
12182 37 : if (colno != 0)
12183 : putchar_unlocked ('\n');
12184 :
12185 37 : colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
12186 : reglocs, nregloc);
12187 37 : if (colno != 0)
12188 : putchar_unlocked ('\n');
12189 : }
12190 :
12191 : static void
12192 57 : handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
12193 : GElf_Off start, Elf_Data *data)
12194 : {
12195 57 : fputs_unlocked (gettext (" Owner Data size Type\n"), stdout);
12196 :
12197 57 : if (data == NULL)
12198 : goto bad_note;
12199 :
12200 : size_t offset = 0;
12201 : GElf_Nhdr nhdr;
12202 : size_t name_offset;
12203 : size_t desc_offset;
12204 188 : while (offset < data->d_size
12205 131 : && (offset = gelf_getnote (data, offset,
12206 : &nhdr, &name_offset, &desc_offset)) > 0)
12207 : {
12208 131 : const char *name = nhdr.n_namesz == 0 ? "" : data->d_buf + name_offset;
12209 131 : const char *desc = data->d_buf + desc_offset;
12210 :
12211 : /* GNU Build Attributes are weird, they store most of their data
12212 : into the owner name field. Extract just the owner name
12213 : prefix here, then use the rest later as data. */
12214 131 : bool is_gnu_build_attr
12215 131 : = strncmp (name, ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX,
12216 : strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX)) == 0;
12217 131 : const char *print_name = (is_gnu_build_attr
12218 131 : ? ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX : name);
12219 131 : size_t print_namesz = (is_gnu_build_attr
12220 131 : ? strlen (print_name) : nhdr.n_namesz);
12221 :
12222 : char buf[100];
12223 : char buf2[100];
12224 393 : printf (gettext (" %-13.*s %9" PRId32 " %s\n"),
12225 : (int) print_namesz, print_name, nhdr.n_descsz,
12226 131 : ehdr->e_type == ET_CORE
12227 59 : ? ebl_core_note_type_name (ebl, nhdr.n_type,
12228 : buf, sizeof (buf))
12229 72 : : ebl_object_note_type_name (ebl, name, nhdr.n_type,
12230 : nhdr.n_descsz,
12231 : buf2, sizeof (buf2)));
12232 :
12233 : /* Filter out invalid entries. */
12234 : if (memchr (name, '\0', nhdr.n_namesz) != NULL
12235 : /* XXX For now help broken Linux kernels. */
12236 : || 1)
12237 : {
12238 131 : if (ehdr->e_type == ET_CORE)
12239 : {
12240 59 : if (nhdr.n_type == NT_AUXV
12241 9 : && (nhdr.n_namesz == 4 /* Broken old Linux kernels. */
12242 9 : || (nhdr.n_namesz == 5 && name[4] == '\0'))
12243 9 : && !memcmp (name, "CORE", 4))
12244 9 : handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
12245 : start + desc_offset);
12246 50 : else if (nhdr.n_namesz == 5 && strcmp (name, "CORE") == 0)
12247 38 : switch (nhdr.n_type)
12248 : {
12249 6 : case NT_SIGINFO:
12250 6 : handle_siginfo_note (ebl->elf, nhdr.n_descsz,
12251 : start + desc_offset);
12252 : break;
12253 :
12254 6 : case NT_FILE:
12255 6 : handle_file_note (ebl->elf, nhdr.n_descsz,
12256 : start + desc_offset);
12257 : break;
12258 :
12259 26 : default:
12260 26 : handle_core_note (ebl, &nhdr, name, desc);
12261 : }
12262 : else
12263 12 : handle_core_note (ebl, &nhdr, name, desc);
12264 : }
12265 : else
12266 72 : ebl_object_note (ebl, nhdr.n_namesz, name, nhdr.n_type,
12267 : nhdr.n_descsz, desc);
12268 : }
12269 : }
12270 :
12271 57 : if (offset == data->d_size)
12272 57 : return;
12273 :
12274 0 : bad_note:
12275 0 : error (0, 0,
12276 0 : gettext ("cannot get content of note: %s"),
12277 : data != NULL ? "garbage data" : elf_errmsg (-1));
12278 : }
12279 :
12280 : static void
12281 60 : handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
12282 : {
12283 : /* If we have section headers, just look for SHT_NOTE sections.
12284 : In a debuginfo file, the program headers are not reliable. */
12285 60 : if (shnum != 0)
12286 : {
12287 : /* Get the section header string table index. */
12288 : size_t shstrndx;
12289 49 : if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
12290 : error (EXIT_FAILURE, 0,
12291 0 : gettext ("cannot get section header string table index"));
12292 :
12293 : Elf_Scn *scn = NULL;
12294 1181 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
12295 : {
12296 : GElf_Shdr shdr_mem;
12297 1132 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
12298 :
12299 1132 : if (shdr == NULL || shdr->sh_type != SHT_NOTE)
12300 : /* Not what we are looking for. */
12301 1087 : continue;
12302 :
12303 135 : printf (gettext ("\
12304 : \nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
12305 : elf_ndxscn (scn),
12306 45 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
12307 : shdr->sh_size, shdr->sh_offset);
12308 :
12309 45 : handle_notes_data (ebl, ehdr, shdr->sh_offset,
12310 : elf_getdata (scn, NULL));
12311 : }
12312 : return;
12313 : }
12314 :
12315 : /* We have to look through the program header to find the note
12316 : sections. There can be more than one. */
12317 129 : for (size_t cnt = 0; cnt < phnum; ++cnt)
12318 : {
12319 : GElf_Phdr mem;
12320 129 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
12321 :
12322 129 : if (phdr == NULL || phdr->p_type != PT_NOTE)
12323 : /* Not what we are looking for. */
12324 117 : continue;
12325 :
12326 24 : printf (gettext ("\
12327 : \nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
12328 : phdr->p_filesz, phdr->p_offset);
12329 :
12330 24 : handle_notes_data (ebl, ehdr, phdr->p_offset,
12331 : elf_getdata_rawchunk (ebl->elf,
12332 12 : phdr->p_offset, phdr->p_filesz,
12333 12 : (phdr->p_align == 8
12334 : ? ELF_T_NHDR8 : ELF_T_NHDR)));
12335 : }
12336 : }
12337 :
12338 :
12339 : static void
12340 5 : hex_dump (const uint8_t *data, size_t len)
12341 : {
12342 5 : size_t pos = 0;
12343 31 : while (pos < len)
12344 : {
12345 21 : printf (" 0x%08zx ", pos);
12346 :
12347 21 : const size_t chunk = MIN (len - pos, 16);
12348 :
12349 342 : for (size_t i = 0; i < chunk; ++i)
12350 321 : if (i % 4 == 3)
12351 80 : printf ("%02x ", data[pos + i]);
12352 : else
12353 241 : printf ("%02x", data[pos + i]);
12354 :
12355 21 : if (chunk < 16)
12356 1 : printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
12357 :
12358 321 : for (size_t i = 0; i < chunk; ++i)
12359 : {
12360 321 : unsigned char b = data[pos + i];
12361 642 : printf ("%c", isprint (b) ? b : '.');
12362 : }
12363 :
12364 21 : putchar ('\n');
12365 21 : pos += chunk;
12366 : }
12367 5 : }
12368 :
12369 : static void
12370 5 : dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
12371 : {
12372 5 : if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
12373 0 : printf (gettext ("\nSection [%zu] '%s' has no data to dump.\n"),
12374 : elf_ndxscn (scn), name);
12375 : else
12376 : {
12377 5 : if (print_decompress)
12378 : {
12379 : /* We try to decompress the section, but keep the old shdr around
12380 : so we can show both the original shdr size and the uncompressed
12381 : data size. */
12382 4 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
12383 : {
12384 2 : if (elf_compress (scn, 0, 0) < 0)
12385 0 : printf ("WARNING: %s [%zd]\n",
12386 : gettext ("Couldn't uncompress section"),
12387 : elf_ndxscn (scn));
12388 : }
12389 2 : else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
12390 : {
12391 2 : if (elf_compress_gnu (scn, 0, 0) < 0)
12392 0 : printf ("WARNING: %s [%zd]\n",
12393 : gettext ("Couldn't uncompress section"),
12394 : elf_ndxscn (scn));
12395 : }
12396 : }
12397 :
12398 5 : Elf_Data *data = elf_rawdata (scn, NULL);
12399 5 : if (data == NULL)
12400 0 : error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
12401 : elf_ndxscn (scn), name, elf_errmsg (-1));
12402 : else
12403 : {
12404 5 : if (data->d_size == shdr->sh_size)
12405 1 : printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
12406 : " bytes at offset %#0" PRIx64 ":\n"),
12407 : elf_ndxscn (scn), name,
12408 : shdr->sh_size, shdr->sh_offset);
12409 : else
12410 4 : printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
12411 : " bytes (%zd uncompressed) at offset %#0"
12412 : PRIx64 ":\n"),
12413 : elf_ndxscn (scn), name,
12414 : shdr->sh_size, data->d_size, shdr->sh_offset);
12415 5 : hex_dump (data->d_buf, data->d_size);
12416 : }
12417 : }
12418 5 : }
12419 :
12420 : static void
12421 89 : print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
12422 : {
12423 89 : if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
12424 0 : printf (gettext ("\nSection [%zu] '%s' has no strings to dump.\n"),
12425 : elf_ndxscn (scn), name);
12426 : else
12427 : {
12428 89 : if (print_decompress)
12429 : {
12430 : /* We try to decompress the section, but keep the old shdr around
12431 : so we can show both the original shdr size and the uncompressed
12432 : data size. */
12433 1 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
12434 : {
12435 0 : if (elf_compress (scn, 0, 0) < 0)
12436 0 : printf ("WARNING: %s [%zd]\n",
12437 : gettext ("Couldn't uncompress section"),
12438 : elf_ndxscn (scn));
12439 : }
12440 1 : else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
12441 : {
12442 1 : if (elf_compress_gnu (scn, 0, 0) < 0)
12443 0 : printf ("WARNING: %s [%zd]\n",
12444 : gettext ("Couldn't uncompress section"),
12445 : elf_ndxscn (scn));
12446 : }
12447 : }
12448 :
12449 89 : Elf_Data *data = elf_rawdata (scn, NULL);
12450 89 : if (data == NULL)
12451 0 : error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
12452 : elf_ndxscn (scn), name, elf_errmsg (-1));
12453 : else
12454 : {
12455 89 : if (data->d_size == shdr->sh_size)
12456 88 : printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
12457 : " bytes at offset %#0" PRIx64 ":\n"),
12458 : elf_ndxscn (scn), name,
12459 : shdr->sh_size, shdr->sh_offset);
12460 : else
12461 1 : printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
12462 : " bytes (%zd uncompressed) at offset %#0"
12463 : PRIx64 ":\n"),
12464 : elf_ndxscn (scn), name,
12465 : shdr->sh_size, data->d_size, shdr->sh_offset);
12466 :
12467 89 : const char *start = data->d_buf;
12468 89 : const char *const limit = start + data->d_size;
12469 : do
12470 : {
12471 16130 : const char *end = memchr (start, '\0', limit - start);
12472 16130 : const size_t pos = start - (const char *) data->d_buf;
12473 16130 : if (unlikely (end == NULL))
12474 : {
12475 0 : printf (" [%6zx]- %.*s\n",
12476 : pos, (int) (limit - start), start);
12477 : break;
12478 : }
12479 16130 : printf (" [%6zx] %s\n", pos, start);
12480 16130 : start = end + 1;
12481 16130 : } while (start < limit);
12482 : }
12483 : }
12484 89 : }
12485 :
12486 : static void
12487 46 : for_each_section_argument (Elf *elf, const struct section_argument *list,
12488 : void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
12489 : const char *name))
12490 : {
12491 : /* Get the section header string table index. */
12492 : size_t shstrndx;
12493 46 : if (elf_getshdrstrndx (elf, &shstrndx) < 0)
12494 : error (EXIT_FAILURE, 0,
12495 0 : gettext ("cannot get section header string table index"));
12496 :
12497 126 : for (const struct section_argument *a = list; a != NULL; a = a->next)
12498 : {
12499 : Elf_Scn *scn;
12500 : GElf_Shdr shdr_mem;
12501 126 : const char *name = NULL;
12502 :
12503 126 : char *endp = NULL;
12504 126 : unsigned long int shndx = strtoul (a->arg, &endp, 0);
12505 126 : if (endp != a->arg && *endp == '\0')
12506 : {
12507 0 : scn = elf_getscn (elf, shndx);
12508 0 : if (scn == NULL)
12509 : {
12510 0 : error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
12511 0 : continue;
12512 : }
12513 :
12514 0 : if (gelf_getshdr (scn, &shdr_mem) == NULL)
12515 0 : error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
12516 : elf_errmsg (-1));
12517 0 : name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
12518 : }
12519 : else
12520 : {
12521 : /* Need to look up the section by name. */
12522 : scn = NULL;
12523 : bool found = false;
12524 3207 : while ((scn = elf_nextscn (elf, scn)) != NULL)
12525 : {
12526 3081 : if (gelf_getshdr (scn, &shdr_mem) == NULL)
12527 0 : continue;
12528 3081 : name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
12529 3081 : if (name == NULL)
12530 0 : continue;
12531 3081 : if (!strcmp (name, a->arg))
12532 : {
12533 94 : found = true;
12534 94 : (*dump) (scn, &shdr_mem, name);
12535 : }
12536 : }
12537 :
12538 126 : if (unlikely (!found) && !a->implicit)
12539 0 : error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
12540 : }
12541 : }
12542 46 : }
12543 :
12544 : static void
12545 : dump_data (Ebl *ebl)
12546 : {
12547 5 : for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
12548 : }
12549 :
12550 : static void
12551 : dump_strings (Ebl *ebl)
12552 : {
12553 41 : for_each_section_argument (ebl->elf, string_sections, &print_string_section);
12554 : }
12555 :
12556 : static void
12557 0 : print_strings (Ebl *ebl)
12558 : {
12559 : /* Get the section header string table index. */
12560 : size_t shstrndx;
12561 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
12562 : error (EXIT_FAILURE, 0,
12563 0 : gettext ("cannot get section header string table index"));
12564 :
12565 : Elf_Scn *scn;
12566 : GElf_Shdr shdr_mem;
12567 : const char *name;
12568 : scn = NULL;
12569 0 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
12570 : {
12571 0 : if (gelf_getshdr (scn, &shdr_mem) == NULL)
12572 0 : continue;
12573 :
12574 0 : if (shdr_mem.sh_type != SHT_PROGBITS
12575 0 : || !(shdr_mem.sh_flags & SHF_STRINGS))
12576 0 : continue;
12577 :
12578 0 : name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
12579 0 : if (name == NULL)
12580 0 : continue;
12581 :
12582 0 : print_string_section (scn, &shdr_mem, name);
12583 : }
12584 0 : }
12585 :
12586 : static void
12587 2 : dump_archive_index (Elf *elf, const char *fname)
12588 : {
12589 : size_t narsym;
12590 2 : const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
12591 2 : if (arsym == NULL)
12592 : {
12593 0 : int result = elf_errno ();
12594 0 : if (unlikely (result != ELF_E_NO_INDEX))
12595 0 : error (EXIT_FAILURE, 0,
12596 0 : gettext ("cannot get symbol index of archive '%s': %s"),
12597 : fname, elf_errmsg (result));
12598 : else
12599 0 : printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
12600 0 : return;
12601 : }
12602 :
12603 4 : printf (gettext ("\nIndex of archive '%s' has %zu entries:\n"),
12604 : fname, narsym);
12605 :
12606 2 : size_t as_off = 0;
12607 11 : for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
12608 : {
12609 9 : if (s->as_off != as_off)
12610 : {
12611 6 : as_off = s->as_off;
12612 :
12613 6 : Elf *subelf = NULL;
12614 6 : if (unlikely (elf_rand (elf, as_off) == 0)
12615 6 : || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
12616 : == NULL))
12617 : #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
12618 : while (1)
12619 : #endif
12620 0 : error (EXIT_FAILURE, 0,
12621 0 : gettext ("cannot extract member at offset %zu in '%s': %s"),
12622 : as_off, fname, elf_errmsg (-1));
12623 :
12624 6 : const Elf_Arhdr *h = elf_getarhdr (subelf);
12625 :
12626 12 : printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
12627 :
12628 6 : elf_end (subelf);
12629 : }
12630 :
12631 18 : printf ("\t%s\n", s->as_name);
12632 : }
12633 : }
12634 :
12635 : #include "debugpred.h"
|