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 280 : main (int argc, char *argv[])
317 : {
318 : /* We use no threads here which can interfere with handling a stream. */
319 280 : (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
320 :
321 : /* Set locale. */
322 280 : setlocale (LC_ALL, "");
323 :
324 : /* Initialize the message catalog. */
325 280 : textdomain (PACKAGE_TARNAME);
326 :
327 : /* Look up once. */
328 280 : yes_str = gettext ("yes");
329 280 : no_str = gettext ("no");
330 :
331 : /* Parse and process arguments. */
332 : int remaining;
333 280 : argp_parse (&argp, argc, argv, 0, &remaining, NULL);
334 :
335 : /* Before we start tell the ELF library which version we are using. */
336 280 : elf_version (EV_CURRENT);
337 :
338 : /* Now process all the files given at the command line. */
339 280 : bool only_one = remaining + 1 == argc;
340 : do
341 : {
342 : /* Open the file. */
343 572 : int fd = open (argv[remaining], O_RDONLY);
344 286 : if (fd == -1)
345 : {
346 0 : error (0, errno, gettext ("cannot open input file"));
347 0 : continue;
348 : }
349 :
350 286 : process_file (fd, argv[remaining], only_one);
351 :
352 286 : close (fd);
353 : }
354 286 : while (++remaining < argc);
355 :
356 280 : return error_message_count != 0;
357 : }
358 :
359 :
360 : /* Handle program arguments. */
361 : static error_t
362 1745 : 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 1745 : 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 15 : case 'n':
426 15 : print_notes = true;
427 15 : any_control_option = true;
428 15 : 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 280 : case ARGP_KEY_FINI:
548 280 : 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 272 : 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 272 : if (*(bool *) arg)
731 : return DWARF_CB_ABORT;
732 272 : *(bool *) arg = true;
733 272 : 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 284 : 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 284 : const struct process_dwflmod_args *a = arg;
750 :
751 : /* Print the file name. */
752 284 : 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 284 : process_elf_file (dwflmod, a->fd);
761 :
762 284 : 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 293 : create_dwfl (int fd, const char *fname)
795 : {
796 : /* Duplicate an fd for dwfl_report_offline to swallow. */
797 293 : int dwfl_fd = dup (fd);
798 293 : 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 293 : Dwfl *dwfl = dwfl_begin (&callbacks);
809 293 : if (likely (dwfl != NULL))
810 : /* Let 0 be the logical address of the file (or first in archive). */
811 293 : dwfl->offline_next_address = 0;
812 293 : 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 293 : dwfl_report_end (dwfl, NULL, NULL);
827 :
828 293 : return dwfl;
829 : }
830 :
831 : /* Process one input file. */
832 : static void
833 286 : process_file (int fd, const char *fname, bool only_one)
834 : {
835 286 : if (print_archive_index)
836 2 : check_archive_index (fd, fname, only_one);
837 :
838 286 : if (!any_control_option)
839 : return;
840 :
841 284 : 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 284 : Dwfl *dwfl = create_dwfl (fd, fname);
857 284 : if (dwfl != NULL)
858 : {
859 284 : if (only_one)
860 : {
861 : /* Clear ONLY_ONE if we have multiple modules, from an archive. */
862 272 : bool seen = false;
863 272 : only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
864 : }
865 :
866 : /* Process the one or more modules gleaned from this file. */
867 284 : struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
868 284 : 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 284 : if (! do_not_close_dwfl)
873 284 : dwfl_end (dwfl);
874 :
875 : /* Need to close the replaced fd if we created it. Caller takes
876 : care of original. */
877 284 : 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 94 : elf_contains_chdrs (Elf *elf)
884 : {
885 94 : Elf_Scn *scn = NULL;
886 788819 : while ((scn = elf_nextscn (elf, scn)) != NULL)
887 : {
888 : GElf_Shdr shdr_mem;
889 788637 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
890 788637 : 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 284 : process_elf_file (Dwfl_Module *dwflmod, int fd)
899 : {
900 : GElf_Addr dwflbias;
901 284 : Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
902 :
903 : GElf_Ehdr ehdr_mem;
904 284 : GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
905 :
906 284 : if (ehdr == NULL)
907 : {
908 0 : error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
909 0 : return;
910 : }
911 :
912 284 : Ebl *ebl = ebl_openbackend (elf);
913 284 : 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 284 : 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 284 : 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 568 : bool print_unchanged = ((print_section_header
938 156 : || print_relocations
939 155 : || dump_data_sections != NULL
940 150 : || print_notes)
941 433 : && (ehdr->e_type == ET_REL
942 94 : || elf_contains_chdrs (ebl->elf)));
943 :
944 284 : Elf *pure_elf = NULL;
945 284 : Ebl *pure_ebl = ebl;
946 284 : if (print_unchanged)
947 : {
948 : /* Read the file afresh. */
949 61 : off_t aroff = elf_getaroff (elf);
950 61 : pure_elf = dwelf_elf_begin (fd);
951 61 : 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 61 : if (pure_elf == NULL)
960 : {
961 0 : error (0, 0, gettext ("cannot read ELF: %s"), elf_errmsg (-1));
962 : return;
963 : }
964 61 : pure_ebl = ebl_openbackend (pure_elf);
965 61 : if (pure_ebl == NULL)
966 : goto ebl_error;
967 : }
968 :
969 284 : if (print_file_header)
970 40 : print_ehdr (ebl, ehdr);
971 284 : if (print_section_header)
972 128 : print_shdr (pure_ebl, ehdr);
973 284 : if (print_program_header)
974 40 : print_phdr (ebl, ehdr);
975 284 : if (print_section_groups)
976 49 : print_scngrp (ebl);
977 284 : if (print_dynamic_table)
978 42 : print_dynamic (ebl);
979 284 : if (print_relocations)
980 41 : print_relocs (pure_ebl, ehdr);
981 284 : if (print_histogram)
982 40 : handle_hash (ebl);
983 284 : if (print_symbol_table)
984 54 : print_symtab (ebl, SHT_DYNSYM);
985 284 : if (print_version_info)
986 40 : print_verinfo (ebl);
987 284 : if (print_symbol_table)
988 54 : print_symtab (ebl, SHT_SYMTAB);
989 284 : if (print_arch)
990 44 : print_liblist (ebl);
991 284 : if (print_arch)
992 44 : print_attributes (ebl, ehdr);
993 284 : if (dump_data_sections != NULL)
994 5 : dump_data (pure_ebl);
995 284 : if (string_sections != NULL)
996 41 : dump_strings (ebl);
997 284 : if ((print_debug_sections | implicit_debug_sections) != 0)
998 145 : print_debug (dwflmod, ebl, ehdr);
999 284 : if (print_notes)
1000 55 : handle_notes (pure_ebl, ehdr);
1001 284 : if (print_string_sections)
1002 0 : print_strings (ebl);
1003 :
1004 284 : ebl_closebackend (ebl);
1005 :
1006 284 : if (pure_ebl != ebl)
1007 : {
1008 61 : ebl_closebackend (pure_ebl);
1009 61 : 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 14885 : switch (value)
1155 : {
1156 : case STV_DEFAULT:
1157 : return "DEFAULT";
1158 0 : case STV_INTERNAL:
1159 : return "INTERNAL";
1160 72 : 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 38711 : for (int cnt = 0; cnt < nentries; ++cnt)
2196 : {
2197 : GElf_Rela relmem;
2198 38543 : GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
2199 38543 : if (likely (rel != NULL))
2200 : {
2201 : char buf[64];
2202 : GElf_Sym symmem;
2203 : Elf32_Word xndx;
2204 38543 : GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
2205 38543 : GELF_R_SYM (rel->r_info),
2206 : &symmem, &xndx);
2207 :
2208 38543 : 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 38543 : else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
2261 82772 : printf ("\
2262 : %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
2263 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2264 20693 : 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 20693 : ? 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 41386 : 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 17850 : secshdr = gelf_getshdr (elf_getscn (ebl->elf,
2280 17850 : sym->st_shndx == SHN_XINDEX
2281 0 : ? xndx : sym->st_shndx),
2282 : &secshdr_mem);
2283 :
2284 17850 : 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 53550 : printf ("\
2298 : %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
2299 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2300 17850 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2301 : /* Avoid the leading R_ which isn't carrying any
2302 : information. */
2303 17850 : ? 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 17850 : 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 14947 : 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 14885 : GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
2455 :
2456 14885 : if (unlikely (sym == NULL))
2457 0 : continue;
2458 :
2459 : /* Determine the real section index. */
2460 14885 : if (likely (sym->st_shndx != SHN_XINDEX))
2461 14885 : xndx = sym->st_shndx;
2462 :
2463 119080 : 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 14885 : ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
2470 : typebuf, sizeof (typebuf)),
2471 14885 : ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
2472 : bindbuf, sizeof (bindbuf)),
2473 14885 : get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
2474 14885 : ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
2475 : sizeof (scnbuf), NULL, shnum),
2476 29770 : elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
2477 :
2478 14885 : if (versym_data != NULL)
2479 : {
2480 : /* Get the version information. */
2481 : GElf_Versym versym_mem;
2482 1392 : GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
2483 :
2484 1392 : if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
2485 : {
2486 1186 : bool is_nobits = false;
2487 1186 : bool check_def = xndx != SHN_UNDEF;
2488 :
2489 1186 : if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
2490 : {
2491 : GElf_Shdr symshdr_mem;
2492 1150 : GElf_Shdr *symshdr =
2493 1150 : gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
2494 :
2495 1150 : is_nobits = (symshdr != NULL
2496 1150 : && symshdr->sh_type == SHT_NOBITS);
2497 : }
2498 :
2499 1186 : if (is_nobits || ! check_def)
2500 : {
2501 : /* We must test both. */
2502 : GElf_Vernaux vernaux_mem;
2503 810 : GElf_Vernaux *vernaux = NULL;
2504 810 : size_t vn_offset = 0;
2505 :
2506 : GElf_Verneed verneed_mem;
2507 810 : GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
2508 : &verneed_mem);
2509 4046 : while (verneed != NULL)
2510 : {
2511 3236 : size_t vna_offset = vn_offset;
2512 :
2513 3236 : vernaux = gelf_getvernaux (verneed_data,
2514 3236 : vna_offset += verneed->vn_aux,
2515 : &vernaux_mem);
2516 9821 : while (vernaux != NULL
2517 6585 : && vernaux->vna_other != *versym
2518 5775 : && vernaux->vna_next != 0)
2519 : {
2520 : /* Update the offset. */
2521 3349 : vna_offset += vernaux->vna_next;
2522 :
2523 3349 : vernaux = (vernaux->vna_next == 0
2524 : ? NULL
2525 3349 : : gelf_getvernaux (verneed_data,
2526 : vna_offset,
2527 : &vernaux_mem));
2528 : }
2529 :
2530 : /* Check whether we found the version. */
2531 3236 : if (vernaux != NULL && vernaux->vna_other == *versym)
2532 : /* Found it. */
2533 : break;
2534 :
2535 2426 : vn_offset += verneed->vn_next;
2536 : verneed = (verneed->vn_next == 0
2537 : ? NULL
2538 2426 : : gelf_getverneed (verneed_data, vn_offset,
2539 : &verneed_mem));
2540 : }
2541 :
2542 810 : if (vernaux != NULL && vernaux->vna_other == *versym)
2543 : {
2544 2430 : printf ("@%s (%u)",
2545 : elf_strptr (ebl->elf, verneed_stridx,
2546 810 : vernaux->vna_name),
2547 : (unsigned int) vernaux->vna_other);
2548 810 : 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 14885 : 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 122 : get_ver_flags (unsigned int flags)
2628 : {
2629 : static char buf[32];
2630 : char *endp;
2631 :
2632 122 : if (flags == 0)
2633 117 : 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 119 : for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2709 : {
2710 : GElf_Vernaux auxmem;
2711 82 : GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
2712 82 : if (unlikely (aux == NULL))
2713 : break;
2714 :
2715 410 : printf (gettext (" %#06x: Name: %s Flags: %s Version: %hu\n"),
2716 : auxoffset,
2717 164 : elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
2718 82 : get_ver_flags (aux->vna_flags),
2719 82 : (unsigned short int) aux->vna_other);
2720 :
2721 82 : if (aux->vna_next == 0)
2722 : break;
2723 :
2724 45 : 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 119 : for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
2927 : {
2928 : GElf_Vernaux auxmem;
2929 : GElf_Vernaux *aux;
2930 :
2931 82 : aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
2932 82 : if (unlikely (aux == NULL))
2933 : break;
2934 :
2935 82 : nvername = MAX (nvername,
2936 : (size_t) (aux->vna_other & 0x7fff));
2937 :
2938 82 : if (aux->vna_next == 0)
2939 : break;
2940 45 : 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 119 : for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
3023 : {
3024 : GElf_Vernaux auxmem;
3025 82 : GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
3026 : &auxmem);
3027 82 : if (unlikely (aux == NULL))
3028 : break;
3029 :
3030 82 : vername[aux->vna_other & 0x7fff]
3031 164 : = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
3032 82 : filename[aux->vna_other & 0x7fff]
3033 164 : = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
3034 :
3035 82 : if (aux->vna_next == 0)
3036 : break;
3037 45 : 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 1315 : for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
3077 : {
3078 1305 : if (cnt % 2 == 0)
3079 : printf ("\n %4d:", cnt);
3080 :
3081 : GElf_Versym symmem;
3082 1305 : GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
3083 1305 : if (sym == NULL)
3084 : break;
3085 :
3086 1305 : switch (*sym)
3087 : {
3088 : ssize_t n;
3089 112 : case 0:
3090 112 : fputs_unlocked (gettext (" 0 *local* "),
3091 : stdout);
3092 : break;
3093 :
3094 20 : case 1:
3095 20 : fputs_unlocked (gettext (" 1 *global* "),
3096 : stdout);
3097 : break;
3098 :
3099 1173 : default:
3100 4692 : n = printf ("%4d%c%s",
3101 1173 : *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
3102 : (vername != NULL
3103 1173 : && (unsigned int) (*sym & 0x7fff) < nvername)
3104 1173 : ? vername[*sym & 0x7fff] : "???");
3105 1173 : if ((unsigned int) (*sym & 0x7fff) < nvername
3106 1173 : && filename != NULL && filename[*sym & 0x7fff] != NULL)
3107 1594 : n += printf ("(%s)", filename[*sym & 0x7fff]);
3108 1173 : 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 51 : for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
3166 : {
3167 41 : nzero_counts += counts[cnt] * cnt;
3168 123 : printf (gettext ("\
3169 : %7d %6" PRIu32 " %5.1f%% %5.1f%%\n"),
3170 41 : (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
3171 41 : (nzero_counts * 100.0) / nsyms);
3172 : }
3173 :
3174 : Elf32_Word acc = 0;
3175 41 : for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
3176 : {
3177 41 : acc += cnt;
3178 41 : 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 222 : Elf32_Word inner = bucket[cnt] - symbias;
3380 : do
3381 : {
3382 425 : ++nsyms;
3383 425 : if (maxlength < ++lengths[cnt])
3384 41 : ++maxlength;
3385 425 : if (inner >= max_nsyms)
3386 : goto invalid_data;
3387 : }
3388 425 : 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 607252 : 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 607252 : GElf_Off off = 0;
3734 1821728 : const char *name = (print_address_names && ! print_unresolved_addresses)
3735 607152 : ? dwfl_module_addrinfo (dwflmod, address, &off, &sym, NULL, NULL, NULL)
3736 1214404 : : NULL;
3737 :
3738 : const char *scn;
3739 607252 : if (print_unresolved_addresses)
3740 : {
3741 72 : address = raw;
3742 72 : scn = NULL;
3743 : }
3744 : else
3745 : {
3746 : /* Relativize the address. */
3747 607180 : int n = dwfl_module_relocations (dwflmod);
3748 607180 : 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 606180 : : dwfl_module_relocation_info (dwflmod, i, NULL));
3753 : }
3754 :
3755 607252 : if ((name != NULL
3756 596149 : ? (off != 0
3757 : ? (scn != NULL
3758 : ? (address_size == 0
3759 293160 : ? printf ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">",
3760 : scn, address, name, off)
3761 1273923 : : printf ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">",
3762 424641 : 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 53130 : : printf ("%s+%#0*" PRIx64 " <%s>",
3774 17710 : 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 11208 : ? printf ("%s+%#" PRIx64, scn, address)
3782 10678 : : printf ("%s+%#0*" PRIx64, scn, 2 + address_size * 2, address))
3783 : : (address_size == 0
3784 64 : ? printf ("%#" PRIx64, address)
3785 1810653 : : printf ("%#0*" PRIx64, 2 + address_size * 2, address)))) < 0)
3786 0 : error (EXIT_FAILURE, 0, _("sprintf failure"));
3787 607252 : }
3788 :
3789 :
3790 : static const char *
3791 772619 : dwarf_tag_string (unsigned int tag)
3792 : {
3793 772619 : 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 2722670 : dwarf_attr_string (unsigned int attrnum)
3806 : {
3807 2722670 : switch (attrnum)
3808 : {
3809 : #define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
3810 4383 : 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 2722676 : dwarf_form_string (unsigned int form)
3820 : {
3821 2722676 : 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 2859 : if (likely (code < sizeof (known) / sizeof (known[0])))
3857 2859 : 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 16417 : if (likely (code < sizeof (known) / sizeof (known[0])))
3874 16417 : 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 380372 : if (likely (code < sizeof (known) / sizeof (known[0])))
4030 380372 : 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 6238510 : 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 6238510 : 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 772619 : dwarf_tag_name (unsigned int tag)
4122 : {
4123 772619 : const char *ret = dwarf_tag_string (tag);
4124 772619 : return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true);
4125 : }
4126 :
4127 : static const char *
4128 2722670 : dwarf_attr_name (unsigned int attr)
4129 : {
4130 2722670 : const char *ret = dwarf_attr_string (attr);
4131 2722670 : return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true);
4132 : }
4133 :
4134 :
4135 : static const char *
4136 2722676 : dwarf_form_name (unsigned int form)
4137 : {
4138 2722676 : const char *ret = dwarf_form_string (form);
4139 2722676 : 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 2859 : const char *ret = dwarf_inline_string (code);
4155 2859 : 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 16417 : const char *ret = dwarf_encoding_string (code);
4163 16417 : 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 267298 : 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 267298 : const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
4323 :
4324 267298 : 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 647670 : while (len-- > 0)
4335 : {
4336 380372 : uint_fast8_t op = *data++;
4337 :
4338 760744 : const char *op_name = dwarf_locexpr_opcode_string (op);
4339 380372 : 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 380372 : switch (op)
4350 : {
4351 7461 : case DW_OP_addr:;
4352 : /* Address operand. */
4353 : Dwarf_Word addr;
4354 7461 : NEED (addrsize);
4355 7461 : if (addrsize == 4)
4356 28 : addr = read_4ubyte_unaligned (dbg, data);
4357 7443 : else if (addrsize == 8)
4358 7461 : addr = read_8ubyte_unaligned (dbg, data);
4359 : else
4360 : goto invalid;
4361 7461 : data += addrsize;
4362 7461 : CONSUME (addrsize);
4363 :
4364 7461 : printf ("%*s[%2" PRIuMAX "] %s ",
4365 : indent, "", (uintmax_t) offset, op_name);
4366 7461 : print_dwarf_addr (dwflmod, 0, addr, addr);
4367 7461 : printf ("\n");
4368 :
4369 7461 : offset += 1 + addrsize;
4370 387833 : 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 9509 : 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 9509 : NEED (1);
4397 19018 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 "\n",
4398 : indent, "", (uintmax_t) offset,
4399 9509 : op_name, *((uint8_t *) data));
4400 9509 : ++data;
4401 9509 : --len;
4402 9509 : offset += 2;
4403 9509 : break;
4404 :
4405 948 : case DW_OP_const2u:
4406 948 : NEED (2);
4407 : // XXX value might be modified by relocation
4408 2844 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu16 "\n",
4409 : indent, "", (uintmax_t) offset,
4410 1896 : op_name, read_2ubyte_unaligned (dbg, data));
4411 948 : CONSUME (2);
4412 948 : data += 2;
4413 948 : offset += 3;
4414 948 : break;
4415 :
4416 576 : case DW_OP_const4u:
4417 576 : NEED (4);
4418 : // XXX value might be modified by relocation
4419 1728 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu32 "\n",
4420 : indent, "", (uintmax_t) offset,
4421 1152 : op_name, read_4ubyte_unaligned (dbg, data));
4422 576 : CONSUME (4);
4423 576 : data += 4;
4424 576 : offset += 5;
4425 576 : 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 2107 : case DW_OP_const1s:
4439 2107 : NEED (1);
4440 : // XXX value might be modified by relocation
4441 4214 : printf ("%*s[%2" PRIuMAX "] %s %" PRId8 "\n",
4442 : indent, "", (uintmax_t) offset,
4443 2107 : op_name, *((int8_t *) data));
4444 2107 : ++data;
4445 2107 : --len;
4446 2107 : offset += 2;
4447 2107 : 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 7815 : case DW_OP_piece:
4483 : case DW_OP_regx:
4484 : case DW_OP_plus_uconst:
4485 : case DW_OP_constu:;
4486 7815 : const unsigned char *start = data;
4487 : uint64_t uleb;
4488 7815 : NEED (1);
4489 7815 : get_uleb128 (uleb, data, data + len);
4490 7815 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
4491 : indent, "", (uintmax_t) offset, op_name, uleb);
4492 7815 : CONSUME (data - start);
4493 7815 : offset += 1 + (data - start);
4494 7815 : 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 68809 : case DW_OP_fbreg:
4530 : case DW_OP_breg0 ... DW_OP_breg31:
4531 : case DW_OP_consts:
4532 68809 : start = data;
4533 : int64_t sleb;
4534 68809 : NEED (1);
4535 68809 : get_sleb128 (sleb, data, data + len);
4536 68809 : printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
4537 : indent, "", (uintmax_t) offset, op_name, sleb);
4538 68809 : CONSUME (data - start);
4539 68809 : offset += 1 + (data - start);
4540 68809 : 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 269 : case DW_OP_skip:
4575 : case DW_OP_bra:
4576 269 : NEED (2);
4577 269 : printf ("%*s[%2" PRIuMAX "] %s %" PRIuMAX "\n",
4578 : indent, "", (uintmax_t) offset, op_name,
4579 269 : (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
4580 269 : CONSUME (2);
4581 269 : data += 2;
4582 269 : offset += 3;
4583 269 : 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 3542 : case DW_OP_implicit_pointer:
4599 : case DW_OP_GNU_implicit_pointer:
4600 : /* DIE offset operand. */
4601 3542 : start = data;
4602 3542 : NEED (ref_size);
4603 3542 : if (ref_size != 4 && ref_size != 8)
4604 : goto invalid; /* Cannot be used in CFA. */
4605 3542 : if (ref_size == 4)
4606 3542 : addr = read_4ubyte_unaligned (dbg, data);
4607 : else
4608 0 : addr = read_8ubyte_unaligned (dbg, data);
4609 3542 : data += ref_size;
4610 : /* Byte offset operand. */
4611 3542 : NEED (1);
4612 3542 : get_sleb128 (sleb, data, data + len);
4613 :
4614 7084 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
4615 : indent, "", (intmax_t) offset,
4616 : op_name, (uintmax_t) addr, sleb);
4617 3542 : CONSUME (data - start);
4618 3542 : offset += 1 + (data - start);
4619 3542 : break;
4620 :
4621 20399 : case DW_OP_entry_value:
4622 : case DW_OP_GNU_entry_value:
4623 : /* Size plus expression block. */
4624 20399 : start = data;
4625 20399 : NEED (1);
4626 20399 : get_uleb128 (uleb, data, data + len);
4627 20399 : printf ("%*s[%2" PRIuMAX "] %s:\n",
4628 : indent, "", (uintmax_t) offset, op_name);
4629 20399 : NEED (uleb);
4630 20399 : print_ops (dwflmod, dbg, indent + 5, indent + 5, vers,
4631 : addrsize, offset_size, cu, uleb, data);
4632 20399 : data += uleb;
4633 20399 : CONSUME (data - start);
4634 20399 : offset += 1 + (data - start);
4635 20399 : 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 258422 : default:
4738 : /* No Operand. */
4739 258422 : printf ("%*s[%2" PRIuMAX "] %s\n",
4740 : indent, "", (uintmax_t) offset, op_name);
4741 258422 : ++offset;
4742 258422 : break;
4743 : }
4744 :
4745 380372 : indent = indentrest;
4746 380372 : 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 57510 : 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 57510 : 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 57510 : return base;
4786 : }
4787 :
4788 : static Dwarf_Addr
4789 57510 : listptr_base (struct listptr *p)
4790 : {
4791 115020 : Dwarf_Die cu = CUDIE (p->cu);
4792 57510 : return cudie_base (&cu);
4793 : }
4794 :
4795 : static int
4796 319295 : compare_listptr (const void *a, const void *b, void *arg)
4797 : {
4798 319295 : const char *name = arg;
4799 319295 : struct listptr *p1 = (void *) a;
4800 319295 : struct listptr *p2 = (void *) b;
4801 :
4802 319295 : if (p1->offset < p2->offset)
4803 : return -1;
4804 21006 : if (p1->offset > p2->offset)
4805 : return 1;
4806 :
4807 4241 : if (!p1->warned && !p2->warned)
4808 : {
4809 4241 : 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 4241 : 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 4241 : 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 4241 : 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 53200 : 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 53200 : if (print_debug_sections & section)
4873 : {
4874 53099 : if (table->n == table->alloc)
4875 : {
4876 176 : if (table->alloc == 0)
4877 81 : table->alloc = 128;
4878 : else
4879 95 : table->alloc *= 2;
4880 176 : table->table = xrealloc (table->table,
4881 176 : table->alloc * sizeof table->table[0]);
4882 : }
4883 :
4884 53099 : struct listptr *p = &table->table[table->n++];
4885 :
4886 106198 : *p = (struct listptr)
4887 : {
4888 53099 : .addr64 = address_size == 8,
4889 53099 : .dwarf64 = offset_size == 8,
4890 : .offset = offset,
4891 : .cu = cu,
4892 : .attr = attr
4893 : };
4894 :
4895 53099 : 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 49022 : 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 49022 : if (table->n == 0)
4920 : return false;
4921 :
4922 102020 : while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
4923 52998 : ++*idxp;
4924 :
4925 49022 : struct listptr *p = &table->table[*idxp];
4926 :
4927 49022 : if (*idxp == table->n
4928 49022 : || 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 49022 : 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 49022 : if (address_sizep != NULL)
4945 49022 : *address_sizep = listptr_address_size (p);
4946 49022 : if (offset_sizep != NULL)
4947 40092 : *offset_sizep = listptr_offset_size (p);
4948 49022 : if (base != NULL)
4949 49022 : *base = listptr_base (p);
4950 49022 : if (cu != NULL)
4951 49022 : *cu = p->cu;
4952 49022 : if (attr != NULL)
4953 40092 : *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 56876 : {
5030 : size_t length;
5031 : Dwarf_Abbrev abbrev;
5032 :
5033 57963 : int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
5034 57963 : 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 56876 : unsigned int code = dwarf_getabbrevcode (&abbrev);
5051 56876 : unsigned int tag = dwarf_getabbrevtag (&abbrev);
5052 56876 : int has_children = dwarf_abbrevhaschildren (&abbrev);
5053 :
5054 113752 : 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 56876 : size_t cnt = 0;
5061 : unsigned int name;
5062 : unsigned int form;
5063 : Dwarf_Sword data;
5064 : Dwarf_Off enoffset;
5065 333733 : while (dwarf_getabbrevattr_data (&abbrev, cnt, &name, &form,
5066 : &data, &enoffset) == 0)
5067 : {
5068 439962 : printf (" attr: %s, form: %s",
5069 : dwarf_attr_name (name), dwarf_form_name (form));
5070 219981 : if (form == DW_FORM_implicit_const)
5071 0 : printf (" (%" PRId64 ")", data);
5072 439962 : printf (", offset: %#" PRIx64 "\n", (uint64_t) enoffset);
5073 219981 : ++cnt;
5074 : }
5075 :
5076 56876 : 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 1084 : 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 38193 : while (readp < endp)
5964 : {
5965 38133 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
5966 38133 : Dwarf_CU *cu = last_cu;
5967 :
5968 38133 : 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 38133 : if (last_cu != cu)
5974 : {
5975 : Dwarf_Die cudie;
5976 585 : 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 585 : printf (gettext ("\n CU [%6" PRIx64 "] base: "),
5982 : dwarf_dieoffset (&cudie));
5983 585 : print_dwarf_addr (dwflmod, address_size, base, base);
5984 585 : printf ("\n");
5985 : }
5986 38133 : last_cu = cu;
5987 :
5988 38133 : 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 38133 : if (address_size == 8)
5997 : {
5998 38133 : begin = read_8ubyte_unaligned_inc (dbg, readp);
5999 38133 : 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 38133 : 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 38133 : else if (begin == 0 && end == 0) /* End of list entry. */
6017 : {
6018 8930 : 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 29203 : if (first) /* First address range entry in a list. */
6026 : printf (" [%6tx] ", offset);
6027 : else
6028 : printf (" ");
6029 :
6030 29203 : printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
6031 29203 : if (! print_unresolved_addresses)
6032 : {
6033 29193 : printf (" ");
6034 29193 : print_dwarf_addr (dwflmod, address_size, base + begin,
6035 : base + begin);
6036 29193 : printf ("..\n ");
6037 29193 : 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 9703 : 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 9703 : ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
6056 : bits ?: &ignore, type ?: &ignore);
6057 9703 : 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 9703 : if (bits != NULL && *bits <= 0)
6072 0 : *bits = loc != NULL ? loc->bits : 0;
6073 9703 : if (type != NULL && *type == DW_ATE_void)
6074 0 : *type = DW_ATE_unsigned;
6075 :
6076 : }
6077 9703 : 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 4631 : 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 8855 : register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
6148 : return regnamebuf;
6149 : }
6150 :
6151 4631 : puts ("\n Program:");
6152 4631 : Dwarf_Word pc = vma_base;
6153 85567 : while (readp < endp)
6154 : {
6155 76305 : unsigned int opcode = *readp++;
6156 :
6157 76305 : if (opcode < DW_CFA_advance_loc)
6158 : /* Extended opcode. */
6159 43983 : switch (opcode)
6160 : {
6161 : uint64_t op1;
6162 : int64_t sop1;
6163 : uint64_t op2;
6164 : int64_t sop2;
6165 :
6166 12910 : case DW_CFA_nop:
6167 12910 : puts (" nop");
6168 56893 : 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 1661 : case DW_CFA_advance_loc1:
6177 1661 : if ((uint64_t) (endp - readp) < 1)
6178 : goto invalid;
6179 3322 : printf (" advance_loc1 %u to %#" PRIx64 "\n",
6180 1661 : *readp, pc += *readp * code_align);
6181 1661 : ++readp;
6182 1661 : break;
6183 761 : case DW_CFA_advance_loc2:
6184 761 : if ((uint64_t) (endp - readp) < 2)
6185 : goto invalid;
6186 761 : op1 = read_2ubyte_unaligned_inc (dbg, readp);
6187 761 : printf (" advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
6188 761 : 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 2616 : case DW_CFA_remember_state:
6238 2616 : puts (" remember_state");
6239 2616 : break;
6240 2616 : case DW_CFA_restore_state:
6241 2616 : puts (" restore_state");
6242 2616 : 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 23187 : case DW_CFA_def_cfa_offset:
6261 23187 : if ((uint64_t) (endp - readp) < 1)
6262 : goto invalid;
6263 23187 : get_uleb128 (op1, readp, endp);
6264 23187 : 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 32322 : else if (opcode < DW_CFA_offset)
6379 23663 : printf (" advance_loc %u to %#" PRIx64 "\n",
6380 23663 : opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
6381 8659 : else if (opcode < DW_CFA_restore)
6382 : {
6383 : uint64_t offset;
6384 7341 : if ((uint64_t) (endp - readp) < 1)
6385 : goto invalid;
6386 7341 : get_uleb128 (offset, readp, endp);
6387 14682 : printf (" offset r%u (%s) at cfa%+" PRId64 "\n",
6388 : opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
6389 : }
6390 : else
6391 2636 : printf (" restore r%u (%s)\n",
6392 : opcode & 0x3f, regname (opcode & 0x3f));
6393 : }
6394 : }
6395 :
6396 :
6397 : static unsigned int
6398 4559 : encoded_ptr_size (int encoding, unsigned int ptr_size)
6399 : {
6400 4559 : 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 4741 : while (readp < dataend)
6569 : {
6570 4645 : 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 4645 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
6581 :
6582 4689 : Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
6583 4645 : unsigned int length = 4;
6584 4645 : 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 4645 : if (unlikely (unit_length == 0))
6594 : {
6595 28 : printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
6596 14 : continue;
6597 : }
6598 :
6599 4631 : Dwarf_Word maxsize = dataend - readp;
6600 4631 : if (unlikely (unit_length > maxsize))
6601 : goto invalid_data;
6602 :
6603 4631 : unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6604 :
6605 4631 : ptrdiff_t start = readp - (unsigned char *) data->d_buf;
6606 4631 : const unsigned char *const cieend = readp + unit_length;
6607 4631 : if (unlikely (cieend > dataend))
6608 : goto invalid_data;
6609 :
6610 : Dwarf_Off cie_id;
6611 4631 : if (length == 4)
6612 : {
6613 4631 : if (unlikely (cieend - readp < 4))
6614 : goto invalid_data;
6615 4675 : cie_id = read_4ubyte_unaligned_inc (dbg, readp);
6616 4631 : 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 4631 : uint_fast8_t version = 2;
6627 : unsigned int code_alignment_factor;
6628 : int data_alignment_factor;
6629 4631 : unsigned int fde_encoding = 0;
6630 4631 : unsigned int lsda_encoding = 0;
6631 4631 : Dwarf_Word initial_location = 0;
6632 4631 : Dwarf_Word vma_base = 0;
6633 :
6634 4631 : 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 4559 : while (cie != NULL)
6774 9118 : if (is_eh_frame
6775 4521 : ? ((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 4559 : if (unlikely (cie == NULL))
6781 : {
6782 0 : puts ("invalid CIE reference in FDE");
6783 0 : return;
6784 : }
6785 :
6786 : /* Initialize from CIE data. */
6787 4559 : fde_encoding = cie->fde_encoding;
6788 4559 : lsda_encoding = cie->lsda_encoding;
6789 4559 : ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
6790 4559 : code_alignment_factor = cie->code_alignment_factor;
6791 4559 : data_alignment_factor = cie->data_alignment_factor;
6792 :
6793 4559 : const unsigned char *base = readp;
6794 : // XXX There are sometimes relocations for this value
6795 4581 : initial_location = read_addr_unaligned_inc (ptr_size, dbg, readp);
6796 4559 : Dwarf_Word address_range
6797 4581 : = 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 4559 : Dwarf_Addr pc_start = initial_location;
6805 4559 : if (ptr_size == 4)
6806 4519 : pc_start = (uint64_t) (int32_t) pc_start;
6807 4559 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
6808 9030 : pc_start += ((uint64_t) shdr->sh_addr
6809 4515 : + (base - (const unsigned char *) data->d_buf)
6810 4515 : - bias);
6811 :
6812 9118 : 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 4559 : print_dwarf_addr (dwflmod, cie->address_size,
6818 : pc_start, initial_location);
6819 4559 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
6820 : {
6821 9030 : vma_base = (((uint64_t) shdr->sh_offset
6822 4515 : + (base - (const unsigned char *) data->d_buf)
6823 4515 : + (uint64_t) initial_location)
6824 : & (ptr_size == 4
6825 : ? UINT64_C (0xffffffff)
6826 4515 : : UINT64_C (0xffffffffffffffff)));
6827 4515 : printf (gettext (" (offset: %#" PRIx64 ")"),
6828 : (uint64_t) vma_base);
6829 : }
6830 :
6831 4559 : printf ("\n address_range: %#" PRIx64,
6832 : (uint64_t) address_range);
6833 4559 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
6834 4515 : printf (gettext (" (end offset: %#" PRIx64 ")"),
6835 4515 : ((uint64_t) vma_base + (uint64_t) address_range)
6836 : & (ptr_size == 4
6837 : ? UINT64_C (0xffffffff)
6838 4515 : : UINT64_C (0xffffffffffffffff)));
6839 4559 : putchar ('\n');
6840 :
6841 4559 : if (cie->augmentation[0] == 'z')
6842 : {
6843 : unsigned int augmentationlen;
6844 4515 : if (cieend - readp < 1)
6845 : goto invalid_data;
6846 4515 : get_uleb128 (augmentationlen, readp, cieend);
6847 :
6848 4515 : 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 4515 : 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 4515 : readp += augmentationlen;
6887 : }
6888 : }
6889 :
6890 : /* Handle the initialization instructions. */
6891 4631 : 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 4631 : print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
6895 : data_alignment_factor, version, ptr_size,
6896 : fde_encoding, dwflmod, ebl, dbg);
6897 4631 : 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 100207 : die_type_sign_bytes (Dwarf_Die *die, bool *is_signed, int *bytes)
6907 : {
6908 : Dwarf_Attribute attr;
6909 : Dwarf_Die type;
6910 :
6911 100207 : *bytes = 0;
6912 100207 : *is_signed = false;
6913 :
6914 100207 : 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 100207 : }
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 2507048 : attr_callback (Dwarf_Attribute *attrp, void *arg)
6946 : {
6947 2507048 : struct attrcb_args *cbargs = (struct attrcb_args *) arg;
6948 2507048 : const int level = cbargs->level;
6949 2507048 : Dwarf_Die *die = cbargs->die;
6950 2507048 : bool is_split = cbargs->is_split;
6951 :
6952 2507048 : unsigned int attr = dwarf_whatattr (attrp);
6953 2507048 : 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 2507048 : unsigned int form = dwarf_whatform (attrp);
6963 2507048 : 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 2507048 : switch (form)
6973 : {
6974 39542 : 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 39542 : if (!cbargs->silent)
6982 : {
6983 : Dwarf_Addr addr;
6984 39273 : 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 39273 : 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 39265 : printf (" %*s%-20s (%s) ",
7009 : (int) (level * 2), "", dwarf_attr_name (attr),
7010 : dwarf_form_name (form));
7011 39273 : print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr, addr);
7012 39273 : printf ("\n");
7013 : }
7014 2247020 : break;
7015 :
7016 466328 : 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 466328 : if (cbargs->silent)
7028 : break;
7029 465580 : const char *str = dwarf_formstring (attrp);
7030 465580 : if (unlikely (str == NULL))
7031 : goto attrval_out;
7032 465580 : printf (" %*s%-20s (%s) \"%s\"\n",
7033 : (int) (level * 2), "", dwarf_attr_name (attr),
7034 : dwarf_form_name (form), str);
7035 : break;
7036 :
7037 595253 : 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 595253 : if (cbargs->silent)
7047 : break;
7048 : Dwarf_Die ref;
7049 594466 : if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
7050 : goto attrval_out;
7051 :
7052 1188932 : printf (" %*s%-20s (%s) ",
7053 : (int) (level * 2), "", dwarf_attr_name (attr),
7054 : dwarf_form_name (form));
7055 594466 : if (is_split)
7056 33 : printf ("{%6" PRIxMAX "}\n", (uintmax_t) dwarf_dieoffset (&ref));
7057 : else
7058 594433 : 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 1248084 : 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 1248084 : if (unlikely (dwarf_formudata (attrp, &num) != 0))
7082 : goto attrval_out;
7083 :
7084 1248084 : const char *valuestr = NULL;
7085 1248084 : bool as_hex_id = false;
7086 1248084 : switch (attr)
7087 : {
7088 : /* This case can take either a constant or a loclistptr. */
7089 206763 : case DW_AT_data_member_location:
7090 206763 : if (form != DW_FORM_sec_offset
7091 206763 : && (cbargs->version >= 4
7092 23806 : || (form != DW_FORM_data4 && form != DW_FORM_data8)))
7093 : {
7094 206763 : if (!cbargs->silent)
7095 206763 : 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 42224 : if (cbargs->cu->version < 5)
7120 : {
7121 42153 : if (! cbargs->is_split)
7122 : {
7123 126399 : nlpt = notice_listptr (section_loc, &known_locsptr,
7124 42133 : cbargs->addrsize,
7125 42133 : 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 42224 : if (!cbargs->silent)
7148 : {
7149 42043 : if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
7150 42036 : 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 11019 : case DW_AT_ranges:
7179 : case DW_AT_start_scope:
7180 : {
7181 : bool nlpt;
7182 11019 : if (cbargs->cu->version < 5)
7183 33009 : nlpt = notice_listptr (section_ranges, &known_rangelistptr,
7184 22006 : 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 11019 : if (!cbargs->silent)
7202 : {
7203 10977 : if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
7204 10975 : 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 16417 : case DW_AT_encoding:
7267 32834 : valuestr = dwarf_encoding_name (num);
7268 16417 : 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 2859 : case DW_AT_inline:
7288 5718 : valuestr = dwarf_inline_name (num);
7289 2859 : 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 366893 : case DW_AT_decl_file:
7297 : case DW_AT_call_file:
7298 366893 : {
7299 366893 : 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 366472 : 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 366472 : if (dwarf_getsrcfiles (&cudie, &files, &nfiles) == 0)
7312 : {
7313 366472 : valuestr = dwarf_filesrc (files, num, NULL, NULL);
7314 366472 : if (valuestr != NULL)
7315 : {
7316 366472 : char *filename = strrchr (valuestr, '/');
7317 366472 : if (filename != NULL)
7318 366472 : 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 366472 : if (valuestr == NULL)
7332 : valuestr = "???";
7333 : }
7334 366472 : 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 988056 : 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 986215 : if (attr == DW_AT_high_pc && dwarf_highpc (cbargs->die, &highpc) == 0)
7351 : {
7352 27524 : printf (" %*s%-20s (%s) %" PRIuMAX " (",
7353 : (int) (level * 2), "", dwarf_attr_name (attr),
7354 : dwarf_form_name (form), (uintmax_t) num);
7355 13762 : print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, highpc, highpc);
7356 : printf (")\n");
7357 : }
7358 : else
7359 : {
7360 972453 : 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 972451 : {
7368 972451 : Dwarf_Sword snum = 0;
7369 : bool is_signed;
7370 972451 : int bytes = 0;
7371 972451 : if (attr == DW_AT_const_value)
7372 100207 : die_type_sign_bytes (cbargs->die, &is_signed, &bytes);
7373 : else
7374 1744488 : is_signed = (form == DW_FORM_sdata
7375 872244 : || form == DW_FORM_implicit_const);
7376 :
7377 972451 : if (is_signed)
7378 144 : if (unlikely (dwarf_formsdata (attrp, &snum) != 0))
7379 : goto attrval_out;
7380 :
7381 972451 : if (valuestr == NULL)
7382 : {
7383 585854 : printf (" %*s%-20s (%s) ",
7384 : (int) (level * 2), "", dwarf_attr_name (attr),
7385 : dwarf_form_name (form));
7386 : }
7387 : else
7388 : {
7389 386597 : printf (" %*s%-20s (%s) %s (",
7390 : (int) (level * 2), "", dwarf_attr_name (attr),
7391 : dwarf_form_name (form), valuestr);
7392 : }
7393 :
7394 972451 : 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 972244 : default:
7425 972244 : if (is_signed)
7426 21 : printf ("%" PRIdMAX, (intmax_t) snum);
7427 : else
7428 972223 : 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 972451 : if (attr == DW_AT_const_value
7435 100207 : && (form == DW_FORM_sdata || form == DW_FORM_implicit_const)
7436 1227 : && !is_signed)
7437 1219 : printf (" (%" PRIdMAX ")", (intmax_t) num);
7438 :
7439 972451 : 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 65933 : case DW_FORM_flag_present:
7460 65933 : if (cbargs->silent)
7461 : break;
7462 65659 : 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 82782 : 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 82782 : if (cbargs->silent)
7474 : break;
7475 : Dwarf_Block block;
7476 82653 : if (unlikely (dwarf_formblock (attrp, &block) != 0))
7477 : goto attrval_out;
7478 :
7479 165306 : printf (" %*s%-20s (%s) ",
7480 : (int) (level * 2), "", dwarf_attr_name (attr),
7481 : dwarf_form_name (form));
7482 :
7483 82653 : 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 82637 : if (form != DW_FORM_data16)
7517 : {
7518 82637 : putchar ('\n');
7519 165274 : print_ops (cbargs->dwflmod, cbargs->dbg,
7520 82637 : 12 + level * 2, 12 + level * 2,
7521 : cbargs->version, cbargs->addrsize, cbargs->offset_size,
7522 82637 : 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 2247020 : 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 715566 : do_cu:
7693 : do
7694 : {
7695 716731 : Dwarf_Off offset = dwarf_dieoffset (&dies[level]);
7696 716731 : 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 716731 : int tag = dwarf_tag (&dies[level]);
7705 716731 : 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 716731 : if (!silent)
7715 : {
7716 715743 : unsigned int code = dwarf_getabbrevcode (dies[level].abbrev);
7717 715743 : if (is_split)
7718 : printf (" {%6" PRIx64 "} ", (uint64_t) offset);
7719 : else
7720 : printf (" [%6" PRIx64 "] ", (uint64_t) offset);
7721 715743 : printf ("%*s%-20s abbrev: %u\n", (int) (level * 2), "",
7722 : dwarf_tag_name (tag), code);
7723 : }
7724 :
7725 : /* Print the attribute values. */
7726 716731 : args.level = level;
7727 716731 : args.die = &dies[level];
7728 716731 : (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
7729 :
7730 : /* Make room for the next level's DIE. */
7731 716731 : if (level + 1 == maxdies)
7732 0 : dies = (Dwarf_Die *) xrealloc (dies,
7733 0 : (maxdies += 10)
7734 : * sizeof (Dwarf_Die));
7735 :
7736 716731 : int res = dwarf_child (&dies[level], &dies[level + 1]);
7737 716731 : if (res > 0)
7738 : {
7739 716731 : while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
7740 102282 : if (level-- == 0)
7741 : break;
7742 :
7743 615614 : 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 101117 : 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 716731 : 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 1097 : 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 8148 : while (*linep != 0)
8448 : {
8449 7053 : unsigned char *endp = memchr (linep, '\0', lineendp - linep);
8450 7053 : if (unlikely (endp == NULL))
8451 : goto invalid_unit;
8452 :
8453 14106 : printf (" %s\n", (char *) linep);
8454 :
8455 7053 : linep = endp + 1;
8456 : }
8457 : /* Skip the final NUL byte. */
8458 1095 : ++linep;
8459 : }
8460 :
8461 1097 : if (unlikely (linep >= lineendp))
8462 : goto invalid_unit;
8463 :
8464 1097 : puts (gettext ("\nFile name table:"));
8465 1097 : if (version > 4)
8466 : {
8467 : struct encpair { uint16_t desc; uint16_t form; };
8468 : struct encpair enc[256];
8469 :
8470 4 : printf (gettext (" ["));
8471 2 : if ((size_t) (lineendp - linep) < 1)
8472 : goto invalid_data;
8473 2 : unsigned char file_name_format_count = *linep++;
8474 8 : for (int i = 0; i < file_name_format_count; i++)
8475 : {
8476 : uint64_t desc, form;
8477 4 : if ((size_t) (lineendp - linep) < 1)
8478 : goto invalid_data;
8479 4 : get_uleb128 (desc, linep, lineendp);
8480 4 : if ((size_t) (lineendp - linep) < 1)
8481 : goto invalid_data;
8482 4 : get_uleb128 (form, linep, lineendp);
8483 :
8484 4 : if (! libdw_valid_user_form (form))
8485 : goto invalid_data;
8486 :
8487 : enc[i].desc = desc;
8488 4 : enc[i].form = form;
8489 :
8490 8 : printf ("%s(%s)",
8491 : dwarf_line_content_description_name (desc),
8492 : dwarf_form_name (form));
8493 4 : if (i + 1 < file_name_format_count)
8494 : printf (", ");
8495 : }
8496 2 : printf ("]\n");
8497 :
8498 : uint64_t file_name_count;
8499 2 : if ((size_t) (lineendp - linep) < 1)
8500 : goto invalid_data;
8501 2 : get_uleb128 (file_name_count, linep, lineendp);
8502 :
8503 4 : if (file_name_format_count == 0
8504 2 : && file_name_count != 0)
8505 : goto invalid_data;
8506 :
8507 8 : for (uint64_t i = 0; i < file_name_count; i++)
8508 : {
8509 8 : printf (" %-5" PRIu64 " ", i);
8510 32 : for (int j = 0; j < file_name_format_count; j++)
8511 : {
8512 16 : linep = print_form_data (dbg, enc[j].form,
8513 : linep, lineendp, length,
8514 : str_offsets_base);
8515 16 : if (j + 1 < file_name_format_count)
8516 : printf (", ");
8517 : }
8518 8 : printf ("\n");
8519 8 : if (linep >= lineendp)
8520 : goto invalid_unit;
8521 : }
8522 : }
8523 : else
8524 : {
8525 1095 : puts (gettext (" Entry Dir Time Size Name"));
8526 22156 : for (unsigned int cnt = 1; *linep != 0; ++cnt)
8527 : {
8528 : /* First comes the file name. */
8529 21061 : char *fname = (char *) linep;
8530 21061 : unsigned char *endp = memchr (fname, '\0', lineendp - linep);
8531 21061 : if (unlikely (endp == NULL))
8532 : goto invalid_unit;
8533 21061 : linep = endp + 1;
8534 :
8535 : /* Then the index. */
8536 : unsigned int diridx;
8537 21061 : if (lineendp - linep < 1)
8538 : goto invalid_unit;
8539 21061 : get_uleb128 (diridx, linep, lineendp);
8540 :
8541 : /* Next comes the modification time. */
8542 : unsigned int mtime;
8543 21061 : if (lineendp - linep < 1)
8544 : goto invalid_unit;
8545 21061 : get_uleb128 (mtime, linep, lineendp);
8546 :
8547 : /* Finally the length of the file. */
8548 : unsigned int fsize;
8549 21061 : if (lineendp - linep < 1)
8550 : goto invalid_unit;
8551 21061 : get_uleb128 (fsize, linep, lineendp);
8552 :
8553 21061 : printf (" %-5u %-5u %-9u %-9u %s\n",
8554 : cnt, diridx, mtime, fsize, fname);
8555 : }
8556 : /* Skip the final NUL byte. */
8557 1095 : ++linep;
8558 : }
8559 :
8560 1097 : puts (gettext ("\nLine number statements:"));
8561 : Dwarf_Word address = 0;
8562 : unsigned int op_index = 0;
8563 1097 : size_t line = 1;
8564 1097 : uint_fast8_t is_stmt = default_is_stmt;
8565 :
8566 : /* Apply the "operation advance" from a special opcode
8567 : or DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */
8568 : unsigned int op_addr_advance;
8569 : bool show_op_index;
8570 : inline void advance_pc (unsigned int op_advance)
8571 : {
8572 300062 : op_addr_advance = minimum_instr_len * ((op_index + op_advance)
8573 150031 : / max_ops_per_instr);
8574 150031 : address += op_addr_advance;
8575 300062 : show_op_index = (op_index > 0 ||
8576 150031 : (op_index + op_advance) % max_ops_per_instr > 0);
8577 150031 : op_index = (op_index + op_advance) % max_ops_per_instr;
8578 : }
8579 :
8580 1097 : if (max_ops_per_instr == 0)
8581 : {
8582 0 : error (0, 0,
8583 0 : gettext ("invalid maximum operations per instruction is zero"));
8584 0 : linep = lineendp;
8585 0 : continue;
8586 : }
8587 :
8588 243402 : while (linep < lineendp)
8589 : {
8590 242305 : size_t offset = linep - (const unsigned char *) data->d_buf;
8591 : unsigned int u128;
8592 : int s128;
8593 :
8594 : /* Read the opcode. */
8595 242305 : unsigned int opcode = *linep++;
8596 :
8597 242305 : printf (" [%6" PRIx64 "]", (uint64_t)offset);
8598 : /* Is this a special opcode? */
8599 242305 : if (likely (opcode >= opcode_base))
8600 : {
8601 111302 : if (unlikely (line_range == 0))
8602 : goto invalid_unit;
8603 :
8604 : /* Yes. Handling this is quite easy since the opcode value
8605 : is computed with
8606 :
8607 : opcode = (desired line increment - line_base)
8608 : + (line_range * address advance) + opcode_base
8609 : */
8610 111302 : int line_increment = (line_base
8611 111302 : + (opcode - opcode_base) % line_range);
8612 :
8613 : /* Perform the increments. */
8614 111302 : line += line_increment;
8615 222604 : advance_pc ((opcode - opcode_base) / line_range);
8616 :
8617 222604 : printf (gettext (" special opcode %u: address+%u = "),
8618 : opcode, op_addr_advance);
8619 111302 : print_dwarf_addr (dwflmod, 0, address, address);
8620 111302 : if (show_op_index)
8621 0 : printf (gettext (", op_index = %u, line%+d = %zu\n"),
8622 : op_index, line_increment, line);
8623 : else
8624 111302 : printf (gettext (", line%+d = %zu\n"),
8625 : line_increment, line);
8626 : }
8627 131003 : else if (opcode == 0)
8628 : {
8629 : /* This an extended opcode. */
8630 12846 : if (unlikely (linep + 2 > lineendp))
8631 : goto invalid_unit;
8632 :
8633 : /* The length. */
8634 12846 : unsigned int len = *linep++;
8635 :
8636 12846 : if (unlikely (linep + len > lineendp))
8637 : goto invalid_unit;
8638 :
8639 : /* The sub-opcode. */
8640 12846 : opcode = *linep++;
8641 :
8642 25692 : printf (gettext (" extended opcode %u: "), opcode);
8643 :
8644 12846 : switch (opcode)
8645 : {
8646 1126 : case DW_LNE_end_sequence:
8647 1126 : puts (gettext (" end of sequence"));
8648 :
8649 : /* Reset the registers we care about. */
8650 : address = 0;
8651 : op_index = 0;
8652 1126 : line = 1;
8653 1126 : is_stmt = default_is_stmt;
8654 1126 : break;
8655 :
8656 1254 : case DW_LNE_set_address:
8657 : op_index = 0;
8658 1254 : if (unlikely ((size_t) (lineendp - linep) < address_size))
8659 : goto invalid_unit;
8660 1254 : if (address_size == 4)
8661 17 : address = read_4ubyte_unaligned_inc (dbg, linep);
8662 : else
8663 1256 : address = read_8ubyte_unaligned_inc (dbg, linep);
8664 : {
8665 2508 : printf (gettext (" set address to "));
8666 1254 : print_dwarf_addr (dwflmod, 0, address, address);
8667 : printf ("\n");
8668 : }
8669 : break;
8670 :
8671 0 : case DW_LNE_define_file:
8672 : {
8673 0 : char *fname = (char *) linep;
8674 0 : unsigned char *endp = memchr (linep, '\0',
8675 0 : lineendp - linep);
8676 0 : if (unlikely (endp == NULL))
8677 : goto invalid_unit;
8678 0 : linep = endp + 1;
8679 :
8680 : unsigned int diridx;
8681 0 : if (lineendp - linep < 1)
8682 : goto invalid_unit;
8683 0 : get_uleb128 (diridx, linep, lineendp);
8684 : Dwarf_Word mtime;
8685 0 : if (lineendp - linep < 1)
8686 : goto invalid_unit;
8687 0 : get_uleb128 (mtime, linep, lineendp);
8688 : Dwarf_Word filelength;
8689 0 : if (lineendp - linep < 1)
8690 : goto invalid_unit;
8691 0 : get_uleb128 (filelength, linep, lineendp);
8692 :
8693 0 : printf (gettext ("\
8694 : define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
8695 : diridx, (uint64_t) mtime, (uint64_t) filelength,
8696 : fname);
8697 : }
8698 : break;
8699 :
8700 10466 : case DW_LNE_set_discriminator:
8701 : /* Takes one ULEB128 parameter, the discriminator. */
8702 10466 : if (unlikely (standard_opcode_lengths[opcode] != 1))
8703 : goto invalid_unit;
8704 :
8705 10466 : get_uleb128 (u128, linep, lineendp);
8706 10466 : printf (gettext (" set discriminator to %u\n"), u128);
8707 : break;
8708 :
8709 0 : default:
8710 : /* Unknown, ignore it. */
8711 0 : puts (gettext (" unknown opcode"));
8712 0 : linep += len - 1;
8713 0 : break;
8714 : }
8715 : }
8716 118157 : else if (opcode <= DW_LNS_set_isa)
8717 : {
8718 : /* This is a known standard opcode. */
8719 118157 : switch (opcode)
8720 : {
8721 8388 : case DW_LNS_copy:
8722 : /* Takes no argument. */
8723 8388 : puts (gettext (" copy"));
8724 8388 : break;
8725 :
8726 12204 : case DW_LNS_advance_pc:
8727 : /* Takes one uleb128 parameter which is added to the
8728 : address. */
8729 12204 : get_uleb128 (u128, linep, lineendp);
8730 12204 : advance_pc (u128);
8731 : {
8732 24408 : printf (gettext (" advance address by %u to "),
8733 : op_addr_advance);
8734 12204 : print_dwarf_addr (dwflmod, 0, address, address);
8735 12204 : if (show_op_index)
8736 0 : printf (gettext (", op_index to %u"), op_index);
8737 : printf ("\n");
8738 : }
8739 : break;
8740 :
8741 48103 : case DW_LNS_advance_line:
8742 : /* Takes one sleb128 parameter which is added to the
8743 : line. */
8744 48103 : get_sleb128 (s128, linep, lineendp);
8745 48103 : line += s128;
8746 48103 : printf (gettext ("\
8747 : advance line by constant %d to %" PRId64 "\n"),
8748 : s128, (int64_t) line);
8749 : break;
8750 :
8751 18325 : case DW_LNS_set_file:
8752 : /* Takes one uleb128 parameter which is stored in file. */
8753 18325 : get_uleb128 (u128, linep, lineendp);
8754 18325 : printf (gettext (" set file to %" PRIu64 "\n"),
8755 : (uint64_t) u128);
8756 : break;
8757 :
8758 131 : case DW_LNS_set_column:
8759 : /* Takes one uleb128 parameter which is stored in column. */
8760 131 : if (unlikely (standard_opcode_lengths[opcode] != 1))
8761 : goto invalid_unit;
8762 :
8763 131 : get_uleb128 (u128, linep, lineendp);
8764 131 : printf (gettext (" set column to %" PRIu64 "\n"),
8765 : (uint64_t) u128);
8766 : break;
8767 :
8768 4458 : case DW_LNS_negate_stmt:
8769 : /* Takes no argument. */
8770 4458 : is_stmt = 1 - is_stmt;
8771 4458 : printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
8772 : "is_stmt", is_stmt);
8773 : break;
8774 :
8775 0 : case DW_LNS_set_basic_block:
8776 : /* Takes no argument. */
8777 0 : puts (gettext (" set basic block flag"));
8778 0 : break;
8779 :
8780 26525 : case DW_LNS_const_add_pc:
8781 : /* Takes no argument. */
8782 :
8783 26525 : if (unlikely (line_range == 0))
8784 : goto invalid_unit;
8785 :
8786 53050 : advance_pc ((255 - opcode_base) / line_range);
8787 : {
8788 53050 : printf (gettext (" advance address by constant %u to "),
8789 : op_addr_advance);
8790 26525 : print_dwarf_addr (dwflmod, 0, address, address);
8791 26525 : if (show_op_index)
8792 0 : printf (gettext (", op_index to %u"), op_index);
8793 : printf ("\n");
8794 : }
8795 : break;
8796 :
8797 22 : case DW_LNS_fixed_advance_pc:
8798 : /* Takes one 16 bit parameter which is added to the
8799 : address. */
8800 22 : if (unlikely (standard_opcode_lengths[opcode] != 1))
8801 : goto invalid_unit;
8802 :
8803 22 : u128 = read_2ubyte_unaligned_inc (dbg, linep);
8804 22 : address += u128;
8805 : op_index = 0;
8806 : {
8807 44 : printf (gettext ("\
8808 : advance address by fixed value %u to \n"),
8809 : u128);
8810 22 : print_dwarf_addr (dwflmod, 0, address, address);
8811 : printf ("\n");
8812 : }
8813 : break;
8814 :
8815 1 : case DW_LNS_set_prologue_end:
8816 : /* Takes no argument. */
8817 1 : puts (gettext (" set prologue end flag"));
8818 1 : break;
8819 :
8820 0 : case DW_LNS_set_epilogue_begin:
8821 : /* Takes no argument. */
8822 0 : puts (gettext (" set epilogue begin flag"));
8823 0 : break;
8824 :
8825 0 : case DW_LNS_set_isa:
8826 : /* Takes one uleb128 parameter which is stored in isa. */
8827 0 : if (unlikely (standard_opcode_lengths[opcode] != 1))
8828 : goto invalid_unit;
8829 :
8830 0 : get_uleb128 (u128, linep, lineendp);
8831 0 : printf (gettext (" set isa to %u\n"), u128);
8832 : break;
8833 : }
8834 : }
8835 : else
8836 : {
8837 : /* This is a new opcode the generator but not we know about.
8838 : Read the parameters associated with it but then discard
8839 : everything. Read all the parameters for this opcode. */
8840 0 : printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
8841 : " unknown opcode with %" PRIu8 " parameters:",
8842 : standard_opcode_lengths[opcode]),
8843 0 : standard_opcode_lengths[opcode]);
8844 0 : for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
8845 : {
8846 0 : get_uleb128 (u128, linep, lineendp);
8847 0 : if (n != standard_opcode_lengths[opcode])
8848 0 : putc_unlocked (',', stdout);
8849 0 : printf (" %u", u128);
8850 : }
8851 :
8852 : /* Next round, ignore this opcode. */
8853 0 : continue;
8854 : }
8855 : }
8856 : }
8857 :
8858 : /* There must only be one data block. */
8859 46 : assert (elf_getdata (scn, data) == NULL);
8860 : }
8861 :
8862 :
8863 : static void
8864 3 : print_debug_loclists_section (Dwfl_Module *dwflmod,
8865 : Ebl *ebl,
8866 : GElf_Ehdr *ehdr __attribute__ ((unused)),
8867 : Elf_Scn *scn, GElf_Shdr *shdr,
8868 : Dwarf *dbg)
8869 : {
8870 6 : printf (gettext ("\
8871 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
8872 : elf_ndxscn (scn), section_name (ebl, shdr),
8873 3 : (uint64_t) shdr->sh_offset);
8874 :
8875 6 : Elf_Data *data = (dbg->sectiondata[IDX_debug_loclists]
8876 3 : ?: elf_rawdata (scn, NULL));
8877 3 : if (unlikely (data == NULL))
8878 : {
8879 0 : error (0, 0, gettext ("cannot get .debug_loclists content: %s"),
8880 : elf_errmsg (-1));
8881 0 : return;
8882 : }
8883 :
8884 : /* For the listptr to get the base address/CU. */
8885 6 : sort_listptr (&known_loclistsptr, "loclistsptr");
8886 3 : size_t listptr_idx = 0;
8887 :
8888 3 : const unsigned char *readp = data->d_buf;
8889 3 : const unsigned char *const dataend = ((unsigned char *) data->d_buf
8890 3 : + data->d_size);
8891 10 : while (readp < dataend)
8892 : {
8893 4 : if (unlikely (readp > dataend - 4))
8894 : {
8895 0 : invalid_data:
8896 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
8897 : elf_ndxscn (scn), section_name (ebl, shdr));
8898 0 : return;
8899 : }
8900 :
8901 4 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
8902 8 : printf (gettext ("Table at Offset 0x%" PRIx64 ":\n\n"),
8903 : (uint64_t) offset);
8904 :
8905 4 : uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
8906 4 : unsigned int offset_size = 4;
8907 4 : if (unlikely (unit_length == 0xffffffff))
8908 : {
8909 0 : if (unlikely (readp > dataend - 8))
8910 : goto invalid_data;
8911 :
8912 0 : unit_length = read_8ubyte_unaligned_inc (dbg, readp);
8913 0 : offset_size = 8;
8914 : }
8915 8 : printf (gettext (" Length: %8" PRIu64 "\n"), unit_length);
8916 :
8917 : /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
8918 : bytes to complete the header. And this unit cannot go beyond
8919 : the section data. */
8920 4 : if (readp > dataend - 8
8921 4 : || unit_length < 8
8922 4 : || unit_length > (uint64_t) (dataend - readp))
8923 : goto invalid_data;
8924 :
8925 4 : const unsigned char *nexthdr = readp + unit_length;
8926 :
8927 4 : uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
8928 8 : printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
8929 :
8930 4 : if (version != 5)
8931 : {
8932 0 : error (0, 0, gettext ("Unknown version"));
8933 : goto next_table;
8934 : }
8935 :
8936 4 : uint8_t address_size = *readp++;
8937 8 : printf (gettext (" Address size: %8" PRIu64 "\n"),
8938 : (uint64_t) address_size);
8939 :
8940 4 : if (address_size != 4 && address_size != 8)
8941 : {
8942 0 : error (0, 0, gettext ("unsupported address size"));
8943 : goto next_table;
8944 : }
8945 :
8946 4 : uint8_t segment_size = *readp++;
8947 8 : printf (gettext (" Segment size: %8" PRIu64 "\n"),
8948 : (uint64_t) segment_size);
8949 :
8950 4 : if (segment_size != 0)
8951 : {
8952 0 : error (0, 0, gettext ("unsupported segment size"));
8953 : goto next_table;
8954 : }
8955 :
8956 4 : uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
8957 8 : printf (gettext (" Offset entries: %8" PRIu64 "\n"),
8958 : (uint64_t) offset_entry_count);
8959 :
8960 : /* We need the CU that uses this unit to get the initial base address. */
8961 4 : Dwarf_Addr cu_base = 0;
8962 4 : struct Dwarf_CU *cu = NULL;
8963 4 : if (listptr_cu (&known_loclistsptr, &listptr_idx,
8964 : (Dwarf_Off) offset,
8965 4 : (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
8966 : &cu_base, &cu)
8967 0 : || split_dwarf_cu_base (dbg, &cu, &cu_base))
8968 4 : {
8969 : Dwarf_Die cudie;
8970 4 : if (dwarf_cu_die (cu, &cudie,
8971 : NULL, NULL, NULL, NULL,
8972 : NULL, NULL) == NULL)
8973 0 : printf (gettext (" Unknown CU base: "));
8974 : else
8975 4 : printf (gettext (" CU [%6" PRIx64 "] base: "),
8976 : dwarf_dieoffset (&cudie));
8977 4 : print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
8978 4 : printf ("\n");
8979 : }
8980 : else
8981 0 : printf (gettext (" Not associated with a CU.\n"));
8982 :
8983 4 : printf ("\n");
8984 :
8985 4 : const unsigned char *offset_array_start = readp;
8986 4 : if (offset_entry_count > 0)
8987 : {
8988 2 : uint64_t max_entries = (unit_length - 8) / offset_size;
8989 2 : if (offset_entry_count > max_entries)
8990 : {
8991 0 : error (0, 0,
8992 0 : gettext ("too many offset entries for unit length"));
8993 0 : offset_entry_count = max_entries;
8994 : }
8995 :
8996 4 : printf (gettext (" Offsets starting at 0x%" PRIx64 ":\n"),
8997 : (uint64_t) (offset_array_start
8998 2 : - (unsigned char *) data->d_buf));
8999 18 : for (uint32_t idx = 0; idx < offset_entry_count; idx++)
9000 : {
9001 16 : printf (" [%6" PRIu32 "] ", idx);
9002 16 : if (offset_size == 4)
9003 : {
9004 16 : uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
9005 : printf ("0x%" PRIx32 "\n", off);
9006 : }
9007 : else
9008 : {
9009 0 : uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
9010 : printf ("0x%" PRIx64 "\n", off);
9011 : }
9012 : }
9013 : printf ("\n");
9014 : }
9015 :
9016 4 : Dwarf_Addr base = cu_base;
9017 4 : bool start_of_list = true;
9018 97 : while (readp < nexthdr)
9019 : {
9020 89 : uint8_t kind = *readp++;
9021 : uint64_t op1, op2, len;
9022 :
9023 : /* Skip padding. */
9024 89 : if (start_of_list && kind == DW_LLE_end_of_list)
9025 0 : continue;
9026 :
9027 89 : if (start_of_list)
9028 : {
9029 32 : base = cu_base;
9030 96 : printf (" Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
9031 32 : (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
9032 32 : (uint64_t) (readp - offset_array_start - 1));
9033 32 : start_of_list = false;
9034 : }
9035 :
9036 178 : printf (" %s", dwarf_loc_list_encoding_name (kind));
9037 89 : switch (kind)
9038 : {
9039 32 : case DW_LLE_end_of_list:
9040 32 : start_of_list = true;
9041 : printf ("\n\n");
9042 : break;
9043 :
9044 0 : case DW_LLE_base_addressx:
9045 0 : if ((uint64_t) (nexthdr - readp) < 1)
9046 : {
9047 0 : invalid_entry:
9048 0 : error (0, 0, gettext ("invalid loclists data"));
9049 : goto next_table;
9050 : }
9051 0 : get_uleb128 (op1, readp, nexthdr);
9052 0 : printf (" %" PRIx64 "\n", op1);
9053 0 : if (! print_unresolved_addresses)
9054 : {
9055 : Dwarf_Addr addr;
9056 0 : if (get_indexed_addr (cu, op1, &addr) != 0)
9057 : printf (" ???\n");
9058 : else
9059 : {
9060 0 : printf (" ");
9061 0 : print_dwarf_addr (dwflmod, address_size, addr, addr);
9062 : printf ("\n");
9063 : }
9064 : }
9065 : break;
9066 :
9067 0 : case DW_LLE_startx_endx:
9068 0 : if ((uint64_t) (nexthdr - readp) < 1)
9069 : goto invalid_entry;
9070 0 : get_uleb128 (op1, readp, nexthdr);
9071 0 : if ((uint64_t) (nexthdr - readp) < 1)
9072 : goto invalid_entry;
9073 0 : get_uleb128 (op2, readp, nexthdr);
9074 0 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
9075 0 : if (! print_unresolved_addresses)
9076 : {
9077 : Dwarf_Addr addr1;
9078 : Dwarf_Addr addr2;
9079 0 : if (get_indexed_addr (cu, op1, &addr1) != 0
9080 0 : || get_indexed_addr (cu, op2, &addr2) != 0)
9081 : {
9082 0 : printf (" ???..\n");
9083 : printf (" ???\n");
9084 : }
9085 : else
9086 : {
9087 0 : printf (" ");
9088 0 : print_dwarf_addr (dwflmod, address_size, addr1, addr1);
9089 0 : printf ("..\n ");
9090 0 : print_dwarf_addr (dwflmod, address_size,
9091 : addr2 - 1, addr2);
9092 : printf ("\n");
9093 : }
9094 : }
9095 0 : if ((uint64_t) (nexthdr - readp) < 1)
9096 : goto invalid_entry;
9097 0 : get_uleb128 (len, readp, nexthdr);
9098 0 : if ((uint64_t) (nexthdr - readp) < len)
9099 : goto invalid_entry;
9100 0 : print_ops (dwflmod, dbg, 8, 8, version,
9101 : address_size, offset_size, cu, len, readp);
9102 0 : readp += len;
9103 0 : break;
9104 :
9105 26 : case DW_LLE_startx_length:
9106 26 : if ((uint64_t) (nexthdr - readp) < 1)
9107 : goto invalid_entry;
9108 26 : get_uleb128 (op1, readp, nexthdr);
9109 26 : if ((uint64_t) (nexthdr - readp) < 1)
9110 : goto invalid_entry;
9111 26 : get_uleb128 (op2, readp, nexthdr);
9112 26 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
9113 26 : if (! print_unresolved_addresses)
9114 : {
9115 : Dwarf_Addr addr1;
9116 : Dwarf_Addr addr2;
9117 26 : if (get_indexed_addr (cu, op1, &addr1) != 0)
9118 : {
9119 0 : printf (" ???..\n");
9120 : printf (" ???\n");
9121 : }
9122 : else
9123 : {
9124 26 : addr2 = addr1 + op2;
9125 26 : printf (" ");
9126 26 : print_dwarf_addr (dwflmod, address_size, addr1, addr1);
9127 26 : printf ("..\n ");
9128 26 : print_dwarf_addr (dwflmod, address_size,
9129 : addr2 - 1, addr2);
9130 : printf ("\n");
9131 : }
9132 : }
9133 26 : if ((uint64_t) (nexthdr - readp) < 1)
9134 : goto invalid_entry;
9135 26 : get_uleb128 (len, readp, nexthdr);
9136 26 : if ((uint64_t) (nexthdr - readp) < len)
9137 : goto invalid_entry;
9138 26 : print_ops (dwflmod, dbg, 8, 8, version,
9139 : address_size, offset_size, cu, len, readp);
9140 26 : readp += len;
9141 26 : break;
9142 :
9143 24 : case DW_LLE_offset_pair:
9144 24 : if ((uint64_t) (nexthdr - readp) < 1)
9145 : goto invalid_entry;
9146 24 : get_uleb128 (op1, readp, nexthdr);
9147 24 : if ((uint64_t) (nexthdr - readp) < 1)
9148 : goto invalid_entry;
9149 24 : get_uleb128 (op2, readp, nexthdr);
9150 24 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
9151 24 : if (! print_unresolved_addresses)
9152 : {
9153 24 : op1 += base;
9154 24 : op2 += base;
9155 24 : printf (" ");
9156 24 : print_dwarf_addr (dwflmod, address_size, op1, op1);
9157 24 : printf ("..\n ");
9158 24 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
9159 : printf ("\n");
9160 : }
9161 24 : if ((uint64_t) (nexthdr - readp) < 1)
9162 : goto invalid_entry;
9163 24 : get_uleb128 (len, readp, nexthdr);
9164 24 : if ((uint64_t) (nexthdr - readp) < len)
9165 : goto invalid_entry;
9166 24 : print_ops (dwflmod, dbg, 8, 8, version,
9167 : address_size, offset_size, cu, len, readp);
9168 24 : readp += len;
9169 24 : break;
9170 :
9171 0 : case DW_LLE_default_location:
9172 0 : if ((uint64_t) (nexthdr - readp) < 1)
9173 : goto invalid_entry;
9174 0 : get_uleb128 (len, readp, nexthdr);
9175 0 : if ((uint64_t) (nexthdr - readp) < len)
9176 : goto invalid_entry;
9177 0 : print_ops (dwflmod, dbg, 8, 8, version,
9178 : address_size, offset_size, cu, len, readp);
9179 0 : readp += len;
9180 0 : break;
9181 :
9182 5 : case DW_LLE_base_address:
9183 5 : if (address_size == 4)
9184 : {
9185 0 : if ((uint64_t) (nexthdr - readp) < 4)
9186 : goto invalid_entry;
9187 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
9188 : }
9189 : else
9190 : {
9191 5 : if ((uint64_t) (nexthdr - readp) < 8)
9192 : goto invalid_entry;
9193 5 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
9194 : }
9195 5 : base = op1;
9196 5 : printf (" 0x%" PRIx64 "\n", base);
9197 5 : if (! print_unresolved_addresses)
9198 : {
9199 5 : printf (" ");
9200 5 : print_dwarf_addr (dwflmod, address_size, base, base);
9201 : printf ("\n");
9202 : }
9203 : break;
9204 :
9205 0 : case DW_LLE_start_end:
9206 0 : if (address_size == 4)
9207 : {
9208 0 : if ((uint64_t) (nexthdr - readp) < 8)
9209 : goto invalid_entry;
9210 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
9211 0 : op2 = read_4ubyte_unaligned_inc (dbg, readp);
9212 : }
9213 : else
9214 : {
9215 0 : if ((uint64_t) (nexthdr - readp) < 16)
9216 : goto invalid_entry;
9217 0 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
9218 0 : op2 = read_8ubyte_unaligned_inc (dbg, readp);
9219 : }
9220 0 : printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
9221 0 : if (! print_unresolved_addresses)
9222 : {
9223 0 : printf (" ");
9224 0 : print_dwarf_addr (dwflmod, address_size, op1, op1);
9225 0 : printf ("..\n ");
9226 0 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
9227 : printf ("\n");
9228 : }
9229 0 : if ((uint64_t) (nexthdr - readp) < 1)
9230 : goto invalid_entry;
9231 0 : get_uleb128 (len, readp, nexthdr);
9232 0 : if ((uint64_t) (nexthdr - readp) < len)
9233 : goto invalid_entry;
9234 0 : print_ops (dwflmod, dbg, 8, 8, version,
9235 : address_size, offset_size, cu, len, readp);
9236 0 : readp += len;
9237 0 : break;
9238 :
9239 2 : case DW_LLE_start_length:
9240 2 : if (address_size == 4)
9241 : {
9242 0 : if ((uint64_t) (nexthdr - readp) < 4)
9243 : goto invalid_entry;
9244 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
9245 : }
9246 : else
9247 : {
9248 2 : if ((uint64_t) (nexthdr - readp) < 8)
9249 : goto invalid_entry;
9250 2 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
9251 : }
9252 2 : if ((uint64_t) (nexthdr - readp) < 1)
9253 : goto invalid_entry;
9254 2 : get_uleb128 (op2, readp, nexthdr);
9255 2 : printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
9256 2 : if (! print_unresolved_addresses)
9257 : {
9258 2 : op2 = op1 + op2;
9259 2 : printf (" ");
9260 2 : print_dwarf_addr (dwflmod, address_size, op1, op1);
9261 2 : printf ("..\n ");
9262 2 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
9263 : printf ("\n");
9264 : }
9265 2 : if ((uint64_t) (nexthdr - readp) < 1)
9266 : goto invalid_entry;
9267 2 : get_uleb128 (len, readp, nexthdr);
9268 2 : if ((uint64_t) (nexthdr - readp) < len)
9269 : goto invalid_entry;
9270 2 : print_ops (dwflmod, dbg, 8, 8, version,
9271 : address_size, offset_size, cu, len, readp);
9272 2 : readp += len;
9273 2 : break;
9274 :
9275 : default:
9276 : goto invalid_entry;
9277 : }
9278 : }
9279 :
9280 4 : next_table:
9281 4 : if (readp != nexthdr)
9282 : {
9283 0 : size_t padding = nexthdr - readp;
9284 0 : printf (gettext (" %zu padding bytes\n\n"), padding);
9285 0 : readp = nexthdr;
9286 : }
9287 : }
9288 : }
9289 :
9290 :
9291 : static void
9292 44 : print_debug_loc_section (Dwfl_Module *dwflmod,
9293 : Ebl *ebl, GElf_Ehdr *ehdr,
9294 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
9295 : {
9296 88 : Elf_Data *data = (dbg->sectiondata[IDX_debug_loc]
9297 44 : ?: elf_rawdata (scn, NULL));
9298 :
9299 44 : if (unlikely (data == NULL))
9300 : {
9301 0 : error (0, 0, gettext ("cannot get .debug_loc content: %s"),
9302 : elf_errmsg (-1));
9303 0 : return;
9304 : }
9305 :
9306 88 : printf (gettext ("\
9307 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
9308 : elf_ndxscn (scn), section_name (ebl, shdr),
9309 44 : (uint64_t) shdr->sh_offset);
9310 :
9311 88 : sort_listptr (&known_locsptr, "loclistptr");
9312 44 : size_t listptr_idx = 0;
9313 :
9314 44 : uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
9315 44 : uint_fast8_t offset_size = 4;
9316 :
9317 44 : bool first = true;
9318 44 : Dwarf_Addr base = 0;
9319 44 : unsigned char *readp = data->d_buf;
9320 44 : unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
9321 44 : Dwarf_CU *last_cu = NULL;
9322 204378 : while (readp < endp)
9323 : {
9324 204290 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
9325 204290 : Dwarf_CU *cu = last_cu;
9326 204290 : unsigned int attr = 0;
9327 :
9328 204290 : if (first && skip_listptr_hole (&known_locsptr, &listptr_idx,
9329 : &address_size, &offset_size, &base,
9330 : &cu, offset, &readp, endp, &attr))
9331 0 : continue;
9332 :
9333 204290 : if (last_cu != cu)
9334 : {
9335 : Dwarf_Die cudie;
9336 974 : if (dwarf_cu_die (cu, &cudie,
9337 : NULL, NULL, NULL, NULL,
9338 : NULL, NULL) == NULL)
9339 0 : printf (gettext ("\n Unknown CU base: "));
9340 : else
9341 974 : printf (gettext ("\n CU [%6" PRIx64 "] base: "),
9342 : dwarf_dieoffset (&cudie));
9343 974 : print_dwarf_addr (dwflmod, address_size, base, base);
9344 974 : printf ("\n");
9345 : }
9346 204290 : last_cu = cu;
9347 :
9348 204290 : if (attr == DW_AT_GNU_locviews)
9349 : {
9350 0 : Dwarf_Off next_off = next_listptr_offset (&known_locsptr,
9351 : listptr_idx);
9352 0 : const unsigned char *locp = readp;
9353 : const unsigned char *locendp;
9354 0 : if (next_off == 0
9355 0 : || next_off > (size_t) (endp
9356 0 : - (const unsigned char *) data->d_buf))
9357 : locendp = endp;
9358 : else
9359 0 : locendp = (const unsigned char *) data->d_buf + next_off;
9360 :
9361 0 : while (locp < locendp)
9362 : {
9363 : uint64_t v1, v2;
9364 0 : get_uleb128 (v1, locp, locendp);
9365 0 : if (locp >= locendp)
9366 : {
9367 0 : printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
9368 : break;
9369 : }
9370 0 : get_uleb128 (v2, locp, locendp);
9371 0 : if (first) /* First view pair in a list. */
9372 : printf (" [%6tx] ", offset);
9373 : else
9374 : printf (" ");
9375 0 : printf ("view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
9376 0 : first = false;
9377 : }
9378 :
9379 0 : first = true;
9380 0 : readp = (unsigned char *) locendp;
9381 0 : continue;
9382 : }
9383 :
9384 : /* GNU DebugFission encoded addresses as addrx. */
9385 204290 : bool is_debugfission = ((cu != NULL
9386 0 : || split_dwarf_cu_base (dbg, &cu, &base))
9387 408580 : && (cu->version < 5
9388 204290 : && cu->unit_type == DW_UT_split_compile));
9389 204290 : if (!is_debugfission
9390 204230 : && unlikely (data->d_size - offset < (size_t) address_size * 2))
9391 : {
9392 0 : invalid_data:
9393 0 : printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
9394 0 : break;
9395 : }
9396 :
9397 : Dwarf_Addr begin;
9398 : Dwarf_Addr end;
9399 204290 : bool use_base = true;
9400 204290 : if (is_debugfission)
9401 : {
9402 60 : const unsigned char *locp = readp;
9403 60 : const unsigned char *locendp = readp + data->d_size;
9404 60 : if (locp >= locendp)
9405 : goto invalid_data;
9406 :
9407 : Dwarf_Word idx;
9408 60 : unsigned char code = *locp++;
9409 60 : switch (code)
9410 : {
9411 20 : case DW_LLE_GNU_end_of_list_entry:
9412 20 : begin = 0;
9413 20 : end = 0;
9414 20 : break;
9415 :
9416 0 : case DW_LLE_GNU_base_address_selection_entry:
9417 0 : if (locp >= locendp)
9418 : goto invalid_data;
9419 0 : begin = (Dwarf_Addr) -1;
9420 0 : get_uleb128 (idx, locp, locendp);
9421 0 : if (get_indexed_addr (cu, idx, &end) != 0)
9422 0 : end = idx; /* ... */
9423 : break;
9424 :
9425 0 : case DW_LLE_GNU_start_end_entry:
9426 0 : if (locp >= locendp)
9427 : goto invalid_data;
9428 0 : get_uleb128 (idx, locp, locendp);
9429 0 : if (get_indexed_addr (cu, idx, &begin) != 0)
9430 0 : begin = idx; /* ... */
9431 0 : if (locp >= locendp)
9432 : goto invalid_data;
9433 0 : get_uleb128 (idx, locp, locendp);
9434 0 : if (get_indexed_addr (cu, idx, &end) != 0)
9435 0 : end = idx; /* ... */
9436 : use_base = false;
9437 : break;
9438 :
9439 40 : case DW_LLE_GNU_start_length_entry:
9440 40 : if (locp >= locendp)
9441 : goto invalid_data;
9442 40 : get_uleb128 (idx, locp, locendp);
9443 40 : if (get_indexed_addr (cu, idx, &begin) != 0)
9444 0 : begin = idx; /* ... */
9445 40 : if (locendp - locp < 4)
9446 : goto invalid_data;
9447 40 : end = read_4ubyte_unaligned_inc (dbg, locp);
9448 40 : end += begin;
9449 40 : use_base = false;
9450 40 : break;
9451 :
9452 : default:
9453 : goto invalid_data;
9454 : }
9455 :
9456 60 : readp = (unsigned char *) locp;
9457 : }
9458 204230 : else if (address_size == 8)
9459 : {
9460 204284 : begin = read_8ubyte_unaligned_inc (dbg, readp);
9461 204284 : end = read_8ubyte_unaligned_inc (dbg, readp);
9462 : }
9463 : else
9464 : {
9465 0 : begin = read_4ubyte_unaligned_inc (dbg, readp);
9466 0 : end = read_4ubyte_unaligned_inc (dbg, readp);
9467 0 : if (begin == (Dwarf_Addr) (uint32_t) -1)
9468 0 : begin = (Dwarf_Addr) -1l;
9469 : }
9470 :
9471 204290 : if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
9472 : {
9473 0 : printf (gettext (" [%6tx] base address\n "), offset);
9474 0 : print_dwarf_addr (dwflmod, address_size, end, end);
9475 0 : printf ("\n");
9476 0 : base = end;
9477 : }
9478 204290 : else if (begin == 0 && end == 0) /* End of list entry. */
9479 : {
9480 40092 : if (first)
9481 0 : printf (gettext (" [%6tx] empty list\n"), offset);
9482 : first = true;
9483 : }
9484 : else
9485 : {
9486 : /* We have a location expression entry. */
9487 164198 : uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
9488 :
9489 164198 : if (first) /* First entry in a list. */
9490 : printf (" [%6tx] ", offset);
9491 : else
9492 : printf (" ");
9493 :
9494 328396 : printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
9495 164198 : if (! print_unresolved_addresses)
9496 : {
9497 164168 : Dwarf_Addr dab = use_base ? base + begin : begin;
9498 164168 : Dwarf_Addr dae = use_base ? base + end : end;
9499 164168 : printf (" ");
9500 164168 : print_dwarf_addr (dwflmod, address_size, dab, dab);
9501 164168 : printf ("..\n ");
9502 164168 : print_dwarf_addr (dwflmod, address_size, dae - 1, dae);
9503 : printf ("\n");
9504 : }
9505 :
9506 164198 : if (endp - readp <= (ptrdiff_t) len)
9507 : {
9508 0 : fputs (gettext (" <INVALID DATA>\n"), stdout);
9509 0 : break;
9510 : }
9511 :
9512 328396 : print_ops (dwflmod, dbg, 11, 11,
9513 164198 : cu != NULL ? cu->version : 3,
9514 : address_size, offset_size, cu, len, readp);
9515 :
9516 164198 : first = false;
9517 164198 : readp += len;
9518 : }
9519 : }
9520 : }
9521 :
9522 : struct mac_culist
9523 : {
9524 : Dwarf_Die die;
9525 : Dwarf_Off offset;
9526 : Dwarf_Files *files;
9527 : struct mac_culist *next;
9528 : };
9529 :
9530 :
9531 : static int
9532 0 : mac_compare (const void *p1, const void *p2)
9533 : {
9534 0 : struct mac_culist *m1 = (struct mac_culist *) p1;
9535 0 : struct mac_culist *m2 = (struct mac_culist *) p2;
9536 :
9537 0 : if (m1->offset < m2->offset)
9538 : return -1;
9539 0 : if (m1->offset > m2->offset)
9540 : return 1;
9541 0 : return 0;
9542 : }
9543 :
9544 :
9545 : static void
9546 0 : print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
9547 : Ebl *ebl,
9548 : GElf_Ehdr *ehdr __attribute__ ((unused)),
9549 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
9550 : {
9551 0 : printf (gettext ("\
9552 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
9553 : elf_ndxscn (scn), section_name (ebl, shdr),
9554 0 : (uint64_t) shdr->sh_offset);
9555 0 : putc_unlocked ('\n', stdout);
9556 :
9557 : /* There is no function in libdw to iterate over the raw content of
9558 : the section but it is easy enough to do. */
9559 0 : Elf_Data *data = (dbg->sectiondata[IDX_debug_macinfo]
9560 0 : ?: elf_rawdata (scn, NULL));
9561 0 : if (unlikely (data == NULL))
9562 : {
9563 0 : error (0, 0, gettext ("cannot get macro information section data: %s"),
9564 : elf_errmsg (-1));
9565 0 : return;
9566 : }
9567 :
9568 : /* Get the source file information for all CUs. */
9569 : Dwarf_Off offset;
9570 0 : Dwarf_Off ncu = 0;
9571 : size_t hsize;
9572 0 : struct mac_culist *culist = NULL;
9573 0 : size_t nculist = 0;
9574 0 : while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
9575 : {
9576 : Dwarf_Die cudie;
9577 0 : if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
9578 0 : continue;
9579 :
9580 : Dwarf_Attribute attr;
9581 0 : if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
9582 0 : continue;
9583 :
9584 : Dwarf_Word macoff;
9585 0 : if (dwarf_formudata (&attr, &macoff) != 0)
9586 0 : continue;
9587 :
9588 0 : struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
9589 0 : newp->die = cudie;
9590 0 : newp->offset = macoff;
9591 0 : newp->files = NULL;
9592 0 : newp->next = culist;
9593 0 : culist = newp;
9594 0 : ++nculist;
9595 : }
9596 :
9597 : /* Convert the list into an array for easier consumption. */
9598 0 : struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
9599 : * sizeof (*cus));
9600 : /* Add sentinel. */
9601 0 : cus[nculist].offset = data->d_size;
9602 0 : cus[nculist].files = (Dwarf_Files *) -1l;
9603 0 : if (nculist > 0)
9604 : {
9605 0 : for (size_t cnt = nculist - 1; culist != NULL; --cnt)
9606 : {
9607 0 : assert (cnt < nculist);
9608 0 : cus[cnt] = *culist;
9609 0 : culist = culist->next;
9610 : }
9611 :
9612 : /* Sort the array according to the offset in the .debug_macinfo
9613 : section. Note we keep the sentinel at the end. */
9614 0 : qsort (cus, nculist, sizeof (*cus), mac_compare);
9615 : }
9616 :
9617 0 : const unsigned char *readp = (const unsigned char *) data->d_buf;
9618 0 : const unsigned char *readendp = readp + data->d_size;
9619 0 : int level = 1;
9620 :
9621 0 : while (readp < readendp)
9622 : {
9623 0 : unsigned int opcode = *readp++;
9624 : unsigned int u128;
9625 : unsigned int u128_2;
9626 : const unsigned char *endp;
9627 :
9628 0 : switch (opcode)
9629 : {
9630 0 : case DW_MACINFO_define:
9631 : case DW_MACINFO_undef:
9632 : case DW_MACINFO_vendor_ext:
9633 : /* For the first two opcodes the parameters are
9634 : line, string
9635 : For the latter
9636 : number, string.
9637 : We can treat these cases together. */
9638 0 : get_uleb128 (u128, readp, readendp);
9639 :
9640 0 : endp = memchr (readp, '\0', readendp - readp);
9641 0 : if (unlikely (endp == NULL))
9642 : {
9643 0 : printf (gettext ("\
9644 : %*s*** non-terminated string at end of section"),
9645 : level, "");
9646 : return;
9647 : }
9648 :
9649 0 : if (opcode == DW_MACINFO_define)
9650 0 : printf ("%*s#define %s, line %u\n",
9651 : level, "", (char *) readp, u128);
9652 0 : else if (opcode == DW_MACINFO_undef)
9653 0 : printf ("%*s#undef %s, line %u\n",
9654 : level, "", (char *) readp, u128);
9655 : else
9656 0 : printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
9657 :
9658 0 : readp = endp + 1;
9659 0 : break;
9660 :
9661 0 : case DW_MACINFO_start_file:
9662 : /* The two parameters are line and file index, in this order. */
9663 0 : get_uleb128 (u128, readp, readendp);
9664 0 : if (readendp - readp < 1)
9665 : {
9666 0 : printf (gettext ("\
9667 : %*s*** missing DW_MACINFO_start_file argument at end of section"),
9668 : level, "");
9669 : return;
9670 : }
9671 0 : get_uleb128 (u128_2, readp, readendp);
9672 :
9673 : /* Find the CU DIE for this file. */
9674 0 : size_t macoff = readp - (const unsigned char *) data->d_buf;
9675 0 : const char *fname = "???";
9676 0 : if (macoff >= cus[0].offset)
9677 : {
9678 0 : while (macoff >= cus[1].offset && cus[1].offset != data->d_size)
9679 0 : ++cus;
9680 :
9681 0 : if (cus[0].files == NULL
9682 0 : && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
9683 0 : cus[0].files = (Dwarf_Files *) -1l;
9684 :
9685 0 : if (cus[0].files != (Dwarf_Files *) -1l)
9686 0 : fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
9687 0 : ?: "???");
9688 : }
9689 :
9690 0 : printf ("%*sstart_file %u, [%u] %s\n",
9691 : level, "", u128, u128_2, fname);
9692 0 : ++level;
9693 0 : break;
9694 :
9695 0 : case DW_MACINFO_end_file:
9696 0 : --level;
9697 : printf ("%*send_file\n", level, "");
9698 : /* Nothing more to do. */
9699 : break;
9700 :
9701 0 : default:
9702 : // XXX gcc seems to generate files with a trailing zero.
9703 0 : if (unlikely (opcode != 0 || readp != readendp))
9704 : printf ("%*s*** invalid opcode %u\n", level, "", opcode);
9705 : break;
9706 : }
9707 : }
9708 : }
9709 :
9710 :
9711 : static void
9712 3 : print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
9713 : Ebl *ebl,
9714 : GElf_Ehdr *ehdr __attribute__ ((unused)),
9715 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
9716 : {
9717 6 : printf (gettext ("\
9718 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
9719 : elf_ndxscn (scn), section_name (ebl, shdr),
9720 3 : (uint64_t) shdr->sh_offset);
9721 6 : putc_unlocked ('\n', stdout);
9722 :
9723 3 : Elf_Data *data = elf_getdata (scn, NULL);
9724 3 : if (unlikely (data == NULL))
9725 : {
9726 0 : error (0, 0, gettext ("cannot get macro information section data: %s"),
9727 : elf_errmsg (-1));
9728 0 : return;
9729 : }
9730 :
9731 : /* Get the source file information for all CUs. Uses same
9732 : datastructure as macinfo. But uses offset field to directly
9733 : match .debug_line offset. And just stored in a list. */
9734 : Dwarf_Off offset;
9735 3 : Dwarf_Off ncu = 0;
9736 : size_t hsize;
9737 3 : struct mac_culist *culist = NULL;
9738 3 : size_t nculist = 0;
9739 10 : while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
9740 : {
9741 : Dwarf_Die cudie;
9742 4 : if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
9743 0 : continue;
9744 :
9745 : Dwarf_Attribute attr;
9746 4 : if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL)
9747 0 : continue;
9748 :
9749 : Dwarf_Word lineoff;
9750 4 : if (dwarf_formudata (&attr, &lineoff) != 0)
9751 0 : continue;
9752 :
9753 4 : struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
9754 4 : newp->die = cudie;
9755 4 : newp->offset = lineoff;
9756 4 : newp->files = NULL;
9757 4 : newp->next = culist;
9758 4 : culist = newp;
9759 4 : ++nculist;
9760 : }
9761 :
9762 3 : const unsigned char *readp = (const unsigned char *) data->d_buf;
9763 3 : const unsigned char *readendp = readp + data->d_size;
9764 :
9765 14 : while (readp < readendp)
9766 : {
9767 16 : printf (gettext (" Offset: 0x%" PRIx64 "\n"),
9768 8 : (uint64_t) (readp - (const unsigned char *) data->d_buf));
9769 :
9770 : // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
9771 : // optional vendor extension macro entry table.
9772 8 : if (readp + 2 > readendp)
9773 : {
9774 0 : invalid_data:
9775 0 : error (0, 0, gettext ("invalid data"));
9776 0 : return;
9777 : }
9778 8 : const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
9779 16 : printf (gettext (" Version: %" PRIu16 "\n"), vers);
9780 :
9781 : // Version 4 is the GNU extension for DWARF4. DWARF5 will use version
9782 : // 5 when it gets standardized.
9783 8 : if (vers != 4 && vers != 5)
9784 : {
9785 0 : printf (gettext (" unknown version, cannot parse section\n"));
9786 : return;
9787 : }
9788 :
9789 8 : if (readp + 1 > readendp)
9790 : goto invalid_data;
9791 8 : const unsigned char flag = *readp++;
9792 16 : printf (gettext (" Flag: 0x%" PRIx8), flag);
9793 8 : if (flag != 0)
9794 : {
9795 4 : printf (" (");
9796 4 : if ((flag & 0x01) != 0)
9797 : {
9798 0 : printf ("offset_size");
9799 0 : if ((flag & 0xFE) != 0)
9800 : printf (", ");
9801 : }
9802 4 : if ((flag & 0x02) != 0)
9803 : {
9804 4 : printf ("debug_line_offset");
9805 4 : if ((flag & 0xFC) != 0)
9806 : printf (", ");
9807 : }
9808 4 : if ((flag & 0x04) != 0)
9809 : {
9810 0 : printf ("operands_table");
9811 0 : if ((flag & 0xF8) != 0)
9812 : printf (", ");
9813 : }
9814 4 : if ((flag & 0xF8) != 0)
9815 : printf ("unknown");
9816 : printf (")");
9817 : }
9818 8 : printf ("\n");
9819 :
9820 8 : unsigned int offset_len = (flag & 0x01) ? 8 : 4;
9821 16 : printf (gettext (" Offset length: %" PRIu8 "\n"), offset_len);
9822 8 : Dwarf_Off line_offset = -1;
9823 8 : if (flag & 0x02)
9824 : {
9825 4 : if (offset_len == 8)
9826 0 : line_offset = read_8ubyte_unaligned_inc (dbg, readp);
9827 : else
9828 4 : line_offset = read_4ubyte_unaligned_inc (dbg, readp);
9829 4 : printf (gettext (" .debug_line offset: 0x%" PRIx64 "\n"),
9830 : line_offset);
9831 : }
9832 :
9833 4 : struct mac_culist *cu = NULL;
9834 4 : if (line_offset != (Dwarf_Off) -1)
9835 : {
9836 : cu = culist;
9837 5 : while (cu != NULL && line_offset != cu->offset)
9838 1 : cu = cu->next;
9839 : }
9840 :
9841 8 : Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, (cu != NULL
9842 : ? cu->die.cu
9843 : : NULL));
9844 :
9845 : const unsigned char *vendor[DW_MACRO_hi_user - DW_MACRO_lo_user + 1];
9846 8 : memset (vendor, 0, sizeof vendor);
9847 8 : if (flag & 0x04)
9848 : {
9849 : // 1 byte length, for each item, 1 byte opcode, uleb128 number
9850 : // of arguments, for each argument 1 byte form code.
9851 0 : if (readp + 1 > readendp)
9852 : goto invalid_data;
9853 0 : unsigned int tlen = *readp++;
9854 0 : printf (gettext (" extension opcode table, %" PRIu8 " items:\n"),
9855 : tlen);
9856 0 : for (unsigned int i = 0; i < tlen; i++)
9857 : {
9858 0 : if (readp + 1 > readendp)
9859 : goto invalid_data;
9860 0 : unsigned int opcode = *readp++;
9861 0 : printf (gettext (" [%" PRIx8 "]"), opcode);
9862 0 : if (opcode < DW_MACRO_lo_user
9863 0 : || opcode > DW_MACRO_hi_user)
9864 : goto invalid_data;
9865 : // Record the start of description for this vendor opcode.
9866 : // uleb128 nr args, 1 byte per arg form.
9867 0 : vendor[opcode - DW_MACRO_lo_user] = readp;
9868 0 : if (readp + 1 > readendp)
9869 : goto invalid_data;
9870 0 : unsigned int args = *readp++;
9871 0 : if (args > 0)
9872 : {
9873 0 : printf (gettext (" %" PRIu8 " arguments:"), args);
9874 0 : while (args > 0)
9875 : {
9876 0 : if (readp + 1 > readendp)
9877 : goto invalid_data;
9878 0 : unsigned int form = *readp++;
9879 0 : printf (" %s", dwarf_form_name (form));
9880 0 : if (! libdw_valid_user_form (form))
9881 : goto invalid_data;
9882 0 : args--;
9883 0 : if (args > 0)
9884 : putchar_unlocked (',');
9885 : }
9886 : }
9887 : else
9888 0 : printf (gettext (" no arguments."));
9889 0 : putchar_unlocked ('\n');
9890 : }
9891 : }
9892 8 : putchar_unlocked ('\n');
9893 :
9894 8 : int level = 1;
9895 8 : if (readp + 1 > readendp)
9896 : goto invalid_data;
9897 8 : unsigned int opcode = *readp++;
9898 743 : while (opcode != 0)
9899 : {
9900 : unsigned int u128;
9901 : unsigned int u128_2;
9902 : const unsigned char *endp;
9903 : uint64_t off;
9904 :
9905 727 : switch (opcode)
9906 : {
9907 6 : case DW_MACRO_start_file:
9908 6 : get_uleb128 (u128, readp, readendp);
9909 6 : if (readp >= readendp)
9910 : goto invalid_data;
9911 6 : get_uleb128 (u128_2, readp, readendp);
9912 :
9913 : /* Find the CU DIE that matches this line offset. */
9914 6 : const char *fname = "???";
9915 6 : if (cu != NULL)
9916 : {
9917 6 : if (cu->files == NULL
9918 4 : && dwarf_getsrcfiles (&cu->die, &cu->files,
9919 : NULL) != 0)
9920 0 : cu->files = (Dwarf_Files *) -1l;
9921 :
9922 6 : if (cu->files != (Dwarf_Files *) -1l)
9923 6 : fname = (dwarf_filesrc (cu->files, u128_2,
9924 6 : NULL, NULL) ?: "???");
9925 : }
9926 6 : printf ("%*sstart_file %u, [%u] %s\n",
9927 : level, "", u128, u128_2, fname);
9928 6 : ++level;
9929 6 : break;
9930 :
9931 6 : case DW_MACRO_end_file:
9932 6 : --level;
9933 : printf ("%*send_file\n", level, "");
9934 : break;
9935 :
9936 1 : case DW_MACRO_define:
9937 1 : get_uleb128 (u128, readp, readendp);
9938 1 : endp = memchr (readp, '\0', readendp - readp);
9939 1 : if (endp == NULL)
9940 : goto invalid_data;
9941 2 : printf ("%*s#define %s, line %u\n",
9942 : level, "", readp, u128);
9943 1 : readp = endp + 1;
9944 1 : break;
9945 :
9946 0 : case DW_MACRO_undef:
9947 0 : get_uleb128 (u128, readp, readendp);
9948 0 : endp = memchr (readp, '\0', readendp - readp);
9949 0 : if (endp == NULL)
9950 : goto invalid_data;
9951 0 : printf ("%*s#undef %s, line %u\n",
9952 : level, "", readp, u128);
9953 0 : readp = endp + 1;
9954 0 : break;
9955 :
9956 707 : case DW_MACRO_define_strp:
9957 707 : get_uleb128 (u128, readp, readendp);
9958 707 : if (readp + offset_len > readendp)
9959 : goto invalid_data;
9960 707 : if (offset_len == 8)
9961 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
9962 : else
9963 707 : off = read_4ubyte_unaligned_inc (dbg, readp);
9964 707 : printf ("%*s#define %s, line %u (indirect)\n",
9965 : level, "", dwarf_getstring (dbg, off, NULL), u128);
9966 : break;
9967 :
9968 1 : case DW_MACRO_undef_strp:
9969 1 : get_uleb128 (u128, readp, readendp);
9970 1 : if (readp + offset_len > readendp)
9971 : goto invalid_data;
9972 1 : if (offset_len == 8)
9973 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
9974 : else
9975 1 : off = read_4ubyte_unaligned_inc (dbg, readp);
9976 1 : printf ("%*s#undef %s, line %u (indirect)\n",
9977 : level, "", dwarf_getstring (dbg, off, NULL), u128);
9978 : break;
9979 :
9980 6 : case DW_MACRO_import:
9981 6 : if (readp + offset_len > readendp)
9982 : goto invalid_data;
9983 6 : if (offset_len == 8)
9984 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
9985 : else
9986 6 : off = read_4ubyte_unaligned_inc (dbg, readp);
9987 : printf ("%*s#include offset 0x%" PRIx64 "\n",
9988 : level, "", off);
9989 : break;
9990 :
9991 0 : case DW_MACRO_define_sup:
9992 0 : get_uleb128 (u128, readp, readendp);
9993 0 : if (readp + offset_len > readendp)
9994 : goto invalid_data;
9995 0 : printf ("%*s#define ", level, "");
9996 0 : readp = print_form_data (dbg, DW_FORM_strp_sup,
9997 : readp, readendp, offset_len,
9998 : str_offsets_base);
9999 : printf (", line %u (sup)\n", u128);
10000 : break;
10001 :
10002 0 : case DW_MACRO_undef_sup:
10003 0 : get_uleb128 (u128, readp, readendp);
10004 0 : if (readp + offset_len > readendp)
10005 : goto invalid_data;
10006 0 : printf ("%*s#undef ", level, "");
10007 0 : readp = print_form_data (dbg, DW_FORM_strp_sup,
10008 : readp, readendp, offset_len,
10009 : str_offsets_base);
10010 : printf (", line %u (sup)\n", u128);
10011 : break;
10012 :
10013 0 : case DW_MACRO_import_sup:
10014 0 : if (readp + offset_len > readendp)
10015 : goto invalid_data;
10016 0 : if (offset_len == 8)
10017 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
10018 : else
10019 0 : off = read_4ubyte_unaligned_inc (dbg, readp);
10020 : // XXX Needs support for reading from supplementary object file.
10021 : printf ("%*s#include offset 0x%" PRIx64 " (sup)\n",
10022 : level, "", off);
10023 : break;
10024 :
10025 0 : case DW_MACRO_define_strx:
10026 0 : get_uleb128 (u128, readp, readendp);
10027 0 : if (readp + offset_len > readendp)
10028 : goto invalid_data;
10029 0 : printf ("%*s#define ", level, "");
10030 0 : readp = print_form_data (dbg, DW_FORM_strx,
10031 : readp, readendp, offset_len,
10032 : str_offsets_base);
10033 : printf (", line %u (strx)\n", u128);
10034 : break;
10035 :
10036 0 : case DW_MACRO_undef_strx:
10037 0 : get_uleb128 (u128, readp, readendp);
10038 0 : if (readp + offset_len > readendp)
10039 : goto invalid_data;
10040 0 : printf ("%*s#undef ", level, "");
10041 0 : readp = print_form_data (dbg, DW_FORM_strx,
10042 : readp, readendp, offset_len,
10043 : str_offsets_base);
10044 : printf (", line %u (strx)\n", u128);
10045 : break;
10046 :
10047 0 : default:
10048 0 : printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
10049 0 : if (opcode < DW_MACRO_lo_user
10050 : || opcode > DW_MACRO_lo_user
10051 0 : || vendor[opcode - DW_MACRO_lo_user] == NULL)
10052 : goto invalid_data;
10053 :
10054 : const unsigned char *op_desc;
10055 0 : op_desc = vendor[opcode - DW_MACRO_lo_user];
10056 :
10057 : // Just skip the arguments, we cannot really interpret them,
10058 : // but print as much as we can.
10059 0 : unsigned int args = *op_desc++;
10060 0 : while (args > 0 && readp < readendp)
10061 0 : {
10062 0 : unsigned int form = *op_desc++;
10063 0 : readp = print_form_data (dbg, form, readp, readendp,
10064 : offset_len, str_offsets_base);
10065 0 : args--;
10066 0 : if (args > 0)
10067 : printf (", ");
10068 : }
10069 : putchar_unlocked ('\n');
10070 : }
10071 :
10072 727 : if (readp + 1 > readendp)
10073 : goto invalid_data;
10074 727 : opcode = *readp++;
10075 727 : if (opcode == 0)
10076 : putchar_unlocked ('\n');
10077 : }
10078 : }
10079 : }
10080 :
10081 :
10082 : /* Callback for printing global names. */
10083 : static int
10084 34 : print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
10085 : void *arg)
10086 : {
10087 34 : int *np = (int *) arg;
10088 :
10089 102 : printf (gettext (" [%5d] DIE offset: %6" PRId64
10090 : ", CU DIE offset: %6" PRId64 ", name: %s\n"),
10091 34 : (*np)++, global->die_offset, global->cu_offset, global->name);
10092 :
10093 34 : return 0;
10094 : }
10095 :
10096 :
10097 : /* Print the known exported symbols in the DWARF section '.debug_pubnames'. */
10098 : static void
10099 8 : print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10100 : Ebl *ebl,
10101 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10102 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10103 : {
10104 16 : printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
10105 : elf_ndxscn (scn), section_name (ebl, shdr),
10106 8 : (uint64_t) shdr->sh_offset);
10107 :
10108 8 : int n = 0;
10109 8 : (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
10110 8 : }
10111 :
10112 : /* Print the content of the DWARF string section '.debug_str'. */
10113 : static void
10114 45 : print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10115 : Ebl *ebl,
10116 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10117 : Elf_Scn *scn, GElf_Shdr *shdr,
10118 : Dwarf *dbg __attribute__ ((unused)))
10119 : {
10120 45 : Elf_Data *data = elf_rawdata (scn, NULL);
10121 45 : const size_t sh_size = data ? data->d_size : 0;
10122 :
10123 : /* Compute floor(log16(shdr->sh_size)). */
10124 45 : GElf_Addr tmp = sh_size;
10125 45 : int digits = 1;
10126 200 : while (tmp >= 16)
10127 : {
10128 110 : ++digits;
10129 110 : tmp >>= 4;
10130 : }
10131 45 : digits = MAX (4, digits);
10132 :
10133 135 : printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
10134 : " %*s String\n"),
10135 : elf_ndxscn (scn),
10136 45 : section_name (ebl, shdr), (uint64_t) shdr->sh_offset,
10137 : /* TRANS: the debugstr| prefix makes the string unique. */
10138 45 : digits + 2, sgettext ("debugstr|Offset"));
10139 :
10140 45 : Dwarf_Off offset = 0;
10141 61290 : while (offset < sh_size)
10142 : {
10143 : size_t len;
10144 61200 : const char *str = (const char *) data->d_buf + offset;
10145 61200 : const char *endp = memchr (str, '\0', sh_size - offset);
10146 61200 : if (unlikely (endp == NULL))
10147 : {
10148 0 : printf (gettext (" *** error, missing string terminator\n"));
10149 : break;
10150 : }
10151 :
10152 61200 : printf (" [%*" PRIx64 "] \"%s\"\n", digits, (uint64_t) offset, str);
10153 61200 : len = endp - str;
10154 61200 : offset += len + 1;
10155 : }
10156 45 : }
10157 :
10158 : static void
10159 4 : print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10160 : Ebl *ebl,
10161 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10162 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10163 : {
10164 8 : printf (gettext ("\
10165 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
10166 : elf_ndxscn (scn), section_name (ebl, shdr),
10167 4 : (uint64_t) shdr->sh_offset);
10168 :
10169 4 : if (shdr->sh_size == 0)
10170 : return;
10171 :
10172 : /* We like to get the section from libdw to make sure they are relocated. */
10173 8 : Elf_Data *data = (dbg->sectiondata[IDX_debug_str_offsets]
10174 4 : ?: elf_rawdata (scn, NULL));
10175 4 : if (unlikely (data == NULL))
10176 : {
10177 0 : error (0, 0, gettext ("cannot get .debug_str_offsets section data: %s"),
10178 : elf_errmsg (-1));
10179 : return;
10180 : }
10181 :
10182 4 : size_t idx = 0;
10183 8 : sort_listptr (&known_stroffbases, "str_offsets");
10184 :
10185 4 : const unsigned char *start = (const unsigned char *) data->d_buf;
10186 4 : const unsigned char *readp = start;
10187 4 : const unsigned char *readendp = ((const unsigned char *) data->d_buf
10188 4 : + data->d_size);
10189 :
10190 12 : while (readp < readendp)
10191 : {
10192 : /* Most string offset tables will have a header. For split
10193 : dwarf unit GNU DebugFission didn't add one. But they were
10194 : also only defined for split units (main or skeleton units
10195 : didn't have indirect strings). So if we don't have a
10196 : DW_AT_str_offsets_base at all and this is offset zero, then
10197 : just start printing offsets immediately, if this is a .dwo
10198 : section. */
10199 4 : Dwarf_Off off = (Dwarf_Off) (readp
10200 4 : - (const unsigned char *) data->d_buf);
10201 :
10202 4 : printf ("Table at offset %" PRIx64 " ", off);
10203 :
10204 4 : struct listptr *listptr = get_listptr (&known_stroffbases, idx++);
10205 0 : const unsigned char *next_unitp = readendp;
10206 : uint8_t offset_size;
10207 : bool has_header;
10208 0 : if (listptr == NULL)
10209 : {
10210 : /* This can happen for .dwo files. There is only an header
10211 : in the case this is a version 5 split DWARF file. */
10212 : Dwarf_CU *cu;
10213 : uint8_t unit_type;
10214 4 : if (dwarf_get_units (dbg, NULL, &cu, NULL, &unit_type,
10215 : NULL, NULL) != 0)
10216 : {
10217 0 : error (0, 0, "Warning: Cannot find any DWARF unit.");
10218 : /* Just guess some values. */
10219 0 : has_header = false;
10220 0 : offset_size = 4;
10221 : }
10222 4 : else if (off == 0
10223 4 : && (unit_type == DW_UT_split_type
10224 4 : || unit_type == DW_UT_split_compile))
10225 : {
10226 4 : has_header = cu->version > 4;
10227 4 : offset_size = cu->offset_size;
10228 : }
10229 : else
10230 : {
10231 0 : error (0, 0,
10232 : "Warning: No CU references .debug_str_offsets after %"
10233 : PRIx64, off);
10234 0 : has_header = cu->version > 4;
10235 0 : offset_size = cu->offset_size;
10236 : }
10237 4 : printf ("\n");
10238 : }
10239 : else
10240 : {
10241 : /* This must be DWARF5, since GNU DebugFission didn't define
10242 : DW_AT_str_offsets_base. */
10243 0 : has_header = true;
10244 :
10245 : Dwarf_Die cudie;
10246 0 : if (dwarf_cu_die (listptr->cu, &cudie,
10247 : NULL, NULL, NULL, NULL,
10248 : NULL, NULL) == NULL)
10249 0 : printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
10250 : else
10251 0 : printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
10252 : }
10253 :
10254 4 : if (has_header)
10255 : {
10256 : uint64_t unit_length;
10257 : uint16_t version;
10258 : uint16_t padding;
10259 :
10260 2 : unit_length = read_4ubyte_unaligned_inc (dbg, readp);
10261 2 : if (unlikely (unit_length == 0xffffffff))
10262 : {
10263 0 : if (unlikely (readp > readendp - 8))
10264 : {
10265 0 : invalid_data:
10266 : error (0, 0, "Invalid data");
10267 : return;
10268 : }
10269 0 : unit_length = read_8ubyte_unaligned_inc (dbg, readp);
10270 0 : offset_size = 8;
10271 : }
10272 : else
10273 : offset_size = 4;
10274 :
10275 2 : printf ("\n");
10276 4 : printf (gettext (" Length: %8" PRIu64 "\n"),
10277 : unit_length);
10278 4 : printf (gettext (" Offset size: %8" PRIu8 "\n"),
10279 : offset_size);
10280 :
10281 : /* We need at least 2-bytes (version) + 2-bytes (padding) =
10282 : 4 bytes to complete the header. And this unit cannot go
10283 : beyond the section data. */
10284 2 : if (readp > readendp - 4
10285 2 : || unit_length < 4
10286 2 : || unit_length > (uint64_t) (readendp - readp))
10287 : goto invalid_data;
10288 :
10289 2 : next_unitp = readp + unit_length;
10290 :
10291 2 : version = read_2ubyte_unaligned_inc (dbg, readp);
10292 4 : printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
10293 :
10294 2 : if (version != 5)
10295 : {
10296 0 : error (0, 0, gettext ("Unknown version"));
10297 : goto next_unit;
10298 : }
10299 :
10300 2 : padding = read_2ubyte_unaligned_inc (dbg, readp);
10301 4 : printf (gettext (" Padding: %8" PRIx16 "\n"), padding);
10302 :
10303 2 : if (listptr != NULL
10304 0 : && listptr->offset != (Dwarf_Off) (readp - start))
10305 : {
10306 : error (0, 0, "String offsets index doesn't start after header");
10307 : goto next_unit;
10308 : }
10309 :
10310 : printf ("\n");
10311 : }
10312 :
10313 4 : int digits = 1;
10314 4 : size_t offsets = (next_unitp - readp) / offset_size;
10315 12 : while (offsets >= 10)
10316 : {
10317 4 : ++digits;
10318 4 : offsets /= 10;
10319 : }
10320 :
10321 4 : unsigned int uidx = 0;
10322 4 : size_t index_offset = readp - (const unsigned char *) data->d_buf;
10323 : printf (" Offsets start at 0x%zx:\n", index_offset);
10324 64 : while (readp <= next_unitp - offset_size)
10325 : {
10326 : Dwarf_Word offset;
10327 60 : if (offset_size == 4)
10328 60 : offset = read_4ubyte_unaligned_inc (dbg, readp);
10329 : else
10330 0 : offset = read_8ubyte_unaligned_inc (dbg, readp);
10331 60 : const char *str = dwarf_getstring (dbg, offset, NULL);
10332 120 : printf (" [%*u] [%*" PRIx64 "] \"%s\"\n",
10333 60 : digits, uidx++, (int) offset_size * 2, offset, str ?: "???");
10334 : }
10335 4 : printf ("\n");
10336 :
10337 4 : if (readp != next_unitp)
10338 0 : error (0, 0, "extra %zd bytes at end of unit",
10339 0 : (size_t) (next_unitp - readp));
10340 :
10341 4 : next_unit:
10342 : readp = next_unitp;
10343 : }
10344 : }
10345 :
10346 :
10347 : /* Print the content of the call frame search table section
10348 : '.eh_frame_hdr'. */
10349 : static void
10350 14 : print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10351 : Ebl *ebl __attribute__ ((unused)),
10352 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10353 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10354 : {
10355 28 : printf (gettext ("\
10356 : \nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
10357 : elf_ndxscn (scn));
10358 :
10359 14 : Elf_Data *data = elf_rawdata (scn, NULL);
10360 :
10361 14 : if (unlikely (data == NULL))
10362 : {
10363 0 : error (0, 0, gettext ("cannot get %s content: %s"),
10364 : ".eh_frame_hdr", elf_errmsg (-1));
10365 0 : return;
10366 : }
10367 :
10368 14 : const unsigned char *readp = data->d_buf;
|