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 : static void
316 : cleanup_list (struct section_argument *list)
317 : {
318 716 : while (list != NULL)
319 : {
320 132 : struct section_argument *a = list;
321 132 : list = a->next;
322 132 : free (a);
323 : }
324 : }
325 :
326 : int
327 292 : main (int argc, char *argv[])
328 : {
329 : /* We use no threads here which can interfere with handling a stream. */
330 292 : (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
331 :
332 : /* Set locale. */
333 292 : setlocale (LC_ALL, "");
334 :
335 : /* Initialize the message catalog. */
336 292 : textdomain (PACKAGE_TARNAME);
337 :
338 : /* Look up once. */
339 292 : yes_str = gettext ("yes");
340 292 : no_str = gettext ("no");
341 :
342 : /* Parse and process arguments. */
343 292 : int remaining;
344 292 : argp_parse (&argp, argc, argv, 0, &remaining, NULL);
345 :
346 : /* Before we start tell the ELF library which version we are using. */
347 292 : elf_version (EV_CURRENT);
348 :
349 : /* Now process all the files given at the command line. */
350 292 : bool only_one = remaining + 1 == argc;
351 299 : do
352 : {
353 : /* Open the file. */
354 299 : int fd = open (argv[remaining], O_RDONLY);
355 299 : if (fd == -1)
356 : {
357 0 : error (0, errno, gettext ("cannot open input file"));
358 0 : continue;
359 : }
360 :
361 299 : process_file (fd, argv[remaining], only_one);
362 :
363 299 : close (fd);
364 : }
365 299 : while (++remaining < argc);
366 :
367 292 : cleanup_list (dump_data_sections);
368 292 : cleanup_list (string_sections);
369 :
370 292 : return error_message_count != 0;
371 : }
372 :
373 :
374 : /* Handle program arguments. */
375 : static error_t
376 1818 : parse_opt (int key, char *arg,
377 : struct argp_state *state __attribute__ ((unused)))
378 : {
379 1950 : void add_dump_section (const char *name, bool implicit)
380 : {
381 132 : struct section_argument *a = xmalloc (sizeof *a);
382 132 : a->arg = name;
383 132 : a->next = NULL;
384 132 : a->implicit = implicit;
385 264 : struct section_argument ***tailp
386 132 : = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
387 132 : **tailp = a;
388 132 : *tailp = &a->next;
389 132 : }
390 :
391 1818 : switch (key)
392 : {
393 42 : case 'a':
394 42 : print_file_header = true;
395 42 : print_program_header = true;
396 42 : print_relocations = true;
397 42 : print_section_header = true;
398 42 : print_symbol_table = true;
399 42 : print_version_info = true;
400 42 : print_dynamic_table = true;
401 42 : print_section_groups = true;
402 42 : print_histogram = true;
403 42 : print_arch = true;
404 42 : print_notes = true;
405 42 : implicit_debug_sections |= section_exception;
406 42 : add_dump_section (".strtab", true);
407 42 : add_dump_section (".dynstr", true);
408 42 : add_dump_section (".comment", true);
409 42 : any_control_option = true;
410 42 : break;
411 4 : case 'A':
412 4 : print_arch = true;
413 4 : any_control_option = true;
414 4 : break;
415 2 : case 'd':
416 2 : print_dynamic_table = true;
417 2 : any_control_option = true;
418 2 : break;
419 0 : case 'e':
420 0 : print_debug_sections |= section_exception;
421 0 : any_control_option = true;
422 0 : break;
423 9 : case 'g':
424 9 : print_section_groups = true;
425 9 : any_control_option = true;
426 9 : break;
427 0 : case 'h':
428 0 : print_file_header = true;
429 0 : any_control_option = true;
430 0 : break;
431 0 : case 'I':
432 0 : print_histogram = true;
433 0 : any_control_option = true;
434 0 : break;
435 0 : case 'l':
436 0 : print_program_header = true;
437 0 : any_control_option = true;
438 0 : break;
439 20 : case 'n':
440 20 : print_notes = true;
441 20 : any_control_option = true;
442 20 : break;
443 1 : case 'r':
444 1 : print_relocations = true;
445 1 : any_control_option = true;
446 1 : break;
447 90 : case 'S':
448 90 : print_section_header = true;
449 90 : any_control_option = true;
450 90 : break;
451 14 : case 's':
452 14 : print_symbol_table = true;
453 14 : any_control_option = true;
454 14 : symbol_table_section = arg;
455 14 : break;
456 0 : case 'V':
457 0 : print_version_info = true;
458 0 : any_control_option = true;
459 0 : break;
460 2 : case 'c':
461 2 : print_archive_index = true;
462 2 : break;
463 117 : case 'w':
464 117 : if (arg == NULL)
465 : {
466 41 : print_debug_sections = section_all;
467 41 : implicit_debug_sections = section_info;
468 41 : show_split_units = true;
469 : }
470 76 : else if (strcmp (arg, "abbrev") == 0)
471 0 : print_debug_sections |= section_abbrev;
472 76 : else if (strcmp (arg, "addr") == 0)
473 : {
474 2 : print_debug_sections |= section_addr;
475 2 : implicit_debug_sections |= section_info;
476 : }
477 74 : else if (strcmp (arg, "aranges") == 0)
478 3 : print_debug_sections |= section_aranges;
479 71 : else if (strcmp (arg, "decodedaranges") == 0)
480 : {
481 1 : print_debug_sections |= section_aranges;
482 1 : decodedaranges = true;
483 : }
484 70 : else if (strcmp (arg, "ranges") == 0)
485 : {
486 12 : print_debug_sections |= section_ranges;
487 12 : implicit_debug_sections |= section_info;
488 : }
489 58 : else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
490 2 : print_debug_sections |= section_frame;
491 56 : else if (strcmp (arg, "info") == 0)
492 : {
493 18 : print_debug_sections |= section_info;
494 18 : print_debug_sections |= section_types;
495 : }
496 38 : else if (strcmp (arg, "info+") == 0)
497 : {
498 2 : print_debug_sections |= section_info;
499 2 : print_debug_sections |= section_types;
500 2 : show_split_units = true;
501 : }
502 36 : else if (strcmp (arg, "loc") == 0)
503 : {
504 18 : print_debug_sections |= section_loc;
505 18 : implicit_debug_sections |= section_info;
506 : }
507 18 : else if (strcmp (arg, "line") == 0)
508 6 : print_debug_sections |= section_line;
509 12 : else if (strcmp (arg, "decodedline") == 0)
510 : {
511 4 : print_debug_sections |= section_line;
512 4 : decodedline = true;
513 : }
514 8 : else if (strcmp (arg, "pubnames") == 0)
515 0 : print_debug_sections |= section_pubnames;
516 8 : else if (strcmp (arg, "str") == 0)
517 : {
518 3 : print_debug_sections |= section_str;
519 : /* For mapping string offset tables to CUs. */
520 3 : implicit_debug_sections |= section_info;
521 : }
522 5 : else if (strcmp (arg, "macinfo") == 0)
523 0 : print_debug_sections |= section_macinfo;
524 5 : else if (strcmp (arg, "macro") == 0)
525 3 : print_debug_sections |= section_macro;
526 2 : else if (strcmp (arg, "exception") == 0)
527 0 : print_debug_sections |= section_exception;
528 2 : else if (strcmp (arg, "gdb_index") == 0)
529 2 : print_debug_sections |= section_gdb_index;
530 : else
531 : {
532 0 : fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
533 : arg);
534 0 : argp_help (&argp, stderr, ARGP_HELP_SEE,
535 : program_invocation_short_name);
536 0 : exit (1);
537 : }
538 117 : any_control_option = true;
539 117 : break;
540 1 : case 'p':
541 1 : any_control_option = true;
542 1 : if (arg == NULL)
543 : {
544 0 : print_string_sections = true;
545 0 : break;
546 : }
547 6 : FALLTHROUGH;
548 : case 'x':
549 6 : add_dump_section (arg, false);
550 6 : any_control_option = true;
551 6 : break;
552 2 : case 'N':
553 2 : print_address_names = false;
554 2 : break;
555 27 : case 'U':
556 27 : print_unresolved_addresses = true;
557 27 : break;
558 0 : case ARGP_KEY_NO_ARGS:
559 0 : fputs (gettext ("Missing file name.\n"), stderr);
560 0 : goto do_argp_help;
561 292 : case ARGP_KEY_FINI:
562 292 : if (! any_control_option && ! print_archive_index)
563 : {
564 0 : fputs (gettext ("No operation specified.\n"), stderr);
565 0 : do_argp_help:
566 0 : argp_help (&argp, stderr, ARGP_HELP_SEE,
567 : program_invocation_short_name);
568 0 : exit (EXIT_FAILURE);
569 : }
570 : break;
571 : case 'W': /* Ignored. */
572 : break;
573 13 : case 'z':
574 13 : print_decompress = true;
575 13 : break;
576 4 : case ELF_INPUT_SECTION:
577 4 : if (arg == NULL)
578 4 : elf_input_section = ".gnu_debugdata";
579 : else
580 0 : elf_input_section = arg;
581 : break;
582 5 : case DWARF_SKELETON:
583 5 : dwarf_skeleton = arg;
584 5 : break;
585 : default:
586 : return ARGP_ERR_UNKNOWN;
587 : }
588 : return 0;
589 : }
590 :
591 :
592 : /* Create a file descriptor to read the data from the
593 : elf_input_section given a file descriptor to an ELF file. */
594 : static int
595 4 : open_input_section (int fd)
596 : {
597 4 : size_t shnums;
598 4 : size_t cnt;
599 4 : size_t shstrndx;
600 4 : Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
601 4 : if (elf == NULL)
602 : {
603 0 : error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
604 : elf_errmsg (-1));
605 0 : return -1;
606 : }
607 :
608 4 : if (elf_getshdrnum (elf, &shnums) < 0)
609 : {
610 0 : error (0, 0, gettext ("cannot determine number of sections: %s"),
611 : elf_errmsg (-1));
612 0 : open_error:
613 0 : elf_end (elf);
614 0 : return -1;
615 : }
616 :
617 4 : if (elf_getshdrstrndx (elf, &shstrndx) < 0)
618 : {
619 0 : error (0, 0, gettext ("cannot get section header string table index"));
620 0 : goto open_error;
621 : }
622 :
623 91 : for (cnt = 0; cnt < shnums; ++cnt)
624 : {
625 91 : Elf_Scn *scn = elf_getscn (elf, cnt);
626 91 : if (scn == NULL)
627 : {
628 0 : error (0, 0, gettext ("cannot get section: %s"),
629 : elf_errmsg (-1));
630 0 : goto open_error;
631 : }
632 :
633 91 : GElf_Shdr shdr_mem;
634 91 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
635 91 : if (unlikely (shdr == NULL))
636 : {
637 0 : error (0, 0, gettext ("cannot get section header: %s"),
638 : elf_errmsg (-1));
639 0 : goto open_error;
640 : }
641 :
642 91 : const char *sname = elf_strptr (elf, shstrndx, shdr->sh_name);
643 91 : if (sname == NULL)
644 : {
645 0 : error (0, 0, gettext ("cannot get section name"));
646 0 : goto open_error;
647 : }
648 :
649 91 : if (strcmp (sname, elf_input_section) == 0)
650 : {
651 4 : Elf_Data *data = elf_rawdata (scn, NULL);
652 4 : if (data == NULL)
653 : {
654 0 : error (0, 0, gettext ("cannot get %s content: %s"),
655 : sname, elf_errmsg (-1));
656 0 : goto open_error;
657 : }
658 :
659 : /* Create (and immediately unlink) a temporary file to store
660 : section data in to create a file descriptor for it. */
661 4 : const char *tmpdir = getenv ("TMPDIR") ?: P_tmpdir;
662 4 : static const char suffix[] = "/readelfXXXXXX";
663 4 : int tmplen = strlen (tmpdir) + sizeof (suffix);
664 4 : char *tempname = alloca (tmplen);
665 4 : sprintf (tempname, "%s%s", tmpdir, suffix);
666 :
667 4 : int sfd = mkstemp (tempname);
668 4 : if (sfd == -1)
669 : {
670 0 : error (0, 0, gettext ("cannot create temp file '%s'"),
671 : tempname);
672 0 : goto open_error;
673 : }
674 4 : unlink (tempname);
675 :
676 4 : ssize_t size = data->d_size;
677 4 : if (write_retry (sfd, data->d_buf, size) != size)
678 : {
679 0 : error (0, 0, gettext ("cannot write section data"));
680 0 : goto open_error;
681 : }
682 :
683 4 : if (elf_end (elf) != 0)
684 : {
685 0 : error (0, 0, gettext ("error while closing Elf descriptor: %s"),
686 : elf_errmsg (-1));
687 4 : return -1;
688 : }
689 :
690 4 : if (lseek (sfd, 0, SEEK_SET) == -1)
691 : {
692 0 : error (0, 0, gettext ("error while rewinding file descriptor"));
693 0 : return -1;
694 : }
695 :
696 : return sfd;
697 : }
698 : }
699 :
700 : /* Named section not found. */
701 0 : if (elf_end (elf) != 0)
702 0 : error (0, 0, gettext ("error while closing Elf descriptor: %s"),
703 : elf_errmsg (-1));
704 : return -1;
705 : }
706 :
707 : /* Check if the file is an archive, and if so dump its index. */
708 : static void
709 2 : check_archive_index (int fd, const char *fname, bool only_one)
710 : {
711 : /* Create an `Elf' descriptor. */
712 2 : Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
713 2 : if (elf == NULL)
714 0 : error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
715 : elf_errmsg (-1));
716 : else
717 : {
718 2 : if (elf_kind (elf) == ELF_K_AR)
719 : {
720 2 : if (!only_one)
721 0 : printf ("\n%s:\n\n", fname);
722 2 : dump_archive_index (elf, fname);
723 : }
724 : else
725 0 : error (0, 0,
726 0 : gettext ("'%s' is not an archive, cannot print archive index"),
727 : fname);
728 :
729 : /* Now we can close the descriptor. */
730 2 : if (elf_end (elf) != 0)
731 0 : error (0, 0, gettext ("error while closing Elf descriptor: %s"),
732 : elf_errmsg (-1));
733 : }
734 2 : }
735 :
736 : /* Trivial callback used for checking if we opened an archive. */
737 : static int
738 283 : count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
739 : void **userdata __attribute__ ((unused)),
740 : const char *name __attribute__ ((unused)),
741 : Dwarf_Addr base __attribute__ ((unused)),
742 : void *arg)
743 : {
744 283 : if (*(bool *) arg)
745 : return DWARF_CB_ABORT;
746 283 : *(bool *) arg = true;
747 283 : return DWARF_CB_OK;
748 : }
749 :
750 : struct process_dwflmod_args
751 : {
752 : int fd;
753 : bool only_one;
754 : };
755 :
756 : static int
757 297 : process_dwflmod (Dwfl_Module *dwflmod,
758 : void **userdata __attribute__ ((unused)),
759 : const char *name __attribute__ ((unused)),
760 : Dwarf_Addr base __attribute__ ((unused)),
761 : void *arg)
762 : {
763 297 : const struct process_dwflmod_args *a = arg;
764 :
765 : /* Print the file name. */
766 297 : if (!a->only_one)
767 : {
768 14 : const char *fname;
769 14 : dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
770 :
771 14 : printf ("\n%s:\n\n", fname);
772 : }
773 :
774 297 : process_elf_file (dwflmod, a->fd);
775 :
776 297 : return DWARF_CB_OK;
777 : }
778 :
779 : /* Stub libdwfl callback, only the ELF handle already open is ever used.
780 : Only used for finding the alternate debug file if the Dwarf comes from
781 : the main file. We are not interested in separate debuginfo. */
782 : static int
783 37 : find_no_debuginfo (Dwfl_Module *mod,
784 : void **userdata,
785 : const char *modname,
786 : Dwarf_Addr base,
787 : const char *file_name,
788 : const char *debuglink_file,
789 : GElf_Word debuglink_crc,
790 : char **debuginfo_file_name)
791 : {
792 37 : Dwarf_Addr dwbias;
793 37 : dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
794 :
795 : /* We are only interested if the Dwarf has been setup on the main
796 : elf file but is only missing the alternate debug link. If dwbias
797 : hasn't even been setup, this is searching for separate debuginfo
798 : for the main elf. We don't care in that case. */
799 37 : if (dwbias == (Dwarf_Addr) -1)
800 : return -1;
801 :
802 5 : return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
803 : file_name, debuglink_file,
804 : debuglink_crc, debuginfo_file_name);
805 : }
806 :
807 : static Dwfl *
808 306 : create_dwfl (int fd, const char *fname)
809 : {
810 : /* Duplicate an fd for dwfl_report_offline to swallow. */
811 306 : int dwfl_fd = dup (fd);
812 306 : if (unlikely (dwfl_fd < 0))
813 0 : error (EXIT_FAILURE, errno, "dup");
814 :
815 : /* Use libdwfl in a trivial way to open the libdw handle for us.
816 : This takes care of applying relocations to DWARF data in ET_REL files. */
817 306 : static const Dwfl_Callbacks callbacks =
818 : {
819 : .section_address = dwfl_offline_section_address,
820 : .find_debuginfo = find_no_debuginfo
821 : };
822 306 : Dwfl *dwfl = dwfl_begin (&callbacks);
823 306 : if (likely (dwfl != NULL))
824 : /* Let 0 be the logical address of the file (or first in archive). */
825 306 : dwfl->offline_next_address = 0;
826 306 : if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
827 : {
828 0 : struct stat st;
829 0 : if (fstat (dwfl_fd, &st) != 0)
830 0 : error (0, errno, gettext ("cannot stat input file"));
831 0 : else if (unlikely (st.st_size == 0))
832 0 : error (0, 0, gettext ("input file is empty"));
833 : else
834 0 : error (0, 0, gettext ("failed reading '%s': %s"),
835 : fname, dwfl_errmsg (-1));
836 0 : close (dwfl_fd); /* Consumed on success, not on failure. */
837 0 : dwfl = NULL;
838 : }
839 : else
840 306 : dwfl_report_end (dwfl, NULL, NULL);
841 :
842 306 : return dwfl;
843 : }
844 :
845 : /* Process one input file. */
846 : static void
847 299 : process_file (int fd, const char *fname, bool only_one)
848 : {
849 299 : if (print_archive_index)
850 2 : check_archive_index (fd, fname, only_one);
851 :
852 299 : if (!any_control_option)
853 : return;
854 :
855 297 : if (elf_input_section != NULL)
856 : {
857 : /* Replace fname and fd with section content. */
858 4 : char *fnname = alloca (strlen (fname) + strlen (elf_input_section) + 2);
859 4 : sprintf (fnname, "%s:%s", fname, elf_input_section);
860 4 : fd = open_input_section (fd);
861 4 : if (fd == -1)
862 : {
863 0 : error (0, 0, gettext ("No such section '%s' in '%s'"),
864 : elf_input_section, fname);
865 0 : return;
866 : }
867 : fname = fnname;
868 : }
869 :
870 297 : Dwfl *dwfl = create_dwfl (fd, fname);
871 297 : if (dwfl != NULL)
872 : {
873 297 : if (only_one)
874 : {
875 : /* Clear ONLY_ONE if we have multiple modules, from an archive. */
876 283 : bool seen = false;
877 283 : only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
878 : }
879 :
880 : /* Process the one or more modules gleaned from this file. */
881 297 : struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
882 297 : dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
883 : }
884 : /* Terrible hack for hooking unrelated skeleton/split compile units,
885 : see __libdw_link_skel_split in print_debug. */
886 297 : if (! do_not_close_dwfl)
887 297 : dwfl_end (dwfl);
888 :
889 : /* Need to close the replaced fd if we created it. Caller takes
890 : care of original. */
891 297 : if (elf_input_section != NULL)
892 4 : close (fd);
893 : }
894 :
895 : /* Check whether there are any compressed sections in the ELF file. */
896 : static bool
897 96 : elf_contains_chdrs (Elf *elf)
898 : {
899 96 : Elf_Scn *scn = NULL;
900 788763 : while ((scn = elf_nextscn (elf, scn)) != NULL)
901 : {
902 788673 : GElf_Shdr shdr_mem;
903 788673 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
904 788673 : if (shdr != NULL && (shdr->sh_flags & SHF_COMPRESSED) != 0)
905 6 : return true;
906 : }
907 : return false;
908 : }
909 :
910 : /* Process one ELF file. */
911 : static void
912 297 : process_elf_file (Dwfl_Module *dwflmod, int fd)
913 : {
914 297 : GElf_Addr dwflbias;
915 297 : Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
916 :
917 297 : GElf_Ehdr ehdr_mem;
918 297 : GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
919 :
920 297 : if (ehdr == NULL)
921 : {
922 0 : error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
923 0 : return;
924 : }
925 :
926 297 : Ebl *ebl = ebl_openbackend (elf);
927 297 : if (unlikely (ebl == NULL))
928 : {
929 0 : ebl_error:
930 0 : error (0, errno, gettext ("cannot create EBL handle"));
931 0 : return;
932 : }
933 :
934 : /* Determine the number of sections. */
935 297 : if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
936 0 : error (EXIT_FAILURE, 0,
937 0 : gettext ("cannot determine number of sections: %s"),
938 : elf_errmsg (-1));
939 :
940 : /* Determine the number of phdrs. */
941 297 : if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
942 0 : error (EXIT_FAILURE, 0,
943 0 : gettext ("cannot determine number of program headers: %s"),
944 : elf_errmsg (-1));
945 :
946 : /* For an ET_REL file, libdwfl has adjusted the in-core shdrs and
947 : may have applied relocation to some sections. If there are any
948 : compressed sections, any pass (or libdw/libdwfl) might have
949 : uncompressed them. So we need to get a fresh Elf handle on the
950 : file to display those. */
951 594 : bool print_unchanged = ((print_section_header
952 165 : || print_relocations
953 164 : || dump_data_sections != NULL
954 159 : || print_notes)
955 323 : && (ehdr->e_type == ET_REL
956 96 : || elf_contains_chdrs (ebl->elf)));
957 :
958 297 : Elf *pure_elf = NULL;
959 297 : Ebl *pure_ebl = ebl;
960 297 : if (print_unchanged)
961 : {
962 : /* Read the file afresh. */
963 68 : off_t aroff = elf_getaroff (elf);
964 68 : pure_elf = dwelf_elf_begin (fd);
965 68 : if (aroff > 0)
966 : {
967 : /* Archive member. */
968 0 : (void) elf_rand (pure_elf, aroff);
969 0 : Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
970 0 : elf_end (pure_elf);
971 0 : pure_elf = armem;
972 : }
973 68 : if (pure_elf == NULL)
974 : {
975 0 : error (0, 0, gettext ("cannot read ELF: %s"), elf_errmsg (-1));
976 0 : return;
977 : }
978 68 : pure_ebl = ebl_openbackend (pure_elf);
979 68 : if (pure_ebl == NULL)
980 : goto ebl_error;
981 : }
982 :
983 297 : if (print_file_header)
984 42 : print_ehdr (ebl, ehdr);
985 297 : if (print_section_header)
986 132 : print_shdr (pure_ebl, ehdr);
987 297 : if (print_program_header)
988 42 : print_phdr (ebl, ehdr);
989 297 : if (print_section_groups)
990 51 : print_scngrp (ebl);
991 297 : if (print_dynamic_table)
992 44 : print_dynamic (ebl);
993 297 : if (print_relocations)
994 43 : print_relocs (pure_ebl, ehdr);
995 297 : if (print_histogram)
996 42 : handle_hash (ebl);
997 297 : if (print_symbol_table)
998 56 : print_symtab (ebl, SHT_DYNSYM);
999 297 : if (print_version_info)
1000 42 : print_verinfo (ebl);
1001 297 : if (print_symbol_table)
1002 56 : print_symtab (ebl, SHT_SYMTAB);
1003 297 : if (print_arch)
1004 46 : print_liblist (ebl);
1005 297 : if (print_arch)
1006 46 : print_attributes (ebl, ehdr);
1007 297 : if (dump_data_sections != NULL)
1008 5 : dump_data (pure_ebl);
1009 297 : if (string_sections != NULL)
1010 43 : dump_strings (ebl);
1011 297 : if ((print_debug_sections | implicit_debug_sections) != 0)
1012 151 : print_debug (dwflmod, ebl, ehdr);
1013 297 : if (print_notes)
1014 62 : handle_notes (pure_ebl, ehdr);
1015 297 : if (print_string_sections)
1016 0 : print_strings (ebl);
1017 :
1018 297 : ebl_closebackend (ebl);
1019 :
1020 297 : if (pure_ebl != ebl)
1021 : {
1022 68 : ebl_closebackend (pure_ebl);
1023 68 : elf_end (pure_elf);
1024 : }
1025 : }
1026 :
1027 :
1028 : /* Print file type. */
1029 : static void
1030 42 : print_file_type (unsigned short int e_type)
1031 : {
1032 42 : if (likely (e_type <= ET_CORE))
1033 : {
1034 42 : static const char *const knowntypes[] =
1035 : {
1036 : N_("NONE (None)"),
1037 : N_("REL (Relocatable file)"),
1038 : N_("EXEC (Executable file)"),
1039 : N_("DYN (Shared object file)"),
1040 : N_("CORE (Core file)")
1041 : };
1042 42 : puts (gettext (knowntypes[e_type]));
1043 : }
1044 0 : else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
1045 0 : printf (gettext ("OS Specific: (%x)\n"), e_type);
1046 0 : else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
1047 0 : printf (gettext ("Processor Specific: (%x)\n"), e_type);
1048 : else
1049 0 : puts ("???");
1050 42 : }
1051 :
1052 :
1053 : /* Print ELF header. */
1054 : static void
1055 42 : print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
1056 : {
1057 42 : fputs_unlocked (gettext ("ELF Header:\n Magic: "), stdout);
1058 714 : for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
1059 672 : printf (" %02hhx", ehdr->e_ident[cnt]);
1060 :
1061 42 : printf (gettext ("\n Class: %s\n"),
1062 42 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
1063 : : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
1064 34 : : "\?\?\?");
1065 :
1066 42 : printf (gettext (" Data: %s\n"),
1067 42 : ehdr->e_ident[EI_DATA] == ELFDATA2LSB
1068 : ? "2's complement, little endian"
1069 : : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
1070 12 : ? "2's complement, big endian" : "\?\?\?");
1071 :
1072 168 : printf (gettext (" Ident Version: %hhd %s\n"),
1073 42 : ehdr->e_ident[EI_VERSION],
1074 42 : ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
1075 : : "(\?\?\?)");
1076 :
1077 42 : char buf[512];
1078 42 : printf (gettext (" OS/ABI: %s\n"),
1079 42 : ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
1080 :
1081 126 : printf (gettext (" ABI Version: %hhd\n"),
1082 42 : ehdr->e_ident[EI_ABIVERSION]);
1083 :
1084 42 : fputs_unlocked (gettext (" Type: "), stdout);
1085 42 : print_file_type (ehdr->e_type);
1086 :
1087 42 : const char *machine = dwelf_elf_e_machine_string (ehdr->e_machine);
1088 42 : if (machine != NULL)
1089 42 : printf (gettext (" Machine: %s\n"), machine);
1090 : else
1091 0 : printf (gettext (" Machine: <unknown>: 0x%x\n"),
1092 0 : ehdr->e_machine);
1093 :
1094 42 : printf (gettext (" Version: %d %s\n"),
1095 : ehdr->e_version,
1096 42 : ehdr->e_version == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
1097 :
1098 42 : printf (gettext (" Entry point address: %#" PRIx64 "\n"),
1099 : ehdr->e_entry);
1100 :
1101 42 : printf (gettext (" Start of program headers: %" PRId64 " %s\n"),
1102 : ehdr->e_phoff, gettext ("(bytes into file)"));
1103 :
1104 42 : printf (gettext (" Start of section headers: %" PRId64 " %s\n"),
1105 : ehdr->e_shoff, gettext ("(bytes into file)"));
1106 :
1107 42 : printf (gettext (" Flags: %s\n"),
1108 : ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
1109 :
1110 126 : printf (gettext (" Size of this header: %" PRId16 " %s\n"),
1111 42 : ehdr->e_ehsize, gettext ("(bytes)"));
1112 :
1113 126 : printf (gettext (" Size of program header entries: %" PRId16 " %s\n"),
1114 42 : ehdr->e_phentsize, gettext ("(bytes)"));
1115 :
1116 126 : printf (gettext (" Number of program headers entries: %" PRId16),
1117 42 : ehdr->e_phnum);
1118 42 : if (ehdr->e_phnum == PN_XNUM)
1119 : {
1120 0 : GElf_Shdr shdr_mem;
1121 0 : GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
1122 0 : if (shdr != NULL)
1123 0 : printf (gettext (" (%" PRIu32 " in [0].sh_info)"),
1124 0 : (uint32_t) shdr->sh_info);
1125 : else
1126 0 : fputs_unlocked (gettext (" ([0] not available)"), stdout);
1127 : }
1128 42 : fputc_unlocked ('\n', stdout);
1129 :
1130 126 : printf (gettext (" Size of section header entries: %" PRId16 " %s\n"),
1131 42 : ehdr->e_shentsize, gettext ("(bytes)"));
1132 :
1133 126 : printf (gettext (" Number of section headers entries: %" PRId16),
1134 42 : ehdr->e_shnum);
1135 42 : if (ehdr->e_shnum == 0)
1136 : {
1137 0 : GElf_Shdr shdr_mem;
1138 0 : GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
1139 0 : if (shdr != NULL)
1140 0 : printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
1141 0 : (uint32_t) shdr->sh_size);
1142 : else
1143 0 : fputs_unlocked (gettext (" ([0] not available)"), stdout);
1144 : }
1145 42 : fputc_unlocked ('\n', stdout);
1146 :
1147 42 : if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
1148 : {
1149 0 : GElf_Shdr shdr_mem;
1150 0 : GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
1151 0 : if (shdr != NULL)
1152 : /* We managed to get the zeroth section. */
1153 0 : snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
1154 0 : (uint32_t) shdr->sh_link);
1155 : else
1156 : {
1157 0 : strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
1158 0 : buf[sizeof (buf) - 1] = '\0';
1159 : }
1160 :
1161 0 : printf (gettext (" Section header string table index: XINDEX%s\n\n"),
1162 : buf);
1163 : }
1164 : else
1165 42 : printf (gettext (" Section header string table index: %" PRId16 "\n\n"),
1166 : ehdr->e_shstrndx);
1167 42 : }
1168 :
1169 :
1170 : static const char *
1171 : get_visibility_type (int value)
1172 : {
1173 14971 : switch (value)
1174 : {
1175 : case STV_DEFAULT:
1176 : return "DEFAULT";
1177 0 : case STV_INTERNAL:
1178 0 : return "INTERNAL";
1179 68 : case STV_HIDDEN:
1180 68 : return "HIDDEN";
1181 0 : case STV_PROTECTED:
1182 0 : return "PROTECTED";
1183 0 : default:
1184 0 : return "???";
1185 : }
1186 : }
1187 :
1188 : static const char *
1189 : elf_ch_type_name (unsigned int code)
1190 : {
1191 0 : if (code == 0)
1192 : return "NONE";
1193 :
1194 0 : if (code == ELFCOMPRESS_ZLIB)
1195 0 : return "ZLIB";
1196 :
1197 : return "UNKNOWN";
1198 : }
1199 :
1200 : /* Print the section headers. */
1201 : static void
1202 0 : print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
1203 : {
1204 0 : size_t cnt;
1205 0 : size_t shstrndx;
1206 :
1207 0 : if (! print_file_header)
1208 : {
1209 0 : size_t sections;
1210 0 : if (unlikely (elf_getshdrnum (ebl->elf, §ions) < 0))
1211 0 : error (EXIT_FAILURE, 0,
1212 0 : gettext ("cannot get number of sections: %s"),
1213 : elf_errmsg (-1));
1214 :
1215 0 : printf (gettext ("\
1216 : There are %zd section headers, starting at offset %#" PRIx64 ":\n\
1217 : \n"),
1218 : sections, ehdr->e_shoff);
1219 : }
1220 :
1221 : /* Get the section header string table index. */
1222 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1223 0 : error (EXIT_FAILURE, 0,
1224 0 : gettext ("cannot get section header string table index: %s"),
1225 : elf_errmsg (-1));
1226 :
1227 0 : puts (gettext ("Section Headers:"));
1228 :
1229 0 : if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1230 0 : puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
1231 : else
1232 0 : puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
1233 :
1234 0 : if (print_decompress)
1235 : {
1236 0 : if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1237 0 : puts (gettext (" [Compression Size Al]"));
1238 : else
1239 0 : puts (gettext (" [Compression Size Al]"));
1240 : }
1241 :
1242 0 : for (cnt = 0; cnt < shnum; ++cnt)
1243 : {
1244 0 : Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
1245 :
1246 0 : if (unlikely (scn == NULL))
1247 0 : error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
1248 : elf_errmsg (-1));
1249 :
1250 : /* Get the section header. */
1251 0 : GElf_Shdr shdr_mem;
1252 0 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1253 0 : if (unlikely (shdr == NULL))
1254 0 : error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
1255 : elf_errmsg (-1));
1256 :
1257 0 : char flagbuf[20];
1258 0 : char *cp = flagbuf;
1259 0 : if (shdr->sh_flags & SHF_WRITE)
1260 0 : *cp++ = 'W';
1261 0 : if (shdr->sh_flags & SHF_ALLOC)
1262 0 : *cp++ = 'A';
1263 0 : if (shdr->sh_flags & SHF_EXECINSTR)
1264 0 : *cp++ = 'X';
1265 0 : if (shdr->sh_flags & SHF_MERGE)
1266 0 : *cp++ = 'M';
1267 0 : if (shdr->sh_flags & SHF_STRINGS)
1268 0 : *cp++ = 'S';
1269 0 : if (shdr->sh_flags & SHF_INFO_LINK)
1270 0 : *cp++ = 'I';
1271 0 : if (shdr->sh_flags & SHF_LINK_ORDER)
1272 0 : *cp++ = 'L';
1273 0 : if (shdr->sh_flags & SHF_OS_NONCONFORMING)
1274 0 : *cp++ = 'N';
1275 0 : if (shdr->sh_flags & SHF_GROUP)
1276 0 : *cp++ = 'G';
1277 0 : if (shdr->sh_flags & SHF_TLS)
1278 0 : *cp++ = 'T';
1279 0 : if (shdr->sh_flags & SHF_COMPRESSED)
1280 0 : *cp++ = 'C';
1281 0 : if (shdr->sh_flags & SHF_ORDERED)
1282 0 : *cp++ = 'O';
1283 0 : if (shdr->sh_flags & SHF_EXCLUDE)
1284 0 : *cp++ = 'E';
1285 0 : *cp = '\0';
1286 :
1287 0 : const char *sname;
1288 0 : char buf[128];
1289 0 : sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "<corrupt>";
1290 0 : printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
1291 : " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
1292 : " %2" PRId64 "\n",
1293 : cnt, sname,
1294 0 : ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
1295 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
1296 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
1297 0 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
1298 : shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
1299 : shdr->sh_addralign);
1300 :
1301 0 : if (print_decompress)
1302 : {
1303 0 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1304 : {
1305 0 : GElf_Chdr chdr;
1306 0 : if (gelf_getchdr (scn, &chdr) != NULL)
1307 0 : printf (" [ELF %s (%" PRId32 ") %0*" PRIx64
1308 : " %2" PRId64 "]\n",
1309 : elf_ch_type_name (chdr.ch_type),
1310 : chdr.ch_type,
1311 0 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8,
1312 : chdr.ch_size, chdr.ch_addralign);
1313 : else
1314 0 : error (0, 0,
1315 0 : gettext ("bad compression header for section %zd: %s"),
1316 : elf_ndxscn (scn), elf_errmsg (-1));
1317 : }
1318 0 : else if (strncmp(".zdebug", sname, strlen (".zdebug")) == 0)
1319 : {
1320 0 : ssize_t size;
1321 0 : if ((size = dwelf_scn_gnu_compressed_size (scn)) >= 0)
1322 0 : printf (" [GNU ZLIB %0*zx ]\n",
1323 0 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, size);
1324 : else
1325 0 : error (0, 0,
1326 0 : gettext ("bad gnu compressed size for section %zd: %s"),
1327 : elf_ndxscn (scn), elf_errmsg (-1));
1328 : }
1329 : }
1330 : }
1331 :
1332 0 : fputc_unlocked ('\n', stdout);
1333 0 : }
1334 :
1335 :
1336 : /* Print the program header. */
1337 : static void
1338 0 : print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
1339 : {
1340 0 : if (phnum == 0)
1341 : /* No program header, this is OK in relocatable objects. */
1342 0 : return;
1343 :
1344 0 : puts (gettext ("Program Headers:"));
1345 0 : if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1346 0 : puts (gettext ("\
1347 : Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
1348 : else
1349 0 : puts (gettext ("\
1350 : Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
1351 :
1352 : /* Process all program headers. */
1353 : bool has_relro = false;
1354 : GElf_Addr relro_from = 0;
1355 : GElf_Addr relro_to = 0;
1356 0 : for (size_t cnt = 0; cnt < phnum; ++cnt)
1357 : {
1358 0 : char buf[128];
1359 0 : GElf_Phdr mem;
1360 0 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
1361 :
1362 : /* If for some reason the header cannot be returned show this. */
1363 0 : if (unlikely (phdr == NULL))
1364 : {
1365 0 : puts (" ???");
1366 0 : continue;
1367 : }
1368 :
1369 0 : printf (" %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
1370 : " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
1371 0 : ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
1372 : phdr->p_offset,
1373 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
1374 0 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
1375 : phdr->p_filesz,
1376 : phdr->p_memsz,
1377 0 : phdr->p_flags & PF_R ? 'R' : ' ',
1378 0 : phdr->p_flags & PF_W ? 'W' : ' ',
1379 0 : phdr->p_flags & PF_X ? 'E' : ' ',
1380 : phdr->p_align);
1381 :
1382 0 : if (phdr->p_type == PT_INTERP)
1383 : {
1384 : /* If we are sure the file offset is valid then we can show
1385 : the user the name of the interpreter. We check whether
1386 : there is a section at the file offset. Normally there
1387 : would be a section called ".interp". But in separate
1388 : .debug files it is a NOBITS section (and so doesn't match
1389 : with gelf_offscn). Which probably means the offset is
1390 : not valid another reason could be because the ELF file
1391 : just doesn't contain any section headers, in that case
1392 : just play it safe and don't display anything. */
1393 :
1394 0 : Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
1395 0 : GElf_Shdr shdr_mem;
1396 0 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1397 :
1398 0 : size_t maxsize;
1399 0 : char *filedata = elf_rawfile (ebl->elf, &maxsize);
1400 :
1401 0 : if (shdr != NULL && shdr->sh_type == SHT_PROGBITS
1402 0 : && filedata != NULL && phdr->p_offset < maxsize
1403 0 : && phdr->p_filesz <= maxsize - phdr->p_offset
1404 0 : && memchr (filedata + phdr->p_offset, '\0',
1405 : phdr->p_filesz) != NULL)
1406 0 : printf (gettext ("\t[Requesting program interpreter: %s]\n"),
1407 : filedata + phdr->p_offset);
1408 : }
1409 0 : else if (phdr->p_type == PT_GNU_RELRO)
1410 : {
1411 0 : has_relro = true;
1412 0 : relro_from = phdr->p_vaddr;
1413 0 : relro_to = relro_from + phdr->p_memsz;
1414 : }
1415 : }
1416 :
1417 0 : size_t sections;
1418 0 : if (unlikely (elf_getshdrnum (ebl->elf, §ions) < 0))
1419 0 : error (EXIT_FAILURE, 0,
1420 0 : gettext ("cannot get number of sections: %s"),
1421 : elf_errmsg (-1));
1422 :
1423 0 : if (sections == 0)
1424 : /* No sections in the file. Punt. */
1425 0 : return;
1426 :
1427 : /* Get the section header string table index. */
1428 0 : size_t shstrndx;
1429 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1430 0 : error (EXIT_FAILURE, 0,
1431 0 : gettext ("cannot get section header string table index"));
1432 :
1433 0 : puts (gettext ("\n Section to Segment mapping:\n Segment Sections..."));
1434 :
1435 0 : for (size_t cnt = 0; cnt < phnum; ++cnt)
1436 : {
1437 : /* Print the segment number. */
1438 0 : printf (" %2.2zu ", cnt);
1439 :
1440 0 : GElf_Phdr phdr_mem;
1441 0 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
1442 : /* This must not happen. */
1443 0 : if (unlikely (phdr == NULL))
1444 0 : error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
1445 : elf_errmsg (-1));
1446 :
1447 : /* Iterate over the sections. */
1448 : bool in_relro = false;
1449 : bool in_ro = false;
1450 0 : for (size_t inner = 1; inner < shnum; ++inner)
1451 : {
1452 0 : Elf_Scn *scn = elf_getscn (ebl->elf, inner);
1453 : /* This should not happen. */
1454 0 : if (unlikely (scn == NULL))
1455 0 : error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
1456 : elf_errmsg (-1));
1457 :
1458 : /* Get the section header. */
1459 0 : GElf_Shdr shdr_mem;
1460 0 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1461 0 : if (unlikely (shdr == NULL))
1462 0 : error (EXIT_FAILURE, 0,
1463 0 : gettext ("cannot get section header: %s"),
1464 : elf_errmsg (-1));
1465 :
1466 0 : if (shdr->sh_size > 0
1467 : /* Compare allocated sections by VMA, unallocated
1468 : sections by file offset. */
1469 0 : && (shdr->sh_flags & SHF_ALLOC
1470 0 : ? (shdr->sh_addr >= phdr->p_vaddr
1471 0 : && (shdr->sh_addr + shdr->sh_size
1472 0 : <= phdr->p_vaddr + phdr->p_memsz))
1473 0 : : (shdr->sh_offset >= phdr->p_offset
1474 0 : && (shdr->sh_offset + shdr->sh_size
1475 0 : <= phdr->p_offset + phdr->p_filesz))))
1476 : {
1477 0 : if (has_relro && !in_relro
1478 0 : && shdr->sh_addr >= relro_from
1479 0 : && shdr->sh_addr + shdr->sh_size <= relro_to)
1480 : {
1481 0 : fputs_unlocked (" [RELRO:", stdout);
1482 0 : in_relro = true;
1483 : }
1484 0 : else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
1485 : {
1486 0 : fputs_unlocked ("]", stdout);
1487 0 : in_relro = false;
1488 : }
1489 0 : else if (has_relro && in_relro
1490 0 : && shdr->sh_addr + shdr->sh_size > relro_to)
1491 0 : fputs_unlocked ("] <RELRO:", stdout);
1492 0 : else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
1493 : {
1494 0 : if (!in_ro)
1495 : {
1496 0 : fputs_unlocked (" [RO:", stdout);
1497 0 : in_ro = true;
1498 : }
1499 : }
1500 : else
1501 : {
1502 : /* Determine the segment this section is part of. */
1503 : size_t cnt2;
1504 : GElf_Phdr phdr2_mem;
1505 : GElf_Phdr *phdr2 = NULL;
1506 0 : for (cnt2 = 0; cnt2 < phnum; ++cnt2)
1507 : {
1508 0 : phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
1509 :
1510 0 : if (phdr2 != NULL && phdr2->p_type == PT_LOAD
1511 0 : && shdr->sh_addr >= phdr2->p_vaddr
1512 0 : && (shdr->sh_addr + shdr->sh_size
1513 0 : <= phdr2->p_vaddr + phdr2->p_memsz))
1514 : break;
1515 : }
1516 :
1517 0 : if (cnt2 < phnum)
1518 : {
1519 0 : if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
1520 : {
1521 0 : fputs_unlocked (" [RO:", stdout);
1522 0 : in_ro = true;
1523 : }
1524 0 : else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
1525 : {
1526 0 : fputs_unlocked ("]", stdout);
1527 0 : in_ro = false;
1528 : }
1529 : }
1530 : }
1531 :
1532 0 : printf (" %s",
1533 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1534 :
1535 : /* Signal that this sectin is only partially covered. */
1536 0 : if (has_relro && in_relro
1537 0 : && shdr->sh_addr + shdr->sh_size > relro_to)
1538 : {
1539 0 : fputs_unlocked (">", stdout);
1540 0 : in_relro = false;
1541 : }
1542 : }
1543 : }
1544 0 : if (in_relro || in_ro)
1545 0 : fputs_unlocked ("]", stdout);
1546 :
1547 : /* Finish the line. */
1548 0 : fputc_unlocked ('\n', stdout);
1549 : }
1550 : }
1551 :
1552 :
1553 : static const char *
1554 0 : section_name (Ebl *ebl, GElf_Shdr *shdr)
1555 : {
1556 0 : size_t shstrndx;
1557 0 : if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
1558 0 : return "???";
1559 0 : return elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "???";
1560 : }
1561 :
1562 :
1563 : static void
1564 0 : handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1565 : {
1566 : /* Get the data of the section. */
1567 0 : Elf_Data *data = elf_getdata (scn, NULL);
1568 :
1569 0 : Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1570 0 : GElf_Shdr symshdr_mem;
1571 0 : GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1572 0 : Elf_Data *symdata = elf_getdata (symscn, NULL);
1573 :
1574 0 : if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
1575 0 : || symdata == NULL)
1576 0 : return;
1577 :
1578 : /* Get the section header string table index. */
1579 0 : size_t shstrndx;
1580 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1581 0 : error (EXIT_FAILURE, 0,
1582 0 : gettext ("cannot get section header string table index"));
1583 :
1584 0 : Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
1585 :
1586 0 : GElf_Sym sym_mem;
1587 0 : GElf_Sym *sym = gelf_getsym (symdata, shdr->sh_info, &sym_mem);
1588 :
1589 0 : printf ((grpref[0] & GRP_COMDAT)
1590 0 : ? ngettext ("\
1591 : \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
1592 : "\
1593 : \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1594 : data->d_size / sizeof (Elf32_Word) - 1)
1595 0 : : ngettext ("\
1596 : \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
1597 : \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1598 : data->d_size / sizeof (Elf32_Word) - 1),
1599 : elf_ndxscn (scn),
1600 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1601 : (sym == NULL ? NULL
1602 0 : : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
1603 0 : ?: gettext ("<INVALID SYMBOL>"),
1604 0 : data->d_size / sizeof (Elf32_Word) - 1);
1605 :
1606 0 : for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1607 : {
1608 0 : GElf_Shdr grpshdr_mem;
1609 0 : GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
1610 : &grpshdr_mem);
1611 :
1612 0 : const char *str;
1613 0 : printf (" [%2u] %s\n",
1614 : grpref[cnt],
1615 : grpshdr != NULL
1616 0 : && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
1617 0 : ? str : gettext ("<INVALID SECTION>"));
1618 : }
1619 : }
1620 :
1621 :
1622 : static void
1623 51 : print_scngrp (Ebl *ebl)
1624 : {
1625 : /* Find all relocation sections and handle them. */
1626 51 : Elf_Scn *scn = NULL;
1627 :
1628 1332 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1629 : {
1630 : /* Handle the section if it is a symbol table. */
1631 1281 : GElf_Shdr shdr_mem;
1632 1281 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1633 :
1634 1281 : if (shdr != NULL && shdr->sh_type == SHT_GROUP)
1635 : {
1636 16 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1637 : {
1638 0 : if (elf_compress (scn, 0, 0) < 0)
1639 0 : printf ("WARNING: %s [%zd]\n",
1640 : gettext ("Couldn't uncompress section"),
1641 : elf_ndxscn (scn));
1642 0 : shdr = gelf_getshdr (scn, &shdr_mem);
1643 0 : if (unlikely (shdr == NULL))
1644 0 : error (EXIT_FAILURE, 0,
1645 0 : gettext ("cannot get section [%zd] header: %s"),
1646 : elf_ndxscn (scn),
1647 : elf_errmsg (-1));
1648 : }
1649 16 : handle_scngrp (ebl, scn, shdr);
1650 : }
1651 : }
1652 51 : }
1653 :
1654 :
1655 : static const struct flags
1656 : {
1657 : int mask;
1658 : const char *str;
1659 : } dt_flags[] =
1660 : {
1661 : { DF_ORIGIN, "ORIGIN" },
1662 : { DF_SYMBOLIC, "SYMBOLIC" },
1663 : { DF_TEXTREL, "TEXTREL" },
1664 : { DF_BIND_NOW, "BIND_NOW" },
1665 : { DF_STATIC_TLS, "STATIC_TLS" }
1666 : };
1667 : static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
1668 :
1669 : static const struct flags dt_flags_1[] =
1670 : {
1671 : { DF_1_NOW, "NOW" },
1672 : { DF_1_GLOBAL, "GLOBAL" },
1673 : { DF_1_GROUP, "GROUP" },
1674 : { DF_1_NODELETE, "NODELETE" },
1675 : { DF_1_LOADFLTR, "LOADFLTR" },
1676 : { DF_1_INITFIRST, "INITFIRST" },
1677 : { DF_1_NOOPEN, "NOOPEN" },
1678 : { DF_1_ORIGIN, "ORIGIN" },
1679 : { DF_1_DIRECT, "DIRECT" },
1680 : { DF_1_TRANS, "TRANS" },
1681 : { DF_1_INTERPOSE, "INTERPOSE" },
1682 : { DF_1_NODEFLIB, "NODEFLIB" },
1683 : { DF_1_NODUMP, "NODUMP" },
1684 : { DF_1_CONFALT, "CONFALT" },
1685 : { DF_1_ENDFILTEE, "ENDFILTEE" },
1686 : { DF_1_DISPRELDNE, "DISPRELDNE" },
1687 : { DF_1_DISPRELPND, "DISPRELPND" },
1688 : };
1689 : static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
1690 :
1691 : static const struct flags dt_feature_1[] =
1692 : {
1693 : { DTF_1_PARINIT, "PARINIT" },
1694 : { DTF_1_CONFEXP, "CONFEXP" }
1695 : };
1696 : static const int ndt_feature_1 = (sizeof (dt_feature_1)
1697 : / sizeof (dt_feature_1[0]));
1698 :
1699 : static const struct flags dt_posflag_1[] =
1700 : {
1701 : { DF_P1_LAZYLOAD, "LAZYLOAD" },
1702 : { DF_P1_GROUPPERM, "GROUPPERM" }
1703 : };
1704 : static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
1705 : / sizeof (dt_posflag_1[0]));
1706 :
1707 :
1708 : static void
1709 10 : print_flags (int class, GElf_Xword d_val, const struct flags *flags,
1710 : int nflags)
1711 : {
1712 10 : bool first = true;
1713 10 : int cnt;
1714 :
1715 138 : for (cnt = 0; cnt < nflags; ++cnt)
1716 128 : if (d_val & flags[cnt].mask)
1717 : {
1718 22 : if (!first)
1719 18 : putchar_unlocked (' ');
1720 22 : fputs_unlocked (flags[cnt].str, stdout);
1721 22 : d_val &= ~flags[cnt].mask;
1722 22 : first = false;
1723 : }
1724 :
1725 10 : if (d_val != 0)
1726 : {
1727 10 : if (!first)
1728 4 : putchar_unlocked (' ');
1729 16 : printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
1730 : }
1731 :
1732 10 : putchar_unlocked ('\n');
1733 10 : }
1734 :
1735 :
1736 : static void
1737 : print_dt_flags (int class, GElf_Xword d_val)
1738 : {
1739 1 : print_flags (class, d_val, dt_flags, ndt_flags);
1740 : }
1741 :
1742 :
1743 : static void
1744 : print_dt_flags_1 (int class, GElf_Xword d_val)
1745 : {
1746 7 : print_flags (class, d_val, dt_flags_1, ndt_flags_1);
1747 : }
1748 :
1749 :
1750 : static void
1751 : print_dt_feature_1 (int class, GElf_Xword d_val)
1752 : {
1753 1 : print_flags (class, d_val, dt_feature_1, ndt_feature_1);
1754 : }
1755 :
1756 :
1757 : static void
1758 : print_dt_posflag_1 (int class, GElf_Xword d_val)
1759 : {
1760 1 : print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
1761 : }
1762 :
1763 :
1764 : static void
1765 12 : handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1766 : {
1767 12 : int class = gelf_getclass (ebl->elf);
1768 12 : GElf_Shdr glink_mem;
1769 12 : GElf_Shdr *glink;
1770 12 : Elf_Data *data;
1771 12 : size_t cnt;
1772 12 : size_t shstrndx;
1773 12 : size_t sh_entsize;
1774 :
1775 : /* Get the data of the section. */
1776 12 : data = elf_getdata (scn, NULL);
1777 12 : if (data == NULL)
1778 0 : return;
1779 :
1780 : /* Get the section header string table index. */
1781 12 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1782 0 : error (EXIT_FAILURE, 0,
1783 0 : gettext ("cannot get section header string table index"));
1784 :
1785 12 : sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT);
1786 :
1787 12 : glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
1788 12 : if (glink == NULL)
1789 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
1790 : elf_ndxscn (scn));
1791 :
1792 12 : printf (ngettext ("\
1793 : \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1794 : "\
1795 : \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1796 : shdr->sh_size / sh_entsize),
1797 12 : (unsigned long int) (shdr->sh_size / sh_entsize),
1798 : class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
1799 : shdr->sh_offset,
1800 12 : (int) shdr->sh_link,
1801 12 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
1802 12 : fputs_unlocked (gettext (" Type Value\n"), stdout);
1803 :
1804 448 : for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
1805 : {
1806 436 : GElf_Dyn dynmem;
1807 436 : GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
1808 436 : if (dyn == NULL)
1809 : break;
1810 :
1811 436 : char buf[64];
1812 436 : printf (" %-17s ",
1813 : ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
1814 :
1815 436 : switch (dyn->d_tag)
1816 : {
1817 66 : case DT_NULL:
1818 : case DT_DEBUG:
1819 : case DT_BIND_NOW:
1820 : case DT_TEXTREL:
1821 : /* No further output. */
1822 66 : fputc_unlocked ('\n', stdout);
1823 : break;
1824 :
1825 52 : case DT_NEEDED:
1826 52 : printf (gettext ("Shared library: [%s]\n"),
1827 52 : elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1828 : break;
1829 :
1830 3 : case DT_SONAME:
1831 3 : printf (gettext ("Library soname: [%s]\n"),
1832 3 : elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1833 : break;
1834 :
1835 1 : case DT_RPATH:
1836 1 : printf (gettext ("Library rpath: [%s]\n"),
1837 1 : elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1838 : break;
1839 :
1840 2 : case DT_RUNPATH:
1841 2 : printf (gettext ("Library runpath: [%s]\n"),
1842 2 : elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1843 : break;
1844 :
1845 91 : case DT_PLTRELSZ:
1846 : case DT_RELASZ:
1847 : case DT_STRSZ:
1848 : case DT_RELSZ:
1849 : case DT_RELAENT:
1850 : case DT_SYMENT:
1851 : case DT_RELENT:
1852 : case DT_PLTPADSZ:
1853 : case DT_MOVEENT:
1854 : case DT_MOVESZ:
1855 : case DT_INIT_ARRAYSZ:
1856 : case DT_FINI_ARRAYSZ:
1857 : case DT_SYMINSZ:
1858 : case DT_SYMINENT:
1859 : case DT_GNU_CONFLICTSZ:
1860 : case DT_GNU_LIBLISTSZ:
1861 91 : printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
1862 : break;
1863 :
1864 31 : case DT_VERDEFNUM:
1865 : case DT_VERNEEDNUM:
1866 : case DT_RELACOUNT:
1867 : case DT_RELCOUNT:
1868 31 : printf ("%" PRId64 "\n", dyn->d_un.d_val);
1869 : break;
1870 :
1871 12 : case DT_PLTREL:;
1872 12 : const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
1873 : NULL, 0);
1874 12 : puts (tagname ?: "???");
1875 12 : break;
1876 :
1877 1 : case DT_FLAGS:
1878 1 : print_dt_flags (class, dyn->d_un.d_val);
1879 : break;
1880 :
1881 7 : case DT_FLAGS_1:
1882 7 : print_dt_flags_1 (class, dyn->d_un.d_val);
1883 : break;
1884 :
1885 1 : case DT_FEATURE_1:
1886 1 : print_dt_feature_1 (class, dyn->d_un.d_val);
1887 : break;
1888 :
1889 1 : case DT_POSFLAG_1:
1890 1 : print_dt_posflag_1 (class, dyn->d_un.d_val);
1891 : break;
1892 :
1893 168 : default:
1894 168 : printf ("%#0*" PRIx64 "\n",
1895 : class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
1896 : break;
1897 : }
1898 : }
1899 : }
1900 :
1901 :
1902 : /* Print the dynamic segment. */
1903 : static void
1904 44 : print_dynamic (Ebl *ebl)
1905 : {
1906 100 : for (size_t i = 0; i < phnum; ++i)
1907 : {
1908 68 : GElf_Phdr phdr_mem;
1909 68 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
1910 :
1911 68 : if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
1912 : {
1913 12 : Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
1914 12 : GElf_Shdr shdr_mem;
1915 12 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1916 12 : if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
1917 12 : handle_dynamic (ebl, scn, shdr);
1918 12 : break;
1919 : }
1920 : }
1921 44 : }
1922 :
1923 :
1924 : /* Print relocations. */
1925 : static void
1926 43 : print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
1927 : {
1928 : /* Find all relocation sections and handle them. */
1929 43 : Elf_Scn *scn = NULL;
1930 :
1931 1108 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1932 : {
1933 : /* Handle the section if it is a symbol table. */
1934 1065 : GElf_Shdr shdr_mem;
1935 1065 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1936 :
1937 1065 : if (likely (shdr != NULL))
1938 : {
1939 1065 : if (shdr->sh_type == SHT_REL)
1940 22 : handle_relocs_rel (ebl, ehdr, scn, shdr);
1941 1043 : else if (shdr->sh_type == SHT_RELA)
1942 172 : handle_relocs_rela (ebl, ehdr, scn, shdr);
1943 : }
1944 : }
1945 43 : }
1946 :
1947 :
1948 : /* Handle a relocation section. */
1949 : static void
1950 0 : handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1951 : {
1952 0 : int class = gelf_getclass (ebl->elf);
1953 0 : size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
1954 0 : int nentries = shdr->sh_size / sh_entsize;
1955 :
1956 : /* Get the data of the section. */
1957 0 : Elf_Data *data = elf_getdata (scn, NULL);
1958 0 : if (data == NULL)
1959 0 : return;
1960 :
1961 : /* Get the symbol table information. */
1962 0 : Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1963 0 : GElf_Shdr symshdr_mem;
1964 0 : GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1965 0 : Elf_Data *symdata = elf_getdata (symscn, NULL);
1966 :
1967 : /* Get the section header of the section the relocations are for. */
1968 0 : GElf_Shdr destshdr_mem;
1969 0 : GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1970 : &destshdr_mem);
1971 :
1972 0 : if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
1973 : {
1974 0 : printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1975 : shdr->sh_offset);
1976 0 : return;
1977 : }
1978 :
1979 : /* Search for the optional extended section index table. */
1980 0 : Elf_Data *xndxdata = NULL;
1981 0 : int xndxscnidx = elf_scnshndx (scn);
1982 0 : if (unlikely (xndxscnidx > 0))
1983 0 : xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
1984 :
1985 : /* Get the section header string table index. */
1986 0 : size_t shstrndx;
1987 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1988 0 : error (EXIT_FAILURE, 0,
1989 0 : gettext ("cannot get section header string table index"));
1990 :
1991 0 : if (shdr->sh_info != 0)
1992 0 : printf (ngettext ("\
1993 : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1994 : "\
1995 : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1996 : nentries),
1997 : elf_ndxscn (scn),
1998 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1999 0 : (unsigned int) shdr->sh_info,
2000 0 : elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
2001 : shdr->sh_offset,
2002 : nentries);
2003 : else
2004 : /* The .rel.dyn section does not refer to a specific section but
2005 : instead of section index zero. Do not try to print a section
2006 : name. */
2007 0 : printf (ngettext ("\
2008 : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2009 : "\
2010 : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2011 : nentries),
2012 0 : (unsigned int) elf_ndxscn (scn),
2013 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2014 : shdr->sh_offset,
2015 : nentries);
2016 0 : fputs_unlocked (class == ELFCLASS32
2017 0 : ? gettext ("\
2018 : Offset Type Value Name\n")
2019 0 : : gettext ("\
2020 : Offset Type Value Name\n"),
2021 : stdout);
2022 :
2023 0 : int is_statically_linked = 0;
2024 0 : for (int cnt = 0; cnt < nentries; ++cnt)
2025 : {
2026 0 : GElf_Rel relmem;
2027 0 : GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
2028 0 : if (likely (rel != NULL))
2029 : {
2030 0 : char buf[128];
2031 0 : GElf_Sym symmem;
2032 0 : Elf32_Word xndx;
2033 0 : GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
2034 0 : GELF_R_SYM (rel->r_info),
2035 : &symmem, &xndx);
2036 0 : if (unlikely (sym == NULL))
2037 : {
2038 : /* As a special case we have to handle relocations in static
2039 : executables. This only happens for IRELATIVE relocations
2040 : (so far). There is no symbol table. */
2041 0 : if (is_statically_linked == 0)
2042 : {
2043 : /* Find the program header and look for a PT_INTERP entry. */
2044 0 : is_statically_linked = -1;
2045 0 : if (ehdr->e_type == ET_EXEC)
2046 : {
2047 : is_statically_linked = 1;
2048 :
2049 0 : for (size_t inner = 0; inner < phnum; ++inner)
2050 : {
2051 0 : GElf_Phdr phdr_mem;
2052 0 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
2053 : &phdr_mem);
2054 0 : if (phdr != NULL && phdr->p_type == PT_INTERP)
2055 : {
2056 0 : is_statically_linked = -1;
2057 0 : break;
2058 : }
2059 : }
2060 : }
2061 : }
2062 :
2063 0 : if (is_statically_linked > 0 && shdr->sh_link == 0)
2064 0 : printf ("\
2065 : %#0*" PRIx64 " %-20s %*s %s\n",
2066 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2067 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2068 : /* Avoid the leading R_ which isn't carrying any
2069 : information. */
2070 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2071 : buf, sizeof (buf)) + 2
2072 0 : : gettext ("<INVALID RELOC>"),
2073 : class == ELFCLASS32 ? 10 : 18, "",
2074 0 : elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
2075 : else
2076 0 : printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
2077 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2078 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2079 : /* Avoid the leading R_ which isn't carrying any
2080 : information. */
2081 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2082 : buf, sizeof (buf)) + 2
2083 0 : : gettext ("<INVALID RELOC>"),
2084 : gettext ("INVALID SYMBOL"),
2085 0 : (long int) GELF_R_SYM (rel->r_info));
2086 : }
2087 0 : else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
2088 0 : printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
2089 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2090 0 : likely (ebl_reloc_type_check (ebl,
2091 : GELF_R_TYPE (rel->r_info)))
2092 : /* Avoid the leading R_ which isn't carrying any
2093 : information. */
2094 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2095 : buf, sizeof (buf)) + 2
2096 0 : : gettext ("<INVALID RELOC>"),
2097 : class == ELFCLASS32 ? 10 : 18, sym->st_value,
2098 0 : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
2099 : else
2100 : {
2101 : /* This is a relocation against a STT_SECTION symbol. */
2102 0 : GElf_Shdr secshdr_mem;
2103 0 : GElf_Shdr *secshdr;
2104 0 : secshdr = gelf_getshdr (elf_getscn (ebl->elf,
2105 0 : sym->st_shndx == SHN_XINDEX
2106 0 : ? xndx : sym->st_shndx),
2107 : &secshdr_mem);
2108 :
2109 0 : if (unlikely (secshdr == NULL))
2110 0 : printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
2111 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2112 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2113 : /* Avoid the leading R_ which isn't carrying any
2114 : information. */
2115 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2116 : buf, sizeof (buf)) + 2
2117 0 : : gettext ("<INVALID RELOC>"),
2118 : gettext ("INVALID SECTION"),
2119 0 : (long int) (sym->st_shndx == SHN_XINDEX
2120 0 : ? xndx : sym->st_shndx));
2121 : else
2122 0 : printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
2123 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2124 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2125 : /* Avoid the leading R_ which isn't carrying any
2126 : information. */
2127 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2128 : buf, sizeof (buf)) + 2
2129 0 : : gettext ("<INVALID RELOC>"),
2130 : class == ELFCLASS32 ? 10 : 18, sym->st_value,
2131 0 : elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
2132 : }
2133 : }
2134 : }
2135 : }
2136 :
2137 :
2138 : /* Handle a relocation section. */
2139 : static void
2140 0 : handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
2141 : {
2142 0 : int class = gelf_getclass (ebl->elf);
2143 0 : size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
2144 0 : int nentries = shdr->sh_size / sh_entsize;
2145 :
2146 : /* Get the data of the section. */
2147 0 : Elf_Data *data = elf_getdata (scn, NULL);
2148 0 : if (data == NULL)
2149 0 : return;
2150 :
2151 : /* Get the symbol table information. */
2152 0 : Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2153 0 : GElf_Shdr symshdr_mem;
2154 0 : GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2155 0 : Elf_Data *symdata = elf_getdata (symscn, NULL);
2156 :
2157 : /* Get the section header of the section the relocations are for. */
2158 0 : GElf_Shdr destshdr_mem;
2159 0 : GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
2160 : &destshdr_mem);
2161 :
2162 0 : if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
2163 : {
2164 0 : printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
2165 : shdr->sh_offset);
2166 0 : return;
2167 : }
2168 :
2169 : /* Search for the optional extended section index table. */
2170 0 : Elf_Data *xndxdata = NULL;
2171 0 : int xndxscnidx = elf_scnshndx (scn);
2172 0 : if (unlikely (xndxscnidx > 0))
2173 0 : xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
2174 :
2175 : /* Get the section header string table index. */
2176 0 : size_t shstrndx;
2177 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2178 0 : error (EXIT_FAILURE, 0,
2179 0 : gettext ("cannot get section header string table index"));
2180 :
2181 0 : if (shdr->sh_info != 0)
2182 0 : printf (ngettext ("\
2183 : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2184 : "\
2185 : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2186 : nentries),
2187 : elf_ndxscn (scn),
2188 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2189 0 : (unsigned int) shdr->sh_info,
2190 0 : elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
2191 : shdr->sh_offset,
2192 : nentries);
2193 : else
2194 : /* The .rela.dyn section does not refer to a specific section but
2195 : instead of section index zero. Do not try to print a section
2196 : name. */
2197 0 : printf (ngettext ("\
2198 : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2199 : "\
2200 : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2201 : nentries),
2202 0 : (unsigned int) elf_ndxscn (scn),
2203 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2204 : shdr->sh_offset,
2205 : nentries);
2206 0 : fputs_unlocked (class == ELFCLASS32
2207 0 : ? gettext ("\
2208 : Offset Type Value Addend Name\n")
2209 0 : : gettext ("\
2210 : Offset Type Value Addend Name\n"),
2211 : stdout);
2212 :
2213 0 : int is_statically_linked = 0;
2214 0 : for (int cnt = 0; cnt < nentries; ++cnt)
2215 : {
2216 0 : GElf_Rela relmem;
2217 0 : GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
2218 0 : if (likely (rel != NULL))
2219 : {
2220 0 : char buf[64];
2221 0 : GElf_Sym symmem;
2222 0 : Elf32_Word xndx;
2223 0 : GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
2224 0 : GELF_R_SYM (rel->r_info),
2225 : &symmem, &xndx);
2226 :
2227 0 : if (unlikely (sym == NULL))
2228 : {
2229 : /* As a special case we have to handle relocations in static
2230 : executables. This only happens for IRELATIVE relocations
2231 : (so far). There is no symbol table. */
2232 0 : if (is_statically_linked == 0)
2233 : {
2234 : /* Find the program header and look for a PT_INTERP entry. */
2235 0 : is_statically_linked = -1;
2236 0 : if (ehdr->e_type == ET_EXEC)
2237 : {
2238 : is_statically_linked = 1;
2239 :
2240 0 : for (size_t inner = 0; inner < phnum; ++inner)
2241 : {
2242 0 : GElf_Phdr phdr_mem;
2243 0 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
2244 : &phdr_mem);
2245 0 : if (phdr != NULL && phdr->p_type == PT_INTERP)
2246 : {
2247 0 : is_statically_linked = -1;
2248 0 : break;
2249 : }
2250 : }
2251 : }
2252 : }
2253 :
2254 0 : if (is_statically_linked > 0 && shdr->sh_link == 0)
2255 0 : printf ("\
2256 : %#0*" PRIx64 " %-15s %*s %#6" PRIx64 " %s\n",
2257 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2258 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2259 : /* Avoid the leading R_ which isn't carrying any
2260 : information. */
2261 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2262 : buf, sizeof (buf)) + 2
2263 0 : : gettext ("<INVALID RELOC>"),
2264 : class == ELFCLASS32 ? 10 : 18, "",
2265 : rel->r_addend,
2266 0 : elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
2267 : else
2268 0 : printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
2269 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2270 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2271 : /* Avoid the leading R_ which isn't carrying any
2272 : information. */
2273 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2274 : buf, sizeof (buf)) + 2
2275 0 : : gettext ("<INVALID RELOC>"),
2276 : gettext ("INVALID SYMBOL"),
2277 0 : (long int) GELF_R_SYM (rel->r_info));
2278 : }
2279 0 : else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
2280 0 : printf ("\
2281 : %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
2282 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2283 0 : likely (ebl_reloc_type_check (ebl,
2284 : GELF_R_TYPE (rel->r_info)))
2285 : /* Avoid the leading R_ which isn't carrying any
2286 : information. */
2287 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2288 : buf, sizeof (buf)) + 2
2289 0 : : gettext ("<INVALID RELOC>"),
2290 : class == ELFCLASS32 ? 10 : 18, sym->st_value,
2291 : rel->r_addend,
2292 0 : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
2293 : else
2294 : {
2295 : /* This is a relocation against a STT_SECTION symbol. */
2296 0 : GElf_Shdr secshdr_mem;
2297 0 : GElf_Shdr *secshdr;
2298 0 : secshdr = gelf_getshdr (elf_getscn (ebl->elf,
2299 0 : sym->st_shndx == SHN_XINDEX
2300 0 : ? xndx : sym->st_shndx),
2301 : &secshdr_mem);
2302 :
2303 0 : if (unlikely (secshdr == NULL))
2304 0 : printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
2305 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2306 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2307 : /* Avoid the leading R_ which isn't carrying any
2308 : information. */
2309 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2310 : buf, sizeof (buf)) + 2
2311 0 : : gettext ("<INVALID RELOC>"),
2312 : gettext ("INVALID SECTION"),
2313 0 : (long int) (sym->st_shndx == SHN_XINDEX
2314 0 : ? xndx : sym->st_shndx));
2315 : else
2316 0 : printf ("\
2317 : %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
2318 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2319 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2320 : /* Avoid the leading R_ which isn't carrying any
2321 : information. */
2322 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2323 : buf, sizeof (buf)) + 2
2324 0 : : gettext ("<INVALID RELOC>"),
2325 : class == ELFCLASS32 ? 10 : 18, sym->st_value,
2326 : rel->r_addend,
2327 0 : elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
2328 : }
2329 : }
2330 : }
2331 : }
2332 :
2333 :
2334 : /* Print the program header. */
2335 : static void
2336 112 : print_symtab (Ebl *ebl, int type)
2337 : {
2338 : /* Find the symbol table(s). For this we have to search through the
2339 : section table. */
2340 112 : Elf_Scn *scn = NULL;
2341 :
2342 2932 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2343 : {
2344 : /* Handle the section if it is a symbol table. */
2345 2820 : GElf_Shdr shdr_mem;
2346 2820 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2347 :
2348 2820 : if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
2349 : {
2350 66 : if (symbol_table_section != NULL)
2351 : {
2352 : /* Get the section header string table index. */
2353 4 : size_t shstrndx;
2354 4 : const char *sname;
2355 4 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2356 0 : error (EXIT_FAILURE, 0,
2357 0 : gettext ("cannot get section header string table index"));
2358 4 : sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
2359 4 : if (sname == NULL || strcmp (sname, symbol_table_section) != 0)
2360 2 : continue;
2361 : }
2362 :
2363 64 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
2364 : {
2365 0 : if (elf_compress (scn, 0, 0) < 0)
2366 0 : printf ("WARNING: %s [%zd]\n",
2367 : gettext ("Couldn't uncompress section"),
2368 : elf_ndxscn (scn));
2369 0 : shdr = gelf_getshdr (scn, &shdr_mem);
2370 0 : if (unlikely (shdr == NULL))
2371 0 : error (EXIT_FAILURE, 0,
2372 0 : gettext ("cannot get section [%zd] header: %s"),
2373 : elf_ndxscn (scn), elf_errmsg (-1));
2374 : }
2375 64 : handle_symtab (ebl, scn, shdr);
2376 : }
2377 : }
2378 112 : }
2379 :
2380 :
2381 : static void
2382 64 : handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2383 : {
2384 64 : Elf_Data *versym_data = NULL;
2385 64 : Elf_Data *verneed_data = NULL;
2386 64 : Elf_Data *verdef_data = NULL;
2387 64 : Elf_Data *xndx_data = NULL;
2388 64 : int class = gelf_getclass (ebl->elf);
2389 64 : Elf32_Word verneed_stridx = 0;
2390 64 : Elf32_Word verdef_stridx = 0;
2391 :
2392 : /* Get the data of the section. */
2393 64 : Elf_Data *data = elf_getdata (scn, NULL);
2394 64 : if (data == NULL)
2395 0 : return;
2396 :
2397 : /* Find out whether we have other sections we might need. */
2398 : Elf_Scn *runscn = NULL;
2399 1800 : while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
2400 : {
2401 1736 : GElf_Shdr runshdr_mem;
2402 1736 : GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
2403 :
2404 1736 : if (likely (runshdr != NULL))
2405 : {
2406 1736 : if (runshdr->sh_type == SHT_GNU_versym
2407 27 : && runshdr->sh_link == elf_ndxscn (scn))
2408 : /* Bingo, found the version information. Now get the data. */
2409 17 : versym_data = elf_getdata (runscn, NULL);
2410 1719 : else if (runshdr->sh_type == SHT_GNU_verneed)
2411 : {
2412 : /* This is the information about the needed versions. */
2413 27 : verneed_data = elf_getdata (runscn, NULL);
2414 27 : verneed_stridx = runshdr->sh_link;
2415 : }
2416 1692 : else if (runshdr->sh_type == SHT_GNU_verdef)
2417 : {
2418 : /* This is the information about the defined versions. */
2419 8 : verdef_data = elf_getdata (runscn, NULL);
2420 8 : verdef_stridx = runshdr->sh_link;
2421 : }
2422 1684 : else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
2423 0 : && runshdr->sh_link == elf_ndxscn (scn))
2424 : /* Extended section index. */
2425 0 : xndx_data = elf_getdata (runscn, NULL);
2426 : }
2427 : }
2428 :
2429 : /* Get the section header string table index. */
2430 64 : size_t shstrndx;
2431 64 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2432 0 : error (EXIT_FAILURE, 0,
2433 0 : gettext ("cannot get section header string table index"));
2434 :
2435 64 : GElf_Shdr glink_mem;
2436 64 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2437 : &glink_mem);
2438 64 : if (glink == NULL)
2439 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
2440 : elf_ndxscn (scn));
2441 :
2442 : /* Now we can compute the number of entries in the section. */
2443 128 : unsigned int nsyms = data->d_size / (class == ELFCLASS32
2444 : ? sizeof (Elf32_Sym)
2445 64 : : sizeof (Elf64_Sym));
2446 :
2447 64 : printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
2448 : "\nSymbol table [%2u] '%s' contains %u entries:\n",
2449 : nsyms),
2450 64 : (unsigned int) elf_ndxscn (scn),
2451 64 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
2452 64 : printf (ngettext (" %lu local symbol String table: [%2u] '%s'\n",
2453 : " %lu local symbols String table: [%2u] '%s'\n",
2454 : shdr->sh_info),
2455 64 : (unsigned long int) shdr->sh_info,
2456 64 : (unsigned int) shdr->sh_link,
2457 64 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
2458 :
2459 64 : fputs_unlocked (class == ELFCLASS32
2460 8 : ? gettext ("\
2461 : Num: Value Size Type Bind Vis Ndx Name\n")
2462 56 : : gettext ("\
2463 : Num: Value Size Type Bind Vis Ndx Name\n"),
2464 : stdout);
2465 :
2466 15035 : for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
2467 : {
2468 14971 : char typebuf[64];
2469 14971 : char bindbuf[64];
2470 14971 : char scnbuf[64];
2471 14971 : Elf32_Word xndx;
2472 14971 : GElf_Sym sym_mem;
2473 14971 : GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
2474 :
2475 14971 : if (unlikely (sym == NULL))
2476 0 : continue;
2477 :
2478 : /* Determine the real section index. */
2479 14971 : if (likely (sym->st_shndx != SHN_XINDEX))
2480 14971 : xndx = sym->st_shndx;
2481 :
2482 29750 : printf (gettext ("\
2483 : %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
2484 : cnt,
2485 : class == ELFCLASS32 ? 8 : 16,
2486 : sym->st_value,
2487 : sym->st_size,
2488 14971 : ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
2489 : typebuf, sizeof (typebuf)),
2490 14971 : ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
2491 : bindbuf, sizeof (bindbuf)),
2492 14971 : get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
2493 14971 : ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
2494 : sizeof (scnbuf), NULL, shnum),
2495 14971 : elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
2496 :
2497 14971 : if (versym_data != NULL)
2498 : {
2499 : /* Get the version information. */
2500 1390 : GElf_Versym versym_mem;
2501 1390 : GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
2502 :
2503 1390 : if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
2504 : {
2505 1192 : bool is_nobits = false;
2506 1192 : bool check_def = xndx != SHN_UNDEF;
2507 :
2508 1192 : if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
2509 : {
2510 1155 : GElf_Shdr symshdr_mem;
2511 1155 : GElf_Shdr *symshdr =
2512 1155 : gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
2513 :
2514 1155 : is_nobits = (symshdr != NULL
2515 1155 : && symshdr->sh_type == SHT_NOBITS);
2516 : }
2517 :
2518 1192 : if (is_nobits || ! check_def)
2519 : {
2520 : /* We must test both. */
2521 813 : GElf_Vernaux vernaux_mem;
2522 813 : GElf_Vernaux *vernaux = NULL;
2523 813 : size_t vn_offset = 0;
2524 :
2525 813 : GElf_Verneed verneed_mem;
2526 813 : GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
2527 : &verneed_mem);
2528 3244 : while (verneed != NULL)
2529 : {
2530 3244 : size_t vna_offset = vn_offset;
2531 :
2532 6488 : vernaux = gelf_getvernaux (verneed_data,
2533 3244 : vna_offset += verneed->vn_aux,
2534 : &vernaux_mem);
2535 6605 : while (vernaux != NULL
2536 6605 : && vernaux->vna_other != *versym
2537 5792 : && vernaux->vna_next != 0)
2538 : {
2539 : /* Update the offset. */
2540 3361 : vna_offset += vernaux->vna_next;
2541 :
2542 6722 : vernaux = (vernaux->vna_next == 0
2543 : ? NULL
2544 3361 : : gelf_getvernaux (verneed_data,
2545 : vna_offset,
2546 : &vernaux_mem));
2547 : }
2548 :
2549 : /* Check whether we found the version. */
2550 3244 : if (vernaux != NULL && vernaux->vna_other == *versym)
2551 : /* Found it. */
2552 : break;
2553 :
2554 2431 : vn_offset += verneed->vn_next;
2555 2431 : verneed = (verneed->vn_next == 0
2556 : ? NULL
2557 2431 : : gelf_getverneed (verneed_data, vn_offset,
2558 : &verneed_mem));
2559 : }
2560 :
2561 813 : if (vernaux != NULL && vernaux->vna_other == *versym)
2562 : {
2563 813 : printf ("@%s (%u)",
2564 : elf_strptr (ebl->elf, verneed_stridx,
2565 813 : vernaux->vna_name),
2566 : (unsigned int) vernaux->vna_other);
2567 813 : check_def = 0;
2568 : }
2569 0 : else if (unlikely (! is_nobits))
2570 0 : error (0, 0, gettext ("bad dynamic symbol"));
2571 : else
2572 : check_def = 1;
2573 : }
2574 :
2575 1192 : if (check_def && *versym != 0x8001)
2576 : {
2577 : /* We must test both. */
2578 379 : size_t vd_offset = 0;
2579 :
2580 379 : GElf_Verdef verdef_mem;
2581 379 : GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
2582 : &verdef_mem);
2583 2553 : while (verdef != NULL)
2584 : {
2585 2553 : if (verdef->vd_ndx == (*versym & 0x7fff))
2586 : /* Found the definition. */
2587 : break;
2588 :
2589 2174 : vd_offset += verdef->vd_next;
2590 2174 : verdef = (verdef->vd_next == 0
2591 : ? NULL
2592 2174 : : gelf_getverdef (verdef_data, vd_offset,
2593 : &verdef_mem));
2594 : }
2595 :
2596 379 : if (verdef != NULL)
2597 : {
2598 379 : GElf_Verdaux verdaux_mem;
2599 379 : GElf_Verdaux *verdaux
2600 758 : = gelf_getverdaux (verdef_data,
2601 379 : vd_offset + verdef->vd_aux,
2602 : &verdaux_mem);
2603 :
2604 379 : if (verdaux != NULL)
2605 745 : printf ((*versym & 0x8000) ? "@%s" : "@@%s",
2606 : elf_strptr (ebl->elf, verdef_stridx,
2607 379 : verdaux->vda_name));
2608 : }
2609 : }
2610 : }
2611 : }
2612 :
2613 29942 : putchar_unlocked ('\n');
2614 : }
2615 : }
2616 :
2617 :
2618 : /* Print version information. */
2619 : static void
2620 42 : print_verinfo (Ebl *ebl)
2621 : {
2622 : /* Find the version information sections. For this we have to
2623 : search through the section table. */
2624 42 : Elf_Scn *scn = NULL;
2625 :
2626 1073 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2627 : {
2628 : /* Handle the section if it is part of the versioning handling. */
2629 1031 : GElf_Shdr shdr_mem;
2630 1031 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2631 :
2632 1031 : if (likely (shdr != NULL))
2633 : {
2634 1031 : if (shdr->sh_type == SHT_GNU_verneed)
2635 10 : handle_verneed (ebl, scn, shdr);
2636 1021 : else if (shdr->sh_type == SHT_GNU_verdef)
2637 4 : handle_verdef (ebl, scn, shdr);
2638 1017 : else if (shdr->sh_type == SHT_GNU_versym)
2639 10 : handle_versym (ebl, scn, shdr);
2640 : }
2641 : }
2642 42 : }
2643 :
2644 :
2645 : static const char *
2646 123 : get_ver_flags (unsigned int flags)
2647 : {
2648 123 : static char buf[32];
2649 123 : char *endp;
2650 :
2651 123 : if (flags == 0)
2652 118 : return gettext ("none");
2653 :
2654 5 : if (flags & VER_FLG_BASE)
2655 8 : endp = stpcpy (buf, "BASE ");
2656 : else
2657 : endp = buf;
2658 :
2659 5 : if (flags & VER_FLG_WEAK)
2660 : {
2661 1 : if (endp != buf)
2662 0 : endp = stpcpy (endp, "| ");
2663 :
2664 2 : endp = stpcpy (endp, "WEAK ");
2665 : }
2666 :
2667 5 : if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
2668 : {
2669 0 : strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
2670 0 : buf[sizeof (buf) - 1] = '\0';
2671 : }
2672 :
2673 : return buf;
2674 : }
2675 :
2676 :
2677 : static void
2678 0 : handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2679 : {
2680 0 : int class = gelf_getclass (ebl->elf);
2681 :
2682 : /* Get the data of the section. */
2683 0 : Elf_Data *data = elf_getdata (scn, NULL);
2684 0 : if (data == NULL)
2685 0 : return;
2686 :
2687 : /* Get the section header string table index. */
2688 0 : size_t shstrndx;
2689 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2690 0 : error (EXIT_FAILURE, 0,
2691 0 : gettext ("cannot get section header string table index"));
2692 :
2693 0 : GElf_Shdr glink_mem;
2694 0 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2695 : &glink_mem);
2696 0 : if (glink == NULL)
2697 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
2698 : elf_ndxscn (scn));
2699 :
2700 0 : printf (ngettext ("\
2701 : \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2702 : "\
2703 : \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2704 : shdr->sh_info),
2705 0 : (unsigned int) elf_ndxscn (scn),
2706 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
2707 : class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2708 : shdr->sh_offset,
2709 0 : (unsigned int) shdr->sh_link,
2710 0 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
2711 :
2712 0 : unsigned int offset = 0;
2713 0 : for (int cnt = shdr->sh_info; --cnt >= 0; )
2714 : {
2715 : /* Get the data at the next offset. */
2716 0 : GElf_Verneed needmem;
2717 0 : GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
2718 0 : if (unlikely (need == NULL))
2719 : break;
2720 :
2721 0 : printf (gettext (" %#06x: Version: %hu File: %s Cnt: %hu\n"),
2722 0 : offset, (unsigned short int) need->vn_version,
2723 0 : elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
2724 0 : (unsigned short int) need->vn_cnt);
2725 :
2726 0 : unsigned int auxoffset = offset + need->vn_aux;
2727 0 : for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2728 : {
2729 0 : GElf_Vernaux auxmem;
2730 0 : GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
2731 0 : if (unlikely (aux == NULL))
2732 : break;
2733 :
2734 0 : printf (gettext (" %#06x: Name: %s Flags: %s Version: %hu\n"),
2735 : auxoffset,
2736 0 : elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
2737 0 : get_ver_flags (aux->vna_flags),
2738 0 : (unsigned short int) aux->vna_other);
2739 :
2740 0 : if (aux->vna_next == 0)
2741 : break;
2742 :
2743 0 : auxoffset += aux->vna_next;
2744 : }
2745 :
2746 : /* Find the next offset. */
2747 0 : if (need->vn_next == 0)
2748 : break;
2749 :
2750 0 : offset += need->vn_next;
2751 : }
2752 : }
2753 :
2754 :
2755 : static void
2756 0 : handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2757 : {
2758 : /* Get the data of the section. */
2759 0 : Elf_Data *data = elf_getdata (scn, NULL);
2760 0 : if (data == NULL)
2761 0 : return;
2762 :
2763 : /* Get the section header string table index. */
2764 0 : size_t shstrndx;
2765 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2766 0 : error (EXIT_FAILURE, 0,
2767 0 : gettext ("cannot get section header string table index"));
2768 :
2769 0 : GElf_Shdr glink_mem;
2770 0 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2771 : &glink_mem);
2772 0 : if (glink == NULL)
2773 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
2774 : elf_ndxscn (scn));
2775 :
2776 0 : int class = gelf_getclass (ebl->elf);
2777 0 : printf (ngettext ("\
2778 : \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2779 : "\
2780 : \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2781 : shdr->sh_info),
2782 0 : (unsigned int) elf_ndxscn (scn),
2783 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2784 : shdr->sh_info,
2785 : class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2786 : shdr->sh_offset,
2787 0 : (unsigned int) shdr->sh_link,
2788 0 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
2789 :
2790 0 : unsigned int offset = 0;
2791 0 : for (int cnt = shdr->sh_info; --cnt >= 0; )
2792 : {
2793 : /* Get the data at the next offset. */
2794 0 : GElf_Verdef defmem;
2795 0 : GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
2796 0 : if (unlikely (def == NULL))
2797 : break;
2798 :
2799 0 : unsigned int auxoffset = offset + def->vd_aux;
2800 0 : GElf_Verdaux auxmem;
2801 0 : GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
2802 0 : if (unlikely (aux == NULL))
2803 : break;
2804 :
2805 0 : printf (gettext ("\
2806 : %#06x: Version: %hd Flags: %s Index: %hd Cnt: %hd Name: %s\n"),
2807 0 : offset, def->vd_version,
2808 0 : get_ver_flags (def->vd_flags),
2809 0 : def->vd_ndx,
2810 0 : def->vd_cnt,
2811 0 : elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2812 :
2813 0 : auxoffset += aux->vda_next;
2814 0 : for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
2815 : {
2816 0 : aux = gelf_getverdaux (data, auxoffset, &auxmem);
2817 0 : if (unlikely (aux == NULL))
2818 : break;
2819 :
2820 0 : printf (gettext (" %#06x: Parent %d: %s\n"),
2821 : auxoffset, cnt2,
2822 0 : elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2823 :
2824 0 : if (aux->vda_next == 0)
2825 : break;
2826 :
2827 0 : auxoffset += aux->vda_next;
2828 : }
2829 :
2830 : /* Find the next offset. */
2831 0 : if (def->vd_next == 0)
2832 : break;
2833 0 : offset += def->vd_next;
2834 : }
2835 : }
2836 :
2837 :
2838 : static void
2839 0 : handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2840 : {
2841 0 : int class = gelf_getclass (ebl->elf);
2842 0 : const char **vername;
2843 0 : const char **filename;
2844 :
2845 : /* Get the data of the section. */
2846 0 : Elf_Data *data = elf_getdata (scn, NULL);
2847 0 : if (data == NULL)
2848 0 : return;
2849 :
2850 : /* Get the section header string table index. */
2851 0 : size_t shstrndx;
2852 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2853 0 : error (EXIT_FAILURE, 0,
2854 0 : gettext ("cannot get section header string table index"));
2855 :
2856 : /* We have to find the version definition section and extract the
2857 : version names. */
2858 : Elf_Scn *defscn = NULL;
2859 : Elf_Scn *needscn = NULL;
2860 :
2861 : Elf_Scn *verscn = NULL;
2862 0 : while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
2863 : {
2864 0 : GElf_Shdr vershdr_mem;
2865 0 : GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
2866 :
2867 0 : if (likely (vershdr != NULL))
2868 : {
2869 0 : if (vershdr->sh_type == SHT_GNU_verdef)
2870 : defscn = verscn;
2871 0 : else if (vershdr->sh_type == SHT_GNU_verneed)
2872 0 : needscn = verscn;
2873 : }
2874 : }
2875 :
2876 0 : size_t nvername;
2877 0 : if (defscn != NULL || needscn != NULL)
2878 : {
2879 : /* We have a version information (better should have). Now get
2880 : the version names. First find the maximum version number. */
2881 0 : nvername = 0;
2882 0 : if (defscn != NULL)
2883 : {
2884 : /* Run through the version definitions and find the highest
2885 : index. */
2886 0 : unsigned int offset = 0;
2887 0 : Elf_Data *defdata;
2888 0 : GElf_Shdr defshdrmem;
2889 0 : GElf_Shdr *defshdr;
2890 :
2891 0 : defdata = elf_getdata (defscn, NULL);
2892 0 : if (unlikely (defdata == NULL))
2893 0 : return;
2894 :
2895 0 : defshdr = gelf_getshdr (defscn, &defshdrmem);
2896 0 : if (unlikely (defshdr == NULL))
2897 0 : return;
2898 :
2899 0 : for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
2900 : {
2901 0 : GElf_Verdef defmem;
2902 0 : GElf_Verdef *def;
2903 :
2904 : /* Get the data at the next offset. */
2905 0 : def = gelf_getverdef (defdata, offset, &defmem);
2906 0 : if (unlikely (def == NULL))
2907 : break;
2908 :
2909 0 : nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
2910 :
2911 0 : if (def->vd_next == 0)
2912 : break;
2913 0 : offset += def->vd_next;
2914 : }
2915 : }
2916 0 : if (needscn != NULL)
2917 : {
2918 0 : unsigned int offset = 0;
2919 0 : Elf_Data *needdata;
2920 0 : GElf_Shdr needshdrmem;
2921 0 : GElf_Shdr *needshdr;
2922 :
2923 0 : needdata = elf_getdata (needscn, NULL);
2924 0 : if (unlikely (needdata == NULL))
2925 0 : return;
2926 :
2927 0 : needshdr = gelf_getshdr (needscn, &needshdrmem);
2928 0 : if (unlikely (needshdr == NULL))
2929 0 : return;
2930 :
2931 0 : for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
2932 : {
2933 0 : GElf_Verneed needmem;
2934 0 : GElf_Verneed *need;
2935 0 : unsigned int auxoffset;
2936 0 : int cnt2;
2937 :
2938 : /* Get the data at the next offset. */
2939 0 : need = gelf_getverneed (needdata, offset, &needmem);
2940 0 : if (unlikely (need == NULL))
2941 : break;
2942 :
2943 : /* Run through the auxiliary entries. */
2944 0 : auxoffset = offset + need->vn_aux;
2945 0 : for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
2946 : {
2947 0 : GElf_Vernaux auxmem;
2948 0 : GElf_Vernaux *aux;
2949 :
2950 0 : aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
2951 0 : if (unlikely (aux == NULL))
2952 : break;
2953 :
2954 0 : nvername = MAX (nvername,
2955 : (size_t) (aux->vna_other & 0x7fff));
2956 :
2957 0 : if (aux->vna_next == 0)
2958 : break;
2959 0 : auxoffset += aux->vna_next;
2960 : }
2961 :
2962 0 : if (need->vn_next == 0)
2963 : break;
2964 0 : offset += need->vn_next;
2965 : }
2966 : }
2967 :
2968 : /* This is the number of versions we know about. */
2969 0 : ++nvername;
2970 :
2971 : /* Allocate the array. */
2972 0 : vername = (const char **) alloca (nvername * sizeof (const char *));
2973 0 : memset(vername, 0, nvername * sizeof (const char *));
2974 0 : filename = (const char **) alloca (nvername * sizeof (const char *));
2975 0 : memset(filename, 0, nvername * sizeof (const char *));
2976 :
2977 : /* Run through the data structures again and collect the strings. */
2978 0 : if (defscn != NULL)
2979 : {
2980 : /* Run through the version definitions and find the highest
2981 : index. */
2982 0 : unsigned int offset = 0;
2983 0 : Elf_Data *defdata;
2984 0 : GElf_Shdr defshdrmem;
2985 0 : GElf_Shdr *defshdr;
2986 :
2987 0 : defdata = elf_getdata (defscn, NULL);
2988 0 : if (unlikely (defdata == NULL))
2989 0 : return;
2990 :
2991 0 : defshdr = gelf_getshdr (defscn, &defshdrmem);
2992 0 : if (unlikely (defshdr == NULL))
2993 0 : return;
2994 :
2995 0 : for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
2996 : {
2997 :
2998 : /* Get the data at the next offset. */
2999 0 : GElf_Verdef defmem;
3000 0 : GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
3001 0 : if (unlikely (def == NULL))
3002 : break;
3003 :
3004 0 : GElf_Verdaux auxmem;
3005 0 : GElf_Verdaux *aux = gelf_getverdaux (defdata,
3006 0 : offset + def->vd_aux,
3007 : &auxmem);
3008 0 : if (unlikely (aux == NULL))
3009 : break;
3010 :
3011 0 : vername[def->vd_ndx & 0x7fff]
3012 0 : = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
3013 0 : filename[def->vd_ndx & 0x7fff] = NULL;
3014 :
3015 0 : if (def->vd_next == 0)
3016 : break;
3017 0 : offset += def->vd_next;
3018 : }
3019 : }
3020 0 : if (needscn != NULL)
3021 : {
3022 0 : unsigned int offset = 0;
3023 :
3024 0 : Elf_Data *needdata = elf_getdata (needscn, NULL);
3025 0 : GElf_Shdr needshdrmem;
3026 0 : GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
3027 0 : if (unlikely (needdata == NULL || needshdr == NULL))
3028 0 : return;
3029 :
3030 0 : for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
3031 : {
3032 : /* Get the data at the next offset. */
3033 0 : GElf_Verneed needmem;
3034 0 : GElf_Verneed *need = gelf_getverneed (needdata, offset,
3035 : &needmem);
3036 0 : if (unlikely (need == NULL))
3037 : break;
3038 :
3039 : /* Run through the auxiliary entries. */
3040 0 : unsigned int auxoffset = offset + need->vn_aux;
3041 0 : for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
3042 : {
3043 0 : GElf_Vernaux auxmem;
3044 0 : GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
3045 : &auxmem);
3046 0 : if (unlikely (aux == NULL))
3047 : break;
3048 :
3049 0 : vername[aux->vna_other & 0x7fff]
3050 0 : = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
3051 0 : filename[aux->vna_other & 0x7fff]
3052 0 : = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
3053 :
3054 0 : if (aux->vna_next == 0)
3055 : break;
3056 0 : auxoffset += aux->vna_next;
3057 : }
3058 :
3059 0 : if (need->vn_next == 0)
3060 : break;
3061 0 : offset += need->vn_next;
3062 : }
3063 : }
3064 : }
3065 : else
3066 : {
3067 : vername = NULL;
3068 : nvername = 1;
3069 : filename = NULL;
3070 : }
3071 :
3072 0 : GElf_Shdr glink_mem;
3073 0 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
3074 : &glink_mem);
3075 0 : size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_HALF, 1, EV_CURRENT);
3076 0 : if (glink == NULL)
3077 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
3078 : elf_ndxscn (scn));
3079 :
3080 : /* Print the header. */
3081 0 : printf (ngettext ("\
3082 : \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
3083 : "\
3084 : \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
3085 : shdr->sh_size / sh_entsize),
3086 0 : (unsigned int) elf_ndxscn (scn),
3087 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3088 0 : (int) (shdr->sh_size / sh_entsize),
3089 : class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
3090 : shdr->sh_offset,
3091 0 : (unsigned int) shdr->sh_link,
3092 0 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
3093 :
3094 : /* Now we can finally look at the actual contents of this section. */
3095 0 : for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
3096 : {
3097 0 : if (cnt % 2 == 0)
3098 0 : printf ("\n %4d:", cnt);
3099 :
3100 0 : GElf_Versym symmem;
3101 0 : GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
3102 0 : if (sym == NULL)
3103 : break;
3104 :
3105 0 : switch (*sym)
3106 : {
3107 0 : ssize_t n;
3108 0 : case 0:
3109 0 : fputs_unlocked (gettext (" 0 *local* "),
3110 : stdout);
3111 0 : break;
3112 :
3113 0 : case 1:
3114 0 : fputs_unlocked (gettext (" 1 *global* "),
3115 : stdout);
3116 0 : break;
3117 :
3118 0 : default:
3119 0 : n = printf ("%4d%c%s",
3120 0 : *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
3121 : (vername != NULL
3122 0 : && (unsigned int) (*sym & 0x7fff) < nvername)
3123 0 : ? vername[*sym & 0x7fff] : "???");
3124 0 : if ((unsigned int) (*sym & 0x7fff) < nvername
3125 0 : && filename != NULL && filename[*sym & 0x7fff] != NULL)
3126 0 : n += printf ("(%s)", filename[*sym & 0x7fff]);
3127 0 : printf ("%*s", MAX (0, 33 - (int) n), " ");
3128 : break;
3129 : }
3130 : }
3131 0 : putchar_unlocked ('\n');
3132 : }
3133 :
3134 :
3135 : static void
3136 0 : print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
3137 : uint_fast32_t maxlength, Elf32_Word nbucket,
3138 : uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
3139 : {
3140 0 : uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
3141 :
3142 0 : for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
3143 0 : ++counts[lengths[cnt]];
3144 :
3145 0 : GElf_Shdr glink_mem;
3146 0 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf,
3147 0 : shdr->sh_link),
3148 : &glink_mem);
3149 0 : if (glink == NULL)
3150 : {
3151 0 : error (0, 0, gettext ("invalid sh_link value in section %zu"),
3152 : elf_ndxscn (scn));
3153 0 : return;
3154 : }
3155 :
3156 0 : printf (ngettext ("\
3157 : \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",
3158 : "\
3159 : \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",
3160 : nbucket),
3161 0 : (unsigned int) elf_ndxscn (scn),
3162 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3163 : (int) nbucket,
3164 0 : gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
3165 : shdr->sh_addr,
3166 : shdr->sh_offset,
3167 0 : (unsigned int) shdr->sh_link,
3168 0 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
3169 :
3170 0 : if (extrastr != NULL)
3171 0 : fputs (extrastr, stdout);
3172 :
3173 0 : if (likely (nbucket > 0))
3174 : {
3175 0 : uint64_t success = 0;
3176 :
3177 : /* xgettext:no-c-format */
3178 0 : fputs_unlocked (gettext ("\
3179 : Length Number % of total Coverage\n"), stdout);
3180 0 : printf (gettext (" 0 %6" PRIu32 " %5.1f%%\n"),
3181 0 : counts[0], (counts[0] * 100.0) / nbucket);
3182 :
3183 0 : uint64_t nzero_counts = 0;
3184 0 : for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
3185 : {
3186 0 : nzero_counts += counts[cnt] * cnt;
3187 0 : printf (gettext ("\
3188 : %7d %6" PRIu32 " %5.1f%% %5.1f%%\n"),
3189 0 : (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
3190 0 : (nzero_counts * 100.0) / nsyms);
3191 : }
3192 :
3193 : Elf32_Word acc = 0;
3194 0 : for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
3195 : {
3196 0 : acc += cnt;
3197 0 : success += counts[cnt] * acc;
3198 : }
3199 :
3200 0 : printf (gettext ("\
3201 : Average number of tests: successful lookup: %f\n\
3202 : unsuccessful lookup: %f\n"),
3203 0 : (double) success / (double) nzero_counts,
3204 0 : (double) nzero_counts / (double) nbucket);
3205 : }
3206 :
3207 0 : free (counts);
3208 : }
3209 :
3210 :
3211 : /* This function handles the traditional System V-style hash table format. */
3212 : static void
3213 0 : handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
3214 : {
3215 0 : Elf_Data *data = elf_getdata (scn, NULL);
3216 0 : if (unlikely (data == NULL))
3217 : {
3218 0 : error (0, 0, gettext ("cannot get data for section %d: %s"),
3219 0 : (int) elf_ndxscn (scn), elf_errmsg (-1));
3220 0 : return;
3221 : }
3222 :
3223 0 : if (unlikely (data->d_size < 2 * sizeof (Elf32_Word)))
3224 : {
3225 0 : invalid_data:
3226 0 : error (0, 0, gettext ("invalid data in sysv.hash section %d"),
3227 0 : (int) elf_ndxscn (scn));
3228 0 : return;
3229 : }
3230 :
3231 0 : Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
3232 0 : Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
3233 :
3234 0 : uint64_t used_buf = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
3235 0 : if (used_buf > data->d_size)
3236 : goto invalid_data;
3237 :
3238 0 : Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
3239 0 : Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
3240 :
3241 0 : uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
3242 :
3243 0 : uint_fast32_t maxlength = 0;
3244 0 : uint_fast32_t nsyms = 0;
3245 0 : for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
3246 : {
3247 0 : Elf32_Word inner = bucket[cnt];
3248 0 : Elf32_Word chain_len = 0;
3249 0 : while (inner > 0 && inner < nchain)
3250 : {
3251 0 : ++nsyms;
3252 0 : ++chain_len;
3253 0 : if (chain_len > nchain)
3254 : {
3255 0 : error (0, 0, gettext ("invalid chain in sysv.hash section %d"),
3256 0 : (int) elf_ndxscn (scn));
3257 0 : free (lengths);
3258 0 : return;
3259 : }
3260 0 : if (maxlength < ++lengths[cnt])
3261 0 : ++maxlength;
3262 :
3263 0 : inner = chain[inner];
3264 : }
3265 : }
3266 :
3267 0 : print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
3268 : lengths, NULL);
3269 :
3270 0 : free (lengths);
3271 : }
3272 :
3273 :
3274 : /* This function handles the incorrect, System V-style hash table
3275 : format some 64-bit architectures use. */
3276 : static void
3277 0 : handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
3278 : {
3279 0 : Elf_Data *data = elf_getdata (scn, NULL);
3280 0 : if (unlikely (data == NULL))
3281 : {
3282 0 : error (0, 0, gettext ("cannot get data for section %d: %s"),
3283 0 : (int) elf_ndxscn (scn), elf_errmsg (-1));
3284 0 : return;
3285 : }
3286 :
3287 0 : if (unlikely (data->d_size < 2 * sizeof (Elf64_Xword)))
3288 : {
3289 0 : invalid_data:
3290 0 : error (0, 0, gettext ("invalid data in sysv.hash64 section %d"),
3291 0 : (int) elf_ndxscn (scn));
3292 0 : return;
3293 : }
3294 :
3295 0 : Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
3296 0 : Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
3297 :
3298 0 : uint64_t maxwords = data->d_size / sizeof (Elf64_Xword);
3299 0 : if (maxwords < 2
3300 0 : || maxwords - 2 < nbucket
3301 0 : || maxwords - 2 - nbucket < nchain)
3302 : goto invalid_data;
3303 :
3304 0 : Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
3305 0 : Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
3306 :
3307 0 : uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
3308 :
3309 0 : uint_fast32_t maxlength = 0;
3310 0 : uint_fast32_t nsyms = 0;
3311 0 : for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
3312 : {
3313 0 : Elf64_Xword inner = bucket[cnt];
3314 0 : Elf64_Xword chain_len = 0;
3315 0 : while (inner > 0 && inner < nchain)
3316 : {
3317 0 : ++nsyms;
3318 0 : ++chain_len;
3319 0 : if (chain_len > nchain)
3320 : {
3321 0 : error (0, 0, gettext ("invalid chain in sysv.hash64 section %d"),
3322 0 : (int) elf_ndxscn (scn));
3323 0 : free (lengths);
3324 0 : return;
3325 : }
3326 0 : if (maxlength < ++lengths[cnt])
3327 0 : ++maxlength;
3328 :
3329 0 : inner = chain[inner];
3330 : }
3331 : }
3332 :
3333 0 : print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
3334 : lengths, NULL);
3335 :
3336 0 : free (lengths);
3337 : }
3338 :
3339 :
3340 : /* This function handles the GNU-style hash table format. */
3341 : static void
3342 10 : handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
3343 : {
3344 10 : uint32_t *lengths = NULL;
3345 10 : Elf_Data *data = elf_getdata (scn, NULL);
3346 10 : if (unlikely (data == NULL))
3347 : {
3348 0 : error (0, 0, gettext ("cannot get data for section %d: %s"),
3349 0 : (int) elf_ndxscn (scn), elf_errmsg (-1));
3350 0 : return;
3351 : }
3352 :
3353 10 : if (unlikely (data->d_size < 4 * sizeof (Elf32_Word)))
3354 : {
3355 0 : invalid_data:
3356 0 : free (lengths);
3357 0 : error (0, 0, gettext ("invalid data in gnu.hash section %d"),
3358 0 : (int) elf_ndxscn (scn));
3359 0 : return;
3360 : }
3361 :
3362 10 : Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
3363 10 : Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
3364 :
3365 : /* Next comes the size of the bitmap. It's measured in words for
3366 : the architecture. It's 32 bits for 32 bit archs, and 64 bits for
3367 : 64 bit archs. There is always a bloom filter present, so zero is
3368 : an invalid value. */
3369 10 : Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
3370 10 : if (gelf_getclass (ebl->elf) == ELFCLASS64)
3371 10 : bitmask_words *= 2;
3372 :
3373 10 : if (bitmask_words == 0)
3374 : goto invalid_data;
3375 :
3376 10 : Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
3377 :
3378 : /* Is there still room for the sym chain?
3379 : Use uint64_t calculation to prevent 32bit overlow. */
3380 10 : uint64_t used_buf = (4ULL + bitmask_words + nbucket) * sizeof (Elf32_Word);
3381 10 : uint32_t max_nsyms = (data->d_size - used_buf) / sizeof (Elf32_Word);
3382 10 : if (used_buf > data->d_size)
3383 : goto invalid_data;
3384 :
3385 10 : lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
3386 :
3387 10 : Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
3388 10 : Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
3389 20 : Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
3390 10 : + nbucket];
3391 :
3392 : /* Compute distribution of chain lengths. */
3393 10 : uint_fast32_t maxlength = 0;
3394 10 : uint_fast32_t nsyms = 0;
3395 326 : for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
3396 316 : if (bucket[cnt] != 0)
3397 : {
3398 220 : Elf32_Word inner = bucket[cnt] - symbias;
3399 420 : do
3400 : {
3401 420 : ++nsyms;
3402 420 : if (maxlength < ++lengths[cnt])
3403 37 : ++maxlength;
3404 420 : if (inner >= max_nsyms)
3405 : goto invalid_data;
3406 : }
3407 420 : while ((chain[inner++] & 1) == 0);
3408 : }
3409 :
3410 : /* Count bits in bitmask. */
3411 : uint_fast32_t nbits = 0;
3412 122 : for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
3413 : {
3414 112 : uint_fast32_t word = bitmask[cnt];
3415 :
3416 112 : word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
3417 112 : word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
3418 112 : word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
3419 112 : word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
3420 112 : nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
3421 : }
3422 :
3423 10 : char *str;
3424 10 : if (unlikely (asprintf (&str, gettext ("\
3425 : Symbol Bias: %u\n\
3426 : Bitmask Size: %zu bytes %" PRIuFAST32 "%% bits set 2nd hash shift: %u\n"),
3427 : (unsigned int) symbias,
3428 : bitmask_words * sizeof (Elf32_Word),
3429 : ((nbits * 100 + 50)
3430 : / (uint_fast32_t) (bitmask_words
3431 : * sizeof (Elf32_Word) * 8)),
3432 : (unsigned int) shift) == -1))
3433 0 : error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
3434 :
3435 10 : print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
3436 : lengths, str);
3437 :
3438 10 : free (str);
3439 10 : free (lengths);
3440 : }
3441 :
3442 :
3443 : /* Find the symbol table(s). For this we have to search through the
3444 : section table. */
3445 : static void
3446 42 : handle_hash (Ebl *ebl)
3447 : {
3448 : /* Get the section header string table index. */
3449 42 : size_t shstrndx;
3450 42 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
3451 0 : error (EXIT_FAILURE, 0,
3452 0 : gettext ("cannot get section header string table index"));
3453 :
3454 : Elf_Scn *scn = NULL;
3455 1073 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3456 : {
3457 : /* Handle the section if it is a symbol table. */
3458 1031 : GElf_Shdr shdr_mem;
3459 1031 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3460 :
3461 1031 : if (likely (shdr != NULL))
3462 : {
3463 1031 : if ((shdr->sh_type == SHT_HASH || shdr->sh_type == SHT_GNU_HASH)
3464 10 : && (shdr->sh_flags & SHF_COMPRESSED) != 0)
3465 : {
3466 0 : if (elf_compress (scn, 0, 0) < 0)
3467 0 : printf ("WARNING: %s [%zd]\n",
3468 : gettext ("Couldn't uncompress section"),
3469 : elf_ndxscn (scn));
3470 0 : shdr = gelf_getshdr (scn, &shdr_mem);
3471 0 : if (unlikely (shdr == NULL))
3472 0 : error (EXIT_FAILURE, 0,
3473 0 : gettext ("cannot get section [%zd] header: %s"),
3474 : elf_ndxscn (scn), elf_errmsg (-1));
3475 : }
3476 :
3477 1031 : if (shdr->sh_type == SHT_HASH)
3478 : {
3479 0 : if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
3480 0 : handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
3481 : else
3482 0 : handle_sysv_hash (ebl, scn, shdr, shstrndx);
3483 : }
3484 1031 : else if (shdr->sh_type == SHT_GNU_HASH)
3485 10 : handle_gnu_hash (ebl, scn, shdr, shstrndx);
3486 : }
3487 : }
3488 42 : }
3489 :
3490 :
3491 : static void
3492 0 : print_liblist (Ebl *ebl)
3493 : {
3494 : /* Find the library list sections. For this we have to search
3495 : through the section table. */
3496 0 : Elf_Scn *scn = NULL;
3497 :
3498 : /* Get the section header string table index. */
3499 0 : size_t shstrndx;
3500 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
3501 0 : error (EXIT_FAILURE, 0,
3502 0 : gettext ("cannot get section header string table index"));
3503 :
3504 0 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3505 : {
3506 0 : GElf_Shdr shdr_mem;
3507 0 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3508 :
3509 0 : if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
3510 : {
3511 0 : size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_LIB, 1, EV_CURRENT);
3512 0 : int nentries = shdr->sh_size / sh_entsize;
3513 0 : printf (ngettext ("\
3514 : \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
3515 : "\
3516 : \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
3517 : nentries),
3518 : elf_ndxscn (scn),
3519 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3520 : shdr->sh_offset,
3521 : nentries);
3522 :
3523 0 : Elf_Data *data = elf_getdata (scn, NULL);
3524 0 : if (data == NULL)
3525 0 : return;
3526 :
3527 0 : puts (gettext ("\
3528 : Library Time Stamp Checksum Version Flags"));
3529 :
3530 0 : for (int cnt = 0; cnt < nentries; ++cnt)
3531 : {
3532 0 : GElf_Lib lib_mem;
3533 0 : GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
3534 0 : if (unlikely (lib == NULL))
3535 0 : continue;
3536 :
3537 0 : time_t t = (time_t) lib->l_time_stamp;
3538 0 : struct tm *tm = gmtime (&t);
3539 0 : if (unlikely (tm == NULL))
3540 0 : continue;
3541 :
3542 0 : printf (" [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
3543 0 : cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
3544 0 : tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
3545 : tm->tm_hour, tm->tm_min, tm->tm_sec,
3546 0 : (unsigned int) lib->l_checksum,
3547 0 : (unsigned int) lib->l_version,
3548 0 : (unsigned int) lib->l_flags);
3549 : }
3550 : }
3551 : }
3552 : }
3553 :
3554 : static void
3555 0 : print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
3556 : {
3557 : /* Find the object attributes sections. For this we have to search
3558 : through the section table. */
3559 0 : Elf_Scn *scn = NULL;
3560 :
3561 : /* Get the section header string table index. */
3562 0 : size_t shstrndx;
3563 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
3564 0 : error (EXIT_FAILURE, 0,
3565 0 : gettext ("cannot get section header string table index"));
3566 :
3567 0 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3568 : {
3569 0 : GElf_Shdr shdr_mem;
3570 0 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3571 :
3572 0 : if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
3573 0 : && (shdr->sh_type != SHT_ARM_ATTRIBUTES
3574 0 : || ehdr->e_machine != EM_ARM)
3575 0 : && (shdr->sh_type != SHT_CSKY_ATTRIBUTES
3576 0 : || ehdr->e_machine != EM_CSKY)))
3577 0 : continue;
3578 :
3579 0 : printf (gettext ("\
3580 : \nObject attributes section [%2zu] '%s' of %" PRIu64
3581 : " bytes at offset %#0" PRIx64 ":\n"),
3582 : elf_ndxscn (scn),
3583 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3584 : shdr->sh_size, shdr->sh_offset);
3585 :
3586 0 : Elf_Data *data = elf_rawdata (scn, NULL);
3587 0 : if (unlikely (data == NULL || data->d_size == 0))
3588 0 : return;
3589 :
3590 0 : const unsigned char *p = data->d_buf;
3591 :
3592 : /* There is only one 'version', A. */
3593 0 : if (unlikely (*p++ != 'A'))
3594 0 : return;
3595 :
3596 0 : fputs_unlocked (gettext (" Owner Size\n"), stdout);
3597 :
3598 0 : inline size_t left (void)
3599 : {
3600 0 : return (const unsigned char *) data->d_buf + data->d_size - p;
3601 : }
3602 :
3603 : /* Loop over the sections. */
3604 0 : while (left () >= 4)
3605 : {
3606 : /* Section length. */
3607 0 : uint32_t len;
3608 0 : memcpy (&len, p, sizeof len);
3609 :
3610 0 : if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3611 0 : CONVERT (len);
3612 :
3613 0 : if (unlikely (len > left ()))
3614 : break;
3615 :
3616 : /* Section vendor name. */
3617 0 : const unsigned char *name = p + sizeof len;
3618 0 : p += len;
3619 :
3620 0 : unsigned const char *q = memchr (name, '\0', len);
3621 0 : if (unlikely (q == NULL))
3622 : break;
3623 0 : ++q;
3624 :
3625 0 : printf (gettext (" %-13s %4" PRIu32 "\n"), name, len);
3626 :
3627 0 : bool gnu_vendor = (q - name == sizeof "gnu"
3628 0 : && !memcmp (name, "gnu", sizeof "gnu"));
3629 :
3630 : /* Loop over subsections. */
3631 0 : if (shdr->sh_type != SHT_GNU_ATTRIBUTES
3632 0 : || gnu_vendor)
3633 0 : while (q < p)
3634 : {
3635 0 : const unsigned char *const sub = q;
3636 :
3637 0 : unsigned int subsection_tag;
3638 0 : get_uleb128 (subsection_tag, q, p);
3639 0 : if (unlikely (q >= p))
3640 : break;
3641 :
3642 0 : uint32_t subsection_len;
3643 0 : if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
3644 : break;
3645 :
3646 0 : memcpy (&subsection_len, q, sizeof subsection_len);
3647 :
3648 0 : if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3649 0 : CONVERT (subsection_len);
3650 :
3651 : /* Don't overflow, ptrdiff_t might be 32bits, but signed. */
3652 0 : if (unlikely (subsection_len == 0
3653 : || subsection_len >= (uint32_t) PTRDIFF_MAX
3654 : || p - sub < (ptrdiff_t) subsection_len))
3655 : break;
3656 :
3657 0 : const unsigned char *r = q + sizeof subsection_len;
3658 0 : q = sub + subsection_len;
3659 :
3660 0 : switch (subsection_tag)
3661 : {
3662 0 : default:
3663 : /* Unknown subsection, print and skip. */
3664 0 : printf (gettext (" %-4u %12" PRIu32 "\n"),
3665 : subsection_tag, subsection_len);
3666 : break;
3667 :
3668 0 : case 1: /* Tag_File */
3669 0 : printf (gettext (" File: %11" PRIu32 "\n"),
3670 : subsection_len);
3671 :
3672 0 : while (r < q)
3673 0 : {
3674 0 : unsigned int tag;
3675 0 : get_uleb128 (tag, r, q);
3676 0 : if (unlikely (r >= q))
3677 : break;
3678 :
3679 : /* GNU style tags have either a uleb128 value,
3680 : when lowest bit is not set, or a string
3681 : when the lowest bit is set.
3682 : "compatibility" (32) is special. It has
3683 : both a string and a uleb128 value. For
3684 : non-gnu we assume 6 till 31 only take ints.
3685 : XXX see arm backend, do we need a separate
3686 : hook? */
3687 0 : uint64_t value = 0;
3688 0 : const char *string = NULL;
3689 0 : if (tag == 32 || (tag & 1) == 0
3690 0 : || (! gnu_vendor && (tag > 5 && tag < 32)))
3691 : {
3692 0 : get_uleb128 (value, r, q);
3693 0 : if (r > q)
3694 : break;
3695 : }
3696 0 : if (tag == 32
3697 0 : || ((tag & 1) != 0
3698 0 : && (gnu_vendor
3699 0 : || (! gnu_vendor && tag > 32)))
3700 0 : || (! gnu_vendor && tag > 3 && tag < 6))
3701 : {
3702 0 : string = (const char *) r;
3703 0 : r = memchr (r, '\0', q - r);
3704 0 : if (r == NULL)
3705 : break;
3706 0 : ++r;
3707 : }
3708 :
3709 0 : const char *tag_name = NULL;
3710 0 : const char *value_name = NULL;
3711 0 : ebl_check_object_attribute (ebl, (const char *) name,
3712 : tag, value,
3713 : &tag_name, &value_name);
3714 :
3715 0 : if (tag_name != NULL)
3716 : {
3717 0 : if (tag == 32)
3718 0 : printf (gettext (" %s: %" PRId64 ", %s\n"),
3719 : tag_name, value, string);
3720 0 : else if (string == NULL && value_name == NULL)
3721 0 : printf (gettext (" %s: %" PRId64 "\n"),
3722 : tag_name, value);
3723 : else
3724 0 : printf (gettext (" %s: %s\n"),
3725 : tag_name, string ?: value_name);
3726 : }
3727 : else
3728 : {
3729 : /* For "gnu" vendor 32 "compatibility" has
3730 : already been handled above. */
3731 0 : assert (tag != 32
3732 : || strcmp ((const char *) name, "gnu"));
3733 0 : if (string == NULL)
3734 0 : printf (gettext (" %u: %" PRId64 "\n"),
3735 : tag, value);
3736 : else
3737 0 : printf (gettext (" %u: %s\n"),
3738 : tag, string);
3739 : }
3740 : }
3741 : }
3742 : }
3743 : }
3744 : }
3745 : }
3746 :
3747 :
3748 : void
3749 786859 : print_dwarf_addr (Dwfl_Module *dwflmod,
3750 : int address_size, Dwarf_Addr address, Dwarf_Addr raw)
3751 : {
3752 : /* See if there is a name we can give for this address. */
3753 786859 : GElf_Sym sym;
3754 786859 : GElf_Off off = 0;
3755 786831 : const char *name = (print_address_names && ! print_unresolved_addresses)
3756 786749 : ? dwfl_module_addrinfo (dwflmod, address, &off, &sym, NULL, NULL, NULL)
3757 1573608 : : NULL;
3758 :
3759 786859 : const char *scn;
3760 786859 : if (print_unresolved_addresses)
3761 : {
3762 82 : address = raw;
3763 82 : scn = NULL;
3764 : }
3765 : else
3766 : {
3767 : /* Relativize the address. */
3768 786777 : int n = dwfl_module_relocations (dwflmod);
3769 786777 : int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
3770 :
3771 : /* In an ET_REL file there is a section name to refer to. */
3772 785777 : scn = (i < 0 ? NULL
3773 785777 : : dwfl_module_relocation_info (dwflmod, i, NULL));
3774 : }
3775 :
3776 786859 : if ((name != NULL
3777 775450 : ? (off != 0
3778 : ? (scn != NULL
3779 : ? (address_size == 0
3780 249813 : ? printf ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">",
3781 : scn, address, name, off)
3782 1492578 : : printf ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">",
3783 497526 : scn, 2 + address_size * 2, address,
3784 : name, off))
3785 : : (address_size == 0
3786 169 : ? printf ("%#" PRIx64 " <%s+%#" PRIx64 ">",
3787 : address, name, off)
3788 1410 : : printf ("%#0*" PRIx64 " <%s+%#" PRIx64 ">",
3789 470 : 2 + address_size * 2, address,
3790 : name, off)))
3791 : : (scn != NULL
3792 : ? (address_size == 0
3793 9189 : ? printf ("%s+%#" PRIx64 " <%s>", scn, address, name)
3794 54030 : : printf ("%s+%#0*" PRIx64 " <%s>",
3795 18010 : scn, 2 + address_size * 2, address, name))
3796 : : (address_size == 0
3797 79 : ? printf ("%#" PRIx64 " <%s>", address, name)
3798 582 : : printf ("%#0*" PRIx64 " <%s>",
3799 194 : 2 + address_size * 2, address, name))))
3800 : : (scn != NULL
3801 : ? (address_size == 0
3802 5877 : ? printf ("%s+%#" PRIx64, scn, address)
3803 5362 : : printf ("%s+%#0*" PRIx64, scn, 2 + address_size * 2, address))
3804 : : (address_size == 0
3805 34 : ? printf ("%#" PRIx64, address)
3806 1573582 : : printf ("%#0*" PRIx64, 2 + address_size * 2, address)))) < 0)
3807 0 : error (EXIT_FAILURE, 0, _("sprintf failure"));
3808 786859 : }
3809 :
3810 :
3811 : static const char *
3812 775008 : dwarf_tag_string (unsigned int tag)
3813 : {
3814 775008 : switch (tag)
3815 : {
3816 : #define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
3817 775008 : DWARF_ALL_KNOWN_DW_TAG
3818 : #undef DWARF_ONE_KNOWN_DW_TAG
3819 0 : default:
3820 0 : return NULL;
3821 : }
3822 : }
3823 :
3824 :
3825 : static const char *
3826 3140967 : dwarf_attr_string (unsigned int attrnum)
3827 : {
3828 3140967 : switch (attrnum)
3829 : {
3830 : #define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
3831 3140966 : DWARF_ALL_KNOWN_DW_AT
3832 : #undef DWARF_ONE_KNOWN_DW_AT
3833 0 : default:
3834 0 : return NULL;
3835 : }
3836 : }
3837 :
3838 :
3839 : static const char *
3840 3140973 : dwarf_form_string (unsigned int form)
3841 : {
3842 3140973 : switch (form)
3843 : {
3844 : #define DWARF_ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
3845 3140971 : DWARF_ALL_KNOWN_DW_FORM
3846 : #undef DWARF_ONE_KNOWN_DW_FORM
3847 0 : default:
3848 0 : return NULL;
3849 : }
3850 : }
3851 :
3852 :
3853 : static const char *
3854 1162 : dwarf_lang_string (unsigned int lang)
3855 : {
3856 1162 : switch (lang)
3857 : {
3858 : #define DWARF_ONE_KNOWN_DW_LANG(NAME, CODE) case CODE: return #NAME;
3859 1162 : DWARF_ALL_KNOWN_DW_LANG
3860 : #undef DWARF_ONE_KNOWN_DW_LANG
3861 0 : default:
3862 0 : return NULL;
3863 : }
3864 : }
3865 :
3866 :
3867 : static const char *
3868 : dwarf_inline_string (unsigned int code)
3869 : {
3870 2934 : static const char *const known[] =
3871 : {
3872 : #define DWARF_ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME,
3873 : DWARF_ALL_KNOWN_DW_INL
3874 : #undef DWARF_ONE_KNOWN_DW_INL
3875 : };
3876 :
3877 2934 : if (likely (code < sizeof (known) / sizeof (known[0])))
3878 2934 : return known[code];
3879 :
3880 : return NULL;
3881 : }
3882 :
3883 :
3884 : static const char *
3885 : dwarf_encoding_string (unsigned int code)
3886 : {
3887 16569 : static const char *const known[] =
3888 : {
3889 : #define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
3890 : DWARF_ALL_KNOWN_DW_ATE
3891 : #undef DWARF_ONE_KNOWN_DW_ATE
3892 : };
3893 :
3894 16569 : if (likely (code < sizeof (known) / sizeof (known[0])))
3895 16569 : return known[code];
3896 :
3897 : return NULL;
3898 : }
3899 :
3900 :
3901 : static const char *
3902 : dwarf_access_string (unsigned int code)
3903 : {
3904 0 : static const char *const known[] =
3905 : {
3906 : #define DWARF_ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME,
3907 : DWARF_ALL_KNOWN_DW_ACCESS
3908 : #undef DWARF_ONE_KNOWN_DW_ACCESS
3909 : };
3910 :
3911 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3912 0 : return known[code];
3913 :
3914 : return NULL;
3915 : }
3916 :
3917 :
3918 : static const char *
3919 : dwarf_defaulted_string (unsigned int code)
3920 : {
3921 0 : static const char *const known[] =
3922 : {
3923 : #define DWARF_ONE_KNOWN_DW_DEFAULTED(NAME, CODE) [CODE] = #NAME,
3924 : DWARF_ALL_KNOWN_DW_DEFAULTED
3925 : #undef DWARF_ONE_KNOWN_DW_DEFAULTED
3926 : };
3927 :
3928 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3929 0 : return known[code];
3930 :
3931 : return NULL;
3932 : }
3933 :
3934 :
3935 : static const char *
3936 : dwarf_visibility_string (unsigned int code)
3937 : {
3938 0 : static const char *const known[] =
3939 : {
3940 : #define DWARF_ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
3941 : DWARF_ALL_KNOWN_DW_VIS
3942 : #undef DWARF_ONE_KNOWN_DW_VIS
3943 : };
3944 :
3945 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3946 0 : return known[code];
3947 :
3948 : return NULL;
3949 : }
3950 :
3951 :
3952 : static const char *
3953 : dwarf_virtuality_string (unsigned int code)
3954 : {
3955 0 : static const char *const known[] =
3956 : {
3957 : #define DWARF_ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
3958 : DWARF_ALL_KNOWN_DW_VIRTUALITY
3959 : #undef DWARF_ONE_KNOWN_DW_VIRTUALITY
3960 : };
3961 :
3962 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3963 0 : return known[code];
3964 :
3965 : return NULL;
3966 : }
3967 :
3968 :
3969 : static const char *
3970 : dwarf_identifier_case_string (unsigned int code)
3971 : {
3972 0 : static const char *const known[] =
3973 : {
3974 : #define DWARF_ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
3975 : DWARF_ALL_KNOWN_DW_ID
3976 : #undef DWARF_ONE_KNOWN_DW_ID
3977 : };
3978 :
3979 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3980 0 : return known[code];
3981 :
3982 : return NULL;
3983 : }
3984 :
3985 :
3986 : static const char *
3987 : dwarf_calling_convention_string (unsigned int code)
3988 : {
3989 0 : static const char *const known[] =
3990 : {
3991 : #define DWARF_ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
3992 : DWARF_ALL_KNOWN_DW_CC
3993 : #undef DWARF_ONE_KNOWN_DW_CC
3994 : };
3995 :
3996 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3997 0 : return known[code];
3998 :
3999 : return NULL;
4000 : }
4001 :
4002 :
4003 : static const char *
4004 : dwarf_ordering_string (unsigned int code)
4005 : {
4006 0 : static const char *const known[] =
4007 : {
4008 : #define DWARF_ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
4009 : DWARF_ALL_KNOWN_DW_ORD
4010 : #undef DWARF_ONE_KNOWN_DW_ORD
4011 : };
4012 :
4013 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
4014 0 : return known[code];
4015 :
4016 : return NULL;
4017 : }
4018 :
4019 :
4020 : static const char *
4021 : dwarf_discr_list_string (unsigned int code)
4022 : {
4023 8 : static const char *const known[] =
4024 : {
4025 : #define DWARF_ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
4026 : DWARF_ALL_KNOWN_DW_DSC
4027 : #undef DWARF_ONE_KNOWN_DW_DSC
4028 : };
4029 :
4030 8 : if (likely (code < sizeof (known) / sizeof (known[0])))
4031 8 : return known[code];
4032 :
4033 : return NULL;
4034 : }
4035 :
4036 :
4037 : static const char *
4038 : dwarf_locexpr_opcode_string (unsigned int code)
4039 : {
4040 426735 : static const char *const known[] =
4041 : {
4042 : /* Normally we can't affort building huge table of 64K entries,
4043 : most of them zero, just because there are a couple defined
4044 : values at the far end. In case of opcodes, it's OK. */
4045 : #define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
4046 : DWARF_ALL_KNOWN_DW_OP
4047 : #undef DWARF_ONE_KNOWN_DW_OP
4048 : };
4049 :
4050 426735 : if (likely (code < sizeof (known) / sizeof (known[0])))
4051 426735 : return known[code];
4052 :
4053 : return NULL;
4054 : }
4055 :
4056 :
4057 : static const char *
4058 : dwarf_unit_string (unsigned int type)
4059 : {
4060 8 : switch (type)
4061 : {
4062 : #define DWARF_ONE_KNOWN_DW_UT(NAME, CODE) case CODE: return #NAME;
4063 7 : DWARF_ALL_KNOWN_DW_UT
4064 : #undef DWARF_ONE_KNOWN_DW_UT
4065 0 : default:
4066 0 : return NULL;
4067 : }
4068 : }
4069 :
4070 :
4071 : static const char *
4072 14 : dwarf_range_list_encoding_string (unsigned int kind)
4073 : {
4074 14 : switch (kind)
4075 : {
4076 : #define DWARF_ONE_KNOWN_DW_RLE(NAME, CODE) case CODE: return #NAME;
4077 12 : DWARF_ALL_KNOWN_DW_RLE
4078 : #undef DWARF_ONE_KNOWN_DW_RLE
4079 0 : default:
4080 0 : return NULL;
4081 : }
4082 : }
4083 :
4084 :
4085 : static const char *
4086 89 : dwarf_loc_list_encoding_string (unsigned int kind)
4087 : {
4088 89 : switch (kind)
4089 : {
4090 : #define DWARF_ONE_KNOWN_DW_LLE(NAME, CODE) case CODE: return #NAME;
4091 84 : DWARF_ALL_KNOWN_DW_LLE
4092 : #undef DWARF_ONE_KNOWN_DW_LLE
4093 0 : default:
4094 0 : return NULL;
4095 : }
4096 : }
4097 :
4098 :
4099 : static const char *
4100 : dwarf_line_content_description_string (unsigned int kind)
4101 : {
4102 6 : switch (kind)
4103 : {
4104 : #define DWARF_ONE_KNOWN_DW_LNCT(NAME, CODE) case CODE: return #NAME;
4105 6 : DWARF_ALL_KNOWN_DW_LNCT
4106 : #undef DWARF_ONE_KNOWN_DW_LNCT
4107 0 : default:
4108 0 : return NULL;
4109 : }
4110 : }
4111 :
4112 :
4113 : /* Used by all dwarf_foo_name functions. */
4114 : static const char *
4115 7077738 : string_or_unknown (const char *known, unsigned int code,
4116 : unsigned int lo_user, unsigned int hi_user,
4117 : bool print_unknown_num)
4118 : {
4119 7077738 : static char unknown_buf[20];
4120 :
4121 7077738 : if (likely (known != NULL))
4122 : return known;
4123 :
4124 0 : if (lo_user != 0 && code >= lo_user && code <= hi_user)
4125 : {
4126 0 : snprintf (unknown_buf, sizeof unknown_buf, "lo_user+%#x",
4127 : code - lo_user);
4128 0 : return unknown_buf;
4129 : }
4130 :
4131 0 : if (print_unknown_num)
4132 : {
4133 0 : snprintf (unknown_buf, sizeof unknown_buf, "??? (%#x)", code);
4134 0 : return unknown_buf;
4135 : }
4136 :
4137 : return "???";
4138 : }
4139 :
4140 :
4141 : static const char *
4142 775008 : dwarf_tag_name (unsigned int tag)
4143 : {
4144 775008 : const char *ret = dwarf_tag_string (tag);
4145 775008 : return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true);
4146 : }
4147 :
4148 : static const char *
4149 3140967 : dwarf_attr_name (unsigned int attr)
4150 : {
4151 3140967 : const char *ret = dwarf_attr_string (attr);
4152 3140967 : return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true);
4153 : }
4154 :
4155 :
4156 : static const char *
4157 3140973 : dwarf_form_name (unsigned int form)
4158 : {
4159 3140973 : const char *ret = dwarf_form_string (form);
4160 3140973 : return string_or_unknown (ret, form, 0, 0, true);
4161 : }
4162 :
4163 :
4164 : static const char *
4165 1162 : dwarf_lang_name (unsigned int lang)
4166 : {
4167 1162 : const char *ret = dwarf_lang_string (lang);
4168 1162 : return string_or_unknown (ret, lang, DW_LANG_lo_user, DW_LANG_hi_user, false);
4169 : }
4170 :
4171 :
4172 : static const char *
4173 : dwarf_inline_name (unsigned int code)
4174 : {
4175 5868 : const char *ret = dwarf_inline_string (code);
4176 2934 : return string_or_unknown (ret, code, 0, 0, false);
4177 : }
4178 :
4179 :
4180 : static const char *
4181 : dwarf_encoding_name (unsigned int code)
4182 : {
4183 33138 : const char *ret = dwarf_encoding_string (code);
4184 16569 : return string_or_unknown (ret, code, DW_ATE_lo_user, DW_ATE_hi_user, false);
4185 : }
4186 :
4187 :
4188 : static const char *
4189 : dwarf_access_name (unsigned int code)
4190 : {
4191 0 : const char *ret = dwarf_access_string (code);
4192 0 : return string_or_unknown (ret, code, 0, 0, false);
4193 : }
4194 :
4195 :
4196 : static const char *
4197 : dwarf_defaulted_name (unsigned int code)
4198 : {
4199 0 : const char *ret = dwarf_defaulted_string (code);
4200 0 : return string_or_unknown (ret, code, 0, 0, false);
4201 : }
4202 :
4203 :
4204 : static const char *
4205 : dwarf_visibility_name (unsigned int code)
4206 : {
4207 0 : const char *ret = dwarf_visibility_string (code);
4208 0 : return string_or_unknown (ret, code, 0, 0, false);
4209 : }
4210 :
4211 :
4212 : static const char *
4213 : dwarf_virtuality_name (unsigned int code)
4214 : {
4215 0 : const char *ret = dwarf_virtuality_string (code);
4216 0 : return string_or_unknown (ret, code, 0, 0, false);
4217 : }
4218 :
4219 :
4220 : static const char *
4221 : dwarf_identifier_case_name (unsigned int code)
4222 : {
4223 0 : const char *ret = dwarf_identifier_case_string (code);
4224 0 : return string_or_unknown (ret, code, 0, 0, false);
4225 : }
4226 :
4227 :
4228 : static const char *
4229 : dwarf_calling_convention_name (unsigned int code)
4230 : {
4231 0 : const char *ret = dwarf_calling_convention_string (code);
4232 0 : return string_or_unknown (ret, code, DW_CC_lo_user, DW_CC_hi_user, false);
4233 : }
4234 :
4235 :
4236 : static const char *
4237 : dwarf_ordering_name (unsigned int code)
4238 : {
4239 0 : const char *ret = dwarf_ordering_string (code);
4240 0 : return string_or_unknown (ret, code, 0, 0, false);
4241 : }
4242 :
4243 :
4244 : static const char *
4245 : dwarf_discr_list_name (unsigned int code)
4246 : {
4247 16 : const char *ret = dwarf_discr_list_string (code);
4248 8 : return string_or_unknown (ret, code, 0, 0, false);
4249 : }
4250 :
4251 :
4252 : static const char *
4253 8 : dwarf_unit_name (unsigned int type)
4254 : {
4255 8 : const char *ret = dwarf_unit_string (type);
4256 8 : return string_or_unknown (ret, type, DW_UT_lo_user, DW_UT_hi_user, true);
4257 : }
4258 :
4259 :
4260 : static const char *
4261 14 : dwarf_range_list_encoding_name (unsigned int kind)
4262 : {
4263 14 : const char *ret = dwarf_range_list_encoding_string (kind);
4264 14 : return string_or_unknown (ret, kind, 0, 0, false);
4265 : }
4266 :
4267 :
4268 : static const char *
4269 89 : dwarf_loc_list_encoding_name (unsigned int kind)
4270 : {
4271 89 : const char *ret = dwarf_loc_list_encoding_string (kind);
4272 89 : return string_or_unknown (ret, kind, 0, 0, false);
4273 : }
4274 :
4275 :
4276 : static const char *
4277 6 : dwarf_line_content_description_name (unsigned int kind)
4278 : {
4279 6 : const char *ret = dwarf_line_content_description_string (kind);
4280 6 : return string_or_unknown (ret, kind, DW_LNCT_lo_user, DW_LNCT_hi_user,
4281 : false);
4282 : }
4283 :
4284 :
4285 : static void
4286 161 : print_block (size_t n, const void *block)
4287 : {
4288 161 : if (n == 0)
4289 0 : puts (_("empty block"));
4290 : else
4291 : {
4292 161 : printf (_("%zu byte block:"), n);
4293 161 : const unsigned char *data = block;
4294 2062 : do
4295 2062 : printf (" %02x", *data++);
4296 2062 : while (--n > 0);
4297 161 : putchar ('\n');
4298 : }
4299 161 : }
4300 :
4301 : static void
4302 0 : print_bytes (size_t n, const unsigned char *bytes)
4303 : {
4304 0 : while (n-- > 0)
4305 : {
4306 0 : printf ("%02x", *bytes++);
4307 0 : if (n > 0)
4308 0 : printf (" ");
4309 : }
4310 0 : }
4311 :
4312 : static int
4313 68 : get_indexed_addr (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr)
4314 : {
4315 68 : if (cu == NULL)
4316 : return -1;
4317 :
4318 68 : Elf_Data *debug_addr = cu->dbg->sectiondata[IDX_debug_addr];
4319 68 : if (debug_addr == NULL)
4320 : return -1;
4321 :
4322 68 : Dwarf_Off base = __libdw_cu_addr_base (cu);
4323 68 : Dwarf_Word off = idx * cu->address_size;
4324 68 : if (base > debug_addr->d_size
4325 68 : || off > debug_addr->d_size - base
4326 68 : || cu->address_size > debug_addr->d_size - base - off)
4327 : return -1;
4328 :
4329 68 : const unsigned char *addrp = debug_addr->d_buf + base + off;
4330 68 : if (cu->address_size == 4)
4331 0 : *addr = read_4ubyte_unaligned (cu->dbg, addrp);
4332 : else
4333 68 : *addr = read_8ubyte_unaligned (cu->dbg, addrp);
4334 :
4335 : return 0;
4336 : }
4337 :
4338 : static void
4339 294635 : print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
4340 : unsigned int vers, unsigned int addrsize, unsigned int offset_size,
4341 : struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data)
4342 : {
4343 294635 : const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
4344 :
4345 294635 : if (len == 0)
4346 : {
4347 0 : printf ("%*s(empty)\n", indent, "");
4348 0 : return;
4349 : }
4350 :
4351 : #define NEED(n) if (len < (Dwarf_Word) (n)) goto invalid
4352 : #define CONSUME(n) NEED (n); else len -= (n)
4353 :
4354 : Dwarf_Word offset = 0;
4355 721370 : while (len-- > 0)
4356 : {
4357 426735 : uint_fast8_t op = *data++;
4358 :
4359 426735 : const char *op_name = dwarf_locexpr_opcode_string (op);
4360 426735 : if (unlikely (op_name == NULL))
4361 : {
4362 0 : static char buf[20];
4363 0 : if (op >= DW_OP_lo_user)
4364 0 : snprintf (buf, sizeof buf, "lo_user+%#x", op - DW_OP_lo_user);
4365 : else
4366 0 : snprintf (buf, sizeof buf, "??? (%#x)", op);
4367 : op_name = buf;
4368 : }
4369 :
4370 426735 : switch (op)
4371 : {
4372 7420 : case DW_OP_addr:;
4373 : /* Address operand. */
4374 7420 : Dwarf_Word addr;
4375 7420 : NEED (addrsize);
4376 7420 : if (addrsize == 4)
4377 24 : addr = read_4ubyte_unaligned (dbg, data);
4378 7396 : else if (addrsize == 8)
4379 7396 : addr = read_8ubyte_unaligned (dbg, data);
4380 : else
4381 0 : goto invalid;
4382 7420 : data += addrsize;
4383 7420 : CONSUME (addrsize);
4384 :
4385 7420 : printf ("%*s[%2" PRIuMAX "] %s ",
4386 : indent, "", (uintmax_t) offset, op_name);
4387 7420 : print_dwarf_addr (dwflmod, 0, addr, addr);
4388 7420 : printf ("\n");
4389 :
4390 7420 : offset += 1 + addrsize;
4391 7420 : break;
4392 :
4393 0 : case DW_OP_call_ref:
4394 : case DW_OP_GNU_variable_value:
4395 : /* Offset operand. */
4396 0 : if (ref_size != 4 && ref_size != 8)
4397 0 : goto invalid; /* Cannot be used in CFA. */
4398 0 : NEED (ref_size);
4399 0 : if (ref_size == 4)
4400 0 : addr = read_4ubyte_unaligned (dbg, data);
4401 : else
4402 0 : addr = read_8ubyte_unaligned (dbg, data);
4403 0 : data += ref_size;
4404 0 : CONSUME (ref_size);
4405 : /* addr is a DIE offset, so format it as one. */
4406 0 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
4407 : indent, "", (uintmax_t) offset,
4408 : op_name, (uintmax_t) addr);
4409 0 : offset += 1 + ref_size;
4410 0 : break;
4411 :
4412 11182 : case DW_OP_deref_size:
4413 : case DW_OP_xderef_size:
4414 : case DW_OP_pick:
4415 : case DW_OP_const1u:
4416 : // XXX value might be modified by relocation
4417 11182 : NEED (1);
4418 33546 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 "\n",
4419 : indent, "", (uintmax_t) offset,
4420 11182 : op_name, *((uint8_t *) data));
4421 11182 : ++data;
4422 11182 : --len;
4423 11182 : offset += 2;
4424 11182 : break;
4425 :
4426 971 : case DW_OP_const2u:
4427 971 : NEED (2);
4428 : // XXX value might be modified by relocation
4429 971 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu16 "\n",
4430 : indent, "", (uintmax_t) offset,
4431 971 : op_name, read_2ubyte_unaligned (dbg, data));
4432 971 : CONSUME (2);
4433 971 : data += 2;
4434 971 : offset += 3;
4435 971 : break;
4436 :
4437 651 : case DW_OP_const4u:
4438 651 : NEED (4);
4439 : // XXX value might be modified by relocation
4440 651 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu32 "\n",
4441 : indent, "", (uintmax_t) offset,
4442 651 : op_name, read_4ubyte_unaligned (dbg, data));
4443 651 : CONSUME (4);
4444 651 : data += 4;
4445 651 : offset += 5;
4446 651 : break;
4447 :
4448 43 : case DW_OP_const8u:
4449 43 : NEED (8);
4450 : // XXX value might be modified by relocation
4451 43 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
4452 : indent, "", (uintmax_t) offset,
4453 43 : op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
4454 43 : CONSUME (8);
4455 43 : data += 8;
4456 43 : offset += 9;
4457 43 : break;
4458 :
4459 2202 : case DW_OP_const1s:
4460 2202 : NEED (1);
4461 : // XXX value might be modified by relocation
4462 6606 : printf ("%*s[%2" PRIuMAX "] %s %" PRId8 "\n",
4463 : indent, "", (uintmax_t) offset,
4464 2202 : op_name, *((int8_t *) data));
4465 2202 : ++data;
4466 2202 : --len;
4467 2202 : offset += 2;
4468 2202 : break;
4469 :
4470 3 : case DW_OP_const2s:
4471 3 : NEED (2);
4472 : // XXX value might be modified by relocation
4473 3 : printf ("%*s[%2" PRIuMAX "] %s %" PRId16 "\n",
4474 : indent, "", (uintmax_t) offset,
4475 3 : op_name, read_2sbyte_unaligned (dbg, data));
4476 3 : CONSUME (2);
4477 3 : data += 2;
4478 3 : offset += 3;
4479 3 : break;
4480 :
4481 0 : case DW_OP_const4s:
4482 0 : NEED (4);
4483 : // XXX value might be modified by relocation
4484 0 : printf ("%*s[%2" PRIuMAX "] %s %" PRId32 "\n",
4485 : indent, "", (uintmax_t) offset,
4486 0 : op_name, read_4sbyte_unaligned (dbg, data));
4487 0 : CONSUME (4);
4488 0 : data += 4;
4489 0 : offset += 5;
4490 0 : break;
4491 :
4492 0 : case DW_OP_const8s:
4493 0 : NEED (8);
4494 : // XXX value might be modified by relocation
4495 0 : printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
4496 : indent, "", (uintmax_t) offset,
4497 0 : op_name, read_8sbyte_unaligned (dbg, data));
4498 0 : CONSUME (8);
4499 0 : data += 8;
4500 0 : offset += 9;
4501 0 : break;
4502 :
4503 9514 : case DW_OP_piece:
4504 : case DW_OP_regx:
4505 : case DW_OP_plus_uconst:
4506 9514 : case DW_OP_constu:;
4507 9514 : const unsigned char *start = data;
4508 9514 : uint64_t uleb;
4509 9514 : NEED (1);
4510 9514 : get_uleb128 (uleb, data, data + len);
4511 9514 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
4512 : indent, "", (uintmax_t) offset, op_name, uleb);
4513 9514 : CONSUME (data - start);
4514 9514 : offset += 1 + (data - start);
4515 9514 : break;
4516 :
4517 2 : case DW_OP_addrx:
4518 : case DW_OP_GNU_addr_index:
4519 : case DW_OP_constx:
4520 2 : case DW_OP_GNU_const_index:;
4521 2 : start = data;
4522 2 : NEED (1);
4523 2 : get_uleb128 (uleb, data, data + len);
4524 2 : printf ("%*s[%2" PRIuMAX "] %s [%" PRIu64 "] ",
4525 : indent, "", (uintmax_t) offset, op_name, uleb);
4526 2 : CONSUME (data - start);
4527 2 : offset += 1 + (data - start);
4528 2 : if (get_indexed_addr (cu, uleb, &addr) != 0)
4529 0 : printf ("???\n");
4530 : else
4531 : {
4532 2 : print_dwarf_addr (dwflmod, 0, addr, addr);
4533 2 : printf ("\n");
4534 : }
4535 : break;
4536 :
4537 4 : case DW_OP_bit_piece:
4538 4 : start = data;
4539 4 : uint64_t uleb2;
4540 4 : NEED (1);
4541 4 : get_uleb128 (uleb, data, data + len);
4542 4 : NEED (1);
4543 4 : get_uleb128 (uleb2, data, data + len);
4544 4 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
4545 : indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
4546 4 : CONSUME (data - start);
4547 4 : offset += 1 + (data - start);
4548 4 : break;
4549 :
4550 75317 : case DW_OP_fbreg:
4551 : case DW_OP_breg0 ... DW_OP_breg31:
4552 : case DW_OP_consts:
4553 75317 : start = data;
4554 75317 : int64_t sleb;
4555 75317 : NEED (1);
4556 75317 : get_sleb128 (sleb, data, data + len);
4557 75317 : printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
4558 : indent, "", (uintmax_t) offset, op_name, sleb);
4559 75317 : CONSUME (data - start);
4560 75317 : offset += 1 + (data - start);
4561 75317 : break;
4562 :
4563 0 : case DW_OP_bregx:
4564 0 : start = data;
4565 0 : NEED (1);
4566 0 : get_uleb128 (uleb, data, data + len);
4567 0 : NEED (1);
4568 0 : get_sleb128 (sleb, data, data + len);
4569 0 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
4570 : indent, "", (uintmax_t) offset, op_name, uleb, sleb);
4571 0 : CONSUME (data - start);
4572 0 : offset += 1 + (data - start);
4573 0 : break;
4574 :
4575 0 : case DW_OP_call2:
4576 0 : NEED (2);
4577 0 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx16 "]\n",
4578 : indent, "", (uintmax_t) offset, op_name,
4579 0 : read_2ubyte_unaligned (dbg, data));
4580 0 : CONSUME (2);
4581 0 : data += 2;
4582 0 : offset += 3;
4583 0 : break;
4584 :
4585 4 : case DW_OP_call4:
4586 4 : NEED (4);
4587 4 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx32 "]\n",
4588 : indent, "", (uintmax_t) offset, op_name,
4589 4 : read_4ubyte_unaligned (dbg, data));
4590 4 : CONSUME (4);
4591 4 : data += 4;
4592 4 : offset += 5;
4593 4 : break;
4594 :
4595 421 : case DW_OP_skip:
4596 : case DW_OP_bra:
4597 421 : NEED (2);
4598 1263 : printf ("%*s[%2" PRIuMAX "] %s %" PRIuMAX "\n",
4599 : indent, "", (uintmax_t) offset, op_name,
4600 421 : (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
4601 421 : CONSUME (2);
4602 421 : data += 2;
4603 421 : offset += 3;
4604 421 : break;
4605 :
4606 156 : case DW_OP_implicit_value:
4607 156 : start = data;
4608 156 : NEED (1);
4609 156 : get_uleb128 (uleb, data, data + len);
4610 156 : printf ("%*s[%2" PRIuMAX "] %s: ",
4611 : indent, "", (uintmax_t) offset, op_name);
4612 156 : NEED (uleb);
4613 156 : print_block (uleb, data);
4614 156 : data += uleb;
4615 156 : CONSUME (data - start);
4616 156 : offset += 1 + (data - start);
4617 156 : break;
4618 :
4619 3850 : case DW_OP_implicit_pointer:
4620 : case DW_OP_GNU_implicit_pointer:
4621 : /* DIE offset operand. */
4622 3850 : start = data;
4623 3850 : NEED (ref_size);
4624 3850 : if (ref_size != 4 && ref_size != 8)
4625 0 : goto invalid; /* Cannot be used in CFA. */
4626 3850 : if (ref_size == 4)
4627 3850 : addr = read_4ubyte_unaligned (dbg, data);
4628 : else
4629 0 : addr = read_8ubyte_unaligned (dbg, data);
4630 3850 : data += ref_size;
4631 : /* Byte offset operand. */
4632 3850 : NEED (1);
4633 3850 : get_sleb128 (sleb, data, data + len);
4634 :
4635 3850 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
4636 : indent, "", (intmax_t) offset,
4637 : op_name, (uintmax_t) addr, sleb);
4638 3850 : CONSUME (data - start);
4639 3850 : offset += 1 + (data - start);
4640 3850 : break;
4641 :
4642 22663 : case DW_OP_entry_value:
4643 : case DW_OP_GNU_entry_value:
4644 : /* Size plus expression block. */
4645 22663 : start = data;
4646 22663 : NEED (1);
4647 22663 : get_uleb128 (uleb, data, data + len);
4648 22663 : printf ("%*s[%2" PRIuMAX "] %s:\n",
4649 : indent, "", (uintmax_t) offset, op_name);
4650 22663 : NEED (uleb);
4651 22663 : print_ops (dwflmod, dbg, indent + 5, indent + 5, vers,
4652 : addrsize, offset_size, cu, uleb, data);
4653 22663 : data += uleb;
4654 22663 : CONSUME (data - start);
4655 22663 : offset += 1 + (data - start);
4656 22663 : break;
4657 :
4658 1 : case DW_OP_const_type:
4659 : case DW_OP_GNU_const_type:
4660 : /* uleb128 CU relative DW_TAG_base_type DIE offset, 1-byte
4661 : unsigned size plus block. */
4662 1 : start = data;
4663 1 : NEED (1);
4664 1 : get_uleb128 (uleb, data, data + len);
4665 1 : if (! print_unresolved_addresses && cu != NULL)
4666 1 : uleb += cu->start;
4667 1 : NEED (1);
4668 1 : uint8_t usize = *(uint8_t *) data++;
4669 1 : NEED (usize);
4670 1 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] ",
4671 : indent, "", (uintmax_t) offset, op_name, uleb);
4672 1 : print_block (usize, data);
4673 1 : data += usize;
4674 1 : CONSUME (data - start);
4675 1 : offset += 1 + (data - start);
4676 1 : break;
4677 :
4678 0 : case DW_OP_regval_type:
4679 : case DW_OP_GNU_regval_type:
4680 : /* uleb128 register number, uleb128 CU relative
4681 : DW_TAG_base_type DIE offset. */
4682 0 : start = data;
4683 0 : NEED (1);
4684 0 : get_uleb128 (uleb, data, data + len);
4685 0 : NEED (1);
4686 0 : get_uleb128 (uleb2, data, data + len);
4687 0 : if (! print_unresolved_addresses && cu != NULL)
4688 0 : uleb2 += cu->start;
4689 0 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
4690 : indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
4691 0 : CONSUME (data - start);
4692 0 : offset += 1 + (data - start);
4693 0 : break;
4694 :
4695 6 : case DW_OP_deref_type:
4696 : case DW_OP_GNU_deref_type:
4697 : /* 1-byte unsigned size of value, uleb128 CU relative
4698 : DW_TAG_base_type DIE offset. */
4699 6 : start = data;
4700 6 : NEED (1);
4701 6 : usize = *(uint8_t *) data++;
4702 6 : NEED (1);
4703 6 : get_uleb128 (uleb, data, data + len);
4704 6 : if (! print_unresolved_addresses && cu != NULL)
4705 6 : uleb += cu->start;
4706 6 : printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
4707 : indent, "", (uintmax_t) offset,
4708 : op_name, usize, uleb);
4709 6 : CONSUME (data - start);
4710 6 : offset += 1 + (data - start);
4711 6 : break;
4712 :
4713 0 : case DW_OP_xderef_type:
4714 : /* 1-byte unsigned size of value, uleb128 base_type DIE offset. */
4715 0 : start = data;
4716 0 : NEED (1);
4717 0 : usize = *(uint8_t *) data++;
4718 0 : NEED (1);
4719 0 : get_uleb128 (uleb, data, data + len);
4720 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
4721 : indent, "", (uintmax_t) offset,
4722 : op_name, usize, uleb);
4723 0 : CONSUME (data - start);
4724 0 : offset += 1 + (data - start);
4725 0 : break;
4726 :
4727 342 : case DW_OP_convert:
4728 : case DW_OP_GNU_convert:
4729 : case DW_OP_reinterpret:
4730 : case DW_OP_GNU_reinterpret:
4731 : /* uleb128 CU relative offset to DW_TAG_base_type, or zero
4732 : for conversion to untyped. */
4733 342 : start = data;
4734 342 : NEED (1);
4735 342 : get_uleb128 (uleb, data, data + len);
4736 342 : if (uleb != 0 && ! print_unresolved_addresses && cu != NULL)
4737 229 : uleb += cu->start;
4738 342 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
4739 : indent, "", (uintmax_t) offset, op_name, uleb);
4740 342 : CONSUME (data - start);
4741 342 : offset += 1 + (data - start);
4742 342 : break;
4743 :
4744 21 : case DW_OP_GNU_parameter_ref:
4745 : /* 4 byte CU relative reference to the abstract optimized away
4746 : DW_TAG_formal_parameter. */
4747 21 : NEED (4);
4748 21 : uintmax_t param_off = (uintmax_t) read_4ubyte_unaligned (dbg, data);
4749 21 : if (! print_unresolved_addresses && cu != NULL)
4750 21 : param_off += cu->start;
4751 21 : printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
4752 : indent, "", (uintmax_t) offset, op_name, param_off);
4753 21 : CONSUME (4);
4754 21 : data += 4;
4755 21 : offset += 5;
4756 21 : break;
4757 :
4758 : default:
4759 : /* No Operand. */
4760 291962 : printf ("%*s[%2" PRIuMAX "] %s\n",
4761 : indent, "", (uintmax_t) offset, op_name);
4762 291962 : ++offset;
4763 291962 : break;
4764 : }
4765 :
4766 426735 : indent = indentrest;
4767 426735 : continue;
4768 :
4769 0 : invalid:
4770 0 : printf (gettext ("%*s[%2" PRIuMAX "] %s <TRUNCATED>\n"),
4771 : indent, "", (uintmax_t) offset, op_name);
4772 : break;
4773 : }
4774 : }
4775 :
4776 :
4777 : struct listptr
4778 : {
4779 : Dwarf_Off offset:(64 - 3);
4780 : bool addr64:1;
4781 : bool dwarf64:1;
4782 : bool warned:1;
4783 : struct Dwarf_CU *cu;
4784 : unsigned int attr;
4785 : };
4786 :
4787 : #define listptr_offset_size(p) ((p)->dwarf64 ? 8 : 4)
4788 : #define listptr_address_size(p) ((p)->addr64 ? 8 : 4)
4789 :
4790 : static Dwarf_Addr
4791 104845 : cudie_base (Dwarf_Die *cudie)
4792 : {
4793 104845 : Dwarf_Addr base;
4794 : /* Find the base address of the compilation unit. It will normally
4795 : be specified by DW_AT_low_pc. In DWARF-3 draft 4, the base
4796 : address could be overridden by DW_AT_entry_pc. It's been
4797 : removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc for
4798 : compilation units with discontinuous ranges. */
4799 104845 : if (unlikely (dwarf_lowpc (cudie, &base) != 0))
4800 : {
4801 0 : Dwarf_Attribute attr_mem;
4802 0 : if (dwarf_formaddr (dwarf_attr (cudie, DW_AT_entry_pc, &attr_mem),
4803 : &base) != 0)
4804 0 : base = 0;
4805 : }
4806 104845 : return base;
4807 : }
4808 :
4809 : static Dwarf_Addr
4810 0 : listptr_base (struct listptr *p)
4811 : {
4812 0 : Dwarf_Die cu = CUDIE (p->cu);
4813 0 : return cudie_base (&cu);
4814 : }
4815 :
4816 : static int
4817 682078 : compare_listptr (const void *a, const void *b, void *arg)
4818 : {
4819 682078 : const char *name = arg;
4820 682078 : struct listptr *p1 = (void *) a;
4821 682078 : struct listptr *p2 = (void *) b;
4822 :
4823 682078 : if (p1->offset < p2->offset)
4824 : return -1;
4825 68032 : if (p1->offset > p2->offset)
4826 : return 1;
4827 :
4828 3670 : if (!p1->warned && !p2->warned)
4829 : {
4830 3670 : if (p1->addr64 != p2->addr64)
4831 : {
4832 0 : p1->warned = p2->warned = true;
4833 0 : error (0, 0,
4834 0 : gettext ("%s %#" PRIx64 " used with different address sizes"),
4835 : name, (uint64_t) p1->offset);
4836 : }
4837 3670 : if (p1->dwarf64 != p2->dwarf64)
4838 : {
4839 0 : p1->warned = p2->warned = true;
4840 0 : error (0, 0,
4841 0 : gettext ("%s %#" PRIx64 " used with different offset sizes"),
4842 0 : name, (uint64_t) p1->offset);
4843 : }
4844 3670 : if (listptr_base (p1) != listptr_base (p2))
4845 : {
4846 0 : p1->warned = p2->warned = true;
4847 0 : error (0, 0,
4848 0 : gettext ("%s %#" PRIx64 " used with different base addresses"),
4849 0 : name, (uint64_t) p1->offset);
4850 : }
4851 3670 : if (p1->attr != p2 ->attr)
4852 : {
4853 0 : p1->warned = p2->warned = true;
4854 0 : error (0, 0,
4855 0 : gettext ("%s %#" PRIx64
4856 : " used with different attribute %s and %s"),
4857 0 : name, (uint64_t) p1->offset, dwarf_attr_name (p2->attr),
4858 : dwarf_attr_name (p2->attr));
4859 : }
4860 : }
4861 :
4862 : return 0;
4863 : }
4864 :
4865 : struct listptr_table
4866 : {
4867 : size_t n;
4868 : size_t alloc;
4869 : struct listptr *table;
4870 : };
4871 :
4872 : static struct listptr_table known_locsptr;
4873 : static struct listptr_table known_loclistsptr;
4874 : static struct listptr_table known_rangelistptr;
4875 : static struct listptr_table known_rnglistptr;
4876 : static struct listptr_table known_addrbases;
4877 : static struct listptr_table known_stroffbases;
4878 :
4879 : static void
4880 : reset_listptr (struct listptr_table *table)
4881 : {
4882 906 : free (table->table);
4883 906 : table->table = NULL;
4884 906 : table->n = table->alloc = 0;
4885 : }
4886 :
4887 : /* Returns false if offset doesn't fit. See struct listptr. */
4888 : static bool
4889 101211 : notice_listptr (enum section_e section, struct listptr_table *table,
4890 : uint_fast8_t address_size, uint_fast8_t offset_size,
4891 : struct Dwarf_CU *cu, Dwarf_Off offset, unsigned int attr)
4892 : {
4893 101211 : if (print_debug_sections & section)
4894 : {
4895 101110 : if (table->n == table->alloc)
4896 : {
4897 203 : if (table->alloc == 0)
4898 83 : table->alloc = 128;
4899 : else
4900 120 : table->alloc *= 2;
4901 203 : table->table = xrealloc (table->table,
4902 203 : table->alloc * sizeof table->table[0]);
4903 : }
4904 :
4905 101110 : struct listptr *p = &table->table[table->n++];
4906 :
4907 202220 : *p = (struct listptr)
4908 : {
4909 101110 : .addr64 = address_size == 8,
4910 101110 : .dwarf64 = offset_size == 8,
4911 : .offset = offset,
4912 : .cu = cu,
4913 : .attr = attr
4914 : };
4915 :
4916 101110 : if (p->offset != offset)
4917 : {
4918 0 : table->n--;
4919 0 : return false;
4920 : }
4921 : }
4922 : return true;
4923 : }
4924 :
4925 : static void
4926 0 : sort_listptr (struct listptr_table *table, const char *name)
4927 : {
4928 0 : if (table->n > 0)
4929 83 : qsort_r (table->table, table->n, sizeof table->table[0],
4930 : &compare_listptr, (void *) name);
4931 0 : }
4932 :
4933 : static bool
4934 0 : skip_listptr_hole (struct listptr_table *table, size_t *idxp,
4935 : uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
4936 : Dwarf_Addr *base, struct Dwarf_CU **cu, ptrdiff_t offset,
4937 : unsigned char **readp, unsigned char *endp,
4938 : unsigned int *attr)
4939 : {
4940 0 : if (table->n == 0)
4941 0 : return false;
4942 :
4943 0 : while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
4944 0 : ++*idxp;
4945 :
4946 0 : struct listptr *p = &table->table[*idxp];
4947 :
4948 0 : if (*idxp == table->n
4949 0 : || p->offset >= (Dwarf_Off) (endp - *readp + offset))
4950 : {
4951 0 : *readp = endp;
4952 0 : printf (gettext (" [%6tx] <UNUSED GARBAGE IN REST OF SECTION>\n"),
4953 : offset);
4954 0 : return true;
4955 : }
4956 :
4957 0 : if (p->offset != (Dwarf_Off) offset)
4958 : {
4959 0 : *readp += p->offset - offset;
4960 0 : printf (gettext (" [%6tx] <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
4961 : offset, (Dwarf_Off) p->offset - offset);
4962 0 : return true;
4963 : }
4964 :
4965 0 : if (address_sizep != NULL)
4966 0 : *address_sizep = listptr_address_size (p);
4967 0 : if (offset_sizep != NULL)
4968 0 : *offset_sizep = listptr_offset_size (p);
4969 0 : if (base != NULL)
4970 0 : *base = listptr_base (p);
4971 0 : if (cu != NULL)
4972 0 : *cu = p->cu;
4973 0 : if (attr != NULL)
4974 0 : *attr = p->attr;
4975 :
4976 : return false;
4977 : }
4978 :
4979 : static Dwarf_Off
4980 0 : next_listptr_offset (struct listptr_table *table, size_t idx)
4981 : {
4982 : /* Note that multiple attributes could in theory point to the same loclist
4983 : offset, so make sure we pick one that is bigger than the current one.
4984 : The table is sorted on offset. */
4985 43054 : Dwarf_Off offset = table->table[idx].offset;
4986 43837 : while (++idx < table->n)
4987 : {
4988 43837 : Dwarf_Off next = table->table[idx].offset;
4989 43837 : if (next > offset)
4990 0 : return next;
4991 : }
4992 : return 0;
4993 : }
4994 :
4995 : /* Returns the listptr associated with the given index, or NULL. */
4996 : static struct listptr *
4997 0 : get_listptr (struct listptr_table *table, size_t idx)
4998 : {
4999 0 : if (idx >= table->n)
5000 0 : return NULL;
5001 0 : return &table->table[idx];
5002 : }
5003 :
5004 : /* Returns the next index, base address and CU associated with the
5005 : list unit offsets. If there is none false is returned, otherwise
5006 : true. Assumes the table has been sorted. */
5007 : static bool
5008 0 : listptr_cu (struct listptr_table *table, size_t *idxp,
5009 : Dwarf_Off start, Dwarf_Off end,
5010 : Dwarf_Addr *base, struct Dwarf_CU **cu)
5011 : {
5012 0 : while (*idxp < table->n
5013 0 : && table->table[*idxp].offset < start)
5014 0 : ++*idxp;
5015 :
5016 0 : if (*idxp < table->n
5017 0 : && table->table[*idxp].offset >= start
5018 0 : && table->table[*idxp].offset < end)
5019 : {
5020 0 : struct listptr *p = &table->table[*idxp];
5021 0 : *base = listptr_base (p);
5022 0 : *cu = p->cu;
5023 0 : ++*idxp;
5024 0 : return true;
5025 : }
5026 :
5027 : return false;
5028 : }
5029 :
5030 : static void
5031 42 : print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
5032 : Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
5033 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5034 : {
5035 84 : const size_t sh_size = (dbg->sectiondata[IDX_debug_abbrev] ?
5036 42 : dbg->sectiondata[IDX_debug_abbrev]->d_size : 0);
5037 :
5038 42 : printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
5039 : " [ Code]\n"),
5040 : elf_ndxscn (scn), section_name (ebl, shdr),
5041 42 : (uint64_t) shdr->sh_offset);
5042 :
5043 42 : Dwarf_Off offset = 0;
5044 1137 : while (offset < sh_size)
5045 : {
5046 1095 : printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
5047 : offset);
5048 :
5049 57787 : while (1)
5050 56692 : {
5051 57787 : size_t length;
5052 57787 : Dwarf_Abbrev abbrev;
5053 :
5054 57787 : int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
5055 57787 : if (res != 0)
5056 : {
5057 1095 : if (unlikely (res < 0))
5058 : {
5059 0 : printf (gettext ("\
5060 : *** error while reading abbreviation: %s\n"),
5061 : dwarf_errmsg (-1));
5062 0 : return;
5063 : }
5064 :
5065 : /* This is the NUL byte at the end of the section. */
5066 1095 : ++offset;
5067 1095 : break;
5068 : }
5069 :
5070 : /* We know these calls can never fail. */
5071 56692 : unsigned int code = dwarf_getabbrevcode (&abbrev);
5072 56692 : unsigned int tag = dwarf_getabbrevtag (&abbrev);
5073 56692 : int has_children = dwarf_abbrevhaschildren (&abbrev);
5074 :
5075 56692 : printf (gettext (" [%5u] offset: %" PRId64
5076 : ", children: %s, tag: %s\n"),
5077 : code, (int64_t) offset,
5078 : has_children ? yes_str : no_str,
5079 : dwarf_tag_name (tag));
5080 :
5081 56692 : size_t cnt = 0;
5082 56692 : unsigned int name;
5083 56692 : unsigned int form;
5084 56692 : Dwarf_Sword data;
5085 56692 : Dwarf_Off enoffset;
5086 312292 : while (dwarf_getabbrevattr_data (&abbrev, cnt, &name, &form,
5087 : &data, &enoffset) == 0)
5088 : {
5089 255600 : printf (" attr: %s, form: %s",
5090 : dwarf_attr_name (name), dwarf_form_name (form));
5091 255600 : if (form == DW_FORM_implicit_const)
5092 0 : printf (" (%" PRId64 ")", data);
5093 255600 : printf (", offset: %#" PRIx64 "\n", (uint64_t) enoffset);
5094 255600 : ++cnt;
5095 : }
5096 :
5097 56692 : offset += length;
5098 : }
5099 : }
5100 : }
5101 :
5102 :
5103 : static void
5104 2 : print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
5105 : Ebl *ebl, GElf_Ehdr *ehdr,
5106 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5107 : {
5108 2 : printf (gettext ("\
5109 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5110 : elf_ndxscn (scn), section_name (ebl, shdr),
5111 2 : (uint64_t) shdr->sh_offset);
5112 :
5113 2 : if (shdr->sh_size == 0)
5114 : return;
5115 :
5116 : /* We like to get the section from libdw to make sure they are relocated. */
5117 4 : Elf_Data *data = (dbg->sectiondata[IDX_debug_addr]
5118 2 : ?: elf_rawdata (scn, NULL));
5119 2 : if (unlikely (data == NULL))
5120 : {
5121 0 : error (0, 0, gettext ("cannot get .debug_addr section data: %s"),
5122 : elf_errmsg (-1));
5123 0 : return;
5124 : }
5125 :
5126 2 : size_t idx = 0;
5127 2 : sort_listptr (&known_addrbases, "addr_base");
5128 :
5129 2 : const unsigned char *start = (const unsigned char *) data->d_buf;
5130 2 : const unsigned char *readp = start;
5131 4 : const unsigned char *readendp = ((const unsigned char *) data->d_buf
5132 2 : + data->d_size);
5133 :
5134 6 : while (readp < readendp)
5135 : {
5136 : /* We cannot really know whether or not there is an header. The
5137 : DebugFission extension to DWARF4 doesn't add one. The DWARF5
5138 : .debug_addr variant does. Whether or not we have an header,
5139 : DW_AT_[GNU_]addr_base points at "index 0". So if the current
5140 : offset equals the CU addr_base then we can just start
5141 : printing addresses. If there is no CU with an exact match
5142 : then we'll try to parse the header first. */
5143 8 : Dwarf_Off off = (Dwarf_Off) (readp
5144 4 : - (const unsigned char *) data->d_buf);
5145 :
5146 4 : printf ("Table at offset %" PRIx64 " ", off);
5147 :
5148 4 : struct listptr *listptr = get_listptr (&known_addrbases, idx++);
5149 4 : const unsigned char *next_unitp;
5150 :
5151 4 : uint64_t unit_length;
5152 4 : uint16_t version;
5153 4 : uint8_t address_size;
5154 4 : uint8_t segment_size;
5155 4 : if (listptr == NULL)
5156 : {
5157 0 : error (0, 0, "Warning: No CU references .debug_addr after %" PRIx64,
5158 : off);
5159 :
5160 : /* We will have to assume it is just addresses to the end... */
5161 0 : address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5162 0 : next_unitp = readendp;
5163 0 : printf ("Unknown CU:\n");
5164 : }
5165 : else
5166 : {
5167 4 : Dwarf_Die cudie;
5168 4 : if (dwarf_cu_die (listptr->cu, &cudie,
5169 : NULL, NULL, NULL, NULL,
5170 : NULL, NULL) == NULL)
5171 0 : printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
5172 : else
5173 4 : printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
5174 :
5175 4 : if (listptr->offset == off)
5176 : {
5177 2 : address_size = listptr_address_size (listptr);
5178 2 : segment_size = 0;
5179 2 : version = 4;
5180 :
5181 : /* The addresses start here, but where do they end? */
5182 2 : listptr = get_listptr (&known_addrbases, idx);
5183 1 : if (listptr == NULL)
5184 : next_unitp = readendp;
5185 1 : else if (listptr->cu->version < 5)
5186 : {
5187 1 : next_unitp = start + listptr->offset;
5188 1 : if (listptr->offset < off || listptr->offset > data->d_size)
5189 : {
5190 0 : error (0, 0,
5191 : "Warning: Bad address base for next unit at %"
5192 : PRIx64, off);
5193 0 : next_unitp = readendp;
5194 : }
5195 : }
5196 : else
5197 : {
5198 : /* Tricky, we don't have a header for this unit, but
5199 : there is one for the next. We will have to
5200 : "guess" how big it is and subtract it from the
5201 : offset (because that points after the header). */
5202 0 : unsigned int offset_size = listptr_offset_size (listptr);
5203 0 : Dwarf_Off next_off = (listptr->offset
5204 0 : - (offset_size == 4 ? 4 : 12) /* len */
5205 : - 2 /* version */
5206 : - 1 /* address size */
5207 0 : - 1); /* segment selector size */
5208 0 : next_unitp = start + next_off;
5209 0 : if (next_off < off || next_off > data->d_size)
5210 : {
5211 0 : error (0, 0,
5212 : "Warning: Couldn't calculate .debug_addr "
5213 : " unit lenght at %" PRIx64, off);
5214 0 : next_unitp = readendp;
5215 : }
5216 : }
5217 2 : unit_length = (uint64_t) (next_unitp - readp);
5218 :
5219 : /* Pretend we have a header. */
5220 2 : printf ("\n");
5221 2 : printf (gettext (" Length: %8" PRIu64 "\n"),
5222 : unit_length);
5223 2 : printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
5224 2 : printf (gettext (" Address size: %8" PRIu64 "\n"),
5225 : (uint64_t) address_size);
5226 2 : printf (gettext (" Segment size: %8" PRIu64 "\n"),
5227 : (uint64_t) segment_size);
5228 2 : printf ("\n");
5229 : }
5230 : else
5231 : {
5232 : /* OK, we have to parse an header first. */
5233 2 : unit_length = read_4ubyte_unaligned_inc (dbg, readp);
5234 2 : if (unlikely (unit_length == 0xffffffff))
5235 : {
5236 0 : if (unlikely (readp > readendp - 8))
5237 : {
5238 0 : invalid_data:
5239 0 : error (0, 0, "Invalid data");
5240 0 : return;
5241 : }
5242 0 : unit_length = read_8ubyte_unaligned_inc (dbg, readp);
5243 : }
5244 2 : printf ("\n");
5245 2 : printf (gettext (" Length: %8" PRIu64 "\n"),
5246 : unit_length);
5247 :
5248 : /* We need at least 2-bytes (version) + 1-byte
5249 : (addr_size) + 1-byte (segment_size) = 4 bytes to
5250 : complete the header. And this unit cannot go beyond
5251 : the section data. */
5252 2 : if (readp > readendp - 4
5253 2 : || unit_length < 4
5254 2 : || unit_length > (uint64_t) (readendp - readp))
5255 : goto invalid_data;
5256 :
5257 2 : next_unitp = readp + unit_length;
5258 :
5259 2 : version = read_2ubyte_unaligned_inc (dbg, readp);
5260 2 : printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
5261 :
5262 2 : if (version != 5)
5263 : {
5264 0 : error (0, 0, gettext ("Unknown version"));
5265 0 : goto next_unit;
5266 : }
5267 :
5268 2 : address_size = *readp++;
5269 2 : printf (gettext (" Address size: %8" PRIu64 "\n"),
5270 : (uint64_t) address_size);
5271 :
5272 2 : if (address_size != 4 && address_size != 8)
5273 : {
5274 0 : error (0, 0, gettext ("unsupported address size"));
5275 0 : goto next_unit;
5276 : }
5277 :
5278 2 : segment_size = *readp++;
5279 2 : printf (gettext (" Segment size: %8" PRIu64 "\n"),
5280 : (uint64_t) segment_size);
5281 2 : printf ("\n");
5282 :
5283 2 : if (segment_size != 0)
5284 : {
5285 0 : error (0, 0, gettext ("unsupported segment size"));
5286 0 : goto next_unit;
5287 : }
5288 :
5289 2 : if (listptr->offset != (Dwarf_Off) (readp - start))
5290 : {
5291 0 : error (0, 0, "Address index doesn't start after header");
5292 0 : goto next_unit;
5293 : }
5294 : }
5295 : }
5296 :
5297 4 : int digits = 1;
5298 4 : size_t addresses = (next_unitp - readp) / address_size;
5299 8 : while (addresses >= 10)
5300 : {
5301 4 : ++digits;
5302 4 : addresses /= 10;
5303 : }
5304 :
5305 4 : unsigned int uidx = 0;
5306 4 : size_t index_offset = readp - (const unsigned char *) data->d_buf;
5307 4 : printf (" Addresses start at offset 0x%zx:\n", index_offset);
5308 76 : while (readp <= next_unitp - address_size)
5309 : {
5310 72 : Dwarf_Addr addr = read_addr_unaligned_inc (address_size, dbg,
5311 : readp);
5312 72 : printf (" [%*u] ", digits, uidx++);
5313 72 : print_dwarf_addr (dwflmod, address_size, addr, addr);
5314 72 : printf ("\n");
5315 : }
5316 4 : printf ("\n");
5317 :
5318 4 : if (readp != next_unitp)
5319 0 : error (0, 0, "extra %zd bytes at end of unit",
5320 0 : (size_t) (next_unitp - readp));
5321 :
5322 4 : next_unit:
5323 : readp = next_unitp;
5324 : }
5325 : }
5326 :
5327 : /* Print content of DWARF .debug_aranges section. We fortunately do
5328 : not have to know a bit about the structure of the section, libdwarf
5329 : takes care of it. */
5330 : static void
5331 0 : print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
5332 : GElf_Shdr *shdr, Dwarf *dbg)
5333 : {
5334 0 : Dwarf_Aranges *aranges;
5335 0 : size_t cnt;
5336 0 : if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
5337 : {
5338 0 : error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
5339 : dwarf_errmsg (-1));
5340 0 : return;
5341 : }
5342 :
5343 0 : GElf_Shdr glink_mem;
5344 0 : GElf_Shdr *glink;
5345 0 : glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
5346 0 : if (glink == NULL)
5347 : {
5348 0 : error (0, 0, gettext ("invalid sh_link value in section %zu"),
5349 : elf_ndxscn (scn));
5350 0 : return;
5351 : }
5352 :
5353 0 : printf (ngettext ("\
5354 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
5355 : "\
5356 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
5357 : cnt),
5358 : elf_ndxscn (scn), section_name (ebl, shdr),
5359 0 : (uint64_t) shdr->sh_offset, cnt);
5360 :
5361 : /* Compute floor(log16(cnt)). */
5362 0 : size_t tmp = cnt;
5363 0 : int digits = 1;
5364 0 : while (tmp >= 16)
5365 : {
5366 0 : ++digits;
5367 0 : tmp >>= 4;
5368 : }
5369 :
5370 0 : for (size_t n = 0; n < cnt; ++n)
5371 : {
5372 0 : Dwarf_Arange *runp = dwarf_onearange (aranges, n);
5373 0 : if (unlikely (runp == NULL))
5374 : {
5375 0 : printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
5376 0 : return;
5377 : }
5378 :
5379 0 : Dwarf_Addr start;
5380 0 : Dwarf_Word length;
5381 0 : Dwarf_Off offset;
5382 :
5383 0 : if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
5384 0 : printf (gettext (" [%*zu] ???\n"), digits, n);
5385 : else
5386 0 : printf (gettext (" [%*zu] start: %0#*" PRIx64
5387 : ", length: %5" PRIu64 ", CU DIE offset: %6"
5388 : PRId64 "\n"),
5389 0 : digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
5390 : (uint64_t) start, (uint64_t) length, (int64_t) offset);
5391 : }
5392 : }
5393 :
5394 :
5395 : /* Print content of DWARF .debug_aranges section. */
5396 : static void
5397 46 : print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
5398 : Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
5399 : GElf_Shdr *shdr, Dwarf *dbg)
5400 : {
5401 46 : if (decodedaranges)
5402 : {
5403 1 : print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg);
5404 1 : return;
5405 : }
5406 :
5407 90 : Elf_Data *data = (dbg->sectiondata[IDX_debug_aranges]
5408 45 : ?: elf_rawdata (scn, NULL));
5409 :
5410 45 : if (unlikely (data == NULL))
5411 : {
5412 0 : error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
5413 : elf_errmsg (-1));
5414 0 : return;
5415 : }
5416 :
5417 45 : printf (gettext ("\
5418 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5419 : elf_ndxscn (scn), section_name (ebl, shdr),
5420 45 : (uint64_t) shdr->sh_offset);
5421 :
5422 45 : const unsigned char *readp = data->d_buf;
5423 45 : const unsigned char *readendp = readp + data->d_size;
5424 :
5425 1137 : while (readp < readendp)
5426 : {
5427 1092 : const unsigned char *hdrstart = readp;
5428 1092 : size_t start_offset = hdrstart - (const unsigned char *) data->d_buf;
5429 :
5430 1092 : printf (gettext ("\nTable at offset %zu:\n"), start_offset);
5431 1092 : if (readp + 4 > readendp)
5432 : {
5433 0 : invalid_data:
5434 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
5435 : elf_ndxscn (scn), section_name (ebl, shdr));
5436 0 : return;
5437 : }
5438 :
5439 1092 : Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
5440 1092 : unsigned int length_bytes = 4;
5441 1092 : if (length == DWARF3_LENGTH_64_BIT)
5442 : {
5443 0 : if (readp + 8 > readendp)
5444 : goto invalid_data;
5445 0 : length = read_8ubyte_unaligned_inc (dbg, readp);
5446 0 : length_bytes = 8;
5447 : }
5448 :
5449 1092 : const unsigned char *nexthdr = readp + length;
5450 1092 : printf (gettext ("\n Length: %6" PRIu64 "\n"),
5451 : (uint64_t) length);
5452 :
5453 1092 : if (unlikely (length > (size_t) (readendp - readp)))
5454 : goto invalid_data;
5455 :
5456 1092 : if (length == 0)
5457 : continue;
5458 :
5459 1092 : if (readp + 2 > readendp)
5460 : goto invalid_data;
5461 1092 : uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, readp);
5462 1092 : printf (gettext (" DWARF version: %6" PRIuFAST16 "\n"),
5463 : version);
5464 1092 : if (version != 2)
5465 : {
5466 0 : error (0, 0, gettext ("unsupported aranges version"));
5467 0 : goto next_table;
5468 : }
5469 :
5470 1092 : Dwarf_Word offset;
5471 1092 : if (readp + length_bytes > readendp)
5472 : goto invalid_data;
5473 1092 : if (length_bytes == 8)
5474 0 : offset = read_8ubyte_unaligned_inc (dbg, readp);
5475 : else
5476 1092 : offset = read_4ubyte_unaligned_inc (dbg, readp);
5477 1092 : printf (gettext (" CU offset: %6" PRIx64 "\n"),
5478 : (uint64_t) offset);
5479 :
5480 1092 : if (readp + 1 > readendp)
5481 : goto invalid_data;
5482 1092 : unsigned int address_size = *readp++;
5483 1092 : printf (gettext (" Address size: %6" PRIu64 "\n"),
5484 : (uint64_t) address_size);
5485 1092 : if (address_size != 4 && address_size != 8)
5486 : {
5487 0 : error (0, 0, gettext ("unsupported address size"));
5488 0 : goto next_table;
5489 : }
5490 :
5491 1092 : if (readp + 1 > readendp)
5492 : goto invalid_data;
5493 1092 : unsigned int segment_size = *readp++;
5494 1092 : printf (gettext (" Segment size: %6" PRIu64 "\n\n"),
5495 : (uint64_t) segment_size);
5496 1092 : if (segment_size != 0 && segment_size != 4 && segment_size != 8)
5497 : {
5498 0 : error (0, 0, gettext ("unsupported segment size"));
5499 0 : goto next_table;
5500 : }
5501 :
5502 : /* Round the address to the next multiple of 2*address_size. */
5503 2184 : readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
5504 1092 : % (2 * address_size));
5505 :
5506 2219 : while (readp < nexthdr)
5507 : {
5508 2219 : Dwarf_Word range_address;
5509 2219 : Dwarf_Word range_length;
5510 2219 : Dwarf_Word segment = 0;
5511 2219 : if (readp + 2 * address_size + segment_size > readendp)
5512 : goto invalid_data;
5513 2219 : if (address_size == 4)
5514 : {
5515 36 : range_address = read_4ubyte_unaligned_inc (dbg, readp);
5516 36 : range_length = read_4ubyte_unaligned_inc (dbg, readp);
5517 : }
5518 : else
5519 : {
5520 2183 : range_address = read_8ubyte_unaligned_inc (dbg, readp);
5521 2183 : range_length = read_8ubyte_unaligned_inc (dbg, readp);
5522 : }
5523 :
5524 2219 : if (segment_size == 4)
5525 0 : segment = read_4ubyte_unaligned_inc (dbg, readp);
5526 2219 : else if (segment_size == 8)
5527 0 : segment = read_8ubyte_unaligned_inc (dbg, readp);
5528 :
5529 2219 : if (range_address == 0 && range_length == 0 && segment == 0)
5530 : break;
5531 :
5532 1127 : printf (" ");
5533 1127 : print_dwarf_addr (dwflmod, address_size, range_address,
5534 : range_address);
5535 1127 : printf ("..");
5536 2254 : print_dwarf_addr (dwflmod, address_size,
5537 1127 : range_address + range_length - 1,
5538 : range_length);
5539 1127 : if (segment_size != 0)
5540 0 : printf (" (%" PRIx64 ")\n", (uint64_t) segment);
5541 : else
5542 1127 : printf ("\n");
5543 : }
5544 :
5545 1092 : next_table:
5546 1092 : if (readp != nexthdr)
5547 : {
5548 0 : size_t padding = nexthdr - readp;
5549 0 : printf (gettext (" %zu padding bytes\n"), padding);
5550 0 : readp = nexthdr;
5551 : }
5552 : }
5553 : }
5554 :
5555 :
5556 : static bool is_split_dwarf (Dwarf *dbg, uint64_t *id, Dwarf_CU **split_cu);
5557 :
5558 : /* Returns true and sets cu and cu_base if the given Dwarf is a split
5559 : DWARF (.dwo) file. */
5560 : static bool
5561 0 : split_dwarf_cu_base (Dwarf *dbg, Dwarf_CU **cu, Dwarf_Addr *cu_base)
5562 : {
5563 0 : uint64_t id;
5564 0 : if (is_split_dwarf (dbg, &id, cu))
5565 : {
5566 0 : Dwarf_Die cudie;
5567 0 : if (dwarf_cu_info (*cu, NULL, NULL, &cudie, NULL, NULL, NULL, NULL) == 0)
5568 : {
5569 0 : *cu_base = cudie_base (&cudie);
5570 0 : return true;
5571 : }
5572 : }
5573 : return false;
5574 : }
5575 :
5576 : /* Print content of DWARF .debug_rnglists section. */
5577 : static void
5578 2 : print_debug_rnglists_section (Dwfl_Module *dwflmod,
5579 : Ebl *ebl,
5580 : GElf_Ehdr *ehdr __attribute__ ((unused)),
5581 : Elf_Scn *scn, GElf_Shdr *shdr,
5582 : Dwarf *dbg __attribute__((unused)))
5583 : {
5584 2 : printf (gettext ("\
5585 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5586 : elf_ndxscn (scn), section_name (ebl, shdr),
5587 2 : (uint64_t) shdr->sh_offset);
5588 :
5589 4 : Elf_Data *data =(dbg->sectiondata[IDX_debug_rnglists]
5590 2 : ?: elf_rawdata (scn, NULL));
5591 2 : if (unlikely (data == NULL))
5592 : {
5593 0 : error (0, 0, gettext ("cannot get .debug_rnglists content: %s"),
5594 : elf_errmsg (-1));
5595 0 : return;
5596 : }
5597 :
5598 : /* For the listptr to get the base address/CU. */
5599 2 : sort_listptr (&known_rnglistptr, "rnglistptr");
5600 2 : size_t listptr_idx = 0;
5601 :
5602 2 : const unsigned char *readp = data->d_buf;
5603 4 : const unsigned char *const dataend = ((unsigned char *) data->d_buf
5604 2 : + data->d_size);
5605 4 : while (readp < dataend)
5606 : {
5607 2 : if (unlikely (readp > dataend - 4))
5608 : {
5609 0 : invalid_data:
5610 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
5611 : elf_ndxscn (scn), section_name (ebl, shdr));
5612 0 : return;
5613 : }
5614 :
5615 2 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
5616 2 : printf (gettext ("Table at Offset 0x%" PRIx64 ":\n\n"),
5617 : (uint64_t) offset);
5618 :
5619 2 : uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
5620 2 : unsigned int offset_size = 4;
5621 2 : if (unlikely (unit_length == 0xffffffff))
5622 : {
5623 0 : if (unlikely (readp > dataend - 8))
5624 : goto invalid_data;
5625 :
5626 0 : unit_length = read_8ubyte_unaligned_inc (dbg, readp);
5627 0 : offset_size = 8;
5628 : }
5629 2 : printf (gettext (" Length: %8" PRIu64 "\n"), unit_length);
5630 :
5631 : /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
5632 : bytes to complete the header. And this unit cannot go beyond
5633 : the section data. */
5634 2 : if (readp > dataend - 8
5635 2 : || unit_length < 8
5636 2 : || unit_length > (uint64_t) (dataend - readp))
5637 : goto invalid_data;
5638 :
5639 2 : const unsigned char *nexthdr = readp + unit_length;
5640 :
5641 2 : uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
5642 2 : printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
5643 :
5644 2 : if (version != 5)
5645 : {
5646 0 : error (0, 0, gettext ("Unknown version"));
5647 0 : goto next_table;
5648 : }
5649 :
5650 2 : uint8_t address_size = *readp++;
5651 2 : printf (gettext (" Address size: %8" PRIu64 "\n"),
5652 : (uint64_t) address_size);
5653 :
5654 2 : if (address_size != 4 && address_size != 8)
5655 : {
5656 0 : error (0, 0, gettext ("unsupported address size"));
5657 0 : goto next_table;
5658 : }
5659 :
5660 2 : uint8_t segment_size = *readp++;
5661 2 : printf (gettext (" Segment size: %8" PRIu64 "\n"),
5662 : (uint64_t) segment_size);
5663 :
5664 2 : if (segment_size != 0 && segment_size != 4 && segment_size != 8)
5665 : {
5666 0 : error (0, 0, gettext ("unsupported segment size"));
5667 0 : goto next_table;
5668 : }
5669 :
5670 2 : uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
5671 2 : printf (gettext (" Offset entries: %8" PRIu64 "\n"),
5672 : (uint64_t) offset_entry_count);
5673 :
5674 : /* We need the CU that uses this unit to get the initial base address. */
5675 2 : Dwarf_Addr cu_base = 0;
5676 2 : struct Dwarf_CU *cu = NULL;
5677 2 : if (listptr_cu (&known_rnglistptr, &listptr_idx,
5678 : (Dwarf_Off) offset,
5679 2 : (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
5680 : &cu_base, &cu)
5681 0 : || split_dwarf_cu_base (dbg, &cu, &cu_base))
5682 2 : {
5683 2 : Dwarf_Die cudie;
5684 2 : if (dwarf_cu_die (cu, &cudie,
5685 : NULL, NULL, NULL, NULL,
5686 : NULL, NULL) == NULL)
5687 0 : printf (gettext (" Unknown CU base: "));
5688 : else
5689 2 : printf (gettext (" CU [%6" PRIx64 "] base: "),
5690 : dwarf_dieoffset (&cudie));
5691 2 : print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
5692 2 : printf ("\n");
5693 : }
5694 : else
5695 0 : printf (gettext (" Not associated with a CU.\n"));
5696 :
5697 2 : printf ("\n");
5698 :
5699 2 : const unsigned char *offset_array_start = readp;
5700 2 : if (offset_entry_count > 0)
5701 : {
5702 1 : uint64_t max_entries = (unit_length - 8) / offset_size;
5703 1 : if (offset_entry_count > max_entries)
5704 : {
5705 0 : error (0, 0,
5706 0 : gettext ("too many offset entries for unit length"));
5707 0 : offset_entry_count = max_entries;
5708 : }
5709 :
5710 3 : printf (gettext (" Offsets starting at 0x%" PRIx64 ":\n"),
5711 : (uint64_t) (offset_array_start
5712 1 : - (unsigned char *) data->d_buf));
5713 3 : for (uint32_t idx = 0; idx < offset_entry_count; idx++)
5714 : {
5715 2 : printf (" [%6" PRIu32 "] ", idx);
5716 2 : if (offset_size == 4)
5717 : {
5718 2 : uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
5719 2 : printf ("0x%" PRIx32 "\n", off);
5720 : }
5721 : else
5722 : {
5723 0 : uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
5724 0 : printf ("0x%" PRIx64 "\n", off);
5725 : }
5726 : }
5727 1 : printf ("\n");
5728 : }
5729 :
5730 2 : Dwarf_Addr base = cu_base;
5731 2 : bool start_of_list = true;
5732 16 : while (readp < nexthdr)
5733 : {
5734 14 : uint8_t kind = *readp++;
5735 14 : uint64_t op1, op2;
5736 :
5737 : /* Skip padding. */
5738 14 : if (start_of_list && kind == DW_RLE_end_of_list)
5739 : continue;
5740 :
5741 14 : if (start_of_list)
5742 : {
5743 4 : base = cu_base;
5744 16 : printf (" Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
5745 4 : (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
5746 4 : (uint64_t) (readp - offset_array_start - 1));
5747 4 : start_of_list = false;
5748 : }
5749 :
5750 14 : printf (" %s", dwarf_range_list_encoding_name (kind));
5751 14 : switch (kind)
5752 : {
5753 4 : case DW_RLE_end_of_list:
5754 4 : start_of_list = true;
5755 4 : printf ("\n\n");
5756 : break;
5757 :
5758 0 : case DW_RLE_base_addressx:
5759 0 : if ((uint64_t) (nexthdr - readp) < 1)
5760 : {
5761 0 : invalid_range:
5762 0 : error (0, 0, gettext ("invalid range list data"));
5763 0 : goto next_table;
5764 : }
5765 0 : get_uleb128 (op1, readp, nexthdr);
5766 0 : printf (" %" PRIx64 "\n", op1);
5767 0 : if (! print_unresolved_addresses)
5768 : {
5769 0 : Dwarf_Addr addr;
5770 0 : if (get_indexed_addr (cu, op1, &addr) != 0)
5771 0 : printf (" ???\n");
5772 : else
5773 : {
5774 0 : printf (" ");
5775 0 : print_dwarf_addr (dwflmod, address_size, addr, addr);
5776 0 : printf ("\n");
5777 : }
5778 : }
5779 : break;
5780 :
5781 0 : case DW_RLE_startx_endx:
5782 0 : if ((uint64_t) (nexthdr - readp) < 1)
5783 : goto invalid_range;
5784 0 : get_uleb128 (op1, readp, nexthdr);
5785 0 : if ((uint64_t) (nexthdr - readp) < 1)
5786 : goto invalid_range;
5787 0 : get_uleb128 (op2, readp, nexthdr);
5788 0 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
5789 0 : if (! print_unresolved_addresses)
5790 : {
5791 0 : Dwarf_Addr addr1;
5792 0 : Dwarf_Addr addr2;
5793 0 : if (get_indexed_addr (cu, op1, &addr1) != 0
5794 0 : || get_indexed_addr (cu, op2, &addr2) != 0)
5795 : {
5796 0 : printf (" ???..\n");
5797 0 : printf (" ???\n");
5798 : }
5799 : else
5800 : {
5801 0 : printf (" ");
5802 0 : print_dwarf_addr (dwflmod, address_size, addr1, addr1);
5803 0 : printf ("..\n ");
5804 0 : print_dwarf_addr (dwflmod, address_size,
5805 : addr2 - 1, addr2);
5806 0 : printf ("\n");
5807 : }
5808 : }
5809 : break;
5810 :
5811 0 : case DW_RLE_startx_length:
5812 0 : if ((uint64_t) (nexthdr - readp) < 1)
5813 : goto invalid_range;
5814 0 : get_uleb128 (op1, readp, nexthdr);
5815 0 : if ((uint64_t) (nexthdr - readp) < 1)
5816 : goto invalid_range;
5817 0 : get_uleb128 (op2, readp, nexthdr);
5818 0 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
5819 0 : if (! print_unresolved_addresses)
5820 : {
5821 0 : Dwarf_Addr addr1;
5822 0 : Dwarf_Addr addr2;
5823 0 : if (get_indexed_addr (cu, op1, &addr1) != 0)
5824 : {
5825 0 : printf (" ???..\n");
5826 0 : printf (" ???\n");
5827 : }
5828 : else
5829 : {
5830 0 : addr2 = addr1 + op2;
5831 0 : printf (" ");
5832 0 : print_dwarf_addr (dwflmod, address_size, addr1, addr1);
5833 0 : printf ("..\n ");
5834 0 : print_dwarf_addr (dwflmod, address_size,
5835 : addr2 - 1, addr2);
5836 0 : printf ("\n");
5837 : }
5838 : }
5839 : break;
5840 :
5841 4 : case DW_RLE_offset_pair:
5842 4 : if ((uint64_t) (nexthdr - readp) < 1)
5843 : goto invalid_range;
5844 4 : get_uleb128 (op1, readp, nexthdr);
5845 4 : if ((uint64_t) (nexthdr - readp) < 1)
5846 : goto invalid_range;
5847 4 : get_uleb128 (op2, readp, nexthdr);
5848 4 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
5849 4 : if (! print_unresolved_addresses)
5850 : {
5851 4 : op1 += base;
5852 4 : op2 += base;
5853 4 : printf (" ");
5854 4 : print_dwarf_addr (dwflmod, address_size, op1, op1);
5855 4 : printf ("..\n ");
5856 4 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
5857 4 : printf ("\n");
5858 : }
5859 : break;
5860 :
5861 2 : case DW_RLE_base_address:
5862 2 : if (address_size == 4)
5863 : {
5864 0 : if ((uint64_t) (nexthdr - readp) < 4)
5865 : goto invalid_range;
5866 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
5867 : }
5868 : else
5869 : {
5870 2 : if ((uint64_t) (nexthdr - readp) < 8)
5871 : goto invalid_range;
5872 2 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
5873 : }
5874 2 : base = op1;
5875 2 : printf (" 0x%" PRIx64 "\n", base);
5876 2 : if (! print_unresolved_addresses)
5877 : {
5878 2 : printf (" ");
5879 2 : print_dwarf_addr (dwflmod, address_size, base, base);
5880 2 : printf ("\n");
5881 : }
5882 : break;
5883 :
5884 0 : case DW_RLE_start_end:
5885 0 : if (address_size == 4)
5886 : {
5887 0 : if ((uint64_t) (nexthdr - readp) < 8)
5888 : goto invalid_range;
5889 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
5890 0 : op2 = read_4ubyte_unaligned_inc (dbg, readp);
5891 : }
5892 : else
5893 : {
5894 0 : if ((uint64_t) (nexthdr - readp) < 16)
5895 : goto invalid_range;
5896 0 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
5897 0 : op2 = read_8ubyte_unaligned_inc (dbg, readp);
5898 : }
5899 0 : printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
5900 0 : if (! print_unresolved_addresses)
5901 : {
5902 0 : printf (" ");
5903 0 : print_dwarf_addr (dwflmod, address_size, op1, op1);
5904 0 : printf ("..\n ");
5905 0 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
5906 0 : printf ("\n");
5907 : }
5908 : break;
5909 :
5910 4 : case DW_RLE_start_length:
5911 4 : if (address_size == 4)
5912 : {
5913 0 : if ((uint64_t) (nexthdr - readp) < 4)
5914 : goto invalid_range;
5915 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
5916 : }
5917 : else
5918 : {
5919 4 : if ((uint64_t) (nexthdr - readp) < 8)
5920 : goto invalid_range;
5921 4 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
5922 : }
5923 4 : if ((uint64_t) (nexthdr - readp) < 1)
5924 : goto invalid_range;
5925 4 : get_uleb128 (op2, readp, nexthdr);
5926 4 : printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
5927 4 : if (! print_unresolved_addresses)
5928 : {
5929 4 : op2 = op1 + op2;
5930 4 : printf (" ");
5931 4 : print_dwarf_addr (dwflmod, address_size, op1, op1);
5932 4 : printf ("..\n ");
5933 4 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
5934 4 : printf ("\n");
5935 : }
5936 : break;
5937 :
5938 : default:
5939 : goto invalid_range;
5940 : }
5941 : }
5942 :
5943 2 : next_table:
5944 2 : if (readp != nexthdr)
5945 : {
5946 0 : size_t padding = nexthdr - readp;
5947 0 : printf (gettext (" %zu padding bytes\n\n"), padding);
5948 0 : readp = nexthdr;
5949 : }
5950 : }
5951 : }
5952 :
5953 : /* Print content of DWARF .debug_ranges section. */
5954 : static void
5955 32 : print_debug_ranges_section (Dwfl_Module *dwflmod,
5956 : Ebl *ebl, GElf_Ehdr *ehdr,
5957 : Elf_Scn *scn, GElf_Shdr *shdr,
5958 : Dwarf *dbg)
5959 : {
5960 64 : Elf_Data *data = (dbg->sectiondata[IDX_debug_ranges]
5961 32 : ?: elf_rawdata (scn, NULL));
5962 32 : if (unlikely (data == NULL))
5963 : {
5964 0 : error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
5965 : elf_errmsg (-1));
5966 0 : return;
5967 : }
5968 :
5969 32 : printf (gettext ("\
5970 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5971 : elf_ndxscn (scn), section_name (ebl, shdr),
5972 32 : (uint64_t) shdr->sh_offset);
5973 :
5974 32 : sort_listptr (&known_rangelistptr, "rangelistptr");
5975 32 : size_t listptr_idx = 0;
5976 :
5977 32 : uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5978 :
5979 32 : bool first = true;
5980 32 : Dwarf_Addr base = 0;
5981 32 : unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
5982 32 : unsigned char *readp = data->d_buf;
5983 32 : Dwarf_CU *last_cu = NULL;
5984 50489 : while (readp < endp)
5985 : {
5986 50457 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
5987 50457 : Dwarf_CU *cu = last_cu;
5988 :
5989 50457 : if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
5990 : &address_size, NULL, &base, &cu,
5991 : offset, &readp, endp, NULL))
5992 4 : continue;
5993 :
5994 50453 : if (last_cu != cu)
5995 : {
5996 643 : Dwarf_Die cudie;
5997 643 : if (dwarf_cu_die (cu, &cudie,
5998 : NULL, NULL, NULL, NULL,
5999 : NULL, NULL) == NULL)
6000 0 : printf (gettext ("\n Unknown CU base: "));
6001 : else
6002 643 : printf (gettext ("\n CU [%6" PRIx64 "] base: "),
6003 : dwarf_dieoffset (&cudie));
6004 643 : print_dwarf_addr (dwflmod, address_size, base, base);
6005 643 : printf ("\n");
6006 : }
6007 50453 : last_cu = cu;
6008 :
6009 50453 : if (unlikely (data->d_size - offset < (size_t) address_size * 2))
6010 : {
6011 0 : printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
6012 0 : break;
6013 : }
6014 :
6015 50453 : Dwarf_Addr begin;
6016 50453 : Dwarf_Addr end;
6017 50453 : if (address_size == 8)
6018 : {
6019 50445 : begin = read_8ubyte_unaligned_inc (dbg, readp);
6020 50445 : end = read_8ubyte_unaligned_inc (dbg, readp);
6021 : }
6022 : else
6023 : {
6024 8 : begin = read_4ubyte_unaligned_inc (dbg, readp);
6025 8 : end = read_4ubyte_unaligned_inc (dbg, readp);
6026 8 : if (begin == (Dwarf_Addr) (uint32_t) -1)
6027 : begin = (Dwarf_Addr) -1l;
6028 : }
6029 :
6030 50453 : if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
6031 : {
6032 0 : printf (gettext (" [%6tx] base address\n "), offset);
6033 0 : print_dwarf_addr (dwflmod, address_size, end, end);
6034 0 : printf ("\n");
6035 0 : base = end;
6036 : }
6037 50453 : else if (begin == 0 && end == 0) /* End of list entry. */
6038 : {
6039 11317 : if (first)
6040 4 : printf (gettext (" [%6tx] empty list\n"), offset);
6041 : first = true;
6042 : }
6043 : else
6044 : {
6045 : /* We have an address range entry. */
6046 39136 : if (first) /* First address range entry in a list. */
6047 11313 : printf (" [%6tx] ", offset);
6048 : else
6049 27823 : printf (" ");
6050 :
6051 39136 : printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
6052 39136 : if (! print_unresolved_addresses)
6053 : {
6054 39126 : printf (" ");
6055 39126 : print_dwarf_addr (dwflmod, address_size, base + begin,
6056 : base + begin);
6057 39126 : printf ("..\n ");
6058 39126 : print_dwarf_addr (dwflmod, address_size,
6059 : base + end - 1, base + end);
6060 39126 : printf ("\n");
6061 : }
6062 :
6063 : first = false;
6064 : }
6065 : }
6066 : }
6067 :
6068 : #define REGNAMESZ 16
6069 : static const char *
6070 9478 : register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
6071 : char name[REGNAMESZ], int *bits, int *type)
6072 : {
6073 9478 : const char *set;
6074 9478 : const char *pfx;
6075 9478 : int ignore;
6076 26738 : ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
6077 : bits ?: &ignore, type ?: &ignore);
6078 9478 : if (n <= 0)
6079 : {
6080 0 : if (loc != NULL)
6081 0 : snprintf (name, REGNAMESZ, "reg%u", loc->regno);
6082 : else
6083 0 : snprintf (name, REGNAMESZ, "??? 0x%x", regno);
6084 0 : if (bits != NULL)
6085 0 : *bits = loc != NULL ? loc->bits : 0;
6086 0 : if (type != NULL)
6087 0 : *type = DW_ATE_unsigned;
6088 0 : set = "??? unrecognized";
6089 : }
6090 : else
6091 : {
6092 9478 : if (bits != NULL && *bits <= 0)
6093 0 : *bits = loc != NULL ? loc->bits : 0;
6094 9478 : if (type != NULL && *type == DW_ATE_void)
6095 0 : *type = DW_ATE_unsigned;
6096 :
6097 : }
6098 9478 : return set;
6099 : }
6100 :
6101 : static const unsigned char *
6102 0 : read_encoded (unsigned int encoding, const unsigned char *readp,
6103 : const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
6104 : {
6105 0 : if ((encoding & 0xf) == DW_EH_PE_absptr)
6106 0 : encoding = gelf_getclass (dbg->elf) == ELFCLASS32
6107 0 : ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
6108 :
6109 0 : switch (encoding & 0xf)
6110 : {
6111 0 : case DW_EH_PE_uleb128:
6112 0 : get_uleb128 (*res, readp, endp);
6113 0 : break;
6114 0 : case DW_EH_PE_sleb128:
6115 0 : get_sleb128 (*res, readp, endp);
6116 0 : break;
6117 0 : case DW_EH_PE_udata2:
6118 0 : if (readp + 2 > endp)
6119 0 : goto invalid;
6120 0 : *res = read_2ubyte_unaligned_inc (dbg, readp);
6121 0 : break;
6122 0 : case DW_EH_PE_udata4:
6123 0 : if (readp + 4 > endp)
6124 0 : goto invalid;
6125 0 : *res = read_4ubyte_unaligned_inc (dbg, readp);
6126 0 : break;
6127 0 : case DW_EH_PE_udata8:
6128 0 : if (readp + 8 > endp)
6129 0 : goto invalid;
6130 0 : *res = read_8ubyte_unaligned_inc (dbg, readp);
6131 0 : break;
6132 0 : case DW_EH_PE_sdata2:
6133 0 : if (readp + 2 > endp)
6134 0 : goto invalid;
6135 0 : *res = read_2sbyte_unaligned_inc (dbg, readp);
6136 0 : break;
6137 0 : case DW_EH_PE_sdata4:
6138 0 : if (readp + 4 > endp)
6139 0 : goto invalid;
6140 0 : *res = read_4sbyte_unaligned_inc (dbg, readp);
6141 0 : break;
6142 0 : case DW_EH_PE_sdata8:
6143 0 : if (readp + 8 > endp)
6144 0 : goto invalid;
6145 0 : *res = read_8sbyte_unaligned_inc (dbg, readp);
6146 0 : break;
6147 : default:
6148 0 : invalid:
6149 0 : error (1, 0,
6150 0 : gettext ("invalid encoding"));
6151 : }
6152 :
6153 0 : return readp;
6154 : }
6155 :
6156 :
6157 : static void
6158 4690 : print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
6159 : Dwarf_Word vma_base, unsigned int code_align,
6160 : int data_align,
6161 : unsigned int version, unsigned int ptr_size,
6162 : unsigned int encoding,
6163 : Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
6164 : {
6165 4690 : char regnamebuf[REGNAMESZ];
6166 4690 : const char *regname (unsigned int regno)
6167 : {
6168 8630 : register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
6169 8630 : return regnamebuf;
6170 : }
6171 :
6172 4690 : puts ("\n Program:");
6173 4690 : Dwarf_Word pc = vma_base;
6174 84030 : while (readp < endp)
6175 : {
6176 79340 : unsigned int opcode = *readp++;
6177 :
6178 79340 : if (opcode < DW_CFA_advance_loc)
6179 : /* Extended opcode. */
6180 46036 : switch (opcode)
6181 : {
6182 13042 : uint64_t op1;
6183 13042 : int64_t sop1;
6184 13042 : uint64_t op2;
6185 13042 : int64_t sop2;
6186 :
6187 13042 : case DW_CFA_nop:
6188 13042 : puts (" nop");
6189 46036 : break;
6190 0 : case DW_CFA_set_loc:
6191 0 : if ((uint64_t) (endp - readp) < 1)
6192 : goto invalid;
6193 0 : readp = read_encoded (encoding, readp, endp, &op1, dbg);
6194 0 : printf (" set_loc %#" PRIx64 " to %#" PRIx64 "\n",
6195 0 : op1, pc = vma_base + op1);
6196 : break;
6197 1784 : case DW_CFA_advance_loc1:
6198 1784 : if ((uint64_t) (endp - readp) < 1)
6199 : goto invalid;
6200 5352 : printf (" advance_loc1 %u to %#" PRIx64 "\n",
6201 1784 : *readp, pc += *readp * code_align);
6202 1784 : ++readp;
6203 1784 : break;
6204 705 : case DW_CFA_advance_loc2:
6205 705 : if ((uint64_t) (endp - readp) < 2)
6206 : goto invalid;
6207 705 : op1 = read_2ubyte_unaligned_inc (dbg, readp);
6208 1410 : printf (" advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
6209 705 : op1, pc += op1 * code_align);
6210 : break;
6211 24 : case DW_CFA_advance_loc4:
6212 24 : if ((uint64_t) (endp - readp) < 4)
6213 : goto invalid;
6214 24 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
6215 48 : printf (" advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
6216 24 : op1, pc += op1 * code_align);
6217 : break;
6218 4 : case DW_CFA_offset_extended:
6219 4 : if ((uint64_t) (endp - readp) < 1)
6220 : goto invalid;
6221 4 : get_uleb128 (op1, readp, endp);
6222 4 : if ((uint64_t) (endp - readp) < 1)
6223 : goto invalid;
6224 4 : get_uleb128 (op2, readp, endp);
6225 4 : printf (" offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
6226 : "\n",
6227 : op1, regname (op1), op2 * data_align);
6228 : break;
6229 0 : case DW_CFA_restore_extended:
6230 0 : if ((uint64_t) (endp - readp) < 1)
6231 : goto invalid;
6232 0 : get_uleb128 (op1, readp, endp);
6233 0 : printf (" restore_extended r%" PRIu64 " (%s)\n",
6234 : op1, regname (op1));
6235 : break;
6236 6 : case DW_CFA_undefined:
6237 6 : if ((uint64_t) (endp - readp) < 1)
6238 : goto invalid;
6239 6 : get_uleb128 (op1, readp, endp);
6240 6 : printf (" undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
6241 : break;
6242 0 : case DW_CFA_same_value:
6243 0 : if ((uint64_t) (endp - readp) < 1)
6244 : goto invalid;
6245 0 : get_uleb128 (op1, readp, endp);
6246 0 : printf (" same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
6247 : break;
6248 0 : case DW_CFA_register:
6249 0 : if ((uint64_t) (endp - readp) < 1)
6250 : goto invalid;
6251 0 : get_uleb128 (op1, readp, endp);
6252 0 : if ((uint64_t) (endp - readp) < 1)
6253 : goto invalid;
6254 0 : get_uleb128 (op2, readp, endp);
6255 0 : printf (" register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
6256 : op1, regname (op1), op2, regname (op2));
6257 : break;
6258 3110 : case DW_CFA_remember_state:
6259 3110 : puts (" remember_state");
6260 3110 : break;
6261 3110 : case DW_CFA_restore_state:
6262 3110 : puts (" restore_state");
6263 3110 : break;
6264 155 : case DW_CFA_def_cfa:
6265 155 : if ((uint64_t) (endp - readp) < 1)
6266 : goto invalid;
6267 155 : get_uleb128 (op1, readp, endp);
6268 155 : if ((uint64_t) (endp - readp) < 1)
6269 : goto invalid;
6270 155 : get_uleb128 (op2, readp, endp);
6271 155 : printf (" def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
6272 : op1, regname (op1), op2);
6273 : break;
6274 50 : case DW_CFA_def_cfa_register:
6275 50 : if ((uint64_t) (endp - readp) < 1)
6276 : goto invalid;
6277 50 : get_uleb128 (op1, readp, endp);
6278 50 : printf (" def_cfa_register r%" PRIu64 " (%s)\n",
6279 : op1, regname (op1));
6280 : break;
6281 24018 : case DW_CFA_def_cfa_offset:
6282 24018 : if ((uint64_t) (endp - readp) < 1)
6283 : goto invalid;
6284 24018 : get_uleb128 (op1, readp, endp);
6285 24018 : printf (" def_cfa_offset %" PRIu64 "\n", op1);
6286 : break;
6287 12 : case DW_CFA_def_cfa_expression:
6288 12 : if ((uint64_t) (endp - readp) < 1)
6289 : goto invalid;
6290 12 : get_uleb128 (op1, readp, endp); /* Length of DW_FORM_block. */
6291 12 : printf (" def_cfa_expression %" PRIu64 "\n", op1);
6292 12 : if ((uint64_t) (endp - readp) < op1)
6293 : {
6294 0 : invalid:
6295 0 : fputs (gettext (" <INVALID DATA>\n"), stdout);
6296 0 : return;
6297 : }
6298 12 : print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
6299 : op1, readp);
6300 12 : readp += op1;
6301 12 : break;
6302 0 : case DW_CFA_expression:
6303 0 : if ((uint64_t) (endp - readp) < 1)
6304 : goto invalid;
6305 0 : get_uleb128 (op1, readp, endp);
6306 0 : if ((uint64_t) (endp - readp) < 1)
6307 : goto invalid;
6308 0 : get_uleb128 (op2, readp, endp); /* Length of DW_FORM_block. */
6309 0 : printf (" expression r%" PRIu64 " (%s) \n",
6310 : op1, regname (op1));
6311 0 : if ((uint64_t) (endp - readp) < op2)
6312 : goto invalid;
6313 0 : print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
6314 : op2, readp);
6315 0 : readp += op2;
6316 0 : break;
6317 16 : case DW_CFA_offset_extended_sf:
6318 16 : if ((uint64_t) (endp - readp) < 1)
6319 : goto invalid;
6320 16 : get_uleb128 (op1, readp, endp);
6321 16 : if ((uint64_t) (endp - readp) < 1)
6322 : goto invalid;
6323 16 : get_sleb128 (sop2, readp, endp);
6324 16 : printf (" offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
6325 : PRId64 "\n",
6326 : op1, regname (op1), sop2 * data_align);
6327 : break;
6328 0 : case DW_CFA_def_cfa_sf:
6329 0 : if ((uint64_t) (endp - readp) < 1)
6330 : goto invalid;
6331 0 : get_uleb128 (op1, readp, endp);
6332 0 : if ((uint64_t) (endp - readp) < 1)
6333 : goto invalid;
6334 0 : get_sleb128 (sop2, readp, endp);
6335 0 : printf (" def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
6336 : op1, regname (op1), sop2 * data_align);
6337 : break;
6338 0 : case DW_CFA_def_cfa_offset_sf:
6339 0 : if ((uint64_t) (endp - readp) < 1)
6340 : goto invalid;
6341 0 : get_sleb128 (sop1, readp, endp);
6342 0 : printf (" def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
6343 : break;
6344 0 : case DW_CFA_val_offset:
6345 0 : if ((uint64_t) (endp - readp) < 1)
6346 : goto invalid;
6347 0 : get_uleb128 (op1, readp, endp);
6348 0 : if ((uint64_t) (endp - readp) < 1)
6349 : goto invalid;
6350 0 : get_uleb128 (op2, readp, endp);
6351 0 : printf (" val_offset %" PRIu64 " at offset %" PRIu64 "\n",
6352 : op1, op2 * data_align);
6353 : break;
6354 0 : case DW_CFA_val_offset_sf:
6355 0 : if ((uint64_t) (endp - readp) < 1)
6356 : goto invalid;
6357 0 : get_uleb128 (op1, readp, endp);
6358 0 : if ((uint64_t) (endp - readp) < 1)
6359 : goto invalid;
6360 0 : get_sleb128 (sop2, readp, endp);
6361 0 : printf (" val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
6362 : op1, sop2 * data_align);
6363 : break;
6364 0 : case DW_CFA_val_expression:
6365 0 : if ((uint64_t) (endp - readp) < 1)
6366 : goto invalid;
6367 0 : get_uleb128 (op1, readp, endp);
6368 0 : if ((uint64_t) (endp - readp) < 1)
6369 : goto invalid;
6370 0 : get_uleb128 (op2, readp, endp); /* Length of DW_FORM_block. */
6371 0 : printf (" val_expression r%" PRIu64 " (%s)\n",
6372 : op1, regname (op1));
6373 0 : if ((uint64_t) (endp - readp) < op2)
6374 : goto invalid;
6375 0 : print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0,
6376 : NULL, op2, readp);
6377 0 : readp += op2;
6378 0 : break;
6379 0 : case DW_CFA_MIPS_advance_loc8:
6380 0 : if ((uint64_t) (endp - readp) < 8)
6381 : goto invalid;
6382 0 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
6383 0 : printf (" MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
6384 0 : op1, pc += op1 * code_align);
6385 : break;
6386 0 : case DW_CFA_GNU_window_save:
6387 0 : puts (" GNU_window_save");
6388 0 : break;
6389 0 : case DW_CFA_GNU_args_size:
6390 0 : if ((uint64_t) (endp - readp) < 1)
6391 : goto invalid;
6392 0 : get_uleb128 (op1, readp, endp);
6393 0 : printf (" args_size %" PRIu64 "\n", op1);
6394 : break;
6395 : default:
6396 0 : printf (" ??? (%u)\n", opcode);
6397 : break;
6398 : }
6399 33304 : else if (opcode < DW_CFA_offset)
6400 49810 : printf (" advance_loc %u to %#" PRIx64 "\n",
6401 24905 : opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
6402 8399 : else if (opcode < DW_CFA_restore)
6403 : {
6404 7289 : uint64_t offset;
6405 7289 : if ((uint64_t) (endp - readp) < 1)
6406 : goto invalid;
6407 7289 : get_uleb128 (offset, readp, endp);
6408 7289 : printf (" offset r%u (%s) at cfa%+" PRId64 "\n",
6409 : opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
6410 : }
6411 : else
6412 1110 : printf (" restore r%u (%s)\n",
6413 : opcode & 0x3f, regname (opcode & 0x3f));
6414 : }
6415 : }
6416 :
6417 :
6418 : static unsigned int
6419 4587 : encoded_ptr_size (int encoding, unsigned int ptr_size)
6420 : {
6421 4587 : switch (encoding & 7)
6422 : {
6423 : case DW_EH_PE_udata4:
6424 : return 4;
6425 0 : case DW_EH_PE_udata8:
6426 0 : return 8;
6427 48 : case 0:
6428 48 : return ptr_size;
6429 : }
6430 :
6431 0 : fprintf (stderr, "Unsupported pointer encoding: %#x, "
6432 : "assuming pointer size of %d.\n", encoding, ptr_size);
6433 0 : return ptr_size;
6434 : }
6435 :
6436 :
6437 : static unsigned int
6438 105 : print_encoding (unsigned int val)
6439 : {
6440 105 : switch (val & 0xf)
6441 : {
6442 0 : case DW_EH_PE_absptr:
6443 0 : fputs ("absptr", stdout);
6444 0 : break;
6445 0 : case DW_EH_PE_uleb128:
6446 0 : fputs ("uleb128", stdout);
6447 0 : break;
6448 0 : case DW_EH_PE_udata2:
6449 0 : fputs ("udata2", stdout);
6450 0 : break;
6451 14 : case DW_EH_PE_udata4:
6452 14 : fputs ("udata4", stdout);
6453 14 : break;
6454 0 : case DW_EH_PE_udata8:
6455 0 : fputs ("udata8", stdout);
6456 0 : break;
6457 0 : case DW_EH_PE_sleb128:
6458 0 : fputs ("sleb128", stdout);
6459 0 : break;
6460 0 : case DW_EH_PE_sdata2:
6461 0 : fputs ("sdata2", stdout);
6462 0 : break;
6463 91 : case DW_EH_PE_sdata4:
6464 91 : fputs ("sdata4", stdout);
6465 91 : break;
6466 0 : case DW_EH_PE_sdata8:
6467 0 : fputs ("sdata8", stdout);
6468 0 : break;
6469 : default:
6470 : /* We did not use any of the bits after all. */
6471 : return val;
6472 : }
6473 :
6474 105 : return val & ~0xf;
6475 : }
6476 :
6477 :
6478 : static unsigned int
6479 91 : print_relinfo (unsigned int val)
6480 : {
6481 91 : switch (val & 0x70)
6482 : {
6483 77 : case DW_EH_PE_pcrel:
6484 77 : fputs ("pcrel", stdout);
6485 77 : break;
6486 0 : case DW_EH_PE_textrel:
6487 0 : fputs ("textrel", stdout);
6488 0 : break;
6489 14 : case DW_EH_PE_datarel:
6490 14 : fputs ("datarel", stdout);
6491 14 : break;
6492 0 : case DW_EH_PE_funcrel:
6493 0 : fputs ("funcrel", stdout);
6494 0 : break;
6495 0 : case DW_EH_PE_aligned:
6496 0 : fputs ("aligned", stdout);
6497 0 : break;
6498 : default:
6499 : return val;
6500 : }
6501 :
6502 91 : return val & ~0x70;
6503 : }
6504 :
6505 :
6506 : static void
6507 105 : print_encoding_base (const char *pfx, unsigned int fde_encoding)
6508 : {
6509 105 : printf ("(%s", pfx);
6510 :
6511 105 : if (fde_encoding == DW_EH_PE_omit)
6512 0 : puts ("omit)");
6513 : else
6514 : {
6515 105 : unsigned int w = fde_encoding;
6516 :
6517 105 : w = print_encoding (w);
6518 :
6519 105 : if (w & 0x70)
6520 : {
6521 91 : if (w != fde_encoding)
6522 91 : fputc_unlocked (' ', stdout);
6523 :
6524 91 : w = print_relinfo (w);
6525 : }
6526 :
6527 105 : if (w != 0)
6528 0 : printf ("%s%x", w != fde_encoding ? " " : "", w);
6529 :
6530 105 : puts (")");
6531 : }
6532 105 : }
6533 :
6534 :
6535 : static void
6536 50 : print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
6537 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6538 : {
6539 50 : size_t shstrndx;
6540 : /* We know this call will succeed since it did in the caller. */
6541 50 : (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
6542 50 : const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
6543 :
6544 : /* Needed if we find PC-relative addresses. */
6545 50 : GElf_Addr bias;
6546 50 : if (dwfl_module_getelf (dwflmod, &bias) == NULL)
6547 : {
6548 0 : error (0, 0, gettext ("cannot get ELF: %s"), dwfl_errmsg (-1));
6549 0 : return;
6550 : }
6551 :
6552 50 : bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
6553 100 : Elf_Data *data = (is_eh_frame
6554 26 : ? elf_rawdata (scn, NULL)
6555 50 : : (dbg->sectiondata[IDX_debug_frame]
6556 24 : ?: elf_rawdata (scn, NULL)));
6557 :
6558 50 : if (unlikely (data == NULL))
6559 : {
6560 0 : error (0, 0, gettext ("cannot get %s content: %s"),
6561 : scnname, elf_errmsg (-1));
6562 0 : return;
6563 : }
6564 :
6565 50 : if (is_eh_frame)
6566 26 : printf (gettext ("\
6567 : \nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6568 26 : elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
6569 : else
6570 24 : printf (gettext ("\
6571 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6572 24 : elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
6573 :
6574 50 : struct cieinfo
6575 : {
6576 : ptrdiff_t cie_offset;
6577 : const char *augmentation;
6578 : unsigned int code_alignment_factor;
6579 : unsigned int data_alignment_factor;
6580 : uint8_t address_size;
6581 : uint8_t fde_encoding;
6582 : uint8_t lsda_encoding;
6583 : struct cieinfo *next;
6584 50 : } *cies = NULL;
6585 :
6586 50 : const unsigned char *readp = data->d_buf;
6587 100 : const unsigned char *const dataend = ((unsigned char *) data->d_buf
6588 50 : + data->d_size);
6589 4754 : while (readp < dataend)
6590 : {
6591 4704 : if (unlikely (readp + 4 > dataend))
6592 : {
6593 0 : invalid_data:
6594 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
6595 : elf_ndxscn (scn), scnname);
6596 0 : return;
6597 : }
6598 :
6599 : /* At the beginning there must be a CIE. There can be multiple,
6600 : hence we test tis in a loop. */
6601 4704 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
6602 :
6603 4704 : Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
6604 4704 : unsigned int length = 4;
6605 4704 : if (unlikely (unit_length == 0xffffffff))
6606 : {
6607 0 : if (unlikely (readp + 8 > dataend))
6608 : goto invalid_data;
6609 :
6610 0 : unit_length = read_8ubyte_unaligned_inc (dbg, readp);
6611 0 : length = 8;
6612 : }
6613 :
6614 4704 : if (unlikely (unit_length == 0))
6615 : {
6616 14 : printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
6617 14 : continue;
6618 : }
6619 :
6620 4690 : Dwarf_Word maxsize = dataend - readp;
6621 4690 : if (unlikely (unit_length > maxsize))
6622 : goto invalid_data;
6623 :
6624 4690 : unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6625 :
6626 4690 : ptrdiff_t start = readp - (unsigned char *) data->d_buf;
6627 4690 : const unsigned char *const cieend = readp + unit_length;
6628 4690 : if (unlikely (cieend > dataend))
6629 : goto invalid_data;
6630 :
6631 4690 : Dwarf_Off cie_id;
6632 4690 : if (length == 4)
6633 : {
6634 4690 : if (unlikely (cieend - readp < 4))
6635 : goto invalid_data;
6636 4690 : cie_id = read_4ubyte_unaligned_inc (dbg, readp);
6637 4690 : if (!is_eh_frame && cie_id == DW_CIE_ID_32)
6638 38 : cie_id = DW_CIE_ID_64;
6639 : }
6640 : else
6641 : {
6642 0 : if (unlikely (cieend - readp < 8))
6643 : goto invalid_data;
6644 0 : cie_id = read_8ubyte_unaligned_inc (dbg, readp);
6645 : }
6646 :
6647 4690 : uint_fast8_t version = 2;
6648 4690 : unsigned int code_alignment_factor;
6649 4690 : int data_alignment_factor;
6650 4690 : unsigned int fde_encoding = 0;
6651 4690 : unsigned int lsda_encoding = 0;
6652 4690 : Dwarf_Word initial_location = 0;
6653 4690 : Dwarf_Word vma_base = 0;
6654 :
6655 4770 : if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
6656 : {
6657 103 : if (unlikely (cieend - readp < 2))
6658 : goto invalid_data;
6659 103 : version = *readp++;
6660 103 : const char *const augmentation = (const char *) readp;
6661 103 : readp = memchr (readp, '\0', cieend - readp);
6662 103 : if (unlikely (readp == NULL))
6663 : goto invalid_data;
6664 103 : ++readp;
6665 :
6666 103 : uint_fast8_t segment_size = 0;
6667 103 : if (version >= 4)
6668 : {
6669 0 : if (cieend - readp < 5)
6670 : goto invalid_data;
6671 0 : ptr_size = *readp++;
6672 0 : segment_size = *readp++;
6673 : }
6674 :
6675 103 : if (cieend - readp < 1)
6676 : goto invalid_data;
6677 103 : get_uleb128 (code_alignment_factor, readp, cieend);
6678 103 : if (cieend - readp < 1)
6679 : goto invalid_data;
6680 103 : get_sleb128 (data_alignment_factor, readp, cieend);
6681 :
6682 : /* In some variant for unwind data there is another field. */
6683 103 : if (strcmp (augmentation, "eh") == 0)
6684 0 : readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6685 :
6686 103 : unsigned int return_address_register;
6687 103 : if (cieend - readp < 1)
6688 : goto invalid_data;
6689 103 : if (unlikely (version == 1))
6690 91 : return_address_register = *readp++;
6691 : else
6692 12 : get_uleb128 (return_address_register, readp, cieend);
6693 :
6694 103 : printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
6695 : " CIE_id: %" PRIu64 "\n"
6696 : " version: %u\n"
6697 : " augmentation: \"%s\"\n",
6698 : offset, (uint64_t) unit_length, (uint64_t) cie_id,
6699 : version, augmentation);
6700 103 : if (version >= 4)
6701 0 : printf (" address_size: %u\n"
6702 : " segment_size: %u\n",
6703 : ptr_size, segment_size);
6704 103 : printf (" code_alignment_factor: %u\n"
6705 : " data_alignment_factor: %d\n"
6706 : " return_address_register: %u\n",
6707 : code_alignment_factor,
6708 : data_alignment_factor, return_address_register);
6709 :
6710 103 : if (augmentation[0] == 'z')
6711 : {
6712 63 : unsigned int augmentationlen;
6713 63 : get_uleb128 (augmentationlen, readp, cieend);
6714 :
6715 63 : if (augmentationlen > (size_t) (cieend - readp))
6716 : {
6717 0 : error (0, 0, gettext ("invalid augmentation length"));
6718 0 : readp = cieend;
6719 0 : continue;
6720 : }
6721 :
6722 63 : const char *hdr = "Augmentation data:";
6723 63 : const char *cp = augmentation + 1;
6724 126 : while (*cp != '\0' && cp < augmentation + augmentationlen + 1)
6725 : {
6726 63 : printf (" %-26s%#x ", hdr, *readp);
6727 63 : hdr = "";
6728 :
6729 63 : if (*cp == 'R')
6730 : {
6731 63 : fde_encoding = *readp++;
6732 63 : print_encoding_base (gettext ("FDE address encoding: "),
6733 : fde_encoding);
6734 : }
6735 0 : else if (*cp == 'L')
6736 : {
6737 0 : lsda_encoding = *readp++;
6738 0 : print_encoding_base (gettext ("LSDA pointer encoding: "),
6739 : lsda_encoding);
6740 : }
6741 0 : else if (*cp == 'P')
6742 : {
6743 : /* Personality. This field usually has a relocation
6744 : attached pointing to __gcc_personality_v0. */
6745 0 : const unsigned char *startp = readp;
6746 0 : unsigned int encoding = *readp++;
6747 0 : uint64_t val = 0;
6748 0 : readp = read_encoded (encoding, readp,
6749 0 : readp - 1 + augmentationlen,
6750 : &val, dbg);
6751 :
6752 0 : while (++startp < readp)
6753 0 : printf ("%#x ", *startp);
6754 :
6755 0 : putchar ('(');
6756 0 : print_encoding (encoding);
6757 0 : putchar (' ');
6758 0 : switch (encoding & 0xf)
6759 : {
6760 0 : case DW_EH_PE_sleb128:
6761 : case DW_EH_PE_sdata2:
6762 : case DW_EH_PE_sdata4:
6763 0 : printf ("%" PRId64 ")\n", val);
6764 : break;
6765 0 : default:
6766 0 : printf ("%#" PRIx64 ")\n", val);
6767 : break;
6768 : }
6769 : }
6770 : else
6771 0 : printf ("(%x)\n", *readp++);
6772 :
6773 63 : ++cp;
6774 : }
6775 : }
6776 :
6777 103 : if (likely (ptr_size == 4 || ptr_size == 8))
6778 : {
6779 103 : struct cieinfo *newp = alloca (sizeof (*newp));
6780 103 : newp->cie_offset = offset;
6781 103 : newp->augmentation = augmentation;
6782 103 : newp->fde_encoding = fde_encoding;
6783 103 : newp->lsda_encoding = lsda_encoding;
6784 103 : newp->address_size = ptr_size;
6785 103 : newp->code_alignment_factor = code_alignment_factor;
6786 103 : newp->data_alignment_factor = data_alignment_factor;
6787 103 : newp->next = cies;
6788 103 : cies = newp;
6789 : }
6790 : }
6791 : else
6792 : {
6793 : struct cieinfo *cie = cies;
6794 9894 : while (cie != NULL)
6795 19788 : if (is_eh_frame
6796 9852 : ? ((Dwarf_Off) start - cie_id) == (Dwarf_Off) cie->cie_offset
6797 42 : : cie_id == (Dwarf_Off) cie->cie_offset)
6798 : break;
6799 : else
6800 5307 : cie = cie->next;
6801 4587 : if (unlikely (cie == NULL))
6802 : {
6803 0 : puts ("invalid CIE reference in FDE");
6804 0 : return;
6805 : }
6806 :
6807 : /* Initialize from CIE data. */
6808 4587 : fde_encoding = cie->fde_encoding;
6809 4587 : lsda_encoding = cie->lsda_encoding;
6810 4587 : ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
6811 4587 : code_alignment_factor = cie->code_alignment_factor;
6812 4587 : data_alignment_factor = cie->data_alignment_factor;
6813 :
6814 4587 : const unsigned char *base = readp;
6815 : // XXX There are sometimes relocations for this value
6816 4587 : initial_location = read_addr_unaligned_inc (ptr_size, dbg, readp);
6817 9174 : Dwarf_Word address_range
6818 4587 : = read_addr_unaligned_inc (ptr_size, dbg, readp);
6819 :
6820 : /* pcrel for an FDE address is relative to the runtime
6821 : address of the start_address field itself. Sign extend
6822 : if necessary to make sure the calculation is done on the
6823 : full 64 bit address even when initial_location only holds
6824 : the lower 32 bits. */
6825 4587 : Dwarf_Addr pc_start = initial_location;
6826 4587 : if (ptr_size == 4)
6827 4547 : pc_start = (uint64_t) (int32_t) pc_start;
6828 4587 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
6829 9078 : pc_start += ((uint64_t) shdr->sh_addr
6830 4539 : + (base - (const unsigned char *) data->d_buf)
6831 4539 : - bias);
6832 :
6833 4587 : printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
6834 : " CIE_pointer: %" PRIu64 "\n"
6835 : " initial_location: ",
6836 : offset, (uint64_t) unit_length,
6837 : cie->cie_offset, (uint64_t) cie_id);
6838 4587 : print_dwarf_addr (dwflmod, cie->address_size,
6839 : pc_start, initial_location);
6840 4587 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
6841 : {
6842 9078 : vma_base = (((uint64_t) shdr->sh_offset
6843 4539 : + (base - (const unsigned char *) data->d_buf)
6844 4539 : + (uint64_t) initial_location)
6845 : & (ptr_size == 4
6846 : ? UINT64_C (0xffffffff)
6847 4539 : : UINT64_C (0xffffffffffffffff)));
6848 4539 : printf (gettext (" (offset: %#" PRIx64 ")"),
6849 : (uint64_t) vma_base);
6850 : }
6851 :
6852 4587 : printf ("\n address_range: %#" PRIx64,
6853 : (uint64_t) address_range);
6854 4587 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
6855 4539 : printf (gettext (" (end offset: %#" PRIx64 ")"),
6856 4539 : ((uint64_t) vma_base + (uint64_t) address_range)
6857 : & (ptr_size == 4
6858 : ? UINT64_C (0xffffffff)
6859 4539 : : UINT64_C (0xffffffffffffffff)));
6860 4587 : putchar ('\n');
6861 :
6862 4587 : if (cie->augmentation[0] == 'z')
6863 : {
6864 4539 : unsigned int augmentationlen;
6865 4539 : if (cieend - readp < 1)
6866 : goto invalid_data;
6867 4539 : get_uleb128 (augmentationlen, readp, cieend);
6868 :
6869 4539 : if (augmentationlen > (size_t) (cieend - readp))
6870 : {
6871 0 : error (0, 0, gettext ("invalid augmentation length"));
6872 0 : readp = cieend;
6873 0 : continue;
6874 : }
6875 :
6876 4539 : if (augmentationlen > 0)
6877 : {
6878 0 : const char *hdr = "Augmentation data:";
6879 0 : const char *cp = cie->augmentation + 1;
6880 0 : unsigned int u = 0;
6881 0 : while (*cp != '\0'
6882 0 : && cp < cie->augmentation + augmentationlen + 1)
6883 : {
6884 0 : if (*cp == 'L')
6885 : {
6886 0 : uint64_t lsda_pointer;
6887 0 : const unsigned char *p
6888 0 : = read_encoded (lsda_encoding, &readp[u],
6889 : &readp[augmentationlen],
6890 : &lsda_pointer, dbg);
6891 0 : u = p - readp;
6892 0 : printf (gettext ("\
6893 : %-26sLSDA pointer: %#" PRIx64 "\n"),
6894 : hdr, lsda_pointer);
6895 0 : hdr = "";
6896 : }
6897 0 : ++cp;
6898 : }
6899 :
6900 0 : while (u < augmentationlen)
6901 : {
6902 0 : printf (" %-26s%#x\n", hdr, readp[u++]);
6903 0 : hdr = "";
6904 : }
6905 : }
6906 :
6907 4539 : readp += augmentationlen;
6908 : }
6909 : }
6910 :
6911 : /* Handle the initialization instructions. */
6912 4690 : if (ptr_size != 4 && ptr_size !=8)
6913 0 : printf ("invalid CIE pointer size (%u), must be 4 or 8.\n", ptr_size);
6914 : else
6915 4690 : print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
6916 : data_alignment_factor, version, ptr_size,
6917 : fde_encoding, dwflmod, ebl, dbg);
6918 4690 : readp = cieend;
6919 : }
6920 : }
6921 :
6922 :
6923 : /* Returns the signedness (or false if it cannot be determined) and
6924 : the byte size (or zero if it cannot be gotten) of the given DIE
6925 : DW_AT_type attribute. Uses dwarf_peel_type and dwarf_aggregate_size. */
6926 : static void
6927 100758 : die_type_sign_bytes (Dwarf_Die *die, bool *is_signed, int *bytes)
6928 : {
6929 100758 : Dwarf_Attribute attr;
6930 100758 : Dwarf_Die type;
6931 :
6932 100758 : *bytes = 0;
6933 100758 : *is_signed = false;
6934 :
6935 100758 : if (dwarf_peel_type (dwarf_formref_die (dwarf_attr_integrate (die,
6936 : DW_AT_type,
6937 : &attr), &type),
6938 : &type) == 0)
6939 : {
6940 221 : Dwarf_Word val;
6941 221 : *is_signed = (dwarf_formudata (dwarf_attr (&type, DW_AT_encoding,
6942 : &attr), &val) == 0
6943 221 : && (val == DW_ATE_signed || val == DW_ATE_signed_char));
6944 :
6945 221 : if (dwarf_aggregate_size (&type, &val) == 0)
6946 221 : *bytes = val;
6947 : }
6948 100758 : }
6949 :
6950 : struct attrcb_args
6951 : {
6952 : Dwfl_Module *dwflmod;
6953 : Dwarf *dbg;
6954 : Dwarf_Die *dies;
6955 : int level;
6956 : bool silent;
6957 : bool is_split;
6958 : unsigned int version;
6959 : unsigned int addrsize;
6960 : unsigned int offset_size;
6961 : struct Dwarf_CU *cu;
6962 : };
6963 :
6964 :
6965 : static int
6966 2889726 : attr_callback (Dwarf_Attribute *attrp, void *arg)
6967 : {
6968 2889726 : struct attrcb_args *cbargs = (struct attrcb_args *) arg;
6969 2889726 : const int level = cbargs->level;
6970 2889726 : Dwarf_Die *die = &cbargs->dies[level];
6971 2889726 : bool is_split = cbargs->is_split;
6972 :
6973 2889726 : unsigned int attr = dwarf_whatattr (attrp);
6974 2889726 : if (unlikely (attr == 0))
6975 : {
6976 0 : if (!cbargs->silent)
6977 0 : error (0, 0, gettext ("DIE [%" PRIx64 "] "
6978 : "cannot get attribute code: %s"),
6979 : dwarf_dieoffset (die), dwarf_errmsg (-1));
6980 0 : return DWARF_CB_ABORT;
6981 : }
6982 :
6983 2889726 : unsigned int form = dwarf_whatform (attrp);
6984 2889726 : if (unlikely (form == 0))
6985 : {
6986 0 : if (!cbargs->silent)
6987 0 : error (0, 0, gettext ("DIE [%" PRIx64 "] "
6988 : "cannot get attribute form: %s"),
6989 : dwarf_dieoffset (die), dwarf_errmsg (-1));
6990 0 : return DWARF_CB_ABORT;
6991 : }
6992 :
6993 2889726 : switch (form)
6994 : {
6995 44783 : case DW_FORM_addr:
6996 : case DW_FORM_addrx:
6997 : case DW_FORM_addrx1:
6998 : case DW_FORM_addrx2:
6999 : case DW_FORM_addrx3:
7000 : case DW_FORM_addrx4:
7001 : case DW_FORM_GNU_addr_index:
7002 44783 : if (!cbargs->silent)
7003 : {
7004 44514 : Dwarf_Addr addr;
7005 44514 : if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
7006 : {
7007 0 : attrval_out:
7008 0 : if (!cbargs->silent)
7009 0 : error (0, 0, gettext ("DIE [%" PRIx64 "] "
7010 : "cannot get attribute '%s' (%s) value: "
7011 : "%s"),
7012 : dwarf_dieoffset (die),
7013 : dwarf_attr_name (attr),
7014 : dwarf_form_name (form),
7015 : dwarf_errmsg (-1));
7016 : /* Don't ABORT, it might be other attributes can be resolved. */
7017 0 : return DWARF_CB_OK;
7018 : }
7019 44514 : if (form != DW_FORM_addr )
7020 : {
7021 8 : Dwarf_Word word;
7022 8 : if (dwarf_formudata (attrp, &word) != 0)
7023 0 : goto attrval_out;
7024 8 : printf (" %*s%-20s (%s) [%" PRIx64 "] ",
7025 : (int) (level * 2), "", dwarf_attr_name (attr),
7026 : dwarf_form_name (form), word);
7027 : }
7028 : else
7029 44506 : printf (" %*s%-20s (%s) ",
7030 : (int) (level * 2), "", dwarf_attr_name (attr),
7031 : dwarf_form_name (form));
7032 44514 : print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr, addr);
7033 44514 : printf ("\n");
7034 : }
7035 2581704 : break;
7036 :
7037 465635 : case DW_FORM_indirect:
7038 : case DW_FORM_strp:
7039 : case DW_FORM_line_strp:
7040 : case DW_FORM_strx:
7041 : case DW_FORM_strx1:
7042 : case DW_FORM_strx2:
7043 : case DW_FORM_strx3:
7044 : case DW_FORM_strx4:
7045 : case DW_FORM_string:
7046 : case DW_FORM_GNU_strp_alt:
7047 : case DW_FORM_GNU_str_index:
7048 465635 : if (cbargs->silent)
7049 : break;
7050 464887 : const char *str = dwarf_formstring (attrp);
7051 464887 : if (unlikely (str == NULL))
7052 : goto attrval_out;
7053 464887 : printf (" %*s%-20s (%s) \"%s\"\n",
7054 : (int) (level * 2), "", dwarf_attr_name (attr),
7055 : dwarf_form_name (form), str);
7056 : break;
7057 :
7058 596489 : case DW_FORM_ref_addr:
7059 : case DW_FORM_ref_udata:
7060 : case DW_FORM_ref8:
7061 : case DW_FORM_ref4:
7062 : case DW_FORM_ref2:
7063 : case DW_FORM_ref1:
7064 : case DW_FORM_GNU_ref_alt:
7065 : case DW_FORM_ref_sup4:
7066 : case DW_FORM_ref_sup8:
7067 596489 : if (cbargs->silent)
7068 : break;
7069 595702 : Dwarf_Die ref;
7070 595702 : if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
7071 : goto attrval_out;
7072 :
7073 595702 : printf (" %*s%-20s (%s) ",
7074 : (int) (level * 2), "", dwarf_attr_name (attr),
7075 : dwarf_form_name (form));
7076 595702 : if (is_split)
7077 33 : printf ("{%6" PRIxMAX "}\n", (uintmax_t) dwarf_dieoffset (&ref));
7078 : else
7079 595669 : printf ("[%6" PRIxMAX "]\n", (uintmax_t) dwarf_dieoffset (&ref));
7080 : break;
7081 :
7082 4 : case DW_FORM_ref_sig8:
7083 4 : if (cbargs->silent)
7084 : break;
7085 4 : printf (" %*s%-20s (%s) {%6" PRIx64 "}\n",
7086 : (int) (level * 2), "", dwarf_attr_name (attr),
7087 : dwarf_form_name (form),
7088 4 : (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
7089 : break;
7090 :
7091 1627835 : case DW_FORM_sec_offset:
7092 : case DW_FORM_rnglistx:
7093 : case DW_FORM_loclistx:
7094 : case DW_FORM_implicit_const:
7095 : case DW_FORM_udata:
7096 : case DW_FORM_sdata:
7097 : case DW_FORM_data8: /* Note no data16 here, we see that as block. */
7098 : case DW_FORM_data4:
7099 : case DW_FORM_data2:
7100 1627835 : case DW_FORM_data1:;
7101 1627835 : Dwarf_Word num;
7102 1627835 : if (unlikely (dwarf_formudata (attrp, &num) != 0))
7103 : goto attrval_out;
7104 :
7105 1627835 : const char *valuestr = NULL;
7106 1627835 : bool as_hex_id = false;
7107 1627835 : switch (attr)
7108 : {
7109 : /* This case can take either a constant or a loclistptr. */
7110 206746 : case DW_AT_data_member_location:
7111 206746 : if (form != DW_FORM_sec_offset
7112 206746 : && (cbargs->version >= 4
7113 23806 : || (form != DW_FORM_data4 && form != DW_FORM_data8)))
7114 : {
7115 206746 : if (!cbargs->silent)
7116 206746 : printf (" %*s%-20s (%s) %" PRIuMAX "\n",
7117 : (int) (level * 2), "", dwarf_attr_name (attr),
7118 : dwarf_form_name (form), (uintmax_t) num);
7119 206746 : return DWARF_CB_OK;
7120 : }
7121 87891 : FALLTHROUGH;
7122 :
7123 : /* These cases always take a loclist[ptr] and no constant. */
7124 : case DW_AT_location:
7125 : case DW_AT_data_location:
7126 : case DW_AT_vtable_elem_location:
7127 : case DW_AT_string_length:
7128 : case DW_AT_use_location:
7129 : case DW_AT_frame_base:
7130 : case DW_AT_return_addr:
7131 : case DW_AT_static_link:
7132 : case DW_AT_segment:
7133 : case DW_AT_GNU_call_site_value:
7134 : case DW_AT_GNU_call_site_data_value:
7135 : case DW_AT_GNU_call_site_target:
7136 : case DW_AT_GNU_call_site_target_clobbered:
7137 : case DW_AT_GNU_locviews:
7138 : {
7139 87891 : bool nlpt;
7140 87891 : if (cbargs->cu->version < 5)
7141 : {
7142 87820 : if (! cbargs->is_split)
7143 : {
7144 263400 : nlpt = notice_listptr (section_loc, &known_locsptr,
7145 87800 : cbargs->addrsize,
7146 87800 : cbargs->offset_size,
7147 : cbargs->cu, num, attr);
7148 : }
7149 : else
7150 : nlpt = true;
7151 : }
7152 : else
7153 : {
7154 : /* Only register for a real section offset. Otherwise
7155 : it is a DW_FORM_loclistx which is just an index
7156 : number and we should already have registered the
7157 : section offset for the index when we saw the
7158 : DW_AT_loclists_base CU attribute. */
7159 71 : if (form == DW_FORM_sec_offset)
7160 96 : nlpt = notice_listptr (section_loc, &known_loclistsptr,
7161 32 : cbargs->addrsize, cbargs->offset_size,
7162 : cbargs->cu, num, attr);
7163 : else
7164 : nlpt = true;
7165 :
7166 : }
7167 :
7168 87891 : if (!cbargs->silent)
7169 : {
7170 87710 : if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
7171 87703 : printf (" %*s%-20s (%s) location list [%6"
7172 : PRIxMAX "]%s\n",
7173 : (int) (level * 2), "", dwarf_attr_name (attr),
7174 : dwarf_form_name (form), (uintmax_t) num,
7175 : nlpt ? "" : " <WARNING offset too big>");
7176 : else
7177 7 : printf (" %*s%-20s (%s) location index [%6"
7178 : PRIxMAX "]\n",
7179 : (int) (level * 2), "", dwarf_attr_name (attr),
7180 : dwarf_form_name (form), (uintmax_t) num);
7181 : }
7182 : }
7183 : return DWARF_CB_OK;
7184 :
7185 5 : case DW_AT_loclists_base:
7186 4 : {
7187 20 : bool nlpt = notice_listptr (section_loc, &known_loclistsptr,
7188 5 : cbargs->addrsize, cbargs->offset_size,
7189 : cbargs->cu, num, attr);
7190 :
7191 5 : if (!cbargs->silent)
7192 1 : printf (" %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n",
7193 : (int) (level * 2), "", dwarf_attr_name (attr),
7194 : dwarf_form_name (form), (uintmax_t) num,
7195 : nlpt ? "" : " <WARNING offset too big>");
7196 : }
7197 : return DWARF_CB_OK;
7198 :
7199 13363 : case DW_AT_ranges:
7200 : case DW_AT_start_scope:
7201 : {
7202 13363 : bool nlpt;
7203 13363 : if (cbargs->cu->version < 5)
7204 40041 : nlpt = notice_listptr (section_ranges, &known_rangelistptr,
7205 13347 : cbargs->addrsize, cbargs->offset_size,
7206 : cbargs->cu, num, attr);
7207 : else
7208 : {
7209 : /* Only register for a real section offset. Otherwise
7210 : it is a DW_FORM_rangelistx which is just an index
7211 : number and we should already have registered the
7212 : section offset for the index when we saw the
7213 : DW_AT_rnglists_base CU attribute. */
7214 16 : if (form == DW_FORM_sec_offset)
7215 30 : nlpt = notice_listptr (section_ranges, &known_rnglistptr,
7216 10 : cbargs->addrsize, cbargs->offset_size,
7217 : cbargs->cu, num, attr);
7218 : else
7219 : nlpt = true;
7220 : }
7221 :
7222 13363 : if (!cbargs->silent)
7223 : {
7224 13321 : if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
7225 13319 : printf (" %*s%-20s (%s) range list [%6"
7226 : PRIxMAX "]%s\n",
7227 : (int) (level * 2), "", dwarf_attr_name (attr),
7228 : dwarf_form_name (form), (uintmax_t) num,
7229 : nlpt ? "" : " <WARNING offset too big>");
7230 : else
7231 2 : printf (" %*s%-20s (%s) range index [%6"
7232 : PRIxMAX "]\n",
7233 : (int) (level * 2), "", dwarf_attr_name (attr),
7234 : dwarf_form_name (form), (uintmax_t) num);
7235 : }
7236 : }
7237 : return DWARF_CB_OK;
7238 :
7239 4 : case DW_AT_rnglists_base:
7240 2 : {
7241 16 : bool nlpt = notice_listptr (section_ranges, &known_rnglistptr,
7242 4 : cbargs->addrsize, cbargs->offset_size,
7243 : cbargs->cu, num, attr);
7244 4 : if (!cbargs->silent)
7245 2 : printf (" %*s%-20s (%s) range list [%6"
7246 : PRIxMAX "]%s\n",
7247 : (int) (level * 2), "", dwarf_attr_name (attr),
7248 : dwarf_form_name (form), (uintmax_t) num,
7249 : nlpt ? "" : " <WARNING offset too big>");
7250 : }
7251 : return DWARF_CB_OK;
7252 :
7253 13 : case DW_AT_addr_base:
7254 : case DW_AT_GNU_addr_base:
7255 8 : {
7256 52 : bool addrbase = notice_listptr (section_addr, &known_addrbases,
7257 13 : cbargs->addrsize,
7258 13 : cbargs->offset_size,
7259 : cbargs->cu, num, attr);
7260 13 : if (!cbargs->silent)
7261 5 : printf (" %*s%-20s (%s) address base [%6"
7262 : PRIxMAX "]%s\n",
7263 : (int) (level * 2), "", dwarf_attr_name (attr),
7264 : dwarf_form_name (form), (uintmax_t) num,
7265 : addrbase ? "" : " <WARNING offset too big>");
7266 : }
7267 : return DWARF_CB_OK;
7268 :
7269 0 : case DW_AT_str_offsets_base:
7270 0 : {
7271 0 : bool stroffbase = notice_listptr (section_str, &known_stroffbases,
7272 0 : cbargs->addrsize,
7273 0 : cbargs->offset_size,
7274 : cbargs->cu, num, attr);
7275 0 : if (!cbargs->silent)
7276 0 : printf (" %*s%-20s (%s) str offsets base [%6"
7277 : PRIxMAX "]%s\n",
7278 : (int) (level * 2), "", dwarf_attr_name (attr),
7279 : dwarf_form_name (form), (uintmax_t) num,
7280 : stroffbase ? "" : " <WARNING offset too big>");
7281 : }
7282 : return DWARF_CB_OK;
7283 :
7284 1162 : case DW_AT_language:
7285 1162 : valuestr = dwarf_lang_name (num);
7286 1162 : break;
7287 16569 : case DW_AT_encoding:
7288 16569 : valuestr = dwarf_encoding_name (num);
7289 16569 : break;
7290 0 : case DW_AT_accessibility:
7291 0 : valuestr = dwarf_access_name (num);
7292 0 : break;
7293 0 : case DW_AT_defaulted:
7294 0 : valuestr = dwarf_defaulted_name (num);
7295 0 : break;
7296 0 : case DW_AT_visibility:
7297 0 : valuestr = dwarf_visibility_name (num);
7298 0 : break;
7299 0 : case DW_AT_virtuality:
7300 0 : valuestr = dwarf_virtuality_name (num);
7301 0 : break;
7302 0 : case DW_AT_identifier_case:
7303 0 : valuestr = dwarf_identifier_case_name (num);
7304 0 : break;
7305 0 : case DW_AT_calling_convention:
7306 0 : valuestr = dwarf_calling_convention_name (num);
7307 0 : break;
7308 2934 : case DW_AT_inline:
7309 2934 : valuestr = dwarf_inline_name (num);
7310 2934 : break;
7311 0 : case DW_AT_ordering:
7312 0 : valuestr = dwarf_ordering_name (num);
7313 0 : break;
7314 365501 : case DW_AT_decl_file:
7315 : case DW_AT_call_file:
7316 421 : {
7317 365501 : if (cbargs->silent)
7318 : break;
7319 :
7320 : /* Try to get the actual file, the current interface only
7321 : gives us full paths, but we only want to show the file
7322 : name for now. */
7323 365080 : Dwarf_Die cudie;
7324 365080 : if (dwarf_cu_die (cbargs->cu, &cudie,
7325 : NULL, NULL, NULL, NULL, NULL, NULL) != NULL)
7326 : {
7327 365080 : Dwarf_Files *files;
7328 365080 : size_t nfiles;
7329 365080 : if (dwarf_getsrcfiles (&cudie, &files, &nfiles) == 0)
7330 : {
7331 365080 : valuestr = dwarf_filesrc (files, num, NULL, NULL);
7332 365080 : if (valuestr != NULL)
7333 : {
7334 365080 : char *filename = strrchr (valuestr, '/');
7335 365080 : if (filename != NULL)
7336 365080 : valuestr = filename + 1;
7337 : }
7338 : else
7339 0 : error (0, 0, gettext ("invalid file (%" PRId64 "): %s"),
7340 : num, dwarf_errmsg (-1));
7341 : }
7342 : else
7343 0 : error (0, 0, gettext ("no srcfiles for CU [%" PRIx64 "]"),
7344 : dwarf_dieoffset (&cudie));
7345 : }
7346 : else
7347 0 : error (0, 0, gettext ("couldn't get DWARF CU: %s"),
7348 : dwarf_errmsg (-1));
7349 365080 : if (valuestr == NULL)
7350 : valuestr = "???";
7351 : }
7352 365080 : break;
7353 13 : case DW_AT_GNU_dwo_id:
7354 13 : as_hex_id = true;
7355 13 : break;
7356 :
7357 : default:
7358 : /* Nothing. */
7359 : break;
7360 : }
7361 :
7362 1319813 : if (cbargs->silent)
7363 : break;
7364 :
7365 : /* When highpc is in constant form it is relative to lowpc.
7366 : In that case also show the address. */
7367 1317972 : Dwarf_Addr highpc;
7368 1317972 : if (attr == DW_AT_high_pc && dwarf_highpc (die, &highpc) == 0)
7369 : {
7370 11777 : printf (" %*s%-20s (%s) %" PRIuMAX " (",
7371 : (int) (level * 2), "", dwarf_attr_name (attr),
7372 : dwarf_form_name (form), (uintmax_t) num);
7373 11777 : print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, highpc, highpc);
7374 11777 : printf (")\n");
7375 : }
7376 : else
7377 : {
7378 1306195 : if (as_hex_id)
7379 : {
7380 2 : printf (" %*s%-20s (%s) 0x%.16" PRIx64 "\n",
7381 : (int) (level * 2), "", dwarf_attr_name (attr),
7382 : dwarf_form_name (form), num);
7383 : }
7384 : else
7385 1306193 : {
7386 1306193 : Dwarf_Sword snum = 0;
7387 1306193 : bool is_signed;
7388 1306193 : int bytes = 0;
7389 1306193 : if (attr == DW_AT_const_value)
7390 100754 : die_type_sign_bytes (die, &is_signed, &bytes);
7391 : else
7392 2410878 : is_signed = (form == DW_FORM_sdata
7393 1205439 : || form == DW_FORM_implicit_const);
7394 :
7395 1306193 : if (is_signed)
7396 150 : if (unlikely (dwarf_formsdata (attrp, &snum) != 0))
7397 0 : goto attrval_out;
7398 :
7399 1306193 : if (valuestr == NULL)
7400 : {
7401 920751 : printf (" %*s%-20s (%s) ",
7402 : (int) (level * 2), "", dwarf_attr_name (attr),
7403 : dwarf_form_name (form));
7404 : }
7405 : else
7406 : {
7407 385442 : printf (" %*s%-20s (%s) %s (",
7408 : (int) (level * 2), "", dwarf_attr_name (attr),
7409 : dwarf_form_name (form), valuestr);
7410 : }
7411 :
7412 1306193 : switch (bytes)
7413 : {
7414 2 : case 1:
7415 2 : if (is_signed)
7416 1 : printf ("%" PRId8, (int8_t) snum);
7417 : else
7418 1 : printf ("%" PRIu8, (uint8_t) num);
7419 : break;
7420 :
7421 2 : case 2:
7422 2 : if (is_signed)
7423 1 : printf ("%" PRId16, (int16_t) snum);
7424 : else
7425 1 : printf ("%" PRIu16, (uint16_t) num);
7426 : break;
7427 :
7428 128 : case 4:
7429 128 : if (is_signed)
7430 125 : printf ("%" PRId32, (int32_t) snum);
7431 : else
7432 3 : printf ("%" PRIu32, (uint32_t) num);
7433 : break;
7434 :
7435 85 : case 8:
7436 85 : if (is_signed)
7437 1 : printf ("%" PRId64, (int64_t) snum);
7438 : else
7439 84 : printf ("%" PRIu64, (uint64_t) num);
7440 : break;
7441 :
7442 1305976 : default:
7443 1305976 : if (is_signed)
7444 22 : printf ("%" PRIdMAX, (intmax_t) snum);
7445 : else
7446 1305954 : printf ("%" PRIuMAX, (uintmax_t) num);
7447 : break;
7448 : }
7449 :
7450 : /* Make clear if we switched from a signed encoding to
7451 : an unsigned value. */
7452 1306193 : if (attr == DW_AT_const_value
7453 100754 : && (form == DW_FORM_sdata || form == DW_FORM_implicit_const)
7454 1226 : && !is_signed)
7455 1219 : printf (" (%" PRIdMAX ")", (intmax_t) num);
7456 :
7457 1306193 : if (valuestr == NULL)
7458 920751 : printf ("\n");
7459 : else
7460 385442 : printf (")\n");
7461 : }
7462 : }
7463 : break;
7464 :
7465 9122 : case DW_FORM_flag:
7466 9122 : if (cbargs->silent)
7467 : break;
7468 9048 : bool flag;
7469 9048 : if (unlikely (dwarf_formflag (attrp, &flag) != 0))
7470 : goto attrval_out;
7471 :
7472 9048 : printf (" %*s%-20s (%s) %s\n",
7473 : (int) (level * 2), "", dwarf_attr_name (attr),
7474 9048 : dwarf_form_name (form), flag ? yes_str : no_str);
7475 : break;
7476 :
7477 63005 : case DW_FORM_flag_present:
7478 63005 : if (cbargs->silent)
7479 : break;
7480 62731 : printf (" %*s%-20s (%s) %s\n",
7481 : (int) (level * 2), "", dwarf_attr_name (attr),
7482 : dwarf_form_name (form), yes_str);
7483 : break;
7484 :
7485 82853 : case DW_FORM_exprloc:
7486 : case DW_FORM_block4:
7487 : case DW_FORM_block2:
7488 : case DW_FORM_block1:
7489 : case DW_FORM_block:
7490 : case DW_FORM_data16: /* DWARF5 calls this a constant class. */
7491 82853 : if (cbargs->silent)
7492 : break;
7493 82724 : Dwarf_Block block;
7494 82724 : if (unlikely (dwarf_formblock (attrp, &block) != 0))
7495 : goto attrval_out;
7496 :
7497 82724 : printf (" %*s%-20s (%s) ",
7498 : (int) (level * 2), "", dwarf_attr_name (attr),
7499 : dwarf_form_name (form));
7500 :
7501 82724 : switch (attr)
7502 : {
7503 4 : default:
7504 4 : if (form != DW_FORM_exprloc)
7505 : {
7506 4 : print_block (block.length, block.data);
7507 4 : break;
7508 : }
7509 82716 : FALLTHROUGH;
7510 :
7511 : case DW_AT_location:
7512 : case DW_AT_data_location:
7513 : case DW_AT_data_member_location:
7514 : case DW_AT_vtable_elem_location:
7515 : case DW_AT_string_length:
7516 : case DW_AT_use_location:
7517 : case DW_AT_frame_base:
7518 : case DW_AT_return_addr:
7519 : case DW_AT_static_link:
7520 : case DW_AT_allocated:
7521 : case DW_AT_associated:
7522 : case DW_AT_bit_size:
7523 : case DW_AT_bit_offset:
7524 : case DW_AT_bit_stride:
7525 : case DW_AT_byte_size:
7526 : case DW_AT_byte_stride:
7527 : case DW_AT_count:
7528 : case DW_AT_lower_bound:
7529 : case DW_AT_upper_bound:
7530 : case DW_AT_GNU_call_site_value:
7531 : case DW_AT_GNU_call_site_data_value:
7532 : case DW_AT_GNU_call_site_target:
7533 : case DW_AT_GNU_call_site_target_clobbered:
7534 82716 : if (form != DW_FORM_data16)
7535 : {
7536 82716 : putchar ('\n');
7537 248148 : print_ops (cbargs->dwflmod, cbargs->dbg,
7538 82716 : 12 + level * 2, 12 + level * 2,
7539 : cbargs->version, cbargs->addrsize, cbargs->offset_size,
7540 82716 : attrp->cu, block.length, block.data);
7541 : }
7542 : else
7543 0 : print_block (block.length, block.data);
7544 : break;
7545 :
7546 4 : case DW_AT_discr_list:
7547 4 : if (block.length == 0)
7548 0 : puts ("<default>");
7549 4 : else if (form != DW_FORM_data16)
7550 : {
7551 4 : const unsigned char *readp = block.data;
7552 4 : const unsigned char *readendp = readp + block.length;
7553 :
7554 : /* See if we are dealing with a signed or unsigned
7555 : values. If the parent of this variant DIE is a
7556 : variant_part then it will either have a discriminant
7557 : which points to the member which type is the
7558 : discriminant type. Or the variant_part itself has a
7559 : type representing the discriminant. */
7560 4 : bool is_signed = false;
7561 4 : if (level > 0)
7562 : {
7563 4 : Dwarf_Die *parent = &cbargs->dies[level - 1];
7564 4 : if (dwarf_tag (die) == DW_TAG_variant
7565 4 : && dwarf_tag (parent) == DW_TAG_variant_part)
7566 : {
7567 4 : Dwarf_Die member;
7568 4 : Dwarf_Attribute discr_attr;
7569 4 : int bytes;
7570 4 : if (dwarf_formref_die (dwarf_attr (parent,
7571 : DW_AT_discr,
7572 : &discr_attr),
7573 : &member) != NULL)
7574 4 : die_type_sign_bytes (&member, &is_signed, &bytes);
7575 : else
7576 0 : die_type_sign_bytes (parent, &is_signed, &bytes);
7577 : }
7578 : }
7579 12 : while (readp < readendp)
7580 : {
7581 8 : int d = (int) *readp++;
7582 16 : printf ("%s ", dwarf_discr_list_name (d));
7583 8 : if (readp >= readendp)
7584 0 : goto attrval_out;
7585 :
7586 8 : Dwarf_Word val;
7587 8 : Dwarf_Sword sval;
7588 8 : if (d == DW_DSC_label)
7589 : {
7590 4 : if (is_signed)
7591 : {
7592 2 : get_sleb128 (sval, readp, readendp);
7593 2 : printf ("%" PRId64 "", sval);
7594 : }
7595 : else
7596 : {
7597 2 : get_uleb128 (val, readp, readendp);
7598 2 : printf ("%" PRIu64 "", val);
7599 : }
7600 : }
7601 4 : else if (d == DW_DSC_range)
7602 : {
7603 4 : if (is_signed)
7604 : {
7605 3 : get_sleb128 (sval, readp, readendp);
7606 3 : printf ("%" PRId64 "..", sval);
7607 3 : if (readp >= readendp)
7608 : goto attrval_out;
7609 3 : get_sleb128 (sval, readp, readendp);
7610 3 : printf ("%" PRId64 "", sval);
7611 : }
7612 : else
7613 : {
7614 1 : get_uleb128 (val, readp, readendp);
7615 1 : printf ("%" PRIu64 "..", val);
7616 1 : if (readp >= readendp)
7617 : goto attrval_out;
7618 1 : get_uleb128 (val, readp, readendp);
7619 1 : printf ("%" PRIu64 "", val);
7620 : }
7621 : }
7622 : else
7623 : {
7624 0 : print_block (readendp - readp, readp);
7625 0 : break;
7626 : }
7627 8 : if (readp < readendp)
7628 4 : printf (", ");
7629 : }
7630 4 : putchar ('\n');
7631 : }
7632 : else
7633 0 : print_block (block.length, block.data);
7634 : break;
7635 : }
7636 : break;
7637 :
7638 0 : default:
7639 0 : if (cbargs->silent)
7640 : break;
7641 0 : printf (" %*s%-20s (%s) ???\n",
7642 : (int) (level * 2), "", dwarf_attr_name (attr),
7643 : dwarf_form_name (form));
7644 : break;
7645 : }
7646 :
7647 2581704 : return DWARF_CB_OK;
7648 : }
7649 :
7650 : static void
7651 99 : print_debug_units (Dwfl_Module *dwflmod,
7652 : Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
7653 : Elf_Scn *scn, GElf_Shdr *shdr,
7654 : Dwarf *dbg, bool debug_types)
7655 : {
7656 99 : const bool silent = !(print_debug_sections & section_info) && !debug_types;
7657 99 : const char *secname = section_name (ebl, shdr);
7658 :
7659 99 : if (!silent)
7660 64 : printf (gettext ("\
7661 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
7662 64 : elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
7663 :
7664 : /* If the section is empty we don't have to do anything. */
7665 99 : if (!silent && shdr->sh_size == 0)
7666 0 : return;
7667 :
7668 99 : int maxdies = 20;
7669 99 : Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
7670 :
7671 : /* New compilation unit. */
7672 99 : Dwarf_Half version;
7673 :
7674 99 : Dwarf_Die result;
7675 99 : Dwarf_Off abbroffset;
7676 99 : uint8_t addrsize;
7677 99 : uint8_t offsize;
7678 99 : uint64_t unit_id;
7679 99 : Dwarf_Off subdie_off;
7680 :
7681 99 : int unit_res;
7682 99 : Dwarf_CU *cu;
7683 99 : Dwarf_CU cu_mem;
7684 99 : uint8_t unit_type;
7685 99 : Dwarf_Die cudie;
7686 :
7687 : /* We cheat a little because we want to see only the CUs from .debug_info
7688 : or .debug_types. We know the Dwarf_CU struct layout. Set it up at
7689 : the end of .debug_info if we want .debug_types only. Check the returned
7690 : Dwarf_CU is still in the expected section. */
7691 99 : if (debug_types)
7692 : {
7693 1 : cu_mem.dbg = dbg;
7694 1 : cu_mem.end = dbg->sectiondata[IDX_debug_info]->d_size;
7695 1 : cu_mem.sec_idx = IDX_debug_info;
7696 1 : cu = &cu_mem;
7697 : }
7698 : else
7699 98 : cu = NULL;
7700 :
7701 : next_cu:
7702 1270 : unit_res = dwarf_get_units (dbg, cu, &cu, &version, &unit_type,
7703 : &cudie, NULL);
7704 1270 : if (unit_res == 1)
7705 98 : goto do_return;
7706 :
7707 1172 : if (unit_res == -1)
7708 : {
7709 0 : if (!silent)
7710 0 : error (0, 0, gettext ("cannot get next unit: %s"), dwarf_errmsg (-1));
7711 0 : goto do_return;
7712 : }
7713 :
7714 2342 : if (cu->sec_idx != (size_t) (debug_types ? IDX_debug_types : IDX_debug_info))
7715 1 : goto do_return;
7716 :
7717 1171 : dwarf_cu_die (cu, &result, NULL, &abbroffset, &addrsize, &offsize,
7718 : &unit_id, &subdie_off);
7719 :
7720 1171 : if (!silent)
7721 : {
7722 1122 : Dwarf_Off offset = cu->start;
7723 1122 : if (debug_types && version < 5)
7724 2 : {
7725 2 : Dwarf_Die typedie;
7726 2 : Dwarf_Off dieoffset;
7727 2 : dieoffset = dwarf_dieoffset (dwarf_offdie_types (dbg, subdie_off,
7728 : &typedie));
7729 2 : printf (gettext (" Type unit at offset %" PRIu64 ":\n"
7730 : " Version: %" PRIu16
7731 : ", Abbreviation section offset: %" PRIu64
7732 : ", Address size: %" PRIu8
7733 : ", Offset size: %" PRIu8
7734 : "\n Type signature: %#" PRIx64
7735 : ", Type offset: %#" PRIx64 " [%" PRIx64 "]\n"),
7736 : (uint64_t) offset, version, abbroffset, addrsize, offsize,
7737 : unit_id, (uint64_t) subdie_off, dieoffset);
7738 : }
7739 : else
7740 : {
7741 1120 : printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
7742 : " Version: %" PRIu16
7743 : ", Abbreviation section offset: %" PRIu64
7744 : ", Address size: %" PRIu8
7745 : ", Offset size: %" PRIu8 "\n"),
7746 : (uint64_t) offset, version, abbroffset, addrsize, offsize);
7747 :
7748 1120 : if (version >= 5 || (unit_type != DW_UT_compile
7749 1115 : && unit_type != DW_UT_partial))
7750 : {
7751 6 : printf (gettext (" Unit type: %s (%" PRIu8 ")"),
7752 : dwarf_unit_name (unit_type), unit_type);
7753 12 : if (unit_type == DW_UT_type
7754 6 : || unit_type == DW_UT_skeleton
7755 1 : || unit_type == DW_UT_split_compile
7756 1 : || unit_type == DW_UT_split_type)
7757 5 : printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
7758 12 : if (unit_type == DW_UT_type
7759 6 : || unit_type == DW_UT_split_type)
7760 : {
7761 0 : Dwarf_Die typedie;
7762 0 : Dwarf_Off dieoffset;
7763 0 : dwarf_cu_info (cu, NULL, NULL, NULL, &typedie,
7764 : NULL, NULL, NULL);
7765 0 : dieoffset = dwarf_dieoffset (&typedie);
7766 0 : printf (", Unit DIE off: %#" PRIx64 " [%" PRIx64 "]",
7767 : subdie_off, dieoffset);
7768 : }
7769 6 : printf ("\n");
7770 : }
7771 : }
7772 : }
7773 :
7774 1171 : if (version < 2 || version > 5
7775 1171 : || unit_type < DW_UT_compile || unit_type > DW_UT_split_type)
7776 : {
7777 0 : if (!silent)
7778 0 : error (0, 0, gettext ("unknown version (%d) or unit type (%d)"),
7779 : version, unit_type);
7780 0 : goto next_cu;
7781 : }
7782 :
7783 1171 : struct attrcb_args args =
7784 : {
7785 : .dwflmod = dwflmod,
7786 : .silent = silent,
7787 : .version = version,
7788 : .addrsize = addrsize,
7789 : .offset_size = offsize
7790 : };
7791 :
7792 1171 : bool is_split = false;
7793 1171 : int level = 0;
7794 1171 : dies[0] = cudie;
7795 1171 : args.cu = dies[0].cu;
7796 1171 : args.dbg = dbg;
7797 1171 : args.is_split = is_split;
7798 :
7799 : /* We might return here again for the split CU subdie. */
7800 718129 : do_cu:
7801 719304 : do
7802 : {
7803 719304 : Dwarf_Off offset = dwarf_dieoffset (&dies[level]);
7804 719304 : if (unlikely (offset == (Dwarf_Off) -1))
7805 : {
7806 0 : if (!silent)
7807 0 : error (0, 0, gettext ("cannot get DIE offset: %s"),
7808 : dwarf_errmsg (-1));
7809 0 : goto do_return;
7810 : }
7811 :
7812 719304 : int tag = dwarf_tag (&dies[level]);
7813 719304 : if (unlikely (tag == DW_TAG_invalid))
7814 : {
7815 0 : if (!silent)
7816 0 : error (0, 0, gettext ("cannot get tag of DIE at offset [%" PRIx64
7817 : "] in section '%s': %s"),
7818 : (uint64_t) offset, secname, dwarf_errmsg (-1));
7819 0 : goto do_return;
7820 : }
7821 :
7822 719304 : if (!silent)
7823 : {
7824 718316 : unsigned int code = dwarf_getabbrevcode (dies[level].abbrev);
7825 718316 : if (is_split)
7826 48 : printf (" {%6" PRIx64 "} ", (uint64_t) offset);
7827 : else
7828 718268 : printf (" [%6" PRIx64 "] ", (uint64_t) offset);
7829 718316 : printf ("%*s%-20s abbrev: %u\n", (int) (level * 2), "",
7830 : dwarf_tag_name (tag), code);
7831 : }
7832 :
7833 : /* Print the attribute values. */
7834 719304 : args.level = level;
7835 719304 : args.dies = dies;
7836 719304 : (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
7837 :
7838 : /* Make room for the next level's DIE. */
7839 719304 : if (level + 1 == maxdies)
7840 0 : dies = (Dwarf_Die *) xrealloc (dies,
7841 0 : (maxdies += 10)
7842 : * sizeof (Dwarf_Die));
7843 :
7844 719304 : int res = dwarf_child (&dies[level], &dies[level + 1]);
7845 719304 : if (res > 0)
7846 : {
7847 719304 : while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
7848 102905 : if (level-- == 0)
7849 : break;
7850 :
7851 617574 : if (unlikely (res == -1))
7852 : {
7853 0 : if (!silent)
7854 0 : error (0, 0, gettext ("cannot get next DIE: %s\n"),
7855 : dwarf_errmsg (-1));
7856 0 : goto do_return;
7857 : }
7858 : }
7859 101730 : else if (unlikely (res < 0))
7860 : {
7861 0 : if (!silent)
7862 0 : error (0, 0, gettext ("cannot get next DIE: %s"),
7863 : dwarf_errmsg (-1));
7864 0 : goto do_return;
7865 : }
7866 : else
7867 : ++level;
7868 : }
7869 719304 : while (level >= 0);
7870 :
7871 : /* We might want to show the split compile unit if this was a skeleton.
7872 : We need to scan it if we are requesting printing .debug_ranges for
7873 : DWARF4 since GNU DebugFission uses "offsets" into the main ranges
7874 : section. */
7875 1175 : if (unit_type == DW_UT_skeleton
7876 13 : && ((!silent && show_split_units)
7877 10 : || (version < 5 && (print_debug_sections & section_ranges) != 0)))
7878 : {
7879 5 : Dwarf_Die subdie;
7880 5 : if (dwarf_cu_info (cu, NULL, NULL, NULL, &subdie, NULL, NULL, NULL) != 0
7881 5 : || dwarf_tag (&subdie) == DW_TAG_invalid)
7882 : {
7883 1 : if (!silent)
7884 : {
7885 1 : Dwarf_Attribute dwo_at;
7886 2 : const char *dwo_name =
7887 1 : (dwarf_formstring (dwarf_attr (&cudie, DW_AT_dwo_name,
7888 : &dwo_at))
7889 1 : ?: (dwarf_formstring (dwarf_attr (&cudie, DW_AT_GNU_dwo_name,
7890 : &dwo_at))
7891 0 : ?: "<unknown>"));
7892 1 : fprintf (stderr,
7893 : "Could not find split unit '%s', id: %" PRIx64 "\n",
7894 : dwo_name, unit_id);
7895 : }
7896 : }
7897 : else
7898 : {
7899 4 : Dwarf_CU *split_cu = subdie.cu;
7900 4 : dwarf_cu_die (split_cu, &result, NULL, &abbroffset,
7901 : &addrsize, &offsize, &unit_id, &subdie_off);
7902 4 : Dwarf_Off offset = cu->start;
7903 :
7904 4 : if (!silent)
7905 : {
7906 2 : printf (gettext (" Split compilation unit at offset %"
7907 : PRIu64 ":\n"
7908 : " Version: %" PRIu16
7909 : ", Abbreviation section offset: %" PRIu64
7910 : ", Address size: %" PRIu8
7911 : ", Offset size: %" PRIu8 "\n"),
7912 : (uint64_t) offset, version, abbroffset,
7913 : addrsize, offsize);
7914 2 : printf (gettext (" Unit type: %s (%" PRIu8 ")"),
7915 : dwarf_unit_name (unit_type), unit_type);
7916 2 : printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
7917 2 : printf ("\n");
7918 : }
7919 :
7920 4 : unit_type = DW_UT_split_compile;
7921 4 : is_split = true;
7922 4 : level = 0;
7923 4 : dies[0] = subdie;
7924 4 : args.cu = dies[0].cu;
7925 4 : args.dbg = split_cu->dbg;
7926 4 : args.is_split = is_split;
7927 4 : goto do_cu;
7928 : }
7929 : }
7930 :
7931 : /* And again... */
7932 1171 : goto next_cu;
7933 :
7934 99 : do_return:
7935 99 : free (dies);
7936 : }
7937 :
7938 : static void
7939 19 : print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
7940 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7941 : {
7942 19 : print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
7943 19 : }
7944 :
7945 : static void
7946 1 : print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
7947 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7948 : {
7949 1 : print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
7950 1 : }
7951 :
7952 :
7953 : static void
7954 0 : print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
7955 : GElf_Ehdr *ehdr __attribute__ ((unused)),
7956 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7957 : {
7958 0 : printf (gettext ("\
7959 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n\n"),
7960 : elf_ndxscn (scn), section_name (ebl, shdr),
7961 0 : (uint64_t) shdr->sh_offset);
7962 :
7963 0 : size_t address_size
7964 0 : = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
7965 :
7966 0 : Dwarf_Lines *lines;
7967 0 : size_t nlines;
7968 0 : Dwarf_Off off, next_off = 0;
7969 0 : Dwarf_CU *cu = NULL;
7970 0 : while (dwarf_next_lines (dbg, off = next_off, &next_off, &cu, NULL, NULL,
7971 : &lines, &nlines) == 0)
7972 : {
7973 0 : Dwarf_Die cudie;
7974 0 : if (cu != NULL && dwarf_cu_info (cu, NULL, NULL, &cudie,
7975 : NULL, NULL, NULL, NULL) == 0)
7976 0 : printf (" CU [%" PRIx64 "] %s\n",
7977 : dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
7978 : else
7979 : {
7980 : /* DWARF5 lines can be independent of any CU, but they probably
7981 : are used by some CU. Determine the CU this block is for. */
7982 0 : Dwarf_Off cuoffset;
7983 0 : Dwarf_Off ncuoffset = 0;
7984 0 : size_t hsize;
7985 0 : while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
7986 : NULL, NULL, NULL) == 0)
7987 : {
7988 0 : if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
7989 0 : continue;
7990 0 : Dwarf_Attribute stmt_list;
7991 0 : if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
7992 0 : continue;
7993 0 : Dwarf_Word lineoff;
7994 0 : if (dwarf_formudata (&stmt_list, &lineoff) != 0)
7995 0 : continue;
7996 0 : if (lineoff == off)
7997 : {
7998 : /* Found the CU. */
7999 0 : cu = cudie.cu;
8000 0 : break;
8001 : }
8002 : }
8003 :
8004 0 : if (cu != NULL)
8005 0 : printf (" CU [%" PRIx64 "] %s\n",
8006 : dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
8007 : else
8008 0 : printf (" No CU\n");
8009 : }
8010 :
8011 0 : printf (" line:col SBPE* disc isa op address"
8012 : " (Statement Block Prologue Epilogue *End)\n");
8013 0 : const char *last_file = "";
8014 0 : for (size_t n = 0; n < nlines; n++)
8015 : {
8016 0 : Dwarf_Line *line = dwarf_onesrcline (lines, n);
8017 0 : if (line == NULL)
8018 : {
8019 0 : printf (" dwarf_onesrcline: %s\n", dwarf_errmsg (-1));
8020 0 : continue;
8021 : }
8022 0 : Dwarf_Word mtime, length;
8023 0 : const char *file = dwarf_linesrc (line, &mtime, &length);
8024 0 : if (file == NULL)
8025 : {
8026 0 : printf (" <%s> (mtime: ?, length: ?)\n", dwarf_errmsg (-1));
8027 0 : last_file = "";
8028 : }
8029 0 : else if (strcmp (last_file, file) != 0)
8030 : {
8031 0 : printf (" %s (mtime: %" PRIu64 ", length: %" PRIu64 ")\n",
8032 : file, mtime, length);
8033 0 : last_file = file;
8034 : }
8035 :
8036 0 : int lineno, colno;
8037 0 : bool statement, endseq, block, prologue_end, epilogue_begin;
8038 0 : unsigned int lineop, isa, disc;
8039 0 : Dwarf_Addr address;
8040 0 : dwarf_lineaddr (line, &address);
8041 0 : dwarf_lineno (line, &lineno);
8042 0 : dwarf_linecol (line, &colno);
8043 0 : dwarf_lineop_index (line, &lineop);
8044 0 : dwarf_linebeginstatement (line, &statement);
8045 0 : dwarf_lineendsequence (line, &endseq);
8046 0 : dwarf_lineblock (line, &block);
8047 0 : dwarf_lineprologueend (line, &prologue_end);
8048 0 : dwarf_lineepiloguebegin (line, &epilogue_begin);
8049 0 : dwarf_lineisa (line, &isa);
8050 0 : dwarf_linediscriminator (line, &disc);
8051 :
8052 : /* End sequence is special, it is one byte past. */
8053 0 : printf (" %4d:%-3d %c%c%c%c%c %4d %3d %2d ",
8054 : lineno, colno,
8055 0 : (statement ? 'S' : ' '),
8056 0 : (block ? 'B' : ' '),
8057 0 : (prologue_end ? 'P' : ' '),
8058 0 : (epilogue_begin ? 'E' : ' '),
8059 0 : (endseq ? '*' : ' '),
8060 : disc, isa, lineop);
8061 0 : print_dwarf_addr (dwflmod, address_size,
8062 0 : address - (endseq ? 1 : 0), address);
8063 0 : printf ("\n");
8064 :
8065 0 : if (endseq)
8066 0 : printf("\n");
8067 : }
8068 : }
8069 0 : }
8070 :
8071 :
8072 : /* Print the value of a form.
8073 : Returns new value of readp, or readendp on failure. */
8074 : static const unsigned char *
8075 20 : print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
8076 : const unsigned char *readendp, unsigned int offset_len,
8077 : Dwarf_Off str_offsets_base)
8078 : {
8079 20 : Dwarf_Word val;
8080 20 : unsigned char *endp;
8081 20 : Elf_Data *data;
8082 20 : char *str;
8083 20 : switch (form)
8084 : {
8085 8 : case DW_FORM_data1:
8086 8 : if (readendp - readp < 1)
8087 : {
8088 0 : invalid_data:
8089 0 : error (0, 0, "invalid data");
8090 0 : return readendp;
8091 : }
8092 8 : val = *readp++;
8093 8 : printf (" %" PRIx8, (unsigned int) val);
8094 : break;
8095 :
8096 0 : case DW_FORM_data2:
8097 0 : if (readendp - readp < 2)
8098 : goto invalid_data;
8099 0 : val = read_2ubyte_unaligned_inc (dbg, readp);
8100 0 : printf(" %" PRIx16, (unsigned int) val);
8101 : break;
8102 :
8103 0 : case DW_FORM_data4:
8104 0 : if (readendp - readp < 4)
8105 : goto invalid_data;
8106 0 : val = read_4ubyte_unaligned_inc (dbg, readp);
8107 0 : printf (" %" PRIx32, (unsigned int) val);
8108 : break;
8109 :
8110 0 : case DW_FORM_data8:
8111 0 : if (readendp - readp < 8)
8112 : goto invalid_data;
8113 0 : val = read_8ubyte_unaligned_inc (dbg, readp);
8114 0 : printf (" %" PRIx64, val);
8115 : break;
8116 :
8117 0 : case DW_FORM_sdata:
8118 0 : if (readendp - readp < 1)
8119 : goto invalid_data;
8120 0 : get_sleb128 (val, readp, readendp);
8121 0 : printf (" %" PRIx64, val);
8122 : break;
8123 :
8124 0 : case DW_FORM_udata:
8125 0 : if (readendp - readp < 1)
8126 : goto invalid_data;
8127 0 : get_uleb128 (val, readp, readendp);
8128 0 : printf (" %" PRIx64, val);
8129 : break;
8130 :
8131 0 : case DW_FORM_block:
8132 0 : if (readendp - readp < 1)
8133 : goto invalid_data;
8134 0 : get_uleb128 (val, readp, readendp);
8135 0 : if ((size_t) (readendp - readp) < val)
8136 : goto invalid_data;
8137 0 : print_bytes (val, readp);
8138 0 : readp += val;
8139 0 : break;
8140 :
8141 0 : case DW_FORM_block1:
8142 0 : if (readendp - readp < 1)
8143 : goto invalid_data;
8144 0 : val = *readp++;
8145 0 : if ((size_t) (readendp - readp) < val)
8146 : goto invalid_data;
8147 0 : print_bytes (val, readp);
8148 0 : readp += val;
8149 0 : break;
8150 :
8151 0 : case DW_FORM_block2:
8152 0 : if (readendp - readp < 2)
8153 : goto invalid_data;
8154 0 : val = read_2ubyte_unaligned_inc (dbg, readp);
8155 0 : if ((size_t) (readendp - readp) < val)
8156 : goto invalid_data;
8157 0 : print_bytes (val, readp);
8158 0 : readp += val;
8159 0 : break;
8160 :
8161 0 : case DW_FORM_block4:
8162 0 : if (readendp - readp < 4)
8163 : goto invalid_data;
8164 0 : val = read_4ubyte_unaligned_inc (dbg, readp);
8165 0 : if ((size_t) (readendp - readp) < val)
8166 : goto invalid_data;
8167 0 : print_bytes (val, readp);
8168 0 : readp += val;
8169 0 : break;
8170 :
8171 0 : case DW_FORM_data16:
8172 0 : if (readendp - readp < 16)
8173 : goto invalid_data;
8174 0 : print_bytes (16, readp);
8175 0 : readp += 16;
8176 0 : break;
8177 :
8178 0 : case DW_FORM_flag:
8179 0 : if (readendp - readp < 1)
8180 : goto invalid_data;
8181 0 : val = *readp++;
8182 0 : printf ("%s", val != 0 ? yes_str : no_str);
8183 : break;
8184 :
8185 0 : case DW_FORM_string:
8186 0 : endp = memchr (readp, '\0', readendp - readp);
8187 0 : if (endp == NULL)
8188 : goto invalid_data;
8189 0 : printf ("%s", readp);
8190 0 : readp = endp + 1;
8191 0 : break;
8192 :
8193 12 : case DW_FORM_strp:
8194 : case DW_FORM_line_strp:
8195 : case DW_FORM_strp_sup:
8196 12 : if ((size_t) (readendp - readp) < offset_len)
8197 : goto invalid_data;
8198 12 : if (offset_len == 8)
8199 0 : val = read_8ubyte_unaligned_inc (dbg, readp);
8200 : else
8201 12 : val = read_4ubyte_unaligned_inc (dbg, readp);
8202 12 : if (form == DW_FORM_strp)
8203 0 : data = dbg->sectiondata[IDX_debug_str];
8204 12 : else if (form == DW_FORM_line_strp)
8205 12 : data = dbg->sectiondata[IDX_debug_line_str];
8206 : else /* form == DW_FORM_strp_sup */
8207 : {
8208 0 : Dwarf *alt = dwarf_getalt (dbg);
8209 0 : data = alt != NULL ? alt->sectiondata[IDX_debug_str] : NULL;
8210 : }
8211 12 : if (data == NULL || val >= data->d_size
8212 12 : || memchr (data->d_buf + val, '\0', data->d_size - val) == NULL)
8213 : str = "???";
8214 : else
8215 12 : str = (char *) data->d_buf + val;
8216 12 : printf ("%s (%" PRIu64 ")", str, val);
8217 : break;
8218 :
8219 0 : case DW_FORM_sec_offset:
8220 0 : if ((size_t) (readendp - readp) < offset_len)
8221 : goto invalid_data;
8222 0 : if (offset_len == 8)
8223 0 : val = read_8ubyte_unaligned_inc (dbg, readp);
8224 : else
8225 0 : val = read_4ubyte_unaligned_inc (dbg, readp);
8226 0 : printf ("[%" PRIx64 "]", val);
8227 : break;
8228 :
8229 0 : case DW_FORM_strx:
8230 : case DW_FORM_GNU_str_index:
8231 0 : if (readendp - readp < 1)
8232 : goto invalid_data;
8233 0 : get_uleb128 (val, readp, readendp);
8234 0 : strx_val:
8235 0 : data = dbg->sectiondata[IDX_debug_str_offsets];
8236 0 : if (data == NULL
8237 0 : || data->d_size - str_offsets_base < val)
8238 : str = "???";
8239 : else
8240 : {
8241 0 : const unsigned char *strreadp = data->d_buf + str_offsets_base + val;
8242 0 : const unsigned char *strreadendp = data->d_buf + data->d_size;
8243 0 : if ((size_t) (strreadendp - strreadp) < offset_len)
8244 : str = "???";
8245 : else
8246 : {
8247 0 : Dwarf_Off idx;
8248 0 : if (offset_len == 8)
8249 0 : idx = read_8ubyte_unaligned (dbg, strreadp);
8250 : else
8251 0 : idx = read_4ubyte_unaligned (dbg, strreadp);
8252 :
8253 0 : data = dbg->sectiondata[IDX_debug_str];
8254 0 : if (data == NULL || idx >= data->d_size
8255 0 : || memchr (data->d_buf + idx, '\0',
8256 : data->d_size - idx) == NULL)
8257 : str = "???";
8258 : else
8259 0 : str = (char *) data->d_buf + idx;
8260 : }
8261 : }
8262 0 : printf ("%s (%" PRIu64 ")", str, val);
8263 : break;
8264 :
8265 0 : case DW_FORM_strx1:
8266 0 : if (readendp - readp < 1)
8267 : goto invalid_data;
8268 0 : val = *readp++;
8269 0 : goto strx_val;
8270 :
8271 0 : case DW_FORM_strx2:
8272 0 : if (readendp - readp < 2)
8273 : goto invalid_data;
8274 0 : val = read_2ubyte_unaligned_inc (dbg, readp);
8275 0 : goto strx_val;
8276 :
8277 0 : case DW_FORM_strx3:
8278 0 : if (readendp - readp < 3)
8279 : goto invalid_data;
8280 0 : val = read_3ubyte_unaligned_inc (dbg, readp);
8281 0 : goto strx_val;
8282 :
8283 0 : case DW_FORM_strx4:
8284 0 : if (readendp - readp < 4)
8285 : goto invalid_data;
8286 0 : val = read_4ubyte_unaligned_inc (dbg, readp);
8287 0 : goto strx_val;
8288 :
8289 0 : default:
8290 0 : error (0, 0, gettext ("unknown form: %s"), dwarf_form_name (form));
8291 0 : return readendp;
8292 : }
8293 :
8294 20 : return readp;
8295 : }
8296 :
8297 : static void
8298 52 : print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
8299 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
8300 : {
8301 52 : if (decodedline)
8302 : {
8303 4 : print_decoded_line_section (dwflmod, ebl, ehdr, scn, shdr, dbg);
8304 4 : return;
8305 : }
8306 :
8307 48 : printf (gettext ("\
8308 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
8309 : elf_ndxscn (scn), section_name (ebl, shdr),
8310 48 : (uint64_t) shdr->sh_offset);
8311 :
8312 48 : if (shdr->sh_size == 0)
8313 : return;
8314 :
8315 : /* There is no functionality in libdw to read the information in the
8316 : way it is represented here. Hardcode the decoder. */
8317 96 : Elf_Data *data = (dbg->sectiondata[IDX_debug_line]
8318 48 : ?: elf_rawdata (scn, NULL));
8319 48 : if (unlikely (data == NULL))
8320 : {
8321 0 : error (0, 0, gettext ("cannot get line data section data: %s"),
8322 : elf_errmsg (-1));
8323 0 : return;
8324 : }
8325 :
8326 48 : const unsigned char *linep = (const unsigned char *) data->d_buf;
8327 48 : const unsigned char *lineendp;
8328 :
8329 48 : while (linep
8330 1153 : < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
8331 : {
8332 1105 : size_t start_offset = linep - (const unsigned char *) data->d_buf;
8333 :
8334 1105 : printf (gettext ("\nTable at offset %zu:\n"), start_offset);
8335 :
8336 1105 : if (unlikely (linep + 4 > lineendp))
8337 : goto invalid_data;
8338 1105 : Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
8339 1105 : unsigned int length = 4;
8340 1105 : if (unlikely (unit_length == 0xffffffff))
8341 : {
8342 0 : if (unlikely (linep + 8 > lineendp))
8343 : {
8344 0 : invalid_data:
8345 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
8346 : elf_ndxscn (scn), section_name (ebl, shdr));
8347 0 : return;
8348 : }
8349 0 : unit_length = read_8ubyte_unaligned_inc (dbg, linep);
8350 0 : length = 8;
8351 : }
8352 :
8353 : /* Check whether we have enough room in the section. */
8354 1105 : if (unlikely (unit_length > (size_t) (lineendp - linep)))
8355 : goto invalid_data;
8356 1105 : lineendp = linep + unit_length;
8357 :
8358 : /* The next element of the header is the version identifier. */
8359 1105 : if ((size_t) (lineendp - linep) < 2)
8360 : goto invalid_data;
8361 1105 : uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
8362 :
8363 2210 : size_t address_size
8364 1105 : = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
8365 1105 : unsigned char segment_selector_size = 0;
8366 1105 : if (version > 4)
8367 : {
8368 2 : if ((size_t) (lineendp - linep) < 2)
8369 : goto invalid_data;
8370 2 : address_size = *linep++;
8371 2 : segment_selector_size = *linep++;
8372 : }
8373 :
8374 : /* Next comes the header length. */
8375 1105 : Dwarf_Word header_length;
8376 1105 : if (length == 4)
8377 : {
8378 1105 : if ((size_t) (lineendp - linep) < 4)
8379 : goto invalid_data;
8380 1105 : header_length = read_4ubyte_unaligned_inc (dbg, linep);
8381 : }
8382 : else
8383 : {
8384 0 : if ((size_t) (lineendp - linep) < 8)
8385 : goto invalid_data;
8386 0 : header_length = read_8ubyte_unaligned_inc (dbg, linep);
8387 : }
8388 :
8389 : /* Next the minimum instruction length. */
8390 1105 : if ((size_t) (lineendp - linep) < 1)
8391 : goto invalid_data;
8392 1105 : uint_fast8_t minimum_instr_len = *linep++;
8393 :
8394 : /* Next the maximum operations per instruction, in version 4 format. */
8395 1105 : uint_fast8_t max_ops_per_instr;
8396 1105 : if (version < 4)
8397 : max_ops_per_instr = 1;
8398 : else
8399 : {
8400 10 : if ((size_t) (lineendp - linep) < 1)
8401 : goto invalid_data;
8402 10 : max_ops_per_instr = *linep++;
8403 : }
8404 :
8405 : /* We need at least 4 more bytes. */
8406 1105 : if ((size_t) (lineendp - linep) < 4)
8407 : goto invalid_data;
8408 :
8409 : /* Then the flag determining the default value of the is_stmt
8410 : register. */
8411 1105 : uint_fast8_t default_is_stmt = *linep++;
8412 :
8413 : /* Now the line base. */
8414 1105 : int_fast8_t line_base = *linep++;
8415 :
8416 : /* And the line range. */
8417 1105 : uint_fast8_t line_range = *linep++;
8418 :
8419 : /* The opcode base. */
8420 1105 : uint_fast8_t opcode_base = *linep++;
8421 :
8422 : /* Print what we got so far. */
8423 1105 : printf (gettext ("\n"
8424 : " Length: %" PRIu64 "\n"
8425 : " DWARF version: %" PRIuFAST16 "\n"
8426 : " Prologue length: %" PRIu64 "\n"
8427 : " Address size: %zd\n"
8428 : " Segment selector size: %zd\n"
8429 : " Min instruction length: %" PRIuFAST8 "\n"
8430 : " Max operations per instruction: %" PRIuFAST8 "\n"
8431 : " Initial value if 'is_stmt': %" PRIuFAST8 "\n"
8432 : " Line base: %" PRIdFAST8 "\n"
8433 : " Line range: %" PRIuFAST8 "\n"
8434 : " Opcode base: %" PRIuFAST8 "\n"
8435 : "\n"
8436 : "Opcodes:\n"),
8437 : (uint64_t) unit_length, version, (uint64_t) header_length,
8438 : address_size, (size_t) segment_selector_size,
8439 : minimum_instr_len, max_ops_per_instr,
8440 : default_is_stmt, line_base,
8441 : line_range, opcode_base);
8442 :
8443 1105 : if (version < 2 || version > 5)
8444 : {
8445 0 : error (0, 0, gettext ("cannot handle .debug_line version: %u\n"),
8446 : (unsigned int) version);
8447 0 : linep = lineendp;
8448 0 : continue;
8449 : }
8450 :
8451 1105 : if (address_size != 4 && address_size != 8)
8452 : {
8453 0 : error (0, 0, gettext ("cannot handle address size: %u\n"),
8454 : (unsigned int) address_size);
8455 0 : linep = lineendp;
8456 0 : continue;
8457 : }
8458 :
8459 1105 : if (segment_selector_size != 0)
8460 : {
8461 0 : error (0, 0, gettext ("cannot handle segment selector size: %u\n"),
8462 : (unsigned int) segment_selector_size);
8463 0 : linep = lineendp;
8464 0 : continue;
8465 : }
8466 :
8467 1105 : if (unlikely (linep + opcode_base - 1 >= lineendp))
8468 : {
8469 0 : invalid_unit:
8470 0 : error (0, 0,
8471 0 : gettext ("invalid data at offset %tu in section [%zu] '%s'"),
8472 0 : linep - (const unsigned char *) data->d_buf,
8473 : elf_ndxscn (scn), section_name (ebl, shdr));
8474 0 : linep = lineendp;
8475 0 : continue;
8476 : }
8477 1105 : int opcode_base_l10 = 1;
8478 1105 : unsigned int tmp = opcode_base;
8479 2208 : while (tmp > 10)
8480 : {
8481 1103 : tmp /= 10;
8482 1103 : ++opcode_base_l10;
8483 : }
8484 1105 : const uint8_t *standard_opcode_lengths = linep - 1;
8485 14359 : for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
8486 13254 : printf (ngettext (" [%*" PRIuFAST8 "] %hhu argument\n",
8487 : " [%*" PRIuFAST8 "] %hhu arguments\n",
8488 : (int) linep[cnt - 1]),
8489 13254 : opcode_base_l10, cnt, linep[cnt - 1]);
8490 1105 : linep += opcode_base - 1;
8491 :
8492 1105 : if (unlikely (linep >= lineendp))
8493 : goto invalid_unit;
8494 :
8495 1105 : Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, NULL);
8496 :
8497 1105 : puts (gettext ("\nDirectory table:"));
8498 1105 : if (version > 4)
8499 : {
8500 2 : struct encpair { uint16_t desc; uint16_t form; };
8501 2 : struct encpair enc[256];
8502 :
8503 2 : printf (gettext (" ["));
8504 2 : if ((size_t) (lineendp - linep) < 1)
8505 0 : goto invalid_data;
8506 2 : unsigned char directory_entry_format_count = *linep++;
8507 4 : for (int i = 0; i < directory_entry_format_count; i++)
8508 : {
8509 2 : uint16_t desc, form;
8510 2 : if ((size_t) (lineendp - linep) < 1)
8511 : goto invalid_data;
8512 2 : get_uleb128 (desc, linep, lineendp);
8513 2 : if ((size_t) (lineendp - linep) < 1)
8514 : goto invalid_data;
8515 2 : get_uleb128 (form, linep, lineendp);
8516 :
8517 2 : enc[i].desc = desc;
8518 2 : enc[i].form = form;
8519 :
8520 2 : printf ("%s(%s)",
8521 : dwarf_line_content_description_name (desc),
8522 : dwarf_form_name (form));
8523 2 : if (i + 1 < directory_entry_format_count)
8524 0 : printf (", ");
8525 : }
8526 2 : printf ("]\n");
8527 :
8528 2 : uint64_t directories_count;
8529 2 : if ((size_t) (lineendp - linep) < 1)
8530 : goto invalid_data;
8531 2 : get_uleb128 (directories_count, linep, lineendp);
8532 :
8533 4 : if (directory_entry_format_count == 0
8534 2 : && directories_count != 0)
8535 : goto invalid_data;
8536 :
8537 6 : for (uint64_t i = 0; i < directories_count; i++)
8538 : {
8539 4 : printf (" %-5" PRIu64 " ", i);
8540 8 : for (int j = 0; j < directory_entry_format_count; j++)
8541 : {
8542 4 : linep = print_form_data (dbg, enc[j].form,
8543 : linep, lineendp, length,
8544 : str_offsets_base);
8545 4 : if (j + 1 < directory_entry_format_count)
8546 0 : printf (", ");
8547 : }
8548 4 : printf ("\n");
8549 4 : if (linep >= lineendp)
8550 0 : goto invalid_unit;
8551 : }
8552 : }
8553 : else
8554 : {
8555 8399 : while (linep < lineendp && *linep != 0)
8556 : {
8557 7296 : unsigned char *endp = memchr (linep, '\0', lineendp - linep);
8558 7296 : if (unlikely (endp == NULL))
8559 : goto invalid_unit;
8560 :
8561 7296 : printf (" %s\n", (char *) linep);
8562 :
8563 7296 : linep = endp + 1;
8564 : }
8565 1103 : if (linep >= lineendp || *linep != 0)
8566 : goto invalid_unit;
8567 : /* Skip the final NUL byte. */
8568 1103 : ++linep;
8569 : }
8570 :
8571 1105 : if (unlikely (linep >= lineendp))
8572 : goto invalid_unit;
8573 :
8574 1105 : puts (gettext ("\nFile name table:"));
8575 1105 : if (version > 4)
8576 : {
8577 2 : struct encpair { uint16_t desc; uint16_t form; };
8578 2 : struct encpair enc[256];
8579 :
8580 2 : printf (gettext (" ["));
8581 2 : if ((size_t) (lineendp - linep) < 1)
8582 0 : goto invalid_data;
8583 2 : unsigned char file_name_format_count = *linep++;
8584 6 : for (int i = 0; i < file_name_format_count; i++)
8585 : {
8586 4 : uint64_t desc, form;
8587 4 : if ((size_t) (lineendp - linep) < 1)
8588 : goto invalid_data;
8589 4 : get_uleb128 (desc, linep, lineendp);
8590 4 : if ((size_t) (lineendp - linep) < 1)
8591 : goto invalid_data;
8592 4 : get_uleb128 (form, linep, lineendp);
8593 :
8594 4 : if (! libdw_valid_user_form (form))
8595 : goto invalid_data;
8596 :
8597 4 : enc[i].desc = desc;
8598 4 : enc[i].form = form;
8599 :
8600 4 : printf ("%s(%s)",
8601 : dwarf_line_content_description_name (desc),
8602 : dwarf_form_name (form));
8603 4 : if (i + 1 < file_name_format_count)
8604 2 : printf (", ");
8605 : }
8606 2 : printf ("]\n");
8607 :
8608 2 : uint64_t file_name_count;
8609 2 : if ((size_t) (lineendp - linep) < 1)
8610 : goto invalid_data;
8611 2 : get_uleb128 (file_name_count, linep, lineendp);
8612 :
8613 4 : if (file_name_format_count == 0
8614 2 : && file_name_count != 0)
8615 : goto invalid_data;
8616 :
8617 10 : for (uint64_t i = 0; i < file_name_count; i++)
8618 : {
8619 8 : printf (" %-5" PRIu64 " ", i);
8620 24 : for (int j = 0; j < file_name_format_count; j++)
8621 : {
8622 16 : linep = print_form_data (dbg, enc[j].form,
8623 : linep, lineendp, length,
8624 : str_offsets_base);
8625 16 : if (j + 1 < file_name_format_count)
8626 8 : printf (", ");
8627 : }
8628 8 : printf ("\n");
8629 8 : if (linep >= lineendp)
8630 0 : goto invalid_unit;
8631 : }
8632 : }
8633 : else
8634 : {
8635 1103 : puts (gettext (" Entry Dir Time Size Name"));
8636 23173 : for (unsigned int cnt = 1; linep < lineendp && *linep != 0; ++cnt)
8637 : {
8638 : /* First comes the file name. */
8639 22070 : char *fname = (char *) linep;
8640 22070 : unsigned char *endp = memchr (fname, '\0', lineendp - linep);
8641 22070 : if (unlikely (endp == NULL))
8642 : goto invalid_unit;
8643 22070 : linep = endp + 1;
8644 :
8645 : /* Then the index. */
8646 22070 : unsigned int diridx;
8647 22070 : if (lineendp - linep < 1)
8648 : goto invalid_unit;
8649 22070 : get_uleb128 (diridx, linep, lineendp);
8650 :
8651 : /* Next comes the modification time. */
8652 22070 : unsigned int mtime;
8653 22070 : if (lineendp - linep < 1)
8654 : goto invalid_unit;
8655 22070 : get_uleb128 (mtime, linep, lineendp);
8656 :
8657 : /* Finally the length of the file. */
8658 22070 : unsigned int fsize;
8659 22070 : if (lineendp - linep < 1)
8660 : goto invalid_unit;
8661 22070 : get_uleb128 (fsize, linep, lineendp);
8662 :
8663 22070 : printf (" %-5u %-5u %-9u %-9u %s\n",
8664 : cnt, diridx, mtime, fsize, fname);
8665 : }
8666 1103 : if (linep >= lineendp || *linep != '\0')
8667 : goto invalid_unit;
8668 : /* Skip the final NUL byte. */
8669 1103 : ++linep;
8670 : }
8671 :
8672 1105 : puts (gettext ("\nLine number statements:"));
8673 1105 : Dwarf_Word address = 0;
8674 1105 : unsigned int op_index = 0;
8675 1105 : size_t line = 1;
8676 1105 : uint_fast8_t is_stmt = default_is_stmt;
8677 :
8678 : /* Apply the "operation advance" from a special opcode
8679 : or DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */
8680 1105 : unsigned int op_addr_advance;
8681 1105 : bool show_op_index;
8682 1105 : inline void advance_pc (unsigned int op_advance)
8683 : {
8684 512588 : op_addr_advance = minimum_instr_len * ((op_index + op_advance)
8685 256294 : / max_ops_per_instr);
8686 256294 : address += op_addr_advance;
8687 768882 : show_op_index = (op_index > 0 ||
8688 256294 : (op_index + op_advance) % max_ops_per_instr > 0);
8689 256294 : op_index = (op_index + op_advance) % max_ops_per_instr;
8690 : }
8691 :
8692 1105 : if (max_ops_per_instr == 0)
8693 : {
8694 0 : error (0, 0,
8695 0 : gettext ("invalid maximum operations per instruction is zero"));
8696 0 : linep = lineendp;
8697 0 : continue;
8698 : }
8699 :
8700 810340 : while (linep < lineendp)
8701 : {
8702 809235 : size_t offset = linep - (const unsigned char *) data->d_buf;
8703 809235 : unsigned int u128;
8704 809235 : int s128;
8705 :
8706 : /* Read the opcode. */
8707 809235 : unsigned int opcode = *linep++;
8708 :
8709 809235 : printf (" [%6" PRIx64 "]", (uint64_t)offset);
8710 : /* Is this a special opcode? */
8711 809235 : if (likely (opcode >= opcode_base))
8712 : {
8713 234014 : if (unlikely (line_range == 0))
8714 : goto invalid_unit;
8715 :
8716 : /* Yes. Handling this is quite easy since the opcode value
8717 : is computed with
8718 :
8719 : opcode = (desired line increment - line_base)
8720 : + (line_range * address advance) + opcode_base
8721 : */
8722 468028 : int line_increment = (line_base
8723 234014 : + (opcode - opcode_base) % line_range);
8724 :
8725 : /* Perform the increments. */
8726 234014 : line += line_increment;
8727 234014 : advance_pc ((opcode - opcode_base) / line_range);
8728 :
8729 234014 : printf (gettext (" special opcode %u: address+%u = "),
8730 : opcode, op_addr_advance);
8731 234014 : print_dwarf_addr (dwflmod, 0, address, address);
8732 234014 : if (show_op_index)
8733 0 : printf (gettext (", op_index = %u, line%+d = %zu\n"),
8734 : op_index, line_increment, line);
8735 : else
8736 234014 : printf (gettext (", line%+d = %zu\n"),
8737 : line_increment, line);
8738 : }
8739 575221 : else if (opcode == 0)
8740 : {
8741 : /* This an extended opcode. */
8742 33341 : if (unlikely (linep + 2 > lineendp))
8743 : goto invalid_unit;
8744 :
8745 : /* The length. */
8746 33341 : unsigned int len = *linep++;
8747 :
8748 33341 : if (unlikely (linep + len > lineendp))
8749 : goto invalid_unit;
8750 :
8751 : /* The sub-opcode. */
8752 33341 : opcode = *linep++;
8753 :
8754 33341 : printf (gettext (" extended opcode %u: "), opcode);
8755 :
8756 33341 : switch (opcode)
8757 : {
8758 1136 : case DW_LNE_end_sequence:
8759 1136 : puts (gettext (" end of sequence"));
8760 :
8761 : /* Reset the registers we care about. */
8762 1136 : address = 0;
8763 1136 : op_index = 0;
8764 1136 : line = 1;
8765 1136 : is_stmt = default_is_stmt;
8766 1136 : break;
8767 :
8768 1423 : case DW_LNE_set_address:
8769 1423 : op_index = 0;
8770 1423 : if (unlikely ((size_t) (lineendp - linep) < address_size))
8771 : goto invalid_unit;
8772 1423 : if (address_size == 4)
8773 17 : address = read_4ubyte_unaligned_inc (dbg, linep);
8774 : else
8775 1406 : address = read_8ubyte_unaligned_inc (dbg, linep);
8776 : {
8777 1423 : printf (gettext (" set address to "));
8778 1423 : print_dwarf_addr (dwflmod, 0, address, address);
8779 1423 : printf ("\n");
8780 : }
8781 : break;
8782 :
8783 0 : case DW_LNE_define_file:
8784 : {
8785 0 : char *fname = (char *) linep;
8786 0 : unsigned char *endp = memchr (linep, '\0',
8787 0 : lineendp - linep);
8788 0 : if (unlikely (endp == NULL))
8789 : goto invalid_unit;
8790 0 : linep = endp + 1;
8791 :
8792 0 : unsigned int diridx;
8793 0 : if (lineendp - linep < 1)
8794 : goto invalid_unit;
8795 0 : get_uleb128 (diridx, linep, lineendp);
8796 0 : Dwarf_Word mtime;
8797 0 : if (lineendp - linep < 1)
8798 : goto invalid_unit;
8799 0 : get_uleb128 (mtime, linep, lineendp);
8800 0 : Dwarf_Word filelength;
8801 0 : if (lineendp - linep < 1)
8802 : goto invalid_unit;
8803 0 : get_uleb128 (filelength, linep, lineendp);
8804 :
8805 0 : printf (gettext ("\
8806 : define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
8807 : diridx, (uint64_t) mtime, (uint64_t) filelength,
8808 : fname);
8809 : }
8810 : break;
8811 :
8812 30782 : case DW_LNE_set_discriminator:
8813 : /* Takes one ULEB128 parameter, the discriminator. */
8814 30782 : if (unlikely (standard_opcode_lengths[opcode] != 1
8815 : || lineendp - linep < 1))
8816 : goto invalid_unit;
8817 :
8818 30782 : get_uleb128 (u128, linep, lineendp);
8819 30782 : printf (gettext (" set discriminator to %u\n"), u128);
8820 : break;
8821 :
8822 0 : default:
8823 : /* Unknown, ignore it. */
8824 0 : puts (gettext (" unknown opcode"));
8825 0 : linep += len - 1;
8826 0 : break;
8827 : }
8828 : }
8829 541880 : else if (opcode <= DW_LNS_set_isa)
8830 : {
8831 : /* This is a known standard opcode. */
8832 541880 : switch (opcode)
8833 : {
8834 85451 : case DW_LNS_copy:
8835 : /* Takes no argument. */
8836 85451 : puts (gettext (" copy"));
8837 85451 : break;
8838 :
8839 3390 : case DW_LNS_advance_pc:
8840 : /* Takes one uleb128 parameter which is added to the
8841 : address. */
8842 3390 : if (lineendp - linep < 1)
8843 : goto invalid_unit;
8844 3390 : get_uleb128 (u128, linep, lineendp);
8845 3390 : advance_pc (u128);
8846 : {
8847 3390 : printf (gettext (" advance address by %u to "),
8848 : op_addr_advance);
8849 3390 : print_dwarf_addr (dwflmod, 0, address, address);
8850 3390 : if (show_op_index)
8851 0 : printf (gettext (", op_index to %u"), op_index);
8852 3390 : printf ("\n");
8853 : }
8854 : break;
8855 :
8856 61929 : case DW_LNS_advance_line:
8857 : /* Takes one sleb128 parameter which is added to the
8858 : line. */
8859 61929 : if (lineendp - linep < 1)
8860 : goto invalid_unit;
8861 61929 : get_sleb128 (s128, linep, lineendp);
8862 61929 : line += s128;
8863 61929 : printf (gettext ("\
8864 : advance line by constant %d to %" PRId64 "\n"),
8865 : s128, (int64_t) line);
8866 : break;
8867 :
8868 25095 : case DW_LNS_set_file:
8869 : /* Takes one uleb128 parameter which is stored in file. */
8870 25095 : if (lineendp - linep < 1)
8871 : goto invalid_unit;
8872 25095 : get_uleb128 (u128, linep, lineendp);
8873 25095 : printf (gettext (" set file to %" PRIu64 "\n"),
8874 : (uint64_t) u128);
8875 : break;
8876 :
8877 205787 : case DW_LNS_set_column:
8878 : /* Takes one uleb128 parameter which is stored in column. */
8879 205787 : if (unlikely (standard_opcode_lengths[opcode] != 1
8880 : || lineendp - linep < 1))
8881 : goto invalid_unit;
8882 :
8883 205787 : get_uleb128 (u128, linep, lineendp);
8884 205787 : printf (gettext (" set column to %" PRIu64 "\n"),
8885 : (uint64_t) u128);
8886 : break;
8887 :
8888 141315 : case DW_LNS_negate_stmt:
8889 : /* Takes no argument. */
8890 141315 : is_stmt = 1 - is_stmt;
8891 141315 : printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
8892 : "is_stmt", is_stmt);
8893 : break;
8894 :
8895 0 : case DW_LNS_set_basic_block:
8896 : /* Takes no argument. */
8897 0 : puts (gettext (" set basic block flag"));
8898 0 : break;
8899 :
8900 18890 : case DW_LNS_const_add_pc:
8901 : /* Takes no argument. */
8902 :
8903 18890 : if (unlikely (line_range == 0))
8904 : goto invalid_unit;
8905 :
8906 18890 : advance_pc ((255 - opcode_base) / line_range);
8907 : {
8908 18890 : printf (gettext (" advance address by constant %u to "),
8909 : op_addr_advance);
8910 18890 : print_dwarf_addr (dwflmod, 0, address, address);
8911 18890 : if (show_op_index)
8912 0 : printf (gettext (", op_index to %u"), op_index);
8913 18890 : printf ("\n");
8914 : }
8915 : break;
8916 :
8917 22 : case DW_LNS_fixed_advance_pc:
8918 : /* Takes one 16 bit parameter which is added to the
8919 : address. */
8920 22 : if (unlikely (standard_opcode_lengths[opcode] != 1
8921 : || lineendp - linep < 2))
8922 : goto invalid_unit;
8923 :
8924 22 : u128 = read_2ubyte_unaligned_inc (dbg, linep);
8925 22 : address += u128;
8926 22 : op_index = 0;
8927 : {
8928 22 : printf (gettext ("\
8929 : advance address by fixed value %u to \n"),
8930 : u128);
8931 22 : print_dwarf_addr (dwflmod, 0, address, address);
8932 22 : printf ("\n");
8933 : }
8934 : break;
8935 :
8936 1 : case DW_LNS_set_prologue_end:
8937 : /* Takes no argument. */
8938 1 : puts (gettext (" set prologue end flag"));
8939 1 : break;
8940 :
8941 0 : case DW_LNS_set_epilogue_begin:
8942 : /* Takes no argument. */
8943 0 : puts (gettext (" set epilogue begin flag"));
8944 0 : break;
8945 :
8946 0 : case DW_LNS_set_isa:
8947 : /* Takes one uleb128 parameter which is stored in isa. */
8948 0 : if (unlikely (standard_opcode_lengths[opcode] != 1
8949 : || lineendp - linep < 1))
8950 : goto invalid_unit;
8951 :
8952 0 : get_uleb128 (u128, linep, lineendp);
8953 0 : printf (gettext (" set isa to %u\n"), u128);
8954 : break;
8955 : }
8956 : }
8957 : else
8958 : {
8959 : /* This is a new opcode the generator but not we know about.
8960 : Read the parameters associated with it but then discard
8961 : everything. Read all the parameters for this opcode. */
8962 0 : printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
8963 : " unknown opcode with %" PRIu8 " parameters:",
8964 : standard_opcode_lengths[opcode]),
8965 0 : standard_opcode_lengths[opcode]);
8966 0 : for (int n = standard_opcode_lengths[opcode];
8967 0 : n > 0 && linep < lineendp; --n)
8968 : {
8969 0 : get_uleb128 (u128, linep, lineendp);
8970 0 : if (n != standard_opcode_lengths[opcode])
8971 0 : putc_unlocked (',', stdout);
8972 0 : printf (" %u", u128);
8973 : }
8974 :
8975 : /* Next round, ignore this opcode. */
8976 : continue;
8977 : }
8978 : }
8979 : }
8980 :
8981 : /* There must only be one data block. */
8982 48 : assert (elf_getdata (scn, data) == NULL);
8983 : }
8984 :
8985 :
8986 : static void
8987 3 : print_debug_loclists_section (Dwfl_Module *dwflmod,
8988 : Ebl *ebl,
8989 : GElf_Ehdr *ehdr __attribute__ ((unused)),
8990 : Elf_Scn *scn, GElf_Shdr *shdr,
8991 : Dwarf *dbg)
8992 : {
8993 3 : printf (gettext ("\
8994 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
8995 : elf_ndxscn (scn), section_name (ebl, shdr),
8996 3 : (uint64_t) shdr->sh_offset);
8997 :
8998 6 : Elf_Data *data = (dbg->sectiondata[IDX_debug_loclists]
8999 3 : ?: elf_rawdata (scn, NULL));
9000 3 : if (unlikely (data == NULL))
9001 : {
9002 0 : error (0, 0, gettext ("cannot get .debug_loclists content: %s"),
9003 : elf_errmsg (-1));
9004 0 : return;
9005 : }
9006 :
9007 : /* For the listptr to get the base address/CU. */
9008 3 : sort_listptr (&known_loclistsptr, "loclistsptr");
9009 3 : size_t listptr_idx = 0;
9010 :
9011 3 : const unsigned char *readp = data->d_buf;
9012 6 : const unsigned char *const dataend = ((unsigned char *) data->d_buf
9013 3 : + data->d_size);
9014 7 : while (readp < dataend)
9015 : {
9016 4 : if (unlikely (readp > dataend - 4))
9017 : {
9018 0 : invalid_data:
9019 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
9020 : elf_ndxscn (scn), section_name (ebl, shdr));
9021 0 : return;
9022 : }
9023 :
9024 4 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
9025 4 : printf (gettext ("Table at Offset 0x%" PRIx64 ":\n\n"),
9026 : (uint64_t) offset);
9027 :
9028 4 : uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
9029 4 : unsigned int offset_size = 4;
9030 4 : if (unlikely (unit_length == 0xffffffff))
9031 : {
9032 0 : if (unlikely (readp > dataend - 8))
9033 : goto invalid_data;
9034 :
9035 0 : unit_length = read_8ubyte_unaligned_inc (dbg, readp);
9036 0 : offset_size = 8;
9037 : }
9038 4 : printf (gettext (" Length: %8" PRIu64 "\n"), unit_length);
9039 :
9040 : /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
9041 : bytes to complete the header. And this unit cannot go beyond
9042 : the section data. */
9043 4 : if (readp > dataend - 8
9044 4 : || unit_length < 8
9045 4 : || unit_length > (uint64_t) (dataend - readp))
9046 : goto invalid_data;
9047 :
9048 4 : const unsigned char *nexthdr = readp + unit_length;
9049 :
9050 4 : uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
9051 4 : printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
9052 :
9053 4 : if (version != 5)
9054 : {
9055 0 : error (0, 0, gettext ("Unknown version"));
9056 0 : goto next_table;
9057 : }
9058 :
9059 4 : uint8_t address_size = *readp++;
9060 4 : printf (gettext (" Address size: %8" PRIu64 "\n"),
9061 : (uint64_t) address_size);
9062 :
9063 4 : if (address_size != 4 && address_size != 8)
9064 : {
9065 0 : error (0, 0, gettext ("unsupported address size"));
9066 0 : goto next_table;
9067 : }
9068 :
9069 4 : uint8_t segment_size = *readp++;
9070 4 : printf (gettext (" Segment size: %8" PRIu64 "\n"),
9071 : (uint64_t) segment_size);
9072 :
9073 4 : if (segment_size != 0)
9074 : {
9075 0 : error (0, 0, gettext ("unsupported segment size"));
9076 0 : goto next_table;
9077 : }
9078 :
9079 4 : uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
9080 4 : printf (gettext (" Offset entries: %8" PRIu64 "\n"),
9081 : (uint64_t) offset_entry_count);
9082 :
9083 : /* We need the CU that uses this unit to get the initial base address. */
9084 4 : Dwarf_Addr cu_base = 0;
9085 4 : struct Dwarf_CU *cu = NULL;
9086 4 : if (listptr_cu (&known_loclistsptr, &listptr_idx,
9087 : (Dwarf_Off) offset,
9088 4 : (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
9089 : &cu_base, &cu)
9090 0 : || split_dwarf_cu_base (dbg, &cu, &cu_base))
9091 4 : {
9092 4 : Dwarf_Die cudie;
9093 4 : if (dwarf_cu_die (cu, &cudie,
9094 : NULL, NULL, NULL, NULL,
9095 : NULL, NULL) == NULL)
9096 0 : printf (gettext (" Unknown CU base: "));
9097 : else
9098 4 : printf (gettext (" CU [%6" PRIx64 "] base: "),
9099 : dwarf_dieoffset (&cudie));
9100 4 : print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
9101 4 : printf ("\n");
9102 : }
9103 : else
9104 0 : printf (gettext (" Not associated with a CU.\n"));
9105 :
9106 4 : printf ("\n");
9107 :
9108 4 : const unsigned char *offset_array_start = readp;
9109 4 : if (offset_entry_count > 0)
9110 : {
9111 2 : uint64_t max_entries = (unit_length - 8) / offset_size;
9112 2 : if (offset_entry_count > max_entries)
9113 : {
9114 0 : error (0, 0,
9115 0 : gettext ("too many offset entries for unit length"));
9116 0 : offset_entry_count = max_entries;
9117 : }
9118 :
9119 6 : printf (gettext (" Offsets starting at 0x%" PRIx64 ":\n"),
9120 : (uint64_t) (offset_array_start
9121 2 : - (unsigned char *) data->d_buf));
9122 18 : for (uint32_t idx = 0; idx < offset_entry_count; idx++)
9123 : {
9124 16 : printf (" [%6" PRIu32 "] ", idx);
9125 16 : if (offset_size == 4)
9126 : {
9127 16 : uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
9128 16 : printf ("0x%" PRIx32 "\n", off);
9129 : }
9130 : else
9131 : {
9132 0 : uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
9133 0 : printf ("0x%" PRIx64 "\n", off);
9134 : }
9135 : }
9136 2 : printf ("\n");
9137 : }
9138 :
9139 4 : Dwarf_Addr base = cu_base;
9140 4 : bool start_of_list = true;
9141 93 : while (readp < nexthdr)
9142 : {
9143 89 : uint8_t kind = *readp++;
9144 89 : uint64_t op1, op2, len;
9145 :
9146 : /* Skip padding. */
9147 89 : if (start_of_list && kind == DW_LLE_end_of_list)
9148 : continue;
9149 :
9150 89 : if (start_of_list)
9151 : {
9152 32 : base = cu_base;
9153 128 : printf (" Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
9154 32 : (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
9155 32 : (uint64_t) (readp - offset_array_start - 1));
9156 32 : start_of_list = false;
9157 : }
9158 :
9159 89 : printf (" %s", dwarf_loc_list_encoding_name (kind));
9160 89 : switch (kind)
9161 : {
9162 32 : case DW_LLE_end_of_list:
9163 32 : start_of_list = true;
9164 32 : printf ("\n\n");
9165 : break;
9166 :
9167 0 : case DW_LLE_base_addressx:
9168 0 : if ((uint64_t) (nexthdr - readp) < 1)
9169 : {
9170 0 : invalid_entry:
9171 0 : error (0, 0, gettext ("invalid loclists data"));
9172 0 : goto next_table;
9173 : }
9174 0 : get_uleb128 (op1, readp, nexthdr);
9175 0 : printf (" %" PRIx64 "\n", op1);
9176 0 : if (! print_unresolved_addresses)
9177 : {
9178 0 : Dwarf_Addr addr;
9179 0 : if (get_indexed_addr (cu, op1, &addr) != 0)
9180 0 : printf (" ???\n");
9181 : else
9182 : {
9183 0 : printf (" ");
9184 0 : print_dwarf_addr (dwflmod, address_size, addr, addr);
9185 0 : printf ("\n");
9186 : }
9187 : }
9188 : break;
9189 :
9190 0 : case DW_LLE_startx_endx:
9191 0 : if ((uint64_t) (nexthdr - readp) < 1)
9192 : goto invalid_entry;
9193 0 : get_uleb128 (op1, readp, nexthdr);
9194 0 : if ((uint64_t) (nexthdr - readp) < 1)
9195 : goto invalid_entry;
9196 0 : get_uleb128 (op2, readp, nexthdr);
9197 0 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
9198 0 : if (! print_unresolved_addresses)
9199 : {
9200 0 : Dwarf_Addr addr1;
9201 0 : Dwarf_Addr addr2;
9202 0 : if (get_indexed_addr (cu, op1, &addr1) != 0
9203 0 : || get_indexed_addr (cu, op2, &addr2) != 0)
9204 : {
9205 0 : printf (" ???..\n");
9206 0 : printf (" ???\n");
9207 : }
9208 : else
9209 : {
9210 0 : printf (" ");
9211 0 : print_dwarf_addr (dwflmod, address_size, addr1, addr1);
9212 0 : printf ("..\n ");
9213 0 : print_dwarf_addr (dwflmod, address_size,
9214 : addr2 - 1, addr2);
9215 0 : printf ("\n");
9216 : }
9217 : }
9218 0 : if ((uint64_t) (nexthdr - readp) < 1)
9219 : goto invalid_entry;
9220 0 : get_uleb128 (len, readp, nexthdr);
9221 0 : if ((uint64_t) (nexthdr - readp) < len)
9222 : goto invalid_entry;
9223 0 : print_ops (dwflmod, dbg, 8, 8, version,
9224 : address_size, offset_size, cu, len, readp);
9225 0 : readp += len;
9226 0 : break;
9227 :
9228 26 : case DW_LLE_startx_length:
9229 26 : if ((uint64_t) (nexthdr - readp) < 1)
9230 : goto invalid_entry;
9231 26 : get_uleb128 (op1, readp, nexthdr);
9232 26 : if ((uint64_t) (nexthdr - readp) < 1)
9233 : goto invalid_entry;
9234 26 : get_uleb128 (op2, readp, nexthdr);
9235 26 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
9236 26 : if (! print_unresolved_addresses)
9237 : {
9238 26 : Dwarf_Addr addr1;
9239 26 : Dwarf_Addr addr2;
9240 26 : if (get_indexed_addr (cu, op1, &addr1) != 0)
9241 : {
9242 0 : printf (" ???..\n");
9243 0 : printf (" ???\n");
9244 : }
9245 : else
9246 : {
9247 26 : addr2 = addr1 + op2;
9248 26 : printf (" ");
9249 26 : print_dwarf_addr (dwflmod, address_size, addr1, addr1);
9250 26 : printf ("..\n ");
9251 26 : print_dwarf_addr (dwflmod, address_size,
9252 : addr2 - 1, addr2);
9253 26 : printf ("\n");
9254 : }
9255 : }
9256 26 : if ((uint64_t) (nexthdr - readp) < 1)
9257 : goto invalid_entry;
9258 26 : get_uleb128 (len, readp, nexthdr);
9259 26 : if ((uint64_t) (nexthdr - readp) < len)
9260 : goto invalid_entry;
9261 26 : print_ops (dwflmod, dbg, 8, 8, version,
9262 : address_size, offset_size, cu, len, readp);
9263 26 : readp += len;
9264 26 : break;
9265 :
9266 24 : case DW_LLE_offset_pair:
9267 24 : if ((uint64_t) (nexthdr - readp) < 1)
9268 : goto invalid_entry;
9269 24 : get_uleb128 (op1, readp, nexthdr);
9270 24 : if ((uint64_t) (nexthdr - readp) < 1)
9271 : goto invalid_entry;
9272 24 : get_uleb128 (op2, readp, nexthdr);
9273 24 : printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
9274 24 : if (! print_unresolved_addresses)
9275 : {
9276 24 : op1 += base;
9277 24 : op2 += base;
9278 24 : printf (" ");
9279 24 : print_dwarf_addr (dwflmod, address_size, op1, op1);
9280 24 : printf ("..\n ");
9281 24 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
9282 24 : printf ("\n");
9283 : }
9284 24 : if ((uint64_t) (nexthdr - readp) < 1)
9285 : goto invalid_entry;
9286 24 : get_uleb128 (len, readp, nexthdr);
9287 24 : if ((uint64_t) (nexthdr - readp) < len)
9288 : goto invalid_entry;
9289 24 : print_ops (dwflmod, dbg, 8, 8, version,
9290 : address_size, offset_size, cu, len, readp);
9291 24 : readp += len;
9292 24 : break;
9293 :
9294 0 : case DW_LLE_default_location:
9295 0 : if ((uint64_t) (nexthdr - readp) < 1)
9296 : goto invalid_entry;
9297 0 : get_uleb128 (len, readp, nexthdr);
9298 0 : if ((uint64_t) (nexthdr - readp) < len)
9299 : goto invalid_entry;
9300 0 : print_ops (dwflmod, dbg, 8, 8, version,
9301 : address_size, offset_size, cu, len, readp);
9302 0 : readp += len;
9303 0 : break;
9304 :
9305 5 : case DW_LLE_base_address:
9306 5 : if (address_size == 4)
9307 : {
9308 0 : if ((uint64_t) (nexthdr - readp) < 4)
9309 : goto invalid_entry;
9310 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
9311 : }
9312 : else
9313 : {
9314 5 : if ((uint64_t) (nexthdr - readp) < 8)
9315 : goto invalid_entry;
9316 5 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
9317 : }
9318 5 : base = op1;
9319 5 : printf (" 0x%" PRIx64 "\n", base);
9320 5 : if (! print_unresolved_addresses)
9321 : {
9322 5 : printf (" ");
9323 5 : print_dwarf_addr (dwflmod, address_size, base, base);
9324 5 : printf ("\n");
9325 : }
9326 : break;
9327 :
9328 0 : case DW_LLE_start_end:
9329 0 : if (address_size == 4)
9330 : {
9331 0 : if ((uint64_t) (nexthdr - readp) < 8)
9332 : goto invalid_entry;
9333 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
9334 0 : op2 = read_4ubyte_unaligned_inc (dbg, readp);
9335 : }
9336 : else
9337 : {
9338 0 : if ((uint64_t) (nexthdr - readp) < 16)
9339 : goto invalid_entry;
9340 0 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
9341 0 : op2 = read_8ubyte_unaligned_inc (dbg, readp);
9342 : }
9343 0 : printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
9344 0 : if (! print_unresolved_addresses)
9345 : {
9346 0 : printf (" ");
9347 0 : print_dwarf_addr (dwflmod, address_size, op1, op1);
9348 0 : printf ("..\n ");
9349 0 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
9350 0 : printf ("\n");
9351 : }
9352 0 : if ((uint64_t) (nexthdr - readp) < 1)
9353 : goto invalid_entry;
9354 0 : get_uleb128 (len, readp, nexthdr);
9355 0 : if ((uint64_t) (nexthdr - readp) < len)
9356 : goto invalid_entry;
9357 0 : print_ops (dwflmod, dbg, 8, 8, version,
9358 : address_size, offset_size, cu, len, readp);
9359 0 : readp += len;
9360 0 : break;
9361 :
9362 2 : case DW_LLE_start_length:
9363 2 : if (address_size == 4)
9364 : {
9365 0 : if ((uint64_t) (nexthdr - readp) < 4)
9366 : goto invalid_entry;
9367 0 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
9368 : }
9369 : else
9370 : {
9371 2 : if ((uint64_t) (nexthdr - readp) < 8)
9372 : goto invalid_entry;
9373 2 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
9374 : }
9375 2 : if ((uint64_t) (nexthdr - readp) < 1)
9376 : goto invalid_entry;
9377 2 : get_uleb128 (op2, readp, nexthdr);
9378 2 : printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
9379 2 : if (! print_unresolved_addresses)
9380 : {
9381 2 : op2 = op1 + op2;
9382 2 : printf (" ");
9383 2 : print_dwarf_addr (dwflmod, address_size, op1, op1);
9384 2 : printf ("..\n ");
9385 2 : print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
9386 2 : printf ("\n");
9387 : }
9388 2 : if ((uint64_t) (nexthdr - readp) < 1)
9389 : goto invalid_entry;
9390 2 : get_uleb128 (len, readp, nexthdr);
9391 2 : if ((uint64_t) (nexthdr - readp) < len)
9392 : goto invalid_entry;
9393 2 : print_ops (dwflmod, dbg, 8, 8, version,
9394 : address_size, offset_size, cu, len, readp);
9395 2 : readp += len;
9396 2 : break;
9397 :
9398 : default:
9399 : goto invalid_entry;
9400 : }
9401 : }
9402 :
9403 4 : next_table:
9404 4 : if (readp != nexthdr)
9405 : {
9406 0 : size_t padding = nexthdr - readp;
9407 0 : printf (gettext (" %zu padding bytes\n\n"), padding);
9408 0 : readp = nexthdr;
9409 : }
9410 : }
9411 : }
9412 :
9413 :
9414 : static void
9415 44 : print_debug_loc_section (Dwfl_Module *dwflmod,
9416 : Ebl *ebl, GElf_Ehdr *ehdr,
9417 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
9418 : {
9419 88 : Elf_Data *data = (dbg->sectiondata[IDX_debug_loc]
9420 44 : ?: elf_rawdata (scn, NULL));
9421 :
9422 44 : if (unlikely (data == NULL))
9423 : {
9424 0 : error (0, 0, gettext ("cannot get .debug_loc content: %s"),
9425 : elf_errmsg (-1));
9426 0 : return;
9427 : }
9428 :
9429 44 : printf (gettext ("\
9430 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
9431 : elf_ndxscn (scn), section_name (ebl, shdr),
9432 44 : (uint64_t) shdr->sh_offset);
9433 :
9434 44 : sort_listptr (&known_locsptr, "loclistptr");
9435 44 : size_t listptr_idx = 0;
9436 :
9437 44 : uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
9438 44 : uint_fast8_t offset_size = 4;
9439 :
9440 44 : bool first = true;
9441 44 : Dwarf_Addr base = 0;
9442 44 : unsigned char *readp = data->d_buf;
9443 44 : unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
9444 44 : Dwarf_CU *last_cu = NULL;
9445 275418 : while (readp < endp)
9446 : {
9447 275374 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
9448 275374 : Dwarf_CU *cu = last_cu;
9449 275374 : unsigned int attr = 0;
9450 :
9451 275374 : if (first && skip_listptr_hole (&known_locsptr, &listptr_idx,
9452 : &address_size, &offset_size, &base,
9453 : &cu, offset, &readp, endp, &attr))
9454 43054 : continue;
9455 :
9456 275374 : if (last_cu != cu)
9457 : {
9458 974 : Dwarf_Die cudie;
9459 974 : if (dwarf_cu_die (cu, &cudie,
9460 : NULL, NULL, NULL, NULL,
9461 : NULL, NULL) == NULL)
9462 0 : printf (gettext ("\n Unknown CU base: "));
9463 : else
9464 974 : printf (gettext ("\n CU [%6" PRIx64 "] base: "),
9465 : dwarf_dieoffset (&cudie));
9466 974 : print_dwarf_addr (dwflmod, address_size, base, base);
9467 974 : printf ("\n");
9468 : }
9469 275374 : last_cu = cu;
9470 :
9471 275374 : if (attr == DW_AT_GNU_locviews)
9472 : {
9473 43054 : Dwarf_Off next_off = next_listptr_offset (&known_locsptr,
9474 : listptr_idx);
9475 43054 : const unsigned char *locp = readp;
9476 43054 : const unsigned char *locendp;
9477 43054 : if (next_off == 0
9478 43054 : || next_off > (size_t) (endp
9479 43054 : - (const unsigned char *) data->d_buf))
9480 : locendp = endp;
9481 : else
9482 43054 : locendp = (const unsigned char *) data->d_buf + next_off;
9483 :
9484 232101 : while (locp < locendp)
9485 : {
9486 189047 : uint64_t v1, v2;
9487 189047 : get_uleb128 (v1, locp, locendp);
9488 189047 : if (locp >= locendp)
9489 : {
9490 0 : printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
9491 : break;
9492 : }
9493 189047 : get_uleb128 (v2, locp, locendp);
9494 189047 : if (first) /* First view pair in a list. */
9495 43054 : printf (" [%6tx] ", offset);
9496 : else
9497 145993 : printf (" ");
9498 189047 : printf ("view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
9499 189047 : first = false;
9500 : }
9501 :
9502 43054 : first = true;
9503 43054 : readp = (unsigned char *) locendp;
9504 43054 : continue;
9505 : }
9506 :
9507 : /* GNU DebugFission encoded addresses as addrx. */
9508 464640 : bool is_debugfission = ((cu != NULL
9509 0 : || split_dwarf_cu_base (dbg, &cu, &base))
9510 232320 : && (cu->version < 5
9511 232320 : && cu->unit_type == DW_UT_split_compile));
9512 232320 : if (!is_debugfission
9513 232260 : && unlikely (data->d_size - offset < (size_t) address_size * 2))
9514 : {
9515 0 : invalid_data:
9516 0 : printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
9517 0 : break;
9518 : }
9519 :
9520 232320 : Dwarf_Addr begin;
9521 232320 : Dwarf_Addr end;
9522 232320 : bool use_base = true;
9523 232320 : if (is_debugfission)
9524 : {
9525 60 : const unsigned char *locp = readp;
9526 60 : const unsigned char *locendp = readp + data->d_size;
9527 60 : if (locp >= locendp)
9528 0 : goto invalid_data;
9529 :
9530 60 : Dwarf_Word idx;
9531 60 : unsigned char code = *locp++;
9532 60 : switch (code)
9533 : {
9534 20 : case DW_LLE_GNU_end_of_list_entry:
9535 20 : begin = 0;
9536 20 : end = 0;
9537 20 : break;
9538 :
9539 0 : case DW_LLE_GNU_base_address_selection_entry:
9540 0 : if (locp >= locendp)
9541 0 : goto invalid_data;
9542 0 : begin = (Dwarf_Addr) -1;
9543 0 : get_uleb128 (idx, locp, locendp);
9544 0 : if (get_indexed_addr (cu, idx, &end) != 0)
9545 0 : end = idx; /* ... */
9546 : break;
9547 :
9548 0 : case DW_LLE_GNU_start_end_entry:
9549 0 : if (locp >= locendp)
9550 0 : goto invalid_data;
9551 0 : get_uleb128 (idx, locp, locendp);
9552 0 : if (get_indexed_addr (cu, idx, &begin) != 0)
9553 0 : begin = idx; /* ... */
9554 0 : if (locp >= locendp)
9555 0 : goto invalid_data;
9556 0 : get_uleb128 (idx, locp, locendp);
9557 0 : if (get_indexed_addr (cu, idx, &end) != 0)
9558 0 : end = idx; /* ... */
9559 : use_base = false;
9560 : break;
9561 :
9562 40 : case DW_LLE_GNU_start_length_entry:
9563 40 : if (locp >= locendp)
9564 0 : goto invalid_data;
9565 40 : get_uleb128 (idx, locp, locendp);
9566 40 : if (get_indexed_addr (cu, idx, &begin) != 0)
9567 0 : begin = idx; /* ... */
9568 40 : if (locendp - locp < 4)
9569 0 : goto invalid_data;
9570 40 : end = read_4ubyte_unaligned_inc (dbg, locp);
9571 40 : end += begin;
9572 40 : use_base = false;
9573 40 : break;
9574 :
9575 0 : default:
9576 0 : goto invalid_data;
9577 : }
9578 :
9579 60 : readp = (unsigned char *) locp;
9580 : }
9581 232260 : else if (address_size == 8)
9582 : {
9583 232260 : begin = read_8ubyte_unaligned_inc (dbg, readp);
9584 232260 : end = read_8ubyte_unaligned_inc (dbg, readp);
9585 : }
9586 : else
9587 : {
9588 0 : begin = read_4ubyte_unaligned_inc (dbg, readp);
9589 0 : end = read_4ubyte_unaligned_inc (dbg, readp);
9590 0 : if (begin == (Dwarf_Addr) (uint32_t) -1)
9591 0 : begin = (Dwarf_Addr) -1l;
9592 : }
9593 :
9594 232320 : if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
9595 : {
9596 0 : printf (gettext (" [%6tx] base address\n "), offset);
9597 0 : print_dwarf_addr (dwflmod, address_size, end, end);
9598 0 : printf ("\n");
9599 0 : base = end;
9600 : }
9601 232320 : else if (begin == 0 && end == 0) /* End of list entry. */
9602 : {
9603 43128 : if (first)
9604 0 : printf (gettext (" [%6tx] empty list\n"), offset);
9605 : first = true;
9606 : }
9607 : else
9608 : {
9609 : /* We have a location expression entry. */
9610 189192 : uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
9611 :
9612 189192 : if (first) /* First entry in a list. */
9613 43128 : printf (" [%6tx] ", offset);
9614 : else
9615 146064 : printf (" ");
9616 :
9617 189192 : printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
9618 189192 : if (! print_unresolved_addresses)
9619 : {
9620 189162 : Dwarf_Addr dab = use_base ? base + begin : begin;
9621 189162 : Dwarf_Addr dae = use_base ? base + end : end;
9622 189162 : printf (" ");
9623 189162 : print_dwarf_addr (dwflmod, address_size, dab, dab);
9624 189162 : printf ("..\n ");
9625 189162 : print_dwarf_addr (dwflmod, address_size, dae - 1, dae);
9626 189162 : printf ("\n");
9627 : }
9628 :
9629 189192 : if (endp - readp <= (ptrdiff_t) len)
9630 : {
9631 0 : fputs (gettext (" <INVALID DATA>\n"), stdout);
9632 0 : break;
9633 : }
9634 :
9635 378384 : print_ops (dwflmod, dbg, 11, 11,
9636 189192 : cu != NULL ? cu->version : 3,
9637 : address_size, offset_size, cu, len, readp);
9638 :
9639 189192 : first = false;
9640 189192 : readp += len;
9641 : }
9642 : }
9643 : }
9644 :
9645 : struct mac_culist
9646 : {
9647 : Dwarf_Die die;
9648 : Dwarf_Off offset;
9649 : Dwarf_Files *files;
9650 : struct mac_culist *next;
9651 : };
9652 :
9653 :
9654 : static int
9655 0 : mac_compare (const void *p1, const void *p2)
9656 : {
9657 0 : struct mac_culist *m1 = (struct mac_culist *) p1;
9658 0 : struct mac_culist *m2 = (struct mac_culist *) p2;
9659 :
9660 0 : if (m1->offset < m2->offset)
9661 : return -1;
9662 0 : if (m1->offset > m2->offset)
9663 0 : return 1;
9664 : return 0;
9665 : }
9666 :
9667 :
9668 : static void
9669 0 : print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
9670 : Ebl *ebl,
9671 : GElf_Ehdr *ehdr __attribute__ ((unused)),
9672 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
9673 : {
9674 0 : printf (gettext ("\
9675 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
9676 : elf_ndxscn (scn), section_name (ebl, shdr),
9677 0 : (uint64_t) shdr->sh_offset);
9678 0 : putc_unlocked ('\n', stdout);
9679 :
9680 : /* There is no function in libdw to iterate over the raw content of
9681 : the section but it is easy enough to do. */
9682 0 : Elf_Data *data = (dbg->sectiondata[IDX_debug_macinfo]
9683 0 : ?: elf_rawdata (scn, NULL));
9684 0 : if (unlikely (data == NULL))
9685 : {
9686 0 : error (0, 0, gettext ("cannot get macro information section data: %s"),
9687 : elf_errmsg (-1));
9688 0 : return;
9689 : }
9690 :
9691 : /* Get the source file information for all CUs. */
9692 0 : Dwarf_Off offset;
9693 0 : Dwarf_Off ncu = 0;
9694 0 : size_t hsize;
9695 0 : struct mac_culist *culist = NULL;
9696 0 : size_t nculist = 0;
9697 0 : while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
9698 : {
9699 0 : Dwarf_Die cudie;
9700 0 : if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
9701 0 : continue;
9702 :
9703 0 : Dwarf_Attribute attr;
9704 0 : if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
9705 : continue;
9706 :
9707 0 : Dwarf_Word macoff;
9708 0 : if (dwarf_formudata (&attr, &macoff) != 0)
9709 : continue;
9710 :
9711 0 : struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
9712 0 : newp->die = cudie;
9713 0 : newp->offset = macoff;
9714 0 : newp->files = NULL;
9715 0 : newp->next = culist;
9716 0 : culist = newp;
9717 0 : ++nculist;
9718 : }
9719 :
9720 : /* Convert the list into an array for easier consumption. */
9721 0 : struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
9722 : * sizeof (*cus));
9723 : /* Add sentinel. */
9724 0 : cus[nculist].offset = data->d_size;
9725 0 : cus[nculist].files = (Dwarf_Files *) -1l;
9726 0 : if (nculist > 0)
9727 : {
9728 0 : for (size_t cnt = nculist - 1; culist != NULL; --cnt)
9729 : {
9730 0 : assert (cnt < nculist);
9731 0 : cus[cnt] = *culist;
9732 0 : culist = culist->next;
9733 : }
9734 :
9735 : /* Sort the array according to the offset in the .debug_macinfo
9736 : section. Note we keep the sentinel at the end. */
9737 0 : qsort (cus, nculist, sizeof (*cus), mac_compare);
9738 : }
9739 :
9740 0 : const unsigned char *readp = (const unsigned char *) data->d_buf;
9741 0 : const unsigned char *readendp = readp + data->d_size;
9742 0 : int level = 1;
9743 :
9744 0 : while (readp < readendp)
9745 : {
9746 0 : unsigned int opcode = *readp++;
9747 0 : unsigned int u128;
9748 0 : unsigned int u128_2;
9749 0 : const unsigned char *endp;
9750 :
9751 0 : switch (opcode)
9752 : {
9753 0 : case DW_MACINFO_define:
9754 : case DW_MACINFO_undef:
9755 : case DW_MACINFO_vendor_ext:
9756 : /* For the first two opcodes the parameters are
9757 : line, string
9758 : For the latter
9759 : number, string.
9760 : We can treat these cases together. */
9761 0 : get_uleb128 (u128, readp, readendp);
9762 :
9763 0 : endp = memchr (readp, '\0', readendp - readp);
9764 0 : if (unlikely (endp == NULL))
9765 : {
9766 0 : printf (gettext ("\
9767 : %*s*** non-terminated string at end of section"),
9768 : level, "");
9769 0 : return;
9770 : }
9771 :
9772 0 : if (opcode == DW_MACINFO_define)
9773 0 : printf ("%*s#define %s, line %u\n",
9774 : level, "", (char *) readp, u128);
9775 0 : else if (opcode == DW_MACINFO_undef)
9776 0 : printf ("%*s#undef %s, line %u\n",
9777 : level, "", (char *) readp, u128);
9778 : else
9779 0 : printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
9780 :
9781 0 : readp = endp + 1;
9782 0 : break;
9783 :
9784 0 : case DW_MACINFO_start_file:
9785 : /* The two parameters are line and file index, in this order. */
9786 0 : get_uleb128 (u128, readp, readendp);
9787 0 : if (readendp - readp < 1)
9788 : {
9789 0 : printf (gettext ("\
9790 : %*s*** missing DW_MACINFO_start_file argument at end of section"),
9791 : level, "");
9792 0 : return;
9793 : }
9794 0 : get_uleb128 (u128_2, readp, readendp);
9795 :
9796 : /* Find the CU DIE for this file. */
9797 0 : size_t macoff = readp - (const unsigned char *) data->d_buf;
9798 0 : const char *fname = "???";
9799 0 : if (macoff >= cus[0].offset && cus[0].offset != data->d_size)
9800 : {
9801 0 : while (macoff >= cus[1].offset && cus[1].offset != data->d_size)
9802 0 : ++cus;
9803 :
9804 0 : if (cus[0].files == NULL
9805 0 : && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
9806 0 : cus[0].files = (Dwarf_Files *) -1l;
9807 :
9808 0 : if (cus[0].files != (Dwarf_Files *) -1l)
9809 0 : fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
9810 0 : ?: "???");
9811 : }
9812 :
9813 0 : printf ("%*sstart_file %u, [%u] %s\n",
9814 : level, "", u128, u128_2, fname);
9815 0 : ++level;
9816 0 : break;
9817 :
9818 0 : case DW_MACINFO_end_file:
9819 0 : --level;
9820 0 : printf ("%*send_file\n", level, "");
9821 : /* Nothing more to do. */
9822 : break;
9823 :
9824 0 : default:
9825 : // XXX gcc seems to generate files with a trailing zero.
9826 0 : if (unlikely (opcode != 0 || readp != readendp))
9827 0 : printf ("%*s*** invalid opcode %u\n", level, "", opcode);
9828 : break;
9829 : }
9830 : }
9831 : }
9832 :
9833 :
9834 : static void
9835 3 : print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
9836 : Ebl *ebl,
9837 : GElf_Ehdr *ehdr __attribute__ ((unused)),
9838 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
9839 : {
9840 3 : printf (gettext ("\
9841 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
9842 : elf_ndxscn (scn), section_name (ebl, shdr),
9843 3 : (uint64_t) shdr->sh_offset);
9844 3 : putc_unlocked ('\n', stdout);
9845 :
9846 3 : Elf_Data *data = elf_getdata (scn, NULL);
9847 3 : if (unlikely (data == NULL))
9848 : {
9849 0 : error (0, 0, gettext ("cannot get macro information section data: %s"),
9850 : elf_errmsg (-1));
9851 0 : return;
9852 : }
9853 :
9854 : /* Get the source file information for all CUs. Uses same
9855 : datastructure as macinfo. But uses offset field to directly
9856 : match .debug_line offset. And just stored in a list. */
9857 3 : Dwarf_Off offset;
9858 3 : Dwarf_Off ncu = 0;
9859 3 : size_t hsize;
9860 3 : struct mac_culist *culist = NULL;
9861 3 : size_t nculist = 0;
9862 7 : while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
9863 : {
9864 4 : Dwarf_Die cudie;
9865 4 : if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
9866 0 : continue;
9867 :
9868 4 : Dwarf_Attribute attr;
9869 4 : if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL)
9870 : continue;
9871 :
9872 4 : Dwarf_Word lineoff;
9873 4 : if (dwarf_formudata (&attr, &lineoff) != 0)
9874 : continue;
9875 :
9876 4 : struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
9877 4 : newp->die = cudie;
9878 4 : newp->offset = lineoff;
9879 4 : newp->files = NULL;
9880 4 : newp->next = culist;
9881 4 : culist = newp;
9882 4 : ++nculist;
9883 : }
9884 :
9885 3 : const unsigned char *readp = (const unsigned char *) data->d_buf;
9886 3 : const unsigned char *readendp = readp + data->d_size;
9887 :
9888 11 : while (readp < readendp)
9889 : {
9890 24 : printf (gettext (" Offset: 0x%" PRIx64 "\n"),
9891 8 : (uint64_t) (readp - (const unsigned char *) data->d_buf));
9892 :
9893 : // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
9894 : // optional vendor extension macro entry table.
9895 8 : if (readp + 2 > readendp)
9896 : {
9897 0 : invalid_data:
9898 0 : error (0, 0, gettext ("invalid data"));
9899 0 : return;
9900 : }
9901 8 : const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
9902 8 : printf (gettext (" Version: %" PRIu16 "\n"), vers);
9903 :
9904 : // Version 4 is the GNU extension for DWARF4. DWARF5 will use version
9905 : // 5 when it gets standardized.
9906 8 : if (vers != 4 && vers != 5)
9907 : {
9908 0 : printf (gettext (" unknown version, cannot parse section\n"));
9909 0 : return;
9910 : }
9911 :
9912 8 : if (readp + 1 > readendp)
9913 : goto invalid_data;
9914 8 : const unsigned char flag = *readp++;
9915 8 : printf (gettext (" Flag: 0x%" PRIx8), flag);
9916 8 : if (flag != 0)
9917 : {
9918 4 : printf (" (");
9919 4 : if ((flag & 0x01) != 0)
9920 : {
9921 0 : printf ("offset_size");
9922 0 : if ((flag & 0xFE) != 0)
9923 0 : printf (", ");
9924 : }
9925 4 : if ((flag & 0x02) != 0)
9926 : {
9927 4 : printf ("debug_line_offset");
9928 4 : if ((flag & 0xFC) != 0)
9929 0 : printf (", ");
9930 : }
9931 4 : if ((flag & 0x04) != 0)
9932 : {
9933 0 : printf ("operands_table");
9934 0 : if ((flag & 0xF8) != 0)
9935 0 : printf (", ");
9936 : }
9937 4 : if ((flag & 0xF8) != 0)
9938 0 : printf ("unknown");
9939 4 : printf (")");
9940 : }
9941 8 : printf ("\n");
9942 :
9943 8 : unsigned int offset_len = (flag & 0x01) ? 8 : 4;
9944 8 : printf (gettext (" Offset length: %" PRIu8 "\n"), offset_len);
9945 8 : Dwarf_Off line_offset = -1;
9946 8 : if (flag & 0x02)
9947 : {
9948 4 : if (offset_len == 8)
9949 0 : line_offset = read_8ubyte_unaligned_inc (dbg, readp);
9950 : else
9951 4 : line_offset = read_4ubyte_unaligned_inc (dbg, readp);
9952 4 : printf (gettext (" .debug_line offset: 0x%" PRIx64 "\n"),
9953 : line_offset);
9954 : }
9955 :
9956 4 : struct mac_culist *cu = NULL;
9957 4 : if (line_offset != (Dwarf_Off) -1)
9958 : {
9959 : cu = culist;
9960 5 : while (cu != NULL && line_offset != cu->offset)
9961 1 : cu = cu->next;
9962 : }
9963 :
9964 8 : Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, (cu != NULL
9965 : ? cu->die.cu
9966 : : NULL));
9967 :
9968 8 : const unsigned char *vendor[DW_MACRO_hi_user - DW_MACRO_lo_user + 1];
9969 8 : memset (vendor, 0, sizeof vendor);
9970 8 : if (flag & 0x04)
9971 : {
9972 : // 1 byte length, for each item, 1 byte opcode, uleb128 number
9973 : // of arguments, for each argument 1 byte form code.
9974 0 : if (readp + 1 > readendp)
9975 : goto invalid_data;
9976 0 : unsigned int tlen = *readp++;
9977 0 : printf (gettext (" extension opcode table, %" PRIu8 " items:\n"),
9978 : tlen);
9979 0 : for (unsigned int i = 0; i < tlen; i++)
9980 : {
9981 0 : if (readp + 1 > readendp)
9982 : goto invalid_data;
9983 0 : unsigned int opcode = *readp++;
9984 0 : printf (gettext (" [%" PRIx8 "]"), opcode);
9985 0 : if (opcode < DW_MACRO_lo_user
9986 0 : || opcode > DW_MACRO_hi_user)
9987 : goto invalid_data;
9988 : // Record the start of description for this vendor opcode.
9989 : // uleb128 nr args, 1 byte per arg form.
9990 0 : vendor[opcode - DW_MACRO_lo_user] = readp;
9991 0 : if (readp + 1 > readendp)
9992 : goto invalid_data;
9993 0 : unsigned int args = *readp++;
9994 0 : if (args > 0)
9995 : {
9996 0 : printf (gettext (" %" PRIu8 " arguments:"), args);
9997 0 : while (args > 0)
9998 : {
9999 0 : if (readp + 1 > readendp)
10000 : goto invalid_data;
10001 0 : unsigned int form = *readp++;
10002 0 : printf (" %s", dwarf_form_name (form));
10003 0 : if (! libdw_valid_user_form (form))
10004 : goto invalid_data;
10005 0 : args--;
10006 0 : if (args > 0)
10007 0 : putchar_unlocked (',');
10008 : }
10009 : }
10010 : else
10011 0 : printf (gettext (" no arguments."));
10012 0 : putchar_unlocked ('\n');
10013 : }
10014 : }
10015 8 : putchar_unlocked ('\n');
10016 :
10017 8 : int level = 1;
10018 8 : if (readp + 1 > readendp)
10019 : goto invalid_data;
10020 8 : unsigned int opcode = *readp++;
10021 735 : while (opcode != 0)
10022 : {
10023 727 : unsigned int u128;
10024 727 : unsigned int u128_2;
10025 727 : const unsigned char *endp;
10026 727 : uint64_t off;
10027 :
10028 727 : switch (opcode)
10029 : {
10030 6 : case DW_MACRO_start_file:
10031 6 : get_uleb128 (u128, readp, readendp);
10032 6 : if (readp >= readendp)
10033 : goto invalid_data;
10034 6 : get_uleb128 (u128_2, readp, readendp);
10035 :
10036 : /* Find the CU DIE that matches this line offset. */
10037 6 : const char *fname = "???";
10038 6 : if (cu != NULL)
10039 : {
10040 6 : if (cu->files == NULL
10041 4 : && dwarf_getsrcfiles (&cu->die, &cu->files,
10042 : NULL) != 0)
10043 0 : cu->files = (Dwarf_Files *) -1l;
10044 :
10045 6 : if (cu->files != (Dwarf_Files *) -1l)
10046 6 : fname = (dwarf_filesrc (cu->files, u128_2,
10047 6 : NULL, NULL) ?: "???");
10048 : }
10049 6 : printf ("%*sstart_file %u, [%u] %s\n",
10050 : level, "", u128, u128_2, fname);
10051 6 : ++level;
10052 6 : break;
10053 :
10054 6 : case DW_MACRO_end_file:
10055 6 : --level;
10056 6 : printf ("%*send_file\n", level, "");
10057 : break;
10058 :
10059 1 : case DW_MACRO_define:
10060 1 : get_uleb128 (u128, readp, readendp);
10061 1 : endp = memchr (readp, '\0', readendp - readp);
10062 1 : if (endp == NULL)
10063 : goto invalid_data;
10064 1 : printf ("%*s#define %s, line %u\n",
10065 : level, "", readp, u128);
10066 1 : readp = endp + 1;
10067 1 : break;
10068 :
10069 0 : case DW_MACRO_undef:
10070 0 : get_uleb128 (u128, readp, readendp);
10071 0 : endp = memchr (readp, '\0', readendp - readp);
10072 0 : if (endp == NULL)
10073 : goto invalid_data;
10074 0 : printf ("%*s#undef %s, line %u\n",
10075 : level, "", readp, u128);
10076 0 : readp = endp + 1;
10077 0 : break;
10078 :
10079 707 : case DW_MACRO_define_strp:
10080 707 : get_uleb128 (u128, readp, readendp);
10081 707 : if (readp + offset_len > readendp)
10082 : goto invalid_data;
10083 707 : if (offset_len == 8)
10084 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
10085 : else
10086 707 : off = read_4ubyte_unaligned_inc (dbg, readp);
10087 707 : printf ("%*s#define %s, line %u (indirect)\n",
10088 : level, "", dwarf_getstring (dbg, off, NULL), u128);
10089 : break;
10090 :
10091 1 : case DW_MACRO_undef_strp:
10092 1 : get_uleb128 (u128, readp, readendp);
10093 1 : if (readp + offset_len > readendp)
10094 : goto invalid_data;
10095 1 : if (offset_len == 8)
10096 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
10097 : else
10098 1 : off = read_4ubyte_unaligned_inc (dbg, readp);
10099 1 : printf ("%*s#undef %s, line %u (indirect)\n",
10100 : level, "", dwarf_getstring (dbg, off, NULL), u128);
10101 : break;
10102 :
10103 6 : case DW_MACRO_import:
10104 6 : if (readp + offset_len > readendp)
10105 : goto invalid_data;
10106 6 : if (offset_len == 8)
10107 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
10108 : else
10109 6 : off = read_4ubyte_unaligned_inc (dbg, readp);
10110 6 : printf ("%*s#include offset 0x%" PRIx64 "\n",
10111 : level, "", off);
10112 : break;
10113 :
10114 0 : case DW_MACRO_define_sup:
10115 0 : get_uleb128 (u128, readp, readendp);
10116 0 : if (readp + offset_len > readendp)
10117 : goto invalid_data;
10118 0 : printf ("%*s#define ", level, "");
10119 0 : readp = print_form_data (dbg, DW_FORM_strp_sup,
10120 : readp, readendp, offset_len,
10121 : str_offsets_base);
10122 0 : printf (", line %u (sup)\n", u128);
10123 : break;
10124 :
10125 0 : case DW_MACRO_undef_sup:
10126 0 : get_uleb128 (u128, readp, readendp);
10127 0 : if (readp + offset_len > readendp)
10128 : goto invalid_data;
10129 0 : printf ("%*s#undef ", level, "");
10130 0 : readp = print_form_data (dbg, DW_FORM_strp_sup,
10131 : readp, readendp, offset_len,
10132 : str_offsets_base);
10133 0 : printf (", line %u (sup)\n", u128);
10134 : break;
10135 :
10136 0 : case DW_MACRO_import_sup:
10137 0 : if (readp + offset_len > readendp)
10138 : goto invalid_data;
10139 0 : if (offset_len == 8)
10140 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
10141 : else
10142 0 : off = read_4ubyte_unaligned_inc (dbg, readp);
10143 : // XXX Needs support for reading from supplementary object file.
10144 0 : printf ("%*s#include offset 0x%" PRIx64 " (sup)\n",
10145 : level, "", off);
10146 : break;
10147 :
10148 0 : case DW_MACRO_define_strx:
10149 0 : get_uleb128 (u128, readp, readendp);
10150 0 : if (readp + offset_len > readendp)
10151 : goto invalid_data;
10152 0 : printf ("%*s#define ", level, "");
10153 0 : readp = print_form_data (dbg, DW_FORM_strx,
10154 : readp, readendp, offset_len,
10155 : str_offsets_base);
10156 0 : printf (", line %u (strx)\n", u128);
10157 : break;
10158 :
10159 0 : case DW_MACRO_undef_strx:
10160 0 : get_uleb128 (u128, readp, readendp);
10161 0 : if (readp + offset_len > readendp)
10162 : goto invalid_data;
10163 0 : printf ("%*s#undef ", level, "");
10164 0 : readp = print_form_data (dbg, DW_FORM_strx,
10165 : readp, readendp, offset_len,
10166 : str_offsets_base);
10167 0 : printf (", line %u (strx)\n", u128);
10168 : break;
10169 :
10170 : default:
10171 0 : printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
10172 0 : if (opcode < DW_MACRO_lo_user
10173 : || opcode > DW_MACRO_lo_user
10174 0 : || vendor[opcode - DW_MACRO_lo_user] == NULL)
10175 : goto invalid_data;
10176 :
10177 0 : const unsigned char *op_desc;
10178 0 : op_desc = vendor[opcode - DW_MACRO_lo_user];
10179 :
10180 : // Just skip the arguments, we cannot really interpret them,
10181 : // but print as much as we can.
10182 0 : unsigned int args = *op_desc++;
10183 0 : while (args > 0 && readp < readendp)
10184 0 : {
10185 0 : unsigned int form = *op_desc++;
10186 0 : readp = print_form_data (dbg, form, readp, readendp,
10187 : offset_len, str_offsets_base);
10188 0 : args--;
10189 0 : if (args > 0)
10190 0 : printf (", ");
10191 : }
10192 0 : putchar_unlocked ('\n');
10193 : }
10194 :
10195 727 : if (readp + 1 > readendp)
10196 : goto invalid_data;
10197 727 : opcode = *readp++;
10198 727 : if (opcode == 0)
10199 8 : putchar_unlocked ('\n');
10200 : }
10201 : }
10202 : }
10203 :
10204 :
10205 : /* Callback for printing global names. */
10206 : static int
10207 34 : print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
10208 : void *arg)
10209 : {
10210 34 : int *np = (int *) arg;
10211 :
10212 102 : printf (gettext (" [%5d] DIE offset: %6" PRId64
10213 : ", CU DIE offset: %6" PRId64 ", name: %s\n"),
10214 34 : (*np)++, global->die_offset, global->cu_offset, global->name);
10215 :
10216 34 : return 0;
10217 : }
10218 :
10219 :
10220 : /* Print the known exported symbols in the DWARF section '.debug_pubnames'. */
10221 : static void
10222 8 : print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10223 : Ebl *ebl,
10224 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10225 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10226 : {
10227 8 : printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
10228 : elf_ndxscn (scn), section_name (ebl, shdr),
10229 8 : (uint64_t) shdr->sh_offset);
10230 :
10231 8 : int n = 0;
10232 8 : (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
10233 8 : }
10234 :
10235 : /* Print the content of the DWARF string section '.debug_str'. */
10236 : static void
10237 47 : print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10238 : Ebl *ebl,
10239 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10240 : Elf_Scn *scn, GElf_Shdr *shdr,
10241 : Dwarf *dbg __attribute__ ((unused)))
10242 : {
10243 47 : Elf_Data *data = elf_rawdata (scn, NULL);
10244 47 : const size_t sh_size = data ? data->d_size : 0;
10245 :
10246 : /* Compute floor(log16(shdr->sh_size)). */
10247 47 : GElf_Addr tmp = sh_size;
10248 47 : int digits = 1;
10249 163 : while (tmp >= 16)
10250 : {
10251 116 : ++digits;
10252 116 : tmp >>= 4;
10253 : }
10254 47 : digits = MAX (4, digits);
10255 :
10256 47 : printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
10257 : " %*s String\n"),
10258 : elf_ndxscn (scn),
10259 47 : section_name (ebl, shdr), (uint64_t) shdr->sh_offset,
10260 : /* TRANS: the debugstr| prefix makes the string unique. */
10261 47 : digits + 2, sgettext ("debugstr|Offset"));
10262 :
10263 47 : Dwarf_Off offset = 0;
10264 64239 : while (offset < sh_size)
10265 : {
10266 64192 : size_t len;
10267 64192 : const char *str = (const char *) data->d_buf + offset;
10268 64192 : const char *endp = memchr (str, '\0', sh_size - offset);
10269 64192 : if (unlikely (endp == NULL))
10270 : {
10271 0 : printf (gettext (" *** error, missing string terminator\n"));
10272 : break;
10273 : }
10274 :
10275 64192 : printf (" [%*" PRIx64 "] \"%s\"\n", digits, (uint64_t) offset, str);
10276 64192 : len = endp - str;
10277 64192 : offset += len + 1;
10278 : }
10279 47 : }
10280 :
10281 : static void
10282 4 : print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10283 : Ebl *ebl,
10284 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10285 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10286 : {
10287 4 : printf (gettext ("\
10288 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
10289 : elf_ndxscn (scn), section_name (ebl, shdr),
10290 4 : (uint64_t) shdr->sh_offset);
10291 :
10292 4 : if (shdr->sh_size == 0)
10293 : return;
10294 :
10295 : /* We like to get the section from libdw to make sure they are relocated. */
10296 8 : Elf_Data *data = (dbg->sectiondata[IDX_debug_str_offsets]
10297 4 : ?: elf_rawdata (scn, NULL));
10298 4 : if (unlikely (data == NULL))
10299 : {
10300 0 : error (0, 0, gettext ("cannot get .debug_str_offsets section data: %s"),
10301 : elf_errmsg (-1));
10302 0 : return;
10303 : }
10304 :
10305 4 : size_t idx = 0;
10306 4 : sort_listptr (&known_stroffbases, "str_offsets");
10307 :
10308 4 : const unsigned char *start = (const unsigned char *) data->d_buf;
10309 4 : const unsigned char *readp = start;
10310 8 : const unsigned char *readendp = ((const unsigned char *) data->d_buf
10311 4 : + data->d_size);
10312 :
10313 8 : while (readp < readendp)
10314 : {
10315 : /* Most string offset tables will have a header. For split
10316 : dwarf unit GNU DebugFission didn't add one. But they were
10317 : also only defined for split units (main or skeleton units
10318 : didn't have indirect strings). So if we don't have a
10319 : DW_AT_str_offsets_base at all and this is offset zero, then
10320 : just start printing offsets immediately, if this is a .dwo
10321 : section. */
10322 8 : Dwarf_Off off = (Dwarf_Off) (readp
10323 4 : - (const unsigned char *) data->d_buf);
10324 :
10325 4 : printf ("Table at offset %" PRIx64 " ", off);
10326 :
10327 4 : struct listptr *listptr = get_listptr (&known_stroffbases, idx++);
10328 0 : const unsigned char *next_unitp = readendp;
10329 0 : uint8_t offset_size;
10330 0 : bool has_header;
10331 0 : if (listptr == NULL)
10332 : {
10333 : /* This can happen for .dwo files. There is only an header
10334 : in the case this is a version 5 split DWARF file. */
10335 4 : Dwarf_CU *cu;
10336 4 : uint8_t unit_type;
10337 4 : if (dwarf_get_units (dbg, NULL, &cu, NULL, &unit_type,
10338 : NULL, NULL) != 0)
10339 : {
10340 0 : error (0, 0, "Warning: Cannot find any DWARF unit.");
10341 : /* Just guess some values. */
10342 0 : has_header = false;
10343 0 : offset_size = 4;
10344 : }
10345 4 : else if (off == 0
10346 4 : && (unit_type == DW_UT_split_type
10347 4 : || unit_type == DW_UT_split_compile))
10348 : {
10349 4 : has_header = cu->version > 4;
10350 4 : offset_size = cu->offset_size;
10351 : }
10352 : else
10353 : {
10354 0 : error (0, 0,
10355 : "Warning: No CU references .debug_str_offsets after %"
10356 : PRIx64, off);
10357 0 : has_header = cu->version > 4;
10358 0 : offset_size = cu->offset_size;
10359 : }
10360 4 : printf ("\n");
10361 : }
10362 : else
10363 : {
10364 : /* This must be DWARF5, since GNU DebugFission didn't define
10365 : DW_AT_str_offsets_base. */
10366 0 : has_header = true;
10367 :
10368 0 : Dwarf_Die cudie;
10369 0 : if (dwarf_cu_die (listptr->cu, &cudie,
10370 : NULL, NULL, NULL, NULL,
10371 : NULL, NULL) == NULL)
10372 0 : printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
10373 : else
10374 0 : printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
10375 : }
10376 :
10377 4 : if (has_header)
10378 : {
10379 2 : uint64_t unit_length;
10380 2 : uint16_t version;
10381 2 : uint16_t padding;
10382 :
10383 2 : unit_length = read_4ubyte_unaligned_inc (dbg, readp);
10384 2 : if (unlikely (unit_length == 0xffffffff))
10385 : {
10386 0 : if (unlikely (readp > readendp - 8))
10387 : {
10388 0 : invalid_data:
10389 0 : error (0, 0, "Invalid data");
10390 0 : return;
10391 : }
10392 0 : unit_length = read_8ubyte_unaligned_inc (dbg, readp);
10393 0 : offset_size = 8;
10394 : }
10395 : else
10396 : offset_size = 4;
10397 :
10398 2 : printf ("\n");
10399 2 : printf (gettext (" Length: %8" PRIu64 "\n"),
10400 : unit_length);
10401 2 : printf (gettext (" Offset size: %8" PRIu8 "\n"),
10402 : offset_size);
10403 :
10404 : /* We need at least 2-bytes (version) + 2-bytes (padding) =
10405 : 4 bytes to complete the header. And this unit cannot go
10406 : beyond the section data. */
10407 2 : if (readp > readendp - 4
10408 2 : || unit_length < 4
10409 2 : || unit_length > (uint64_t) (readendp - readp))
10410 : goto invalid_data;
10411 :
10412 2 : next_unitp = readp + unit_length;
10413 :
10414 2 : version = read_2ubyte_unaligned_inc (dbg, readp);
10415 2 : printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
10416 :
10417 2 : if (version != 5)
10418 : {
10419 0 : error (0, 0, gettext ("Unknown version"));
10420 0 : goto next_unit;
10421 : }
10422 :
10423 2 : padding = read_2ubyte_unaligned_inc (dbg, readp);
10424 2 : printf (gettext (" Padding: %8" PRIx16 "\n"), padding);
10425 :
10426 2 : if (listptr != NULL
10427 0 : && listptr->offset != (Dwarf_Off) (readp - start))
10428 : {
10429 0 : error (0, 0, "String offsets index doesn't start after header");
10430 0 : goto next_unit;
10431 : }
10432 :
10433 2 : printf ("\n");
10434 : }
10435 :
10436 4 : int digits = 1;
10437 4 : size_t offsets = (next_unitp - readp) / offset_size;
10438 8 : while (offsets >= 10)
10439 : {
10440 4 : ++digits;
10441 4 : offsets /= 10;
10442 : }
10443 :
10444 4 : unsigned int uidx = 0;
10445 4 : size_t index_offset = readp - (const unsigned char *) data->d_buf;
10446 4 : printf (" Offsets start at 0x%zx:\n", index_offset);
10447 64 : while (readp <= next_unitp - offset_size)
10448 : {
10449 60 : Dwarf_Word offset;
10450 60 : if (offset_size == 4)
10451 60 : offset = read_4ubyte_unaligned_inc (dbg, readp);
10452 : else
10453 0 : offset = read_8ubyte_unaligned_inc (dbg, readp);
10454 60 : const char *str = dwarf_getstring (dbg, offset, NULL);
10455 60 : printf (" [%*u] [%*" PRIx64 "] \"%s\"\n",
10456 60 : digits, uidx++, (int) offset_size * 2, offset, str ?: "???");
10457 : }
10458 4 : printf ("\n");
10459 :
10460 4 : if (readp != next_unitp)
10461 0 : error (0, 0, "extra %zd bytes at end of unit",
10462 0 : (size_t) (next_unitp - readp));
10463 :
10464 4 : next_unit:
10465 : readp = next_unitp;
10466 : }
10467 : }
10468 :
10469 :
10470 : /* Print the content of the call frame search table section
10471 : '.eh_frame_hdr'. */
10472 : static void
10473 14 : print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10474 : Ebl *ebl __attribute__ ((unused)),
10475 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10476 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10477 : {
10478 14 : printf (gettext ("\
10479 : \nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
10480 : elf_ndxscn (scn));
10481 :
10482 14 : Elf_Data *data = elf_rawdata (scn, NULL);
10483 :
10484 14 : if (unlikely (data == NULL))
10485 : {
10486 0 : error (0, 0, gettext ("cannot get %s content: %s"),
10487 : ".eh_frame_hdr", elf_errmsg (-1));
10488 0 : return;
10489 : }
10490 :
10491 14 : const unsigned char *readp = data->d_buf;
10492 28 : const unsigned char *const dataend = ((unsigned char *) data->d_buf
10493 14 : + data->d_size);
10494 :
10495 14 : if (unlikely (readp + 4 > dataend))
10496 : {
10497 0 : invalid_data:
10498 0 : error (0, 0, gettext ("invalid data"));
10499 0 : return;
10500 : }
10501 :
10502 14 : unsigned int version = *readp++;
10503 14 : unsigned int eh_frame_ptr_enc = *readp++;
10504 14 : unsigned int fde_count_enc = *readp++;
10505 14 : unsigned int table_enc = *readp++;
10506 :
10507 14 : printf (" version: %u\n"
10508 : " eh_frame_ptr_enc: %#x ",
10509 : version, eh_frame_ptr_enc);
10510 14 : print_encoding_base ("", eh_frame_ptr_enc);
10511 14 : printf (" fde_count_enc: %#x ", fde_count_enc);
10512 14 : print_encoding_base ("", fde_count_enc);
10513 14 : printf (" table_enc: %#x ", table_enc);
10514 14 : print_encoding_base ("", table_enc);
10515 :
10516 14 : uint64_t eh_frame_ptr = 0;
10517 14 : if (eh_frame_ptr_enc != DW_EH_PE_omit)
10518 : {
10519 14 : readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
10520 : dbg);
10521 14 : if (unlikely (readp == NULL))
10522 : goto invalid_data;
10523 :
10524 14 : printf (" eh_frame_ptr: %#" PRIx64, eh_frame_ptr);
10525 14 : if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
10526 28 : printf (" (offset: %#" PRIx64 ")",
10527 : /* +4 because of the 4 byte header of the section. */
10528 14 : (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
10529 :
10530 14 : putchar_unlocked ('\n');
10531 : }
10532 :
10533 14 : uint64_t fde_count = 0;
10534 14 : if (fde_count_enc != DW_EH_PE_omit)
10535 : {
10536 14 : readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
10537 14 : if (unlikely (readp == NULL))
10538 : goto invalid_data;
10539 :
10540 14 : printf (" fde_count: %" PRIu64 "\n", fde_count);
10541 : }
10542 :
10543 14 : if (fde_count == 0 || table_enc == DW_EH_PE_omit)
10544 : return;
10545 :
10546 14 : puts (" Table:");
10547 :
10548 : /* Optimize for the most common case. */
10549 14 : if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
10550 4446 : while (fde_count > 0 && readp + 8 <= dataend)
10551 : {
10552 4432 : int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
10553 8864 : uint64_t initial_offset = ((uint64_t) shdr->sh_offset
10554 4432 : + (int64_t) initial_location);
10555 4432 : int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
10556 : // XXX Possibly print symbol name or section offset for initial_offset
10557 8864 : printf (" %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
10558 : " fde=[%6" PRIx64 "]\n",
10559 : initial_location, initial_offset,
10560 4432 : address, address - (eh_frame_ptr + 4));
10561 : }
10562 : else
10563 : while (0 && readp < dataend)
10564 : {
10565 :
10566 14 : }
10567 : }
10568 :
10569 :
10570 : /* Print the content of the exception handling table section
10571 : '.eh_frame_hdr'. */
10572 : static void
10573 0 : print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
10574 : Ebl *ebl __attribute__ ((unused)),
10575 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10576 : Elf_Scn *scn,
10577 : GElf_Shdr *shdr __attribute__ ((unused)),
10578 : Dwarf *dbg __attribute__ ((unused)))
10579 : {
10580 0 : printf (gettext ("\
10581 : \nException handling table section [%2zu] '.gcc_except_table':\n"),
10582 : elf_ndxscn (scn));
10583 :
10584 0 : Elf_Data *data = elf_rawdata (scn, NULL);
10585 :
10586 0 : if (unlikely (data == NULL))
10587 : {
10588 0 : error (0, 0, gettext ("cannot get %s content: %s"),
10589 : ".gcc_except_table", elf_errmsg (-1));
10590 0 : return;
10591 : }
10592 :
10593 0 : const unsigned char *readp = data->d_buf;
10594 0 : const unsigned char *const dataend = readp + data->d_size;
10595 :
10596 0 : if (unlikely (readp + 1 > dataend))
10597 : {
10598 0 : invalid_data:
10599 0 : error (0, 0, gettext ("invalid data"));
10600 0 : return;
10601 : }
10602 0 : unsigned int lpstart_encoding = *readp++;
10603 0 : printf (gettext (" LPStart encoding: %#x "), lpstart_encoding);
10604 0 : print_encoding_base ("", lpstart_encoding);
10605 0 : if (lpstart_encoding != DW_EH_PE_omit)
10606 : {
10607 0 : uint64_t lpstart;
10608 0 : readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
10609 0 : printf (" LPStart: %#" PRIx64 "\n", lpstart);
10610 : }
10611 :
10612 0 : if (unlikely (readp + 1 > dataend))
10613 : goto invalid_data;
10614 0 : unsigned int ttype_encoding = *readp++;
10615 0 : printf (gettext (" TType encoding: %#x "), ttype_encoding);
10616 0 : print_encoding_base ("", ttype_encoding);
10617 0 : const unsigned char *ttype_base = NULL;
10618 0 : if (ttype_encoding != DW_EH_PE_omit)
10619 : {
10620 0 : unsigned int ttype_base_offset;
10621 0 : get_uleb128 (ttype_base_offset, readp, dataend);
10622 0 : printf (" TType base offset: %#x\n", ttype_base_offset);
10623 0 : if ((size_t) (dataend - readp) > ttype_base_offset)
10624 0 : ttype_base = readp + ttype_base_offset;
10625 : }
10626 :
10627 0 : if (unlikely (readp + 1 > dataend))
10628 : goto invalid_data;
10629 0 : unsigned int call_site_encoding = *readp++;
10630 0 : printf (gettext (" Call site encoding: %#x "), call_site_encoding);
10631 0 : print_encoding_base ("", call_site_encoding);
10632 0 : unsigned int call_site_table_len;
10633 0 : get_uleb128 (call_site_table_len, readp, dataend);
10634 :
10635 0 : const unsigned char *const action_table = readp + call_site_table_len;
10636 0 : if (unlikely (action_table > dataend))
10637 : goto invalid_data;
10638 : unsigned int u = 0;
10639 : unsigned int max_action = 0;
10640 0 : while (readp < action_table)
10641 : {
10642 0 : if (u == 0)
10643 0 : puts (gettext ("\n Call site table:"));
10644 :
10645 0 : uint64_t call_site_start;
10646 0 : readp = read_encoded (call_site_encoding, readp, dataend,
10647 : &call_site_start, dbg);
10648 0 : uint64_t call_site_length;
10649 0 : readp = read_encoded (call_site_encoding, readp, dataend,
10650 : &call_site_length, dbg);
10651 0 : uint64_t landing_pad;
10652 0 : readp = read_encoded (call_site_encoding, readp, dataend,
10653 : &landing_pad, dbg);
10654 0 : unsigned int action;
10655 0 : get_uleb128 (action, readp, dataend);
10656 0 : max_action = MAX (action, max_action);
10657 0 : printf (gettext (" [%4u] Call site start: %#" PRIx64 "\n"
10658 : " Call site length: %" PRIu64 "\n"
10659 : " Landing pad: %#" PRIx64 "\n"
10660 : " Action: %u\n"),
10661 : u++, call_site_start, call_site_length, landing_pad, action);
10662 : }
10663 0 : if (readp != action_table)
10664 : goto invalid_data;
10665 :
10666 0 : unsigned int max_ar_filter = 0;
10667 0 : if (max_action > 0)
10668 : {
10669 0 : puts ("\n Action table:");
10670 :
10671 0 : size_t maxdata = (size_t) (dataend - action_table);
10672 0 : if (max_action > maxdata || maxdata - max_action < 1)
10673 : {
10674 0 : invalid_action_table:
10675 0 : fputs (gettext (" <INVALID DATA>\n"), stdout);
10676 0 : return;
10677 : }
10678 :
10679 0 : const unsigned char *const action_table_end
10680 0 : = action_table + max_action + 1;
10681 :
10682 0 : u = 0;
10683 0 : do
10684 : {
10685 0 : int ar_filter;
10686 0 : get_sleb128 (ar_filter, readp, action_table_end);
10687 0 : if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
10688 0 : max_ar_filter = ar_filter;
10689 0 : int ar_disp;
10690 0 : if (readp >= action_table_end)
10691 : goto invalid_action_table;
10692 0 : get_sleb128 (ar_disp, readp, action_table_end);
10693 :
10694 0 : printf (" [%4u] ar_filter: % d\n"
10695 : " ar_disp: % -5d",
10696 : u, ar_filter, ar_disp);
10697 0 : if (abs (ar_disp) & 1)
10698 0 : printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
10699 0 : else if (ar_disp != 0)
10700 0 : puts (" -> ???");
10701 : else
10702 0 : putchar_unlocked ('\n');
10703 0 : ++u;
10704 : }
10705 0 : while (readp < action_table_end);
10706 : }
10707 :
10708 0 : if (max_ar_filter > 0 && ttype_base != NULL)
10709 : {
10710 0 : unsigned char dsize;
10711 0 : puts ("\n TType table:");
10712 :
10713 : // XXX Not *4, size of encoding;
10714 0 : switch (ttype_encoding & 7)
10715 : {
10716 : case DW_EH_PE_udata2:
10717 : case DW_EH_PE_sdata2:
10718 : dsize = 2;
10719 : break;
10720 : case DW_EH_PE_udata4:
10721 : case DW_EH_PE_sdata4:
10722 : dsize = 4;
10723 : break;
10724 : case DW_EH_PE_udata8:
10725 : case DW_EH_PE_sdata8:
10726 : dsize = 8;
10727 : break;
10728 0 : default:
10729 0 : dsize = 0;
10730 0 : error (1, 0, gettext ("invalid TType encoding"));
10731 : }
10732 :
10733 0 : if (max_ar_filter
10734 0 : > (size_t) (ttype_base - (const unsigned char *) data->d_buf) / dsize)
10735 : goto invalid_data;
10736 :
10737 0 : readp = ttype_base - max_ar_filter * dsize;
10738 0 : do
10739 : {
10740 0 : uint64_t ttype;
10741 0 : readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
10742 : dbg);
10743 0 : printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
10744 : }
10745 0 : while (readp < ttype_base);
10746 : }
10747 : }
10748 :
10749 : /* Print the content of the '.gdb_index' section.
10750 : http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
10751 : */
10752 : static void
10753 2 : print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
10754 : GElf_Ehdr *ehdr __attribute__ ((unused)),
10755 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10756 : {
10757 2 : printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
10758 : " contains %" PRId64 " bytes :\n"),
10759 : elf_ndxscn (scn), section_name (ebl, shdr),
10760 2 : (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
10761 :
10762 2 : Elf_Data *data = elf_rawdata (scn, NULL);
10763 :
10764 2 : if (unlikely (data == NULL))
10765 : {
10766 0 : error (0, 0, gettext ("cannot get %s content: %s"),
10767 : ".gdb_index", elf_errmsg (-1));
10768 0 : return;
10769 : }
10770 :
10771 : // .gdb_index is always in little endian.
10772 2 : Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
10773 2 : dbg = &dummy_dbg;
10774 :
10775 2 : const unsigned char *readp = data->d_buf;
10776 2 : const unsigned char *const dataend = readp + data->d_size;
10777 :
10778 2 : if (unlikely (readp + 4 > dataend))
10779 : {
10780 0 : invalid_data:
10781 0 : error (0, 0, gettext ("invalid data"));
10782 0 : return;
10783 : }
10784 :
10785 2 : int32_t vers = read_4ubyte_unaligned (dbg, readp);
10786 2 : printf (gettext (" Version: %" PRId32 "\n"), vers);
10787 :
10788 : // The only difference between version 4 and version 5 is the
10789 : // hash used for generating the table. Version 6 contains symbols
10790 : // for inlined functions, older versions didn't. Version 7 adds
10791 : // symbol kinds. Version 8 just indicates that it correctly includes
10792 : // TUs for symbols.
10793 2 : if (vers < 4 || vers > 8)
10794 : {
10795 0 : printf (gettext (" unknown version, cannot parse section\n"));
10796 0 : return;
10797 : }
10798 :
10799 2 : readp += 4;
10800 2 : if (unlikely (readp + 4 > dataend))
10801 : goto invalid_data;
10802 :
10803 2 : uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
10804 2 : printf (gettext (" CU offset: %#" PRIx32 "\n"), cu_off);
10805 :
10806 2 : readp += 4;
10807 2 : if (unlikely (readp + 4 > dataend))
10808 : goto invalid_data;
10809 :
10810 2 : uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
10811 2 : printf (gettext (" TU offset: %#" PRIx32 "\n"), tu_off);
10812 :
10813 2 : readp += 4;
10814 2 : if (unlikely (readp + 4 > dataend))
10815 : goto invalid_data;
10816 :
10817 2 : uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
10818 2 : printf (gettext (" address offset: %#" PRIx32 "\n"), addr_off);
10819 :
10820 2 : readp += 4;
10821 2 : if (unlikely (readp + 4 > dataend))
10822 : goto invalid_data;
10823 :
10824 2 : uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
10825 2 : printf (gettext (" symbol offset: %#" PRIx32 "\n"), sym_off);
10826 :
10827 2 : readp += 4;
10828 2 : if (unlikely (readp + 4 > dataend))
10829 : goto invalid_data;
10830 :
10831 2 : uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
10832 2 : printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
10833 :
10834 2 : if (unlikely ((size_t) (dataend - (const unsigned char *) data->d_buf)
10835 : < const_off))
10836 : goto invalid_data;
10837 :
10838 2 : readp = data->d_buf + cu_off;
10839 :
10840 2 : const unsigned char *nextp = data->d_buf + tu_off;
10841 2 : if (tu_off >= data->d_size)
10842 : goto invalid_data;
10843 :
10844 2 : size_t cu_nr = (nextp - readp) / 16;
10845 :
10846 2 : printf (gettext ("\n CU list at offset %#" PRIx32
10847 : " contains %zu entries:\n"),
10848 : cu_off, cu_nr);
10849 :
10850 2 : size_t n = 0;
10851 6 : while (dataend - readp >= 16 && n < cu_nr)
10852 : {
10853 4 : uint64_t off = read_8ubyte_unaligned (dbg, readp);
10854 4 : readp += 8;
10855 :
10856 4 : uint64_t len = read_8ubyte_unaligned (dbg, readp);
10857 4 : readp += 8;
10858 :
10859 4 : printf (" [%4zu] start: %0#8" PRIx64
10860 : ", length: %5" PRIu64 "\n", n, off, len);
10861 4 : n++;
10862 : }
10863 :
10864 2 : readp = data->d_buf + tu_off;
10865 2 : nextp = data->d_buf + addr_off;
10866 2 : if (addr_off >= data->d_size)
10867 : goto invalid_data;
10868 :
10869 2 : size_t tu_nr = (nextp - readp) / 24;
10870 :
10871 2 : printf (gettext ("\n TU list at offset %#" PRIx32
10872 : " contains %zu entries:\n"),
10873 : tu_off, tu_nr);
10874 :
10875 2 : n = 0;
10876 4 : while (dataend - readp >= 24 && n < tu_nr)
10877 : {
10878 2 : uint64_t off = read_8ubyte_unaligned (dbg, readp);
10879 2 : readp += 8;
10880 :
10881 2 : uint64_t type = read_8ubyte_unaligned (dbg, readp);
10882 2 : readp += 8;
10883 :
10884 2 : uint64_t sig = read_8ubyte_unaligned (dbg, readp);
10885 2 : readp += 8;
10886 :
10887 2 : printf (" [%4zu] CU offset: %5" PRId64
10888 : ", type offset: %5" PRId64
10889 : ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
10890 2 : n++;
10891 : }
10892 :
10893 2 : readp = data->d_buf + addr_off;
10894 2 : nextp = data->d_buf + sym_off;
10895 2 : if (sym_off >= data->d_size)
10896 : goto invalid_data;
10897 :
10898 2 : size_t addr_nr = (nextp - readp) / 20;
10899 :
10900 2 : printf (gettext ("\n Address list at offset %#" PRIx32
10901 : " contains %zu entries:\n"),
10902 : addr_off, addr_nr);
10903 :
10904 2 : n = 0;
10905 6 : while (dataend - readp >= 20 && n < addr_nr)
10906 : {
10907 4 : uint64_t low = read_8ubyte_unaligned (dbg, readp);
10908 4 : readp += 8;
10909 :
10910 4 : uint64_t high = read_8ubyte_unaligned (dbg, readp);
10911 4 : readp += 8;
10912 :
10913 4 : uint32_t idx = read_4ubyte_unaligned (dbg, readp);
10914 4 : readp += 4;
10915 :
10916 4 : printf (" [%4zu] ", n);
10917 4 : print_dwarf_addr (dwflmod, 8, low, low);
10918 4 : printf ("..");
10919 4 : print_dwarf_addr (dwflmod, 8, high - 1, high);
10920 4 : printf (", CU index: %5" PRId32 "\n", idx);
10921 4 : n++;
10922 : }
10923 :
10924 2 : const unsigned char *const_start = data->d_buf + const_off;
10925 2 : if (const_off >= data->d_size)
10926 : goto invalid_data;
10927 :
10928 2 : readp = data->d_buf + sym_off;
10929 2 : nextp = const_start;
10930 2 : size_t sym_nr = (nextp - readp) / 8;
10931 :
10932 2 : printf (gettext ("\n Symbol table at offset %#" PRIx32
10933 : " contains %zu slots:\n"),
10934 : addr_off, sym_nr);
10935 :
10936 2 : n = 0;
10937 2050 : while (dataend - readp >= 8 && n < sym_nr)
10938 : {
10939 2048 : uint32_t name = read_4ubyte_unaligned (dbg, readp);
10940 2048 : readp += 4;
10941 :
10942 2048 : uint32_t vector = read_4ubyte_unaligned (dbg, readp);
10943 2048 : readp += 4;
10944 :
10945 2048 : if (name != 0 || vector != 0)
10946 : {
10947 14 : const unsigned char *sym = const_start + name;
10948 14 : if (unlikely ((size_t) (dataend - const_start) < name
10949 : || memchr (sym, '\0', dataend - sym) == NULL))
10950 : goto invalid_data;
10951 :
10952 14 : printf (" [%4zu] symbol: %s, CUs: ", n, sym);
10953 :
10954 14 : const unsigned char *readcus = const_start + vector;
10955 14 : if (unlikely ((size_t) (dataend - const_start) < vector))
10956 : goto invalid_data;
10957 14 : uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
10958 30 : while (cus--)
10959 : {
10960 16 : uint32_t cu_kind, cu, kind;
10961 16 : bool is_static;
10962 16 : readcus += 4;
10963 16 : if (unlikely (readcus + 4 > dataend))
10964 : goto invalid_data;
10965 16 : cu_kind = read_4ubyte_unaligned (dbg, readcus);
10966 16 : cu = cu_kind & ((1 << 24) - 1);
10967 16 : kind = (cu_kind >> 28) & 7;
10968 16 : is_static = cu_kind & (1U << 31);
10969 16 : if (cu > cu_nr - 1)
10970 2 : printf ("%" PRId32 "T", cu - (uint32_t) cu_nr);
10971 : else
10972 14 : printf ("%" PRId32, cu);
10973 16 : if (kind != 0)
10974 : {
10975 8 : printf (" (");
10976 8 : switch (kind)
10977 : {
10978 : case 1:
10979 3 : printf ("type");
10980 : break;
10981 : case 2:
10982 2 : printf ("var");
10983 : break;
10984 : case 3:
10985 3 : printf ("func");
10986 : break;
10987 : case 4:
10988 0 : printf ("other");
10989 : break;
10990 : default:
10991 0 : printf ("unknown-0x%" PRIx32, kind);
10992 : break;
10993 : }
10994 11 : printf (":%c)", (is_static ? 'S' : 'G'));
10995 : }
10996 16 : if (cus > 0)
10997 2 : printf (", ");
10998 : }
10999 14 : printf ("\n");
11000 : }
11001 2048 : n++;
11002 : }
11003 : }
11004 :
11005 : /* Returns true and sets split DWARF CU id if there is a split compile
11006 : unit in the given Dwarf, and no non-split units are found (before it). */
11007 : static bool
11008 121 : is_split_dwarf (Dwarf *dbg, uint64_t *id, Dwarf_CU **split_cu)
11009 : {
11010 121 : Dwarf_CU *cu = NULL;
11011 121 : while (dwarf_get_units (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
11012 : {
11013 121 : uint8_t unit_type;
11014 121 : if (dwarf_cu_info (cu, NULL, &unit_type, NULL, NULL,
11015 : id, NULL, NULL) != 0)
11016 121 : return false;
11017 :
11018 121 : if (unit_type != DW_UT_split_compile && unit_type != DW_UT_split_type)
11019 : return false;
11020 :
11021 : /* We really only care about the split compile unit, the types
11022 : should be fine and self sufficient. Also they don't have an
11023 : id that we can match with a skeleton unit. */
11024 9 : if (unit_type == DW_UT_split_compile)
11025 : {
11026 9 : *split_cu = cu;
11027 9 : return true;
11028 : }
11029 : }
11030 :
11031 : return false;
11032 : }
11033 :
11034 : /* Check that there is one and only one Dwfl_Module, return in arg. */
11035 : static int
11036 9 : getone_dwflmod (Dwfl_Module *dwflmod,
11037 : void **userdata __attribute__ ((unused)),
11038 : const char *name __attribute__ ((unused)),
11039 : Dwarf_Addr base __attribute__ ((unused)),
11040 : void *arg)
11041 : {
11042 9 : Dwfl_Module **m = (Dwfl_Module **) arg;
11043 9 : if (*m != NULL)
11044 : return DWARF_CB_ABORT;
11045 9 : *m = dwflmod;
11046 9 : return DWARF_CB_OK;
11047 : }
11048 :
11049 : static void
11050 151 : print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
11051 : {
11052 : /* Used for skeleton file, if necessary for split DWARF. */
11053 151 : Dwfl *skel_dwfl = NULL;
11054 151 : Dwfl_Module *skel_mod = NULL;
11055 151 : char *skel_name = NULL;
11056 151 : Dwarf *split_dbg = NULL;
11057 151 : Dwarf_CU *split_cu = NULL;
11058 :
11059 : /* Before we start the real work get a debug context descriptor. */
11060 151 : Dwarf_Addr dwbias;
11061 151 : Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
11062 453 : Dwarf dummy_dbg =
11063 : {
11064 151 : .elf = ebl->elf,
11065 151 : .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
11066 : };
11067 151 : if (dbg == NULL)
11068 : {
11069 30 : if ((print_debug_sections & ~section_exception) != 0)
11070 0 : error (0, 0, gettext ("cannot get debug context descriptor: %s"),
11071 : dwfl_errmsg (-1));
11072 : dbg = &dummy_dbg;
11073 : }
11074 : else
11075 : {
11076 : /* If we are asked about a split dwarf (.dwo) file, use the user
11077 : provided, or find the corresponding skeleton file. If we got
11078 : a skeleton file, replace the given dwflmod and dbg, with one
11079 : derived from the skeleton file to provide enough context. */
11080 121 : uint64_t split_id;
11081 121 : if (is_split_dwarf (dbg, &split_id, &split_cu))
11082 : {
11083 9 : if (dwarf_skeleton != NULL)
11084 9 : skel_name = strdup (dwarf_skeleton);
11085 : else
11086 : {
11087 : /* Replace file.dwo with file.o and see if that matches. */
11088 0 : const char *fname;
11089 0 : dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL,
11090 : &fname, NULL);
11091 0 : if (fname != NULL)
11092 : {
11093 0 : size_t flen = strlen (fname);
11094 0 : if (flen > 4 && strcmp (".dwo", fname + flen - 4) == 0)
11095 : {
11096 0 : skel_name = strdup (fname);
11097 0 : if (skel_name != NULL)
11098 : {
11099 0 : skel_name[flen - 3] = 'o';
11100 0 : skel_name[flen - 2] = '\0';
11101 : }
11102 : }
11103 : }
11104 : }
11105 :
11106 9 : if (skel_name != NULL)
11107 : {
11108 9 : int skel_fd = open (skel_name, O_RDONLY);
11109 9 : if (skel_fd == -1)
11110 0 : fprintf (stderr, "Warning: Couldn't open DWARF skeleton file"
11111 : " '%s'\n", skel_name);
11112 : else
11113 9 : skel_dwfl = create_dwfl (skel_fd, skel_name);
11114 :
11115 9 : if (skel_dwfl != NULL)
11116 : {
11117 9 : if (dwfl_getmodules (skel_dwfl, &getone_dwflmod,
11118 : &skel_mod, 0) != 0)
11119 : {
11120 0 : fprintf (stderr, "Warning: Bad DWARF skeleton,"
11121 : " multiple modules '%s'\n", skel_name);
11122 0 : dwfl_end (skel_dwfl);
11123 0 : skel_mod = NULL;
11124 : }
11125 : }
11126 0 : else if (skel_fd != -1)
11127 0 : fprintf (stderr, "Warning: Couldn't create skeleton dwfl for"
11128 : " '%s': %s\n", skel_name, dwfl_errmsg (-1));
11129 :
11130 9 : if (skel_mod != NULL)
11131 : {
11132 9 : Dwarf *skel_dbg = dwfl_module_getdwarf (skel_mod, &dwbias);
11133 9 : if (skel_dbg != NULL)
11134 : {
11135 : /* First check the skeleton CU DIE, only fetch
11136 : the split DIE if we know the id matches to
11137 : not unnecessary search for any split DIEs we
11138 : don't need. */
11139 9 : Dwarf_CU *cu = NULL;
11140 13 : while (dwarf_get_units (skel_dbg, cu, &cu,
11141 : NULL, NULL, NULL, NULL) == 0)
11142 : {
11143 13 : uint8_t unit_type;
11144 13 : uint64_t skel_id;
11145 13 : if (dwarf_cu_info (cu, NULL, &unit_type, NULL, NULL,
11146 : &skel_id, NULL, NULL) == 0
11147 13 : && unit_type == DW_UT_skeleton
11148 13 : && split_id == skel_id)
11149 : {
11150 9 : Dwarf_Die subdie;
11151 9 : if (dwarf_cu_info (cu, NULL, NULL, NULL,
11152 : &subdie,
11153 : NULL, NULL, NULL) == 0
11154 9 : && dwarf_tag (&subdie) != DW_TAG_invalid)
11155 : {
11156 9 : split_dbg = dwarf_cu_getdwarf (subdie.cu);
11157 9 : if (split_dbg == NULL)
11158 0 : fprintf (stderr,
11159 : "Warning: Couldn't get split_dbg:"
11160 : " %s\n", dwarf_errmsg (-1));
11161 9 : break;
11162 : }
11163 : else
11164 : {
11165 : /* Everything matches up, but not
11166 : according to libdw. Which means
11167 : the user knew better. So...
11168 : Terrible hack... We can never
11169 : destroy the underlying dwfl
11170 : because it would free the wrong
11171 : Dwarfs... So we leak memory...*/
11172 0 : if (cu->split == NULL
11173 0 : && dwarf_skeleton != NULL)
11174 : {
11175 0 : do_not_close_dwfl = true;
11176 0 : __libdw_link_skel_split (cu, split_cu);
11177 0 : split_dbg = dwarf_cu_getdwarf (split_cu);
11178 0 : break;
11179 : }
11180 : else
11181 0 : fprintf (stderr, "Warning: Couldn't get"
11182 : " skeleton subdie: %s\n",
11183 : dwarf_errmsg (-1));
11184 : }
11185 : }
11186 : }
11187 9 : if (split_dbg == NULL)
11188 0 : fprintf (stderr, "Warning: '%s' didn't contain a skeleton for split id %" PRIx64 "\n", skel_name, split_id);
11189 : }
11190 : else
11191 0 : fprintf (stderr, "Warning: Couldn't get skeleton DWARF:"
11192 : " %s\n", dwfl_errmsg (-1));
11193 : }
11194 : }
11195 :
11196 9 : if (split_dbg != NULL)
11197 : {
11198 9 : dbg = split_dbg;
11199 9 : dwflmod = skel_mod;
11200 : }
11201 0 : else if (skel_name == NULL)
11202 0 : fprintf (stderr,
11203 : "Warning: split DWARF file, but no skeleton found.\n");
11204 : }
11205 112 : else if (dwarf_skeleton != NULL)
11206 0 : fprintf (stderr, "Warning: DWARF skeleton given,"
11207 : " but not a split DWARF file\n");
11208 : }
11209 :
11210 : /* Get the section header string table index. */
11211 151 : size_t shstrndx;
11212 151 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
11213 0 : error (EXIT_FAILURE, 0,
11214 0 : gettext ("cannot get section header string table index"));
11215 :
11216 : /* If the .debug_info section is listed as implicitly required then
11217 : we must make sure to handle it before handling any other debug
11218 : section. Various other sections depend on the CU DIEs being
11219 : scanned (silently) first. */
11220 151 : bool implicit_info = (implicit_debug_sections & section_info) != 0;
11221 151 : bool explicit_info = (print_debug_sections & section_info) != 0;
11222 151 : if (implicit_info)
11223 : {
11224 : Elf_Scn *scn = NULL;
11225 1542 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
11226 : {
11227 1542 : GElf_Shdr shdr_mem;
11228 1542 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
11229 :
11230 1542 : if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
11231 : {
11232 1872 : const char *name = elf_strptr (ebl->elf, shstrndx,
11233 624 : shdr->sh_name);
11234 624 : if (name == NULL)
11235 0 : continue;
11236 :
11237 624 : if (strcmp (name, ".debug_info") == 0
11238 560 : || strcmp (name, ".debug_info.dwo") == 0
11239 551 : || strcmp (name, ".zdebug_info") == 0
11240 545 : || strcmp (name, ".zdebug_info.dwo") == 0)
11241 : {
11242 79 : print_debug_info_section (dwflmod, ebl, ehdr,
11243 : scn, shdr, dbg);
11244 79 : break;
11245 : }
11246 : }
11247 : }
11248 79 : print_debug_sections &= ~section_info;
11249 79 : implicit_debug_sections &= ~section_info;
11250 : }
11251 :
11252 : /* Look through all the sections for the debugging sections to print. */
11253 : Elf_Scn *scn = NULL;
11254 4524 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
11255 : {
11256 4373 : GElf_Shdr shdr_mem;
11257 4373 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
11258 :
11259 4373 : if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
11260 : {
11261 2113 : static const struct
11262 : {
11263 : const char *name;
11264 : enum section_e bitmask;
11265 : void (*fp) (Dwfl_Module *, Ebl *,
11266 : GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
11267 : } debug_sections[] =
11268 : {
11269 : #define NEW_SECTION(name) \
11270 : { ".debug_" #name, section_##name, print_debug_##name##_section }
11271 : NEW_SECTION (abbrev),
11272 : NEW_SECTION (addr),
11273 : NEW_SECTION (aranges),
11274 : NEW_SECTION (frame),
11275 : NEW_SECTION (info),
11276 : NEW_SECTION (types),
11277 : NEW_SECTION (line),
11278 : NEW_SECTION (loc),
11279 : /* loclists is loc for DWARF5. */
11280 : { ".debug_loclists", section_loc,
11281 : print_debug_loclists_section },
11282 : NEW_SECTION (pubnames),
11283 : NEW_SECTION (str),
11284 : /* A DWARF5 specialised debug string section. */
11285 : { ".debug_line_str", section_str,
11286 : print_debug_str_section },
11287 : /* DWARF5 string offsets table. */
11288 : { ".debug_str_offsets", section_str,
11289 : print_debug_str_offsets_section },
11290 : NEW_SECTION (macinfo),
11291 : NEW_SECTION (macro),
11292 : NEW_SECTION (ranges),
11293 : /* rnglists is ranges for DWARF5. */
11294 : { ".debug_rnglists", section_ranges,
11295 : print_debug_rnglists_section },
11296 : { ".eh_frame", section_frame | section_exception,
11297 : print_debug_frame_section },
11298 : { ".eh_frame_hdr", section_frame | section_exception,
11299 : print_debug_frame_hdr_section },
11300 : { ".gcc_except_table", section_frame | section_exception,
11301 : print_debug_exception_table },
11302 : { ".gdb_index", section_gdb_index, print_gdb_index_section }
11303 : };
11304 2113 : const int ndebug_sections = (sizeof (debug_sections)
11305 : / sizeof (debug_sections[0]));
11306 6339 : const char *name = elf_strptr (ebl->elf, shstrndx,
11307 2113 : shdr->sh_name);
11308 2113 : if (name == NULL)
11309 0 : continue;
11310 :
11311 : int n;
11312 33177 : for (n = 0; n < ndebug_sections; ++n)
11313 : {
11314 32050 : size_t dbglen = strlen (debug_sections[n].name);
11315 32050 : size_t scnlen = strlen (name);
11316 32050 : if ((strncmp (name, debug_sections[n].name, dbglen) == 0
11317 988 : && (dbglen == scnlen
11318 138 : || (scnlen == dbglen + 4
11319 121 : && strstr (name, ".dwo") == name + dbglen)))
11320 31146 : || (name[0] == '.' && name[1] == 'z'
11321 566 : && debug_sections[n].name[1] == 'd'
11322 566 : && strncmp (&name[2], &debug_sections[n].name[1],
11323 : dbglen - 1) == 0
11324 82 : && (scnlen == dbglen + 1
11325 0 : || (scnlen == dbglen + 5
11326 0 : && strstr (name, ".dwo") == name + dbglen + 1))))
11327 : {
11328 1972 : if ((print_debug_sections | implicit_debug_sections)
11329 986 : & debug_sections[n].bitmask)
11330 371 : debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
11331 : break;
11332 : }
11333 : }
11334 : }
11335 : }
11336 :
11337 151 : dwfl_end (skel_dwfl);
11338 151 : free (skel_name);
11339 :
11340 : /* Turn implicit and/or explicit back on in case we go over another file. */
11341 151 : if (implicit_info)
11342 79 : implicit_debug_sections |= section_info;
11343 151 : if (explicit_info)
11344 63 : print_debug_sections |= section_info;
11345 :
11346 302 : reset_listptr (&known_locsptr);
11347 302 : reset_listptr (&known_loclistsptr);
11348 302 : reset_listptr (&known_rangelistptr);
11349 302 : reset_listptr (&known_rnglistptr);
11350 302 : reset_listptr (&known_addrbases);
11351 302 : reset_listptr (&known_stroffbases);
11352 151 : }
11353 :
11354 :
11355 : #define ITEM_INDENT 4
11356 : #define WRAP_COLUMN 75
11357 :
11358 : /* Print "NAME: FORMAT", wrapping when output text would make the line
11359 : exceed WRAP_COLUMN. Unpadded numbers look better for the core items
11360 : but this function is also used for registers which should be printed
11361 : aligned. Fortunately registers output uses fixed fields width (such
11362 : as %11d) for the alignment.
11363 :
11364 : Line breaks should not depend on the particular values although that
11365 : may happen in some cases of the core items. */
11366 :
11367 : static unsigned int
11368 : __attribute__ ((format (printf, 6, 7)))
11369 821 : print_core_item (unsigned int colno, char sep, unsigned int wrap,
11370 : size_t name_width, const char *name, const char *format, ...)
11371 : {
11372 821 : size_t len = strlen (name);
11373 821 : if (name_width < len)
11374 397 : name_width = len;
11375 :
11376 821 : char *out;
11377 821 : va_list ap;
11378 821 : va_start (ap, format);
11379 821 : int out_len = vasprintf (&out, format, ap);
11380 821 : va_end (ap);
11381 821 : if (out_len == -1)
11382 0 : error (EXIT_FAILURE, 0, _("memory exhausted"));
11383 :
11384 821 : size_t n = name_width + sizeof ": " - 1 + out_len;
11385 :
11386 821 : if (colno == 0)
11387 : {
11388 51 : printf ("%*s", ITEM_INDENT, "");
11389 51 : colno = ITEM_INDENT + n;
11390 : }
11391 770 : else if (colno + 2 + n < wrap)
11392 : {
11393 468 : printf ("%c ", sep);
11394 468 : colno += 2 + n;
11395 : }
11396 : else
11397 : {
11398 302 : printf ("\n%*s", ITEM_INDENT, "");
11399 302 : colno = ITEM_INDENT + n;
11400 : }
11401 :
11402 821 : printf ("%s: %*s%s", name, (int) (name_width - len), "", out);
11403 :
11404 821 : free (out);
11405 :
11406 821 : return colno;
11407 : }
11408 :
11409 : static const void *
11410 931 : convert (Elf *core, Elf_Type type, uint_fast16_t count,
11411 : void *value, const void *data, size_t size)
11412 : {
11413 1862 : Elf_Data valuedata =
11414 : {
11415 : .d_type = type,
11416 : .d_buf = value,
11417 931 : .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
11418 : .d_version = EV_CURRENT,
11419 : };
11420 931 : Elf_Data indata =
11421 : {
11422 : .d_type = type,
11423 : .d_buf = (void *) data,
11424 : .d_size = valuedata.d_size,
11425 : .d_version = EV_CURRENT,
11426 : };
11427 :
11428 931 : Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
11429 931 : ? elf32_xlatetom : elf64_xlatetom)
11430 931 : (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
11431 931 : if (d == NULL)
11432 0 : error (EXIT_FAILURE, 0,
11433 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
11434 :
11435 931 : return data + indata.d_size;
11436 : }
11437 :
11438 : typedef uint8_t GElf_Byte;
11439 :
11440 : static unsigned int
11441 400 : handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
11442 : unsigned int colno, size_t *repeated_size)
11443 : {
11444 400 : uint_fast16_t count = item->count ?: 1;
11445 : /* Ebl_Core_Item count is always a small number.
11446 : Make sure the backend didn't put in some large bogus value. */
11447 62 : assert (count < 128);
11448 :
11449 : #define TYPES \
11450 : DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8); \
11451 : DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16); \
11452 : DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32); \
11453 : DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32); \
11454 : DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64); \
11455 : DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64)
11456 :
11457 : #define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name
11458 400 : typedef union { TYPES; } value_t;
11459 400 : void *data = alloca (count * sizeof (value_t));
11460 : #undef DO_TYPE
11461 :
11462 : #define DO_TYPE(NAME, Name, hex, dec) \
11463 : GElf_##Name *value_##Name __attribute__((unused)) = data
11464 400 : TYPES;
11465 : #undef DO_TYPE
11466 :
11467 400 : size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
11468 400 : size_t convsize = size;
11469 400 : if (repeated_size != NULL)
11470 : {
11471 1 : if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
11472 : {
11473 0 : data = alloca (*repeated_size);
11474 0 : count *= *repeated_size / size;
11475 0 : convsize = count * size;
11476 0 : *repeated_size -= convsize;
11477 : }
11478 1 : else if (item->count != 0 || item->format != '\n')
11479 0 : *repeated_size -= size;
11480 : }
11481 :
11482 400 : convert (core, item->type, count, data, desc + item->offset, convsize);
11483 :
11484 400 : Elf_Type type = item->type;
11485 400 : if (type == ELF_T_ADDR)
11486 1 : type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
11487 :
11488 400 : switch (item->format)
11489 : {
11490 193 : case 'd':
11491 193 : assert (count == 1);
11492 193 : switch (type)
11493 : {
11494 : #define DO_TYPE(NAME, Name, hex, dec) \
11495 : case ELF_T_##NAME: \
11496 : colno = print_core_item (colno, ',', WRAP_COLUMN, \
11497 : 0, item->name, dec, value_##Name[0]); \
11498 : break
11499 193 : TYPES;
11500 : #undef DO_TYPE
11501 0 : default:
11502 0 : abort ();
11503 : }
11504 : break;
11505 :
11506 111 : case 'x':
11507 111 : assert (count == 1);
11508 111 : switch (type)
11509 : {
11510 : #define DO_TYPE(NAME, Name, hex, dec) \
11511 : case ELF_T_##NAME: \
11512 : colno = print_core_item (colno, ',', WRAP_COLUMN, \
11513 : 0, item->name, hex, value_##Name[0]); \
11514 : break
11515 111 : TYPES;
11516 : #undef DO_TYPE
11517 0 : default:
11518 0 : abort ();
11519 : }
11520 : break;
11521 :
11522 22 : case 'b':
11523 : case 'B':
11524 22 : assert (size % sizeof (unsigned int) == 0);
11525 22 : unsigned int nbits = count * size * 8;
11526 22 : unsigned int pop = 0;
11527 56 : for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
11528 34 : pop += __builtin_popcount (*i);
11529 22 : bool negate = pop > nbits / 2;
11530 22 : const unsigned int bias = item->format == 'b';
11531 :
11532 44 : {
11533 22 : char printed[(negate ? nbits - pop : pop) * 16 + 1];
11534 22 : char *p = printed;
11535 22 : *p = '\0';
11536 :
11537 22 : if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
11538 : {
11539 : assert (size == sizeof (unsigned int) * 2);
11540 : for (unsigned int *i = data;
11541 : (void *) i < data + count * size; i += 2)
11542 : {
11543 : unsigned int w = i[1];
11544 : i[1] = i[0];
11545 : i[0] = w;
11546 : }
11547 : }
11548 :
11549 22 : unsigned int lastbit = 0;
11550 22 : unsigned int run = 0;
11551 56 : for (const unsigned int *i = data;
11552 34 : (void *) i < data + count * size; ++i)
11553 : {
11554 34 : unsigned int bit = ((void *) i - data) * 8;
11555 34 : unsigned int w = negate ? ~*i : *i;
11556 34 : while (w != 0)
11557 : {
11558 : /* Note that a right shift equal to (or greater than)
11559 : the number of bits of w is undefined behaviour. In
11560 : particular when the least significant bit is bit 32
11561 : (w = 0x8000000) then w >>= n is undefined. So
11562 : explicitly handle that case separately. */
11563 0 : unsigned int n = ffs (w);
11564 0 : if (n < sizeof (w) * 8)
11565 0 : w >>= n;
11566 : else
11567 : w = 0;
11568 0 : bit += n;
11569 :
11570 0 : if (lastbit != 0 && lastbit + 1 == bit)
11571 0 : ++run;
11572 : else
11573 : {
11574 0 : if (lastbit == 0)
11575 0 : p += sprintf (p, "%u", bit - bias);
11576 0 : else if (run == 0)
11577 0 : p += sprintf (p, ",%u", bit - bias);
11578 : else
11579 0 : p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
11580 : run = 0;
11581 : }
11582 :
11583 : lastbit = bit;
11584 : }
11585 : }
11586 22 : if (lastbit > 0 && run > 0 && lastbit + 1 != nbits)
11587 0 : p += sprintf (p, "-%u", lastbit - bias);
11588 :
11589 44 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
11590 : negate ? "~<%s>" : "<%s>", printed);
11591 : }
11592 22 : break;
11593 :
11594 44 : case 'T':
11595 : case (char) ('T'|0x80):
11596 44 : assert (count == 2);
11597 44 : Dwarf_Word sec;
11598 44 : Dwarf_Word usec;
11599 44 : switch (type)
11600 : {
11601 : #define DO_TYPE(NAME, Name, hex, dec) \
11602 : case ELF_T_##NAME: \
11603 : sec = value_##Name[0]; \
11604 : usec = value_##Name[1]; \
11605 : break
11606 44 : TYPES;
11607 : #undef DO_TYPE
11608 0 : default:
11609 0 : abort ();
11610 : }
11611 44 : if (unlikely (item->format == (char) ('T'|0x80)))
11612 : {
11613 : /* This is a hack for an ill-considered 64-bit ABI where
11614 : tv_usec is actually a 32-bit field with 32 bits of padding
11615 : rounding out struct timeval. We've already converted it as
11616 : a 64-bit field. For little-endian, this just means the
11617 : high half is the padding; it's presumably zero, but should
11618 : be ignored anyway. For big-endian, it means the 32-bit
11619 : field went into the high half of USEC. */
11620 0 : GElf_Ehdr ehdr_mem;
11621 0 : GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
11622 0 : if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
11623 0 : usec >>= 32;
11624 : else
11625 0 : usec &= UINT32_MAX;
11626 : }
11627 44 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
11628 : "%" PRIu64 ".%.6" PRIu64, sec, usec);
11629 44 : break;
11630 :
11631 9 : case 'c':
11632 9 : assert (count == 1);
11633 18 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
11634 9 : "%c", value_Byte[0]);
11635 9 : break;
11636 :
11637 18 : case 's':
11638 18 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
11639 : "%.*s", (int) count, value_Byte);
11640 18 : break;
11641 :
11642 1 : case '\n':
11643 : /* This is a list of strings separated by '\n'. */
11644 1 : assert (item->count == 0);
11645 1 : assert (repeated_size != NULL);
11646 1 : assert (item->name == NULL);
11647 1 : if (unlikely (item->offset >= *repeated_size))
11648 : break;
11649 :
11650 1 : const char *s = desc + item->offset;
11651 1 : size = *repeated_size - item->offset;
11652 1 : *repeated_size = 0;
11653 48 : while (size > 0)
11654 : {
11655 48 : const char *eol = memchr (s, '\n', size);
11656 48 : int len = size;
11657 48 : if (eol != NULL)
11658 47 : len = eol - s;
11659 48 : printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
11660 48 : if (eol == NULL)
11661 : break;
11662 47 : size -= eol + 1 - s;
11663 47 : s = eol + 1;
11664 : }
11665 :
11666 : colno = WRAP_COLUMN;
11667 : break;
11668 :
11669 : case 'h':
11670 : break;
11671 :
11672 0 : default:
11673 0 : error (0, 0, "XXX not handling format '%c' for %s",
11674 : item->format, item->name);
11675 : break;
11676 : }
11677 :
11678 : #undef TYPES
11679 :
11680 0 : return colno;
11681 : }
11682 :
11683 :
11684 : /* Sort items by group, and by layout offset within each group. */
11685 : static int
11686 895 : compare_core_items (const void *a, const void *b)
11687 : {
11688 895 : const Ebl_Core_Item *const *p1 = a;
11689 895 : const Ebl_Core_Item *const *p2 = b;
11690 895 : const Ebl_Core_Item *item1 = *p1;
11691 895 : const Ebl_Core_Item *item2 = *p2;
11692 :
11693 895 : return ((item1->group == item2->group ? 0
11694 895 : : strcmp (item1->group, item2->group))
11695 895 : ?: (int) item1->offset - (int) item2->offset);
11696 : }
11697 :
11698 : /* Sort item groups by layout offset of the first item in the group. */
11699 : static int
11700 139 : compare_core_item_groups (const void *a, const void *b)
11701 : {
11702 139 : const Ebl_Core_Item *const *const *p1 = a;
11703 139 : const Ebl_Core_Item *const *const *p2 = b;
11704 139 : const Ebl_Core_Item *const *group1 = *p1;
11705 139 : const Ebl_Core_Item *const *group2 = *p2;
11706 139 : const Ebl_Core_Item *item1 = *group1;
11707 139 : const Ebl_Core_Item *item2 = *group2;
11708 :
11709 139 : return (int) item1->offset - (int) item2->offset;
11710 : }
11711 :
11712 : static unsigned int
11713 37 : handle_core_items (Elf *core, const void *desc, size_t descsz,
11714 : const Ebl_Core_Item *items, size_t nitems)
11715 : {
11716 37 : if (nitems == 0)
11717 : return 0;
11718 34 : unsigned int colno = 0;
11719 :
11720 : /* FORMAT '\n' makes sense to be present only as a single item as it
11721 : processes all the data of a note. FORMATs 'b' and 'B' have a special case
11722 : if present as a single item but they can be also processed with other
11723 : items below. */
11724 34 : if (nitems == 1 && (items[0].format == '\n' || items[0].format == 'b'
11725 8 : || items[0].format == 'B'))
11726 : {
11727 1 : assert (items[0].offset == 0);
11728 1 : size_t size = descsz;
11729 1 : colno = handle_core_item (core, items, desc, colno, &size);
11730 : /* If SIZE is not zero here there is some remaining data. But we do not
11731 : know how to process it anyway. */
11732 1 : return colno;
11733 : }
11734 424 : for (size_t i = 0; i < nitems; ++i)
11735 391 : assert (items[i].format != '\n');
11736 :
11737 : /* Sort to collect the groups together. */
11738 33 : const Ebl_Core_Item *sorted_items[nitems];
11739 424 : for (size_t i = 0; i < nitems; ++i)
11740 391 : sorted_items[i] = &items[i];
11741 33 : qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
11742 :
11743 : /* Collect the unique groups and sort them. */
11744 33 : const Ebl_Core_Item **groups[nitems];
11745 33 : groups[0] = &sorted_items[0];
11746 33 : size_t ngroups = 1;
11747 391 : for (size_t i = 1; i < nitems; ++i)
11748 358 : if (sorted_items[i]->group != sorted_items[i - 1]->group
11749 75 : && strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
11750 75 : groups[ngroups++] = &sorted_items[i];
11751 33 : qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
11752 :
11753 : /* Write out all the groups. */
11754 33 : const void *last = desc;
11755 35 : do
11756 : {
11757 145 : for (size_t i = 0; i < ngroups; ++i)
11758 : {
11759 110 : for (const Ebl_Core_Item **item = groups[i];
11760 509 : (item < &sorted_items[nitems]
11761 474 : && ((*item)->group == groups[i][0]->group
11762 75 : || !strcmp ((*item)->group, groups[i][0]->group)));
11763 399 : ++item)
11764 399 : colno = handle_core_item (core, *item, desc, colno, NULL);
11765 :
11766 : /* Force a line break at the end of the group. */
11767 110 : colno = WRAP_COLUMN;
11768 : }
11769 :
11770 35 : if (descsz == 0)
11771 : break;
11772 :
11773 : /* This set of items consumed a certain amount of the note's data.
11774 : If there is more data there, we have another unit of the same size.
11775 : Loop to print that out too. */
11776 20 : const Ebl_Core_Item *item = &items[nitems - 1];
11777 20 : size_t eltsz = item->offset + gelf_fsize (core, item->type,
11778 20 : item->count ?: 1, EV_CURRENT);
11779 :
11780 20 : int reps = -1;
11781 20 : do
11782 : {
11783 20 : ++reps;
11784 20 : desc += eltsz;
11785 20 : descsz -= eltsz;
11786 : }
11787 20 : while (descsz >= eltsz && !memcmp (desc, last, eltsz));
11788 :
11789 20 : if (reps == 1)
11790 : {
11791 : /* For just one repeat, print it unabridged twice. */
11792 : desc -= eltsz;
11793 : descsz += eltsz;
11794 : }
11795 20 : else if (reps > 1)
11796 0 : printf (gettext ("\n%*s... <repeats %u more times> ..."),
11797 : ITEM_INDENT, "", reps);
11798 :
11799 20 : last = desc;
11800 : }
11801 20 : while (descsz > 0);
11802 :
11803 33 : return colno;
11804 : }
11805 :
11806 : static unsigned int
11807 0 : handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
11808 : unsigned int colno)
11809 : {
11810 0 : desc += regloc->offset;
11811 :
11812 0 : abort (); /* XXX */
11813 : return colno;
11814 : }
11815 :
11816 :
11817 : static unsigned int
11818 162 : handle_core_register (Ebl *ebl, Elf *core, int maxregname,
11819 : const Ebl_Register_Location *regloc, const void *desc,
11820 : unsigned int colno)
11821 : {
11822 162 : if (regloc->bits % 8 != 0)
11823 0 : return handle_bit_registers (regloc, desc, colno);
11824 :
11825 162 : desc += regloc->offset;
11826 :
11827 586 : for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
11828 : {
11829 424 : char name[REGNAMESZ];
11830 424 : int bits;
11831 424 : int type;
11832 424 : register_info (ebl, reg, regloc, name, &bits, &type);
11833 :
11834 : #define TYPES \
11835 : BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8); \
11836 : BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16); \
11837 : BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32); \
11838 : BITS (64, XWORD, "%20" PRId64, " 0x%.16" PRIx64)
11839 :
11840 : #define BITS(bits, xtype, sfmt, ufmt) \
11841 : uint##bits##_t b##bits; int##bits##_t b##bits##s
11842 424 : union { TYPES; uint64_t b128[2]; } value;
11843 : #undef BITS
11844 :
11845 424 : switch (type)
11846 : {
11847 336 : case DW_ATE_unsigned:
11848 : case DW_ATE_signed:
11849 : case DW_ATE_address:
11850 336 : switch (bits)
11851 : {
11852 : #define BITS(bits, xtype, sfmt, ufmt) \
11853 : case bits: \
11854 : desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0); \
11855 : if (type == DW_ATE_signed) \
11856 : colno = print_core_item (colno, ' ', WRAP_COLUMN, \
11857 : maxregname, name, \
11858 : sfmt, value.b##bits##s); \
11859 : else \
11860 : colno = print_core_item (colno, ' ', WRAP_COLUMN, \
11861 : maxregname, name, \
11862 : ufmt, value.b##bits); \
11863 : break
11864 :
11865 288 : TYPES;
11866 :
11867 48 : case 128:
11868 48 : assert (type == DW_ATE_unsigned);
11869 48 : desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
11870 48 : int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
11871 96 : colno = print_core_item (colno, ' ', WRAP_COLUMN,
11872 : maxregname, name,
11873 : "0x%.16" PRIx64 "%.16" PRIx64,
11874 48 : value.b128[!be], value.b128[be]);
11875 48 : break;
11876 :
11877 0 : default:
11878 0 : abort ();
11879 : #undef BITS
11880 : }
11881 : break;
11882 :
11883 88 : default:
11884 : /* Print each byte in hex, the whole thing in native byte order. */
11885 88 : assert (bits % 8 == 0);
11886 88 : const uint8_t *bytes = desc;
11887 88 : desc += bits / 8;
11888 88 : char hex[bits / 4 + 1];
11889 88 : hex[bits / 4] = '\0';
11890 88 : int incr = 1;
11891 88 : if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
11892 : {
11893 48 : bytes += bits / 8 - 1;
11894 48 : incr = -1;
11895 : }
11896 88 : size_t idx = 0;
11897 872 : for (char *h = hex; bits > 0; bits -= 8, idx += incr)
11898 : {
11899 784 : *h++ = "0123456789abcdef"[bytes[idx] >> 4];
11900 784 : *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
11901 : }
11902 88 : colno = print_core_item (colno, ' ', WRAP_COLUMN,
11903 : maxregname, name, "0x%s", hex);
11904 88 : break;
11905 : }
11906 424 : desc += regloc->pad;
11907 :
11908 : #undef TYPES
11909 : }
11910 :
11911 162 : return colno;
11912 : }
11913 :
11914 :
11915 : struct register_info
11916 : {
11917 : const Ebl_Register_Location *regloc;
11918 : const char *set;
11919 : char name[REGNAMESZ];
11920 : int regno;
11921 : int bits;
11922 : int type;
11923 : };
11924 :
11925 : static int
11926 0 : register_bitpos (const struct register_info *r)
11927 : {
11928 2066 : return (r->regloc->offset * 8
11929 4132 : + ((r->regno - r->regloc->regno)
11930 2066 : * (r->regloc->bits + r->regloc->pad * 8)));
11931 : }
11932 :
11933 : static int
11934 1062 : compare_sets_by_info (const struct register_info *r1,
11935 : const struct register_info *r2)
11936 : {
11937 1062 : return ((int) r2->bits - (int) r1->bits
11938 1062 : ?: register_bitpos (r1) - register_bitpos (r2));
11939 : }
11940 :
11941 : /* Sort registers by set, and by size and layout offset within each set. */
11942 : static int
11943 4595 : compare_registers (const void *a, const void *b)
11944 : {
11945 4595 : const struct register_info *r1 = a;
11946 4595 : const struct register_info *r2 = b;
11947 :
11948 : /* Unused elements sort last. */
11949 4595 : if (r1->regloc == NULL)
11950 3309 : return r2->regloc == NULL ? 0 : 1;
11951 1286 : if (r2->regloc == NULL)
11952 : return -1;
11953 :
11954 1121 : return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
11955 1121 : ?: compare_sets_by_info (r1, r2));
11956 : }
11957 :
11958 : /* Sort register sets by layout offset of the first register in the set. */
11959 : static int
11960 20 : compare_register_sets (const void *a, const void *b)
11961 : {
11962 20 : const struct register_info *const *p1 = a;
11963 20 : const struct register_info *const *p2 = b;
11964 20 : return compare_sets_by_info (*p1, *p2);
11965 : }
11966 :
11967 : static unsigned int
11968 37 : handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
11969 : const Ebl_Register_Location *reglocs, size_t nregloc)
11970 : {
11971 37 : if (nregloc == 0)
11972 : return 0;
11973 :
11974 18 : ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
11975 18 : if (maxnreg <= 0)
11976 : {
11977 0 : for (size_t i = 0; i < nregloc; ++i)
11978 0 : if (maxnreg < reglocs[i].regno + reglocs[i].count)
11979 0 : maxnreg = reglocs[i].regno + reglocs[i].count;
11980 0 : assert (maxnreg > 0);
11981 : }
11982 :
11983 18 : struct register_info regs[maxnreg];
11984 18 : memset (regs, 0, sizeof regs);
11985 :
11986 : /* Sort to collect the sets together. */
11987 18 : int maxreg = 0;
11988 180 : for (size_t i = 0; i < nregloc; ++i)
11989 162 : for (int reg = reglocs[i].regno;
11990 586 : reg < reglocs[i].regno + reglocs[i].count;
11991 424 : ++reg)
11992 : {
11993 424 : assert (reg < maxnreg);
11994 424 : if (reg > maxreg)
11995 230 : maxreg = reg;
11996 424 : struct register_info *info = ®s[reg];
11997 424 : info->regloc = ®locs[i];
11998 424 : info->regno = reg;
11999 424 : info->set = register_info (ebl, reg, ®locs[i],
12000 424 : info->name, &info->bits, &info->type);
12001 : }
12002 18 : qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
12003 :
12004 : /* Collect the unique sets and sort them. */
12005 882 : inline bool same_set (const struct register_info *a,
12006 : const struct register_info *b)
12007 : {
12008 864 : return (a < ®s[maxnreg] && a->regloc != NULL
12009 864 : && b < ®s[maxnreg] && b->regloc != NULL
12010 846 : && a->bits == b->bits
12011 1692 : && (a->set == b->set || !strcmp (a->set, b->set)));
12012 : }
12013 18 : struct register_info *sets[maxreg + 1];
12014 18 : sets[0] = ®s[0];
12015 18 : size_t nsets = 1;
12016 1279 : for (int i = 1; i <= maxreg; ++i)
12017 1261 : if (regs[i].regloc != NULL && !same_set (®s[i], ®s[i - 1]))
12018 16 : sets[nsets++] = ®s[i];
12019 18 : qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
12020 :
12021 : /* Write out all the sets. */
12022 18 : unsigned int colno = 0;
12023 52 : for (size_t i = 0; i < nsets; ++i)
12024 : {
12025 : /* Find the longest name of a register in this set. */
12026 34 : size_t maxname = 0;
12027 34 : const struct register_info *end;
12028 458 : for (end = sets[i]; same_set (sets[i], end); ++end)
12029 : {
12030 424 : size_t len = strlen (end->name);
12031 424 : if (len > maxname)
12032 52 : maxname = len;
12033 : }
12034 :
12035 196 : for (const struct register_info *reg = sets[i];
12036 : reg < end;
12037 162 : reg += reg->regloc->count ?: 1)
12038 162 : colno = handle_core_register (ebl, core, maxname,
12039 : reg->regloc, desc, colno);
12040 :
12041 : /* Force a line break at the end of the group. */
12042 34 : colno = WRAP_COLUMN;
12043 : }
12044 :
12045 18 : return colno;
12046 : }
12047 :
12048 : static void
12049 9 : handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
12050 : {
12051 9 : Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
12052 9 : if (data == NULL)
12053 0 : elf_error:
12054 0 : error (EXIT_FAILURE, 0,
12055 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
12056 :
12057 9 : const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
12058 177 : for (size_t i = 0; i < nauxv; ++i)
12059 : {
12060 168 : GElf_auxv_t av_mem;
12061 168 : GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
12062 168 : if (av == NULL)
12063 0 : goto elf_error;
12064 :
12065 168 : const char *name;
12066 168 : const char *fmt;
12067 168 : if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
12068 : {
12069 : /* Unknown type. */
12070 0 : if (av->a_un.a_val == 0)
12071 0 : printf (" %" PRIu64 "\n", av->a_type);
12072 : else
12073 0 : printf (" %" PRIu64 ": %#" PRIx64 "\n",
12074 : av->a_type, av->a_un.a_val);
12075 : }
12076 : else
12077 168 : switch (fmt[0])
12078 : {
12079 9 : case '\0': /* Normally zero. */
12080 9 : if (av->a_un.a_val == 0)
12081 : {
12082 9 : printf (" %s\n", name);
12083 : break;
12084 : }
12085 74 : FALLTHROUGH;
12086 : case 'x': /* hex */
12087 : case 'p': /* address */
12088 : case 's': /* address of string */
12089 74 : printf (" %s: %#" PRIx64 "\n", name, av->a_un.a_val);
12090 : break;
12091 81 : case 'u':
12092 81 : printf (" %s: %" PRIu64 "\n", name, av->a_un.a_val);
12093 : break;
12094 0 : case 'd':
12095 0 : printf (" %s: %" PRId64 "\n", name, av->a_un.a_val);
12096 : break;
12097 :
12098 4 : case 'b':
12099 4 : printf (" %s: %#" PRIx64 " ", name, av->a_un.a_val);
12100 4 : GElf_Xword bit = 1;
12101 4 : const char *pfx = "<";
12102 110 : for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
12103 : {
12104 106 : if (av->a_un.a_val & bit)
12105 : {
12106 77 : printf ("%s%s", pfx, p);
12107 77 : pfx = " ";
12108 : }
12109 106 : bit <<= 1;
12110 : }
12111 4 : printf (">\n");
12112 : break;
12113 :
12114 0 : default:
12115 0 : abort ();
12116 : }
12117 : }
12118 9 : }
12119 :
12120 : static bool
12121 : buf_has_data (unsigned char const *ptr, unsigned char const *end, size_t sz)
12122 : {
12123 195 : return ptr < end && (size_t) (end - ptr) >= sz;
12124 : }
12125 :
12126 : static bool
12127 18 : buf_read_int (Elf *core, unsigned char const **ptrp, unsigned char const *end,
12128 : int *retp)
12129 : {
12130 36 : if (! buf_has_data (*ptrp, end, 4))
12131 : return false;
12132 :
12133 18 : *ptrp = convert (core, ELF_T_WORD, 1, retp, *ptrp, 4);
12134 18 : return true;
12135 : }
12136 :
12137 : static bool
12138 177 : buf_read_ulong (Elf *core, unsigned char const **ptrp, unsigned char const *end,
12139 : uint64_t *retp)
12140 : {
12141 177 : size_t sz = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
12142 354 : if (! buf_has_data (*ptrp, end, sz))
12143 : return false;
12144 :
12145 177 : union
12146 : {
12147 : uint64_t u64;
12148 : uint32_t u32;
12149 : } u;
12150 :
12151 177 : *ptrp = convert (core, ELF_T_ADDR, 1, &u, *ptrp, sz);
12152 :
12153 177 : if (sz == 4)
12154 93 : *retp = u.u32;
12155 : else
12156 84 : *retp = u.u64;
12157 : return true;
12158 : }
12159 :
12160 : static void
12161 6 : handle_siginfo_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
12162 : {
12163 6 : Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
12164 6 : if (data == NULL)
12165 0 : error (EXIT_FAILURE, 0,
12166 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
12167 :
12168 6 : unsigned char const *ptr = data->d_buf;
12169 6 : unsigned char const *const end = data->d_buf + data->d_size;
12170 :
12171 : /* Siginfo head is three ints: signal number, error number, origin
12172 : code. */
12173 6 : int si_signo, si_errno, si_code;
12174 6 : if (! buf_read_int (core, &ptr, end, &si_signo)
12175 6 : || ! buf_read_int (core, &ptr, end, &si_errno)
12176 6 : || ! buf_read_int (core, &ptr, end, &si_code))
12177 : {
12178 0 : fail:
12179 0 : printf (" Not enough data in NT_SIGINFO note.\n");
12180 0 : return;
12181 : }
12182 :
12183 : /* Next is a pointer-aligned union of structures. On 64-bit
12184 : machines, that implies a word of padding. */
12185 6 : if (gelf_getclass (core) == ELFCLASS64)
12186 3 : ptr += 4;
12187 :
12188 6 : printf (" si_signo: %d, si_errno: %d, si_code: %d\n",
12189 : si_signo, si_errno, si_code);
12190 :
12191 6 : if (si_code > 0)
12192 6 : switch (si_signo)
12193 : {
12194 6 : case CORE_SIGILL:
12195 : case CORE_SIGFPE:
12196 : case CORE_SIGSEGV:
12197 : case CORE_SIGBUS:
12198 : {
12199 6 : uint64_t addr;
12200 6 : if (! buf_read_ulong (core, &ptr, end, &addr))
12201 0 : goto fail;
12202 6 : printf (" fault address: %#" PRIx64 "\n", addr);
12203 6 : break;
12204 : }
12205 : default:
12206 : ;
12207 : }
12208 0 : else if (si_code == CORE_SI_USER)
12209 : {
12210 0 : int pid, uid;
12211 0 : if (! buf_read_int (core, &ptr, end, &pid)
12212 0 : || ! buf_read_int (core, &ptr, end, &uid))
12213 0 : goto fail;
12214 0 : printf (" sender PID: %d, sender UID: %d\n", pid, uid);
12215 : }
12216 : }
12217 :
12218 : static void
12219 6 : handle_file_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
12220 : {
12221 6 : Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
12222 6 : if (data == NULL)
12223 0 : error (EXIT_FAILURE, 0,
12224 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
12225 :
12226 6 : unsigned char const *ptr = data->d_buf;
12227 6 : unsigned char const *const end = data->d_buf + data->d_size;
12228 :
12229 6 : uint64_t count, page_size;
12230 6 : if (! buf_read_ulong (core, &ptr, end, &count)
12231 6 : || ! buf_read_ulong (core, &ptr, end, &page_size))
12232 : {
12233 0 : fail:
12234 0 : printf (" Not enough data in NT_FILE note.\n");
12235 0 : return;
12236 : }
12237 :
12238 6 : size_t addrsize = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
12239 6 : uint64_t maxcount = (size_t) (end - ptr) / (3 * addrsize);
12240 6 : if (count > maxcount)
12241 : goto fail;
12242 :
12243 : /* Where file names are stored. */
12244 6 : unsigned char const *const fstart = ptr + 3 * count * addrsize;
12245 6 : char const *fptr = (char *) fstart;
12246 :
12247 6 : printf (" %" PRId64 " files:\n", count);
12248 59 : for (uint64_t i = 0; i < count; ++i)
12249 : {
12250 53 : uint64_t mstart, mend, moffset;
12251 53 : if (! buf_read_ulong (core, &ptr, fstart, &mstart)
12252 53 : || ! buf_read_ulong (core, &ptr, fstart, &mend)
12253 53 : || ! buf_read_ulong (core, &ptr, fstart, &moffset))
12254 0 : goto fail;
12255 :
12256 53 : const char *fnext = memchr (fptr, '\0', (char *) end - fptr);
12257 53 : if (fnext == NULL)
12258 : goto fail;
12259 :
12260 53 : int ct = printf (" %08" PRIx64 "-%08" PRIx64
12261 : " %08" PRIx64 " %" PRId64,
12262 : mstart, mend, moffset * page_size, mend - mstart);
12263 53 : printf ("%*s%s\n", ct > 50 ? 3 : 53 - ct, "", fptr);
12264 :
12265 53 : fptr = fnext + 1;
12266 : }
12267 : }
12268 :
12269 : static void
12270 38 : handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
12271 : const char *name, const void *desc)
12272 : {
12273 38 : GElf_Word regs_offset;
12274 38 : size_t nregloc;
12275 38 : const Ebl_Register_Location *reglocs;
12276 38 : size_t nitems;
12277 38 : const Ebl_Core_Item *items;
12278 :
12279 38 : if (! ebl_core_note (ebl, nhdr, name, desc,
12280 : ®s_offset, &nregloc, ®locs, &nitems, &items))
12281 1 : return;
12282 :
12283 : /* Pass 0 for DESCSZ when there are registers in the note,
12284 : so that the ITEMS array does not describe the whole thing.
12285 : For non-register notes, the actual descsz might be a multiple
12286 : of the unit size, not just exactly the unit size. */
12287 37 : unsigned int colno = handle_core_items (ebl->elf, desc,
12288 37 : nregloc == 0 ? nhdr->n_descsz : 0,
12289 : items, nitems);
12290 37 : if (colno != 0)
12291 34 : putchar_unlocked ('\n');
12292 :
12293 37 : colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
12294 : reglocs, nregloc);
12295 37 : if (colno != 0)
12296 18 : putchar_unlocked ('\n');
12297 : }
12298 :
12299 : static void
12300 0 : handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
12301 : GElf_Off start, Elf_Data *data)
12302 : {
12303 0 : fputs_unlocked (gettext (" Owner Data size Type\n"), stdout);
12304 :
12305 0 : if (data == NULL)
12306 0 : goto bad_note;
12307 :
12308 : size_t offset = 0;
12309 : GElf_Nhdr nhdr;
12310 : size_t name_offset;
12311 : size_t desc_offset;
12312 0 : while (offset < data->d_size
12313 0 : && (offset = gelf_getnote (data, offset,
12314 : &nhdr, &name_offset, &desc_offset)) > 0)
12315 : {
12316 0 : const char *name = nhdr.n_namesz == 0 ? "" : data->d_buf + name_offset;
12317 0 : const char *desc = data->d_buf + desc_offset;
12318 :
12319 : /* GNU Build Attributes are weird, they store most of their data
12320 : into the owner name field. Extract just the owner name
12321 : prefix here, then use the rest later as data. */
12322 0 : bool is_gnu_build_attr
12323 0 : = strncmp (name, ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX,
12324 : strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX)) == 0;
12325 0 : const char *print_name = (is_gnu_build_attr
12326 0 : ? ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX : name);
12327 0 : size_t print_namesz = (is_gnu_build_attr
12328 0 : ? strlen (print_name) : nhdr.n_namesz);
12329 :
12330 0 : char buf[100];
12331 0 : char buf2[100];
12332 0 : printf (gettext (" %-13.*s %9" PRId32 " %s\n"),
12333 : (int) print_namesz, print_name, nhdr.n_descsz,
12334 0 : ehdr->e_type == ET_CORE
12335 0 : ? ebl_core_note_type_name (ebl, nhdr.n_type,
12336 : buf, sizeof (buf))
12337 0 : : ebl_object_note_type_name (ebl, name, nhdr.n_type,
12338 : nhdr.n_descsz,
12339 : buf2, sizeof (buf2)));
12340 :
12341 : /* Filter out invalid entries. */
12342 0 : if (memchr (name, '\0', nhdr.n_namesz) != NULL
12343 : /* XXX For now help broken Linux kernels. */
12344 : || 1)
12345 : {
12346 0 : if (ehdr->e_type == ET_CORE)
12347 : {
12348 0 : if (nhdr.n_type == NT_AUXV
12349 0 : && (nhdr.n_namesz == 4 /* Broken old Linux kernels. */
12350 0 : || (nhdr.n_namesz == 5 && name[4] == '\0'))
12351 0 : && !memcmp (name, "CORE", 4))
12352 0 : handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
12353 : start + desc_offset);
12354 0 : else if (nhdr.n_namesz == 5 && strcmp (name, "CORE") == 0)
12355 0 : switch (nhdr.n_type)
12356 : {
12357 0 : case NT_SIGINFO:
12358 0 : handle_siginfo_note (ebl->elf, nhdr.n_descsz,
12359 : start + desc_offset);
12360 0 : break;
12361 :
12362 0 : case NT_FILE:
12363 0 : handle_file_note (ebl->elf, nhdr.n_descsz,
12364 : start + desc_offset);
12365 0 : break;
12366 :
12367 0 : default:
12368 0 : handle_core_note (ebl, &nhdr, name, desc);
12369 : }
12370 : else
12371 0 : handle_core_note (ebl, &nhdr, name, desc);
12372 : }
12373 : else
12374 0 : ebl_object_note (ebl, nhdr.n_namesz, name, nhdr.n_type,
12375 : nhdr.n_descsz, desc);
12376 : }
12377 : }
12378 :
12379 0 : if (offset == data->d_size)
12380 0 : return;
12381 :
12382 0 : bad_note:
12383 0 : error (0, 0,
12384 0 : gettext ("cannot get content of note: %s"),
12385 0 : data != NULL ? "garbage data" : elf_errmsg (-1));
12386 : }
12387 :
12388 : static void
12389 62 : handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
12390 : {
12391 : /* If we have section headers, just look for SHT_NOTE sections.
12392 : In a debuginfo file, the program headers are not reliable. */
12393 62 : if (shnum != 0)
12394 : {
12395 : /* Get the section header string table index. */
12396 51 : size_t shstrndx;
12397 51 : if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
12398 0 : error (EXIT_FAILURE, 0,
12399 0 : gettext ("cannot get section header string table index"));
12400 :
12401 : Elf_Scn *scn = NULL;
12402 1213 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
12403 : {
12404 1162 : GElf_Shdr shdr_mem;
12405 1162 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
12406 :
12407 1162 : if (shdr == NULL || shdr->sh_type != SHT_NOTE)
12408 : /* Not what we are looking for. */
12409 1115 : continue;
12410 :
12411 47 : printf (gettext ("\
12412 : \nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
12413 : elf_ndxscn (scn),
12414 47 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
12415 : shdr->sh_size, shdr->sh_offset);
12416 :
12417 47 : handle_notes_data (ebl, ehdr, shdr->sh_offset,
12418 : elf_getdata (scn, NULL));
12419 : }
12420 51 : return;
12421 : }
12422 :
12423 : /* We have to look through the program header to find the note
12424 : sections. There can be more than one. */
12425 140 : for (size_t cnt = 0; cnt < phnum; ++cnt)
12426 : {
12427 129 : GElf_Phdr mem;
12428 129 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
12429 :
12430 129 : if (phdr == NULL || phdr->p_type != PT_NOTE)
12431 : /* Not what we are looking for. */
12432 117 : continue;
12433 :
12434 12 : printf (gettext ("\
12435 : \nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
12436 : phdr->p_filesz, phdr->p_offset);
12437 :
12438 12 : handle_notes_data (ebl, ehdr, phdr->p_offset,
12439 : elf_getdata_rawchunk (ebl->elf,
12440 12 : phdr->p_offset, phdr->p_filesz,
12441 12 : (phdr->p_align == 8
12442 : ? ELF_T_NHDR8 : ELF_T_NHDR)));
12443 : }
12444 : }
12445 :
12446 :
12447 : static void
12448 5 : hex_dump (const uint8_t *data, size_t len)
12449 : {
12450 5 : size_t pos = 0;
12451 26 : while (pos < len)
12452 : {
12453 21 : printf (" 0x%08zx ", pos);
12454 :
12455 21 : const size_t chunk = MIN (len - pos, 16);
12456 :
12457 342 : for (size_t i = 0; i < chunk; ++i)
12458 321 : if (i % 4 == 3)
12459 80 : printf ("%02x ", data[pos + i]);
12460 : else
12461 241 : printf ("%02x", data[pos + i]);
12462 :
12463 21 : if (chunk < 16)
12464 1 : printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
12465 :
12466 342 : for (size_t i = 0; i < chunk; ++i)
12467 : {
12468 321 : unsigned char b = data[pos + i];
12469 321 : printf ("%c", isprint (b) ? b : '.');
12470 : }
12471 :
12472 21 : putchar ('\n');
12473 21 : pos += chunk;
12474 : }
12475 5 : }
12476 :
12477 : static void
12478 5 : dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
12479 : {
12480 5 : if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
12481 0 : printf (gettext ("\nSection [%zu] '%s' has no data to dump.\n"),
12482 : elf_ndxscn (scn), name);
12483 : else
12484 : {
12485 5 : if (print_decompress)
12486 : {
12487 : /* We try to decompress the section, but keep the old shdr around
12488 : so we can show both the original shdr size and the uncompressed
12489 : data size. */
12490 4 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
12491 : {
12492 2 : if (elf_compress (scn, 0, 0) < 0)
12493 0 : printf ("WARNING: %s [%zd]\n",
12494 : gettext ("Couldn't uncompress section"),
12495 : elf_ndxscn (scn));
12496 : }
12497 2 : else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
12498 : {
12499 2 : if (elf_compress_gnu (scn, 0, 0) < 0)
12500 0 : printf ("WARNING: %s [%zd]\n",
12501 : gettext ("Couldn't uncompress section"),
12502 : elf_ndxscn (scn));
12503 : }
12504 : }
12505 :
12506 5 : Elf_Data *data = elf_rawdata (scn, NULL);
12507 5 : if (data == NULL)
12508 0 : error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
12509 : elf_ndxscn (scn), name, elf_errmsg (-1));
12510 : else
12511 : {
12512 5 : if (data->d_size == shdr->sh_size)
12513 1 : printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
12514 : " bytes at offset %#0" PRIx64 ":\n"),
12515 : elf_ndxscn (scn), name,
12516 : shdr->sh_size, shdr->sh_offset);
12517 : else
12518 4 : printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
12519 : " bytes (%zd uncompressed) at offset %#0"
12520 : PRIx64 ":\n"),
12521 : elf_ndxscn (scn), name,
12522 : shdr->sh_size, data->d_size, shdr->sh_offset);
12523 5 : hex_dump (data->d_buf, data->d_size);
12524 : }
12525 : }
12526 5 : }
12527 :
12528 : static void
12529 93 : print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
12530 : {
12531 93 : if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
12532 0 : printf (gettext ("\nSection [%zu] '%s' has no strings to dump.\n"),
12533 : elf_ndxscn (scn), name);
12534 : else
12535 : {
12536 93 : if (print_decompress)
12537 : {
12538 : /* We try to decompress the section, but keep the old shdr around
12539 : so we can show both the original shdr size and the uncompressed
12540 : data size. */
12541 1 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
12542 : {
12543 0 : if (elf_compress (scn, 0, 0) < 0)
12544 0 : printf ("WARNING: %s [%zd]\n",
12545 : gettext ("Couldn't uncompress section"),
12546 : elf_ndxscn (scn));
12547 : }
12548 1 : else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
12549 : {
12550 1 : if (elf_compress_gnu (scn, 0, 0) < 0)
12551 0 : printf ("WARNING: %s [%zd]\n",
12552 : gettext ("Couldn't uncompress section"),
12553 : elf_ndxscn (scn));
12554 : }
12555 : }
12556 :
12557 93 : Elf_Data *data = elf_rawdata (scn, NULL);
12558 93 : if (data == NULL)
12559 0 : error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
12560 : elf_ndxscn (scn), name, elf_errmsg (-1));
12561 : else
12562 : {
12563 93 : if (data->d_size == shdr->sh_size)
12564 92 : printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
12565 : " bytes at offset %#0" PRIx64 ":\n"),
12566 : elf_ndxscn (scn), name,
12567 : shdr->sh_size, shdr->sh_offset);
12568 : else
12569 1 : printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
12570 : " bytes (%zd uncompressed) at offset %#0"
12571 : PRIx64 ":\n"),
12572 : elf_ndxscn (scn), name,
12573 : shdr->sh_size, data->d_size, shdr->sh_offset);
12574 :
12575 93 : const char *start = data->d_buf;
12576 93 : const char *const limit = start + data->d_size;
12577 16203 : do
12578 : {
12579 16203 : const char *end = memchr (start, '\0', limit - start);
12580 16203 : const size_t pos = start - (const char *) data->d_buf;
12581 16203 : if (unlikely (end == NULL))
12582 : {
12583 0 : printf (" [%6zx]- %.*s\n",
12584 : pos, (int) (limit - start), start);
12585 : break;
12586 : }
12587 16203 : printf (" [%6zx] %s\n", pos, start);
12588 16203 : start = end + 1;
12589 16203 : } while (start < limit);
12590 : }
12591 : }
12592 93 : }
12593 :
12594 : static void
12595 48 : for_each_section_argument (Elf *elf, const struct section_argument *list,
12596 : void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
12597 : const char *name))
12598 : {
12599 : /* Get the section header string table index. */
12600 48 : size_t shstrndx;
12601 48 : if (elf_getshdrstrndx (elf, &shstrndx) < 0)
12602 0 : error (EXIT_FAILURE, 0,
12603 0 : gettext ("cannot get section header string table index"));
12604 :
12605 180 : for (const struct section_argument *a = list; a != NULL; a = a->next)
12606 : {
12607 132 : Elf_Scn *scn;
12608 132 : GElf_Shdr shdr_mem;
12609 132 : const char *name = NULL;
12610 :
12611 132 : char *endp = NULL;
12612 132 : unsigned long int shndx = strtoul (a->arg, &endp, 0);
12613 132 : if (endp != a->arg && *endp == '\0')
12614 : {
12615 0 : scn = elf_getscn (elf, shndx);
12616 0 : if (scn == NULL)
12617 : {
12618 0 : error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
12619 0 : continue;
12620 : }
12621 :
12622 0 : if (gelf_getshdr (scn, &shdr_mem) == NULL)
12623 0 : error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
12624 : elf_errmsg (-1));
12625 0 : name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
12626 : }
12627 : else
12628 : {
12629 : /* Need to look up the section by name. */
12630 : scn = NULL;
12631 : bool found = false;
12632 3303 : while ((scn = elf_nextscn (elf, scn)) != NULL)
12633 : {
12634 3171 : if (gelf_getshdr (scn, &shdr_mem) == NULL)
12635 : continue;
12636 3171 : name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
12637 3171 : if (name == NULL)
12638 : continue;
12639 3171 : if (!strcmp (name, a->arg))
12640 : {
12641 98 : found = true;
12642 98 : (*dump) (scn, &shdr_mem, name);
12643 : }
12644 : }
12645 :
12646 132 : if (unlikely (!found) && !a->implicit)
12647 0 : error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
12648 : }
12649 : }
12650 48 : }
12651 :
12652 : static void
12653 0 : dump_data (Ebl *ebl)
12654 : {
12655 5 : for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
12656 0 : }
12657 :
12658 : static void
12659 0 : dump_strings (Ebl *ebl)
12660 : {
12661 43 : for_each_section_argument (ebl->elf, string_sections, &print_string_section);
12662 0 : }
12663 :
12664 : static void
12665 0 : print_strings (Ebl *ebl)
12666 : {
12667 : /* Get the section header string table index. */
12668 0 : size_t shstrndx;
12669 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
12670 0 : error (EXIT_FAILURE, 0,
12671 0 : gettext ("cannot get section header string table index"));
12672 :
12673 : Elf_Scn *scn;
12674 : GElf_Shdr shdr_mem;
12675 : const char *name;
12676 : scn = NULL;
12677 0 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
12678 : {
12679 0 : if (gelf_getshdr (scn, &shdr_mem) == NULL)
12680 0 : continue;
12681 :
12682 0 : if (shdr_mem.sh_type != SHT_PROGBITS
12683 0 : || !(shdr_mem.sh_flags & SHF_STRINGS))
12684 0 : continue;
12685 :
12686 0 : name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
12687 0 : if (name == NULL)
12688 0 : continue;
12689 :
12690 0 : print_string_section (scn, &shdr_mem, name);
12691 : }
12692 0 : }
12693 :
12694 : static void
12695 2 : dump_archive_index (Elf *elf, const char *fname)
12696 : {
12697 2 : size_t narsym;
12698 2 : const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
12699 2 : if (arsym == NULL)
12700 : {
12701 0 : int result = elf_errno ();
12702 0 : if (unlikely (result != ELF_E_NO_INDEX))
12703 0 : error (EXIT_FAILURE, 0,
12704 0 : gettext ("cannot get symbol index of archive '%s': %s"),
12705 : fname, elf_errmsg (result));
12706 : else
12707 0 : printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
12708 0 : return;
12709 : }
12710 :
12711 2 : printf (gettext ("\nIndex of archive '%s' has %zu entries:\n"),
12712 : fname, narsym);
12713 :
12714 2 : size_t as_off = 0;
12715 11 : for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
12716 : {
12717 9 : if (s->as_off != as_off)
12718 : {
12719 6 : as_off = s->as_off;
12720 :
12721 6 : Elf *subelf = NULL;
12722 6 : if (unlikely (elf_rand (elf, as_off) == 0)
12723 6 : || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
12724 : == NULL))
12725 : #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
12726 : while (1)
12727 : #endif
12728 0 : error (EXIT_FAILURE, 0,
12729 0 : gettext ("cannot extract member at offset %zu in '%s': %s"),
12730 : as_off, fname, elf_errmsg (-1));
12731 :
12732 6 : const Elf_Arhdr *h = elf_getarhdr (subelf);
12733 :
12734 6 : printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
12735 :
12736 6 : elf_end (subelf);
12737 : }
12738 :
12739 9 : printf ("\t%s\n", s->as_name);
12740 : }
12741 : }
12742 :
12743 : #include "debugpred.h"
|