Line data Source code
1 : /* Print information from ELF file in human-readable form.
2 : Copyright (C) 1999-2016 Red Hat, Inc.
3 : This file is part of elfutils.
4 : Written by Ulrich Drepper <drepper@redhat.com>, 1999.
5 :
6 : This file is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : elfutils is distributed in the hope that it will be useful, but
12 : WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 :
19 : #ifdef HAVE_CONFIG_H
20 : # include <config.h>
21 : #endif
22 :
23 : #include <argp.h>
24 : #include <assert.h>
25 : #include <ctype.h>
26 : #include <dwarf.h>
27 : #include <errno.h>
28 : #include <error.h>
29 : #include <fcntl.h>
30 : #include <gelf.h>
31 : #include <inttypes.h>
32 : #include <langinfo.h>
33 : #include <libdw.h>
34 : #include <libdwfl.h>
35 : #include <libintl.h>
36 : #include <locale.h>
37 : #include <stdarg.h>
38 : #include <stdbool.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 :
61 : /* Name and version of program. */
62 : ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
63 :
64 : /* Bug report address. */
65 : ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
66 :
67 : /* argp key value for --elf-section, non-ascii. */
68 : #define ELF_INPUT_SECTION 256
69 :
70 : /* Definitions of arguments for argp functions. */
71 : static const struct argp_option options[] =
72 : {
73 : { NULL, 0, NULL, 0, N_("ELF input selection:"), 0 },
74 : { "elf-section", ELF_INPUT_SECTION, "SECTION", OPTION_ARG_OPTIONAL,
75 : N_("Use the named SECTION (default .gnu_debugdata) as (compressed) ELF "
76 : "input data"), 0 },
77 : { NULL, 0, NULL, 0, N_("ELF output selection:"), 0 },
78 : { "all", 'a', NULL, 0,
79 : N_("All these plus -p .strtab -p .dynstr -p .comment"), 0 },
80 : { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
81 : { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
82 : { "histogram", 'I', NULL, 0,
83 : N_("Display histogram of bucket list lengths"), 0 },
84 : { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
85 : { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
86 : { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
87 : { "section-headers", 'S', NULL, 0, N_("Display the sections' headers"), 0 },
88 : { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
89 : { "symbols", 's', "SECTION", OPTION_ARG_OPTIONAL,
90 : N_("Display the symbol table sections"), 0 },
91 : { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
92 : { "notes", 'n', NULL, 0, N_("Display the ELF notes"), 0 },
93 : { "arch-specific", 'A', NULL, 0,
94 : N_("Display architecture specific information, if any"), 0 },
95 : { "exception", 'e', NULL, 0,
96 : N_("Display sections for exception handling"), 0 },
97 :
98 : { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 },
99 : { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
100 : N_("Display DWARF section content. SECTION can be one of abbrev, "
101 : "aranges, decodedaranges, frame, gdb_index, info, loc, line, "
102 : "decodedline, ranges, pubnames, str, macinfo, macro or exception"), 0 },
103 : { "hex-dump", 'x', "SECTION", 0,
104 : N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
105 : { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
106 : N_("Print string contents of sections"), 0 },
107 : { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
108 : { "archive-index", 'c', NULL, 0,
109 : N_("Display the symbol index of an archive"), 0 },
110 :
111 : { NULL, 0, NULL, 0, N_("Output control:"), 0 },
112 : { "numeric-addresses", 'N', NULL, 0,
113 : N_("Do not find symbol names for addresses in DWARF data"), 0 },
114 : { "unresolved-address-offsets", 'U', NULL, 0,
115 : N_("Display just offsets instead of resolving values to addresses in DWARF data"), 0 },
116 : { "wide", 'W', NULL, 0,
117 : N_("Ignored for compatibility (lines always wide)"), 0 },
118 : { "decompress", 'z', NULL, 0,
119 : N_("Show compression information for compressed sections (when used with -S); decompress section before dumping data (when used with -p or -x)"), 0 },
120 : { NULL, 0, NULL, 0, NULL, 0 }
121 : };
122 :
123 : /* Short description of program. */
124 : static const char doc[] = N_("\
125 : Print information from ELF file in human-readable form.");
126 :
127 : /* Strings for arguments in help texts. */
128 : static const char args_doc[] = N_("FILE...");
129 :
130 : /* Prototype for option handler. */
131 : static error_t parse_opt (int key, char *arg, struct argp_state *state);
132 :
133 : /* Data structure to communicate with argp functions. */
134 : static struct argp argp =
135 : {
136 : options, parse_opt, args_doc, doc, NULL, NULL, NULL
137 : };
138 :
139 : /* If non-null, the section from which we should read to (compressed) ELF. */
140 : static const char *elf_input_section = NULL;
141 :
142 : /* Flags set by the option controlling the output. */
143 :
144 : /* True if dynamic segment should be printed. */
145 : static bool print_dynamic_table;
146 :
147 : /* True if the file header should be printed. */
148 : static bool print_file_header;
149 :
150 : /* True if the program headers should be printed. */
151 : static bool print_program_header;
152 :
153 : /* True if relocations should be printed. */
154 : static bool print_relocations;
155 :
156 : /* True if the section headers should be printed. */
157 : static bool print_section_header;
158 :
159 : /* True if the symbol table should be printed. */
160 : static bool print_symbol_table;
161 :
162 : /* A specific section name, or NULL to print all symbol tables. */
163 : static char *symbol_table_section;
164 :
165 : /* True if the version information should be printed. */
166 : static bool print_version_info;
167 :
168 : /* True if section groups should be printed. */
169 : static bool print_section_groups;
170 :
171 : /* True if bucket list length histogram should be printed. */
172 : static bool print_histogram;
173 :
174 : /* True if the architecture specific data should be printed. */
175 : static bool print_arch;
176 :
177 : /* True if note section content should be printed. */
178 : static bool print_notes;
179 :
180 : /* True if SHF_STRINGS section content should be printed. */
181 : static bool print_string_sections;
182 :
183 : /* True if archive index should be printed. */
184 : static bool print_archive_index;
185 :
186 : /* True if any of the control options except print_archive_index is set. */
187 : static bool any_control_option;
188 :
189 : /* True if we should print addresses from DWARF in symbolic form. */
190 : static bool print_address_names = true;
191 :
192 : /* True if we should print raw values instead of relativized addresses. */
193 : static bool print_unresolved_addresses = false;
194 :
195 : /* True if we should print the .debug_aranges section using libdw. */
196 : static bool decodedaranges = false;
197 :
198 : /* True if we should print the .debug_aranges section using libdw. */
199 : static bool decodedline = false;
200 :
201 : /* True if we want to show more information about compressed sections. */
202 : static bool print_decompress = false;
203 :
204 : /* Select printing of debugging sections. */
205 : static enum section_e
206 : {
207 : section_abbrev = 1, /* .debug_abbrev */
208 : section_aranges = 2, /* .debug_aranges */
209 : section_frame = 4, /* .debug_frame or .eh_frame & al. */
210 : section_info = 8, /* .debug_info, .debug_types */
211 : section_types = section_info,
212 : section_line = 16, /* .debug_line */
213 : section_loc = 32, /* .debug_loc */
214 : section_pubnames = 64, /* .debug_pubnames */
215 : section_str = 128, /* .debug_str */
216 : section_macinfo = 256, /* .debug_macinfo */
217 : section_ranges = 512, /* .debug_ranges */
218 : section_exception = 1024, /* .eh_frame & al. */
219 : section_gdb_index = 2048, /* .gdb_index */
220 : section_macro = 4096, /* .debug_macro */
221 : section_all = (section_abbrev | section_aranges | section_frame
222 : | section_info | section_line | section_loc
223 : | section_pubnames | section_str | section_macinfo
224 : | section_ranges | section_exception | section_gdb_index
225 : | section_macro)
226 : } print_debug_sections, implicit_debug_sections;
227 :
228 : /* Select hex dumping of sections. */
229 : static struct section_argument *dump_data_sections;
230 : static struct section_argument **dump_data_sections_tail = &dump_data_sections;
231 :
232 : /* Select string dumping of sections. */
233 : static struct section_argument *string_sections;
234 : static struct section_argument **string_sections_tail = &string_sections;
235 :
236 : struct section_argument
237 : {
238 : struct section_argument *next;
239 : const char *arg;
240 : bool implicit;
241 : };
242 :
243 : /* Numbers of sections and program headers in the file. */
244 : static size_t shnum;
245 : static size_t phnum;
246 :
247 :
248 : /* Declarations of local functions. */
249 : static void process_file (int fd, const char *fname, bool only_one);
250 : static void process_elf_file (Dwfl_Module *dwflmod, int fd);
251 : static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
252 : static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
253 : static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
254 : static void print_scngrp (Ebl *ebl);
255 : static void print_dynamic (Ebl *ebl);
256 : static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
257 : static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
258 : GElf_Shdr *shdr);
259 : static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
260 : GElf_Shdr *shdr);
261 : static void print_symtab (Ebl *ebl, int type);
262 : static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
263 : static void print_verinfo (Ebl *ebl);
264 : static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
265 : static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
266 : static void handle_versym (Ebl *ebl, Elf_Scn *scn,
267 : GElf_Shdr *shdr);
268 : static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
269 : static void handle_hash (Ebl *ebl);
270 : static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
271 : static void print_liblist (Ebl *ebl);
272 : static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
273 : static void dump_data (Ebl *ebl);
274 : static void dump_strings (Ebl *ebl);
275 : static void print_strings (Ebl *ebl);
276 : static void dump_archive_index (Elf *, const char *);
277 :
278 :
279 : int
280 147 : main (int argc, char *argv[])
281 : {
282 : /* Set locale. */
283 147 : setlocale (LC_ALL, "");
284 :
285 : /* Initialize the message catalog. */
286 147 : textdomain (PACKAGE_TARNAME);
287 :
288 : /* Parse and process arguments. */
289 : int remaining;
290 147 : argp_parse (&argp, argc, argv, 0, &remaining, NULL);
291 :
292 : /* Before we start tell the ELF library which version we are using. */
293 147 : elf_version (EV_CURRENT);
294 :
295 : /* Now process all the files given at the command line. */
296 147 : bool only_one = remaining + 1 == argc;
297 : do
298 : {
299 : /* Open the file. */
300 296 : int fd = open (argv[remaining], O_RDONLY);
301 148 : if (fd == -1)
302 : {
303 0 : error (0, errno, gettext ("cannot open input file"));
304 0 : continue;
305 : }
306 :
307 148 : process_file (fd, argv[remaining], only_one);
308 :
309 148 : close (fd);
310 : }
311 148 : while (++remaining < argc);
312 :
313 147 : return error_message_count != 0;
314 : }
315 :
316 :
317 : /* Handle program arguments. */
318 : static error_t
319 934 : parse_opt (int key, char *arg,
320 : struct argp_state *state __attribute__ ((unused)))
321 : {
322 102 : void add_dump_section (const char *name, bool implicit)
323 : {
324 102 : struct section_argument *a = xmalloc (sizeof *a);
325 102 : a->arg = name;
326 102 : a->next = NULL;
327 102 : a->implicit = implicit;
328 102 : struct section_argument ***tailp
329 102 : = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
330 102 : **tailp = a;
331 102 : *tailp = &a->next;
332 102 : }
333 :
334 934 : switch (key)
335 : {
336 : case 'a':
337 32 : print_file_header = true;
338 32 : print_program_header = true;
339 32 : print_relocations = true;
340 32 : print_section_header = true;
341 32 : print_symbol_table = true;
342 32 : print_version_info = true;
343 32 : print_dynamic_table = true;
344 32 : print_section_groups = true;
345 32 : print_histogram = true;
346 32 : print_arch = true;
347 32 : print_notes = true;
348 32 : implicit_debug_sections |= section_exception;
349 32 : add_dump_section (".strtab", true);
350 32 : add_dump_section (".dynstr", true);
351 32 : add_dump_section (".comment", true);
352 32 : any_control_option = true;
353 32 : break;
354 : case 'A':
355 4 : print_arch = true;
356 4 : any_control_option = true;
357 4 : break;
358 : case 'd':
359 2 : print_dynamic_table = true;
360 2 : any_control_option = true;
361 2 : break;
362 : case 'e':
363 0 : print_debug_sections |= section_exception;
364 0 : any_control_option = true;
365 0 : break;
366 : case 'g':
367 0 : print_section_groups = true;
368 0 : any_control_option = true;
369 0 : break;
370 : case 'h':
371 0 : print_file_header = true;
372 0 : any_control_option = true;
373 0 : break;
374 : case 'I':
375 0 : print_histogram = true;
376 0 : any_control_option = true;
377 0 : break;
378 : case 'l':
379 0 : print_program_header = true;
380 0 : any_control_option = true;
381 0 : break;
382 : case 'n':
383 10 : print_notes = true;
384 10 : any_control_option = true;
385 10 : break;
386 : case 'r':
387 1 : print_relocations = true;
388 1 : any_control_option = true;
389 1 : break;
390 : case 'S':
391 20 : print_section_header = true;
392 20 : any_control_option = true;
393 20 : break;
394 : case 's':
395 14 : print_symbol_table = true;
396 14 : any_control_option = true;
397 14 : symbol_table_section = arg;
398 14 : break;
399 : case 'V':
400 0 : print_version_info = true;
401 0 : any_control_option = true;
402 0 : break;
403 : case 'c':
404 2 : print_archive_index = true;
405 2 : break;
406 : case 'w':
407 71 : if (arg == NULL)
408 33 : print_debug_sections = section_all;
409 38 : else if (strcmp (arg, "abbrev") == 0)
410 0 : print_debug_sections |= section_abbrev;
411 38 : else if (strcmp (arg, "aranges") == 0)
412 3 : print_debug_sections |= section_aranges;
413 35 : else if (strcmp (arg, "decodedaranges") == 0)
414 : {
415 1 : print_debug_sections |= section_aranges;
416 1 : decodedaranges = true;
417 : }
418 34 : else if (strcmp (arg, "ranges") == 0)
419 : {
420 5 : print_debug_sections |= section_ranges;
421 5 : implicit_debug_sections |= section_info;
422 : }
423 29 : else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
424 2 : print_debug_sections |= section_frame;
425 27 : else if (strcmp (arg, "info") == 0)
426 10 : print_debug_sections |= section_info;
427 17 : else if (strcmp (arg, "loc") == 0)
428 : {
429 8 : print_debug_sections |= section_loc;
430 8 : implicit_debug_sections |= section_info;
431 : }
432 9 : else if (strcmp (arg, "line") == 0)
433 3 : print_debug_sections |= section_line;
434 6 : else if (strcmp (arg, "decodedline") == 0)
435 : {
436 1 : print_debug_sections |= section_line;
437 1 : decodedline = true;
438 : }
439 5 : else if (strcmp (arg, "pubnames") == 0)
440 0 : print_debug_sections |= section_pubnames;
441 5 : else if (strcmp (arg, "str") == 0)
442 0 : print_debug_sections |= section_str;
443 5 : else if (strcmp (arg, "macinfo") == 0)
444 0 : print_debug_sections |= section_macinfo;
445 5 : else if (strcmp (arg, "macro") == 0)
446 3 : print_debug_sections |= section_macro;
447 2 : else if (strcmp (arg, "exception") == 0)
448 0 : print_debug_sections |= section_exception;
449 2 : else if (strcmp (arg, "gdb_index") == 0)
450 2 : print_debug_sections |= section_gdb_index;
451 : else
452 : {
453 0 : fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
454 : arg);
455 0 : argp_help (&argp, stderr, ARGP_HELP_SEE,
456 : program_invocation_short_name);
457 0 : exit (1);
458 : }
459 71 : any_control_option = true;
460 71 : break;
461 : case 'p':
462 1 : any_control_option = true;
463 1 : if (arg == NULL)
464 : {
465 0 : print_string_sections = true;
466 0 : break;
467 : }
468 : /* Fall through. */
469 : case 'x':
470 6 : add_dump_section (arg, false);
471 6 : any_control_option = true;
472 6 : break;
473 : case 'N':
474 1 : print_address_names = false;
475 1 : break;
476 : case 'U':
477 19 : print_unresolved_addresses = true;
478 19 : break;
479 : case ARGP_KEY_NO_ARGS:
480 0 : fputs (gettext ("Missing file name.\n"), stderr);
481 0 : goto do_argp_help;
482 : case ARGP_KEY_FINI:
483 147 : if (! any_control_option && ! print_archive_index)
484 : {
485 0 : fputs (gettext ("No operation specified.\n"), stderr);
486 : do_argp_help:
487 0 : argp_help (&argp, stderr, ARGP_HELP_SEE,
488 : program_invocation_short_name);
489 0 : exit (EXIT_FAILURE);
490 : }
491 : break;
492 : case 'W': /* Ignored. */
493 : break;
494 : case 'z':
495 13 : print_decompress = true;
496 13 : break;
497 : case ELF_INPUT_SECTION:
498 4 : if (arg == NULL)
499 4 : elf_input_section = ".gnu_debugdata";
500 : else
501 0 : elf_input_section = arg;
502 : break;
503 : default:
504 : return ARGP_ERR_UNKNOWN;
505 : }
506 : return 0;
507 : }
508 :
509 :
510 : /* Create a file descriptor to read the data from the
511 : elf_input_section given a file descriptor to an ELF file. */
512 : static int
513 4 : open_input_section (int fd)
514 : {
515 : size_t shnums;
516 : size_t cnt;
517 : size_t shstrndx;
518 4 : Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
519 4 : if (elf == NULL)
520 : {
521 0 : error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
522 : elf_errmsg (-1));
523 0 : return -1;
524 : }
525 :
526 4 : if (elf_getshdrnum (elf, &shnums) < 0)
527 : {
528 0 : error (0, 0, gettext ("cannot determine number of sections: %s"),
529 : elf_errmsg (-1));
530 : open_error:
531 0 : elf_end (elf);
532 0 : return -1;
533 : }
534 :
535 4 : if (elf_getshdrstrndx (elf, &shstrndx) < 0)
536 : {
537 0 : error (0, 0, gettext ("cannot get section header string table index"));
538 : goto open_error;
539 : }
540 :
541 178 : for (cnt = 0; cnt < shnums; ++cnt)
542 : {
543 91 : Elf_Scn *scn = elf_getscn (elf, cnt);
544 91 : if (scn == NULL)
545 : {
546 0 : error (0, 0, gettext ("cannot get section: %s"),
547 : elf_errmsg (-1));
548 0 : goto open_error;
549 : }
550 :
551 : GElf_Shdr shdr_mem;
552 91 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
553 91 : if (unlikely (shdr == NULL))
554 : {
555 0 : error (0, 0, gettext ("cannot get section header: %s"),
556 : elf_errmsg (-1));
557 : goto open_error;
558 : }
559 :
560 91 : const char *sname = elf_strptr (elf, shstrndx, shdr->sh_name);
561 91 : if (sname == NULL)
562 : {
563 0 : error (0, 0, gettext ("cannot get section name"));
564 : goto open_error;
565 : }
566 :
567 91 : if (strcmp (sname, elf_input_section) == 0)
568 : {
569 4 : Elf_Data *data = elf_rawdata (scn, NULL);
570 4 : if (data == NULL)
571 : {
572 0 : error (0, 0, gettext ("cannot get %s content: %s"),
573 : sname, elf_errmsg (-1));
574 : goto open_error;
575 : }
576 :
577 : /* Create (and immediately unlink) a temporary file to store
578 : section data in to create a file descriptor for it. */
579 4 : const char *tmpdir = getenv ("TMPDIR") ?: P_tmpdir;
580 : static const char suffix[] = "/readelfXXXXXX";
581 4 : int tmplen = strlen (tmpdir) + sizeof (suffix);
582 4 : char *tempname = alloca (tmplen);
583 4 : sprintf (tempname, "%s%s", tmpdir, suffix);
584 :
585 4 : int sfd = mkstemp (tempname);
586 4 : if (sfd == -1)
587 : {
588 0 : error (0, 0, gettext ("cannot create temp file '%s'"),
589 : tempname);
590 : goto open_error;
591 : }
592 4 : unlink (tempname);
593 :
594 4 : ssize_t size = data->d_size;
595 4 : if (write_retry (sfd, data->d_buf, size) != size)
596 : {
597 0 : error (0, 0, gettext ("cannot write section data"));
598 : goto open_error;
599 : }
600 :
601 4 : if (elf_end (elf) != 0)
602 : {
603 0 : error (0, 0, gettext ("error while closing Elf descriptor: %s"),
604 : elf_errmsg (-1));
605 0 : return -1;
606 : }
607 :
608 4 : if (lseek (sfd, 0, SEEK_SET) == -1)
609 : {
610 0 : error (0, 0, gettext ("error while rewinding file descriptor"));
611 0 : return -1;
612 : }
613 :
614 : return sfd;
615 : }
616 : }
617 :
618 : /* Named section not found. */
619 0 : if (elf_end (elf) != 0)
620 0 : error (0, 0, gettext ("error while closing Elf descriptor: %s"),
621 : elf_errmsg (-1));
622 : return -1;
623 : }
624 :
625 : /* Check if the file is an archive, and if so dump its index. */
626 : static void
627 2 : check_archive_index (int fd, const char *fname, bool only_one)
628 : {
629 : /* Create an `Elf' descriptor. */
630 2 : Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
631 2 : if (elf == NULL)
632 0 : error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
633 : elf_errmsg (-1));
634 : else
635 : {
636 2 : if (elf_kind (elf) == ELF_K_AR)
637 : {
638 2 : if (!only_one)
639 : printf ("\n%s:\n\n", fname);
640 2 : dump_archive_index (elf, fname);
641 : }
642 : else
643 : error (0, 0,
644 0 : gettext ("'%s' is not an archive, cannot print archive index"),
645 : fname);
646 :
647 : /* Now we can close the descriptor. */
648 2 : if (elf_end (elf) != 0)
649 0 : error (0, 0, gettext ("error while closing Elf descriptor: %s"),
650 : elf_errmsg (-1));
651 : }
652 2 : }
653 :
654 : /* Trivial callback used for checking if we opened an archive. */
655 : static int
656 144 : count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
657 : void **userdata __attribute__ ((unused)),
658 : const char *name __attribute__ ((unused)),
659 : Dwarf_Addr base __attribute__ ((unused)),
660 : void *arg)
661 : {
662 144 : if (*(bool *) arg)
663 : return DWARF_CB_ABORT;
664 144 : *(bool *) arg = true;
665 144 : return DWARF_CB_OK;
666 : }
667 :
668 : struct process_dwflmod_args
669 : {
670 : int fd;
671 : bool only_one;
672 : };
673 :
674 : static int
675 146 : process_dwflmod (Dwfl_Module *dwflmod,
676 : void **userdata __attribute__ ((unused)),
677 : const char *name __attribute__ ((unused)),
678 : Dwarf_Addr base __attribute__ ((unused)),
679 : void *arg)
680 : {
681 146 : const struct process_dwflmod_args *a = arg;
682 :
683 : /* Print the file name. */
684 146 : if (!a->only_one)
685 : {
686 : const char *fname;
687 2 : dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
688 :
689 4 : printf ("\n%s:\n\n", fname);
690 : }
691 :
692 146 : process_elf_file (dwflmod, a->fd);
693 :
694 146 : return DWARF_CB_OK;
695 : }
696 :
697 : /* Stub libdwfl callback, only the ELF handle already open is ever used.
698 : Only used for finding the alternate debug file if the Dwarf comes from
699 : the main file. We are not interested in separate debuginfo. */
700 : static int
701 27 : find_no_debuginfo (Dwfl_Module *mod,
702 : void **userdata,
703 : const char *modname,
704 : Dwarf_Addr base,
705 : const char *file_name,
706 : const char *debuglink_file,
707 : GElf_Word debuglink_crc,
708 : char **debuginfo_file_name)
709 : {
710 : Dwarf_Addr dwbias;
711 27 : dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
712 :
713 : /* We are only interested if the Dwarf has been setup on the main
714 : elf file but is only missing the alternate debug link. If dwbias
715 : hasn't even been setup, this is searching for separate debuginfo
716 : for the main elf. We don't care in that case. */
717 27 : if (dwbias == (Dwarf_Addr) -1)
718 : return -1;
719 :
720 5 : return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
721 : file_name, debuglink_file,
722 : debuglink_crc, debuginfo_file_name);
723 : }
724 :
725 : /* Process one input file. */
726 : static void
727 148 : process_file (int fd, const char *fname, bool only_one)
728 : {
729 148 : if (print_archive_index)
730 2 : check_archive_index (fd, fname, only_one);
731 :
732 148 : if (!any_control_option)
733 : return;
734 :
735 146 : if (elf_input_section != NULL)
736 : {
737 : /* Replace fname and fd with section content. */
738 4 : char *fnname = alloca (strlen (fname) + strlen (elf_input_section) + 2);
739 8 : sprintf (fnname, "%s:%s", fname, elf_input_section);
740 4 : fd = open_input_section (fd);
741 4 : if (fd == -1)
742 : {
743 0 : error (0, 0, gettext ("No such section '%s' in '%s'"),
744 : elf_input_section, fname);
745 : return;
746 : }
747 : fname = fnname;
748 : }
749 :
750 : /* Duplicate an fd for dwfl_report_offline to swallow. */
751 146 : int dwfl_fd = dup (fd);
752 146 : if (unlikely (dwfl_fd < 0))
753 0 : error (EXIT_FAILURE, errno, "dup");
754 :
755 : /* Use libdwfl in a trivial way to open the libdw handle for us.
756 : This takes care of applying relocations to DWARF data in ET_REL files. */
757 : static const Dwfl_Callbacks callbacks =
758 : {
759 : .section_address = dwfl_offline_section_address,
760 : .find_debuginfo = find_no_debuginfo
761 : };
762 146 : Dwfl *dwfl = dwfl_begin (&callbacks);
763 146 : if (likely (dwfl != NULL))
764 : /* Let 0 be the logical address of the file (or first in archive). */
765 146 : dwfl->offline_next_address = 0;
766 146 : if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
767 : {
768 : struct stat st;
769 0 : if (fstat (dwfl_fd, &st) != 0)
770 0 : error (0, errno, gettext ("cannot stat input file"));
771 0 : else if (unlikely (st.st_size == 0))
772 0 : error (0, 0, gettext ("input file is empty"));
773 : else
774 0 : error (0, 0, gettext ("failed reading '%s': %s"),
775 : fname, dwfl_errmsg (-1));
776 0 : close (dwfl_fd); /* Consumed on success, not on failure. */
777 : }
778 : else
779 : {
780 146 : dwfl_report_end (dwfl, NULL, NULL);
781 :
782 146 : if (only_one)
783 : {
784 : /* Clear ONLY_ONE if we have multiple modules, from an archive. */
785 144 : bool seen = false;
786 144 : only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
787 : }
788 :
789 : /* Process the one or more modules gleaned from this file. */
790 146 : struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
791 146 : dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
792 : }
793 146 : dwfl_end (dwfl);
794 :
795 : /* Need to close the replaced fd if we created it. Caller takes
796 : care of original. */
797 146 : if (elf_input_section != NULL)
798 4 : close (fd);
799 : }
800 :
801 : /* Check whether there are any compressed sections in the ELF file. */
802 : static bool
803 44 : elf_contains_chdrs (Elf *elf)
804 : {
805 44 : Elf_Scn *scn = NULL;
806 874 : while ((scn = elf_nextscn (elf, scn)) != NULL)
807 : {
808 : GElf_Shdr shdr_mem;
809 792 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
810 792 : if (shdr != NULL && (shdr->sh_flags & SHF_COMPRESSED) != 0)
811 6 : return true;
812 : }
813 : return false;
814 : }
815 :
816 : /* Process one ELF file. */
817 : static void
818 146 : process_elf_file (Dwfl_Module *dwflmod, int fd)
819 : {
820 : GElf_Addr dwflbias;
821 146 : Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
822 :
823 : GElf_Ehdr ehdr_mem;
824 146 : GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
825 :
826 146 : if (ehdr == NULL)
827 : {
828 : elf_error:
829 0 : error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
830 0 : return;
831 : }
832 :
833 146 : Ebl *ebl = ebl_openbackend (elf);
834 146 : if (unlikely (ebl == NULL))
835 : {
836 : ebl_error:
837 0 : error (0, errno, gettext ("cannot create EBL handle"));
838 : return;
839 : }
840 :
841 : /* Determine the number of sections. */
842 146 : if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
843 0 : error (EXIT_FAILURE, 0,
844 0 : gettext ("cannot determine number of sections: %s"),
845 : elf_errmsg (-1));
846 :
847 : /* Determine the number of phdrs. */
848 146 : if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
849 0 : error (EXIT_FAILURE, 0,
850 0 : gettext ("cannot determine number of program headers: %s"),
851 : elf_errmsg (-1));
852 :
853 : /* For an ET_REL file, libdwfl has adjusted the in-core shdrs and
854 : may have applied relocation to some sections. If there are any
855 : compressed sections, any pass (or libdw/libdwfl) might have
856 : uncompressed them. So we need to get a fresh Elf handle on the
857 : file to display those. */
858 292 : bool print_unchanged = ((print_section_header
859 94 : || print_relocations
860 93 : || dump_data_sections != NULL
861 88 : || print_notes)
862 214 : && (ehdr->e_type == ET_REL
863 44 : || elf_contains_chdrs (ebl->elf)));
864 :
865 146 : Elf *pure_elf = NULL;
866 146 : Ebl *pure_ebl = ebl;
867 146 : if (print_unchanged)
868 : {
869 : /* Read the file afresh. */
870 30 : off_t aroff = elf_getaroff (elf);
871 30 : pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
872 30 : if (aroff > 0)
873 : {
874 : /* Archive member. */
875 0 : (void) elf_rand (pure_elf, aroff);
876 0 : Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
877 0 : elf_end (pure_elf);
878 0 : pure_elf = armem;
879 : }
880 30 : if (pure_elf == NULL)
881 : goto elf_error;
882 30 : pure_ebl = ebl_openbackend (pure_elf);
883 30 : if (pure_ebl == NULL)
884 : goto ebl_error;
885 : }
886 :
887 146 : if (print_file_header)
888 32 : print_ehdr (ebl, ehdr);
889 146 : if (print_section_header)
890 52 : print_shdr (pure_ebl, ehdr);
891 146 : if (print_program_header)
892 32 : print_phdr (ebl, ehdr);
893 146 : if (print_section_groups)
894 32 : print_scngrp (ebl);
895 146 : if (print_dynamic_table)
896 34 : print_dynamic (ebl);
897 146 : if (print_relocations)
898 33 : print_relocs (pure_ebl, ehdr);
899 146 : if (print_histogram)
900 32 : handle_hash (ebl);
901 146 : if (print_symbol_table)
902 46 : print_symtab (ebl, SHT_DYNSYM);
903 146 : if (print_version_info)
904 32 : print_verinfo (ebl);
905 146 : if (print_symbol_table)
906 46 : print_symtab (ebl, SHT_SYMTAB);
907 146 : if (print_arch)
908 36 : print_liblist (ebl);
909 146 : if (print_arch)
910 36 : print_attributes (ebl, ehdr);
911 146 : if (dump_data_sections != NULL)
912 5 : dump_data (pure_ebl);
913 146 : if (string_sections != NULL)
914 33 : dump_strings (ebl);
915 146 : if ((print_debug_sections | implicit_debug_sections) != 0)
916 89 : print_debug (dwflmod, ebl, ehdr);
917 146 : if (print_notes)
918 42 : handle_notes (pure_ebl, ehdr);
919 146 : if (print_string_sections)
920 0 : print_strings (ebl);
921 :
922 146 : ebl_closebackend (ebl);
923 :
924 146 : if (pure_ebl != ebl)
925 : {
926 30 : ebl_closebackend (pure_ebl);
927 30 : elf_end (pure_elf);
928 : }
929 : }
930 :
931 :
932 : /* Print file type. */
933 : static void
934 32 : print_file_type (unsigned short int e_type)
935 : {
936 32 : if (likely (e_type <= ET_CORE))
937 : {
938 : static const char *const knowntypes[] =
939 : {
940 : N_("NONE (None)"),
941 : N_("REL (Relocatable file)"),
942 : N_("EXEC (Executable file)"),
943 : N_("DYN (Shared object file)"),
944 : N_("CORE (Core file)")
945 : };
946 32 : puts (gettext (knowntypes[e_type]));
947 : }
948 0 : else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
949 0 : printf (gettext ("OS Specific: (%x)\n"), e_type);
950 0 : else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
951 0 : printf (gettext ("Processor Specific: (%x)\n"), e_type);
952 : else
953 0 : puts ("???");
954 32 : }
955 :
956 :
957 : /* Print ELF header. */
958 : static void
959 32 : print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
960 : {
961 32 : fputs_unlocked (gettext ("ELF Header:\n Magic: "), stdout);
962 544 : for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
963 1024 : printf (" %02hhx", ehdr->e_ident[cnt]);
964 :
965 96 : printf (gettext ("\n Class: %s\n"),
966 32 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
967 : : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
968 28 : : "\?\?\?");
969 :
970 96 : printf (gettext (" Data: %s\n"),
971 32 : ehdr->e_ident[EI_DATA] == ELFDATA2LSB
972 : ? "2's complement, little endian"
973 : : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
974 6 : ? "2's complement, big endian" : "\?\?\?");
975 :
976 96 : printf (gettext (" Ident Version: %hhd %s\n"),
977 32 : ehdr->e_ident[EI_VERSION],
978 32 : ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
979 : : "(\?\?\?)");
980 :
981 : char buf[512];
982 64 : printf (gettext (" OS/ABI: %s\n"),
983 32 : ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
984 :
985 64 : printf (gettext (" ABI Version: %hhd\n"),
986 32 : ehdr->e_ident[EI_ABIVERSION]);
987 :
988 32 : fputs_unlocked (gettext (" Type: "), stdout);
989 32 : print_file_type (ehdr->e_type);
990 :
991 64 : printf (gettext (" Machine: %s\n"), ebl->name);
992 :
993 64 : printf (gettext (" Version: %d %s\n"),
994 : ehdr->e_version,
995 32 : ehdr->e_version == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
996 :
997 64 : printf (gettext (" Entry point address: %#" PRIx64 "\n"),
998 : ehdr->e_entry);
999 :
1000 64 : printf (gettext (" Start of program headers: %" PRId64 " %s\n"),
1001 : ehdr->e_phoff, gettext ("(bytes into file)"));
1002 :
1003 64 : printf (gettext (" Start of section headers: %" PRId64 " %s\n"),
1004 : ehdr->e_shoff, gettext ("(bytes into file)"));
1005 :
1006 64 : printf (gettext (" Flags: %s\n"),
1007 : ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
1008 :
1009 96 : printf (gettext (" Size of this header: %" PRId16 " %s\n"),
1010 32 : ehdr->e_ehsize, gettext ("(bytes)"));
1011 :
1012 96 : printf (gettext (" Size of program header entries: %" PRId16 " %s\n"),
1013 32 : ehdr->e_phentsize, gettext ("(bytes)"));
1014 :
1015 64 : printf (gettext (" Number of program headers entries: %" PRId16),
1016 32 : ehdr->e_phnum);
1017 32 : if (ehdr->e_phnum == PN_XNUM)
1018 : {
1019 : GElf_Shdr shdr_mem;
1020 0 : GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
1021 0 : if (shdr != NULL)
1022 0 : printf (gettext (" (%" PRIu32 " in [0].sh_info)"),
1023 0 : (uint32_t) shdr->sh_info);
1024 : else
1025 0 : fputs_unlocked (gettext (" ([0] not available)"), stdout);
1026 : }
1027 64 : fputc_unlocked ('\n', stdout);
1028 :
1029 96 : printf (gettext (" Size of section header entries: %" PRId16 " %s\n"),
1030 32 : ehdr->e_shentsize, gettext ("(bytes)"));
1031 :
1032 64 : printf (gettext (" Number of section headers entries: %" PRId16),
1033 32 : ehdr->e_shnum);
1034 32 : if (ehdr->e_shnum == 0)
1035 : {
1036 : GElf_Shdr shdr_mem;
1037 0 : GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
1038 0 : if (shdr != NULL)
1039 0 : printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
1040 0 : (uint32_t) shdr->sh_size);
1041 : else
1042 0 : fputs_unlocked (gettext (" ([0] not available)"), stdout);
1043 : }
1044 64 : fputc_unlocked ('\n', stdout);
1045 :
1046 32 : if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
1047 : {
1048 : GElf_Shdr shdr_mem;
1049 0 : GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
1050 0 : if (shdr != NULL)
1051 : /* We managed to get the zeroth section. */
1052 0 : snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
1053 0 : (uint32_t) shdr->sh_link);
1054 : else
1055 : {
1056 0 : strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
1057 0 : buf[sizeof (buf) - 1] = '\0';
1058 : }
1059 :
1060 0 : printf (gettext (" Section header string table index: XINDEX%s\n\n"),
1061 : buf);
1062 : }
1063 : else
1064 32 : printf (gettext (" Section header string table index: %" PRId16 "\n\n"),
1065 : ehdr->e_shstrndx);
1066 32 : }
1067 :
1068 :
1069 : static const char *
1070 : get_visibility_type (int value)
1071 : {
1072 : switch (value)
1073 : {
1074 : case STV_DEFAULT:
1075 : return "DEFAULT";
1076 : case STV_INTERNAL:
1077 : return "INTERNAL";
1078 : case STV_HIDDEN:
1079 : return "HIDDEN";
1080 : case STV_PROTECTED:
1081 : return "PROTECTED";
1082 : default:
1083 : return "???";
1084 : }
1085 : }
1086 :
1087 : static const char *
1088 : elf_ch_type_name (unsigned int code)
1089 : {
1090 12 : if (code == 0)
1091 : return "NONE";
1092 :
1093 12 : if (code == ELFCOMPRESS_ZLIB)
1094 : return "ZLIB";
1095 :
1096 : return "UNKNOWN";
1097 : }
1098 :
1099 : /* Print the section headers. */
1100 : static void
1101 52 : print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
1102 : {
1103 : size_t cnt;
1104 : size_t shstrndx;
1105 :
1106 52 : if (! print_file_header)
1107 40 : printf (gettext ("\
1108 : There are %d section headers, starting at offset %#" PRIx64 ":\n\
1109 : \n"),
1110 20 : ehdr->e_shnum, ehdr->e_shoff);
1111 :
1112 : /* Get the section header string table index. */
1113 52 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1114 : error (EXIT_FAILURE, 0,
1115 0 : gettext ("cannot get section header string table index"));
1116 :
1117 52 : puts (gettext ("Section Headers:"));
1118 :
1119 52 : if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1120 16 : puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
1121 : else
1122 36 : puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
1123 :
1124 52 : if (print_decompress)
1125 : {
1126 8 : if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1127 4 : puts (gettext (" [Compression Size Al]"));
1128 : else
1129 4 : puts (gettext (" [Compression Size Al]"));
1130 : }
1131 :
1132 1237 : for (cnt = 0; cnt < shnum; ++cnt)
1133 : {
1134 1237 : Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
1135 :
1136 1237 : if (unlikely (scn == NULL))
1137 0 : error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
1138 : elf_errmsg (-1));
1139 :
1140 : /* Get the section header. */
1141 : GElf_Shdr shdr_mem;
1142 1237 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1143 1237 : if (unlikely (shdr == NULL))
1144 0 : error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
1145 : elf_errmsg (-1));
1146 :
1147 : char flagbuf[20];
1148 1237 : char *cp = flagbuf;
1149 1237 : if (shdr->sh_flags & SHF_WRITE)
1150 255 : *cp++ = 'W';
1151 1237 : if (shdr->sh_flags & SHF_ALLOC)
1152 750 : *cp++ = 'A';
1153 1237 : if (shdr->sh_flags & SHF_EXECINSTR)
1154 145 : *cp++ = 'X';
1155 1237 : if (shdr->sh_flags & SHF_MERGE)
1156 78 : *cp++ = 'M';
1157 1237 : if (shdr->sh_flags & SHF_STRINGS)
1158 78 : *cp++ = 'S';
1159 1237 : if (shdr->sh_flags & SHF_INFO_LINK)
1160 86 : *cp++ = 'I';
1161 1237 : if (shdr->sh_flags & SHF_LINK_ORDER)
1162 0 : *cp++ = 'L';
1163 1237 : if (shdr->sh_flags & SHF_OS_NONCONFORMING)
1164 0 : *cp++ = 'N';
1165 1237 : if (shdr->sh_flags & SHF_GROUP)
1166 0 : *cp++ = 'G';
1167 1237 : if (shdr->sh_flags & SHF_TLS)
1168 10 : *cp++ = 'T';
1169 1237 : if (shdr->sh_flags & SHF_COMPRESSED)
1170 12 : *cp++ = 'C';
1171 1237 : if (shdr->sh_flags & SHF_ORDERED)
1172 0 : *cp++ = 'O';
1173 1237 : if (shdr->sh_flags & SHF_EXCLUDE)
1174 0 : *cp++ = 'E';
1175 1237 : *cp = '\0';
1176 :
1177 : const char *sname;
1178 : char buf[128];
1179 1237 : sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "<corrupt>";
1180 4948 : printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
1181 : " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
1182 : " %2" PRId64 "\n",
1183 : cnt, sname,
1184 1237 : ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
1185 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
1186 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
1187 1237 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
1188 : shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
1189 : shdr->sh_addralign);
1190 :
1191 1237 : if (print_decompress)
1192 : {
1193 76 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1194 : {
1195 : GElf_Chdr chdr;
1196 12 : if (gelf_getchdr (scn, &chdr) != NULL)
1197 36 : printf (" [ELF %s (%" PRId32 ") %0*" PRIx64
1198 : " %2" PRId64 "]\n",
1199 : elf_ch_type_name (chdr.ch_type),
1200 : chdr.ch_type,
1201 12 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8,
1202 : chdr.ch_size, chdr.ch_addralign);
1203 : else
1204 0 : error (0, 0,
1205 0 : gettext ("bad compression header for section %zd: %s"),
1206 : elf_ndxscn (scn), elf_errmsg (-1));
1207 : }
1208 64 : else if (strncmp(".zdebug", sname, strlen (".zdebug")) == 0)
1209 : {
1210 : ssize_t size;
1211 12 : if ((size = dwelf_scn_gnu_compressed_size (scn)) >= 0)
1212 12 : printf (" [GNU ZLIB %0*zx ]\n",
1213 12 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, size);
1214 : else
1215 0 : error (0, 0,
1216 0 : gettext ("bad gnu compressed size for section %zd: %s"),
1217 : elf_ndxscn (scn), elf_errmsg (-1));
1218 : }
1219 : }
1220 : }
1221 :
1222 104 : fputc_unlocked ('\n', stdout);
1223 52 : }
1224 :
1225 :
1226 : /* Print the program header. */
1227 : static void
1228 32 : print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
1229 : {
1230 32 : if (phnum == 0)
1231 : /* No program header, this is OK in relocatable objects. */
1232 20 : return;
1233 :
1234 12 : puts (gettext ("Program Headers:"));
1235 12 : if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1236 0 : puts (gettext ("\
1237 : Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
1238 : else
1239 12 : puts (gettext ("\
1240 : Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
1241 :
1242 : /* Process all program headers. */
1243 : bool has_relro = false;
1244 : GElf_Addr relro_from = 0;
1245 : GElf_Addr relro_to = 0;
1246 110 : for (size_t cnt = 0; cnt < phnum; ++cnt)
1247 : {
1248 : char buf[128];
1249 : GElf_Phdr mem;
1250 110 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
1251 :
1252 : /* If for some reason the header cannot be returned show this. */
1253 110 : if (unlikely (phdr == NULL))
1254 : {
1255 0 : puts (" ???");
1256 0 : continue;
1257 : }
1258 :
1259 770 : printf (" %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
1260 : " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
1261 110 : ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
1262 : phdr->p_offset,
1263 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
1264 110 : ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
1265 : phdr->p_filesz,
1266 : phdr->p_memsz,
1267 110 : phdr->p_flags & PF_R ? 'R' : ' ',
1268 110 : phdr->p_flags & PF_W ? 'W' : ' ',
1269 110 : phdr->p_flags & PF_X ? 'E' : ' ',
1270 : phdr->p_align);
1271 :
1272 110 : if (phdr->p_type == PT_INTERP)
1273 : {
1274 : /* If we are sure the file offset is valid then we can show
1275 : the user the name of the interpreter. We check whether
1276 : there is a section at the file offset. Normally there
1277 : would be a section called ".interp". But in separate
1278 : .debug files it is a NOBITS section (and so doesn't match
1279 : with gelf_offscn). Which probably means the offset is
1280 : not valid another reason could be because the ELF file
1281 : just doesn't contain any section headers, in that case
1282 : just play it safe and don't display anything. */
1283 :
1284 8 : Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
1285 : GElf_Shdr shdr_mem;
1286 8 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1287 :
1288 : size_t maxsize;
1289 8 : char *filedata = elf_rawfile (ebl->elf, &maxsize);
1290 :
1291 8 : if (shdr != NULL && shdr->sh_type == SHT_PROGBITS
1292 8 : && filedata != NULL && phdr->p_offset < maxsize
1293 8 : && phdr->p_filesz <= maxsize - phdr->p_offset
1294 8 : && memchr (filedata + phdr->p_offset, '\0',
1295 : phdr->p_filesz) != NULL)
1296 8 : printf (gettext ("\t[Requesting program interpreter: %s]\n"),
1297 : filedata + phdr->p_offset);
1298 : }
1299 102 : else if (phdr->p_type == PT_GNU_RELRO)
1300 : {
1301 12 : has_relro = true;
1302 12 : relro_from = phdr->p_vaddr;
1303 12 : relro_to = relro_from + phdr->p_memsz;
1304 : }
1305 : }
1306 :
1307 12 : if (ehdr->e_shnum == 0)
1308 : /* No sections in the file. Punt. */
1309 : return;
1310 :
1311 : /* Get the section header string table index. */
1312 : size_t shstrndx;
1313 12 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1314 : error (EXIT_FAILURE, 0,
1315 0 : gettext ("cannot get section header string table index"));
1316 :
1317 12 : puts (gettext ("\n Section to Segment mapping:\n Segment Sections..."));
1318 :
1319 122 : for (size_t cnt = 0; cnt < phnum; ++cnt)
1320 : {
1321 : /* Print the segment number. */
1322 110 : printf (" %2.2zu ", cnt);
1323 :
1324 : GElf_Phdr phdr_mem;
1325 110 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
1326 : /* This must not happen. */
1327 110 : if (unlikely (phdr == NULL))
1328 0 : error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
1329 : elf_errmsg (-1));
1330 :
1331 : /* Iterate over the sections. */
1332 : bool in_relro = false;
1333 : bool in_ro = false;
1334 4086 : for (size_t inner = 1; inner < shnum; ++inner)
1335 : {
1336 4086 : Elf_Scn *scn = elf_getscn (ebl->elf, inner);
1337 : /* This should not happen. */
1338 4086 : if (unlikely (scn == NULL))
1339 0 : error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
1340 : elf_errmsg (-1));
1341 :
1342 : /* Get the section header. */
1343 : GElf_Shdr shdr_mem;
1344 4086 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1345 4086 : if (unlikely (shdr == NULL))
1346 0 : error (EXIT_FAILURE, 0,
1347 0 : gettext ("cannot get section header: %s"),
1348 : elf_errmsg (-1));
1349 :
1350 4086 : if (shdr->sh_size > 0
1351 : /* Compare allocated sections by VMA, unallocated
1352 : sections by file offset. */
1353 8172 : && (shdr->sh_flags & SHF_ALLOC
1354 3036 : ? (shdr->sh_addr >= phdr->p_vaddr
1355 5004 : && (shdr->sh_addr + shdr->sh_size
1356 1968 : <= phdr->p_vaddr + phdr->p_memsz))
1357 1050 : : (shdr->sh_offset >= phdr->p_offset
1358 2100 : && (shdr->sh_offset + shdr->sh_size
1359 1050 : <= phdr->p_offset + phdr->p_filesz))))
1360 : {
1361 474 : if (has_relro && !in_relro
1362 322 : && shdr->sh_addr >= relro_from
1363 70 : && shdr->sh_addr + shdr->sh_size <= relro_to)
1364 : {
1365 46 : fputs_unlocked (" [RELRO:", stdout);
1366 46 : in_relro = true;
1367 : }
1368 428 : else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
1369 : {
1370 12 : fputs_unlocked ("]", stdout);
1371 12 : in_relro = false;
1372 : }
1373 416 : else if (has_relro && in_relro
1374 140 : && shdr->sh_addr + shdr->sh_size > relro_to)
1375 0 : fputs_unlocked ("] <RELRO:", stdout);
1376 416 : else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
1377 : {
1378 212 : if (!in_ro)
1379 : {
1380 12 : fputs_unlocked (" [RO:", stdout);
1381 12 : in_ro = true;
1382 : }
1383 : }
1384 : else
1385 : {
1386 : /* Determine the segment this section is part of. */
1387 : size_t cnt2;
1388 : GElf_Phdr phdr2_mem;
1389 : GElf_Phdr *phdr2 = NULL;
1390 452 : for (cnt2 = 0; cnt2 < phnum; ++cnt2)
1391 : {
1392 656 : phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
1393 :
1394 656 : if (phdr2 != NULL && phdr2->p_type == PT_LOAD
1395 368 : && shdr->sh_addr >= phdr2->p_vaddr
1396 736 : && (shdr->sh_addr + shdr->sh_size
1397 368 : <= phdr2->p_vaddr + phdr2->p_memsz))
1398 : break;
1399 : }
1400 :
1401 204 : if (cnt2 < phnum)
1402 : {
1403 204 : if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
1404 : {
1405 32 : fputs_unlocked (" [RO:", stdout);
1406 32 : in_ro = true;
1407 : }
1408 172 : else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
1409 : {
1410 0 : fputs_unlocked ("]", stdout);
1411 0 : in_ro = false;
1412 : }
1413 : }
1414 : }
1415 :
1416 948 : printf (" %s",
1417 474 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1418 :
1419 : /* Signal that this sectin is only partially covered. */
1420 474 : if (has_relro && in_relro
1421 186 : && shdr->sh_addr + shdr->sh_size > relro_to)
1422 : {
1423 0 : fputs_unlocked (">", stdout);
1424 0 : in_relro = false;
1425 : }
1426 : }
1427 : }
1428 110 : if (in_relro || in_ro)
1429 78 : fputs_unlocked ("]", stdout);
1430 :
1431 : /* Finish the line. */
1432 220 : fputc_unlocked ('\n', stdout);
1433 : }
1434 : }
1435 :
1436 :
1437 : static const char *
1438 : section_name (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr)
1439 : {
1440 266 : return elf_strptr (ebl->elf, ehdr->e_shstrndx, shdr->sh_name) ?: "???";
1441 : }
1442 :
1443 :
1444 : static void
1445 0 : handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1446 : {
1447 : /* Get the data of the section. */
1448 0 : Elf_Data *data = elf_getdata (scn, NULL);
1449 :
1450 0 : Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1451 : GElf_Shdr symshdr_mem;
1452 0 : GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1453 0 : Elf_Data *symdata = elf_getdata (symscn, NULL);
1454 :
1455 0 : if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
1456 0 : || symdata == NULL)
1457 0 : return;
1458 :
1459 : /* Get the section header string table index. */
1460 : size_t shstrndx;
1461 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1462 : error (EXIT_FAILURE, 0,
1463 0 : gettext ("cannot get section header string table index"));
1464 :
1465 0 : Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
1466 :
1467 : GElf_Sym sym_mem;
1468 0 : GElf_Sym *sym = gelf_getsym (symdata, shdr->sh_info, &sym_mem);
1469 :
1470 0 : printf ((grpref[0] & GRP_COMDAT)
1471 0 : ? ngettext ("\
1472 : \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
1473 : "\
1474 : \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1475 : data->d_size / sizeof (Elf32_Word) - 1)
1476 0 : : ngettext ("\
1477 : \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
1478 : \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1479 : data->d_size / sizeof (Elf32_Word) - 1),
1480 : elf_ndxscn (scn),
1481 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1482 : (sym == NULL ? NULL
1483 0 : : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
1484 : ?: gettext ("<INVALID SYMBOL>"),
1485 : data->d_size / sizeof (Elf32_Word) - 1);
1486 :
1487 0 : for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1488 : {
1489 : GElf_Shdr grpshdr_mem;
1490 0 : GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
1491 : &grpshdr_mem);
1492 :
1493 : const char *str;
1494 0 : printf (" [%2u] %s\n",
1495 : grpref[cnt],
1496 : grpshdr != NULL
1497 0 : && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
1498 : ? str : gettext ("<INVALID SECTION>"));
1499 : }
1500 : }
1501 :
1502 :
1503 : static void
1504 32 : print_scngrp (Ebl *ebl)
1505 : {
1506 : /* Find all relocation sections and handle them. */
1507 32 : Elf_Scn *scn = NULL;
1508 :
1509 916 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1510 : {
1511 : /* Handle the section if it is a symbol table. */
1512 : GElf_Shdr shdr_mem;
1513 852 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1514 :
1515 852 : if (shdr != NULL && shdr->sh_type == SHT_GROUP)
1516 : {
1517 0 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1518 : {
1519 0 : if (elf_compress (scn, 0, 0) < 0)
1520 0 : printf ("WARNING: %s [%zd]\n",
1521 : gettext ("Couldn't uncompress section"),
1522 : elf_ndxscn (scn));
1523 0 : shdr = gelf_getshdr (scn, &shdr_mem);
1524 0 : if (unlikely (shdr == NULL))
1525 0 : error (EXIT_FAILURE, 0,
1526 0 : gettext ("cannot get section [%zd] header: %s"),
1527 : elf_ndxscn (scn),
1528 : elf_errmsg (-1));
1529 : }
1530 0 : handle_scngrp (ebl, scn, shdr);
1531 : }
1532 : }
1533 32 : }
1534 :
1535 :
1536 : static const struct flags
1537 : {
1538 : int mask;
1539 : const char *str;
1540 : } dt_flags[] =
1541 : {
1542 : { DF_ORIGIN, "ORIGIN" },
1543 : { DF_SYMBOLIC, "SYMBOLIC" },
1544 : { DF_TEXTREL, "TEXTREL" },
1545 : { DF_BIND_NOW, "BIND_NOW" },
1546 : { DF_STATIC_TLS, "STATIC_TLS" }
1547 : };
1548 : static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
1549 :
1550 : static const struct flags dt_flags_1[] =
1551 : {
1552 : { DF_1_NOW, "NOW" },
1553 : { DF_1_GLOBAL, "GLOBAL" },
1554 : { DF_1_GROUP, "GROUP" },
1555 : { DF_1_NODELETE, "NODELETE" },
1556 : { DF_1_LOADFLTR, "LOADFLTR" },
1557 : { DF_1_INITFIRST, "INITFIRST" },
1558 : { DF_1_NOOPEN, "NOOPEN" },
1559 : { DF_1_ORIGIN, "ORIGIN" },
1560 : { DF_1_DIRECT, "DIRECT" },
1561 : { DF_1_TRANS, "TRANS" },
1562 : { DF_1_INTERPOSE, "INTERPOSE" },
1563 : { DF_1_NODEFLIB, "NODEFLIB" },
1564 : { DF_1_NODUMP, "NODUMP" },
1565 : { DF_1_CONFALT, "CONFALT" },
1566 : { DF_1_ENDFILTEE, "ENDFILTEE" },
1567 : { DF_1_DISPRELDNE, "DISPRELDNE" },
1568 : { DF_1_DISPRELPND, "DISPRELPND" },
1569 : };
1570 : static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
1571 :
1572 : static const struct flags dt_feature_1[] =
1573 : {
1574 : { DTF_1_PARINIT, "PARINIT" },
1575 : { DTF_1_CONFEXP, "CONFEXP" }
1576 : };
1577 : static const int ndt_feature_1 = (sizeof (dt_feature_1)
1578 : / sizeof (dt_feature_1[0]));
1579 :
1580 : static const struct flags dt_posflag_1[] =
1581 : {
1582 : { DF_P1_LAZYLOAD, "LAZYLOAD" },
1583 : { DF_P1_GROUPPERM, "GROUPPERM" }
1584 : };
1585 : static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
1586 : / sizeof (dt_posflag_1[0]));
1587 :
1588 :
1589 : static void
1590 4 : print_flags (int class, GElf_Xword d_val, const struct flags *flags,
1591 : int nflags)
1592 : {
1593 4 : bool first = true;
1594 : int cnt;
1595 :
1596 30 : for (cnt = 0; cnt < nflags; ++cnt)
1597 26 : if (d_val & flags[cnt].mask)
1598 : {
1599 22 : if (!first)
1600 : putchar_unlocked (' ');
1601 22 : fputs_unlocked (flags[cnt].str, stdout);
1602 22 : d_val &= ~flags[cnt].mask;
1603 22 : first = false;
1604 : }
1605 :
1606 4 : if (d_val != 0)
1607 : {
1608 4 : if (!first)
1609 : putchar_unlocked (' ');
1610 4 : printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
1611 : }
1612 :
1613 4 : putchar_unlocked ('\n');
1614 4 : }
1615 :
1616 :
1617 : static void
1618 : print_dt_flags (int class, GElf_Xword d_val)
1619 : {
1620 1 : print_flags (class, d_val, dt_flags, ndt_flags);
1621 : }
1622 :
1623 :
1624 : static void
1625 : print_dt_flags_1 (int class, GElf_Xword d_val)
1626 : {
1627 1 : print_flags (class, d_val, dt_flags_1, ndt_flags_1);
1628 : }
1629 :
1630 :
1631 : static void
1632 : print_dt_feature_1 (int class, GElf_Xword d_val)
1633 : {
1634 1 : print_flags (class, d_val, dt_feature_1, ndt_feature_1);
1635 : }
1636 :
1637 :
1638 : static void
1639 : print_dt_posflag_1 (int class, GElf_Xword d_val)
1640 : {
1641 1 : print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
1642 : }
1643 :
1644 :
1645 : static void
1646 14 : handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1647 : {
1648 14 : int class = gelf_getclass (ebl->elf);
1649 : GElf_Shdr glink_mem;
1650 : GElf_Shdr *glink;
1651 : Elf_Data *data;
1652 : size_t cnt;
1653 : size_t shstrndx;
1654 : size_t sh_entsize;
1655 :
1656 : /* Get the data of the section. */
1657 14 : data = elf_getdata (scn, NULL);
1658 14 : if (data == NULL)
1659 0 : return;
1660 :
1661 : /* Get the section header string table index. */
1662 14 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1663 : error (EXIT_FAILURE, 0,
1664 0 : gettext ("cannot get section header string table index"));
1665 :
1666 14 : sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT);
1667 :
1668 14 : glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
1669 14 : if (glink == NULL)
1670 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
1671 : elf_ndxscn (scn));
1672 :
1673 56 : printf (ngettext ("\
1674 : \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1675 : "\
1676 : \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1677 : shdr->sh_size / sh_entsize),
1678 14 : (unsigned long int) (shdr->sh_size / sh_entsize),
1679 : class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
1680 : shdr->sh_offset,
1681 14 : (int) shdr->sh_link,
1682 14 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
1683 14 : fputs_unlocked (gettext (" Type Value\n"), stdout);
1684 :
1685 511 : for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
1686 : {
1687 : GElf_Dyn dynmem;
1688 497 : GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
1689 497 : if (dyn == NULL)
1690 : break;
1691 :
1692 : char buf[64];
1693 994 : printf (" %-17s ",
1694 : ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
1695 :
1696 497 : switch (dyn->d_tag)
1697 : {
1698 : case DT_NULL:
1699 : case DT_DEBUG:
1700 : case DT_BIND_NOW:
1701 : case DT_TEXTREL:
1702 : /* No further output. */
1703 86 : fputc_unlocked ('\n', stdout);
1704 : break;
1705 :
1706 : case DT_NEEDED:
1707 126 : printf (gettext ("Shared library: [%s]\n"),
1708 63 : elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1709 : break;
1710 :
1711 : case DT_SONAME:
1712 6 : printf (gettext ("Library soname: [%s]\n"),
1713 3 : elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1714 : break;
1715 :
1716 : case DT_RPATH:
1717 2 : printf (gettext ("Library rpath: [%s]\n"),
1718 1 : elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1719 : break;
1720 :
1721 : case DT_RUNPATH:
1722 4 : printf (gettext ("Library runpath: [%s]\n"),
1723 2 : elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1724 : break;
1725 :
1726 : case DT_PLTRELSZ:
1727 : case DT_RELASZ:
1728 : case DT_STRSZ:
1729 : case DT_RELSZ:
1730 : case DT_RELAENT:
1731 : case DT_SYMENT:
1732 : case DT_RELENT:
1733 : case DT_PLTPADSZ:
1734 : case DT_MOVEENT:
1735 : case DT_MOVESZ:
1736 : case DT_INIT_ARRAYSZ:
1737 : case DT_FINI_ARRAYSZ:
1738 : case DT_SYMINSZ:
1739 : case DT_SYMINENT:
1740 : case DT_GNU_CONFLICTSZ:
1741 : case DT_GNU_LIBLISTSZ:
1742 105 : printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
1743 : break;
1744 :
1745 : case DT_VERDEFNUM:
1746 : case DT_VERNEEDNUM:
1747 : case DT_RELACOUNT:
1748 : case DT_RELCOUNT:
1749 27 : printf ("%" PRId64 "\n", dyn->d_un.d_val);
1750 : break;
1751 :
1752 : case DT_PLTREL:;
1753 14 : const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
1754 : NULL, 0);
1755 14 : puts (tagname ?: "???");
1756 14 : break;
1757 :
1758 : case DT_FLAGS:
1759 1 : print_dt_flags (class, dyn->d_un.d_val);
1760 : break;
1761 :
1762 : case DT_FLAGS_1:
1763 1 : print_dt_flags_1 (class, dyn->d_un.d_val);
1764 : break;
1765 :
1766 : case DT_FEATURE_1:
1767 1 : print_dt_feature_1 (class, dyn->d_un.d_val);
1768 : break;
1769 :
1770 : case DT_POSFLAG_1:
1771 1 : print_dt_posflag_1 (class, dyn->d_un.d_val);
1772 : break;
1773 :
1774 : default:
1775 192 : printf ("%#0*" PRIx64 "\n",
1776 : class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
1777 : break;
1778 : }
1779 : }
1780 : }
1781 :
1782 :
1783 : /* Print the dynamic segment. */
1784 : static void
1785 34 : print_dynamic (Ebl *ebl)
1786 : {
1787 78 : for (size_t i = 0; i < phnum; ++i)
1788 : {
1789 : GElf_Phdr phdr_mem;
1790 58 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
1791 :
1792 58 : if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
1793 : {
1794 14 : Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
1795 : GElf_Shdr shdr_mem;
1796 14 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1797 14 : if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
1798 14 : handle_dynamic (ebl, scn, shdr);
1799 : break;
1800 : }
1801 : }
1802 34 : }
1803 :
1804 :
1805 : /* Print relocations. */
1806 : static void
1807 33 : print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
1808 : {
1809 : /* Find all relocation sections and handle them. */
1810 33 : Elf_Scn *scn = NULL;
1811 :
1812 952 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1813 : {
1814 : /* Handle the section if it is a symbol table. */
1815 : GElf_Shdr shdr_mem;
1816 886 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1817 :
1818 886 : if (likely (shdr != NULL))
1819 : {
1820 886 : if (shdr->sh_type == SHT_REL)
1821 8 : handle_relocs_rel (ebl, ehdr, scn, shdr);
1822 878 : else if (shdr->sh_type == SHT_RELA)
1823 123 : handle_relocs_rela (ebl, ehdr, scn, shdr);
1824 : }
1825 : }
1826 33 : }
1827 :
1828 :
1829 : /* Handle a relocation section. */
1830 : static void
1831 8 : handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1832 : {
1833 8 : int class = gelf_getclass (ebl->elf);
1834 8 : size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
1835 8 : int nentries = shdr->sh_size / sh_entsize;
1836 :
1837 : /* Get the data of the section. */
1838 8 : Elf_Data *data = elf_getdata (scn, NULL);
1839 8 : if (data == NULL)
1840 0 : return;
1841 :
1842 : /* Get the symbol table information. */
1843 8 : Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1844 : GElf_Shdr symshdr_mem;
1845 8 : GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1846 8 : Elf_Data *symdata = elf_getdata (symscn, NULL);
1847 :
1848 : /* Get the section header of the section the relocations are for. */
1849 : GElf_Shdr destshdr_mem;
1850 8 : GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1851 : &destshdr_mem);
1852 :
1853 8 : if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
1854 : {
1855 0 : printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1856 : shdr->sh_offset);
1857 : return;
1858 : }
1859 :
1860 : /* Search for the optional extended section index table. */
1861 8 : Elf_Data *xndxdata = NULL;
1862 8 : int xndxscnidx = elf_scnshndx (scn);
1863 8 : if (unlikely (xndxscnidx > 0))
1864 0 : xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
1865 :
1866 : /* Get the section header string table index. */
1867 : size_t shstrndx;
1868 8 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1869 : error (EXIT_FAILURE, 0,
1870 0 : gettext ("cannot get section header string table index"));
1871 :
1872 8 : if (shdr->sh_info != 0)
1873 24 : printf (ngettext ("\
1874 : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1875 : "\
1876 : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1877 : nentries),
1878 : elf_ndxscn (scn),
1879 8 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1880 8 : (unsigned int) shdr->sh_info,
1881 8 : elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1882 : shdr->sh_offset,
1883 : nentries);
1884 : else
1885 : /* The .rel.dyn section does not refer to a specific section but
1886 : instead of section index zero. Do not try to print a section
1887 : name. */
1888 0 : printf (ngettext ("\
1889 : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1890 : "\
1891 : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1892 : nentries),
1893 0 : (unsigned int) elf_ndxscn (scn),
1894 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1895 : shdr->sh_offset,
1896 : nentries);
1897 8 : fputs_unlocked (class == ELFCLASS32
1898 : ? gettext ("\
1899 : Offset Type Value Name\n")
1900 : : gettext ("\
1901 : Offset Type Value Name\n"),
1902 : stdout);
1903 :
1904 8 : int is_statically_linked = 0;
1905 33 : for (int cnt = 0; cnt < nentries; ++cnt)
1906 : {
1907 : GElf_Rel relmem;
1908 25 : GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
1909 25 : if (likely (rel != NULL))
1910 : {
1911 : char buf[128];
1912 : GElf_Sym symmem;
1913 : Elf32_Word xndx;
1914 25 : GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1915 25 : GELF_R_SYM (rel->r_info),
1916 : &symmem, &xndx);
1917 25 : if (unlikely (sym == NULL))
1918 : {
1919 : /* As a special case we have to handle relocations in static
1920 : executables. This only happens for IRELATIVE relocations
1921 : (so far). There is no symbol table. */
1922 0 : if (is_statically_linked == 0)
1923 : {
1924 : /* Find the program header and look for a PT_INTERP entry. */
1925 0 : is_statically_linked = -1;
1926 0 : if (ehdr->e_type == ET_EXEC)
1927 : {
1928 : is_statically_linked = 1;
1929 :
1930 0 : for (size_t inner = 0; inner < phnum; ++inner)
1931 : {
1932 : GElf_Phdr phdr_mem;
1933 0 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
1934 : &phdr_mem);
1935 0 : if (phdr != NULL && phdr->p_type == PT_INTERP)
1936 : {
1937 0 : is_statically_linked = -1;
1938 0 : break;
1939 : }
1940 : }
1941 : }
1942 : }
1943 :
1944 0 : if (is_statically_linked > 0 && shdr->sh_link == 0)
1945 0 : printf ("\
1946 : %#0*" PRIx64 " %-20s %*s %s\n",
1947 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1948 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1949 : /* Avoid the leading R_ which isn't carrying any
1950 : information. */
1951 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1952 : buf, sizeof (buf)) + 2
1953 : : gettext ("<INVALID RELOC>"),
1954 : class == ELFCLASS32 ? 10 : 18, "",
1955 0 : elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1956 : else
1957 0 : printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
1958 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1959 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1960 : /* Avoid the leading R_ which isn't carrying any
1961 : information. */
1962 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1963 : buf, sizeof (buf)) + 2
1964 : : gettext ("<INVALID RELOC>"),
1965 : gettext ("INVALID SYMBOL"),
1966 0 : (long int) GELF_R_SYM (rel->r_info));
1967 : }
1968 25 : else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1969 68 : printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
1970 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1971 17 : likely (ebl_reloc_type_check (ebl,
1972 : GELF_R_TYPE (rel->r_info)))
1973 : /* Avoid the leading R_ which isn't carrying any
1974 : information. */
1975 17 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1976 : buf, sizeof (buf)) + 2
1977 : : gettext ("<INVALID RELOC>"),
1978 : class == ELFCLASS32 ? 10 : 18, sym->st_value,
1979 34 : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1980 : else
1981 : {
1982 : /* This is a relocation against a STT_SECTION symbol. */
1983 : GElf_Shdr secshdr_mem;
1984 : GElf_Shdr *secshdr;
1985 8 : secshdr = gelf_getshdr (elf_getscn (ebl->elf,
1986 8 : sym->st_shndx == SHN_XINDEX
1987 0 : ? xndx : sym->st_shndx),
1988 : &secshdr_mem);
1989 :
1990 8 : if (unlikely (secshdr == NULL))
1991 0 : printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
1992 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1993 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1994 : /* Avoid the leading R_ which isn't carrying any
1995 : information. */
1996 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1997 : buf, sizeof (buf)) + 2
1998 : : gettext ("<INVALID RELOC>"),
1999 : gettext ("INVALID SECTION"),
2000 0 : (long int) (sym->st_shndx == SHN_XINDEX
2001 0 : ? xndx : sym->st_shndx));
2002 : else
2003 24 : printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
2004 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2005 8 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2006 : /* Avoid the leading R_ which isn't carrying any
2007 : information. */
2008 8 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2009 : buf, sizeof (buf)) + 2
2010 : : gettext ("<INVALID RELOC>"),
2011 : class == ELFCLASS32 ? 10 : 18, sym->st_value,
2012 8 : elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
2013 : }
2014 : }
2015 : }
2016 : }
2017 :
2018 :
2019 : /* Handle a relocation section. */
2020 : static void
2021 123 : handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
2022 : {
2023 123 : int class = gelf_getclass (ebl->elf);
2024 123 : size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
2025 123 : int nentries = shdr->sh_size / sh_entsize;
2026 :
2027 : /* Get the data of the section. */
2028 123 : Elf_Data *data = elf_getdata (scn, NULL);
2029 123 : if (data == NULL)
2030 0 : return;
2031 :
2032 : /* Get the symbol table information. */
2033 123 : Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2034 : GElf_Shdr symshdr_mem;
2035 123 : GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2036 123 : Elf_Data *symdata = elf_getdata (symscn, NULL);
2037 :
2038 : /* Get the section header of the section the relocations are for. */
2039 : GElf_Shdr destshdr_mem;
2040 123 : GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
2041 : &destshdr_mem);
2042 :
2043 123 : if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
2044 : {
2045 0 : printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
2046 : shdr->sh_offset);
2047 : return;
2048 : }
2049 :
2050 : /* Search for the optional extended section index table. */
2051 123 : Elf_Data *xndxdata = NULL;
2052 123 : int xndxscnidx = elf_scnshndx (scn);
2053 123 : if (unlikely (xndxscnidx > 0))
2054 0 : xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
2055 :
2056 : /* Get the section header string table index. */
2057 : size_t shstrndx;
2058 123 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2059 : error (EXIT_FAILURE, 0,
2060 0 : gettext ("cannot get section header string table index"));
2061 :
2062 123 : if (shdr->sh_info != 0)
2063 333 : printf (ngettext ("\
2064 : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2065 : "\
2066 : \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2067 : nentries),
2068 : elf_ndxscn (scn),
2069 111 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2070 111 : (unsigned int) shdr->sh_info,
2071 111 : elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
2072 : shdr->sh_offset,
2073 : nentries);
2074 : else
2075 : /* The .rela.dyn section does not refer to a specific section but
2076 : instead of section index zero. Do not try to print a section
2077 : name. */
2078 36 : printf (ngettext ("\
2079 : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2080 : "\
2081 : \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2082 : nentries),
2083 12 : (unsigned int) elf_ndxscn (scn),
2084 12 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2085 : shdr->sh_offset,
2086 : nentries);
2087 123 : fputs_unlocked (class == ELFCLASS32
2088 : ? gettext ("\
2089 : Offset Type Value Addend Name\n")
2090 : : gettext ("\
2091 : Offset Type Value Addend Name\n"),
2092 : stdout);
2093 :
2094 123 : int is_statically_linked = 0;
2095 20949 : for (int cnt = 0; cnt < nentries; ++cnt)
2096 : {
2097 : GElf_Rela relmem;
2098 20826 : GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
2099 20826 : if (likely (rel != NULL))
2100 : {
2101 : char buf[64];
2102 : GElf_Sym symmem;
2103 : Elf32_Word xndx;
2104 20826 : GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
2105 20826 : GELF_R_SYM (rel->r_info),
2106 : &symmem, &xndx);
2107 :
2108 20826 : if (unlikely (sym == NULL))
2109 : {
2110 : /* As a special case we have to handle relocations in static
2111 : executables. This only happens for IRELATIVE relocations
2112 : (so far). There is no symbol table. */
2113 0 : if (is_statically_linked == 0)
2114 : {
2115 : /* Find the program header and look for a PT_INTERP entry. */
2116 0 : is_statically_linked = -1;
2117 0 : if (ehdr->e_type == ET_EXEC)
2118 : {
2119 : is_statically_linked = 1;
2120 :
2121 0 : for (size_t inner = 0; inner < phnum; ++inner)
2122 : {
2123 : GElf_Phdr phdr_mem;
2124 0 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
2125 : &phdr_mem);
2126 0 : if (phdr != NULL && phdr->p_type == PT_INTERP)
2127 : {
2128 0 : is_statically_linked = -1;
2129 0 : break;
2130 : }
2131 : }
2132 : }
2133 : }
2134 :
2135 0 : if (is_statically_linked > 0 && shdr->sh_link == 0)
2136 0 : printf ("\
2137 : %#0*" PRIx64 " %-15s %*s %#6" PRIx64 " %s\n",
2138 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2139 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2140 : /* Avoid the leading R_ which isn't carrying any
2141 : information. */
2142 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2143 : buf, sizeof (buf)) + 2
2144 : : gettext ("<INVALID RELOC>"),
2145 : class == ELFCLASS32 ? 10 : 18, "",
2146 : rel->r_addend,
2147 0 : elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
2148 : else
2149 0 : printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
2150 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2151 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2152 : /* Avoid the leading R_ which isn't carrying any
2153 : information. */
2154 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2155 : buf, sizeof (buf)) + 2
2156 : : gettext ("<INVALID RELOC>"),
2157 : gettext ("INVALID SYMBOL"),
2158 0 : (long int) GELF_R_SYM (rel->r_info));
2159 : }
2160 20826 : else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
2161 22244 : printf ("\
2162 : %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
2163 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2164 5561 : likely (ebl_reloc_type_check (ebl,
2165 : GELF_R_TYPE (rel->r_info)))
2166 : /* Avoid the leading R_ which isn't carrying any
2167 : information. */
2168 5561 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2169 : buf, sizeof (buf)) + 2
2170 : : gettext ("<INVALID RELOC>"),
2171 : class == ELFCLASS32 ? 10 : 18, sym->st_value,
2172 : rel->r_addend,
2173 11122 : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
2174 : else
2175 : {
2176 : /* This is a relocation against a STT_SECTION symbol. */
2177 : GElf_Shdr secshdr_mem;
2178 : GElf_Shdr *secshdr;
2179 15265 : secshdr = gelf_getshdr (elf_getscn (ebl->elf,
2180 15265 : sym->st_shndx == SHN_XINDEX
2181 0 : ? xndx : sym->st_shndx),
2182 : &secshdr_mem);
2183 :
2184 15265 : if (unlikely (secshdr == NULL))
2185 0 : printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
2186 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2187 0 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2188 : /* Avoid the leading R_ which isn't carrying any
2189 : information. */
2190 0 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2191 : buf, sizeof (buf)) + 2
2192 : : gettext ("<INVALID RELOC>"),
2193 : gettext ("INVALID SECTION"),
2194 0 : (long int) (sym->st_shndx == SHN_XINDEX
2195 0 : ? xndx : sym->st_shndx));
2196 : else
2197 45795 : printf ("\
2198 : %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
2199 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2200 15265 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2201 : /* Avoid the leading R_ which isn't carrying any
2202 : information. */
2203 15265 : ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2204 : buf, sizeof (buf)) + 2
2205 : : gettext ("<INVALID RELOC>"),
2206 : class == ELFCLASS32 ? 10 : 18, sym->st_value,
2207 : rel->r_addend,
2208 15265 : elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
2209 : }
2210 : }
2211 : }
2212 : }
2213 :
2214 :
2215 : /* Print the program header. */
2216 : static void
2217 92 : print_symtab (Ebl *ebl, int type)
2218 : {
2219 : /* Find the symbol table(s). For this we have to search through the
2220 : section table. */
2221 92 : Elf_Scn *scn = NULL;
2222 :
2223 2646 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2224 : {
2225 : /* Handle the section if it is a symbol table. */
2226 : GElf_Shdr shdr_mem;
2227 2462 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2228 :
2229 2462 : if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
2230 : {
2231 58 : if (symbol_table_section != NULL)
2232 : {
2233 : /* Get the section header string table index. */
2234 : size_t shstrndx;
2235 : const char *sname;
2236 4 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2237 : error (EXIT_FAILURE, 0,
2238 0 : gettext ("cannot get section header string table index"));
2239 4 : sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
2240 4 : if (sname == NULL || strcmp (sname, symbol_table_section) != 0)
2241 2 : continue;
2242 : }
2243 :
2244 56 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
2245 : {
2246 0 : if (elf_compress (scn, 0, 0) < 0)
2247 0 : printf ("WARNING: %s [%zd]\n",
2248 : gettext ("Couldn't uncompress section"),
2249 : elf_ndxscn (scn));
2250 0 : shdr = gelf_getshdr (scn, &shdr_mem);
2251 0 : if (unlikely (shdr == NULL))
2252 0 : error (EXIT_FAILURE, 0,
2253 0 : gettext ("cannot get section [%zd] header: %s"),
2254 : elf_ndxscn (scn), elf_errmsg (-1));
2255 : }
2256 56 : handle_symtab (ebl, scn, shdr);
2257 : }
2258 : }
2259 92 : }
2260 :
2261 :
2262 : static void
2263 56 : handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2264 : {
2265 56 : Elf_Data *versym_data = NULL;
2266 56 : Elf_Data *verneed_data = NULL;
2267 56 : Elf_Data *verdef_data = NULL;
2268 56 : Elf_Data *xndx_data = NULL;
2269 56 : int class = gelf_getclass (ebl->elf);
2270 56 : Elf32_Word verneed_stridx = 0;
2271 56 : Elf32_Word verdef_stridx = 0;
2272 :
2273 : /* Get the data of the section. */
2274 56 : Elf_Data *data = elf_getdata (scn, NULL);
2275 56 : if (data == NULL)
2276 0 : return;
2277 :
2278 : /* Find out whether we have other sections we might need. */
2279 : Elf_Scn *runscn = NULL;
2280 1699 : while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
2281 : {
2282 : GElf_Shdr runshdr_mem;
2283 1643 : GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
2284 :
2285 1643 : if (likely (runshdr != NULL))
2286 : {
2287 1643 : if (runshdr->sh_type == SHT_GNU_versym
2288 31 : && runshdr->sh_link == elf_ndxscn (scn))
2289 : /* Bingo, found the version information. Now get the data. */
2290 19 : versym_data = elf_getdata (runscn, NULL);
2291 1624 : else if (runshdr->sh_type == SHT_GNU_verneed)
2292 : {
2293 : /* This is the information about the needed versions. */
2294 31 : verneed_data = elf_getdata (runscn, NULL);
2295 31 : verneed_stridx = runshdr->sh_link;
2296 : }
2297 1593 : else if (runshdr->sh_type == SHT_GNU_verdef)
2298 : {
2299 : /* This is the information about the defined versions. */
2300 8 : verdef_data = elf_getdata (runscn, NULL);
2301 8 : verdef_stridx = runshdr->sh_link;
2302 : }
2303 1585 : else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
2304 0 : && runshdr->sh_link == elf_ndxscn (scn))
2305 : /* Extended section index. */
2306 0 : xndx_data = elf_getdata (runscn, NULL);
2307 : }
2308 : }
2309 :
2310 : /* Get the section header string table index. */
2311 : size_t shstrndx;
2312 56 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2313 : error (EXIT_FAILURE, 0,
2314 0 : gettext ("cannot get section header string table index"));
2315 :
2316 : GElf_Shdr glink_mem;
2317 56 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2318 : &glink_mem);
2319 56 : if (glink == NULL)
2320 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
2321 : elf_ndxscn (scn));
2322 :
2323 : /* Now we can compute the number of entries in the section. */
2324 112 : unsigned int nsyms = data->d_size / (class == ELFCLASS32
2325 : ? sizeof (Elf32_Sym)
2326 56 : : sizeof (Elf64_Sym));
2327 :
2328 168 : printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
2329 : "\nSymbol table [%2u] '%s' contains %u entries:\n",
2330 : nsyms),
2331 56 : (unsigned int) elf_ndxscn (scn),
2332 56 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
2333 168 : printf (ngettext (" %lu local symbol String table: [%2u] '%s'\n",
2334 : " %lu local symbols String table: [%2u] '%s'\n",
2335 : shdr->sh_info),
2336 56 : (unsigned long int) shdr->sh_info,
2337 56 : (unsigned int) shdr->sh_link,
2338 56 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
2339 :
2340 56 : fputs_unlocked (class == ELFCLASS32
2341 : ? gettext ("\
2342 : Num: Value Size Type Bind Vis Ndx Name\n")
2343 : : gettext ("\
2344 : Num: Value Size Type Bind Vis Ndx Name\n"),
2345 : stdout);
2346 :
2347 16343 : for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
2348 : {
2349 : char typebuf[64];
2350 : char bindbuf[64];
2351 : char scnbuf[64];
2352 : Elf32_Word xndx;
2353 : GElf_Sym sym_mem;
2354 16287 : GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
2355 :
2356 16287 : if (unlikely (sym == NULL))
2357 0 : continue;
2358 :
2359 : /* Determine the real section index. */
2360 16287 : if (likely (sym->st_shndx != SHN_XINDEX))
2361 16287 : xndx = sym->st_shndx;
2362 :
2363 114009 : printf (gettext ("\
2364 : %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
2365 : cnt,
2366 : class == ELFCLASS32 ? 8 : 16,
2367 : sym->st_value,
2368 : sym->st_size,
2369 16287 : ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
2370 : typebuf, sizeof (typebuf)),
2371 16287 : ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
2372 : bindbuf, sizeof (bindbuf)),
2373 16287 : get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
2374 16287 : ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
2375 : sizeof (scnbuf), NULL, shnum),
2376 32574 : elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
2377 :
2378 16287 : if (versym_data != NULL)
2379 : {
2380 : /* Get the version information. */
2381 : GElf_Versym versym_mem;
2382 1590 : GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
2383 :
2384 1590 : if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
2385 : {
2386 1316 : bool is_nobits = false;
2387 1316 : bool check_def = xndx != SHN_UNDEF;
2388 :
2389 1316 : if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
2390 : {
2391 : GElf_Shdr symshdr_mem;
2392 1284 : GElf_Shdr *symshdr =
2393 1284 : gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
2394 :
2395 1284 : is_nobits = (symshdr != NULL
2396 1284 : && symshdr->sh_type == SHT_NOBITS);
2397 : }
2398 :
2399 1316 : if (is_nobits || ! check_def)
2400 : {
2401 : /* We must test both. */
2402 : GElf_Vernaux vernaux_mem;
2403 952 : GElf_Vernaux *vernaux = NULL;
2404 952 : size_t vn_offset = 0;
2405 :
2406 : GElf_Verneed verneed_mem;
2407 952 : GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
2408 : &verneed_mem);
2409 4836 : while (verneed != NULL)
2410 : {
2411 3884 : size_t vna_offset = vn_offset;
2412 :
2413 3884 : vernaux = gelf_getvernaux (verneed_data,
2414 3884 : vna_offset += verneed->vn_aux,
2415 : &vernaux_mem);
2416 11161 : while (vernaux != NULL
2417 7277 : && vernaux->vna_other != *versym
2418 6325 : && vernaux->vna_next != 0)
2419 : {
2420 : /* Update the offset. */
2421 3393 : vna_offset += vernaux->vna_next;
2422 :
2423 3393 : vernaux = (vernaux->vna_next == 0
2424 : ? NULL
2425 3393 : : gelf_getvernaux (verneed_data,
2426 : vna_offset,
2427 : &vernaux_mem));
2428 : }
2429 :
2430 : /* Check whether we found the version. */
2431 3884 : if (vernaux != NULL && vernaux->vna_other == *versym)
2432 : /* Found it. */
2433 : break;
2434 :
2435 2932 : vn_offset += verneed->vn_next;
2436 : verneed = (verneed->vn_next == 0
2437 : ? NULL
2438 2932 : : gelf_getverneed (verneed_data, vn_offset,
2439 : &verneed_mem));
2440 : }
2441 :
2442 952 : if (vernaux != NULL && vernaux->vna_other == *versym)
2443 : {
2444 2856 : printf ("@%s (%u)",
2445 : elf_strptr (ebl->elf, verneed_stridx,
2446 952 : vernaux->vna_name),
2447 : (unsigned int) vernaux->vna_other);
2448 952 : check_def = 0;
2449 : }
2450 0 : else if (unlikely (! is_nobits))
2451 0 : error (0, 0, gettext ("bad dynamic symbol"));
2452 : else
2453 : check_def = 1;
2454 : }
2455 :
2456 1316 : if (check_def && *versym != 0x8001)
2457 : {
2458 : /* We must test both. */
2459 364 : size_t vd_offset = 0;
2460 :
2461 : GElf_Verdef verdef_mem;
2462 364 : GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
2463 : &verdef_mem);
2464 2545 : while (verdef != NULL)
2465 : {
2466 2181 : if (verdef->vd_ndx == (*versym & 0x7fff))
2467 : /* Found the definition. */
2468 : break;
2469 :
2470 1817 : vd_offset += verdef->vd_next;
2471 : verdef = (verdef->vd_next == 0
2472 : ? NULL
2473 1817 : : gelf_getverdef (verdef_data, vd_offset,
2474 : &verdef_mem));
2475 : }
2476 :
2477 364 : if (verdef != NULL)
2478 : {
2479 : GElf_Verdaux verdaux_mem;
2480 364 : GElf_Verdaux *verdaux
2481 364 : = gelf_getverdaux (verdef_data,
2482 364 : vd_offset + verdef->vd_aux,
2483 : &verdaux_mem);
2484 :
2485 364 : if (verdaux != NULL)
2486 364 : printf ((*versym & 0x8000) ? "@%s" : "@@%s",
2487 : elf_strptr (ebl->elf, verdef_stridx,
2488 364 : verdaux->vda_name));
2489 : }
2490 : }
2491 : }
2492 : }
2493 :
2494 16287 : putchar_unlocked ('\n');
2495 : }
2496 : }
2497 :
2498 :
2499 : /* Print version information. */
2500 : static void
2501 32 : print_verinfo (Ebl *ebl)
2502 : {
2503 : /* Find the version information sections. For this we have to
2504 : search through the section table. */
2505 32 : Elf_Scn *scn = NULL;
2506 :
2507 916 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2508 : {
2509 : /* Handle the section if it is part of the versioning handling. */
2510 : GElf_Shdr shdr_mem;
2511 852 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2512 :
2513 852 : if (likely (shdr != NULL))
2514 : {
2515 852 : if (shdr->sh_type == SHT_GNU_verneed)
2516 12 : handle_verneed (ebl, scn, shdr);
2517 840 : else if (shdr->sh_type == SHT_GNU_verdef)
2518 4 : handle_verdef (ebl, scn, shdr);
2519 836 : else if (shdr->sh_type == SHT_GNU_versym)
2520 12 : handle_versym (ebl, scn, shdr);
2521 : }
2522 : }
2523 32 : }
2524 :
2525 :
2526 : static const char *
2527 131 : get_ver_flags (unsigned int flags)
2528 : {
2529 : static char buf[32];
2530 : char *endp;
2531 :
2532 131 : if (flags == 0)
2533 126 : return gettext ("none");
2534 :
2535 5 : if (flags & VER_FLG_BASE)
2536 4 : endp = stpcpy (buf, "BASE ");
2537 : else
2538 : endp = buf;
2539 :
2540 5 : if (flags & VER_FLG_WEAK)
2541 : {
2542 1 : if (endp != buf)
2543 0 : endp = stpcpy (endp, "| ");
2544 :
2545 1 : endp = stpcpy (endp, "WEAK ");
2546 : }
2547 :
2548 5 : if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
2549 : {
2550 0 : strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
2551 0 : buf[sizeof (buf) - 1] = '\0';
2552 : }
2553 :
2554 : return buf;
2555 : }
2556 :
2557 :
2558 : static void
2559 12 : handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2560 : {
2561 12 : int class = gelf_getclass (ebl->elf);
2562 :
2563 : /* Get the data of the section. */
2564 12 : Elf_Data *data = elf_getdata (scn, NULL);
2565 12 : if (data == NULL)
2566 0 : return;
2567 :
2568 : /* Get the section header string table index. */
2569 : size_t shstrndx;
2570 12 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2571 : error (EXIT_FAILURE, 0,
2572 0 : gettext ("cannot get section header string table index"));
2573 :
2574 : GElf_Shdr glink_mem;
2575 12 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2576 : &glink_mem);
2577 12 : if (glink == NULL)
2578 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
2579 : elf_ndxscn (scn));
2580 :
2581 60 : printf (ngettext ("\
2582 : \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2583 : "\
2584 : \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2585 : shdr->sh_info),
2586 12 : (unsigned int) elf_ndxscn (scn),
2587 12 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
2588 : class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2589 : shdr->sh_offset,
2590 12 : (unsigned int) shdr->sh_link,
2591 12 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
2592 :
2593 12 : unsigned int offset = 0;
2594 58 : for (int cnt = shdr->sh_info; --cnt >= 0; )
2595 : {
2596 : /* Get the data at the next offset. */
2597 : GElf_Verneed needmem;
2598 46 : GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
2599 46 : if (unlikely (need == NULL))
2600 : break;
2601 :
2602 230 : printf (gettext (" %#06x: Version: %hu File: %s Cnt: %hu\n"),
2603 46 : offset, (unsigned short int) need->vn_version,
2604 92 : elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
2605 46 : (unsigned short int) need->vn_cnt);
2606 :
2607 46 : unsigned int auxoffset = offset + need->vn_aux;
2608 141 : for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2609 : {
2610 : GElf_Vernaux auxmem;
2611 95 : GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
2612 95 : if (unlikely (aux == NULL))
2613 : break;
2614 :
2615 475 : printf (gettext (" %#06x: Name: %s Flags: %s Version: %hu\n"),
2616 : auxoffset,
2617 190 : elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
2618 95 : get_ver_flags (aux->vna_flags),
2619 95 : (unsigned short int) aux->vna_other);
2620 :
2621 95 : if (aux->vna_next == 0)
2622 : break;
2623 :
2624 49 : auxoffset += aux->vna_next;
2625 : }
2626 :
2627 : /* Find the next offset. */
2628 46 : if (need->vn_next == 0)
2629 : break;
2630 :
2631 34 : offset += need->vn_next;
2632 : }
2633 : }
2634 :
2635 :
2636 : static void
2637 4 : handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2638 : {
2639 : /* Get the data of the section. */
2640 4 : Elf_Data *data = elf_getdata (scn, NULL);
2641 4 : if (data == NULL)
2642 0 : return;
2643 :
2644 : /* Get the section header string table index. */
2645 : size_t shstrndx;
2646 4 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2647 : error (EXIT_FAILURE, 0,
2648 0 : gettext ("cannot get section header string table index"));
2649 :
2650 : GElf_Shdr glink_mem;
2651 4 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2652 : &glink_mem);
2653 4 : if (glink == NULL)
2654 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
2655 : elf_ndxscn (scn));
2656 :
2657 4 : int class = gelf_getclass (ebl->elf);
2658 20 : printf (ngettext ("\
2659 : \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2660 : "\
2661 : \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2662 : shdr->sh_info),
2663 4 : (unsigned int) elf_ndxscn (scn),
2664 4 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2665 : shdr->sh_info,
2666 : class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2667 : shdr->sh_offset,
2668 4 : (unsigned int) shdr->sh_link,
2669 4 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
2670 :
2671 4 : unsigned int offset = 0;
2672 40 : for (int cnt = shdr->sh_info; --cnt >= 0; )
2673 : {
2674 : /* Get the data at the next offset. */
2675 : GElf_Verdef defmem;
2676 36 : GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
2677 36 : if (unlikely (def == NULL))
2678 : break;
2679 :
2680 36 : unsigned int auxoffset = offset + def->vd_aux;
2681 : GElf_Verdaux auxmem;
2682 36 : GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
2683 36 : if (unlikely (aux == NULL))
2684 : break;
2685 :
2686 252 : printf (gettext ("\
2687 : %#06x: Version: %hd Flags: %s Index: %hd Cnt: %hd Name: %s\n"),
2688 36 : offset, def->vd_version,
2689 36 : get_ver_flags (def->vd_flags),
2690 36 : def->vd_ndx,
2691 36 : def->vd_cnt,
2692 72 : elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2693 :
2694 36 : auxoffset += aux->vda_next;
2695 36 : for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
2696 : {
2697 28 : aux = gelf_getverdaux (data, auxoffset, &auxmem);
2698 28 : if (unlikely (aux == NULL))
2699 : break;
2700 :
2701 84 : printf (gettext (" %#06x: Parent %d: %s\n"),
2702 : auxoffset, cnt2,
2703 56 : elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2704 :
2705 28 : if (aux->vda_next == 0)
2706 : break;
2707 :
2708 0 : auxoffset += aux->vda_next;
2709 : }
2710 :
2711 : /* Find the next offset. */
2712 36 : if (def->vd_next == 0)
2713 : break;
2714 32 : offset += def->vd_next;
2715 : }
2716 : }
2717 :
2718 :
2719 : static void
2720 12 : handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2721 : {
2722 12 : int class = gelf_getclass (ebl->elf);
2723 : const char **vername;
2724 : const char **filename;
2725 :
2726 : /* Get the data of the section. */
2727 12 : Elf_Data *data = elf_getdata (scn, NULL);
2728 12 : if (data == NULL)
2729 0 : return;
2730 :
2731 : /* Get the section header string table index. */
2732 : size_t shstrndx;
2733 12 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2734 : error (EXIT_FAILURE, 0,
2735 0 : gettext ("cannot get section header string table index"));
2736 :
2737 : /* We have to find the version definition section and extract the
2738 : version names. */
2739 : Elf_Scn *defscn = NULL;
2740 : Elf_Scn *needscn = NULL;
2741 :
2742 : Elf_Scn *verscn = NULL;
2743 458 : while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
2744 : {
2745 : GElf_Shdr vershdr_mem;
2746 446 : GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
2747 :
2748 446 : if (likely (vershdr != NULL))
2749 : {
2750 446 : if (vershdr->sh_type == SHT_GNU_verdef)
2751 : defscn = verscn;
2752 442 : else if (vershdr->sh_type == SHT_GNU_verneed)
2753 12 : needscn = verscn;
2754 : }
2755 : }
2756 :
2757 : size_t nvername;
2758 12 : if (defscn != NULL || needscn != NULL)
2759 : {
2760 : /* We have a version information (better should have). Now get
2761 : the version names. First find the maximum version number. */
2762 12 : nvername = 0;
2763 12 : if (defscn != NULL)
2764 : {
2765 : /* Run through the version definitions and find the highest
2766 : index. */
2767 4 : unsigned int offset = 0;
2768 : Elf_Data *defdata;
2769 : GElf_Shdr defshdrmem;
2770 : GElf_Shdr *defshdr;
2771 :
2772 4 : defdata = elf_getdata (defscn, NULL);
2773 4 : if (unlikely (defdata == NULL))
2774 0 : return;
2775 :
2776 4 : defshdr = gelf_getshdr (defscn, &defshdrmem);
2777 4 : if (unlikely (defshdr == NULL))
2778 : return;
2779 :
2780 32 : for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
2781 : {
2782 : GElf_Verdef defmem;
2783 : GElf_Verdef *def;
2784 :
2785 : /* Get the data at the next offset. */
2786 36 : def = gelf_getverdef (defdata, offset, &defmem);
2787 36 : if (unlikely (def == NULL))
2788 : break;
2789 :
2790 36 : nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
2791 :
2792 36 : if (def->vd_next == 0)
2793 : break;
2794 32 : offset += def->vd_next;
2795 : }
2796 : }
2797 12 : if (needscn != NULL)
2798 : {
2799 12 : unsigned int offset = 0;
2800 : Elf_Data *needdata;
2801 : GElf_Shdr needshdrmem;
2802 : GElf_Shdr *needshdr;
2803 :
2804 12 : needdata = elf_getdata (needscn, NULL);
2805 12 : if (unlikely (needdata == NULL))
2806 0 : return;
2807 :
2808 12 : needshdr = gelf_getshdr (needscn, &needshdrmem);
2809 12 : if (unlikely (needshdr == NULL))
2810 : return;
2811 :
2812 34 : for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
2813 : {
2814 : GElf_Verneed needmem;
2815 : GElf_Verneed *need;
2816 : unsigned int auxoffset;
2817 : int cnt2;
2818 :
2819 : /* Get the data at the next offset. */
2820 46 : need = gelf_getverneed (needdata, offset, &needmem);
2821 46 : if (unlikely (need == NULL))
2822 : break;
2823 :
2824 : /* Run through the auxiliary entries. */
2825 46 : auxoffset = offset + need->vn_aux;
2826 141 : for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
2827 : {
2828 : GElf_Vernaux auxmem;
2829 : GElf_Vernaux *aux;
2830 :
2831 95 : aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
2832 95 : if (unlikely (aux == NULL))
2833 : break;
2834 :
2835 95 : nvername = MAX (nvername,
2836 : (size_t) (aux->vna_other & 0x7fff));
2837 :
2838 95 : if (aux->vna_next == 0)
2839 : break;
2840 49 : auxoffset += aux->vna_next;
2841 : }
2842 :
2843 46 : if (need->vn_next == 0)
2844 : break;
2845 34 : offset += need->vn_next;
2846 : }
2847 : }
2848 :
2849 : /* This is the number of versions we know about. */
2850 12 : ++nvername;
2851 :
2852 : /* Allocate the array. */
2853 12 : vername = (const char **) alloca (nvername * sizeof (const char *));
2854 24 : memset(vername, 0, nvername * sizeof (const char *));
2855 12 : filename = (const char **) alloca (nvername * sizeof (const char *));
2856 24 : memset(filename, 0, nvername * sizeof (const char *));
2857 :
2858 : /* Run through the data structures again and collect the strings. */
2859 12 : if (defscn != NULL)
2860 : {
2861 : /* Run through the version definitions and find the highest
2862 : index. */
2863 4 : unsigned int offset = 0;
2864 : Elf_Data *defdata;
2865 : GElf_Shdr defshdrmem;
2866 : GElf_Shdr *defshdr;
2867 :
2868 4 : defdata = elf_getdata (defscn, NULL);
2869 4 : if (unlikely (defdata == NULL))
2870 0 : return;
2871 :
2872 4 : defshdr = gelf_getshdr (defscn, &defshdrmem);
2873 4 : if (unlikely (defshdr == NULL))
2874 : return;
2875 :
2876 32 : for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
2877 : {
2878 :
2879 : /* Get the data at the next offset. */
2880 : GElf_Verdef defmem;
2881 36 : GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
2882 36 : if (unlikely (def == NULL))
2883 : break;
2884 :
2885 : GElf_Verdaux auxmem;
2886 36 : GElf_Verdaux *aux = gelf_getverdaux (defdata,
2887 36 : offset + def->vd_aux,
2888 : &auxmem);
2889 36 : if (unlikely (aux == NULL))
2890 : break;
2891 :
2892 36 : vername[def->vd_ndx & 0x7fff]
2893 36 : = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
2894 36 : filename[def->vd_ndx & 0x7fff] = NULL;
2895 :
2896 36 : if (def->vd_next == 0)
2897 : break;
2898 32 : offset += def->vd_next;
2899 : }
2900 : }
2901 12 : if (needscn != NULL)
2902 : {
2903 12 : unsigned int offset = 0;
2904 :
2905 12 : Elf_Data *needdata = elf_getdata (needscn, NULL);
2906 : GElf_Shdr needshdrmem;
2907 12 : GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
2908 12 : if (unlikely (needdata == NULL || needshdr == NULL))
2909 0 : return;
2910 :
2911 34 : for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
2912 : {
2913 : /* Get the data at the next offset. */
2914 : GElf_Verneed needmem;
2915 46 : GElf_Verneed *need = gelf_getverneed (needdata, offset,
2916 : &needmem);
2917 46 : if (unlikely (need == NULL))
2918 : break;
2919 :
2920 : /* Run through the auxiliary entries. */
2921 46 : unsigned int auxoffset = offset + need->vn_aux;
2922 141 : for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2923 : {
2924 : GElf_Vernaux auxmem;
2925 95 : GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
2926 : &auxmem);
2927 95 : if (unlikely (aux == NULL))
2928 : break;
2929 :
2930 95 : vername[aux->vna_other & 0x7fff]
2931 95 : = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
2932 95 : filename[aux->vna_other & 0x7fff]
2933 95 : = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
2934 :
2935 95 : if (aux->vna_next == 0)
2936 : break;
2937 49 : auxoffset += aux->vna_next;
2938 : }
2939 :
2940 46 : if (need->vn_next == 0)
2941 : break;
2942 34 : offset += need->vn_next;
2943 : }
2944 : }
2945 : }
2946 : else
2947 : {
2948 : vername = NULL;
2949 : nvername = 1;
2950 : filename = NULL;
2951 : }
2952 :
2953 : GElf_Shdr glink_mem;
2954 12 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2955 : &glink_mem);
2956 12 : size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_HALF, 1, EV_CURRENT);
2957 12 : if (glink == NULL)
2958 0 : error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %zu"),
2959 : elf_ndxscn (scn));
2960 :
2961 : /* Print the header. */
2962 72 : printf (ngettext ("\
2963 : \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
2964 : "\
2965 : \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
2966 : shdr->sh_size / sh_entsize),
2967 12 : (unsigned int) elf_ndxscn (scn),
2968 12 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2969 12 : (int) (shdr->sh_size / sh_entsize),
2970 : class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2971 : shdr->sh_offset,
2972 12 : (unsigned int) shdr->sh_link,
2973 12 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
2974 :
2975 : /* Now we can finally look at the actual contents of this section. */
2976 1515 : for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
2977 : {
2978 1503 : if (cnt % 2 == 0)
2979 : printf ("\n %4d:", cnt);
2980 :
2981 : GElf_Versym symmem;
2982 1503 : GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
2983 1503 : if (sym == NULL)
2984 : break;
2985 :
2986 1503 : switch (*sym)
2987 : {
2988 : ssize_t n;
2989 : case 0:
2990 159 : fputs_unlocked (gettext (" 0 *local* "),
2991 : stdout);
2992 : break;
2993 :
2994 : case 1:
2995 41 : fputs_unlocked (gettext (" 1 *global* "),
2996 : stdout);
2997 : break;
2998 :
2999 : default:
3000 5212 : n = printf ("%4d%c%s",
3001 1303 : *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
3002 : (vername != NULL
3003 1303 : && (unsigned int) (*sym & 0x7fff) < nvername)
3004 1303 : ? vername[*sym & 0x7fff] : "???");
3005 1303 : if ((unsigned int) (*sym & 0x7fff) < nvername
3006 1303 : && filename != NULL && filename[*sym & 0x7fff] != NULL)
3007 1878 : n += printf ("(%s)", filename[*sym & 0x7fff]);
3008 1303 : printf ("%*s", MAX (0, 33 - (int) n), " ");
3009 : break;
3010 : }
3011 : }
3012 12 : putchar_unlocked ('\n');
3013 : }
3014 :
3015 :
3016 : static void
3017 12 : print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
3018 : uint_fast32_t maxlength, Elf32_Word nbucket,
3019 : uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
3020 : {
3021 12 : uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
3022 :
3023 334 : for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
3024 322 : ++counts[lengths[cnt]];
3025 :
3026 : GElf_Shdr glink_mem;
3027 12 : GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf,
3028 12 : shdr->sh_link),
3029 : &glink_mem);
3030 12 : if (glink == NULL)
3031 : {
3032 0 : error (0, 0, gettext ("invalid sh_link value in section %zu"),
3033 : elf_ndxscn (scn));
3034 0 : return;
3035 : }
3036 :
3037 72 : printf (ngettext ("\
3038 : \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",
3039 : "\
3040 : \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",
3041 : nbucket),
3042 12 : (unsigned int) elf_ndxscn (scn),
3043 12 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3044 : (int) nbucket,
3045 12 : gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
3046 : shdr->sh_addr,
3047 : shdr->sh_offset,
3048 12 : (unsigned int) shdr->sh_link,
3049 12 : elf_strptr (ebl->elf, shstrndx, glink->sh_name));
3050 :
3051 12 : if (extrastr != NULL)
3052 12 : fputs (extrastr, stdout);
3053 :
3054 12 : if (likely (nbucket > 0))
3055 : {
3056 12 : uint64_t success = 0;
3057 :
3058 : /* xgettext:no-c-format */
3059 12 : fputs_unlocked (gettext ("\
3060 : Length Number % of total Coverage\n"), stdout);
3061 24 : printf (gettext (" 0 %6" PRIu32 " %5.1f%%\n"),
3062 12 : counts[0], (counts[0] * 100.0) / nbucket);
3063 :
3064 12 : uint64_t nzero_counts = 0;
3065 66 : for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
3066 : {
3067 54 : nzero_counts += counts[cnt] * cnt;
3068 162 : printf (gettext ("\
3069 : %7d %6" PRIu32 " %5.1f%% %5.1f%%\n"),
3070 54 : (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
3071 54 : (nzero_counts * 100.0) / nsyms);
3072 : }
3073 :
3074 : Elf32_Word acc = 0;
3075 54 : for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
3076 : {
3077 54 : acc += cnt;
3078 54 : success += counts[cnt] * acc;
3079 : }
3080 :
3081 24 : printf (gettext ("\
3082 : Average number of tests: successful lookup: %f\n\
3083 : unsuccessful lookup: %f\n"),
3084 12 : (double) success / (double) nzero_counts,
3085 12 : (double) nzero_counts / (double) nbucket);
3086 : }
3087 :
3088 12 : free (counts);
3089 : }
3090 :
3091 :
3092 : /* This function handles the traditional System V-style hash table format. */
3093 : static void
3094 0 : handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
3095 : {
3096 0 : Elf_Data *data = elf_getdata (scn, NULL);
3097 0 : if (unlikely (data == NULL))
3098 : {
3099 0 : error (0, 0, gettext ("cannot get data for section %d: %s"),
3100 0 : (int) elf_ndxscn (scn), elf_errmsg (-1));
3101 : return;
3102 : }
3103 :
3104 0 : if (unlikely (data->d_size < 2 * sizeof (Elf32_Word)))
3105 : {
3106 : invalid_data:
3107 0 : error (0, 0, gettext ("invalid data in sysv.hash section %d"),
3108 0 : (int) elf_ndxscn (scn));
3109 : return;
3110 : }
3111 :
3112 0 : Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
3113 0 : Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
3114 :
3115 0 : uint64_t used_buf = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
3116 0 : if (used_buf > data->d_size)
3117 : goto invalid_data;
3118 :
3119 0 : Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
3120 0 : Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
3121 :
3122 0 : uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
3123 :
3124 0 : uint_fast32_t maxlength = 0;
3125 0 : uint_fast32_t nsyms = 0;
3126 0 : for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
3127 : {
3128 0 : Elf32_Word inner = bucket[cnt];
3129 0 : while (inner > 0 && inner < nchain)
3130 : {
3131 0 : ++nsyms;
3132 0 : if (maxlength < ++lengths[cnt])
3133 0 : ++maxlength;
3134 :
3135 0 : inner = chain[inner];
3136 : }
3137 : }
3138 :
3139 0 : print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
3140 : lengths, NULL);
3141 :
3142 0 : free (lengths);
3143 : }
3144 :
3145 :
3146 : /* This function handles the incorrect, System V-style hash table
3147 : format some 64-bit architectures use. */
3148 : static void
3149 0 : handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
3150 : {
3151 0 : Elf_Data *data = elf_getdata (scn, NULL);
3152 0 : if (unlikely (data == NULL))
3153 : {
3154 0 : error (0, 0, gettext ("cannot get data for section %d: %s"),
3155 0 : (int) elf_ndxscn (scn), elf_errmsg (-1));
3156 : return;
3157 : }
3158 :
3159 0 : if (unlikely (data->d_size < 2 * sizeof (Elf64_Xword)))
3160 : {
3161 : invalid_data:
3162 0 : error (0, 0, gettext ("invalid data in sysv.hash64 section %d"),
3163 0 : (int) elf_ndxscn (scn));
3164 : return;
3165 : }
3166 :
3167 0 : Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
3168 0 : Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
3169 :
3170 0 : uint64_t maxwords = data->d_size / sizeof (Elf64_Xword);
3171 0 : if (maxwords < 2
3172 0 : || maxwords - 2 < nbucket
3173 0 : || maxwords - 2 - nbucket < nchain)
3174 : goto invalid_data;
3175 :
3176 0 : Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
3177 0 : Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
3178 :
3179 0 : uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
3180 :
3181 0 : uint_fast32_t maxlength = 0;
3182 0 : uint_fast32_t nsyms = 0;
3183 0 : for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
3184 : {
3185 0 : Elf64_Xword inner = bucket[cnt];
3186 0 : while (inner > 0 && inner < nchain)
3187 : {
3188 0 : ++nsyms;
3189 0 : if (maxlength < ++lengths[cnt])
3190 0 : ++maxlength;
3191 :
3192 0 : inner = chain[inner];
3193 : }
3194 : }
3195 :
3196 0 : print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
3197 : lengths, NULL);
3198 :
3199 0 : free (lengths);
3200 : }
3201 :
3202 :
3203 : /* This function handles the GNU-style hash table format. */
3204 : static void
3205 12 : handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
3206 : {
3207 12 : uint32_t *lengths = NULL;
3208 12 : Elf_Data *data = elf_getdata (scn, NULL);
3209 12 : if (unlikely (data == NULL))
3210 : {
3211 0 : error (0, 0, gettext ("cannot get data for section %d: %s"),
3212 0 : (int) elf_ndxscn (scn), elf_errmsg (-1));
3213 0 : return;
3214 : }
3215 :
3216 12 : if (unlikely (data->d_size < 4 * sizeof (Elf32_Word)))
3217 : {
3218 : invalid_data:
3219 0 : free (lengths);
3220 0 : error (0, 0, gettext ("invalid data in gnu.hash section %d"),
3221 0 : (int) elf_ndxscn (scn));
3222 : return;
3223 : }
3224 :
3225 12 : Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
3226 12 : Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
3227 :
3228 : /* Next comes the size of the bitmap. It's measured in words for
3229 : the architecture. It's 32 bits for 32 bit archs, and 64 bits for
3230 : 64 bit archs. There is always a bloom filter present, so zero is
3231 : an invalid value. */
3232 12 : Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
3233 12 : if (gelf_getclass (ebl->elf) == ELFCLASS64)
3234 12 : bitmask_words *= 2;
3235 :
3236 12 : if (bitmask_words == 0)
3237 : goto invalid_data;
3238 :
3239 12 : Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
3240 :
3241 : /* Is there still room for the sym chain?
3242 : Use uint64_t calculation to prevent 32bit overlow. */
3243 12 : uint64_t used_buf = (4ULL + bitmask_words + nbucket) * sizeof (Elf32_Word);
3244 12 : uint32_t max_nsyms = (data->d_size - used_buf) / sizeof (Elf32_Word);
3245 12 : if (used_buf > data->d_size)
3246 : goto invalid_data;
3247 :
3248 12 : lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
3249 :
3250 12 : Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
3251 12 : Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
3252 12 : Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
3253 12 : + nbucket];
3254 :
3255 : /* Compute distribution of chain lengths. */
3256 12 : uint_fast32_t maxlength = 0;
3257 12 : uint_fast32_t nsyms = 0;
3258 334 : for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
3259 322 : if (bucket[cnt] != 0)
3260 : {
3261 225 : Elf32_Word inner = bucket[cnt] - symbias;
3262 : do
3263 : {
3264 435 : ++nsyms;
3265 435 : if (maxlength < ++lengths[cnt])
3266 54 : ++maxlength;
3267 435 : if (inner >= max_nsyms)
3268 : goto invalid_data;
3269 : }
3270 435 : while ((chain[inner++] & 1) == 0);
3271 : }
3272 :
3273 : /* Count bits in bitmask. */
3274 : uint_fast32_t nbits = 0;
3275 118 : for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
3276 : {
3277 118 : uint_fast32_t word = bitmask[cnt];
3278 :
3279 118 : word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
3280 118 : word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
3281 118 : word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
3282 118 : word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
3283 118 : nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
3284 : }
3285 :
3286 : char *str;
3287 24 : if (unlikely (asprintf (&str, gettext ("\
3288 : Symbol Bias: %u\n\
3289 : Bitmask Size: %zu bytes %" PRIuFAST32 "%% bits set 2nd hash shift: %u\n"),
3290 : (unsigned int) symbias,
3291 : bitmask_words * sizeof (Elf32_Word),
3292 : ((nbits * 100 + 50)
3293 : / (uint_fast32_t) (bitmask_words
3294 : * sizeof (Elf32_Word) * 8)),
3295 : (unsigned int) shift) == -1))
3296 0 : error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
3297 :
3298 12 : print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
3299 : lengths, str);
3300 :
3301 12 : free (str);
3302 12 : free (lengths);
3303 : }
3304 :
3305 :
3306 : /* Find the symbol table(s). For this we have to search through the
3307 : section table. */
3308 : static void
3309 32 : handle_hash (Ebl *ebl)
3310 : {
3311 : /* Get the section header string table index. */
3312 : size_t shstrndx;
3313 32 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
3314 : error (EXIT_FAILURE, 0,
3315 0 : gettext ("cannot get section header string table index"));
3316 :
3317 : Elf_Scn *scn = NULL;
3318 884 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3319 : {
3320 : /* Handle the section if it is a symbol table. */
3321 : GElf_Shdr shdr_mem;
3322 852 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3323 :
3324 852 : if (likely (shdr != NULL))
3325 : {
3326 852 : if ((shdr->sh_type == SHT_HASH || shdr->sh_type == SHT_GNU_HASH)
3327 12 : && (shdr->sh_flags & SHF_COMPRESSED) != 0)
3328 : {
3329 0 : if (elf_compress (scn, 0, 0) < 0)
3330 0 : printf ("WARNING: %s [%zd]\n",
3331 : gettext ("Couldn't uncompress section"),
3332 : elf_ndxscn (scn));
3333 0 : shdr = gelf_getshdr (scn, &shdr_mem);
3334 0 : if (unlikely (shdr == NULL))
3335 0 : error (EXIT_FAILURE, 0,
3336 0 : gettext ("cannot get section [%zd] header: %s"),
3337 : elf_ndxscn (scn), elf_errmsg (-1));
3338 : }
3339 :
3340 852 : if (shdr->sh_type == SHT_HASH)
3341 : {
3342 0 : if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
3343 0 : handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
3344 : else
3345 0 : handle_sysv_hash (ebl, scn, shdr, shstrndx);
3346 : }
3347 852 : else if (shdr->sh_type == SHT_GNU_HASH)
3348 12 : handle_gnu_hash (ebl, scn, shdr, shstrndx);
3349 : }
3350 : }
3351 32 : }
3352 :
3353 :
3354 : static void
3355 36 : print_liblist (Ebl *ebl)
3356 : {
3357 : /* Find the library list sections. For this we have to search
3358 : through the section table. */
3359 36 : Elf_Scn *scn = NULL;
3360 :
3361 : /* Get the section header string table index. */
3362 : size_t shstrndx;
3363 36 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
3364 : error (EXIT_FAILURE, 0,
3365 0 : gettext ("cannot get section header string table index"));
3366 :
3367 947 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3368 : {
3369 : GElf_Shdr shdr_mem;
3370 911 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3371 :
3372 911 : if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
3373 : {
3374 0 : size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_LIB, 1, EV_CURRENT);
3375 0 : int nentries = shdr->sh_size / sh_entsize;
3376 0 : printf (ngettext ("\
3377 : \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
3378 : "\
3379 : \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
3380 : nentries),
3381 : elf_ndxscn (scn),
3382 0 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3383 : shdr->sh_offset,
3384 : nentries);
3385 :
3386 0 : Elf_Data *data = elf_getdata (scn, NULL);
3387 0 : if (data == NULL)
3388 0 : return;
3389 :
3390 0 : puts (gettext ("\
3391 : Library Time Stamp Checksum Version Flags"));
3392 :
3393 0 : for (int cnt = 0; cnt < nentries; ++cnt)
3394 : {
3395 : GElf_Lib lib_mem;
3396 0 : GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
3397 0 : if (unlikely (lib == NULL))
3398 0 : continue;
3399 :
3400 0 : time_t t = (time_t) lib->l_time_stamp;
3401 0 : struct tm *tm = gmtime (&t);
3402 0 : if (unlikely (tm == NULL))
3403 0 : continue;
3404 :
3405 0 : printf (" [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
3406 0 : cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
3407 0 : tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
3408 : tm->tm_hour, tm->tm_min, tm->tm_sec,
3409 0 : (unsigned int) lib->l_checksum,
3410 0 : (unsigned int) lib->l_version,
3411 0 : (unsigned int) lib->l_flags);
3412 : }
3413 : }
3414 : }
3415 : }
3416 :
3417 : static void
3418 36 : print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
3419 : {
3420 : /* Find the object attributes sections. For this we have to search
3421 : through the section table. */
3422 36 : Elf_Scn *scn = NULL;
3423 :
3424 : /* Get the section header string table index. */
3425 : size_t shstrndx;
3426 36 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
3427 : error (EXIT_FAILURE, 0,
3428 0 : gettext ("cannot get section header string table index"));
3429 :
3430 947 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3431 : {
3432 : GElf_Shdr shdr_mem;
3433 911 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3434 :
3435 911 : if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
3436 908 : && (shdr->sh_type != SHT_ARM_ATTRIBUTES
3437 1 : || ehdr->e_machine != EM_ARM)))
3438 907 : continue;
3439 :
3440 12 : printf (gettext ("\
3441 : \nObject attributes section [%2zu] '%s' of %" PRIu64
3442 : " bytes at offset %#0" PRIx64 ":\n"),
3443 : elf_ndxscn (scn),
3444 4 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3445 : shdr->sh_size, shdr->sh_offset);
3446 :
3447 4 : Elf_Data *data = elf_rawdata (scn, NULL);
3448 4 : if (unlikely (data == NULL || data->d_size == 0))
3449 0 : return;
3450 :
3451 4 : const unsigned char *p = data->d_buf;
3452 :
3453 : /* There is only one 'version', A. */
3454 4 : if (unlikely (*p++ != 'A'))
3455 : return;
3456 :
3457 4 : fputs_unlocked (gettext (" Owner Size\n"), stdout);
3458 :
3459 : inline size_t left (void)
3460 : {
3461 8 : return (const unsigned char *) data->d_buf + data->d_size - p;
3462 : }
3463 :
3464 : /* Loop over the sections. */
3465 8 : while (left () >= 4)
3466 : {
3467 : /* Section length. */
3468 : uint32_t len;
3469 4 : memcpy (&len, p, sizeof len);
3470 :
3471 4 : if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3472 4 : CONVERT (len);
3473 :
3474 4 : if (unlikely (len > left ()))
3475 : break;
3476 :
3477 : /* Section vendor name. */
3478 4 : const unsigned char *name = p + sizeof len;
3479 4 : p += len;
3480 :
3481 4 : unsigned const char *q = memchr (name, '\0', len);
3482 4 : if (unlikely (q == NULL))
3483 : break;
3484 4 : ++q;
3485 :
3486 8 : printf (gettext (" %-13s %4" PRIu32 "\n"), name, len);
3487 :
3488 8 : bool gnu_vendor = (q - name == sizeof "gnu"
3489 4 : && !memcmp (name, "gnu", sizeof "gnu"));
3490 :
3491 : /* Loop over subsections. */
3492 4 : if (shdr->sh_type != SHT_GNU_ATTRIBUTES
3493 3 : || gnu_vendor)
3494 8 : while (q < p)
3495 : {
3496 4 : const unsigned char *const sub = q;
3497 :
3498 : unsigned int subsection_tag;
3499 4 : get_uleb128 (subsection_tag, q, p);
3500 4 : if (unlikely (q >= p))
3501 : break;
3502 :
3503 : uint32_t subsection_len;
3504 4 : if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
3505 : break;
3506 :
3507 4 : memcpy (&subsection_len, q, sizeof subsection_len);
3508 :
3509 4 : if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3510 4 : CONVERT (subsection_len);
3511 :
3512 : /* Don't overflow, ptrdiff_t might be 32bits, but signed. */
3513 4 : if (unlikely (subsection_len == 0
3514 : || subsection_len >= (uint32_t) PTRDIFF_MAX
3515 : || p - sub < (ptrdiff_t) subsection_len))
3516 : break;
3517 :
3518 4 : const unsigned char *r = q + sizeof subsection_len;
3519 4 : q = sub + subsection_len;
3520 :
3521 4 : switch (subsection_tag)
3522 : {
3523 : default:
3524 : /* Unknown subsection, print and skip. */
3525 0 : printf (gettext (" %-4u %12" PRIu32 "\n"),
3526 : subsection_tag, subsection_len);
3527 : break;
3528 :
3529 : case 1: /* Tag_File */
3530 4 : printf (gettext (" File: %11" PRIu32 "\n"),
3531 : subsection_len);
3532 :
3533 26 : while (r < q)
3534 : {
3535 : unsigned int tag;
3536 22 : get_uleb128 (tag, r, q);
3537 22 : if (unlikely (r >= q))
3538 : break;
3539 :
3540 : /* GNU style tags have either a uleb128 value,
3541 : when lowest bit is not set, or a string
3542 : when the lowest bit is set.
3543 : "compatibility" (32) is special. It has
3544 : both a string and a uleb128 value. For
3545 : non-gnu we assume 6 till 31 only take ints.
3546 : XXX see arm backend, do we need a separate
3547 : hook? */
3548 22 : uint64_t value = 0;
3549 22 : const char *string = NULL;
3550 22 : if (tag == 32 || (tag & 1) == 0
3551 8 : || (! gnu_vendor && (tag > 5 && tag < 32)))
3552 : {
3553 21 : get_uleb128 (value, r, q);
3554 21 : if (r > q)
3555 : break;
3556 : }
3557 22 : if (tag == 32
3558 22 : || ((tag & 1) != 0
3559 8 : && (gnu_vendor
3560 8 : || (! gnu_vendor && tag > 32)))
3561 22 : || (! gnu_vendor && tag > 3 && tag < 6))
3562 : {
3563 1 : string = (const char *) r;
3564 1 : r = memchr (r, '\0', q - r);
3565 1 : if (r == NULL)
3566 : break;
3567 1 : ++r;
3568 : }
3569 :
3570 22 : const char *tag_name = NULL;
3571 22 : const char *value_name = NULL;
3572 22 : ebl_check_object_attribute (ebl, (const char *) name,
3573 : tag, value,
3574 : &tag_name, &value_name);
3575 :
3576 22 : if (tag_name != NULL)
3577 : {
3578 22 : if (tag == 32)
3579 0 : printf (gettext (" %s: %" PRId64 ", %s\n"),
3580 : tag_name, value, string);
3581 22 : else if (string == NULL && value_name == NULL)
3582 1 : printf (gettext (" %s: %" PRId64 "\n"),
3583 : tag_name, value);
3584 : else
3585 21 : printf (gettext (" %s: %s\n"),
3586 : tag_name, string ?: value_name);
3587 : }
3588 : else
3589 : {
3590 : /* For "gnu" vendor 32 "compatibility" has
3591 : already been handled above. */
3592 0 : assert (tag != 32
3593 : || strcmp ((const char *) name, "gnu"));
3594 0 : if (string == NULL)
3595 0 : printf (gettext (" %u: %" PRId64 "\n"),
3596 : tag, value);
3597 : else
3598 0 : printf (gettext (" %u: %s\n"),
3599 : tag, string);
3600 : }
3601 : }
3602 : }
3603 : }
3604 : }
3605 : }
3606 : }
3607 :
3608 :
3609 : static char *
3610 616544 : format_dwarf_addr (Dwfl_Module *dwflmod,
3611 : int address_size, Dwarf_Addr address, Dwarf_Addr raw)
3612 : {
3613 : /* See if there is a name we can give for this address. */
3614 : GElf_Sym sym;
3615 616544 : GElf_Off off = 0;
3616 1849618 : const char *name = (print_address_names && ! print_unresolved_addresses)
3617 616438 : ? dwfl_module_addrinfo (dwflmod, address, &off, &sym, NULL, NULL, NULL)
3618 1232982 : : NULL;
3619 :
3620 : const char *scn;
3621 616544 : if (print_unresolved_addresses)
3622 : {
3623 92 : address = raw;
3624 92 : scn = NULL;
3625 : }
3626 : else
3627 : {
3628 : /* Relativize the address. */
3629 616452 : int n = dwfl_module_relocations (dwflmod);
3630 616452 : int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
3631 :
3632 : /* In an ET_REL file there is a section name to refer to. */
3633 : scn = (i < 0 ? NULL
3634 616452 : : dwfl_module_relocation_info (dwflmod, i, NULL));
3635 : }
3636 :
3637 : char *result;
3638 616544 : if ((name != NULL
3639 594130 : ? (off != 0
3640 : ? (scn != NULL
3641 : ? (address_size == 0
3642 88354 : ? asprintf (&result,
3643 44177 : gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
3644 : scn, address, name, off)
3645 314652 : : asprintf (&result,
3646 104884 : gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
3647 104884 : scn, 2 + address_size * 2, address,
3648 : name, off))
3649 : : (address_size == 0
3650 224290 : ? asprintf (&result,
3651 112145 : gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
3652 : address, name, off)
3653 921474 : : asprintf (&result,
3654 307158 : gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
3655 307158 : 2 + address_size * 2, address,
3656 : name, off)))
3657 : : (scn != NULL
3658 : ? (address_size == 0
3659 4254 : ? asprintf (&result,
3660 2127 : gettext ("%s+%#" PRIx64 " <%s>"),
3661 : scn, address, name)
3662 16248 : : asprintf (&result,
3663 5416 : gettext ("%s+%#0*" PRIx64 " <%s>"),
3664 5416 : scn, 2 + address_size * 2, address, name))
3665 : : (address_size == 0
3666 7956 : ? asprintf (&result,
3667 3978 : gettext ("%#" PRIx64 " <%s>"),
3668 : address, name)
3669 42735 : : asprintf (&result,
3670 14245 : gettext ("%#0*" PRIx64 " <%s>"),
3671 14245 : 2 + address_size * 2, address, name))))
3672 : : (scn != NULL
3673 : ? (address_size == 0
3674 4192 : ? asprintf (&result,
3675 2096 : gettext ("%s+%#" PRIx64),
3676 : scn, address)
3677 13746 : : asprintf (&result,
3678 4582 : gettext ("%s+%#0*" PRIx64),
3679 4582 : scn, 2 + address_size * 2, address))
3680 : : (address_size == 0
3681 4850 : ? asprintf (&result,
3682 : "%#" PRIx64,
3683 : address)
3684 39933 : : asprintf (&result,
3685 : "%#0*" PRIx64,
3686 1840529 : 2 + address_size * 2, address)))) < 0)
3687 0 : error (EXIT_FAILURE, 0, _("memory exhausted"));
3688 :
3689 616544 : return result;
3690 : }
3691 :
3692 : static const char *
3693 856006 : dwarf_tag_string (unsigned int tag)
3694 : {
3695 856006 : switch (tag)
3696 : {
3697 : #define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
3698 0 : DWARF_ALL_KNOWN_DW_TAG
3699 : #undef DWARF_ONE_KNOWN_DW_TAG
3700 : default:
3701 0 : return NULL;
3702 : }
3703 : }
3704 :
3705 :
3706 : static const char *
3707 3014953 : dwarf_attr_string (unsigned int attrnum)
3708 : {
3709 3014953 : switch (attrnum)
3710 : {
3711 : #define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
3712 0 : DWARF_ALL_KNOWN_DW_AT
3713 : #undef DWARF_ONE_KNOWN_DW_AT
3714 : default:
3715 0 : return NULL;
3716 : }
3717 : }
3718 :
3719 :
3720 : static const char *
3721 3014953 : dwarf_form_string (unsigned int form)
3722 : {
3723 3014953 : switch (form)
3724 : {
3725 : #define DWARF_ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
3726 10 : DWARF_ALL_KNOWN_DW_FORM
3727 : #undef DWARF_ONE_KNOWN_DW_FORM
3728 : default:
3729 0 : return NULL;
3730 : }
3731 : }
3732 :
3733 :
3734 : static const char *
3735 1287 : dwarf_lang_string (unsigned int lang)
3736 : {
3737 1287 : switch (lang)
3738 : {
3739 : #define DWARF_ONE_KNOWN_DW_LANG(NAME, CODE) case CODE: return #NAME;
3740 0 : DWARF_ALL_KNOWN_DW_LANG
3741 : #undef DWARF_ONE_KNOWN_DW_LANG
3742 : default:
3743 0 : return NULL;
3744 : }
3745 : }
3746 :
3747 :
3748 : static const char *
3749 : dwarf_inline_string (unsigned int code)
3750 : {
3751 : static const char *const known[] =
3752 : {
3753 : #define DWARF_ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME,
3754 : DWARF_ALL_KNOWN_DW_INL
3755 : #undef DWARF_ONE_KNOWN_DW_INL
3756 : };
3757 :
3758 2953 : if (likely (code < sizeof (known) / sizeof (known[0])))
3759 2953 : return known[code];
3760 :
3761 : return NULL;
3762 : }
3763 :
3764 :
3765 : static const char *
3766 : dwarf_encoding_string (unsigned int code)
3767 : {
3768 : static const char *const known[] =
3769 : {
3770 : #define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
3771 : DWARF_ALL_KNOWN_DW_ATE
3772 : #undef DWARF_ONE_KNOWN_DW_ATE
3773 : };
3774 :
3775 15968 : if (likely (code < sizeof (known) / sizeof (known[0])))
3776 15968 : return known[code];
3777 :
3778 : return NULL;
3779 : }
3780 :
3781 :
3782 : static const char *
3783 : dwarf_access_string (unsigned int code)
3784 : {
3785 : static const char *const known[] =
3786 : {
3787 : #define DWARF_ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME,
3788 : DWARF_ALL_KNOWN_DW_ACCESS
3789 : #undef DWARF_ONE_KNOWN_DW_ACCESS
3790 : };
3791 :
3792 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3793 0 : return known[code];
3794 :
3795 : return NULL;
3796 : }
3797 :
3798 :
3799 : static const char *
3800 : dwarf_visibility_string (unsigned int code)
3801 : {
3802 : static const char *const known[] =
3803 : {
3804 : #define DWARF_ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
3805 : DWARF_ALL_KNOWN_DW_VIS
3806 : #undef DWARF_ONE_KNOWN_DW_VIS
3807 : };
3808 :
3809 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3810 0 : return known[code];
3811 :
3812 : return NULL;
3813 : }
3814 :
3815 :
3816 : static const char *
3817 : dwarf_virtuality_string (unsigned int code)
3818 : {
3819 : static const char *const known[] =
3820 : {
3821 : #define DWARF_ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
3822 : DWARF_ALL_KNOWN_DW_VIRTUALITY
3823 : #undef DWARF_ONE_KNOWN_DW_VIRTUALITY
3824 : };
3825 :
3826 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3827 0 : return known[code];
3828 :
3829 : return NULL;
3830 : }
3831 :
3832 :
3833 : static const char *
3834 : dwarf_identifier_case_string (unsigned int code)
3835 : {
3836 : static const char *const known[] =
3837 : {
3838 : #define DWARF_ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
3839 : DWARF_ALL_KNOWN_DW_ID
3840 : #undef DWARF_ONE_KNOWN_DW_ID
3841 : };
3842 :
3843 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3844 0 : return known[code];
3845 :
3846 : return NULL;
3847 : }
3848 :
3849 :
3850 : static const char *
3851 : dwarf_calling_convention_string (unsigned int code)
3852 : {
3853 : static const char *const known[] =
3854 : {
3855 : #define DWARF_ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
3856 : DWARF_ALL_KNOWN_DW_CC
3857 : #undef DWARF_ONE_KNOWN_DW_CC
3858 : };
3859 :
3860 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3861 0 : return known[code];
3862 :
3863 : return NULL;
3864 : }
3865 :
3866 :
3867 : static const char *
3868 : dwarf_ordering_string (unsigned int code)
3869 : {
3870 : static const char *const known[] =
3871 : {
3872 : #define DWARF_ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
3873 : DWARF_ALL_KNOWN_DW_ORD
3874 : #undef DWARF_ONE_KNOWN_DW_ORD
3875 : };
3876 :
3877 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3878 0 : return known[code];
3879 :
3880 : return NULL;
3881 : }
3882 :
3883 :
3884 : static const char *
3885 : dwarf_discr_list_string (unsigned int code)
3886 : {
3887 : static const char *const known[] =
3888 : {
3889 : #define DWARF_ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
3890 : DWARF_ALL_KNOWN_DW_DSC
3891 : #undef DWARF_ONE_KNOWN_DW_DSC
3892 : };
3893 :
3894 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3895 0 : return known[code];
3896 :
3897 : return NULL;
3898 : }
3899 :
3900 :
3901 : static const char *
3902 : dwarf_locexpr_opcode_string (unsigned int code)
3903 : {
3904 : static const char *const known[] =
3905 : {
3906 : /* Normally we can't affort building huge table of 64K entries,
3907 : most of them zero, just because there are a couple defined
3908 : values at the far end. In case of opcodes, it's OK. */
3909 : #define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
3910 : DWARF_ALL_KNOWN_DW_OP
3911 : #undef DWARF_ONE_KNOWN_DW_OP
3912 : };
3913 :
3914 386773 : if (likely (code < sizeof (known) / sizeof (known[0])))
3915 386773 : return known[code];
3916 :
3917 : return NULL;
3918 : }
3919 :
3920 :
3921 : /* Used by all dwarf_foo_name functions. */
3922 : static const char *
3923 6906120 : string_or_unknown (const char *known, unsigned int code,
3924 : unsigned int lo_user, unsigned int hi_user,
3925 : bool print_unknown_num)
3926 : {
3927 : static char unknown_buf[20];
3928 :
3929 6906120 : if (likely (known != NULL))
3930 : return known;
3931 :
3932 0 : if (lo_user != 0 && code >= lo_user && code <= hi_user)
3933 : {
3934 0 : snprintf (unknown_buf, sizeof unknown_buf, "lo_user+%#x",
3935 : code - lo_user);
3936 0 : return unknown_buf;
3937 : }
3938 :
3939 0 : if (print_unknown_num)
3940 : {
3941 0 : snprintf (unknown_buf, sizeof unknown_buf, "??? (%#x)", code);
3942 0 : return unknown_buf;
3943 : }
3944 :
3945 : return "???";
3946 : }
3947 :
3948 :
3949 : static const char *
3950 856006 : dwarf_tag_name (unsigned int tag)
3951 : {
3952 856006 : const char *ret = dwarf_tag_string (tag);
3953 856006 : return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true);
3954 : }
3955 :
3956 : static const char *
3957 3014953 : dwarf_attr_name (unsigned int attr)
3958 : {
3959 3014953 : const char *ret = dwarf_attr_string (attr);
3960 3014953 : return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true);
3961 : }
3962 :
3963 :
3964 : static const char *
3965 3014953 : dwarf_form_name (unsigned int form)
3966 : {
3967 3014953 : const char *ret = dwarf_form_string (form);
3968 3014953 : return string_or_unknown (ret, form, 0, 0, true);
3969 : }
3970 :
3971 :
3972 : static const char *
3973 1287 : dwarf_lang_name (unsigned int lang)
3974 : {
3975 1287 : const char *ret = dwarf_lang_string (lang);
3976 1287 : return string_or_unknown (ret, lang, DW_LANG_lo_user, DW_LANG_hi_user, false);
3977 : }
3978 :
3979 :
3980 : static const char *
3981 : dwarf_inline_name (unsigned int code)
3982 : {
3983 2953 : const char *ret = dwarf_inline_string (code);
3984 2953 : return string_or_unknown (ret, code, 0, 0, false);
3985 : }
3986 :
3987 :
3988 : static const char *
3989 : dwarf_encoding_name (unsigned int code)
3990 : {
3991 15968 : const char *ret = dwarf_encoding_string (code);
3992 15968 : return string_or_unknown (ret, code, DW_ATE_lo_user, DW_ATE_hi_user, false);
3993 : }
3994 :
3995 :
3996 : static const char *
3997 : dwarf_access_name (unsigned int code)
3998 : {
3999 0 : const char *ret = dwarf_access_string (code);
4000 0 : return string_or_unknown (ret, code, 0, 0, false);
4001 : }
4002 :
4003 :
4004 : static const char *
4005 : dwarf_visibility_name (unsigned int code)
4006 : {
4007 0 : const char *ret = dwarf_visibility_string (code);
4008 0 : return string_or_unknown (ret, code, 0, 0, false);
4009 : }
4010 :
4011 :
4012 : static const char *
4013 : dwarf_virtuality_name (unsigned int code)
4014 : {
4015 0 : const char *ret = dwarf_virtuality_string (code);
4016 0 : return string_or_unknown (ret, code, 0, 0, false);
4017 : }
4018 :
4019 :
4020 : static const char *
4021 : dwarf_identifier_case_name (unsigned int code)
4022 : {
4023 0 : const char *ret = dwarf_identifier_case_string (code);
4024 0 : return string_or_unknown (ret, code, 0, 0, false);
4025 : }
4026 :
4027 :
4028 : static const char *
4029 : dwarf_calling_convention_name (unsigned int code)
4030 : {
4031 0 : const char *ret = dwarf_calling_convention_string (code);
4032 0 : return string_or_unknown (ret, code, DW_CC_lo_user, DW_CC_hi_user, false);
4033 : }
4034 :
4035 :
4036 : static const char *
4037 : dwarf_ordering_name (unsigned int code)
4038 : {
4039 0 : const char *ret = dwarf_ordering_string (code);
4040 0 : return string_or_unknown (ret, code, 0, 0, false);
4041 : }
4042 :
4043 :
4044 : static const char *
4045 : dwarf_discr_list_name (unsigned int code)
4046 : {
4047 0 : const char *ret = dwarf_discr_list_string (code);
4048 0 : return string_or_unknown (ret, code, 0, 0, false);
4049 : }
4050 :
4051 :
4052 : static void
4053 137 : print_block (size_t n, const void *block)
4054 : {
4055 137 : if (n == 0)
4056 0 : puts (_("empty block"));
4057 : else
4058 : {
4059 274 : printf (_("%zu byte block:"), n);
4060 137 : const unsigned char *data = block;
4061 : do
4062 4728 : printf (" %02x", *data++);
4063 2364 : while (--n > 0);
4064 : putchar ('\n');
4065 : }
4066 137 : }
4067 :
4068 : static void
4069 274529 : print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
4070 : unsigned int vers, unsigned int addrsize, unsigned int offset_size,
4071 : struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data)
4072 : {
4073 274529 : const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
4074 :
4075 274529 : if (len == 0)
4076 : {
4077 : printf ("%*s(empty)\n", indent, "");
4078 : return;
4079 : }
4080 :
4081 : #define NEED(n) if (len < (Dwarf_Word) (n)) goto invalid
4082 : #define CONSUME(n) NEED (n); else len -= (n)
4083 :
4084 : Dwarf_Word offset = 0;
4085 661302 : while (len-- > 0)
4086 : {
4087 386773 : uint_fast8_t op = *data++;
4088 :
4089 773546 : const char *op_name = dwarf_locexpr_opcode_string (op);
4090 386773 : if (unlikely (op_name == NULL))
4091 : {
4092 : static char buf[20];
4093 0 : if (op >= DW_OP_lo_user)
4094 0 : snprintf (buf, sizeof buf, "lo_user+%#x", op - DW_OP_lo_user);
4095 : else
4096 0 : snprintf (buf, sizeof buf, "??? (%#x)", op);
4097 : op_name = buf;
4098 : }
4099 :
4100 386773 : switch (op)
4101 : {
4102 : case DW_OP_addr:;
4103 : /* Address operand. */
4104 : Dwarf_Word addr;
4105 7289 : NEED (addrsize);
4106 7289 : if (addrsize == 4)
4107 28 : addr = read_4ubyte_unaligned (dbg, data);
4108 7271 : else if (addrsize == 8)
4109 7289 : addr = read_8ubyte_unaligned (dbg, data);
4110 : else
4111 : goto invalid;
4112 7289 : data += addrsize;
4113 7289 : CONSUME (addrsize);
4114 :
4115 7289 : char *a = format_dwarf_addr (dwflmod, 0, addr, addr);
4116 7289 : printf ("%*s[%4" PRIuMAX "] %s %s\n",
4117 : indent, "", (uintmax_t) offset, op_name, a);
4118 7289 : free (a);
4119 :
4120 7289 : offset += 1 + addrsize;
4121 7289 : break;
4122 :
4123 : case DW_OP_call_ref:
4124 : /* Offset operand. */
4125 0 : if (ref_size != 4 && ref_size != 8)
4126 : goto invalid; /* Cannot be used in CFA. */
4127 0 : NEED (ref_size);
4128 0 : if (ref_size == 4)
4129 0 : addr = read_4ubyte_unaligned (dbg, data);
4130 : else
4131 0 : addr = read_8ubyte_unaligned (dbg, data);
4132 0 : data += ref_size;
4133 0 : CONSUME (ref_size);
4134 :
4135 0 : printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
4136 : indent, "", (uintmax_t) offset,
4137 : op_name, (uintmax_t) addr);
4138 0 : offset += 1 + ref_size;
4139 0 : break;
4140 :
4141 : case DW_OP_deref_size:
4142 : case DW_OP_xderef_size:
4143 : case DW_OP_pick:
4144 : case DW_OP_const1u:
4145 : // XXX value might be modified by relocation
4146 10123 : NEED (1);
4147 20246 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
4148 : indent, "", (uintmax_t) offset,
4149 10123 : op_name, *((uint8_t *) data));
4150 10123 : ++data;
4151 10123 : --len;
4152 10123 : offset += 2;
4153 10123 : break;
4154 :
4155 : case DW_OP_const2u:
4156 1043 : NEED (2);
4157 : // XXX value might be modified by relocation
4158 3129 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
4159 : indent, "", (uintmax_t) offset,
4160 2086 : op_name, read_2ubyte_unaligned (dbg, data));
4161 1043 : CONSUME (2);
4162 1043 : data += 2;
4163 1043 : offset += 3;
4164 1043 : break;
4165 :
4166 : case DW_OP_const4u:
4167 716 : NEED (4);
4168 : // XXX value might be modified by relocation
4169 2148 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
4170 : indent, "", (uintmax_t) offset,
4171 1432 : op_name, read_4ubyte_unaligned (dbg, data));
4172 716 : CONSUME (4);
4173 716 : data += 4;
4174 716 : offset += 5;
4175 716 : break;
4176 :
4177 : case DW_OP_const8u:
4178 75 : NEED (8);
4179 : // XXX value might be modified by relocation
4180 225 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
4181 : indent, "", (uintmax_t) offset,
4182 150 : op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
4183 75 : CONSUME (8);
4184 75 : data += 8;
4185 75 : offset += 9;
4186 75 : break;
4187 :
4188 : case DW_OP_const1s:
4189 1807 : NEED (1);
4190 : // XXX value might be modified by relocation
4191 3614 : printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
4192 : indent, "", (uintmax_t) offset,
4193 1807 : op_name, *((int8_t *) data));
4194 1807 : ++data;
4195 1807 : --len;
4196 1807 : offset += 2;
4197 1807 : break;
4198 :
4199 : case DW_OP_const2s:
4200 6 : NEED (2);
4201 : // XXX value might be modified by relocation
4202 18 : printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
4203 : indent, "", (uintmax_t) offset,
4204 12 : op_name, read_2sbyte_unaligned (dbg, data));
4205 6 : CONSUME (2);
4206 6 : data += 2;
4207 6 : offset += 3;
4208 6 : break;
4209 :
4210 : case DW_OP_const4s:
4211 0 : NEED (4);
4212 : // XXX value might be modified by relocation
4213 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
4214 : indent, "", (uintmax_t) offset,
4215 0 : op_name, read_4sbyte_unaligned (dbg, data));
4216 0 : CONSUME (4);
4217 0 : data += 4;
4218 0 : offset += 5;
4219 0 : break;
4220 :
4221 : case DW_OP_const8s:
4222 0 : NEED (8);
4223 : // XXX value might be modified by relocation
4224 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
4225 : indent, "", (uintmax_t) offset,
4226 0 : op_name, read_8sbyte_unaligned (dbg, data));
4227 0 : CONSUME (8);
4228 0 : data += 8;
4229 0 : offset += 9;
4230 0 : break;
4231 :
4232 : case DW_OP_piece:
4233 : case DW_OP_regx:
4234 : case DW_OP_plus_uconst:
4235 : case DW_OP_constu:;
4236 7264 : const unsigned char *start = data;
4237 : uint64_t uleb;
4238 7264 : NEED (1);
4239 7264 : get_uleb128 (uleb, data, data + len);
4240 7264 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
4241 : indent, "", (uintmax_t) offset, op_name, uleb);
4242 7264 : CONSUME (data - start);
4243 7264 : offset += 1 + (data - start);
4244 7264 : break;
4245 :
4246 : case DW_OP_bit_piece:
4247 0 : start = data;
4248 : uint64_t uleb2;
4249 0 : NEED (1);
4250 0 : get_uleb128 (uleb, data, data + len);
4251 : NEED (1);
4252 0 : get_uleb128 (uleb2, data, data + len);
4253 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
4254 : indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
4255 0 : CONSUME (data - start);
4256 0 : offset += 1 + (data - start);
4257 0 : break;
4258 :
4259 : case DW_OP_fbreg:
4260 : case DW_OP_breg0 ... DW_OP_breg31:
4261 : case DW_OP_consts:
4262 68481 : start = data;
4263 : int64_t sleb;
4264 68481 : NEED (1);
4265 68481 : get_sleb128 (sleb, data, data + len);
4266 68481 : printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
4267 : indent, "", (uintmax_t) offset, op_name, sleb);
4268 68481 : CONSUME (data - start);
4269 68481 : offset += 1 + (data - start);
4270 68481 : break;
4271 :
4272 : case DW_OP_bregx:
4273 0 : start = data;
4274 0 : NEED (1);
4275 0 : get_uleb128 (uleb, data, data + len);
4276 : NEED (1);
4277 0 : get_sleb128 (sleb, data, data + len);
4278 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
4279 : indent, "", (uintmax_t) offset, op_name, uleb, sleb);
4280 0 : CONSUME (data - start);
4281 0 : offset += 1 + (data - start);
4282 0 : break;
4283 :
4284 : case DW_OP_call2:
4285 0 : NEED (2);
4286 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
4287 : indent, "", (uintmax_t) offset, op_name,
4288 0 : read_2ubyte_unaligned (dbg, data));
4289 0 : CONSUME (2);
4290 0 : offset += 3;
4291 0 : break;
4292 :
4293 : case DW_OP_call4:
4294 0 : NEED (4);
4295 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
4296 : indent, "", (uintmax_t) offset, op_name,
4297 0 : read_4ubyte_unaligned (dbg, data));
4298 0 : CONSUME (4);
4299 0 : offset += 5;
4300 0 : break;
4301 :
4302 : case DW_OP_skip:
4303 : case DW_OP_bra:
4304 110 : NEED (2);
4305 110 : printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
4306 : indent, "", (uintmax_t) offset, op_name,
4307 110 : (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
4308 110 : CONSUME (2);
4309 110 : data += 2;
4310 110 : offset += 3;
4311 110 : break;
4312 :
4313 : case DW_OP_implicit_value:
4314 120 : start = data;
4315 120 : NEED (1);
4316 120 : get_uleb128 (uleb, data, data + len);
4317 120 : printf ("%*s[%4" PRIuMAX "] %s: ",
4318 : indent, "", (uintmax_t) offset, op_name);
4319 120 : NEED (uleb);
4320 120 : print_block (uleb, data);
4321 120 : data += uleb;
4322 120 : CONSUME (data - start);
4323 120 : offset += 1 + (data - start);
4324 120 : break;
4325 :
4326 : case DW_OP_GNU_implicit_pointer:
4327 : /* DIE offset operand. */
4328 3209 : start = data;
4329 3209 : NEED (ref_size);
4330 3209 : if (ref_size != 4 && ref_size != 8)
4331 : goto invalid; /* Cannot be used in CFA. */
4332 3209 : if (ref_size == 4)
4333 3209 : addr = read_4ubyte_unaligned (dbg, data);
4334 : else
4335 0 : addr = read_8ubyte_unaligned (dbg, data);
4336 3209 : data += ref_size;
4337 : /* Byte offset operand. */
4338 3209 : NEED (1);
4339 3209 : get_sleb128 (sleb, data, data + len);
4340 :
4341 6418 : printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
4342 : indent, "", (intmax_t) offset,
4343 : op_name, (uintmax_t) addr, sleb);
4344 3209 : CONSUME (data - start);
4345 3209 : offset += 1 + (data - start);
4346 3209 : break;
4347 :
4348 : case DW_OP_GNU_entry_value:
4349 : /* Size plus expression block. */
4350 19331 : start = data;
4351 19331 : NEED (1);
4352 19331 : get_uleb128 (uleb, data, data + len);
4353 19331 : printf ("%*s[%4" PRIuMAX "] %s:\n",
4354 : indent, "", (uintmax_t) offset, op_name);
4355 19331 : NEED (uleb);
4356 19331 : print_ops (dwflmod, dbg, indent + 6, indent + 6, vers,
4357 : addrsize, offset_size, cu, uleb, data);
4358 19331 : data += uleb;
4359 19331 : CONSUME (data - start);
4360 19331 : offset += 1 + (data - start);
4361 19331 : break;
4362 :
4363 : case DW_OP_GNU_const_type:
4364 : /* uleb128 CU relative DW_TAG_base_type DIE offset, 1-byte
4365 : unsigned size plus block. */
4366 1 : start = data;
4367 1 : NEED (1);
4368 1 : get_uleb128 (uleb, data, data + len);
4369 1 : if (! print_unresolved_addresses && cu != NULL)
4370 1 : uleb += cu->start;
4371 : NEED (1);
4372 1 : uint8_t usize = *(uint8_t *) data++;
4373 1 : NEED (usize);
4374 1 : printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] ",
4375 : indent, "", (uintmax_t) offset, op_name, uleb);
4376 1 : print_block (usize, data);
4377 1 : data += usize;
4378 1 : CONSUME (data - start);
4379 1 : offset += 1 + (data - start);
4380 1 : break;
4381 :
4382 : case DW_OP_GNU_regval_type:
4383 : /* uleb128 register number, uleb128 CU relative
4384 : DW_TAG_base_type DIE offset. */
4385 0 : start = data;
4386 0 : NEED (1);
4387 0 : get_uleb128 (uleb, data, data + len);
4388 : NEED (1);
4389 0 : get_uleb128 (uleb2, data, data + len);
4390 0 : if (! print_unresolved_addresses && cu != NULL)
4391 0 : uleb2 += cu->start;
4392 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
4393 : indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
4394 0 : CONSUME (data - start);
4395 0 : offset += 1 + (data - start);
4396 0 : break;
4397 :
4398 : case DW_OP_GNU_deref_type:
4399 : /* 1-byte unsigned size of value, uleb128 CU relative
4400 : DW_TAG_base_type DIE offset. */
4401 6 : start = data;
4402 6 : NEED (1);
4403 6 : usize = *(uint8_t *) data++;
4404 : NEED (1);
4405 6 : get_uleb128 (uleb, data, data + len);
4406 6 : if (! print_unresolved_addresses && cu != NULL)
4407 6 : uleb += cu->start;
4408 12 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
4409 : indent, "", (uintmax_t) offset,
4410 : op_name, usize, uleb);
4411 6 : CONSUME (data - start);
4412 6 : offset += 1 + (data - start);
4413 6 : break;
4414 :
4415 : case DW_OP_GNU_convert:
4416 : case DW_OP_GNU_reinterpret:
4417 : /* uleb128 CU relative offset to DW_TAG_base_type, or zero
4418 : for conversion to untyped. */
4419 198 : start = data;
4420 198 : NEED (1);
4421 198 : get_uleb128 (uleb, data, data + len);
4422 198 : if (uleb != 0 && ! print_unresolved_addresses && cu != NULL)
4423 133 : uleb += cu->start;
4424 198 : printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
4425 : indent, "", (uintmax_t) offset, op_name, uleb);
4426 198 : CONSUME (data - start);
4427 198 : offset += 1 + (data - start);
4428 198 : break;
4429 :
4430 : case DW_OP_GNU_parameter_ref:
4431 : /* 4 byte CU relative reference to the abstract optimized away
4432 : DW_TAG_formal_parameter. */
4433 21 : NEED (4);
4434 21 : uintmax_t param_off = (uintmax_t) read_4ubyte_unaligned (dbg, data);
4435 21 : if (! print_unresolved_addresses && cu != NULL)
4436 21 : param_off += cu->start;
4437 21 : printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
4438 : indent, "", (uintmax_t) offset, op_name, param_off);
4439 21 : CONSUME (4);
4440 21 : data += 4;
4441 21 : offset += 5;
4442 21 : break;
4443 :
4444 : default:
4445 : /* No Operand. */
4446 266973 : printf ("%*s[%4" PRIuMAX "] %s\n",
4447 : indent, "", (uintmax_t) offset, op_name);
4448 266973 : ++offset;
4449 266973 : break;
4450 : }
4451 :
4452 386773 : indent = indentrest;
4453 386773 : continue;
4454 :
4455 : invalid:
4456 0 : printf (gettext ("%*s[%4" PRIuMAX "] %s <TRUNCATED>\n"),
4457 : indent, "", (uintmax_t) offset, op_name);
4458 : break;
4459 : }
4460 : }
4461 :
4462 :
4463 : struct listptr
4464 : {
4465 : Dwarf_Off offset:(64 - 3);
4466 : bool addr64:1;
4467 : bool dwarf64:1;
4468 : bool warned:1;
4469 : struct Dwarf_CU *cu;
4470 : };
4471 :
4472 : #define listptr_offset_size(p) ((p)->dwarf64 ? 8 : 4)
4473 : #define listptr_address_size(p) ((p)->addr64 ? 8 : 4)
4474 :
4475 : static Dwarf_Addr
4476 58670 : listptr_base (struct listptr *p)
4477 : {
4478 : Dwarf_Addr base;
4479 117340 : Dwarf_Die cu = CUDIE (p->cu);
4480 : /* Find the base address of the compilation unit. It will normally
4481 : be specified by DW_AT_low_pc. In DWARF-3 draft 4, the base
4482 : address could be overridden by DW_AT_entry_pc. It's been
4483 : removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc for
4484 : compilation units with discontinuous ranges. */
4485 58670 : if (unlikely (dwarf_lowpc (&cu, &base) != 0))
4486 : {
4487 : Dwarf_Attribute attr_mem;
4488 0 : if (dwarf_formaddr (dwarf_attr (&cu, DW_AT_entry_pc, &attr_mem),
4489 : &base) != 0)
4490 0 : base = 0;
4491 : }
4492 58670 : return base;
4493 : }
4494 :
4495 : static int
4496 322704 : compare_listptr (const void *a, const void *b, void *arg)
4497 : {
4498 322704 : const char *name = arg;
4499 322704 : struct listptr *p1 = (void *) a;
4500 322704 : struct listptr *p2 = (void *) b;
4501 :
4502 322704 : if (p1->offset < p2->offset)
4503 : return -1;
4504 19627 : if (p1->offset > p2->offset)
4505 : return 1;
4506 :
4507 3546 : if (!p1->warned && !p2->warned)
4508 : {
4509 3546 : if (p1->addr64 != p2->addr64)
4510 : {
4511 0 : p1->warned = p2->warned = true;
4512 0 : error (0, 0,
4513 0 : gettext ("%s %#" PRIx64 " used with different address sizes"),
4514 : name, (uint64_t) p1->offset);
4515 : }
4516 3546 : if (p1->dwarf64 != p2->dwarf64)
4517 : {
4518 0 : p1->warned = p2->warned = true;
4519 0 : error (0, 0,
4520 0 : gettext ("%s %#" PRIx64 " used with different offset sizes"),
4521 0 : name, (uint64_t) p1->offset);
4522 : }
4523 3546 : if (listptr_base (p1) != listptr_base (p2))
4524 : {
4525 0 : p1->warned = p2->warned = true;
4526 0 : error (0, 0,
4527 0 : gettext ("%s %#" PRIx64 " used with different base addresses"),
4528 0 : name, (uint64_t) p1->offset);
4529 : }
4530 : }
4531 :
4532 : return 0;
4533 : }
4534 :
4535 : struct listptr_table
4536 : {
4537 : size_t n;
4538 : size_t alloc;
4539 : struct listptr *table;
4540 : };
4541 :
4542 : static struct listptr_table known_loclistptr;
4543 : static struct listptr_table known_rangelistptr;
4544 :
4545 : static void
4546 : reset_listptr (struct listptr_table *table)
4547 : {
4548 178 : free (table->table);
4549 178 : table->table = NULL;
4550 178 : table->n = table->alloc = 0;
4551 : }
4552 :
4553 : /* Returns false if offset doesn't fit. See struct listptr. */
4554 : static bool
4555 55053 : notice_listptr (enum section_e section, struct listptr_table *table,
4556 : uint_fast8_t address_size, uint_fast8_t offset_size,
4557 : struct Dwarf_CU *cu, Dwarf_Off offset)
4558 : {
4559 55053 : if (print_debug_sections & section)
4560 : {
4561 55046 : if (table->n == table->alloc)
4562 : {
4563 159 : if (table->alloc == 0)
4564 55 : table->alloc = 128;
4565 : else
4566 104 : table->alloc *= 2;
4567 159 : table->table = xrealloc (table->table,
4568 159 : table->alloc * sizeof table->table[0]);
4569 : }
4570 :
4571 55046 : struct listptr *p = &table->table[table->n++];
4572 :
4573 110092 : *p = (struct listptr)
4574 : {
4575 55046 : .addr64 = address_size == 8,
4576 55046 : .dwarf64 = offset_size == 8,
4577 : .offset = offset,
4578 : .cu = cu
4579 : };
4580 :
4581 55046 : if (p->offset != offset)
4582 : {
4583 0 : table->n--;
4584 0 : return false;
4585 : }
4586 : }
4587 : return true;
4588 : }
4589 :
4590 : static void
4591 : sort_listptr (struct listptr_table *table, const char *name)
4592 : {
4593 55 : if (table->n > 0)
4594 55 : qsort_r (table->table, table->n, sizeof table->table[0],
4595 : &compare_listptr, (void *) name);
4596 : }
4597 :
4598 : static bool
4599 51578 : skip_listptr_hole (struct listptr_table *table, size_t *idxp,
4600 : uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
4601 : Dwarf_Addr *base, struct Dwarf_CU **cu, ptrdiff_t offset,
4602 : unsigned char **readp, unsigned char *endp)
4603 : {
4604 51578 : if (table->n == 0)
4605 : return false;
4606 :
4607 106569 : while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
4608 54991 : ++*idxp;
4609 :
4610 51578 : struct listptr *p = &table->table[*idxp];
4611 :
4612 51578 : if (*idxp == table->n
4613 51578 : || p->offset >= (Dwarf_Off) (endp - *readp + offset))
4614 : {
4615 0 : *readp = endp;
4616 0 : printf (gettext (" [%6tx] <UNUSED GARBAGE IN REST OF SECTION>\n"),
4617 : offset);
4618 : return true;
4619 : }
4620 :
4621 51578 : if (p->offset != (Dwarf_Off) offset)
4622 : {
4623 0 : *readp += p->offset - offset;
4624 0 : printf (gettext (" [%6tx] <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
4625 : offset, (Dwarf_Off) p->offset - offset);
4626 : return true;
4627 : }
4628 :
4629 51578 : if (address_sizep != NULL)
4630 51578 : *address_sizep = listptr_address_size (p);
4631 51578 : if (offset_sizep != NULL)
4632 42376 : *offset_sizep = listptr_offset_size (p);
4633 51578 : if (base != NULL)
4634 51578 : *base = listptr_base (p);
4635 51578 : if (cu != NULL)
4636 42376 : *cu = p->cu;
4637 :
4638 : return false;
4639 : }
4640 :
4641 :
4642 : static void
4643 34 : print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
4644 : Ebl *ebl, GElf_Ehdr *ehdr,
4645 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
4646 : {
4647 68 : const size_t sh_size = (dbg->sectiondata[IDX_debug_abbrev] ?
4648 34 : dbg->sectiondata[IDX_debug_abbrev]->d_size : 0);
4649 :
4650 102 : printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
4651 : " [ Code]\n"),
4652 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4653 34 : (uint64_t) shdr->sh_offset);
4654 :
4655 34 : Dwarf_Off offset = 0;
4656 34 : while (offset < sh_size)
4657 : {
4658 1264 : printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
4659 : offset);
4660 :
4661 : while (1)
4662 65075 : {
4663 : size_t length;
4664 : Dwarf_Abbrev abbrev;
4665 :
4666 66339 : int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
4667 66339 : if (res != 0)
4668 : {
4669 1264 : if (unlikely (res < 0))
4670 : {
4671 0 : printf (gettext ("\
4672 : *** error while reading abbreviation: %s\n"),
4673 : dwarf_errmsg (-1));
4674 0 : return;
4675 : }
4676 :
4677 : /* This is the NUL byte at the end of the section. */
4678 1264 : ++offset;
4679 1264 : break;
4680 : }
4681 :
4682 : /* We know these calls can never fail. */
4683 65075 : unsigned int code = dwarf_getabbrevcode (&abbrev);
4684 65075 : unsigned int tag = dwarf_getabbrevtag (&abbrev);
4685 65075 : int has_children = dwarf_abbrevhaschildren (&abbrev);
4686 :
4687 130150 : printf (gettext (" [%5u] offset: %" PRId64
4688 : ", children: %s, tag: %s\n"),
4689 : code, (int64_t) offset,
4690 : has_children ? gettext ("yes") : gettext ("no"),
4691 : dwarf_tag_name (tag));
4692 :
4693 65075 : size_t cnt = 0;
4694 : unsigned int name;
4695 : unsigned int form;
4696 : Dwarf_Off enoffset;
4697 379662 : while (dwarf_getabbrevattr (&abbrev, cnt,
4698 : &name, &form, &enoffset) == 0)
4699 : {
4700 499024 : printf (" attr: %s, form: %s, offset: %#" PRIx64 "\n",
4701 : dwarf_attr_name (name), dwarf_form_name (form),
4702 : (uint64_t) enoffset);
4703 :
4704 249512 : ++cnt;
4705 : }
4706 :
4707 65075 : offset += length;
4708 : }
4709 : }
4710 : }
4711 :
4712 :
4713 : /* Print content of DWARF .debug_aranges section. We fortunately do
4714 : not have to know a bit about the structure of the section, libdwarf
4715 : takes care of it. */
4716 : static void
4717 1 : print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4718 : GElf_Shdr *shdr, Dwarf *dbg)
4719 : {
4720 : Dwarf_Aranges *aranges;
4721 : size_t cnt;
4722 1 : if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
4723 : {
4724 0 : error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
4725 : dwarf_errmsg (-1));
4726 0 : return;
4727 : }
4728 :
4729 : GElf_Shdr glink_mem;
4730 : GElf_Shdr *glink;
4731 1 : glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
4732 1 : if (glink == NULL)
4733 : {
4734 0 : error (0, 0, gettext ("invalid sh_link value in section %zu"),
4735 : elf_ndxscn (scn));
4736 : return;
4737 : }
4738 :
4739 3 : printf (ngettext ("\
4740 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
4741 : "\
4742 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
4743 : cnt),
4744 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4745 1 : (uint64_t) shdr->sh_offset, cnt);
4746 :
4747 : /* Compute floor(log16(cnt)). */
4748 1 : size_t tmp = cnt;
4749 1 : int digits = 1;
4750 2 : while (tmp >= 16)
4751 : {
4752 0 : ++digits;
4753 0 : tmp >>= 4;
4754 : }
4755 :
4756 5 : for (size_t n = 0; n < cnt; ++n)
4757 : {
4758 5 : Dwarf_Arange *runp = dwarf_onearange (aranges, n);
4759 5 : if (unlikely (runp == NULL))
4760 : {
4761 0 : printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
4762 0 : return;
4763 : }
4764 :
4765 : Dwarf_Addr start;
4766 : Dwarf_Word length;
4767 : Dwarf_Off offset;
4768 :
4769 5 : if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
4770 0 : printf (gettext (" [%*zu] ???\n"), digits, n);
4771 : else
4772 10 : printf (gettext (" [%*zu] start: %0#*" PRIx64
4773 : ", length: %5" PRIu64 ", CU DIE offset: %6"
4774 : PRId64 "\n"),
4775 5 : digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
4776 : (uint64_t) start, (uint64_t) length, (int64_t) offset);
4777 : }
4778 : }
4779 :
4780 :
4781 : /* Print content of DWARF .debug_aranges section. */
4782 : static void
4783 38 : print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
4784 : Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4785 : GElf_Shdr *shdr, Dwarf *dbg)
4786 : {
4787 38 : if (decodedaranges)
4788 : {
4789 1 : print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg);
4790 1 : return;
4791 : }
4792 :
4793 37 : Elf_Data *data = dbg->sectiondata[IDX_debug_aranges];
4794 :
4795 37 : if (unlikely (data == NULL))
4796 : {
4797 0 : error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
4798 : elf_errmsg (-1));
4799 : return;
4800 : }
4801 :
4802 111 : printf (gettext ("\
4803 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
4804 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4805 37 : (uint64_t) shdr->sh_offset);
4806 :
4807 37 : const unsigned char *readp = data->d_buf;
4808 37 : const unsigned char *readendp = readp + data->d_size;
4809 :
4810 1335 : while (readp < readendp)
4811 : {
4812 1261 : const unsigned char *hdrstart = readp;
4813 1261 : size_t start_offset = hdrstart - (const unsigned char *) data->d_buf;
4814 :
4815 2522 : printf (gettext ("\nTable at offset %zu:\n"), start_offset);
4816 1261 : if (readp + 4 > readendp)
4817 : {
4818 : invalid_data:
4819 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
4820 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
4821 : return;
4822 : }
4823 :
4824 1275 : Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
4825 1261 : unsigned int length_bytes = 4;
4826 1261 : if (length == DWARF3_LENGTH_64_BIT)
4827 : {
4828 0 : if (readp + 8 > readendp)
4829 : goto invalid_data;
4830 0 : length = read_8ubyte_unaligned_inc (dbg, readp);
4831 0 : length_bytes = 8;
4832 : }
4833 :
4834 1261 : const unsigned char *nexthdr = readp + length;
4835 2522 : printf (gettext ("\n Length: %6" PRIu64 "\n"),
4836 : (uint64_t) length);
4837 :
4838 1261 : if (unlikely (length > (size_t) (readendp - readp)))
4839 : goto invalid_data;
4840 :
4841 1261 : if (length == 0)
4842 0 : continue;
4843 :
4844 1261 : if (readp + 2 > readendp)
4845 : goto invalid_data;
4846 1261 : uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, readp);
4847 2522 : printf (gettext (" DWARF version: %6" PRIuFAST16 "\n"),
4848 : version);
4849 1261 : if (version != 2)
4850 : {
4851 0 : error (0, 0, gettext ("unsupported aranges version"));
4852 : goto next_table;
4853 : }
4854 :
4855 : Dwarf_Word offset;
4856 1261 : if (readp + length_bytes > readendp)
4857 : goto invalid_data;
4858 1261 : if (length_bytes == 8)
4859 0 : offset = read_8ubyte_unaligned_inc (dbg, readp);
4860 : else
4861 1275 : offset = read_4ubyte_unaligned_inc (dbg, readp);
4862 2522 : printf (gettext (" CU offset: %6" PRIx64 "\n"),
4863 : (uint64_t) offset);
4864 :
4865 1261 : if (readp + 1 > readendp)
4866 : goto invalid_data;
4867 1261 : unsigned int address_size = *readp++;
4868 2522 : printf (gettext (" Address size: %6" PRIu64 "\n"),
4869 : (uint64_t) address_size);
4870 1261 : if (address_size != 4 && address_size != 8)
4871 : {
4872 0 : error (0, 0, gettext ("unsupported address size"));
4873 : goto next_table;
4874 : }
4875 :
4876 1261 : unsigned int segment_size = *readp++;
4877 2522 : printf (gettext (" Segment size: %6" PRIu64 "\n\n"),
4878 : (uint64_t) segment_size);
4879 1261 : if (segment_size != 0 && segment_size != 4 && segment_size != 8)
4880 : {
4881 0 : error (0, 0, gettext ("unsupported segment size"));
4882 : goto next_table;
4883 : }
4884 :
4885 : /* Round the address to the next multiple of 2*address_size. */
4886 2522 : readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
4887 1261 : % (2 * address_size));
4888 :
4889 3852 : while (readp < nexthdr)
4890 : {
4891 : Dwarf_Word range_address;
4892 : Dwarf_Word range_length;
4893 2591 : Dwarf_Word segment = 0;
4894 2591 : if (readp + 2 * address_size + segment_size > readendp)
4895 : goto invalid_data;
4896 2591 : if (address_size == 4)
4897 : {
4898 36 : range_address = read_4ubyte_unaligned_inc (dbg, readp);
4899 36 : range_length = read_4ubyte_unaligned_inc (dbg, readp);
4900 : }
4901 : else
4902 : {
4903 2581 : range_address = read_8ubyte_unaligned_inc (dbg, readp);
4904 2581 : range_length = read_8ubyte_unaligned_inc (dbg, readp);
4905 : }
4906 :
4907 2591 : if (segment_size == 4)
4908 0 : segment = read_4ubyte_unaligned_inc (dbg, readp);
4909 2591 : else if (segment_size == 8)
4910 0 : segment = read_8ubyte_unaligned_inc (dbg, readp);
4911 :
4912 2591 : if (range_address == 0 && range_length == 0 && segment == 0)
4913 : break;
4914 :
4915 1330 : char *b = format_dwarf_addr (dwflmod, address_size, range_address,
4916 : range_address);
4917 1330 : char *e = format_dwarf_addr (dwflmod, address_size,
4918 1330 : range_address + range_length - 1,
4919 : range_length);
4920 1330 : if (segment_size != 0)
4921 0 : printf (gettext (" %s..%s (%" PRIx64 ")\n"), b, e,
4922 : (uint64_t) segment);
4923 : else
4924 1330 : printf (gettext (" %s..%s\n"), b, e);
4925 1330 : free (b);
4926 1330 : free (e);
4927 : }
4928 :
4929 : next_table:
4930 1261 : if (readp != nexthdr)
4931 : {
4932 0 : size_t padding = nexthdr - readp;
4933 0 : printf (gettext (" %zu padding bytes\n"), padding);
4934 0 : readp = nexthdr;
4935 : }
4936 : }
4937 : }
4938 :
4939 :
4940 : /* Print content of DWARF .debug_ranges section. */
4941 : static void
4942 25 : print_debug_ranges_section (Dwfl_Module *dwflmod,
4943 : Ebl *ebl, GElf_Ehdr *ehdr,
4944 : Elf_Scn *scn, GElf_Shdr *shdr,
4945 : Dwarf *dbg)
4946 : {
4947 25 : Elf_Data *data = dbg->sectiondata[IDX_debug_ranges];
4948 :
4949 25 : if (unlikely (data == NULL))
4950 : {
4951 0 : error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
4952 : elf_errmsg (-1));
4953 0 : return;
4954 : }
4955 :
4956 75 : printf (gettext ("\
4957 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
4958 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4959 25 : (uint64_t) shdr->sh_offset);
4960 :
4961 50 : sort_listptr (&known_rangelistptr, "rangelistptr");
4962 25 : size_t listptr_idx = 0;
4963 :
4964 25 : uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
4965 :
4966 25 : bool first = true;
4967 25 : Dwarf_Addr base = 0;
4968 25 : unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
4969 25 : unsigned char *readp = data->d_buf;
4970 37289 : while (readp < endp)
4971 : {
4972 37239 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
4973 :
4974 37239 : if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
4975 : &address_size, NULL, &base, NULL,
4976 : offset, &readp, endp))
4977 0 : continue;
4978 :
4979 37239 : if (unlikely (data->d_size - offset < (size_t) address_size * 2))
4980 : {
4981 0 : printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
4982 : break;
4983 : }
4984 :
4985 : Dwarf_Addr begin;
4986 : Dwarf_Addr end;
4987 37239 : if (address_size == 8)
4988 : {
4989 37239 : begin = read_8ubyte_unaligned_inc (dbg, readp);
4990 37239 : end = read_8ubyte_unaligned_inc (dbg, readp);
4991 : }
4992 : else
4993 : {
4994 0 : begin = read_4ubyte_unaligned_inc (dbg, readp);
4995 0 : end = read_4ubyte_unaligned_inc (dbg, readp);
4996 0 : if (begin == (Dwarf_Addr) (uint32_t) -1)
4997 0 : begin = (Dwarf_Addr) -1l;
4998 : }
4999 :
5000 37239 : if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
5001 : {
5002 0 : char *b = format_dwarf_addr (dwflmod, address_size, end, end);
5003 0 : printf (gettext (" [%6tx] base address %s\n"), offset, b);
5004 0 : free (b);
5005 0 : base = end;
5006 : }
5007 37239 : else if (begin == 0 && end == 0) /* End of list entry. */
5008 : {
5009 9202 : if (first)
5010 0 : printf (gettext (" [%6tx] empty list\n"), offset);
5011 : first = true;
5012 : }
5013 : else
5014 : {
5015 28037 : char *b = format_dwarf_addr (dwflmod, address_size, base + begin,
5016 : begin);
5017 28037 : char *e = format_dwarf_addr (dwflmod, address_size, base + end,
5018 : end);
5019 : /* We have an address range entry. */
5020 28037 : if (first) /* First address range entry in a list. */
5021 9202 : printf (gettext (" [%6tx] %s..%s\n"), offset, b, e);
5022 : else
5023 18835 : printf (gettext (" %s..%s\n"), b, e);
5024 28037 : free (b);
5025 28037 : free (e);
5026 :
5027 28037 : first = false;
5028 : }
5029 : }
5030 : }
5031 :
5032 : #define REGNAMESZ 16
5033 : static const char *
5034 12214 : register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
5035 : char name[REGNAMESZ], int *bits, int *type)
5036 : {
5037 : const char *set;
5038 : const char *pfx;
5039 : int ignore;
5040 12214 : ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
5041 : bits ?: &ignore, type ?: &ignore);
5042 12214 : if (n <= 0)
5043 : {
5044 0 : if (loc != NULL)
5045 0 : snprintf (name, REGNAMESZ, "reg%u", loc->regno);
5046 : else
5047 : snprintf (name, REGNAMESZ, "??? 0x%x", regno);
5048 0 : if (bits != NULL)
5049 0 : *bits = loc != NULL ? loc->bits : 0;
5050 0 : if (type != NULL)
5051 0 : *type = DW_ATE_unsigned;
5052 0 : set = "??? unrecognized";
5053 : }
5054 : else
5055 : {
5056 12214 : if (bits != NULL && *bits <= 0)
5057 0 : *bits = loc != NULL ? loc->bits : 0;
5058 12214 : if (type != NULL && *type == DW_ATE_void)
5059 0 : *type = DW_ATE_unsigned;
5060 :
5061 : }
5062 12214 : return set;
5063 : }
5064 :
5065 : static const unsigned char *
5066 32 : read_encoded (unsigned int encoding, const unsigned char *readp,
5067 : const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
5068 : {
5069 32 : if ((encoding & 0xf) == DW_EH_PE_absptr)
5070 0 : encoding = gelf_getclass (dbg->elf) == ELFCLASS32
5071 0 : ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
5072 :
5073 32 : switch (encoding & 0xf)
5074 : {
5075 : case DW_EH_PE_uleb128:
5076 0 : get_uleb128 (*res, readp, endp);
5077 : break;
5078 : case DW_EH_PE_sleb128:
5079 0 : get_sleb128 (*res, readp, endp);
5080 : break;
5081 : case DW_EH_PE_udata2:
5082 0 : if (readp + 2 > endp)
5083 : goto invalid;
5084 0 : *res = read_2ubyte_unaligned_inc (dbg, readp);
5085 : break;
5086 : case DW_EH_PE_udata4:
5087 16 : if (readp + 4 > endp)
5088 : goto invalid;
5089 16 : *res = read_4ubyte_unaligned_inc (dbg, readp);
5090 : break;
5091 : case DW_EH_PE_udata8:
5092 0 : if (readp + 8 > endp)
5093 : goto invalid;
5094 0 : *res = read_8ubyte_unaligned_inc (dbg, readp);
5095 : break;
5096 : case DW_EH_PE_sdata2:
5097 0 : if (readp + 2 > endp)
5098 : goto invalid;
5099 0 : *res = read_2sbyte_unaligned_inc (dbg, readp);
5100 : break;
5101 : case DW_EH_PE_sdata4:
5102 16 : if (readp + 4 > endp)
5103 : goto invalid;
5104 16 : *res = read_4sbyte_unaligned_inc (dbg, readp);
5105 : break;
5106 : case DW_EH_PE_sdata8:
5107 0 : if (readp + 8 > endp)
5108 : goto invalid;
5109 0 : *res = read_8sbyte_unaligned_inc (dbg, readp);
5110 : break;
5111 : default:
5112 : invalid:
5113 : error (1, 0,
5114 0 : gettext ("invalid encoding"));
5115 : }
5116 :
5117 32 : return readp;
5118 : }
5119 :
5120 :
5121 : static void
5122 4639 : print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
5123 : Dwarf_Word vma_base, unsigned int code_align,
5124 : int data_align,
5125 : unsigned int version, unsigned int ptr_size,
5126 : unsigned int encoding,
5127 : Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
5128 : {
5129 : char regnamebuf[REGNAMESZ];
5130 : const char *regname (unsigned int regno)
5131 : {
5132 11428 : register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
5133 : return regnamebuf;
5134 : }
5135 :
5136 4639 : puts ("\n Program:");
5137 4639 : Dwarf_Word pc = vma_base;
5138 103987 : while (readp < endp)
5139 : {
5140 94709 : unsigned int opcode = *readp++;
5141 :
5142 94709 : if (opcode < DW_CFA_advance_loc)
5143 : /* Extended opcode. */
5144 57219 : switch (opcode)
5145 : {
5146 : uint64_t op1;
5147 : int64_t sop1;
5148 : uint64_t op2;
5149 : int64_t sop2;
5150 :
5151 : case DW_CFA_nop:
5152 22379 : puts (" nop");
5153 79598 : break;
5154 : case DW_CFA_set_loc:
5155 0 : if ((uint64_t) (endp - readp) < 1)
5156 : goto invalid;
5157 0 : readp = read_encoded (encoding, readp, endp, &op1, dbg);
5158 0 : printf (" set_loc %#" PRIx64 " to %#" PRIx64 "\n",
5159 0 : op1, pc = vma_base + op1);
5160 : break;
5161 : case DW_CFA_advance_loc1:
5162 1938 : if ((uint64_t) (endp - readp) < 1)
5163 : goto invalid;
5164 3876 : printf (" advance_loc1 %u to %#" PRIx64 "\n",
5165 1938 : *readp, pc += *readp * code_align);
5166 1938 : ++readp;
5167 1938 : break;
5168 : case DW_CFA_advance_loc2:
5169 767 : if ((uint64_t) (endp - readp) < 2)
5170 : goto invalid;
5171 767 : op1 = read_2ubyte_unaligned_inc (dbg, readp);
5172 767 : printf (" advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
5173 767 : op1, pc += op1 * code_align);
5174 : break;
5175 : case DW_CFA_advance_loc4:
5176 24 : if ((uint64_t) (endp - readp) < 4)
5177 : goto invalid;
5178 48 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
5179 24 : printf (" advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
5180 24 : op1, pc += op1 * code_align);
5181 : break;
5182 : case DW_CFA_offset_extended:
5183 4 : if ((uint64_t) (endp - readp) < 1)
5184 : goto invalid;
5185 4 : get_uleb128 (op1, readp, endp);
5186 4 : if ((uint64_t) (endp - readp) < 1)
5187 : goto invalid;
5188 4 : get_uleb128 (op2, readp, endp);
5189 8 : printf (" offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
5190 : "\n",
5191 : op1, regname (op1), op2 * data_align);
5192 : break;
5193 : case DW_CFA_restore_extended:
5194 0 : if ((uint64_t) (endp - readp) < 1)
5195 : goto invalid;
5196 0 : get_uleb128 (op1, readp, endp);
5197 0 : printf (" restore_extended r%" PRIu64 " (%s)\n",
5198 : op1, regname (op1));
5199 : break;
5200 : case DW_CFA_undefined:
5201 8 : if ((uint64_t) (endp - readp) < 1)
5202 : goto invalid;
5203 8 : get_uleb128 (op1, readp, endp);
5204 16 : printf (" undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
5205 : break;
5206 : case DW_CFA_same_value:
5207 0 : if ((uint64_t) (endp - readp) < 1)
5208 : goto invalid;
5209 0 : get_uleb128 (op1, readp, endp);
5210 0 : printf (" same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
5211 : break;
5212 : case DW_CFA_register:
5213 0 : if ((uint64_t) (endp - readp) < 1)
5214 : goto invalid;
5215 0 : get_uleb128 (op1, readp, endp);
5216 0 : if ((uint64_t) (endp - readp) < 1)
5217 : goto invalid;
5218 0 : get_uleb128 (op2, readp, endp);
5219 0 : printf (" register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
5220 : op1, regname (op1), op2, regname (op2));
5221 : break;
5222 : case DW_CFA_remember_state:
5223 3065 : puts (" remember_state");
5224 3065 : break;
5225 : case DW_CFA_restore_state:
5226 3065 : puts (" restore_state");
5227 3065 : break;
5228 : case DW_CFA_def_cfa:
5229 125 : if ((uint64_t) (endp - readp) < 1)
5230 : goto invalid;
5231 125 : get_uleb128 (op1, readp, endp);
5232 125 : if ((uint64_t) (endp - readp) < 1)
5233 : goto invalid;
5234 125 : get_uleb128 (op2, readp, endp);
5235 250 : printf (" def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
5236 : op1, regname (op1), op2);
5237 : break;
5238 : case DW_CFA_def_cfa_register:
5239 45 : if ((uint64_t) (endp - readp) < 1)
5240 : goto invalid;
5241 45 : get_uleb128 (op1, readp, endp);
5242 90 : printf (" def_cfa_register r%" PRIu64 " (%s)\n",
5243 : op1, regname (op1));
5244 : break;
5245 : case DW_CFA_def_cfa_offset:
5246 25769 : if ((uint64_t) (endp - readp) < 1)
5247 : goto invalid;
5248 25769 : get_uleb128 (op1, readp, endp);
5249 25769 : printf (" def_cfa_offset %" PRIu64 "\n", op1);
5250 : break;
5251 : case DW_CFA_def_cfa_expression:
5252 14 : if ((uint64_t) (endp - readp) < 1)
5253 : goto invalid;
5254 14 : get_uleb128 (op1, readp, endp); /* Length of DW_FORM_block. */
5255 28 : printf (" def_cfa_expression %" PRIu64 "\n", op1);
5256 14 : if ((uint64_t) (endp - readp) < op1)
5257 : {
5258 : invalid:
5259 0 : fputs (gettext (" <INVALID DATA>\n"), stdout);
5260 0 : return;
5261 : }
5262 14 : print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
5263 : op1, readp);
5264 14 : readp += op1;
5265 14 : break;
5266 : case DW_CFA_expression:
5267 0 : if ((uint64_t) (endp - readp) < 1)
5268 : goto invalid;
5269 0 : get_uleb128 (op1, readp, endp);
5270 0 : if ((uint64_t) (endp - readp) < 1)
5271 : goto invalid;
5272 0 : get_uleb128 (op2, readp, endp); /* Length of DW_FORM_block. */
5273 0 : printf (" expression r%" PRIu64 " (%s) \n",
5274 : op1, regname (op1));
5275 0 : if ((uint64_t) (endp - readp) < op2)
5276 : goto invalid;
5277 0 : print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
5278 : op2, readp);
5279 0 : readp += op2;
5280 0 : break;
5281 : case DW_CFA_offset_extended_sf:
5282 16 : if ((uint64_t) (endp - readp) < 1)
5283 : goto invalid;
5284 16 : get_uleb128 (op1, readp, endp);
5285 16 : if ((uint64_t) (endp - readp) < 1)
5286 : goto invalid;
5287 16 : get_sleb128 (sop2, readp, endp);
5288 32 : printf (" offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
5289 : PRId64 "\n",
5290 : op1, regname (op1), sop2 * data_align);
5291 : break;
5292 : case DW_CFA_def_cfa_sf:
5293 0 : if ((uint64_t) (endp - readp) < 1)
5294 : goto invalid;
5295 0 : get_uleb128 (op1, readp, endp);
5296 0 : if ((uint64_t) (endp - readp) < 1)
5297 : goto invalid;
5298 0 : get_sleb128 (sop2, readp, endp);
5299 0 : printf (" def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
5300 : op1, regname (op1), sop2 * data_align);
5301 : break;
5302 : case DW_CFA_def_cfa_offset_sf:
5303 0 : if ((uint64_t) (endp - readp) < 1)
5304 : goto invalid;
5305 0 : get_sleb128 (sop1, readp, endp);
5306 0 : printf (" def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
5307 : break;
5308 : case DW_CFA_val_offset:
5309 0 : if ((uint64_t) (endp - readp) < 1)
5310 : goto invalid;
5311 0 : get_uleb128 (op1, readp, endp);
5312 0 : if ((uint64_t) (endp - readp) < 1)
5313 : goto invalid;
5314 0 : get_uleb128 (op2, readp, endp);
5315 0 : printf (" val_offset %" PRIu64 " at offset %" PRIu64 "\n",
5316 : op1, op2 * data_align);
5317 : break;
5318 : case DW_CFA_val_offset_sf:
5319 0 : if ((uint64_t) (endp - readp) < 1)
5320 : goto invalid;
5321 0 : get_uleb128 (op1, readp, endp);
5322 0 : if ((uint64_t) (endp - readp) < 1)
5323 : goto invalid;
5324 0 : get_sleb128 (sop2, readp, endp);
5325 0 : printf (" val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
5326 : op1, sop2 * data_align);
5327 : break;
5328 : case DW_CFA_val_expression:
5329 0 : if ((uint64_t) (endp - readp) < 1)
5330 : goto invalid;
5331 0 : get_uleb128 (op1, readp, endp);
5332 0 : if ((uint64_t) (endp - readp) < 1)
5333 : goto invalid;
5334 0 : get_uleb128 (op2, readp, endp); /* Length of DW_FORM_block. */
5335 0 : printf (" val_expression r%" PRIu64 " (%s)\n",
5336 : op1, regname (op1));
5337 0 : if ((uint64_t) (endp - readp) < op2)
5338 : goto invalid;
5339 0 : print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0,
5340 : NULL, op2, readp);
5341 0 : readp += op2;
5342 0 : break;
5343 : case DW_CFA_MIPS_advance_loc8:
5344 0 : if ((uint64_t) (endp - readp) < 8)
5345 : goto invalid;
5346 0 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
5347 0 : printf (" MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
5348 0 : op1, pc += op1 * code_align);
5349 : break;
5350 : case DW_CFA_GNU_window_save:
5351 0 : puts (" GNU_window_save");
5352 0 : break;
5353 : case DW_CFA_GNU_args_size:
5354 0 : if ((uint64_t) (endp - readp) < 1)
5355 : goto invalid;
5356 0 : get_uleb128 (op1, readp, endp);
5357 0 : printf (" args_size %" PRIu64 "\n", op1);
5358 : break;
5359 : default:
5360 : printf (" ??? (%u)\n", opcode);
5361 : break;
5362 : }
5363 37490 : else if (opcode < DW_CFA_offset)
5364 26260 : printf (" advance_loc %u to %#" PRIx64 "\n",
5365 26260 : opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
5366 11230 : else if (opcode < DW_CFA_restore)
5367 : {
5368 : uint64_t offset;
5369 7992 : if ((uint64_t) (endp - readp) < 1)
5370 : goto invalid;
5371 7992 : get_uleb128 (offset, readp, endp);
5372 15984 : printf (" offset r%u (%s) at cfa%+" PRId64 "\n",
5373 : opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
5374 : }
5375 : else
5376 6476 : printf (" restore r%u (%s)\n",
5377 : opcode & 0x3f, regname (opcode & 0x3f));
5378 : }
5379 : }
5380 :
5381 :
5382 : static unsigned int
5383 4573 : encoded_ptr_size (int encoding, unsigned int ptr_size)
5384 : {
5385 4573 : switch (encoding & 7)
5386 : {
5387 : case DW_EH_PE_udata4:
5388 : return 4;
5389 : case DW_EH_PE_udata8:
5390 0 : return 8;
5391 : case 0:
5392 34 : return ptr_size;
5393 : }
5394 :
5395 0 : fprintf (stderr, "Unsupported pointer encoding: %#x, "
5396 : "assuming pointer size of %d.\n", encoding, ptr_size);
5397 0 : return ptr_size;
5398 : }
5399 :
5400 :
5401 : static unsigned int
5402 88 : print_encoding (unsigned int val)
5403 : {
5404 88 : switch (val & 0xf)
5405 : {
5406 : case DW_EH_PE_absptr:
5407 0 : fputs ("absptr", stdout);
5408 0 : break;
5409 : case DW_EH_PE_uleb128:
5410 0 : fputs ("uleb128", stdout);
5411 0 : break;
5412 : case DW_EH_PE_udata2:
5413 0 : fputs ("udata2", stdout);
5414 0 : break;
5415 : case DW_EH_PE_udata4:
5416 16 : fputs ("udata4", stdout);
5417 16 : break;
5418 : case DW_EH_PE_udata8:
5419 0 : fputs ("udata8", stdout);
5420 0 : break;
5421 : case DW_EH_PE_sleb128:
5422 0 : fputs ("sleb128", stdout);
5423 0 : break;
5424 : case DW_EH_PE_sdata2:
5425 0 : fputs ("sdata2", stdout);
5426 0 : break;
5427 : case DW_EH_PE_sdata4:
5428 72 : fputs ("sdata4", stdout);
5429 72 : break;
5430 : case DW_EH_PE_sdata8:
5431 0 : fputs ("sdata8", stdout);
5432 0 : break;
5433 : default:
5434 : /* We did not use any of the bits after all. */
5435 : return val;
5436 : }
5437 :
5438 88 : return val & ~0xf;
5439 : }
5440 :
5441 :
5442 : static unsigned int
5443 72 : print_relinfo (unsigned int val)
5444 : {
5445 72 : switch (val & 0x70)
5446 : {
5447 : case DW_EH_PE_pcrel:
5448 56 : fputs ("pcrel", stdout);
5449 56 : break;
5450 : case DW_EH_PE_textrel:
5451 0 : fputs ("textrel", stdout);
5452 0 : break;
5453 : case DW_EH_PE_datarel:
5454 16 : fputs ("datarel", stdout);
5455 16 : break;
5456 : case DW_EH_PE_funcrel:
5457 0 : fputs ("funcrel", stdout);
5458 0 : break;
5459 : case DW_EH_PE_aligned:
5460 0 : fputs ("aligned", stdout);
5461 0 : break;
5462 : default:
5463 : return val;
5464 : }
5465 :
5466 72 : return val & ~0x70;
5467 : }
5468 :
5469 :
5470 : static void
5471 88 : print_encoding_base (const char *pfx, unsigned int fde_encoding)
5472 : {
5473 88 : printf ("(%s", pfx);
5474 :
5475 88 : if (fde_encoding == DW_EH_PE_omit)
5476 0 : puts ("omit)");
5477 : else
5478 : {
5479 88 : unsigned int w = fde_encoding;
5480 :
5481 88 : w = print_encoding (w);
5482 :
5483 88 : if (w & 0x70)
5484 : {
5485 72 : if (w != fde_encoding)
5486 72 : fputc_unlocked (' ', stdout);
5487 :
5488 72 : w = print_relinfo (w);
5489 : }
5490 :
5491 88 : if (w != 0)
5492 0 : printf ("%s%x", w != fde_encoding ? " " : "", w);
5493 :
5494 88 : puts (")");
5495 : }
5496 88 : }
5497 :
5498 :
5499 : static void
5500 42 : print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
5501 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5502 : {
5503 : size_t shstrndx;
5504 : /* We know this call will succeed since it did in the caller. */
5505 42 : (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
5506 42 : const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
5507 :
5508 : /* Needed if we find PC-relative addresses. */
5509 : GElf_Addr bias;
5510 42 : if (dwfl_module_getelf (dwflmod, &bias) == NULL)
5511 : {
5512 0 : error (0, 0, gettext ("cannot get ELF: %s"), dwfl_errmsg (-1));
5513 0 : return;
5514 : }
5515 :
5516 42 : bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
5517 42 : Elf_Data *data = (is_eh_frame
5518 : ? elf_rawdata (scn, NULL)
5519 42 : : dbg->sectiondata[IDX_debug_frame]);
5520 :
5521 42 : if (unlikely (data == NULL))
5522 : {
5523 0 : error (0, 0, gettext ("cannot get %s content: %s"),
5524 : scnname, elf_errmsg (-1));
5525 : return;
5526 : }
5527 :
5528 42 : if (is_eh_frame)
5529 28 : printf (gettext ("\
5530 : \nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5531 28 : elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
5532 : else
5533 14 : printf (gettext ("\
5534 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5535 14 : elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
5536 :
5537 : struct cieinfo
5538 : {
5539 : ptrdiff_t cie_offset;
5540 : const char *augmentation;
5541 : unsigned int code_alignment_factor;
5542 : unsigned int data_alignment_factor;
5543 : uint8_t address_size;
5544 : uint8_t fde_encoding;
5545 : uint8_t lsda_encoding;
5546 : struct cieinfo *next;
5547 42 : } *cies = NULL;
5548 :
5549 42 : const unsigned char *readp = data->d_buf;
5550 42 : const unsigned char *const dataend = ((unsigned char *) data->d_buf
5551 42 : + data->d_size);
5552 4739 : while (readp < dataend)
5553 : {
5554 4655 : if (unlikely (readp + 4 > dataend))
5555 : {
5556 : invalid_data:
5557 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
5558 : elf_ndxscn (scn), scnname);
5559 : return;
5560 : }
5561 :
5562 : /* At the beginning there must be a CIE. There can be multiple,
5563 : hence we test tis in a loop. */
5564 4655 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
5565 :
5566 4687 : Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
5567 4655 : unsigned int length = 4;
5568 4655 : if (unlikely (unit_length == 0xffffffff))
5569 : {
5570 0 : if (unlikely (readp + 8 > dataend))
5571 : goto invalid_data;
5572 :
5573 0 : unit_length = read_8ubyte_unaligned_inc (dbg, readp);
5574 0 : length = 8;
5575 : }
5576 :
5577 4655 : if (unlikely (unit_length == 0))
5578 : {
5579 32 : printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
5580 16 : continue;
5581 : }
5582 :
5583 4639 : Dwarf_Word maxsize = dataend - readp;
5584 4639 : if (unlikely (unit_length > maxsize))
5585 : goto invalid_data;
5586 :
5587 4639 : unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5588 :
5589 4639 : ptrdiff_t start = readp - (unsigned char *) data->d_buf;
5590 4639 : const unsigned char *const cieend = readp + unit_length;
5591 4639 : if (unlikely (cieend > dataend || readp + 8 > dataend))
5592 : goto invalid_data;
5593 :
5594 : Dwarf_Off cie_id;
5595 4639 : if (length == 4)
5596 : {
5597 4671 : cie_id = read_4ubyte_unaligned_inc (dbg, readp);
5598 4639 : if (!is_eh_frame && cie_id == DW_CIE_ID_32)
5599 24 : cie_id = DW_CIE_ID_64;
5600 : }
5601 : else
5602 0 : cie_id = read_8ubyte_unaligned_inc (dbg, readp);
5603 :
5604 4639 : uint_fast8_t version = 2;
5605 : unsigned int code_alignment_factor;
5606 : int data_alignment_factor;
5607 4639 : unsigned int fde_encoding = 0;
5608 4639 : unsigned int lsda_encoding = 0;
5609 4639 : Dwarf_Word initial_location = 0;
5610 4639 : Dwarf_Word vma_base = 0;
5611 :
5612 4639 : if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
5613 : {
5614 66 : version = *readp++;
5615 66 : const char *const augmentation = (const char *) readp;
5616 66 : readp = memchr (readp, '\0', cieend - readp);
5617 66 : if (unlikely (readp == NULL))
5618 : goto invalid_data;
5619 66 : ++readp;
5620 :
5621 66 : uint_fast8_t segment_size = 0;
5622 66 : if (version >= 4)
5623 : {
5624 0 : if (cieend - readp < 5)
5625 : goto invalid_data;
5626 0 : ptr_size = *readp++;
5627 0 : segment_size = *readp++;
5628 : }
5629 :
5630 66 : if (cieend - readp < 1)
5631 : goto invalid_data;
5632 66 : get_uleb128 (code_alignment_factor, readp, cieend);
5633 66 : if (cieend - readp < 1)
5634 : goto invalid_data;
5635 66 : get_sleb128 (data_alignment_factor, readp, cieend);
5636 :
5637 : /* In some variant for unwind data there is another field. */
5638 66 : if (strcmp (augmentation, "eh") == 0)
5639 0 : readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5640 :
5641 : unsigned int return_address_register;
5642 66 : if (cieend - readp < 1)
5643 : goto invalid_data;
5644 66 : if (unlikely (version == 1))
5645 54 : return_address_register = *readp++;
5646 : else
5647 12 : get_uleb128 (return_address_register, readp, cieend);
5648 :
5649 132 : printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
5650 : " CIE_id: %" PRIu64 "\n"
5651 : " version: %u\n"
5652 : " augmentation: \"%s\"\n",
5653 : offset, (uint64_t) unit_length, (uint64_t) cie_id,
5654 : version, augmentation);
5655 66 : if (version >= 4)
5656 0 : printf (" address_size: %u\n"
5657 : " segment_size: %u\n",
5658 : ptr_size, segment_size);
5659 66 : printf (" code_alignment_factor: %u\n"
5660 : " data_alignment_factor: %d\n"
5661 : " return_address_register: %u\n",
5662 : code_alignment_factor,
5663 : data_alignment_factor, return_address_register);
5664 :
5665 66 : if (augmentation[0] == 'z')
5666 : {
5667 : unsigned int augmentationlen;
5668 40 : get_uleb128 (augmentationlen, readp, cieend);
5669 :
5670 40 : if (augmentationlen > (size_t) (cieend - readp))
5671 : {
5672 0 : error (0, 0, gettext ("invalid augmentation length"));
5673 0 : readp = cieend;
5674 0 : continue;
5675 : }
5676 :
5677 40 : const char *hdr = "Augmentation data:";
5678 40 : const char *cp = augmentation + 1;
5679 120 : while (*cp != '\0' && cp < augmentation + augmentationlen + 1)
5680 : {
5681 80 : printf (" %-26s%#x ", hdr, *readp);
5682 40 : hdr = "";
5683 :
5684 40 : if (*cp == 'R')
5685 : {
5686 40 : fde_encoding = *readp++;
5687 40 : print_encoding_base (gettext ("FDE address encoding: "),
5688 : fde_encoding);
5689 : }
5690 0 : else if (*cp == 'L')
5691 : {
5692 0 : lsda_encoding = *readp++;
5693 0 : print_encoding_base (gettext ("LSDA pointer encoding: "),
5694 : lsda_encoding);
5695 : }
5696 0 : else if (*cp == 'P')
5697 : {
5698 : /* Personality. This field usually has a relocation
5699 : attached pointing to __gcc_personality_v0. */
5700 0 : const unsigned char *startp = readp;
5701 0 : unsigned int encoding = *readp++;
5702 0 : uint64_t val = 0;
5703 0 : readp = read_encoded (encoding, readp,
5704 0 : readp - 1 + augmentationlen,
5705 : &val, dbg);
5706 :
5707 0 : while (++startp < readp)
5708 0 : printf ("%#x ", *startp);
5709 :
5710 0 : putchar ('(');
5711 0 : print_encoding (encoding);
5712 0 : putchar (' ');
5713 0 : switch (encoding & 0xf)
5714 : {
5715 : case DW_EH_PE_sleb128:
5716 : case DW_EH_PE_sdata2:
5717 : case DW_EH_PE_sdata4:
5718 0 : printf ("%" PRId64 ")\n", val);
5719 : break;
5720 : default:
5721 0 : printf ("%#" PRIx64 ")\n", val);
5722 : break;
5723 : }
5724 : }
5725 : else
5726 0 : printf ("(%x)\n", *readp++);
5727 :
5728 40 : ++cp;
5729 : }
5730 : }
5731 :
5732 66 : if (likely (ptr_size == 4 || ptr_size == 8))
5733 : {
5734 66 : struct cieinfo *newp = alloca (sizeof (*newp));
5735 66 : newp->cie_offset = offset;
5736 66 : newp->augmentation = augmentation;
5737 66 : newp->fde_encoding = fde_encoding;
5738 66 : newp->lsda_encoding = lsda_encoding;
5739 66 : newp->address_size = ptr_size;
5740 66 : newp->code_alignment_factor = code_alignment_factor;
5741 66 : newp->data_alignment_factor = data_alignment_factor;
5742 66 : newp->next = cies;
5743 66 : cies = newp;
5744 : }
5745 : }
5746 : else
5747 : {
5748 : struct cieinfo *cie = cies;
5749 4573 : while (cie != NULL)
5750 9146 : if (is_eh_frame
5751 4545 : ? ((Dwarf_Off) start - cie_id) == (Dwarf_Off) cie->cie_offset
5752 28 : : cie_id == (Dwarf_Off) cie->cie_offset)
5753 : break;
5754 : else
5755 0 : cie = cie->next;
5756 4573 : if (unlikely (cie == NULL))
5757 : {
5758 0 : puts ("invalid CIE reference in FDE");
5759 0 : return;
5760 : }
5761 :
5762 : /* Initialize from CIE data. */
5763 4573 : fde_encoding = cie->fde_encoding;
5764 4573 : lsda_encoding = cie->lsda_encoding;
5765 4573 : ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
5766 4573 : code_alignment_factor = cie->code_alignment_factor;
5767 4573 : data_alignment_factor = cie->data_alignment_factor;
5768 :
5769 4573 : const unsigned char *base = readp;
5770 : // XXX There are sometimes relocations for this value
5771 4589 : initial_location = read_addr_unaligned_inc (ptr_size, dbg, readp);
5772 4573 : Dwarf_Word address_range
5773 4589 : = read_addr_unaligned_inc (ptr_size, dbg, readp);
5774 :
5775 : /* pcrel for an FDE address is relative to the runtime
5776 : address of the start_address field itself. Sign extend
5777 : if necessary to make sure the calculation is done on the
5778 : full 64 bit address even when initial_location only holds
5779 : the lower 32 bits. */
5780 4573 : Dwarf_Addr pc_start = initial_location;
5781 4573 : if (ptr_size == 4)
5782 4543 : pc_start = (uint64_t) (int32_t) pc_start;
5783 4573 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
5784 9078 : pc_start += ((uint64_t) shdr->sh_addr
5785 4539 : + (base - (const unsigned char *) data->d_buf)
5786 4539 : - bias);
5787 :
5788 4573 : char *a = format_dwarf_addr (dwflmod, cie->address_size,
5789 : pc_start, initial_location);
5790 9146 : printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
5791 : " CIE_pointer: %" PRIu64 "\n"
5792 : " initial_location: %s",
5793 : offset, (uint64_t) unit_length,
5794 : cie->cie_offset, (uint64_t) cie_id, a);
5795 4573 : free (a);
5796 4573 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
5797 : {
5798 9078 : vma_base = (((uint64_t) shdr->sh_offset
5799 4539 : + (base - (const unsigned char *) data->d_buf)
5800 4539 : + (uint64_t) initial_location)
5801 : & (ptr_size == 4
5802 : ? UINT64_C (0xffffffff)
5803 4539 : : UINT64_C (0xffffffffffffffff)));
5804 4539 : printf (gettext (" (offset: %#" PRIx64 ")"),
5805 : (uint64_t) vma_base);
5806 : }
5807 :
5808 4573 : printf ("\n address_range: %#" PRIx64,
5809 : (uint64_t) address_range);
5810 4573 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
5811 4539 : printf (gettext (" (end offset: %#" PRIx64 ")"),
5812 4539 : ((uint64_t) vma_base + (uint64_t) address_range)
5813 : & (ptr_size == 4
5814 : ? UINT64_C (0xffffffff)
5815 4539 : : UINT64_C (0xffffffffffffffff)));
5816 4573 : putchar ('\n');
5817 :
5818 4573 : if (cie->augmentation[0] == 'z')
5819 : {
5820 : unsigned int augmentationlen;
5821 4539 : if (cieend - readp < 1)
5822 : goto invalid_data;
5823 4539 : get_uleb128 (augmentationlen, readp, cieend);
5824 :
5825 4539 : if (augmentationlen > (size_t) (cieend - readp))
5826 : {
5827 0 : error (0, 0, gettext ("invalid augmentation length"));
5828 0 : readp = cieend;
5829 0 : continue;
5830 : }
5831 :
5832 4539 : if (augmentationlen > 0)
5833 : {
5834 0 : const char *hdr = "Augmentation data:";
5835 0 : const char *cp = cie->augmentation + 1;
5836 0 : unsigned int u = 0;
5837 0 : while (*cp != '\0'
5838 0 : && cp < cie->augmentation + augmentationlen + 1)
5839 : {
5840 0 : if (*cp == 'L')
5841 : {
5842 : uint64_t lsda_pointer;
5843 0 : const unsigned char *p
5844 0 : = read_encoded (lsda_encoding, &readp[u],
5845 : &readp[augmentationlen],
5846 : &lsda_pointer, dbg);
5847 0 : u = p - readp;
5848 0 : printf (gettext ("\
5849 : %-26sLSDA pointer: %#" PRIx64 "\n"),
5850 : hdr, lsda_pointer);
5851 0 : hdr = "";
5852 : }
5853 0 : ++cp;
5854 : }
5855 :
5856 0 : while (u < augmentationlen)
5857 : {
5858 0 : printf (" %-26s%#x\n", hdr, readp[u++]);
5859 0 : hdr = "";
5860 : }
5861 : }
5862 :
5863 4539 : readp += augmentationlen;
5864 : }
5865 : }
5866 :
5867 : /* Handle the initialization instructions. */
5868 4639 : if (ptr_size != 4 && ptr_size !=8)
5869 : printf ("invalid CIE pointer size (%u), must be 4 or 8.\n", ptr_size);
5870 : else
5871 4639 : print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
5872 : data_alignment_factor, version, ptr_size,
5873 : fde_encoding, dwflmod, ebl, dbg);
5874 4639 : readp = cieend;
5875 : }
5876 : }
5877 :
5878 :
5879 : struct attrcb_args
5880 : {
5881 : Dwfl_Module *dwflmod;
5882 : Dwarf *dbg;
5883 : Dwarf_Die *die;
5884 : int level;
5885 : bool silent;
5886 : unsigned int version;
5887 : unsigned int addrsize;
5888 : unsigned int offset_size;
5889 : struct Dwarf_CU *cu;
5890 : };
5891 :
5892 :
5893 : static int
5894 2766178 : attr_callback (Dwarf_Attribute *attrp, void *arg)
5895 : {
5896 2766178 : struct attrcb_args *cbargs = (struct attrcb_args *) arg;
5897 2766178 : const int level = cbargs->level;
5898 :
5899 2766178 : unsigned int attr = dwarf_whatattr (attrp);
5900 2766178 : if (unlikely (attr == 0))
5901 : {
5902 0 : if (!cbargs->silent)
5903 0 : error (0, 0, gettext ("cannot get attribute code: %s"),
5904 : dwarf_errmsg (-1));
5905 : return DWARF_CB_ABORT;
5906 : }
5907 :
5908 2766178 : unsigned int form = dwarf_whatform (attrp);
5909 2766178 : if (unlikely (form == 0))
5910 : {
5911 0 : if (!cbargs->silent)
5912 0 : error (0, 0, gettext ("cannot get attribute form: %s"),
5913 : dwarf_errmsg (-1));
5914 : return DWARF_CB_ABORT;
5915 : }
5916 :
5917 2766178 : switch (form)
5918 : {
5919 : case DW_FORM_addr:
5920 42478 : if (!cbargs->silent)
5921 : {
5922 : Dwarf_Addr addr;
5923 42426 : if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
5924 : {
5925 : attrval_out:
5926 0 : if (!cbargs->silent)
5927 0 : error (0, 0, gettext ("cannot get attribute value: %s"),
5928 : dwarf_errmsg (-1));
5929 0 : return DWARF_CB_ABORT;
5930 : }
5931 42426 : char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize,
5932 : addr, addr);
5933 84852 : printf (" %*s%-20s (%s) %s\n",
5934 : (int) (level * 2), "", dwarf_attr_name (attr),
5935 : dwarf_form_name (form), a);
5936 42426 : free (a);
5937 : }
5938 2476218 : break;
5939 :
5940 : case DW_FORM_indirect:
5941 : case DW_FORM_strp:
5942 : case DW_FORM_string:
5943 : case DW_FORM_GNU_strp_alt:
5944 515586 : if (cbargs->silent)
5945 : break;
5946 515440 : const char *str = dwarf_formstring (attrp);
5947 515440 : if (unlikely (str == NULL))
5948 : goto attrval_out;
5949 515440 : printf (" %*s%-20s (%s) \"%s\"\n",
5950 : (int) (level * 2), "", dwarf_attr_name (attr),
5951 : dwarf_form_name (form), str);
5952 : break;
5953 :
5954 : case DW_FORM_ref_addr:
5955 : case DW_FORM_ref_udata:
5956 : case DW_FORM_ref8:
5957 : case DW_FORM_ref4:
5958 : case DW_FORM_ref2:
5959 : case DW_FORM_ref1:
5960 : case DW_FORM_GNU_ref_alt:
5961 657138 : if (cbargs->silent)
5962 : break;
5963 : Dwarf_Die ref;
5964 657004 : if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
5965 : goto attrval_out;
5966 :
5967 657004 : printf (" %*s%-20s (%s) [%6" PRIxMAX "]\n",
5968 : (int) (level * 2), "", dwarf_attr_name (attr),
5969 657004 : dwarf_form_name (form), (uintmax_t) dwarf_dieoffset (&ref));
5970 : break;
5971 :
5972 : case DW_FORM_ref_sig8:
5973 0 : if (cbargs->silent)
5974 : break;
5975 0 : printf (" %*s%-20s (%s) {%6" PRIx64 "}\n",
5976 : (int) (level * 2), "", dwarf_attr_name (attr),
5977 : dwarf_form_name (form),
5978 0 : (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
5979 : break;
5980 :
5981 : case DW_FORM_sec_offset:
5982 : case DW_FORM_udata:
5983 : case DW_FORM_sdata:
5984 : case DW_FORM_data8:
5985 : case DW_FORM_data4:
5986 : case DW_FORM_data2:
5987 : case DW_FORM_data1:;
5988 : Dwarf_Word num;
5989 1378670 : if (unlikely (dwarf_formudata (attrp, &num) != 0))
5990 : goto attrval_out;
5991 :
5992 1378670 : const char *valuestr = NULL;
5993 1378670 : switch (attr)
5994 : {
5995 : /* This case can take either a constant or a loclistptr. */
5996 : case DW_AT_data_member_location:
5997 234907 : if (form != DW_FORM_sec_offset
5998 234907 : && (cbargs->version >= 4
5999 23806 : || (form != DW_FORM_data4 && form != DW_FORM_data8)))
6000 : {
6001 234907 : if (!cbargs->silent)
6002 234907 : printf (" %*s%-20s (%s) %" PRIxMAX "\n",
6003 : (int) (level * 2), "", dwarf_attr_name (attr),
6004 : dwarf_form_name (form), (uintmax_t) num);
6005 : return DWARF_CB_OK;
6006 : }
6007 : /* else fallthrough */
6008 :
6009 : /* These cases always take a loclistptr and no constant. */
6010 : case DW_AT_location:
6011 : case DW_AT_data_location:
6012 : case DW_AT_vtable_elem_location:
6013 : case DW_AT_string_length:
6014 : case DW_AT_use_location:
6015 : case DW_AT_frame_base:
6016 : case DW_AT_return_addr:
6017 : case DW_AT_static_link:
6018 : case DW_AT_GNU_call_site_value:
6019 : case DW_AT_GNU_call_site_data_value:
6020 : case DW_AT_GNU_call_site_target:
6021 : case DW_AT_GNU_call_site_target_clobbered:
6022 : {
6023 131637 : bool nlpt = notice_listptr (section_loc, &known_loclistptr,
6024 87758 : cbargs->addrsize, cbargs->offset_size,
6025 : cbargs->cu, num);
6026 43879 : if (!cbargs->silent)
6027 43863 : printf (" %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n",
6028 : (int) (level * 2), "", dwarf_attr_name (attr),
6029 : dwarf_form_name (form), (uintmax_t) num,
6030 : nlpt ? "" : " <WARNING offset too big>");
6031 : }
6032 : return DWARF_CB_OK;
6033 :
6034 : case DW_AT_ranges:
6035 : {
6036 33522 : bool nlpt = notice_listptr (section_ranges, &known_rangelistptr,
6037 22348 : cbargs->addrsize, cbargs->offset_size,
6038 : cbargs->cu, num);
6039 11174 : if (!cbargs->silent)
6040 11164 : printf (" %*s%-20s (%s) range list [%6" PRIxMAX "]%s\n",
6041 : (int) (level * 2), "", dwarf_attr_name (attr),
6042 : dwarf_form_name (form), (uintmax_t) num,
6043 : nlpt ? "" : " <WARNING offset too big>");
6044 : }
6045 : return DWARF_CB_OK;
6046 :
6047 : case DW_AT_language:
6048 1287 : valuestr = dwarf_lang_name (num);
6049 1287 : break;
6050 : case DW_AT_encoding:
6051 31936 : valuestr = dwarf_encoding_name (num);
6052 15968 : break;
6053 : case DW_AT_accessibility:
6054 0 : valuestr = dwarf_access_name (num);
6055 0 : break;
6056 : case DW_AT_visibility:
6057 0 : valuestr = dwarf_visibility_name (num);
6058 0 : break;
6059 : case DW_AT_virtuality:
6060 0 : valuestr = dwarf_virtuality_name (num);
6061 0 : break;
6062 : case DW_AT_identifier_case:
6063 0 : valuestr = dwarf_identifier_case_name (num);
6064 0 : break;
6065 : case DW_AT_calling_convention:
6066 0 : valuestr = dwarf_calling_convention_name (num);
6067 0 : break;
6068 : case DW_AT_inline:
6069 5906 : valuestr = dwarf_inline_name (num);
6070 2953 : break;
6071 : case DW_AT_ordering:
6072 0 : valuestr = dwarf_ordering_name (num);
6073 0 : break;
6074 : case DW_AT_discr_list:
6075 0 : valuestr = dwarf_discr_list_name (num);
6076 0 : break;
6077 : default:
6078 : /* Nothing. */
6079 : break;
6080 : }
6081 :
6082 1088710 : if (cbargs->silent)
6083 : break;
6084 :
6085 : /* When highpc is in constant form it is relative to lowpc.
6086 : In that case also show the address. */
6087 : Dwarf_Addr highpc;
6088 1088409 : if (attr == DW_AT_high_pc && dwarf_highpc (cbargs->die, &highpc) == 0)
6089 14818 : {
6090 14818 : char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize,
6091 : highpc, highpc);
6092 29636 : printf (" %*s%-20s (%s) %" PRIuMAX " (%s)\n",
6093 : (int) (level * 2), "", dwarf_attr_name (attr),
6094 : dwarf_form_name (form), (uintmax_t) num, a);
6095 14818 : free (a);
6096 : }
6097 : else
6098 : {
6099 1073591 : Dwarf_Sword snum = 0;
6100 1073591 : if (form == DW_FORM_sdata)
6101 1207 : if (unlikely (dwarf_formsdata (attrp, &snum) != 0))
6102 : goto attrval_out;
6103 :
6104 1073591 : if (valuestr == NULL)
6105 : {
6106 2106876 : printf (" %*s%-20s (%s)",
6107 : (int) (level * 2), "", dwarf_attr_name (attr),
6108 : dwarf_form_name (form));
6109 1053438 : if (form == DW_FORM_sdata)
6110 1207 : printf (" %" PRIdMAX "\n", (intmax_t) snum);
6111 : else
6112 1052231 : printf (" %" PRIuMAX "\n", (uintmax_t) num);
6113 : }
6114 : else
6115 : {
6116 40306 : printf (" %*s%-20s (%s) %s",
6117 : (int) (level * 2), "", dwarf_attr_name (attr),
6118 : dwarf_form_name (form), valuestr);
6119 20153 : if (form == DW_FORM_sdata)
6120 0 : printf (" (%" PRIdMAX ")\n", (intmax_t) snum);
6121 : else
6122 20153 : printf (" (%" PRIuMAX ")\n", (uintmax_t) num);
6123 : }
6124 : }
6125 : break;
6126 :
6127 : case DW_FORM_flag:
6128 9081 : if (cbargs->silent)
6129 : break;
6130 : bool flag;
6131 9048 : if (unlikely (dwarf_formflag (attrp, &flag) != 0))
6132 : goto attrval_out;
6133 :
6134 9048 : printf (" %*s%-20s (%s) %s\n",
6135 : (int) (level * 2), "", dwarf_attr_name (attr),
6136 9048 : dwarf_form_name (form), flag ? gettext ("yes") : gettext ("no"));
6137 : break;
6138 :
6139 : case DW_FORM_flag_present:
6140 72488 : if (cbargs->silent)
6141 : break;
6142 72479 : printf (" %*s%-20s (%s) %s\n",
6143 : (int) (level * 2), "", dwarf_attr_name (attr),
6144 : dwarf_form_name (form), gettext ("yes"));
6145 : break;
6146 :
6147 : case DW_FORM_exprloc:
6148 : case DW_FORM_block4:
6149 : case DW_FORM_block2:
6150 : case DW_FORM_block1:
6151 : case DW_FORM_block:
6152 90737 : if (cbargs->silent)
6153 : break;
6154 : Dwarf_Block block;
6155 90701 : if (unlikely (dwarf_formblock (attrp, &block) != 0))
6156 : goto attrval_out;
6157 :
6158 181402 : printf (" %*s%-20s (%s) ",
6159 : (int) (level * 2), "", dwarf_attr_name (attr),
6160 : dwarf_form_name (form));
6161 :
6162 90701 : switch (attr)
6163 : {
6164 : default:
6165 16 : if (form != DW_FORM_exprloc)
6166 : {
6167 16 : print_block (block.length, block.data);
6168 16 : break;
6169 : }
6170 : /* Fall through. */
6171 :
6172 : case DW_AT_location:
6173 : case DW_AT_data_location:
6174 : case DW_AT_data_member_location:
6175 : case DW_AT_vtable_elem_location:
6176 : case DW_AT_string_length:
6177 : case DW_AT_use_location:
6178 : case DW_AT_frame_base:
6179 : case DW_AT_return_addr:
6180 : case DW_AT_static_link:
6181 : case DW_AT_allocated:
6182 : case DW_AT_associated:
6183 : case DW_AT_bit_size:
6184 : case DW_AT_bit_offset:
6185 : case DW_AT_bit_stride:
6186 : case DW_AT_byte_size:
6187 : case DW_AT_byte_stride:
6188 : case DW_AT_count:
6189 : case DW_AT_lower_bound:
6190 : case DW_AT_upper_bound:
6191 : case DW_AT_GNU_call_site_value:
6192 : case DW_AT_GNU_call_site_data_value:
6193 : case DW_AT_GNU_call_site_target:
6194 : case DW_AT_GNU_call_site_target_clobbered:
6195 90685 : putchar ('\n');
6196 181370 : print_ops (cbargs->dwflmod, cbargs->dbg,
6197 90685 : 12 + level * 2, 12 + level * 2,
6198 : cbargs->version, cbargs->addrsize, cbargs->offset_size,
6199 90685 : attrp->cu, block.length, block.data);
6200 90685 : break;
6201 : }
6202 : break;
6203 :
6204 : default:
6205 0 : if (cbargs->silent)
6206 : break;
6207 0 : printf (" %*s%-20s (form: %#x) ???\n",
6208 : (int) (level * 2), "", dwarf_attr_name (attr),
6209 : (int) form);
6210 : break;
6211 : }
6212 :
6213 2476218 : return DWARF_CB_OK;
6214 : }
6215 :
6216 : static void
6217 54 : print_debug_units (Dwfl_Module *dwflmod,
6218 : Ebl *ebl, GElf_Ehdr *ehdr,
6219 : Elf_Scn *scn, GElf_Shdr *shdr,
6220 : Dwarf *dbg, bool debug_types)
6221 : {
6222 54 : const bool silent = !(print_debug_sections & section_info);
6223 108 : const char *secname = section_name (ebl, ehdr, shdr);
6224 :
6225 54 : if (!silent)
6226 44 : printf (gettext ("\
6227 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
6228 44 : elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
6229 :
6230 : /* If the section is empty we don't have to do anything. */
6231 54 : if (!silent && shdr->sh_size == 0)
6232 0 : return;
6233 :
6234 54 : int maxdies = 20;
6235 54 : Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
6236 :
6237 54 : Dwarf_Off offset = 0;
6238 :
6239 : /* New compilation unit. */
6240 : size_t cuhl;
6241 : Dwarf_Half version;
6242 : Dwarf_Off abbroffset;
6243 : uint8_t addrsize;
6244 : uint8_t offsize;
6245 : Dwarf_Off nextcu;
6246 : uint64_t typesig;
6247 : Dwarf_Off typeoff;
6248 : next_cu:
6249 1341 : if (dwarf_next_unit (dbg, offset, &nextcu, &cuhl, &version,
6250 : &abbroffset, &addrsize, &offsize,
6251 : debug_types ? &typesig : NULL,
6252 : debug_types ? &typeoff : NULL) != 0)
6253 : goto do_return;
6254 :
6255 1287 : if (!silent)
6256 : {
6257 1274 : if (debug_types)
6258 0 : printf (gettext (" Type unit at offset %" PRIu64 ":\n"
6259 : " Version: %" PRIu16 ", Abbreviation section offset: %"
6260 : PRIu64 ", Address size: %" PRIu8
6261 : ", Offset size: %" PRIu8
6262 : "\n Type signature: %#" PRIx64
6263 : ", Type offset: %#" PRIx64 "\n"),
6264 : (uint64_t) offset, version, abbroffset, addrsize, offsize,
6265 : typesig, (uint64_t) typeoff);
6266 : else
6267 1274 : printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
6268 : " Version: %" PRIu16 ", Abbreviation section offset: %"
6269 : PRIu64 ", Address size: %" PRIu8
6270 : ", Offset size: %" PRIu8 "\n"),
6271 : (uint64_t) offset, version, abbroffset, addrsize, offsize);
6272 : }
6273 :
6274 1287 : struct attrcb_args args =
6275 : {
6276 : .dwflmod = dwflmod,
6277 : .dbg = dbg,
6278 : .silent = silent,
6279 : .version = version,
6280 : .addrsize = addrsize,
6281 : .offset_size = offsize
6282 : };
6283 :
6284 1287 : offset += cuhl;
6285 :
6286 1287 : int level = 0;
6287 :
6288 1287 : if (unlikely ((debug_types ? dwarf_offdie_types : dwarf_offdie)
6289 : (dbg, offset, &dies[level]) == NULL))
6290 : {
6291 0 : if (!silent)
6292 0 : error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
6293 : " in section '%s': %s"),
6294 : (uint64_t) offset, secname, dwarf_errmsg (-1));
6295 : goto do_return;
6296 : }
6297 :
6298 1287 : args.cu = dies[0].cu;
6299 :
6300 : do
6301 : {
6302 791092 : offset = dwarf_dieoffset (&dies[level]);
6303 791092 : if (unlikely (offset == ~0ul))
6304 : {
6305 0 : if (!silent)
6306 0 : error (0, 0, gettext ("cannot get DIE offset: %s"),
6307 : dwarf_errmsg (-1));
6308 : goto do_return;
6309 : }
6310 :
6311 791092 : int tag = dwarf_tag (&dies[level]);
6312 791092 : if (unlikely (tag == DW_TAG_invalid))
6313 : {
6314 0 : if (!silent)
6315 0 : error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
6316 : " in section '%s': %s"),
6317 : (uint64_t) offset, secname, dwarf_errmsg (-1));
6318 : goto do_return;
6319 : }
6320 :
6321 791092 : if (!silent)
6322 790931 : printf (" [%6" PRIx64 "] %*s%s\n",
6323 : (uint64_t) offset, (int) (level * 2), "",
6324 : dwarf_tag_name (tag));
6325 :
6326 : /* Print the attribute values. */
6327 791092 : args.level = level;
6328 791092 : args.die = &dies[level];
6329 791092 : (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
6330 :
6331 : /* Make room for the next level's DIE. */
6332 791092 : if (level + 1 == maxdies)
6333 0 : dies = (Dwarf_Die *) xrealloc (dies,
6334 0 : (maxdies += 10)
6335 : * sizeof (Dwarf_Die));
6336 :
6337 791092 : int res = dwarf_child (&dies[level], &dies[level + 1]);
6338 791092 : if (res > 0)
6339 : {
6340 791092 : while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
6341 112179 : if (level-- == 0)
6342 : break;
6343 :
6344 680200 : if (unlikely (res == -1))
6345 : {
6346 0 : if (!silent)
6347 0 : error (0, 0, gettext ("cannot get next DIE: %s\n"),
6348 : dwarf_errmsg (-1));
6349 : goto do_return;
6350 : }
6351 : }
6352 110892 : else if (unlikely (res < 0))
6353 : {
6354 0 : if (!silent)
6355 0 : error (0, 0, gettext ("cannot get next DIE: %s"),
6356 : dwarf_errmsg (-1));
6357 : goto do_return;
6358 : }
6359 : else
6360 : ++level;
6361 : }
6362 791092 : while (level >= 0);
6363 :
6364 1287 : offset = nextcu;
6365 1287 : if (offset != 0)
6366 : goto next_cu;
6367 :
6368 : do_return:
6369 54 : free (dies);
6370 : }
6371 :
6372 : static void
6373 54 : print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
6374 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6375 : {
6376 54 : print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
6377 54 : }
6378 :
6379 : static void
6380 0 : print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
6381 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6382 : {
6383 0 : print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
6384 0 : }
6385 :
6386 :
6387 : static void
6388 1 : print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
6389 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6390 : {
6391 3 : printf (gettext ("\
6392 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n\n"),
6393 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6394 1 : (uint64_t) shdr->sh_offset);
6395 :
6396 1 : size_t address_size
6397 1 : = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6398 :
6399 : Dwarf_Off cuoffset;
6400 1 : Dwarf_Off ncuoffset = 0;
6401 : size_t hsize;
6402 5 : while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
6403 : NULL, NULL, NULL) == 0)
6404 : {
6405 : Dwarf_Die cudie;
6406 3 : if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
6407 0 : continue;
6408 :
6409 : size_t nlines;
6410 : Dwarf_Lines *lines;
6411 3 : if (dwarf_getsrclines (&cudie, &lines, &nlines) != 0)
6412 0 : continue;
6413 :
6414 6 : printf (" CU [%" PRIx64 "] %s\n",
6415 : dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
6416 3 : printf (" line:col SBPE* disc isa op address"
6417 : " (Statement Block Prologue Epilogue *End)\n");
6418 3 : const char *last_file = "";
6419 42 : for (size_t n = 0; n < nlines; n++)
6420 : {
6421 39 : Dwarf_Line *line = dwarf_onesrcline (lines, n);
6422 39 : if (line == NULL)
6423 : {
6424 0 : printf (" dwarf_onesrcline: %s\n", dwarf_errmsg (-1));
6425 0 : continue;
6426 : }
6427 : Dwarf_Word mtime, length;
6428 39 : const char *file = dwarf_linesrc (line, &mtime, &length);
6429 39 : if (file == NULL)
6430 : {
6431 0 : printf (" <%s> (mtime: ?, length: ?)\n", dwarf_errmsg (-1));
6432 0 : last_file = "";
6433 : }
6434 39 : else if (strcmp (last_file, file) != 0)
6435 : {
6436 6 : printf (" %s (mtime: %" PRIu64 ", length: %" PRIu64 ")\n",
6437 : file, mtime, length);
6438 3 : last_file = file;
6439 : }
6440 :
6441 : int lineno, colno;
6442 : bool statement, endseq, block, prologue_end, epilogue_begin;
6443 : unsigned int lineop, isa, disc;
6444 : Dwarf_Addr address;
6445 39 : dwarf_lineaddr (line, &address);
6446 39 : dwarf_lineno (line, &lineno);
6447 39 : dwarf_linecol (line, &colno);
6448 39 : dwarf_lineop_index (line, &lineop);
6449 39 : dwarf_linebeginstatement (line, &statement);
6450 39 : dwarf_lineendsequence (line, &endseq);
6451 39 : dwarf_lineblock (line, &block);
6452 39 : dwarf_lineprologueend (line, &prologue_end);
6453 39 : dwarf_lineepiloguebegin (line, &epilogue_begin);
6454 39 : dwarf_lineisa (line, &isa);
6455 39 : dwarf_linediscriminator (line, &disc);
6456 :
6457 : /* End sequence is special, it is one byte past. */
6458 78 : char *a = format_dwarf_addr (dwflmod, address_size,
6459 39 : address - (endseq ? 1 : 0), address);
6460 273 : printf (" %4d:%-3d %c%c%c%c%c %4d %3d %2d %s\n",
6461 : lineno, colno,
6462 39 : (statement ? 'S' : ' '),
6463 39 : (block ? 'B' : ' '),
6464 39 : (prologue_end ? 'P' : ' '),
6465 39 : (epilogue_begin ? 'E' : ' '),
6466 39 : (endseq ? '*' : ' '),
6467 : disc, isa, lineop, a);
6468 39 : free (a);
6469 :
6470 39 : if (endseq)
6471 : printf("\n");
6472 : }
6473 : }
6474 1 : }
6475 :
6476 :
6477 : static void
6478 38 : print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
6479 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6480 : {
6481 38 : if (decodedline)
6482 : {
6483 1 : print_decoded_line_section (dwflmod, ebl, ehdr, scn, shdr, dbg);
6484 1 : return;
6485 : }
6486 :
6487 111 : printf (gettext ("\
6488 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6489 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6490 37 : (uint64_t) shdr->sh_offset);
6491 :
6492 37 : if (shdr->sh_size == 0)
6493 : return;
6494 :
6495 : /* There is no functionality in libdw to read the information in the
6496 : way it is represented here. Hardcode the decoder. */
6497 37 : Elf_Data *data = dbg->sectiondata[IDX_debug_line];
6498 37 : if (unlikely (data == NULL || data->d_buf == NULL))
6499 : {
6500 0 : error (0, 0, gettext ("cannot get line data section data: %s"),
6501 : elf_errmsg (-1));
6502 : return;
6503 : }
6504 :
6505 37 : const unsigned char *linep = (const unsigned char *) data->d_buf;
6506 : const unsigned char *lineendp;
6507 :
6508 1343 : while (linep
6509 1306 : < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
6510 : {
6511 1269 : size_t start_offset = linep - (const unsigned char *) data->d_buf;
6512 :
6513 2538 : printf (gettext ("\nTable at offset %zu:\n"), start_offset);
6514 :
6515 1269 : if (unlikely (linep + 4 > lineendp))
6516 : goto invalid_data;
6517 1287 : Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
6518 1269 : unsigned int length = 4;
6519 1269 : if (unlikely (unit_length == 0xffffffff))
6520 : {
6521 0 : if (unlikely (linep + 8 > lineendp))
6522 : {
6523 : invalid_data:
6524 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
6525 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
6526 0 : return;
6527 : }
6528 0 : unit_length = read_8ubyte_unaligned_inc (dbg, linep);
6529 0 : length = 8;
6530 : }
6531 :
6532 : /* Check whether we have enough room in the section. */
6533 1269 : if (unlikely (unit_length > (size_t) (lineendp - linep)
6534 : || unit_length < 2 + length + 5 * 1))
6535 : goto invalid_data;
6536 1269 : lineendp = linep + unit_length;
6537 :
6538 : /* The next element of the header is the version identifier. */
6539 1269 : uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
6540 :
6541 : /* Next comes the header length. */
6542 : Dwarf_Word header_length;
6543 1269 : if (length == 4)
6544 1287 : header_length = read_4ubyte_unaligned_inc (dbg, linep);
6545 : else
6546 0 : header_length = read_8ubyte_unaligned_inc (dbg, linep);
6547 : //const unsigned char *header_start = linep;
6548 :
6549 : /* Next the minimum instruction length. */
6550 1269 : uint_fast8_t minimum_instr_len = *linep++;
6551 :
6552 : /* Next the maximum operations per instruction, in version 4 format. */
6553 1269 : uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++;
6554 :
6555 : /* Then the flag determining the default value of the is_stmt
6556 : register. */
6557 1269 : uint_fast8_t default_is_stmt = *linep++;
6558 :
6559 : /* Now the line base. */
6560 1269 : int_fast8_t line_base = *((const int_fast8_t *) linep);
6561 1269 : ++linep;
6562 :
6563 : /* And the line range. */
6564 1269 : uint_fast8_t line_range = *linep++;
6565 :
6566 : /* The opcode base. */
6567 1269 : uint_fast8_t opcode_base = *linep++;
6568 :
6569 : /* Print what we got so far. */
6570 2538 : printf (gettext ("\n"
6571 : " Length: %" PRIu64 "\n"
6572 : " DWARF version: %" PRIuFAST16 "\n"
6573 : " Prologue length: %" PRIu64 "\n"
6574 : " Minimum instruction length: %" PRIuFAST8 "\n"
6575 : " Maximum operations per instruction: %" PRIuFAST8 "\n"
6576 : " Initial value if '%s': %" PRIuFAST8 "\n"
6577 : " Line base: %" PRIdFAST8 "\n"
6578 : " Line range: %" PRIuFAST8 "\n"
6579 : " Opcode base: %" PRIuFAST8 "\n"
6580 : "\n"
6581 : "Opcodes:\n"),
6582 : (uint64_t) unit_length, version, (uint64_t) header_length,
6583 : minimum_instr_len, max_ops_per_instr,
6584 : "is_stmt", default_is_stmt, line_base,
6585 : line_range, opcode_base);
6586 :
6587 1269 : if (unlikely (linep + opcode_base - 1 >= lineendp))
6588 : {
6589 : invalid_unit:
6590 0 : error (0, 0,
6591 0 : gettext ("invalid data at offset %tu in section [%zu] '%s'"),
6592 0 : linep - (const unsigned char *) data->d_buf,
6593 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
6594 0 : linep = lineendp;
6595 0 : continue;
6596 : }
6597 1269 : int opcode_base_l10 = 1;
6598 1269 : unsigned int tmp = opcode_base;
6599 3805 : while (tmp > 10)
6600 : {
6601 1267 : tmp /= 10;
6602 1267 : ++opcode_base_l10;
6603 : }
6604 1269 : const uint8_t *standard_opcode_lengths = linep - 1;
6605 16491 : for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
6606 30444 : printf (ngettext (" [%*" PRIuFAST8 "] %hhu argument\n",
6607 : " [%*" PRIuFAST8 "] %hhu arguments\n",
6608 : (int) linep[cnt - 1]),
6609 15222 : opcode_base_l10, cnt, linep[cnt - 1]);
6610 1269 : linep += opcode_base - 1;
6611 1269 : if (unlikely (linep >= lineendp))
6612 : goto invalid_unit;
6613 :
6614 1269 : puts (gettext ("\nDirectory table:"));
6615 10190 : while (*linep != 0)
6616 : {
6617 7652 : unsigned char *endp = memchr (linep, '\0', lineendp - linep);
6618 7652 : if (unlikely (endp == NULL))
6619 : goto invalid_unit;
6620 :
6621 15304 : printf (" %s\n", (char *) linep);
6622 :
6623 7652 : linep = endp + 1;
6624 : }
6625 : /* Skip the final NUL byte. */
6626 1269 : ++linep;
6627 :
6628 1269 : if (unlikely (linep >= lineendp))
6629 : goto invalid_unit;
6630 1269 : puts (gettext ("\nFile name table:\n"
6631 : " Entry Dir Time Size Name"));
6632 23275 : for (unsigned int cnt = 1; *linep != 0; ++cnt)
6633 : {
6634 : /* First comes the file name. */
6635 22006 : char *fname = (char *) linep;
6636 22006 : unsigned char *endp = memchr (fname, '\0', lineendp - linep);
6637 22006 : if (unlikely (endp == NULL))
6638 : goto invalid_unit;
6639 22006 : linep = endp + 1;
6640 :
6641 : /* Then the index. */
6642 : unsigned int diridx;
6643 22006 : if (lineendp - linep < 1)
6644 : goto invalid_unit;
6645 22006 : get_uleb128 (diridx, linep, lineendp);
6646 :
6647 : /* Next comes the modification time. */
6648 : unsigned int mtime;
6649 22006 : if (lineendp - linep < 1)
6650 : goto invalid_unit;
6651 22006 : get_uleb128 (mtime, linep, lineendp);
6652 :
6653 : /* Finally the length of the file. */
6654 : unsigned int fsize;
6655 22006 : if (lineendp - linep < 1)
6656 : goto invalid_unit;
6657 22006 : get_uleb128 (fsize, linep, lineendp);
6658 :
6659 22006 : printf (" %-5u %-5u %-9u %-9u %s\n",
6660 : cnt, diridx, mtime, fsize, fname);
6661 : }
6662 : /* Skip the final NUL byte. */
6663 1269 : ++linep;
6664 :
6665 1269 : puts (gettext ("\nLine number statements:"));
6666 : Dwarf_Word address = 0;
6667 : unsigned int op_index = 0;
6668 1269 : size_t line = 1;
6669 1269 : uint_fast8_t is_stmt = default_is_stmt;
6670 :
6671 : /* Default address value, in case we do not find the CU. */
6672 1269 : size_t address_size
6673 1269 : = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6674 :
6675 : /* Determine the CU this block is for. */
6676 : Dwarf_Off cuoffset;
6677 1269 : Dwarf_Off ncuoffset = 0;
6678 : size_t hsize;
6679 94809 : while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
6680 : NULL, NULL, NULL) == 0)
6681 : {
6682 : Dwarf_Die cudie;
6683 93540 : if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
6684 0 : continue;
6685 : Dwarf_Attribute stmt_list;
6686 93540 : if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
6687 0 : continue;
6688 : Dwarf_Word lineoff;
6689 93540 : if (dwarf_formudata (&stmt_list, &lineoff) != 0)
6690 0 : continue;
6691 93540 : if (lineoff == start_offset)
6692 : {
6693 : /* Found the CU. */
6694 1269 : address_size = cudie.cu->address_size;
6695 1269 : break;
6696 : }
6697 : }
6698 :
6699 : /* Apply the "operation advance" from a special opcode
6700 : or DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */
6701 : unsigned int op_addr_advance;
6702 : bool show_op_index;
6703 : inline void advance_pc (unsigned int op_advance)
6704 : {
6705 316664 : op_addr_advance = minimum_instr_len * ((op_index + op_advance)
6706 158332 : / max_ops_per_instr);
6707 158332 : address += op_advance;
6708 316664 : show_op_index = (op_index > 0 ||
6709 158332 : (op_index + op_advance) % max_ops_per_instr > 0);
6710 158332 : op_index = (op_index + op_advance) % max_ops_per_instr;
6711 : }
6712 :
6713 1269 : if (max_ops_per_instr == 0)
6714 : {
6715 0 : error (0, 0,
6716 0 : gettext ("invalid maximum operations per instruction is zero"));
6717 0 : linep = lineendp;
6718 0 : continue;
6719 : }
6720 :
6721 257573 : while (linep < lineendp)
6722 : {
6723 256304 : size_t offset = linep - (const unsigned char *) data->d_buf;
6724 : unsigned int u128;
6725 : int s128;
6726 :
6727 : /* Read the opcode. */
6728 256304 : unsigned int opcode = *linep++;
6729 :
6730 256304 : printf (" [%6" PRIx64 "]", (uint64_t)offset);
6731 : /* Is this a special opcode? */
6732 256304 : if (likely (opcode >= opcode_base))
6733 : {
6734 117654 : if (unlikely (line_range == 0))
6735 : goto invalid_unit;
6736 :
6737 : /* Yes. Handling this is quite easy since the opcode value
6738 : is computed with
6739 :
6740 : opcode = (desired line increment - line_base)
6741 : + (line_range * address advance) + opcode_base
6742 : */
6743 117654 : int line_increment = (line_base
6744 117654 : + (opcode - opcode_base) % line_range);
6745 :
6746 : /* Perform the increments. */
6747 117654 : line += line_increment;
6748 235308 : advance_pc ((opcode - opcode_base) / line_range);
6749 :
6750 117654 : char *a = format_dwarf_addr (dwflmod, 0, address, address);
6751 117654 : if (show_op_index)
6752 0 : printf (gettext ("\
6753 : special opcode %u: address+%u = %s, op_index = %u, line%+d = %zu\n"),
6754 : opcode, op_addr_advance, a, op_index,
6755 : line_increment, line);
6756 : else
6757 117654 : printf (gettext ("\
6758 : special opcode %u: address+%u = %s, line%+d = %zu\n"),
6759 : opcode, op_addr_advance, a, line_increment, line);
6760 117654 : free (a);
6761 : }
6762 138650 : else if (opcode == 0)
6763 : {
6764 : /* This an extended opcode. */
6765 14778 : if (unlikely (linep + 2 > lineendp))
6766 : goto invalid_unit;
6767 :
6768 : /* The length. */
6769 14778 : unsigned int len = *linep++;
6770 :
6771 14778 : if (unlikely (linep + len > lineendp))
6772 : goto invalid_unit;
6773 :
6774 : /* The sub-opcode. */
6775 14778 : opcode = *linep++;
6776 :
6777 29556 : printf (gettext (" extended opcode %u: "), opcode);
6778 :
6779 14778 : switch (opcode)
6780 : {
6781 : case DW_LNE_end_sequence:
6782 1307 : puts (gettext (" end of sequence"));
6783 :
6784 : /* Reset the registers we care about. */
6785 : address = 0;
6786 : op_index = 0;
6787 1307 : line = 1;
6788 1307 : is_stmt = default_is_stmt;
6789 1307 : break;
6790 :
6791 : case DW_LNE_set_address:
6792 : op_index = 0;
6793 1327 : if (unlikely ((size_t) (lineendp - linep) < address_size))
6794 : goto invalid_unit;
6795 1327 : if (address_size == 4)
6796 17 : address = read_4ubyte_unaligned_inc (dbg, linep);
6797 : else
6798 1322 : address = read_8ubyte_unaligned_inc (dbg, linep);
6799 : {
6800 1327 : char *a = format_dwarf_addr (dwflmod, 0, address, address);
6801 2654 : printf (gettext (" set address to %s\n"), a);
6802 1327 : free (a);
6803 : }
6804 1327 : break;
6805 :
6806 : case DW_LNE_define_file:
6807 : {
6808 0 : char *fname = (char *) linep;
6809 0 : unsigned char *endp = memchr (linep, '\0',
6810 0 : lineendp - linep);
6811 0 : if (unlikely (endp == NULL))
6812 : goto invalid_unit;
6813 0 : linep = endp + 1;
6814 :
6815 : unsigned int diridx;
6816 0 : if (lineendp - linep < 1)
6817 : goto invalid_unit;
6818 0 : get_uleb128 (diridx, linep, lineendp);
6819 : Dwarf_Word mtime;
6820 0 : if (lineendp - linep < 1)
6821 : goto invalid_unit;
6822 0 : get_uleb128 (mtime, linep, lineendp);
6823 : Dwarf_Word filelength;
6824 0 : if (lineendp - linep < 1)
6825 : goto invalid_unit;
6826 0 : get_uleb128 (filelength, linep, lineendp);
6827 :
6828 0 : printf (gettext ("\
6829 : define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
6830 : diridx, (uint64_t) mtime, (uint64_t) filelength,
6831 : fname);
6832 : }
6833 : break;
6834 :
6835 : case DW_LNE_set_discriminator:
6836 : /* Takes one ULEB128 parameter, the discriminator. */
6837 12144 : if (unlikely (standard_opcode_lengths[opcode] != 1))
6838 : goto invalid_unit;
6839 :
6840 12144 : get_uleb128 (u128, linep, lineendp);
6841 12144 : printf (gettext (" set discriminator to %u\n"), u128);
6842 : break;
6843 :
6844 : default:
6845 : /* Unknown, ignore it. */
6846 0 : puts (gettext (" unknown opcode"));
6847 0 : linep += len - 1;
6848 0 : break;
6849 : }
6850 : }
6851 123872 : else if (opcode <= DW_LNS_set_isa)
6852 : {
6853 : /* This is a known standard opcode. */
6854 123872 : switch (opcode)
6855 : {
6856 : case DW_LNS_copy:
6857 : /* Takes no argument. */
6858 8375 : puts (gettext (" copy"));
6859 8375 : break;
6860 :
6861 : case DW_LNS_advance_pc:
6862 : /* Takes one uleb128 parameter which is added to the
6863 : address. */
6864 12530 : get_uleb128 (u128, linep, lineendp);
6865 12530 : advance_pc (u128);
6866 : {
6867 12530 : char *a = format_dwarf_addr (dwflmod, 0, address, address);
6868 12530 : if (show_op_index)
6869 0 : printf (gettext ("\
6870 : advance address by %u to %s, op_index to %u\n"),
6871 : op_addr_advance, a, op_index);
6872 : else
6873 12530 : printf (gettext (" advance address by %u to %s\n"),
6874 : op_addr_advance, a);
6875 12530 : free (a);
6876 : }
6877 12530 : break;
6878 :
6879 : case DW_LNS_advance_line:
6880 : /* Takes one sleb128 parameter which is added to the
6881 : line. */
6882 49875 : get_sleb128 (s128, linep, lineendp);
6883 49875 : line += s128;
6884 49875 : printf (gettext ("\
6885 : advance line by constant %d to %" PRId64 "\n"),
6886 : s128, (int64_t) line);
6887 : break;
6888 :
6889 : case DW_LNS_set_file:
6890 : /* Takes one uleb128 parameter which is stored in file. */
6891 19830 : get_uleb128 (u128, linep, lineendp);
6892 19830 : printf (gettext (" set file to %" PRIu64 "\n"),
6893 : (uint64_t) u128);
6894 : break;
6895 :
6896 : case DW_LNS_set_column:
6897 : /* Takes one uleb128 parameter which is stored in column. */
6898 0 : if (unlikely (standard_opcode_lengths[opcode] != 1))
6899 : goto invalid_unit;
6900 :
6901 0 : get_uleb128 (u128, linep, lineendp);
6902 0 : printf (gettext (" set column to %" PRIu64 "\n"),
6903 : (uint64_t) u128);
6904 : break;
6905 :
6906 : case DW_LNS_negate_stmt:
6907 : /* Takes no argument. */
6908 5114 : is_stmt = 1 - is_stmt;
6909 5114 : printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
6910 : "is_stmt", is_stmt);
6911 : break;
6912 :
6913 : case DW_LNS_set_basic_block:
6914 : /* Takes no argument. */
6915 0 : puts (gettext (" set basic block flag"));
6916 0 : break;
6917 :
6918 : case DW_LNS_const_add_pc:
6919 : /* Takes no argument. */
6920 :
6921 28148 : if (unlikely (line_range == 0))
6922 : goto invalid_unit;
6923 :
6924 56296 : advance_pc ((255 - opcode_base) / line_range);
6925 : {
6926 28148 : char *a = format_dwarf_addr (dwflmod, 0, address, address);
6927 28148 : if (show_op_index)
6928 0 : printf (gettext ("\
6929 : advance address by constant %u to %s, op_index to %u\n"),
6930 : op_addr_advance, a, op_index);
6931 : else
6932 28148 : printf (gettext ("\
6933 : advance address by constant %u to %s\n"),
6934 : op_addr_advance, a);
6935 28148 : free (a);
6936 : }
6937 28148 : break;
6938 :
6939 : case DW_LNS_fixed_advance_pc:
6940 : /* Takes one 16 bit parameter which is added to the
6941 : address. */
6942 0 : if (unlikely (standard_opcode_lengths[opcode] != 1))
6943 : goto invalid_unit;
6944 :
6945 0 : u128 = read_2ubyte_unaligned_inc (dbg, linep);
6946 0 : address += u128;
6947 : op_index = 0;
6948 : {
6949 0 : char *a = format_dwarf_addr (dwflmod, 0, address, address);
6950 0 : printf (gettext ("\
6951 : advance address by fixed value %u to %s\n"),
6952 : u128, a);
6953 0 : free (a);
6954 : }
6955 0 : break;
6956 :
6957 : case DW_LNS_set_prologue_end:
6958 : /* Takes no argument. */
6959 0 : puts (gettext (" set prologue end flag"));
6960 0 : break;
6961 :
6962 : case DW_LNS_set_epilogue_begin:
6963 : /* Takes no argument. */
6964 0 : puts (gettext (" set epilogue begin flag"));
6965 0 : break;
6966 :
6967 : case DW_LNS_set_isa:
6968 : /* Takes one uleb128 parameter which is stored in isa. */
6969 0 : if (unlikely (standard_opcode_lengths[opcode] != 1))
6970 : goto invalid_unit;
6971 :
6972 0 : get_uleb128 (u128, linep, lineendp);
6973 0 : printf (gettext (" set isa to %u\n"), u128);
6974 : break;
6975 : }
6976 : }
6977 : else
6978 : {
6979 : /* This is a new opcode the generator but not we know about.
6980 : Read the parameters associated with it but then discard
6981 : everything. Read all the parameters for this opcode. */
6982 0 : printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
6983 : " unknown opcode with %" PRIu8 " parameters:",
6984 : standard_opcode_lengths[opcode]),
6985 0 : standard_opcode_lengths[opcode]);
6986 0 : for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
6987 : {
6988 0 : get_uleb128 (u128, linep, lineendp);
6989 0 : if (n != standard_opcode_lengths[opcode])
6990 0 : putc_unlocked (',', stdout);
6991 0 : printf (" %u", u128);
6992 : }
6993 :
6994 : /* Next round, ignore this opcode. */
6995 0 : continue;
6996 : }
6997 : }
6998 : }
6999 :
7000 : /* There must only be one data block. */
7001 37 : assert (elf_getdata (scn, data) == NULL);
7002 : }
7003 :
7004 :
7005 : static void
7006 30 : print_debug_loc_section (Dwfl_Module *dwflmod,
7007 : Ebl *ebl, GElf_Ehdr *ehdr,
7008 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7009 : {
7010 30 : Elf_Data *data = dbg->sectiondata[IDX_debug_loc];
7011 :
7012 30 : if (unlikely (data == NULL))
7013 : {
7014 0 : error (0, 0, gettext ("cannot get .debug_loc content: %s"),
7015 : elf_errmsg (-1));
7016 0 : return;
7017 : }
7018 :
7019 90 : printf (gettext ("\
7020 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
7021 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7022 30 : (uint64_t) shdr->sh_offset);
7023 :
7024 60 : sort_listptr (&known_loclistptr, "loclistptr");
7025 30 : size_t listptr_idx = 0;
7026 :
7027 30 : uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
7028 30 : uint_fast8_t offset_size = 4;
7029 :
7030 30 : bool first = true;
7031 30 : struct Dwarf_CU *cu = NULL;
7032 30 : Dwarf_Addr base = 0;
7033 30 : unsigned char *readp = data->d_buf;
7034 30 : unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
7035 206935 : while (readp < endp)
7036 : {
7037 206875 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
7038 :
7039 206875 : if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx,
7040 : &address_size, &offset_size, &base,
7041 : &cu, offset, &readp, endp))
7042 0 : continue;
7043 :
7044 206875 : if (unlikely (data->d_size - offset < (size_t) address_size * 2))
7045 : {
7046 0 : printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
7047 : break;
7048 : }
7049 :
7050 : Dwarf_Addr begin;
7051 : Dwarf_Addr end;
7052 206875 : if (address_size == 8)
7053 : {
7054 206875 : begin = read_8ubyte_unaligned_inc (dbg, readp);
7055 206875 : end = read_8ubyte_unaligned_inc (dbg, readp);
7056 : }
7057 : else
7058 : {
7059 0 : begin = read_4ubyte_unaligned_inc (dbg, readp);
7060 0 : end = read_4ubyte_unaligned_inc (dbg, readp);
7061 0 : if (begin == (Dwarf_Addr) (uint32_t) -1)
7062 0 : begin = (Dwarf_Addr) -1l;
7063 : }
7064 :
7065 206875 : if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
7066 : {
7067 0 : char *b = format_dwarf_addr (dwflmod, address_size, end, end);
7068 0 : printf (gettext (" [%6tx] base address %s\n"), offset, b);
7069 0 : free (b);
7070 0 : base = end;
7071 : }
7072 206875 : else if (begin == 0 && end == 0) /* End of list entry. */
7073 : {
7074 42376 : if (first)
7075 0 : printf (gettext (" [%6tx] empty list\n"), offset);
7076 : first = true;
7077 : }
7078 : else
7079 : {
7080 : /* We have a location expression entry. */
7081 164499 : uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
7082 :
7083 164499 : char *b = format_dwarf_addr (dwflmod, address_size, base + begin,
7084 : begin);
7085 164499 : char *e = format_dwarf_addr (dwflmod, address_size, base + end,
7086 : end);
7087 :
7088 164499 : if (first) /* First entry in a list. */
7089 42376 : printf (gettext (" [%6tx] %s..%s"), offset, b, e);
7090 : else
7091 122123 : printf (gettext (" %s..%s"), b, e);
7092 :
7093 164499 : free (b);
7094 164499 : free (e);
7095 :
7096 164499 : if (endp - readp <= (ptrdiff_t) len)
7097 : {
7098 0 : fputs (gettext (" <INVALID DATA>\n"), stdout);
7099 0 : break;
7100 : }
7101 :
7102 164499 : print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
7103 : 3 /*XXX*/, address_size, offset_size, cu, len, readp);
7104 :
7105 164499 : first = false;
7106 164499 : readp += len;
7107 : }
7108 : }
7109 : }
7110 :
7111 : struct mac_culist
7112 : {
7113 : Dwarf_Die die;
7114 : Dwarf_Off offset;
7115 : Dwarf_Files *files;
7116 : struct mac_culist *next;
7117 : };
7118 :
7119 :
7120 : static int
7121 0 : mac_compare (const void *p1, const void *p2)
7122 : {
7123 0 : struct mac_culist *m1 = (struct mac_culist *) p1;
7124 0 : struct mac_culist *m2 = (struct mac_culist *) p2;
7125 :
7126 0 : if (m1->offset < m2->offset)
7127 : return -1;
7128 0 : if (m1->offset > m2->offset)
7129 : return 1;
7130 0 : return 0;
7131 : }
7132 :
7133 :
7134 : static void
7135 0 : print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
7136 : Ebl *ebl, GElf_Ehdr *ehdr,
7137 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7138 : {
7139 0 : printf (gettext ("\
7140 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
7141 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7142 0 : (uint64_t) shdr->sh_offset);
7143 0 : putc_unlocked ('\n', stdout);
7144 :
7145 : /* There is no function in libdw to iterate over the raw content of
7146 : the section but it is easy enough to do. */
7147 0 : Elf_Data *data = dbg->sectiondata[IDX_debug_macinfo];
7148 0 : if (unlikely (data == NULL || data->d_buf == NULL))
7149 : {
7150 0 : error (0, 0, gettext ("cannot get macro information section data: %s"),
7151 : elf_errmsg (-1));
7152 0 : return;
7153 : }
7154 :
7155 : /* Get the source file information for all CUs. */
7156 : Dwarf_Off offset;
7157 0 : Dwarf_Off ncu = 0;
7158 : size_t hsize;
7159 0 : struct mac_culist *culist = NULL;
7160 0 : size_t nculist = 0;
7161 0 : while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
7162 : {
7163 : Dwarf_Die cudie;
7164 0 : if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
7165 0 : continue;
7166 :
7167 : Dwarf_Attribute attr;
7168 0 : if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
7169 0 : continue;
7170 :
7171 : Dwarf_Word macoff;
7172 0 : if (dwarf_formudata (&attr, &macoff) != 0)
7173 0 : continue;
7174 :
7175 0 : struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
7176 0 : newp->die = cudie;
7177 0 : newp->offset = macoff;
7178 0 : newp->files = NULL;
7179 0 : newp->next = culist;
7180 0 : culist = newp;
7181 0 : ++nculist;
7182 : }
7183 :
7184 : /* Convert the list into an array for easier consumption. */
7185 0 : struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
7186 : * sizeof (*cus));
7187 : /* Add sentinel. */
7188 0 : cus[nculist].offset = data->d_size;
7189 0 : cus[nculist].files = (Dwarf_Files *) -1l;
7190 0 : if (nculist > 0)
7191 : {
7192 0 : for (size_t cnt = nculist - 1; culist != NULL; --cnt)
7193 : {
7194 0 : assert (cnt < nculist);
7195 0 : cus[cnt] = *culist;
7196 0 : culist = culist->next;
7197 : }
7198 :
7199 : /* Sort the array according to the offset in the .debug_macinfo
7200 : section. Note we keep the sentinel at the end. */
7201 0 : qsort (cus, nculist, sizeof (*cus), mac_compare);
7202 : }
7203 :
7204 0 : const unsigned char *readp = (const unsigned char *) data->d_buf;
7205 0 : const unsigned char *readendp = readp + data->d_size;
7206 0 : int level = 1;
7207 :
7208 0 : while (readp < readendp)
7209 : {
7210 0 : unsigned int opcode = *readp++;
7211 : unsigned int u128;
7212 : unsigned int u128_2;
7213 : const unsigned char *endp;
7214 :
7215 0 : switch (opcode)
7216 : {
7217 : case DW_MACINFO_define:
7218 : case DW_MACINFO_undef:
7219 : case DW_MACINFO_vendor_ext:
7220 : /* For the first two opcodes the parameters are
7221 : line, string
7222 : For the latter
7223 : number, string.
7224 : We can treat these cases together. */
7225 0 : get_uleb128 (u128, readp, readendp);
7226 :
7227 0 : endp = memchr (readp, '\0', readendp - readp);
7228 0 : if (unlikely (endp == NULL))
7229 : {
7230 0 : printf (gettext ("\
7231 : %*s*** non-terminated string at end of section"),
7232 : level, "");
7233 : return;
7234 : }
7235 :
7236 0 : if (opcode == DW_MACINFO_define)
7237 0 : printf ("%*s#define %s, line %u\n",
7238 : level, "", (char *) readp, u128);
7239 0 : else if (opcode == DW_MACINFO_undef)
7240 0 : printf ("%*s#undef %s, line %u\n",
7241 : level, "", (char *) readp, u128);
7242 : else
7243 0 : printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
7244 :
7245 0 : readp = endp + 1;
7246 0 : break;
7247 :
7248 : case DW_MACINFO_start_file:
7249 : /* The two parameters are line and file index, in this order. */
7250 0 : get_uleb128 (u128, readp, readendp);
7251 0 : if (readendp - readp < 1)
7252 : {
7253 0 : printf (gettext ("\
7254 : %*s*** missing DW_MACINFO_start_file argument at end of section"),
7255 : level, "");
7256 : return;
7257 : }
7258 0 : get_uleb128 (u128_2, readp, readendp);
7259 :
7260 : /* Find the CU DIE for this file. */
7261 0 : size_t macoff = readp - (const unsigned char *) data->d_buf;
7262 0 : const char *fname = "???";
7263 0 : if (macoff >= cus[0].offset)
7264 : {
7265 0 : while (macoff >= cus[1].offset && cus[1].offset != data->d_size)
7266 0 : ++cus;
7267 :
7268 0 : if (cus[0].files == NULL
7269 0 : && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
7270 0 : cus[0].files = (Dwarf_Files *) -1l;
7271 :
7272 0 : if (cus[0].files != (Dwarf_Files *) -1l)
7273 0 : fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
7274 0 : ?: "???");
7275 : }
7276 :
7277 0 : printf ("%*sstart_file %u, [%u] %s\n",
7278 : level, "", u128, u128_2, fname);
7279 0 : ++level;
7280 0 : break;
7281 :
7282 : case DW_MACINFO_end_file:
7283 0 : --level;
7284 : printf ("%*send_file\n", level, "");
7285 : /* Nothing more to do. */
7286 : break;
7287 :
7288 : default:
7289 : // XXX gcc seems to generate files with a trailing zero.
7290 0 : if (unlikely (opcode != 0 || readp != readendp))
7291 : printf ("%*s*** invalid opcode %u\n", level, "", opcode);
7292 : break;
7293 : }
7294 : }
7295 : }
7296 :
7297 :
7298 : static void
7299 3 : print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
7300 : Ebl *ebl, GElf_Ehdr *ehdr,
7301 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7302 : {
7303 9 : printf (gettext ("\
7304 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
7305 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7306 3 : (uint64_t) shdr->sh_offset);
7307 6 : putc_unlocked ('\n', stdout);
7308 :
7309 3 : Elf_Data *data = dbg->sectiondata[IDX_debug_macro];
7310 3 : if (unlikely (data == NULL || data->d_buf == NULL))
7311 : {
7312 0 : error (0, 0, gettext ("cannot get macro information section data: %s"),
7313 : elf_errmsg (-1));
7314 0 : return;
7315 : }
7316 :
7317 : /* Get the source file information for all CUs. Uses same
7318 : datastructure as macinfo. But uses offset field to directly
7319 : match .debug_line offset. And just stored in a list. */
7320 : Dwarf_Off offset;
7321 3 : Dwarf_Off ncu = 0;
7322 : size_t hsize;
7323 3 : struct mac_culist *culist = NULL;
7324 3 : size_t nculist = 0;
7325 10 : while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
7326 : {
7327 : Dwarf_Die cudie;
7328 4 : if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
7329 0 : continue;
7330 :
7331 : Dwarf_Attribute attr;
7332 4 : if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL)
7333 0 : continue;
7334 :
7335 : Dwarf_Word lineoff;
7336 4 : if (dwarf_formudata (&attr, &lineoff) != 0)
7337 0 : continue;
7338 :
7339 4 : struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
7340 4 : newp->die = cudie;
7341 4 : newp->offset = lineoff;
7342 4 : newp->files = NULL;
7343 4 : newp->next = culist;
7344 4 : culist = newp;
7345 4 : ++nculist;
7346 : }
7347 :
7348 3 : const unsigned char *readp = (const unsigned char *) data->d_buf;
7349 3 : const unsigned char *readendp = readp + data->d_size;
7350 :
7351 14 : while (readp < readendp)
7352 : {
7353 16 : printf (gettext (" Offset: 0x%" PRIx64 "\n"),
7354 8 : (uint64_t) (readp - (const unsigned char *) data->d_buf));
7355 :
7356 : // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
7357 : // optional vendor extension macro entry table.
7358 8 : if (readp + 2 > readendp)
7359 : {
7360 : invalid_data:
7361 0 : error (0, 0, gettext ("invalid data"));
7362 0 : return;
7363 : }
7364 8 : const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
7365 16 : printf (gettext (" Version: %" PRIu16 "\n"), vers);
7366 :
7367 : // Version 4 is the GNU extension for DWARF4. DWARF5 will use version
7368 : // 5 when it gets standardized.
7369 8 : if (vers != 4)
7370 : {
7371 0 : printf (gettext (" unknown version, cannot parse section\n"));
7372 : return;
7373 : }
7374 :
7375 8 : if (readp + 1 > readendp)
7376 : goto invalid_data;
7377 8 : const unsigned char flag = *readp++;
7378 16 : printf (gettext (" Flag: 0x%" PRIx8 "\n"), flag);
7379 :
7380 8 : unsigned int offset_len = (flag & 0x01) ? 8 : 4;
7381 16 : printf (gettext (" Offset length: %" PRIu8 "\n"), offset_len);
7382 8 : Dwarf_Off line_offset = -1;
7383 8 : if (flag & 0x02)
7384 : {
7385 4 : if (offset_len == 8)
7386 0 : line_offset = read_8ubyte_unaligned_inc (dbg, readp);
7387 : else
7388 4 : line_offset = read_4ubyte_unaligned_inc (dbg, readp);
7389 4 : printf (gettext (" .debug_line offset: 0x%" PRIx64 "\n"),
7390 : line_offset);
7391 : }
7392 :
7393 : const unsigned char *vendor[DW_MACRO_GNU_hi_user - DW_MACRO_GNU_lo_user];
7394 8 : memset (vendor, 0, sizeof vendor);
7395 8 : if (flag & 0x04)
7396 : {
7397 : // 1 byte length, for each item, 1 byte opcode, uleb128 number
7398 : // of arguments, for each argument 1 byte form code.
7399 0 : if (readp + 1 > readendp)
7400 : goto invalid_data;
7401 0 : unsigned int tlen = *readp++;
7402 0 : printf (gettext (" extension opcode table, %" PRIu8 " items:\n"),
7403 : tlen);
7404 0 : for (unsigned int i = 0; i < tlen; i++)
7405 : {
7406 0 : if (readp + 1 > readendp)
7407 : goto invalid_data;
7408 0 : unsigned int opcode = *readp++;
7409 0 : printf (gettext (" [%" PRIx8 "]"), opcode);
7410 0 : if (opcode < DW_MACRO_GNU_lo_user
7411 0 : || opcode > DW_MACRO_GNU_hi_user)
7412 : goto invalid_data;
7413 : // Record the start of description for this vendor opcode.
7414 : // uleb128 nr args, 1 byte per arg form.
7415 0 : vendor[opcode - DW_MACRO_GNU_lo_user] = readp;
7416 0 : if (readp + 1 > readendp)
7417 : goto invalid_data;
7418 0 : unsigned int args = *readp++;
7419 0 : if (args > 0)
7420 : {
7421 0 : printf (gettext (" %" PRIu8 " arguments:"), args);
7422 0 : while (args > 0)
7423 : {
7424 0 : if (readp + 1 > readendp)
7425 : goto invalid_data;
7426 0 : unsigned int form = *readp++;
7427 0 : printf (" %s", dwarf_form_string (form));
7428 0 : if (form != DW_FORM_data1
7429 0 : && form != DW_FORM_data2
7430 : && form != DW_FORM_data4
7431 0 : && form != DW_FORM_data8
7432 0 : && form != DW_FORM_sdata
7433 0 : && form != DW_FORM_udata
7434 : && form != DW_FORM_block
7435 0 : && form != DW_FORM_block1
7436 : && form != DW_FORM_block2
7437 0 : && form != DW_FORM_block4
7438 0 : && form != DW_FORM_flag
7439 0 : && form != DW_FORM_string
7440 0 : && form != DW_FORM_strp
7441 0 : && form != DW_FORM_sec_offset)
7442 : goto invalid_data;
7443 0 : args--;
7444 0 : if (args > 0)
7445 : putchar_unlocked (',');
7446 : }
7447 : }
7448 : else
7449 0 : printf (gettext (" no arguments."));
7450 0 : putchar_unlocked ('\n');
7451 : }
7452 : }
7453 8 : putchar_unlocked ('\n');
7454 :
7455 8 : int level = 1;
7456 8 : if (readp + 1 > readendp)
7457 : goto invalid_data;
7458 8 : unsigned int opcode = *readp++;
7459 743 : while (opcode != 0)
7460 : {
7461 : unsigned int u128;
7462 : unsigned int u128_2;
7463 : const unsigned char *endp;
7464 : uint64_t off;
7465 :
7466 727 : switch (opcode)
7467 : {
7468 : case DW_MACRO_GNU_start_file:
7469 6 : get_uleb128 (u128, readp, readendp);
7470 6 : if (readp >= readendp)
7471 : goto invalid_data;
7472 6 : get_uleb128 (u128_2, readp, readendp);
7473 :
7474 : /* Find the CU DIE that matches this line offset. */
7475 6 : const char *fname = "???";
7476 6 : if (line_offset != (Dwarf_Off) -1)
7477 : {
7478 : struct mac_culist *cu = culist;
7479 8 : while (cu != NULL && line_offset != cu->offset)
7480 2 : cu = cu->next;
7481 6 : if (cu != NULL)
7482 : {
7483 6 : if (cu->files == NULL
7484 4 : && dwarf_getsrcfiles (&cu->die, &cu->files,
7485 : NULL) != 0)
7486 0 : cu->files = (Dwarf_Files *) -1l;
7487 :
7488 6 : if (cu->files != (Dwarf_Files *) -1l)
7489 6 : fname = (dwarf_filesrc (cu->files, u128_2,
7490 6 : NULL, NULL) ?: "???");
7491 : }
7492 : }
7493 6 : printf ("%*sstart_file %u, [%u] %s\n",
7494 : level, "", u128, u128_2, fname);
7495 6 : ++level;
7496 6 : break;
7497 :
7498 : case DW_MACRO_GNU_end_file:
7499 6 : --level;
7500 : printf ("%*send_file\n", level, "");
7501 : break;
7502 :
7503 : case DW_MACRO_GNU_define:
7504 1 : get_uleb128 (u128, readp, readendp);
7505 1 : endp = memchr (readp, '\0', readendp - readp);
7506 1 : if (endp == NULL)
7507 : goto invalid_data;
7508 2 : printf ("%*s#define %s, line %u\n",
7509 : level, "", readp, u128);
7510 1 : readp = endp + 1;
7511 1 : break;
7512 :
7513 : case DW_MACRO_GNU_undef:
7514 0 : get_uleb128 (u128, readp, readendp);
7515 0 : endp = memchr (readp, '\0', readendp - readp);
7516 0 : if (endp == NULL)
7517 : goto invalid_data;
7518 0 : printf ("%*s#undef %s, line %u\n",
7519 : level, "", readp, u128);
7520 0 : readp = endp + 1;
7521 0 : break;
7522 :
7523 : case DW_MACRO_GNU_define_indirect:
7524 707 : get_uleb128 (u128, readp, readendp);
7525 707 : if (readp + offset_len > readendp)
7526 : goto invalid_data;
7527 707 : if (offset_len == 8)
7528 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
7529 : else
7530 707 : off = read_4ubyte_unaligned_inc (dbg, readp);
7531 707 : printf ("%*s#define %s, line %u (indirect)\n",
7532 : level, "", dwarf_getstring (dbg, off, NULL), u128);
7533 : break;
7534 :
7535 : case DW_MACRO_GNU_undef_indirect:
7536 1 : get_uleb128 (u128, readp, readendp);
7537 1 : if (readp + offset_len > readendp)
7538 : goto invalid_data;
7539 1 : if (offset_len == 8)
7540 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
7541 : else
7542 1 : off = read_4ubyte_unaligned_inc (dbg, readp);
7543 1 : printf ("%*s#undef %s, line %u (indirect)\n",
7544 : level, "", dwarf_getstring (dbg, off, NULL), u128);
7545 : break;
7546 :
7547 : case DW_MACRO_GNU_transparent_include:
7548 6 : if (readp + offset_len > readendp)
7549 : goto invalid_data;
7550 6 : if (offset_len == 8)
7551 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
7552 : else
7553 6 : off = read_4ubyte_unaligned_inc (dbg, readp);
7554 : printf ("%*s#include offset 0x%" PRIx64 "\n",
7555 : level, "", off);
7556 : break;
7557 :
7558 : default:
7559 0 : printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
7560 0 : if (opcode < DW_MACRO_GNU_lo_user
7561 : || opcode > DW_MACRO_GNU_lo_user
7562 0 : || vendor[opcode - DW_MACRO_GNU_lo_user] == NULL)
7563 : goto invalid_data;
7564 :
7565 : const unsigned char *op_desc;
7566 0 : op_desc = vendor[opcode - DW_MACRO_GNU_lo_user];
7567 :
7568 : // Just skip the arguments, we cannot really interpret them,
7569 : // but print as much as we can.
7570 0 : unsigned int args = *op_desc++;
7571 0 : while (args > 0)
7572 : {
7573 0 : unsigned int form = *op_desc++;
7574 : Dwarf_Word val;
7575 0 : switch (form)
7576 : {
7577 : case DW_FORM_data1:
7578 0 : if (readp + 1 > readendp)
7579 : goto invalid_data;
7580 0 : val = *readp++;
7581 0 : printf (" %" PRIx8, (unsigned int) val);
7582 : break;
7583 :
7584 : case DW_FORM_data2:
7585 0 : if (readp + 2 > readendp)
7586 : goto invalid_data;
7587 0 : val = read_2ubyte_unaligned_inc (dbg, readp);
7588 0 : printf(" %" PRIx16, (unsigned int) val);
7589 : break;
7590 :
7591 : case DW_FORM_data4:
7592 0 : if (readp + 4 > readendp)
7593 : goto invalid_data;
7594 0 : val = read_4ubyte_unaligned_inc (dbg, readp);
7595 0 : printf (" %" PRIx32, (unsigned int) val);
7596 : break;
7597 :
7598 : case DW_FORM_data8:
7599 0 : if (readp + 8 > readendp)
7600 : goto invalid_data;
7601 0 : val = read_8ubyte_unaligned_inc (dbg, readp);
7602 : printf (" %" PRIx64, val);
7603 : break;
7604 :
7605 : case DW_FORM_sdata:
7606 0 : get_sleb128 (val, readp, readendp);
7607 : printf (" %" PRIx64, val);
7608 : break;
7609 :
7610 : case DW_FORM_udata:
7611 0 : get_uleb128 (val, readp, readendp);
7612 : printf (" %" PRIx64, val);
7613 : break;
7614 :
7615 : case DW_FORM_block:
7616 0 : get_uleb128 (val, readp, readendp);
7617 0 : printf (" block[%" PRIu64 "]", val);
7618 0 : if (readp + val > readendp)
7619 : goto invalid_data;
7620 0 : readp += val;
7621 0 : break;
7622 :
7623 : case DW_FORM_block1:
7624 0 : if (readp + 1 > readendp)
7625 : goto invalid_data;
7626 0 : val = *readp++;
7627 0 : printf (" block[%" PRIu64 "]", val);
7628 0 : if (readp + val > readendp)
7629 : goto invalid_data;
7630 : break;
7631 :
7632 : case DW_FORM_block2:
7633 0 : if (readp + 2 > readendp)
7634 : goto invalid_data;
7635 0 : val = read_2ubyte_unaligned_inc (dbg, readp);
7636 0 : printf (" block[%" PRIu64 "]", val);
7637 0 : if (readp + val > readendp)
7638 : goto invalid_data;
7639 : break;
7640 :
7641 : case DW_FORM_block4:
7642 0 : if (readp + 2 > readendp)
7643 : goto invalid_data;
7644 0 : val =read_4ubyte_unaligned_inc (dbg, readp);
7645 0 : printf (" block[%" PRIu64 "]", val);
7646 0 : if (readp + val > readendp)
7647 : goto invalid_data;
7648 : break;
7649 :
7650 : case DW_FORM_flag:
7651 0 : if (readp + 1 > readendp)
7652 : goto invalid_data;
7653 0 : val = *readp++;
7654 0 : printf (" %s", val != 0 ? gettext ("yes") : gettext ("no"));
7655 : break;
7656 :
7657 : case DW_FORM_string:
7658 0 : endp = memchr (readp, '\0', readendp - readp);
7659 0 : if (endp == NULL)
7660 : goto invalid_data;
7661 0 : printf (" %s", readp);
7662 0 : readp = endp + 1;
7663 0 : break;
7664 :
7665 : case DW_FORM_strp:
7666 0 : if (readp + offset_len > readendp)
7667 : goto invalid_data;
7668 0 : if (offset_len == 8)
7669 0 : val = read_8ubyte_unaligned_inc (dbg, readp);
7670 : else
7671 0 : val = read_4ubyte_unaligned_inc (dbg, readp);
7672 0 : printf (" %s", dwarf_getstring (dbg, val, NULL));
7673 : break;
7674 :
7675 : case DW_FORM_sec_offset:
7676 0 : if (readp + offset_len > readendp)
7677 : goto invalid_data;
7678 0 : if (offset_len == 8)
7679 0 : val = read_8ubyte_unaligned_inc (dbg, readp);
7680 : else
7681 0 : val = read_4ubyte_unaligned_inc (dbg, readp);
7682 : printf (" %" PRIx64, val);
7683 : break;
7684 :
7685 : default:
7686 0 : error (0, 0, gettext ("vendor opcode not verified?"));
7687 : return;
7688 : }
7689 :
7690 0 : args--;
7691 0 : if (args > 0)
7692 : putchar_unlocked (',');
7693 : }
7694 : putchar_unlocked ('\n');
7695 : }
7696 :
7697 727 : if (readp + 1 > readendp)
7698 : goto invalid_data;
7699 727 : opcode = *readp++;
7700 727 : if (opcode == 0)
7701 : putchar_unlocked ('\n');
7702 : }
7703 : }
7704 : }
7705 :
7706 :
7707 : /* Callback for printing global names. */
7708 : static int
7709 34 : print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
7710 : void *arg)
7711 : {
7712 34 : int *np = (int *) arg;
7713 :
7714 102 : printf (gettext (" [%5d] DIE offset: %6" PRId64
7715 : ", CU DIE offset: %6" PRId64 ", name: %s\n"),
7716 34 : (*np)++, global->die_offset, global->cu_offset, global->name);
7717 :
7718 34 : return 0;
7719 : }
7720 :
7721 :
7722 : /* Print the known exported symbols in the DWARF section '.debug_pubnames'. */
7723 : static void
7724 8 : print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
7725 : Ebl *ebl, GElf_Ehdr *ehdr,
7726 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7727 : {
7728 24 : printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
7729 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7730 8 : (uint64_t) shdr->sh_offset);
7731 :
7732 8 : int n = 0;
7733 8 : (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
7734 8 : }
7735 :
7736 : /* Print the content of the DWARF string section '.debug_str'. */
7737 : static void
7738 34 : print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
7739 : Ebl *ebl, GElf_Ehdr *ehdr,
7740 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7741 : {
7742 68 : const size_t sh_size = (dbg->sectiondata[IDX_debug_str] ?
7743 34 : dbg->sectiondata[IDX_debug_str]->d_size : 0);
7744 :
7745 : /* Compute floor(log16(shdr->sh_size)). */
7746 34 : GElf_Addr tmp = sh_size;
7747 34 : int digits = 1;
7748 165 : while (tmp >= 16)
7749 : {
7750 97 : ++digits;
7751 97 : tmp >>= 4;
7752 : }
7753 34 : digits = MAX (4, digits);
7754 :
7755 136 : printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
7756 : " %*s String\n"),
7757 : elf_ndxscn (scn),
7758 34 : section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset,
7759 : /* TRANS: the debugstr| prefix makes the string unique. */
7760 34 : digits + 2, sgettext ("debugstr|Offset"));
7761 :
7762 34 : Dwarf_Off offset = 0;
7763 60444 : while (offset < sh_size)
7764 : {
7765 : size_t len;
7766 60376 : const char *str = dwarf_getstring (dbg, offset, &len);
7767 60376 : if (unlikely (str == NULL))
7768 : {
7769 0 : printf (gettext (" *** error while reading strings: %s\n"),
7770 : dwarf_errmsg (-1));
7771 0 : break;
7772 : }
7773 :
7774 60376 : printf (" [%*" PRIx64 "] \"%s\"\n", digits, (uint64_t) offset, str);
7775 :
7776 60376 : offset += len + 1;
7777 : }
7778 34 : }
7779 :
7780 :
7781 : /* Print the content of the call frame search table section
7782 : '.eh_frame_hdr'. */
7783 : static void
7784 16 : print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
7785 : Ebl *ebl __attribute__ ((unused)),
7786 : GElf_Ehdr *ehdr __attribute__ ((unused)),
7787 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7788 : {
7789 32 : printf (gettext ("\
7790 : \nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
7791 : elf_ndxscn (scn));
7792 :
7793 16 : Elf_Data *data = elf_rawdata (scn, NULL);
7794 :
7795 16 : if (unlikely (data == NULL))
7796 : {
7797 0 : error (0, 0, gettext ("cannot get %s content: %s"),
7798 : ".eh_frame_hdr", elf_errmsg (-1));
7799 0 : return;
7800 : }
7801 :
7802 16 : const unsigned char *readp = data->d_buf;
7803 16 : const unsigned char *const dataend = ((unsigned char *) data->d_buf
7804 16 : + data->d_size);
7805 :
7806 16 : if (unlikely (readp + 4 > dataend))
7807 : {
7808 : invalid_data:
7809 0 : error (0, 0, gettext ("invalid data"));
7810 : return;
7811 : }
7812 :
7813 16 : unsigned int version = *readp++;
7814 16 : unsigned int eh_frame_ptr_enc = *readp++;
7815 16 : unsigned int fde_count_enc = *readp++;
7816 16 : unsigned int table_enc = *readp++;
7817 :
7818 16 : printf (" version: %u\n"
7819 : " eh_frame_ptr_enc: %#x ",
7820 : version, eh_frame_ptr_enc);
7821 16 : print_encoding_base ("", eh_frame_ptr_enc);
7822 16 : printf (" fde_count_enc: %#x ", fde_count_enc);
7823 16 : print_encoding_base ("", fde_count_enc);
7824 16 : printf (" table_enc: %#x ", table_enc);
7825 16 : print_encoding_base ("", table_enc);
7826 :
7827 16 : uint64_t eh_frame_ptr = 0;
7828 16 : if (eh_frame_ptr_enc != DW_EH_PE_omit)
7829 : {
7830 16 : readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
7831 : dbg);
7832 16 : if (unlikely (readp == NULL))
7833 : goto invalid_data;
7834 :
7835 32 : printf (" eh_frame_ptr: %#" PRIx64, eh_frame_ptr);
7836 16 : if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
7837 16 : printf (" (offset: %#" PRIx64 ")",
7838 : /* +4 because of the 4 byte header of the section. */
7839 16 : (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
7840 :
7841 : putchar_unlocked ('\n');
7842 : }
7843 :
7844 16 : uint64_t fde_count = 0;
7845 16 : if (fde_count_enc != DW_EH_PE_omit)
7846 : {
7847 16 : readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
7848 16 : if (unlikely (readp == NULL))
7849 : goto invalid_data;
7850 :
7851 16 : printf (" fde_count: %" PRIu64 "\n", fde_count);
7852 : }
7853 :
7854 16 : if (fde_count == 0 || table_enc == DW_EH_PE_omit)
7855 : return;
7856 :
7857 16 : puts (" Table:");
7858 :
7859 : /* Optimize for the most common case. */
7860 16 : if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
7861 4484 : while (fde_count > 0 && readp + 8 <= dataend)
7862 : {
7863 4468 : int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
7864 8936 : uint64_t initial_offset = ((uint64_t) shdr->sh_offset
7865 4468 : + (int64_t) initial_location);
7866 4468 : int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
7867 : // XXX Possibly print symbol name or section offset for initial_offset
7868 4468 : printf (" %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
7869 : " fde=[%6" PRIx64 "]\n",
7870 : initial_location, initial_offset,
7871 4468 : address, address - (eh_frame_ptr + 4));
7872 : }
7873 : else
7874 : while (0 && readp < dataend)
7875 : {
7876 :
7877 : }
7878 : }
7879 :
7880 :
7881 : /* Print the content of the exception handling table section
7882 : '.eh_frame_hdr'. */
7883 : static void
7884 0 : print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
7885 : Ebl *ebl __attribute__ ((unused)),
7886 : GElf_Ehdr *ehdr __attribute__ ((unused)),
7887 : Elf_Scn *scn,
7888 : GElf_Shdr *shdr __attribute__ ((unused)),
7889 : Dwarf *dbg __attribute__ ((unused)))
7890 : {
7891 0 : printf (gettext ("\
7892 : \nException handling table section [%2zu] '.gcc_except_table':\n"),
7893 : elf_ndxscn (scn));
7894 :
7895 0 : Elf_Data *data = elf_rawdata (scn, NULL);
7896 :
7897 0 : if (unlikely (data == NULL))
7898 : {
7899 0 : error (0, 0, gettext ("cannot get %s content: %s"),
7900 : ".gcc_except_table", elf_errmsg (-1));
7901 0 : return;
7902 : }
7903 :
7904 0 : const unsigned char *readp = data->d_buf;
7905 0 : const unsigned char *const dataend = readp + data->d_size;
7906 :
7907 0 : if (unlikely (readp + 1 > dataend))
7908 : {
7909 : invalid_data:
7910 0 : error (0, 0, gettext ("invalid data"));
7911 : return;
7912 : }
7913 0 : unsigned int lpstart_encoding = *readp++;
7914 0 : printf (gettext (" LPStart encoding: %#x "), lpstart_encoding);
7915 0 : print_encoding_base ("", lpstart_encoding);
7916 0 : if (lpstart_encoding != DW_EH_PE_omit)
7917 : {
7918 : uint64_t lpstart;
7919 0 : readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
7920 0 : printf (" LPStart: %#" PRIx64 "\n", lpstart);
7921 : }
7922 :
7923 0 : if (unlikely (readp + 1 > dataend))
7924 : goto invalid_data;
7925 0 : unsigned int ttype_encoding = *readp++;
7926 0 : printf (gettext (" TType encoding: %#x "), ttype_encoding);
7927 0 : print_encoding_base ("", ttype_encoding);
7928 0 : const unsigned char *ttype_base = NULL;
7929 0 : if (ttype_encoding != DW_EH_PE_omit)
7930 : {
7931 : unsigned int ttype_base_offset;
7932 0 : get_uleb128 (ttype_base_offset, readp, dataend);
7933 0 : printf (" TType base offset: %#x\n", ttype_base_offset);
7934 0 : if ((size_t) (dataend - readp) > ttype_base_offset)
7935 0 : ttype_base = readp + ttype_base_offset;
7936 : }
7937 :
7938 0 : if (unlikely (readp + 1 > dataend))
7939 : goto invalid_data;
7940 0 : unsigned int call_site_encoding = *readp++;
7941 0 : printf (gettext (" Call site encoding: %#x "), call_site_encoding);
7942 0 : print_encoding_base ("", call_site_encoding);
7943 : unsigned int call_site_table_len;
7944 0 : get_uleb128 (call_site_table_len, readp, dataend);
7945 :
7946 0 : const unsigned char *const action_table = readp + call_site_table_len;
7947 0 : if (unlikely (action_table > dataend))
7948 : goto invalid_data;
7949 : unsigned int u = 0;
7950 : unsigned int max_action = 0;
7951 0 : while (readp < action_table)
7952 : {
7953 0 : if (u == 0)
7954 0 : puts (gettext ("\n Call site table:"));
7955 :
7956 : uint64_t call_site_start;
7957 0 : readp = read_encoded (call_site_encoding, readp, dataend,
7958 : &call_site_start, dbg);
7959 : uint64_t call_site_length;
7960 0 : readp = read_encoded (call_site_encoding, readp, dataend,
7961 : &call_site_length, dbg);
7962 : uint64_t landing_pad;
7963 0 : readp = read_encoded (call_site_encoding, readp, dataend,
7964 : &landing_pad, dbg);
7965 : unsigned int action;
7966 0 : get_uleb128 (action, readp, dataend);
7967 0 : max_action = MAX (action, max_action);
7968 0 : printf (gettext (" [%4u] Call site start: %#" PRIx64 "\n"
7969 : " Call site length: %" PRIu64 "\n"
7970 : " Landing pad: %#" PRIx64 "\n"
7971 : " Action: %u\n"),
7972 : u++, call_site_start, call_site_length, landing_pad, action);
7973 : }
7974 0 : if (readp != action_table)
7975 : goto invalid_data;
7976 :
7977 0 : unsigned int max_ar_filter = 0;
7978 0 : if (max_action > 0)
7979 : {
7980 0 : puts ("\n Action table:");
7981 :
7982 0 : size_t maxdata = (size_t) (dataend - action_table);
7983 0 : if (max_action > maxdata || maxdata - max_action < 1)
7984 : {
7985 : invalid_action_table:
7986 0 : fputs (gettext (" <INVALID DATA>\n"), stdout);
7987 0 : return;
7988 : }
7989 :
7990 0 : const unsigned char *const action_table_end
7991 0 : = action_table + max_action + 1;
7992 :
7993 0 : u = 0;
7994 : do
7995 : {
7996 : int ar_filter;
7997 0 : get_sleb128 (ar_filter, readp, action_table_end);
7998 0 : if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
7999 0 : max_ar_filter = ar_filter;
8000 : int ar_disp;
8001 0 : if (readp >= action_table_end)
8002 : goto invalid_action_table;
8003 0 : get_sleb128 (ar_disp, readp, action_table_end);
8004 :
8005 0 : printf (" [%4u] ar_filter: % d\n"
8006 : " ar_disp: % -5d",
8007 : u, ar_filter, ar_disp);
8008 0 : if (abs (ar_disp) & 1)
8009 0 : printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
8010 0 : else if (ar_disp != 0)
8011 0 : puts (" -> ???");
8012 : else
8013 : putchar_unlocked ('\n');
8014 0 : ++u;
8015 : }
8016 0 : while (readp < action_table_end);
8017 : }
8018 :
8019 0 : if (max_ar_filter > 0 && ttype_base != NULL)
8020 : {
8021 : unsigned char dsize;
8022 0 : puts ("\n TType table:");
8023 :
8024 : // XXX Not *4, size of encoding;
8025 : switch (ttype_encoding & 7)
8026 : {
8027 : case DW_EH_PE_udata2:
8028 : case DW_EH_PE_sdata2:
8029 : dsize = 2;
8030 : break;
8031 : case DW_EH_PE_udata4:
8032 : case DW_EH_PE_sdata4:
8033 : dsize = 4;
8034 : break;
8035 : case DW_EH_PE_udata8:
8036 : case DW_EH_PE_sdata8:
8037 : dsize = 8;
8038 : break;
8039 : default:
8040 0 : dsize = 0;
8041 0 : error (1, 0, gettext ("invalid TType encoding"));
8042 : }
8043 :
8044 0 : if (max_ar_filter
8045 0 : > (size_t) (ttype_base - (const unsigned char *) data->d_buf) / dsize)
8046 : goto invalid_data;
8047 :
8048 0 : readp = ttype_base - max_ar_filter * dsize;
8049 : do
8050 : {
8051 : uint64_t ttype;
8052 0 : readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
8053 : dbg);
8054 0 : printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
8055 : }
8056 0 : while (readp < ttype_base);
8057 : }
8058 : }
8059 :
8060 : /* Print the content of the '.gdb_index' section.
8061 : http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
8062 : */
8063 : static void
8064 2 : print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
8065 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
8066 : {
8067 6 : printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
8068 : " contains %" PRId64 " bytes :\n"),
8069 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
8070 2 : (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
8071 :
8072 2 : Elf_Data *data = elf_rawdata (scn, NULL);
8073 :
8074 2 : if (unlikely (data == NULL))
8075 : {
8076 0 : error (0, 0, gettext ("cannot get %s content: %s"),
8077 : ".gdb_index", elf_errmsg (-1));
8078 0 : return;
8079 : }
8080 :
8081 : // .gdb_index is always in little endian.
8082 2 : Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
8083 2 : dbg = &dummy_dbg;
8084 :
8085 2 : const unsigned char *readp = data->d_buf;
8086 2 : const unsigned char *const dataend = readp + data->d_size;
8087 :
8088 2 : if (unlikely (readp + 4 > dataend))
8089 : {
8090 : invalid_data:
8091 0 : error (0, 0, gettext ("invalid data"));
8092 : return;
8093 : }
8094 :
8095 2 : int32_t vers = read_4ubyte_unaligned (dbg, readp);
8096 4 : printf (gettext (" Version: %" PRId32 "\n"), vers);
8097 :
8098 : // The only difference between version 4 and version 5 is the
8099 : // hash used for generating the table. Version 6 contains symbols
8100 : // for inlined functions, older versions didn't. Version 7 adds
8101 : // symbol kinds. Version 8 just indicates that it correctly includes
8102 : // TUs for symbols.
8103 2 : if (vers < 4 || vers > 8)
8104 : {
8105 0 : printf (gettext (" unknown version, cannot parse section\n"));
8106 : return;
8107 : }
8108 :
8109 2 : readp += 4;
8110 2 : if (unlikely (readp + 4 > dataend))
8111 : goto invalid_data;
8112 :
8113 2 : uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
8114 4 : printf (gettext (" CU offset: %#" PRIx32 "\n"), cu_off);
8115 :
8116 2 : readp += 4;
8117 2 : if (unlikely (readp + 4 > dataend))
8118 : goto invalid_data;
8119 :
8120 2 : uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
8121 4 : printf (gettext (" TU offset: %#" PRIx32 "\n"), tu_off);
8122 :
8123 2 : readp += 4;
8124 2 : if (unlikely (readp + 4 > dataend))
8125 : goto invalid_data;
8126 :
8127 2 : uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
8128 4 : printf (gettext (" address offset: %#" PRIx32 "\n"), addr_off);
8129 :
8130 2 : readp += 4;
8131 2 : if (unlikely (readp + 4 > dataend))
8132 : goto invalid_data;
8133 :
8134 2 : uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
8135 4 : printf (gettext (" symbol offset: %#" PRIx32 "\n"), sym_off);
8136 :
8137 2 : readp += 4;
8138 2 : if (unlikely (readp + 4 > dataend))
8139 : goto invalid_data;
8140 :
8141 2 : uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
8142 4 : printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
8143 :
8144 2 : if (unlikely ((size_t) (dataend - (const unsigned char *) data->d_buf)
8145 : < const_off))
8146 : goto invalid_data;
8147 :
8148 2 : readp = data->d_buf + cu_off;
8149 :
8150 2 : const unsigned char *nextp = data->d_buf + tu_off;
8151 2 : if (tu_off >= data->d_size)
8152 : goto invalid_data;
8153 :
8154 2 : size_t cu_nr = (nextp - readp) / 16;
8155 :
8156 4 : printf (gettext ("\n CU list at offset %#" PRIx32
8157 : " contains %zu entries:\n"),
8158 : cu_off, cu_nr);
8159 :
8160 2 : size_t n = 0;
8161 8 : while (dataend - readp >= 16 && n < cu_nr)
8162 : {
8163 4 : uint64_t off = read_8ubyte_unaligned (dbg, readp);
8164 4 : readp += 8;
8165 :
8166 4 : uint64_t len = read_8ubyte_unaligned (dbg, readp);
8167 4 : readp += 8;
8168 :
8169 4 : printf (" [%4zu] start: %0#8" PRIx64
8170 : ", length: %5" PRIu64 "\n", n, off, len);
8171 4 : n++;
8172 : }
8173 :
8174 2 : readp = data->d_buf + tu_off;
8175 2 : nextp = data->d_buf + addr_off;
8176 2 : if (addr_off >= data->d_size)
8177 : goto invalid_data;
8178 :
8179 2 : size_t tu_nr = (nextp - readp) / 24;
8180 :
8181 4 : printf (gettext ("\n TU list at offset %#" PRIx32
8182 : " contains %zu entries:\n"),
8183 : tu_off, tu_nr);
8184 :
8185 2 : n = 0;
8186 6 : while (dataend - readp >= 24 && n < tu_nr)
8187 : {
8188 2 : uint64_t off = read_8ubyte_unaligned (dbg, readp);
8189 2 : readp += 8;
8190 :
8191 2 : uint64_t type = read_8ubyte_unaligned (dbg, readp);
8192 2 : readp += 8;
8193 :
8194 2 : uint64_t sig = read_8ubyte_unaligned (dbg, readp);
8195 2 : readp += 8;
8196 :
8197 2 : printf (" [%4zu] CU offset: %5" PRId64
8198 : ", type offset: %5" PRId64
8199 : ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
8200 2 : n++;
8201 : }
8202 :
8203 2 : readp = data->d_buf + addr_off;
8204 2 : nextp = data->d_buf + sym_off;
8205 2 : if (sym_off >= data->d_size)
8206 : goto invalid_data;
8207 :
8208 2 : size_t addr_nr = (nextp - readp) / 20;
8209 :
8210 4 : printf (gettext ("\n Address list at offset %#" PRIx32
8211 : " contains %zu entries:\n"),
8212 : addr_off, addr_nr);
8213 :
8214 2 : n = 0;
8215 8 : while (dataend - readp >= 20 && n < addr_nr)
8216 : {
8217 4 : uint64_t low = read_8ubyte_unaligned (dbg, readp);
8218 4 : readp += 8;
8219 :
8220 4 : uint64_t high = read_8ubyte_unaligned (dbg, readp);
8221 4 : readp += 8;
8222 :
8223 4 : uint32_t idx = read_4ubyte_unaligned (dbg, readp);
8224 4 : readp += 4;
8225 :
8226 4 : char *l = format_dwarf_addr (dwflmod, 8, low, low);
8227 4 : char *h = format_dwarf_addr (dwflmod, 8, high - 1, high);
8228 4 : printf (" [%4zu] %s..%s, CU index: %5" PRId32 "\n",
8229 : n, l, h, idx);
8230 4 : free (l);
8231 4 : free (h);
8232 4 : n++;
8233 : }
8234 :
8235 2 : const unsigned char *const_start = data->d_buf + const_off;
8236 2 : if (const_off >= data->d_size)
8237 : goto invalid_data;
8238 :
8239 2 : readp = data->d_buf + sym_off;
8240 2 : nextp = const_start;
8241 2 : size_t sym_nr = (nextp - readp) / 8;
8242 :
8243 4 : printf (gettext ("\n Symbol table at offset %#" PRIx32
8244 : " contains %zu slots:\n"),
8245 : addr_off, sym_nr);
8246 :
8247 2 : n = 0;
8248 2052 : while (dataend - readp >= 8 && n < sym_nr)
8249 : {
8250 2048 : uint32_t name = read_4ubyte_unaligned (dbg, readp);
8251 2048 : readp += 4;
8252 :
8253 2048 : uint32_t vector = read_4ubyte_unaligned (dbg, readp);
8254 2048 : readp += 4;
8255 :
8256 2048 : if (name != 0 || vector != 0)
8257 : {
8258 14 : const unsigned char *sym = const_start + name;
8259 14 : if (unlikely ((size_t) (dataend - const_start) < name
8260 : || memchr (sym, '\0', dataend - sym) == NULL))
8261 : goto invalid_data;
8262 :
8263 14 : printf (" [%4zu] symbol: %s, CUs: ", n, sym);
8264 :
8265 14 : const unsigned char *readcus = const_start + vector;
8266 14 : if (unlikely ((size_t) (dataend - const_start) < vector))
8267 : goto invalid_data;
8268 14 : uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
8269 44 : while (cus--)
8270 : {
8271 : uint32_t cu_kind, cu, kind;
8272 : bool is_static;
8273 16 : readcus += 4;
8274 16 : if (unlikely (readcus + 4 > dataend))
8275 : goto invalid_data;
8276 16 : cu_kind = read_4ubyte_unaligned (dbg, readcus);
8277 16 : cu = cu_kind & ((1 << 24) - 1);
8278 16 : kind = (cu_kind >> 28) & 7;
8279 16 : is_static = cu_kind & (1U << 31);
8280 16 : if (cu > cu_nr - 1)
8281 2 : printf ("%" PRId32 "T", cu - (uint32_t) cu_nr);
8282 : else
8283 : printf ("%" PRId32, cu);
8284 16 : if (kind != 0)
8285 : {
8286 8 : printf (" (");
8287 8 : switch (kind)
8288 : {
8289 : case 1:
8290 : printf ("type");
8291 : break;
8292 : case 2:
8293 : printf ("var");
8294 : break;
8295 : case 3:
8296 : printf ("func");
8297 : break;
8298 : case 4:
8299 : printf ("other");
8300 : break;
8301 : default:
8302 : printf ("unknown-0x%" PRIx32, kind);
8303 : break;
8304 : }
8305 8 : printf (":%c)", (is_static ? 'S' : 'G'));
8306 : }
8307 16 : if (cus > 0)
8308 : printf (", ");
8309 : }
8310 : printf ("\n");
8311 : }
8312 2048 : n++;
8313 : }
8314 : }
8315 :
8316 : static void
8317 89 : print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
8318 : {
8319 : /* Before we start the real work get a debug context descriptor. */
8320 : Dwarf_Addr dwbias;
8321 89 : Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
8322 267 : Dwarf dummy_dbg =
8323 : {
8324 89 : .elf = ebl->elf,
8325 89 : .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
8326 : };
8327 89 : if (dbg == NULL)
8328 : {
8329 20 : if ((print_debug_sections & ~section_exception) != 0)
8330 0 : error (0, 0, gettext ("cannot get debug context descriptor: %s"),
8331 : dwfl_errmsg (-1));
8332 : dbg = &dummy_dbg;
8333 : }
8334 :
8335 : /* Get the section header string table index. */
8336 : size_t shstrndx;
8337 89 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
8338 : error (EXIT_FAILURE, 0,
8339 0 : gettext ("cannot get section header string table index"));
8340 :
8341 : /* Look through all the sections for the debugging sections to print. */
8342 : Elf_Scn *scn = NULL;
8343 2837 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
8344 : {
8345 : GElf_Shdr shdr_mem;
8346 2748 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
8347 :
8348 2748 : if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
8349 : {
8350 : static const struct
8351 : {
8352 : const char *name;
8353 : enum section_e bitmask;
8354 : void (*fp) (Dwfl_Module *, Ebl *,
8355 : GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
8356 : } debug_sections[] =
8357 : {
8358 : #define NEW_SECTION(name) \
8359 : { ".debug_" #name, section_##name, print_debug_##name##_section }
8360 : NEW_SECTION (abbrev),
8361 : NEW_SECTION (aranges),
8362 : NEW_SECTION (frame),
8363 : NEW_SECTION (info),
8364 : NEW_SECTION (types),
8365 : NEW_SECTION (line),
8366 : NEW_SECTION (loc),
8367 : NEW_SECTION (pubnames),
8368 : NEW_SECTION (str),
8369 : NEW_SECTION (macinfo),
8370 : NEW_SECTION (macro),
8371 : NEW_SECTION (ranges),
8372 : { ".eh_frame", section_frame | section_exception,
8373 : print_debug_frame_section },
8374 : { ".eh_frame_hdr", section_frame | section_exception,
8375 : print_debug_frame_hdr_section },
8376 : { ".gcc_except_table", section_frame | section_exception,
8377 : print_debug_exception_table },
8378 : { ".gdb_index", section_gdb_index, print_gdb_index_section }
8379 : };
8380 1325 : const int ndebug_sections = (sizeof (debug_sections)
8381 : / sizeof (debug_sections[0]));
8382 1325 : const char *name = elf_strptr (ebl->elf, shstrndx,
8383 1325 : shdr->sh_name);
8384 1325 : if (name == NULL)
8385 0 : continue;
8386 :
8387 : int n;
8388 15271 : for (n = 0; n < ndebug_sections; ++n)
8389 15859 : if (strcmp (name, debug_sections[n].name) == 0
8390 15333 : || (name[0] == '.' && name[1] == 'z'
8391 358 : && debug_sections[n].name[1] == 'd'
8392 358 : && strcmp (&name[2], &debug_sections[n].name[1]) == 0)
8393 : )
8394 : {
8395 1176 : if ((print_debug_sections | implicit_debug_sections)
8396 588 : & debug_sections[n].bitmask)
8397 324 : debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
8398 : break;
8399 : }
8400 : }
8401 : }
8402 :
8403 89 : reset_listptr (&known_loclistptr);
8404 89 : reset_listptr (&known_rangelistptr);
8405 89 : }
8406 :
8407 :
8408 : #define ITEM_INDENT 4
8409 : #define WRAP_COLUMN 75
8410 :
8411 : /* Print "NAME: FORMAT", wrapping when output text would make the line
8412 : exceed WRAP_COLUMN. Unpadded numbers look better for the core items
8413 : but this function is also used for registers which should be printed
8414 : aligned. Fortunately registers output uses fixed fields width (such
8415 : as %11d) for the alignment.
8416 :
8417 : Line breaks should not depend on the particular values although that
8418 : may happen in some cases of the core items. */
8419 :
8420 : static unsigned int
8421 : __attribute__ ((format (printf, 6, 7)))
8422 761 : print_core_item (unsigned int colno, char sep, unsigned int wrap,
8423 : size_t name_width, const char *name, const char *format, ...)
8424 : {
8425 761 : size_t len = strlen (name);
8426 761 : if (name_width < len)
8427 368 : name_width = len;
8428 :
8429 : char *out;
8430 : va_list ap;
8431 761 : va_start (ap, format);
8432 761 : int out_len = vasprintf (&out, format, ap);
8433 761 : va_end (ap);
8434 761 : if (out_len == -1)
8435 0 : error (EXIT_FAILURE, 0, _("memory exhausted"));
8436 :
8437 761 : size_t n = name_width + sizeof ": " - 1 + out_len;
8438 :
8439 761 : if (colno == 0)
8440 : {
8441 48 : printf ("%*s", ITEM_INDENT, "");
8442 48 : colno = ITEM_INDENT + n;
8443 : }
8444 713 : else if (colno + 2 + n < wrap)
8445 : {
8446 866 : printf ("%c ", sep);
8447 433 : colno += 2 + n;
8448 : }
8449 : else
8450 : {
8451 280 : printf ("\n%*s", ITEM_INDENT, "");
8452 280 : colno = ITEM_INDENT + n;
8453 : }
8454 :
8455 1522 : printf ("%s: %*s%s", name, (int) (name_width - len), "", out);
8456 :
8457 761 : free (out);
8458 :
8459 761 : return colno;
8460 : }
8461 :
8462 : static const void *
8463 838 : convert (Elf *core, Elf_Type type, uint_fast16_t count,
8464 : void *value, const void *data, size_t size)
8465 : {
8466 1676 : Elf_Data valuedata =
8467 : {
8468 : .d_type = type,
8469 : .d_buf = value,
8470 838 : .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
8471 : .d_version = EV_CURRENT,
8472 : };
8473 838 : Elf_Data indata =
8474 : {
8475 : .d_type = type,
8476 : .d_buf = (void *) data,
8477 : .d_size = valuedata.d_size,
8478 : .d_version = EV_CURRENT,
8479 : };
8480 :
8481 1676 : Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
8482 1676 : ? elf32_xlatetom : elf64_xlatetom)
8483 838 : (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
8484 838 : if (d == NULL)
8485 0 : error (EXIT_FAILURE, 0,
8486 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
8487 :
8488 838 : return data + indata.d_size;
8489 : }
8490 :
8491 : typedef uint8_t GElf_Byte;
8492 :
8493 : static unsigned int
8494 371 : handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
8495 : unsigned int colno, size_t *repeated_size)
8496 : {
8497 371 : uint_fast16_t count = item->count ?: 1;
8498 : /* Ebl_Core_Item count is always a small number.
8499 : Make sure the backend didn't put in some large bogus value. */
8500 371 : assert (count < 128);
8501 :
8502 : #define TYPES \
8503 : DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8); \
8504 : DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16); \
8505 : DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32); \
8506 : DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32); \
8507 : DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64); \
8508 : DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64)
8509 :
8510 : #define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name
8511 : typedef union { TYPES; } value_t;
8512 371 : void *data = alloca (count * sizeof (value_t));
8513 : #undef DO_TYPE
8514 :
8515 : #define DO_TYPE(NAME, Name, hex, dec) \
8516 : GElf_##Name *value_##Name __attribute__((unused)) = data
8517 371 : TYPES;
8518 : #undef DO_TYPE
8519 :
8520 371 : size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
8521 371 : size_t convsize = size;
8522 371 : if (repeated_size != NULL)
8523 : {
8524 1 : if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
8525 : {
8526 0 : data = alloca (*repeated_size);
8527 0 : count *= *repeated_size / size;
8528 0 : convsize = count * size;
8529 0 : *repeated_size -= convsize;
8530 : }
8531 1 : else if (item->count != 0 || item->format != '\n')
8532 0 : *repeated_size -= size;
8533 : }
8534 :
8535 371 : convert (core, item->type, count, data, desc + item->offset, convsize);
8536 :
8537 371 : Elf_Type type = item->type;
8538 371 : if (type == ELF_T_ADDR)
8539 0 : type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
8540 :
8541 371 : switch (item->format)
8542 : {
8543 : case 'd':
8544 175 : assert (count == 1);
8545 175 : switch (type)
8546 : {
8547 : #define DO_TYPE(NAME, Name, hex, dec) \
8548 : case ELF_T_##NAME: \
8549 : colno = print_core_item (colno, ',', WRAP_COLUMN, \
8550 : 0, item->name, dec, value_##Name[0]); \
8551 : break
8552 24 : TYPES;
8553 : #undef DO_TYPE
8554 : default:
8555 0 : abort ();
8556 : }
8557 : break;
8558 :
8559 : case 'x':
8560 109 : assert (count == 1);
8561 109 : switch (type)
8562 : {
8563 : #define DO_TYPE(NAME, Name, hex, dec) \
8564 : case ELF_T_##NAME: \
8565 : colno = print_core_item (colno, ',', WRAP_COLUMN, \
8566 : 0, item->name, hex, value_##Name[0]); \
8567 : break
8568 0 : TYPES;
8569 : #undef DO_TYPE
8570 : default:
8571 0 : abort ();
8572 : }
8573 : break;
8574 :
8575 : case 'b':
8576 : case 'B':
8577 20 : assert (size % sizeof (unsigned int) == 0);
8578 20 : unsigned int nbits = count * size * 8;
8579 20 : unsigned int pop = 0;
8580 50 : for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
8581 30 : pop += __builtin_popcount (*i);
8582 20 : bool negate = pop > nbits / 2;
8583 20 : const unsigned int bias = item->format == 'b';
8584 :
8585 20 : {
8586 20 : char printed[(negate ? nbits - pop : pop) * 16 + 1];
8587 20 : char *p = printed;
8588 20 : *p = '\0';
8589 :
8590 : if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
8591 : {
8592 : assert (size == sizeof (unsigned int) * 2);
8593 : for (unsigned int *i = data;
8594 : (void *) i < data + count * size; i += 2)
8595 : {
8596 : unsigned int w = i[1];
8597 : i[1] = i[0];
8598 : i[0] = w;
8599 : }
8600 : }
8601 :
8602 20 : unsigned int lastbit = 0;
8603 20 : unsigned int run = 0;
8604 70 : for (const unsigned int *i = data;
8605 30 : (void *) i < data + count * size; ++i)
8606 : {
8607 30 : unsigned int bit = ((void *) i - data) * 8;
8608 30 : unsigned int w = negate ? ~*i : *i;
8609 30 : while (w != 0)
8610 : {
8611 : /* Note that a right shift equal to (or greater than)
8612 : the number of bits of w is undefined behaviour. In
8613 : particular when the least significant bit is bit 32
8614 : (w = 0x8000000) then w >>= n is undefined. So
8615 : explicitly handle that case separately. */
8616 0 : unsigned int n = ffs (w);
8617 0 : if (n < sizeof (w) * 8)
8618 0 : w >>= n;
8619 : else
8620 : w = 0;
8621 0 : bit += n;
8622 :
8623 0 : if (lastbit != 0 && lastbit + 1 == bit)
8624 0 : ++run;
8625 : else
8626 : {
8627 0 : if (lastbit == 0)
8628 0 : p += sprintf (p, "%u", bit - bias);
8629 0 : else if (run == 0)
8630 0 : p += sprintf (p, ",%u", bit - bias);
8631 : else
8632 0 : p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
8633 : run = 0;
8634 : }
8635 :
8636 : lastbit = bit;
8637 : }
8638 : }
8639 20 : if (lastbit > 0 && run > 0 && lastbit + 1 != nbits)
8640 0 : p += sprintf (p, "-%u", lastbit - bias);
8641 :
8642 20 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
8643 : negate ? "~<%s>" : "<%s>", printed);
8644 : }
8645 20 : break;
8646 :
8647 : case 'T':
8648 : case (char) ('T'|0x80):
8649 40 : assert (count == 2);
8650 : Dwarf_Word sec;
8651 : Dwarf_Word usec;
8652 40 : switch (type)
8653 : {
8654 : #define DO_TYPE(NAME, Name, hex, dec) \
8655 : case ELF_T_##NAME: \
8656 : sec = value_##Name[0]; \
8657 : usec = value_##Name[1]; \
8658 : break
8659 0 : TYPES;
8660 : #undef DO_TYPE
8661 : default:
8662 0 : abort ();
8663 : }
8664 40 : if (unlikely (item->format == (char) ('T'|0x80)))
8665 : {
8666 : /* This is a hack for an ill-considered 64-bit ABI where
8667 : tv_usec is actually a 32-bit field with 32 bits of padding
8668 : rounding out struct timeval. We've already converted it as
8669 : a 64-bit field. For little-endian, this just means the
8670 : high half is the padding; it's presumably zero, but should
8671 : be ignored anyway. For big-endian, it means the 32-bit
8672 : field went into the high half of USEC. */
8673 : GElf_Ehdr ehdr_mem;
8674 0 : GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
8675 0 : if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
8676 0 : usec >>= 32;
8677 : else
8678 0 : usec &= UINT32_MAX;
8679 : }
8680 40 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
8681 : "%" PRIu64 ".%.6" PRIu64, sec, usec);
8682 40 : break;
8683 :
8684 : case 'c':
8685 8 : assert (count == 1);
8686 8 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
8687 8 : "%c", value_Byte[0]);
8688 8 : break;
8689 :
8690 : case 's':
8691 16 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
8692 : "%.*s", (int) count, value_Byte);
8693 16 : break;
8694 :
8695 : case '\n':
8696 : /* This is a list of strings separated by '\n'. */
8697 1 : assert (item->count == 0);
8698 1 : assert (repeated_size != NULL);
8699 1 : assert (item->name == NULL);
8700 1 : if (unlikely (item->offset >= *repeated_size))
8701 : break;
8702 :
8703 1 : const char *s = desc + item->offset;
8704 1 : size = *repeated_size - item->offset;
8705 1 : *repeated_size = 0;
8706 49 : while (size > 0)
8707 : {
8708 48 : const char *eol = memchr (s, '\n', size);
8709 48 : int len = size;
8710 48 : if (eol != NULL)
8711 47 : len = eol - s;
8712 48 : printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
8713 48 : if (eol == NULL)
8714 : break;
8715 47 : size -= eol + 1 - s;
8716 47 : s = eol + 1;
8717 : }
8718 :
8719 : colno = WRAP_COLUMN;
8720 : break;
8721 :
8722 : case 'h':
8723 : break;
8724 :
8725 : default:
8726 0 : error (0, 0, "XXX not handling format '%c' for %s",
8727 : item->format, item->name);
8728 : break;
8729 : }
8730 :
8731 : #undef TYPES
8732 :
8733 371 : return colno;
8734 : }
8735 :
8736 :
8737 : /* Sort items by group, and by layout offset within each group. */
8738 : static int
8739 827 : compare_core_items (const void *a, const void *b)
8740 : {
8741 827 : const Ebl_Core_Item *const *p1 = a;
8742 827 : const Ebl_Core_Item *const *p2 = b;
8743 827 : const Ebl_Core_Item *item1 = *p1;
8744 827 : const Ebl_Core_Item *item2 = *p2;
8745 :
8746 827 : return ((item1->group == item2->group ? 0
8747 827 : : strcmp (item1->group, item2->group))
8748 827 : ?: (int) item1->offset - (int) item2->offset);
8749 : }
8750 :
8751 : /* Sort item groups by layout offset of the first item in the group. */
8752 : static int
8753 126 : compare_core_item_groups (const void *a, const void *b)
8754 : {
8755 126 : const Ebl_Core_Item *const *const *p1 = a;
8756 126 : const Ebl_Core_Item *const *const *p2 = b;
8757 126 : const Ebl_Core_Item *const *group1 = *p1;
8758 126 : const Ebl_Core_Item *const *group2 = *p2;
8759 126 : const Ebl_Core_Item *item1 = *group1;
8760 126 : const Ebl_Core_Item *item2 = *group2;
8761 :
8762 126 : return (int) item1->offset - (int) item2->offset;
8763 : }
8764 :
8765 : static unsigned int
8766 35 : handle_core_items (Elf *core, const void *desc, size_t descsz,
8767 : const Ebl_Core_Item *items, size_t nitems)
8768 : {
8769 35 : if (nitems == 0)
8770 : return 0;
8771 32 : unsigned int colno = 0;
8772 :
8773 : /* FORMAT '\n' makes sense to be present only as a single item as it
8774 : processes all the data of a note. FORMATs 'b' and 'B' have a special case
8775 : if present as a single item but they can be also processed with other
8776 : items below. */
8777 32 : if (nitems == 1 && (items[0].format == '\n' || items[0].format == 'b'
8778 8 : || items[0].format == 'B'))
8779 : {
8780 1 : assert (items[0].offset == 0);
8781 1 : size_t size = descsz;
8782 1 : colno = handle_core_item (core, items, desc, colno, &size);
8783 : /* If SIZE is not zero here there is some remaining data. But we do not
8784 : know how to process it anyway. */
8785 : return colno;
8786 : }
8787 362 : for (size_t i = 0; i < nitems; ++i)
8788 362 : assert (items[i].format != '\n');
8789 :
8790 : /* Sort to collect the groups together. */
8791 31 : const Ebl_Core_Item *sorted_items[nitems];
8792 393 : for (size_t i = 0; i < nitems; ++i)
8793 362 : sorted_items[i] = &items[i];
8794 31 : qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
8795 :
8796 : /* Collect the unique groups and sort them. */
8797 31 : const Ebl_Core_Item **groups[nitems];
8798 31 : groups[0] = &sorted_items[0];
8799 31 : size_t ngroups = 1;
8800 362 : for (size_t i = 1; i < nitems; ++i)
8801 331 : if (sorted_items[i]->group != sorted_items[i - 1]->group
8802 68 : && strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
8803 68 : groups[ngroups++] = &sorted_items[i];
8804 31 : qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
8805 :
8806 : /* Write out all the groups. */
8807 31 : const void *last = desc;
8808 : do
8809 : {
8810 134 : for (size_t i = 0; i < ngroups; ++i)
8811 : {
8812 572 : for (const Ebl_Core_Item **item = groups[i];
8813 471 : (item < &sorted_items[nitems]
8814 438 : && ((*item)->group == groups[i][0]->group
8815 68 : || !strcmp ((*item)->group, groups[i][0]->group)));
8816 370 : ++item)
8817 370 : colno = handle_core_item (core, *item, desc, colno, NULL);
8818 :
8819 : /* Force a line break at the end of the group. */
8820 101 : colno = WRAP_COLUMN;
8821 : }
8822 :
8823 33 : if (descsz == 0)
8824 : break;
8825 :
8826 : /* This set of items consumed a certain amount of the note's data.
8827 : If there is more data there, we have another unit of the same size.
8828 : Loop to print that out too. */
8829 19 : const Ebl_Core_Item *item = &items[nitems - 1];
8830 38 : size_t eltsz = item->offset + gelf_fsize (core, item->type,
8831 19 : item->count ?: 1, EV_CURRENT);
8832 :
8833 19 : int reps = -1;
8834 : do
8835 : {
8836 19 : ++reps;
8837 19 : desc += eltsz;
8838 19 : descsz -= eltsz;
8839 : }
8840 19 : while (descsz >= eltsz && !memcmp (desc, last, eltsz));
8841 :
8842 19 : if (reps == 1)
8843 : {
8844 : /* For just one repeat, print it unabridged twice. */
8845 : desc -= eltsz;
8846 : descsz += eltsz;
8847 : }
8848 19 : else if (reps > 1)
8849 0 : printf (gettext ("\n%*s... <repeats %u more times> ..."),
8850 : ITEM_INDENT, "", reps);
8851 :
8852 19 : last = desc;
8853 : }
8854 19 : while (descsz > 0);
8855 :
8856 : return colno;
8857 : }
8858 :
8859 : static unsigned int
8860 : handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
8861 : unsigned int colno)
8862 : {
8863 0 : desc += regloc->offset;
8864 :
8865 0 : abort (); /* XXX */
8866 : return colno;
8867 : }
8868 :
8869 :
8870 : static unsigned int
8871 161 : handle_core_register (Ebl *ebl, Elf *core, int maxregname,
8872 : const Ebl_Register_Location *regloc, const void *desc,
8873 : unsigned int colno)
8874 : {
8875 161 : if (regloc->bits % 8 != 0)
8876 0 : return handle_bit_registers (regloc, desc, colno);
8877 :
8878 161 : desc += regloc->offset;
8879 :
8880 554 : for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
8881 : {
8882 : char name[REGNAMESZ];
8883 : int bits;
8884 : int type;
8885 393 : register_info (ebl, reg, regloc, name, &bits, &type);
8886 :
8887 : #define TYPES \
8888 : BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8); \
8889 : BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16); \
8890 : BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32); \
8891 : BITS (64, XWORD, "%20" PRId64, " 0x%.16" PRIx64)
8892 :
8893 : #define BITS(bits, xtype, sfmt, ufmt) \
8894 : uint##bits##_t b##bits; int##bits##_t b##bits##s
8895 : union { TYPES; uint64_t b128[2]; } value;
8896 : #undef BITS
8897 :
8898 393 : switch (type)
8899 : {
8900 : case DW_ATE_unsigned:
8901 : case DW_ATE_signed:
8902 : case DW_ATE_address:
8903 305 : switch (bits)
8904 : {
8905 : #define BITS(bits, xtype, sfmt, ufmt) \
8906 : case bits: \
8907 : desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0); \
8908 : if (type == DW_ATE_signed) \
8909 : colno = print_core_item (colno, ' ', WRAP_COLUMN, \
8910 : maxregname, name, \
8911 : sfmt, value.b##bits##s); \
8912 : else \
8913 : colno = print_core_item (colno, ' ', WRAP_COLUMN, \
8914 : maxregname, name, \
8915 : ufmt, value.b##bits); \
8916 : break
8917 :
8918 0 : TYPES;
8919 :
8920 : case 128:
8921 48 : assert (type == DW_ATE_unsigned);
8922 48 : desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
8923 48 : int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
8924 96 : colno = print_core_item (colno, ' ', WRAP_COLUMN,
8925 : maxregname, name,
8926 : "0x%.16" PRIx64 "%.16" PRIx64,
8927 48 : value.b128[!be], value.b128[be]);
8928 48 : break;
8929 :
8930 : default:
8931 0 : abort ();
8932 : #undef BITS
8933 : }
8934 : break;
8935 :
8936 : default:
8937 : /* Print each byte in hex, the whole thing in native byte order. */
8938 88 : assert (bits % 8 == 0);
8939 88 : const uint8_t *bytes = desc;
8940 88 : desc += bits / 8;
8941 88 : char hex[bits / 4 + 1];
8942 88 : hex[bits / 4] = '\0';
8943 88 : int incr = 1;
8944 88 : if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
8945 : {
8946 48 : bytes += bits / 8 - 1;
8947 48 : incr = -1;
8948 : }
8949 88 : size_t idx = 0;
8950 872 : for (char *h = hex; bits > 0; bits -= 8, idx += incr)
8951 : {
8952 784 : *h++ = "0123456789abcdef"[bytes[idx] >> 4];
8953 784 : *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
8954 : }
8955 88 : colno = print_core_item (colno, ' ', WRAP_COLUMN,
8956 : maxregname, name, "0x%s", hex);
8957 : break;
8958 : }
8959 393 : desc += regloc->pad;
8960 :
8961 : #undef TYPES
8962 : }
8963 :
8964 : return colno;
8965 : }
8966 :
8967 :
8968 : struct register_info
8969 : {
8970 : const Ebl_Register_Location *regloc;
8971 : const char *set;
8972 : char name[REGNAMESZ];
8973 : int regno;
8974 : int bits;
8975 : int type;
8976 : };
8977 :
8978 : static int
8979 : register_bitpos (const struct register_info *r)
8980 : {
8981 1916 : return (r->regloc->offset * 8
8982 3832 : + ((r->regno - r->regloc->regno)
8983 1916 : * (r->regloc->bits + r->regloc->pad * 8)));
8984 : }
8985 :
8986 : static int
8987 987 : compare_sets_by_info (const struct register_info *r1,
8988 : const struct register_info *r2)
8989 : {
8990 987 : return ((int) r2->bits - (int) r1->bits
8991 2903 : ?: register_bitpos (r1) - register_bitpos (r2));
8992 : }
8993 :
8994 : /* Sort registers by set, and by size and layout offset within each set. */
8995 : static int
8996 4489 : compare_registers (const void *a, const void *b)
8997 : {
8998 4489 : const struct register_info *r1 = a;
8999 4489 : const struct register_info *r2 = b;
9000 :
9001 : /* Unused elements sort last. */
9002 4489 : if (r1->regloc == NULL)
9003 3278 : return r2->regloc == NULL ? 0 : 1;
9004 1211 : if (r2->regloc == NULL)
9005 : return -1;
9006 :
9007 1046 : return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
9008 1046 : ?: compare_sets_by_info (r1, r2));
9009 : }
9010 :
9011 : /* Sort register sets by layout offset of the first register in the set. */
9012 : static int
9013 20 : compare_register_sets (const void *a, const void *b)
9014 : {
9015 20 : const struct register_info *const *p1 = a;
9016 20 : const struct register_info *const *p2 = b;
9017 20 : return compare_sets_by_info (*p1, *p2);
9018 : }
9019 :
9020 : static unsigned int
9021 35 : handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
9022 : const Ebl_Register_Location *reglocs, size_t nregloc)
9023 : {
9024 35 : if (nregloc == 0)
9025 : return 0;
9026 :
9027 17 : ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
9028 17 : if (maxnreg <= 0)
9029 : {
9030 0 : for (size_t i = 0; i < nregloc; ++i)
9031 0 : if (maxnreg < reglocs[i].regno + reglocs[i].count)
9032 0 : maxnreg = reglocs[i].regno + reglocs[i].count;
9033 0 : assert (maxnreg > 0);
9034 : }
9035 :
9036 17 : struct register_info regs[maxnreg];
9037 34 : memset (regs, 0, sizeof regs);
9038 :
9039 : /* Sort to collect the sets together. */
9040 17 : int maxreg = 0;
9041 178 : for (size_t i = 0; i < nregloc; ++i)
9042 715 : for (int reg = reglocs[i].regno;
9043 554 : reg < reglocs[i].regno + reglocs[i].count;
9044 393 : ++reg)
9045 : {
9046 393 : assert (reg < maxnreg);
9047 393 : if (reg > maxreg)
9048 199 : maxreg = reg;
9049 393 : struct register_info *info = ®s[reg];
9050 393 : info->regloc = ®locs[i];
9051 393 : info->regno = reg;
9052 786 : info->set = register_info (ebl, reg, ®locs[i],
9053 393 : info->name, &info->bits, &info->type);
9054 : }
9055 17 : qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
9056 :
9057 : /* Collect the unique sets and sort them. */
9058 802 : inline bool same_set (const struct register_info *a,
9059 : const struct register_info *b)
9060 : {
9061 1604 : return (a < ®s[maxnreg] && a->regloc != NULL
9062 802 : && b < ®s[maxnreg] && b->regloc != NULL
9063 785 : && a->bits == b->bits
9064 1569 : && (a->set == b->set || !strcmp (a->set, b->set)));
9065 : }
9066 17 : struct register_info *sets[maxreg + 1];
9067 17 : sets[0] = ®s[0];
9068 17 : size_t nsets = 1;
9069 1247 : for (int i = 1; i <= maxreg; ++i)
9070 1230 : if (regs[i].regloc != NULL && !same_set (®s[i], ®s[i - 1]))
9071 16 : sets[nsets++] = ®s[i];
9072 17 : qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
9073 :
9074 : /* Write out all the sets. */
9075 17 : unsigned int colno = 0;
9076 50 : for (size_t i = 0; i < nsets; ++i)
9077 : {
9078 : /* Find the longest name of a register in this set. */
9079 33 : size_t maxname = 0;
9080 : const struct register_info *end;
9081 426 : for (end = sets[i]; same_set (sets[i], end); ++end)
9082 : {
9083 393 : size_t len = strlen (end->name);
9084 393 : if (len > maxname)
9085 50 : maxname = len;
9086 : }
9087 :
9088 194 : for (const struct register_info *reg = sets[i];
9089 : reg < end;
9090 161 : reg += reg->regloc->count ?: 1)
9091 161 : colno = handle_core_register (ebl, core, maxname,
9092 : reg->regloc, desc, colno);
9093 :
9094 : /* Force a line break at the end of the group. */
9095 33 : colno = WRAP_COLUMN;
9096 : }
9097 :
9098 : return colno;
9099 : }
9100 :
9101 : static void
9102 8 : handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
9103 : {
9104 8 : Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
9105 8 : if (data == NULL)
9106 : elf_error:
9107 0 : error (EXIT_FAILURE, 0,
9108 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
9109 :
9110 8 : const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
9111 158 : for (size_t i = 0; i < nauxv; ++i)
9112 : {
9113 : GElf_auxv_t av_mem;
9114 150 : GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
9115 150 : if (av == NULL)
9116 : goto elf_error;
9117 :
9118 : const char *name;
9119 : const char *fmt;
9120 150 : if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
9121 : {
9122 : /* Unknown type. */
9123 0 : if (av->a_un.a_val == 0)
9124 0 : printf (" %" PRIu64 "\n", av->a_type);
9125 : else
9126 0 : printf (" %" PRIu64 ": %#" PRIx64 "\n",
9127 : av->a_type, av->a_un.a_val);
9128 : }
9129 : else
9130 150 : switch (fmt[0])
9131 : {
9132 : case '\0': /* Normally zero. */
9133 8 : if (av->a_un.a_val == 0)
9134 : {
9135 8 : printf (" %s\n", name);
9136 : break;
9137 : }
9138 : /* Fall through */
9139 : case 'x': /* hex */
9140 : case 'p': /* address */
9141 : case 's': /* address of string */
9142 66 : printf (" %s: %#" PRIx64 "\n", name, av->a_un.a_val);
9143 : break;
9144 : case 'u':
9145 72 : printf (" %s: %" PRIu64 "\n", name, av->a_un.a_val);
9146 : break;
9147 : case 'd':
9148 0 : printf (" %s: %" PRId64 "\n", name, av->a_un.a_val);
9149 : break;
9150 :
9151 : case 'b':
9152 8 : printf (" %s: %#" PRIx64 " ", name, av->a_un.a_val);
9153 4 : GElf_Xword bit = 1;
9154 4 : const char *pfx = "<";
9155 110 : for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
9156 : {
9157 106 : if (av->a_un.a_val & bit)
9158 : {
9159 77 : printf ("%s%s", pfx, p);
9160 77 : pfx = " ";
9161 : }
9162 106 : bit <<= 1;
9163 : }
9164 : printf (">\n");
9165 : break;
9166 :
9167 : default:
9168 0 : abort ();
9169 : }
9170 : }
9171 8 : }
9172 :
9173 : static bool
9174 : buf_has_data (unsigned char const *ptr, unsigned char const *end, size_t sz)
9175 : {
9176 162 : return ptr < end && (size_t) (end - ptr) >= sz;
9177 : }
9178 :
9179 : static bool
9180 15 : buf_read_int (Elf *core, unsigned char const **ptrp, unsigned char const *end,
9181 : int *retp)
9182 : {
9183 30 : if (! buf_has_data (*ptrp, end, 4))
9184 : return false;
9185 :
9186 15 : *ptrp = convert (core, ELF_T_WORD, 1, retp, *ptrp, 4);
9187 15 : return true;
9188 : }
9189 :
9190 : static bool
9191 147 : buf_read_ulong (Elf *core, unsigned char const **ptrp, unsigned char const *end,
9192 : uint64_t *retp)
9193 : {
9194 147 : size_t sz = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
9195 294 : if (! buf_has_data (*ptrp, end, sz))
9196 : return false;
9197 :
9198 : union
9199 : {
9200 : uint64_t u64;
9201 : uint32_t u32;
9202 : } u;
9203 :
9204 147 : *ptrp = convert (core, ELF_T_ADDR, 1, &u, *ptrp, sz);
9205 :
9206 147 : if (sz == 4)
9207 93 : *retp = u.u32;
9208 : else
9209 54 : *retp = u.u64;
9210 : return true;
9211 : }
9212 :
9213 : static void
9214 5 : handle_siginfo_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
9215 : {
9216 5 : Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
9217 5 : if (data == NULL)
9218 0 : error (EXIT_FAILURE, 0,
9219 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
9220 :
9221 5 : unsigned char const *ptr = data->d_buf;
9222 5 : unsigned char const *const end = data->d_buf + data->d_size;
9223 :
9224 : /* Siginfo head is three ints: signal number, error number, origin
9225 : code. */
9226 : int si_signo, si_errno, si_code;
9227 5 : if (! buf_read_int (core, &ptr, end, &si_signo)
9228 5 : || ! buf_read_int (core, &ptr, end, &si_errno)
9229 5 : || ! buf_read_int (core, &ptr, end, &si_code))
9230 : {
9231 : fail:
9232 0 : printf (" Not enough data in NT_SIGINFO note.\n");
9233 0 : return;
9234 : }
9235 :
9236 : /* Next is a pointer-aligned union of structures. On 64-bit
9237 : machines, that implies a word of padding. */
9238 5 : if (gelf_getclass (core) == ELFCLASS64)
9239 2 : ptr += 4;
9240 :
9241 10 : printf (" si_signo: %d, si_errno: %d, si_code: %d\n",
9242 : si_signo, si_errno, si_code);
9243 :
9244 5 : if (si_code > 0)
9245 5 : switch (si_signo)
9246 : {
9247 : case SIGILL:
9248 : case SIGFPE:
9249 : case SIGSEGV:
9250 : case SIGBUS:
9251 : {
9252 : uint64_t addr;
9253 5 : if (! buf_read_ulong (core, &ptr, end, &addr))
9254 : goto fail;
9255 10 : printf (" fault address: %#" PRIx64 "\n", addr);
9256 5 : break;
9257 : }
9258 : default:
9259 : ;
9260 : }
9261 0 : else if (si_code == SI_USER)
9262 : {
9263 : int pid, uid;
9264 0 : if (! buf_read_int (core, &ptr, end, &pid)
9265 0 : || ! buf_read_int (core, &ptr, end, &uid))
9266 : goto fail;
9267 0 : printf (" sender PID: %d, sender UID: %d\n", pid, uid);
9268 : }
9269 : }
9270 :
9271 : static void
9272 5 : handle_file_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
9273 : {
9274 5 : Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
9275 5 : if (data == NULL)
9276 0 : error (EXIT_FAILURE, 0,
9277 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
9278 :
9279 5 : unsigned char const *ptr = data->d_buf;
9280 5 : unsigned char const *const end = data->d_buf + data->d_size;
9281 :
9282 : uint64_t count, page_size;
9283 5 : if (! buf_read_ulong (core, &ptr, end, &count)
9284 5 : || ! buf_read_ulong (core, &ptr, end, &page_size))
9285 : {
9286 : fail:
9287 0 : printf (" Not enough data in NT_FILE note.\n");
9288 0 : return;
9289 : }
9290 :
9291 5 : size_t addrsize = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
9292 5 : uint64_t maxcount = (size_t) (end - ptr) / (3 * addrsize);
9293 5 : if (count > maxcount)
9294 : goto fail;
9295 :
9296 : /* Where file names are stored. */
9297 5 : unsigned char const *const fstart = ptr + 3 * count * addrsize;
9298 5 : char const *fptr = (char *) fstart;
9299 :
9300 10 : printf (" %" PRId64 " files:\n", count);
9301 49 : for (uint64_t i = 0; i < count; ++i)
9302 : {
9303 : uint64_t mstart, mend, moffset;
9304 44 : if (! buf_read_ulong (core, &ptr, fstart, &mstart)
9305 44 : || ! buf_read_ulong (core, &ptr, fstart, &mend)
9306 44 : || ! buf_read_ulong (core, &ptr, fstart, &moffset))
9307 : goto fail;
9308 :
9309 44 : const char *fnext = memchr (fptr, '\0', (char *) end - fptr);
9310 44 : if (fnext == NULL)
9311 : goto fail;
9312 :
9313 88 : int ct = printf (" %08" PRIx64 "-%08" PRIx64
9314 : " %08" PRIx64 " %" PRId64,
9315 : mstart, mend, moffset * page_size, mend - mstart);
9316 88 : printf ("%*s%s\n", ct > 50 ? 3 : 53 - ct, "", fptr);
9317 :
9318 44 : fptr = fnext + 1;
9319 : }
9320 : }
9321 :
9322 : static void
9323 36 : handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
9324 : const char *name, const void *desc)
9325 : {
9326 : GElf_Word regs_offset;
9327 : size_t nregloc;
9328 : const Ebl_Register_Location *reglocs;
9329 : size_t nitems;
9330 : const Ebl_Core_Item *items;
9331 :
9332 36 : if (! ebl_core_note (ebl, nhdr, name,
9333 : ®s_offset, &nregloc, ®locs, &nitems, &items))
9334 1 : return;
9335 :
9336 : /* Pass 0 for DESCSZ when there are registers in the note,
9337 : so that the ITEMS array does not describe the whole thing.
9338 : For non-register notes, the actual descsz might be a multiple
9339 : of the unit size, not just exactly the unit size. */
9340 88 : unsigned int colno = handle_core_items (ebl->elf, desc,
9341 53 : nregloc == 0 ? nhdr->n_descsz : 0,
9342 : items, nitems);
9343 35 : if (colno != 0)
9344 : putchar_unlocked ('\n');
9345 :
9346 35 : colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
9347 : reglocs, nregloc);
9348 35 : if (colno != 0)
9349 : putchar_unlocked ('\n');
9350 : }
9351 :
9352 : static void
9353 42 : handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
9354 : GElf_Off start, Elf_Data *data)
9355 : {
9356 42 : fputs_unlocked (gettext (" Owner Data size Type\n"), stdout);
9357 :
9358 42 : if (data == NULL)
9359 : goto bad_note;
9360 :
9361 : size_t offset = 0;
9362 : GElf_Nhdr nhdr;
9363 : size_t name_offset;
9364 : size_t desc_offset;
9365 130 : while (offset < data->d_size
9366 88 : && (offset = gelf_getnote (data, offset,
9367 : &nhdr, &name_offset, &desc_offset)) > 0)
9368 : {
9369 88 : const char *name = nhdr.n_namesz == 0 ? "" : data->d_buf + name_offset;
9370 88 : const char *desc = data->d_buf + desc_offset;
9371 :
9372 : char buf[100];
9373 : char buf2[100];
9374 352 : printf (gettext (" %-13.*s %9" PRId32 " %s\n"),
9375 88 : (int) nhdr.n_namesz, name, nhdr.n_descsz,
9376 88 : ehdr->e_type == ET_CORE
9377 54 : ? ebl_core_note_type_name (ebl, nhdr.n_type,
9378 : buf, sizeof (buf))
9379 34 : : ebl_object_note_type_name (ebl, name, nhdr.n_type,
9380 : buf2, sizeof (buf2)));
9381 :
9382 : /* Filter out invalid entries. */
9383 : if (memchr (name, '\0', nhdr.n_namesz) != NULL
9384 : /* XXX For now help broken Linux kernels. */
9385 : || 1)
9386 : {
9387 88 : if (ehdr->e_type == ET_CORE)
9388 : {
9389 54 : if (nhdr.n_type == NT_AUXV
9390 8 : && (nhdr.n_namesz == 4 /* Broken old Linux kernels. */
9391 8 : || (nhdr.n_namesz == 5 && name[4] == '\0'))
9392 8 : && !memcmp (name, "CORE", 4))
9393 8 : handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
9394 : start + desc_offset);
9395 46 : else if (nhdr.n_namesz == 5 && strcmp (name, "CORE") == 0)
9396 34 : switch (nhdr.n_type)
9397 : {
9398 : case NT_SIGINFO:
9399 5 : handle_siginfo_note (ebl->elf, nhdr.n_descsz,
9400 : start + desc_offset);
9401 : break;
9402 :
9403 : case NT_FILE:
9404 5 : handle_file_note (ebl->elf, nhdr.n_descsz,
9405 : start + desc_offset);
9406 : break;
9407 :
9408 : default:
9409 24 : handle_core_note (ebl, &nhdr, name, desc);
9410 : }
9411 : else
9412 12 : handle_core_note (ebl, &nhdr, name, desc);
9413 : }
9414 : else
9415 34 : ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc);
9416 : }
9417 : }
9418 :
9419 42 : if (offset == data->d_size)
9420 42 : return;
9421 :
9422 : bad_note:
9423 0 : error (EXIT_FAILURE, 0,
9424 0 : gettext ("cannot get content of note section: %s"),
9425 : elf_errmsg (-1));
9426 : }
9427 :
9428 : static void
9429 42 : handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
9430 : {
9431 : /* If we have section headers, just look for SHT_NOTE sections.
9432 : In a debuginfo file, the program headers are not reliable. */
9433 42 : if (shnum != 0)
9434 : {
9435 : /* Get the section header string table index. */
9436 : size_t shstrndx;
9437 33 : if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
9438 : error (EXIT_FAILURE, 0,
9439 0 : gettext ("cannot get section header string table index"));
9440 :
9441 : Elf_Scn *scn = NULL;
9442 905 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
9443 : {
9444 : GElf_Shdr shdr_mem;
9445 872 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
9446 :
9447 872 : if (shdr == NULL || shdr->sh_type != SHT_NOTE)
9448 : /* Not what we are looking for. */
9449 839 : continue;
9450 :
9451 99 : printf (gettext ("\
9452 : \nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
9453 : elf_ndxscn (scn),
9454 33 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
9455 : shdr->sh_size, shdr->sh_offset);
9456 :
9457 33 : handle_notes_data (ebl, ehdr, shdr->sh_offset,
9458 : elf_getdata (scn, NULL));
9459 : }
9460 : return;
9461 : }
9462 :
9463 : /* We have to look through the program header to find the note
9464 : sections. There can be more than one. */
9465 102 : for (size_t cnt = 0; cnt < phnum; ++cnt)
9466 : {
9467 : GElf_Phdr mem;
9468 102 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
9469 :
9470 102 : if (phdr == NULL || phdr->p_type != PT_NOTE)
9471 : /* Not what we are looking for. */
9472 93 : continue;
9473 :
9474 18 : printf (gettext ("\
9475 : \nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
9476 : phdr->p_filesz, phdr->p_offset);
9477 :
9478 18 : handle_notes_data (ebl, ehdr, phdr->p_offset,
9479 : elf_getdata_rawchunk (ebl->elf,
9480 9 : phdr->p_offset, phdr->p_filesz,
9481 : ELF_T_NHDR));
9482 : }
9483 : }
9484 :
9485 :
9486 : static void
9487 5 : hex_dump (const uint8_t *data, size_t len)
9488 : {
9489 5 : size_t pos = 0;
9490 31 : while (pos < len)
9491 : {
9492 21 : printf (" 0x%08zx ", pos);
9493 :
9494 21 : const size_t chunk = MIN (len - pos, 16);
9495 :
9496 342 : for (size_t i = 0; i < chunk; ++i)
9497 321 : if (i % 4 == 3)
9498 80 : printf ("%02x ", data[pos + i]);
9499 : else
9500 241 : printf ("%02x", data[pos + i]);
9501 :
9502 21 : if (chunk < 16)
9503 1 : printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
9504 :
9505 321 : for (size_t i = 0; i < chunk; ++i)
9506 : {
9507 321 : unsigned char b = data[pos + i];
9508 642 : printf ("%c", isprint (b) ? b : '.');
9509 : }
9510 :
9511 21 : putchar ('\n');
9512 21 : pos += chunk;
9513 : }
9514 5 : }
9515 :
9516 : static void
9517 5 : dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
9518 : {
9519 5 : if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
9520 0 : printf (gettext ("\nSection [%zu] '%s' has no data to dump.\n"),
9521 : elf_ndxscn (scn), name);
9522 : else
9523 : {
9524 5 : if (print_decompress)
9525 : {
9526 : /* We try to decompress the section, but keep the old shdr around
9527 : so we can show both the original shdr size and the uncompressed
9528 : data size. */
9529 4 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
9530 : {
9531 2 : if (elf_compress (scn, 0, 0) < 0)
9532 0 : printf ("WARNING: %s [%zd]\n",
9533 : gettext ("Couldn't uncompress section"),
9534 : elf_ndxscn (scn));
9535 : }
9536 2 : else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
9537 : {
9538 2 : if (elf_compress_gnu (scn, 0, 0) < 0)
9539 0 : printf ("WARNING: %s [%zd]\n",
9540 : gettext ("Couldn't uncompress section"),
9541 : elf_ndxscn (scn));
9542 : }
9543 : }
9544 :
9545 5 : Elf_Data *data = elf_rawdata (scn, NULL);
9546 5 : if (data == NULL)
9547 0 : error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
9548 : elf_ndxscn (scn), name, elf_errmsg (-1));
9549 : else
9550 : {
9551 5 : if (data->d_size == shdr->sh_size)
9552 1 : printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
9553 : " bytes at offset %#0" PRIx64 ":\n"),
9554 : elf_ndxscn (scn), name,
9555 : shdr->sh_size, shdr->sh_offset);
9556 : else
9557 4 : printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
9558 : " bytes (%zd uncompressed) at offset %#0"
9559 : PRIx64 ":\n"),
9560 : elf_ndxscn (scn), name,
9561 : shdr->sh_size, data->d_size, shdr->sh_offset);
9562 5 : hex_dump (data->d_buf, data->d_size);
9563 : }
9564 : }
9565 5 : }
9566 :
9567 : static void
9568 75 : print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
9569 : {
9570 75 : if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
9571 0 : printf (gettext ("\nSection [%zu] '%s' has no strings to dump.\n"),
9572 : elf_ndxscn (scn), name);
9573 : else
9574 : {
9575 75 : if (print_decompress)
9576 : {
9577 : /* We try to decompress the section, but keep the old shdr around
9578 : so we can show both the original shdr size and the uncompressed
9579 : data size. */
9580 1 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
9581 : {
9582 0 : if (elf_compress (scn, 0, 0) < 0)
9583 0 : printf ("WARNING: %s [%zd]\n",
9584 : gettext ("Couldn't uncompress section"),
9585 : elf_ndxscn (scn));
9586 : }
9587 1 : else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
9588 : {
9589 1 : if (elf_compress_gnu (scn, 0, 0) < 0)
9590 0 : printf ("WARNING: %s [%zd]\n",
9591 : gettext ("Couldn't uncompress section"),
9592 : elf_ndxscn (scn));
9593 : }
9594 : }
9595 :
9596 75 : Elf_Data *data = elf_rawdata (scn, NULL);
9597 75 : if (data == NULL)
9598 0 : error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
9599 : elf_ndxscn (scn), name, elf_errmsg (-1));
9600 : else
9601 : {
9602 75 : if (data->d_size == shdr->sh_size)
9603 74 : printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
9604 : " bytes at offset %#0" PRIx64 ":\n"),
9605 : elf_ndxscn (scn), name,
9606 : shdr->sh_size, shdr->sh_offset);
9607 : else
9608 1 : printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
9609 : " bytes (%zd uncompressed) at offset %#0"
9610 : PRIx64 ":\n"),
9611 : elf_ndxscn (scn), name,
9612 : shdr->sh_size, data->d_size, shdr->sh_offset);
9613 :
9614 75 : const char *start = data->d_buf;
9615 75 : const char *const limit = start + data->d_size;
9616 : do
9617 : {
9618 15563 : const char *end = memchr (start, '\0', limit - start);
9619 15563 : const size_t pos = start - (const char *) data->d_buf;
9620 15563 : if (unlikely (end == NULL))
9621 : {
9622 0 : printf (" [%6zx]- %.*s\n",
9623 : pos, (int) (limit - start), start);
9624 : break;
9625 : }
9626 15563 : printf (" [%6zx] %s\n", pos, start);
9627 15563 : start = end + 1;
9628 15563 : } while (start < limit);
9629 : }
9630 : }
9631 75 : }
9632 :
9633 : static void
9634 38 : for_each_section_argument (Elf *elf, const struct section_argument *list,
9635 : void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
9636 : const char *name))
9637 : {
9638 : /* Get the section header string table index. */
9639 : size_t shstrndx;
9640 38 : if (elf_getshdrstrndx (elf, &shstrndx) < 0)
9641 : error (EXIT_FAILURE, 0,
9642 0 : gettext ("cannot get section header string table index"));
9643 :
9644 102 : for (const struct section_argument *a = list; a != NULL; a = a->next)
9645 : {
9646 : Elf_Scn *scn;
9647 : GElf_Shdr shdr_mem;
9648 102 : const char *name = NULL;
9649 :
9650 102 : char *endp = NULL;
9651 102 : unsigned long int shndx = strtoul (a->arg, &endp, 0);
9652 102 : if (endp != a->arg && *endp == '\0')
9653 : {
9654 0 : scn = elf_getscn (elf, shndx);
9655 0 : if (scn == NULL)
9656 : {
9657 0 : error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
9658 0 : continue;
9659 : }
9660 :
9661 0 : if (gelf_getshdr (scn, &shdr_mem) == NULL)
9662 0 : error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
9663 : elf_errmsg (-1));
9664 0 : name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
9665 : }
9666 : else
9667 : {
9668 : /* Need to look up the section by name. */
9669 : scn = NULL;
9670 : bool found = false;
9671 2736 : while ((scn = elf_nextscn (elf, scn)) != NULL)
9672 : {
9673 2634 : if (gelf_getshdr (scn, &shdr_mem) == NULL)
9674 0 : continue;
9675 2634 : name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
9676 2634 : if (name == NULL)
9677 0 : continue;
9678 2634 : if (!strcmp (name, a->arg))
9679 : {
9680 80 : found = true;
9681 80 : (*dump) (scn, &shdr_mem, name);
9682 : }
9683 : }
9684 :
9685 102 : if (unlikely (!found) && !a->implicit)
9686 0 : error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
9687 : }
9688 : }
9689 38 : }
9690 :
9691 : static void
9692 : dump_data (Ebl *ebl)
9693 : {
9694 5 : for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
9695 : }
9696 :
9697 : static void
9698 : dump_strings (Ebl *ebl)
9699 : {
9700 33 : for_each_section_argument (ebl->elf, string_sections, &print_string_section);
9701 : }
9702 :
9703 : static void
9704 0 : print_strings (Ebl *ebl)
9705 : {
9706 : /* Get the section header string table index. */
9707 : size_t shstrndx;
9708 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
9709 : error (EXIT_FAILURE, 0,
9710 0 : gettext ("cannot get section header string table index"));
9711 :
9712 : Elf_Scn *scn;
9713 : GElf_Shdr shdr_mem;
9714 : const char *name;
9715 : scn = NULL;
9716 0 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
9717 : {
9718 0 : if (gelf_getshdr (scn, &shdr_mem) == NULL)
9719 0 : continue;
9720 :
9721 0 : if (shdr_mem.sh_type != SHT_PROGBITS
9722 0 : || !(shdr_mem.sh_flags & SHF_STRINGS))
9723 0 : continue;
9724 :
9725 0 : name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
9726 0 : if (name == NULL)
9727 0 : continue;
9728 :
9729 0 : print_string_section (scn, &shdr_mem, name);
9730 : }
9731 0 : }
9732 :
9733 : static void
9734 2 : dump_archive_index (Elf *elf, const char *fname)
9735 : {
9736 : size_t narsym;
9737 2 : const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
9738 2 : if (arsym == NULL)
9739 : {
9740 0 : int result = elf_errno ();
9741 0 : if (unlikely (result != ELF_E_NO_INDEX))
9742 0 : error (EXIT_FAILURE, 0,
9743 0 : gettext ("cannot get symbol index of archive '%s': %s"),
9744 : fname, elf_errmsg (result));
9745 : else
9746 0 : printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
9747 0 : return;
9748 : }
9749 :
9750 4 : printf (gettext ("\nIndex of archive '%s' has %zu entries:\n"),
9751 : fname, narsym);
9752 :
9753 2 : size_t as_off = 0;
9754 11 : for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
9755 : {
9756 9 : if (s->as_off != as_off)
9757 : {
9758 6 : as_off = s->as_off;
9759 :
9760 6 : Elf *subelf = NULL;
9761 6 : if (unlikely (elf_rand (elf, as_off) == 0)
9762 6 : || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
9763 : == NULL))
9764 : #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
9765 : while (1)
9766 : #endif
9767 0 : error (EXIT_FAILURE, 0,
9768 0 : gettext ("cannot extract member at offset %zu in '%s': %s"),
9769 : as_off, fname, elf_errmsg (-1));
9770 :
9771 6 : const Elf_Arhdr *h = elf_getarhdr (subelf);
9772 :
9773 12 : printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
9774 :
9775 6 : elf_end (subelf);
9776 : }
9777 :
9778 18 : printf ("\t%s\n", s->as_name);
9779 : }
9780 : }
9781 :
9782 : #include "debugpred.h"
|