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 181 : main (int argc, char *argv[])
281 : {
282 : /* Set locale. */
283 181 : setlocale (LC_ALL, "");
284 :
285 : /* Initialize the message catalog. */
286 181 : textdomain (PACKAGE_TARNAME);
287 :
288 : /* Parse and process arguments. */
289 : int remaining;
290 181 : argp_parse (&argp, argc, argv, 0, &remaining, NULL);
291 :
292 : /* Before we start tell the ELF library which version we are using. */
293 181 : elf_version (EV_CURRENT);
294 :
295 : /* Now process all the files given at the command line. */
296 181 : bool only_one = remaining + 1 == argc;
297 : do
298 : {
299 : /* Open the file. */
300 364 : int fd = open (argv[remaining], O_RDONLY);
301 182 : if (fd == -1)
302 : {
303 0 : error (0, errno, gettext ("cannot open input file"));
304 0 : continue;
305 : }
306 :
307 182 : process_file (fd, argv[remaining], only_one);
308 :
309 182 : close (fd);
310 : }
311 182 : while (++remaining < argc);
312 :
313 181 : return error_message_count != 0;
314 : }
315 :
316 :
317 : /* Handle program arguments. */
318 : static error_t
319 1138 : 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 1138 : switch (key)
335 : {
336 32 : 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 4 : case 'A':
355 4 : print_arch = true;
356 4 : any_control_option = true;
357 4 : break;
358 2 : case 'd':
359 2 : print_dynamic_table = true;
360 2 : any_control_option = true;
361 2 : break;
362 0 : case 'e':
363 0 : print_debug_sections |= section_exception;
364 0 : any_control_option = true;
365 0 : break;
366 0 : case 'g':
367 0 : print_section_groups = true;
368 0 : any_control_option = true;
369 0 : break;
370 0 : case 'h':
371 0 : print_file_header = true;
372 0 : any_control_option = true;
373 0 : break;
374 0 : case 'I':
375 0 : print_histogram = true;
376 0 : any_control_option = true;
377 0 : break;
378 0 : case 'l':
379 0 : print_program_header = true;
380 0 : any_control_option = true;
381 0 : break;
382 10 : case 'n':
383 10 : print_notes = true;
384 10 : any_control_option = true;
385 10 : break;
386 1 : case 'r':
387 1 : print_relocations = true;
388 1 : any_control_option = true;
389 1 : break;
390 54 : case 'S':
391 54 : print_section_header = true;
392 54 : any_control_option = true;
393 54 : break;
394 14 : case 's':
395 14 : print_symbol_table = true;
396 14 : any_control_option = true;
397 14 : symbol_table_section = arg;
398 14 : break;
399 0 : case 'V':
400 0 : print_version_info = true;
401 0 : any_control_option = true;
402 0 : break;
403 2 : case 'c':
404 2 : print_archive_index = true;
405 2 : break;
406 71 : 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 1 : 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 1 : case 'N':
474 1 : print_address_names = false;
475 1 : break;
476 19 : case 'U':
477 19 : print_unresolved_addresses = true;
478 19 : break;
479 0 : case ARGP_KEY_NO_ARGS:
480 0 : fputs (gettext ("Missing file name.\n"), stderr);
481 0 : goto do_argp_help;
482 181 : case ARGP_KEY_FINI:
483 181 : if (! any_control_option && ! print_archive_index)
484 : {
485 0 : fputs (gettext ("No operation specified.\n"), stderr);
486 0 : 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 13 : case 'z':
495 13 : print_decompress = true;
496 13 : break;
497 4 : 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 0 : 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 178 : 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 178 : if (*(bool *) arg)
663 : return DWARF_CB_ABORT;
664 178 : *(bool *) arg = true;
665 178 : 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 180 : 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 180 : const struct process_dwflmod_args *a = arg;
682 :
683 : /* Print the file name. */
684 180 : 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 180 : process_elf_file (dwflmod, a->fd);
693 :
694 180 : 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 182 : process_file (int fd, const char *fname, bool only_one)
728 : {
729 182 : if (print_archive_index)
730 2 : check_archive_index (fd, fname, only_one);
731 :
732 182 : if (!any_control_option)
733 : return;
734 :
735 180 : 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 180 : int dwfl_fd = dup (fd);
752 180 : 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 180 : Dwfl *dwfl = dwfl_begin (&callbacks);
763 180 : if (likely (dwfl != NULL))
764 : /* Let 0 be the logical address of the file (or first in archive). */
765 180 : dwfl->offline_next_address = 0;
766 180 : 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 180 : dwfl_report_end (dwfl, NULL, NULL);
781 :
782 180 : if (only_one)
783 : {
784 : /* Clear ONLY_ONE if we have multiple modules, from an archive. */
785 178 : bool seen = false;
786 178 : only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
787 : }
788 :
789 : /* Process the one or more modules gleaned from this file. */
790 180 : struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
791 180 : dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
792 : }
793 180 : dwfl_end (dwfl);
794 :
795 : /* Need to close the replaced fd if we created it. Caller takes
796 : care of original. */
797 180 : 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 75 : elf_contains_chdrs (Elf *elf)
804 : {
805 75 : Elf_Scn *scn = NULL;
806 1819 : while ((scn = elf_nextscn (elf, scn)) != NULL)
807 : {
808 : GElf_Shdr shdr_mem;
809 1675 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
810 1675 : 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 180 : process_elf_file (Dwfl_Module *dwflmod, int fd)
819 : {
820 : GElf_Addr dwflbias;
821 180 : Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
822 :
823 : GElf_Ehdr ehdr_mem;
824 180 : GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
825 :
826 180 : if (ehdr == NULL)
827 : {
828 0 : elf_error:
829 0 : error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
830 0 : return;
831 : }
832 :
833 180 : Ebl *ebl = ebl_openbackend (elf);
834 180 : if (unlikely (ebl == NULL))
835 : {
836 0 : ebl_error:
837 0 : error (0, errno, gettext ("cannot create EBL handle"));
838 : return;
839 : }
840 :
841 : /* Determine the number of sections. */
842 180 : 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 180 : 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 360 : bool print_unchanged = ((print_section_header
859 94 : || print_relocations
860 93 : || dump_data_sections != NULL
861 88 : || print_notes)
862 282 : && (ehdr->e_type == ET_REL
863 75 : || elf_contains_chdrs (ebl->elf)));
864 :
865 180 : Elf *pure_elf = NULL;
866 180 : Ebl *pure_ebl = ebl;
867 180 : if (print_unchanged)
868 : {
869 : /* Read the file afresh. */
870 33 : off_t aroff = elf_getaroff (elf);
871 33 : pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
872 33 : 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 33 : if (pure_elf == NULL)
881 : goto elf_error;
882 33 : pure_ebl = ebl_openbackend (pure_elf);
883 33 : if (pure_ebl == NULL)
884 : goto ebl_error;
885 : }
886 :
887 180 : if (print_file_header)
888 32 : print_ehdr (ebl, ehdr);
889 180 : if (print_section_header)
890 86 : print_shdr (pure_ebl, ehdr);
891 180 : if (print_program_header)
892 32 : print_phdr (ebl, ehdr);
893 180 : if (print_section_groups)
894 32 : print_scngrp (ebl);
895 180 : if (print_dynamic_table)
896 34 : print_dynamic (ebl);
897 180 : if (print_relocations)
898 33 : print_relocs (pure_ebl, ehdr);
899 180 : if (print_histogram)
900 32 : handle_hash (ebl);
901 180 : if (print_symbol_table)
902 46 : print_symtab (ebl, SHT_DYNSYM);
903 180 : if (print_version_info)
904 32 : print_verinfo (ebl);
905 180 : if (print_symbol_table)
906 46 : print_symtab (ebl, SHT_SYMTAB);
907 180 : if (print_arch)
908 36 : print_liblist (ebl);
909 180 : if (print_arch)
910 36 : print_attributes (ebl, ehdr);
911 180 : if (dump_data_sections != NULL)
912 5 : dump_data (pure_ebl);
913 180 : if (string_sections != NULL)
914 33 : dump_strings (ebl);
915 180 : if ((print_debug_sections | implicit_debug_sections) != 0)
916 89 : print_debug (dwflmod, ebl, ehdr);
917 180 : if (print_notes)
918 42 : handle_notes (pure_ebl, ehdr);
919 180 : if (print_string_sections)
920 0 : print_strings (ebl);
921 :
922 180 : ebl_closebackend (ebl);
923 :
924 180 : if (pure_ebl != ebl)
925 : {
926 33 : ebl_closebackend (pure_ebl);
927 33 : 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 86 : print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
1102 : {
1103 : size_t cnt;
1104 : size_t shstrndx;
1105 :
1106 86 : if (! print_file_header)
1107 108 : printf (gettext ("\
1108 : There are %d section headers, starting at offset %#" PRIx64 ":\n\
1109 : \n"),
1110 54 : ehdr->e_shnum, ehdr->e_shoff);
1111 :
1112 : /* Get the section header string table index. */
1113 86 : 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 86 : puts (gettext ("Section Headers:"));
1118 :
1119 86 : if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1120 34 : puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
1121 : else
1122 52 : puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
1123 :
1124 86 : 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 2221 : for (cnt = 0; cnt < shnum; ++cnt)
1133 : {
1134 2221 : Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
1135 :
1136 2221 : 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 2221 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1143 2221 : 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 2221 : char *cp = flagbuf;
1149 2221 : if (shdr->sh_flags & SHF_WRITE)
1150 492 : *cp++ = 'W';
1151 2221 : if (shdr->sh_flags & SHF_ALLOC)
1152 1457 : *cp++ = 'A';
1153 2221 : if (shdr->sh_flags & SHF_EXECINSTR)
1154 271 : *cp++ = 'X';
1155 2221 : if (shdr->sh_flags & SHF_MERGE)
1156 102 : *cp++ = 'M';
1157 2221 : if (shdr->sh_flags & SHF_STRINGS)
1158 102 : *cp++ = 'S';
1159 2221 : if (shdr->sh_flags & SHF_INFO_LINK)
1160 105 : *cp++ = 'I';
1161 2221 : if (shdr->sh_flags & SHF_LINK_ORDER)
1162 2 : *cp++ = 'L';
1163 2221 : if (shdr->sh_flags & SHF_OS_NONCONFORMING)
1164 0 : *cp++ = 'N';
1165 2221 : if (shdr->sh_flags & SHF_GROUP)
1166 0 : *cp++ = 'G';
1167 2221 : if (shdr->sh_flags & SHF_TLS)
1168 10 : *cp++ = 'T';
1169 2221 : if (shdr->sh_flags & SHF_COMPRESSED)
1170 12 : *cp++ = 'C';
1171 2221 : if (shdr->sh_flags & SHF_ORDERED)
1172 0 : *cp++ = 'O';
1173 2221 : if (shdr->sh_flags & SHF_EXCLUDE)
1174 0 : *cp++ = 'E';
1175 2221 : *cp = '\0';
1176 :
1177 : const char *sname;
1178 : char buf[128];
1179 2221 : sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "<corrupt>";
1180 8884 : 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 2221 : 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 2221 : 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 2221 : 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 172 : fputc_unlocked ('\n', stdout);
1223 86 : }
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 3916 : for (size_t inner = 1; inner < shnum; ++inner)
1335 : {
1336 3916 : Elf_Scn *scn = elf_getscn (ebl->elf, inner);
1337 : /* This should not happen. */
1338 3916 : 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 3916 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1345 3916 : if (unlikely (shdr == NULL))
1346 0 : error (EXIT_FAILURE, 0,
1347 0 : gettext ("cannot get section header: %s"),
1348 : elf_errmsg (-1));
1349 :
1350 3916 : if (shdr->sh_size > 0
1351 : /* Compare allocated sections by VMA, unallocated
1352 : sections by file offset. */
1353 7832 : && (shdr->sh_flags & SHF_ALLOC
1354 2866 : ? (shdr->sh_addr >= phdr->p_vaddr
1355 4706 : && (shdr->sh_addr + shdr->sh_size
1356 1840 : <= 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 444 : if (has_relro && !in_relro
1362 316 : && 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 398 : else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
1369 : {
1370 12 : fputs_unlocked ("]", stdout);
1371 12 : in_relro = false;
1372 : }
1373 386 : else if (has_relro && in_relro
1374 116 : && shdr->sh_addr + shdr->sh_size > relro_to)
1375 0 : fputs_unlocked ("] <RELRO:", stdout);
1376 386 : else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
1377 : {
1378 206 : 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 396 : for (cnt2 = 0; cnt2 < phnum; ++cnt2)
1391 : {
1392 576 : phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
1393 :
1394 576 : if (phdr2 != NULL && phdr2->p_type == PT_LOAD
1395 320 : && shdr->sh_addr >= phdr2->p_vaddr
1396 640 : && (shdr->sh_addr + shdr->sh_size
1397 320 : <= phdr2->p_vaddr + phdr2->p_memsz))
1398 : break;
1399 : }
1400 :
1401 180 : if (cnt2 < phnum)
1402 : {
1403 180 : if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
1404 : {
1405 32 : fputs_unlocked (" [RO:", stdout);
1406 32 : in_ro = true;
1407 : }
1408 148 : 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 888 : printf (" %s",
1417 444 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1418 :
1419 : /* Signal that this sectin is only partially covered. */
1420 444 : if (has_relro && in_relro
1421 162 : && 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 0 : 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 930 : 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 866 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1514 :
1515 866 : 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 86 : 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 63 : 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 3 : 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 1 : 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 2 : 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 105 : 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 27 : 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 14 : 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 1 : case DT_FLAGS:
1759 1 : print_dt_flags (class, dyn->d_un.d_val);
1760 : break;
1761 :
1762 1 : case DT_FLAGS_1:
1763 1 : print_dt_flags_1 (class, dyn->d_un.d_val);
1764 : break;
1765 :
1766 1 : case DT_FEATURE_1:
1767 1 : print_dt_feature_1 (class, dyn->d_un.d_val);
1768 : break;
1769 :
1770 1 : case DT_POSFLAG_1:
1771 1 : print_dt_posflag_1 (class, dyn->d_un.d_val);
1772 : break;
1773 :
1774 192 : 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 966 : 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 900 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1817 :
1818 900 : if (likely (shdr != NULL))
1819 : {
1820 900 : if (shdr->sh_type == SHT_REL)
1821 8 : handle_relocs_rel (ebl, ehdr, scn, shdr);
1822 892 : else if (shdr->sh_type == SHT_RELA)
1823 139 : 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 139 : handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
2022 : {
2023 139 : int class = gelf_getclass (ebl->elf);
2024 139 : size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
2025 139 : int nentries = shdr->sh_size / sh_entsize;
2026 :
2027 : /* Get the data of the section. */
2028 139 : Elf_Data *data = elf_getdata (scn, NULL);
2029 139 : if (data == NULL)
2030 0 : return;
2031 :
2032 : /* Get the symbol table information. */
2033 139 : Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2034 : GElf_Shdr symshdr_mem;
2035 139 : GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2036 139 : 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 139 : GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
2041 : &destshdr_mem);
2042 :
2043 139 : 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 139 : Elf_Data *xndxdata = NULL;
2052 139 : int xndxscnidx = elf_scnshndx (scn);
2053 139 : 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 139 : 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 139 : if (shdr->sh_info != 0)
2063 381 : 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 127 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2070 127 : (unsigned int) shdr->sh_info,
2071 127 : 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 139 : 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 139 : int is_statically_linked = 0;
2095 21824 : for (int cnt = 0; cnt < nentries; ++cnt)
2096 : {
2097 : GElf_Rela relmem;
2098 21685 : GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
2099 21685 : if (likely (rel != NULL))
2100 : {
2101 : char buf[64];
2102 : GElf_Sym symmem;
2103 : Elf32_Word xndx;
2104 21685 : GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
2105 21685 : GELF_R_SYM (rel->r_info),
2106 : &symmem, &xndx);
2107 :
2108 21685 : 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 21685 : else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
2161 23092 : printf ("\
2162 : %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
2163 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2164 5773 : 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 5773 : ? 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 11546 : 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 15912 : secshdr = gelf_getshdr (elf_getscn (ebl->elf,
2180 15912 : sym->st_shndx == SHN_XINDEX
2181 0 : ? xndx : sym->st_shndx),
2182 : &secshdr_mem);
2183 :
2184 15912 : 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 47736 : printf ("\
2198 : %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
2199 : class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2200 15912 : ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2201 : /* Avoid the leading R_ which isn't carrying any
2202 : information. */
2203 15912 : ? 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 15912 : 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 2674 : 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 2490 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2228 :
2229 2490 : 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 17150 : 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 17094 : GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
2355 :
2356 17094 : if (unlikely (sym == NULL))
2357 0 : continue;
2358 :
2359 : /* Determine the real section index. */
2360 17094 : if (likely (sym->st_shndx != SHN_XINDEX))
2361 17094 : xndx = sym->st_shndx;
2362 :
2363 119658 : 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 17094 : ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
2370 : typebuf, sizeof (typebuf)),
2371 17094 : ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
2372 : bindbuf, sizeof (bindbuf)),
2373 17094 : get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
2374 17094 : ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
2375 : sizeof (scnbuf), NULL, shnum),
2376 34188 : elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
2377 :
2378 17094 : if (versym_data != NULL)
2379 : {
2380 : /* Get the version information. */
2381 : GElf_Versym versym_mem;
2382 1562 : GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
2383 :
2384 1562 : if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
2385 : {
2386 1322 : bool is_nobits = false;
2387 1322 : bool check_def = xndx != SHN_UNDEF;
2388 :
2389 1322 : if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
2390 : {
2391 : GElf_Shdr symshdr_mem;
2392 1289 : GElf_Shdr *symshdr =
2393 1289 : gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
2394 :
2395 1289 : is_nobits = (symshdr != NULL
2396 1289 : && symshdr->sh_type == SHT_NOBITS);
2397 : }
2398 :
2399 1322 : if (is_nobits || ! check_def)
2400 : {
2401 : /* We must test both. */
2402 : GElf_Vernaux vernaux_mem;
2403 955 : GElf_Vernaux *vernaux = NULL;
2404 955 : size_t vn_offset = 0;
2405 :
2406 : GElf_Verneed verneed_mem;
2407 955 : GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
2408 : &verneed_mem);
2409 4860 : while (verneed != NULL)
2410 : {
2411 3905 : size_t vna_offset = vn_offset;
2412 :
2413 3905 : vernaux = gelf_getvernaux (verneed_data,
2414 3905 : vna_offset += verneed->vn_aux,
2415 : &vernaux_mem);
2416 11220 : while (vernaux != NULL
2417 7315 : && vernaux->vna_other != *versym
2418 6360 : && vernaux->vna_next != 0)
2419 : {
2420 : /* Update the offset. */
2421 3410 : vna_offset += vernaux->vna_next;
2422 :
2423 3410 : vernaux = (vernaux->vna_next == 0
2424 : ? NULL
2425 3410 : : gelf_getvernaux (verneed_data,
2426 : vna_offset,
2427 : &vernaux_mem));
2428 : }
2429 :
2430 : /* Check whether we found the version. */
2431 3905 : if (vernaux != NULL && vernaux->vna_other == *versym)
2432 : /* Found it. */
2433 : break;
2434 :
2435 2950 : vn_offset += verneed->vn_next;
2436 : verneed = (verneed->vn_next == 0
2437 : ? NULL
2438 2950 : : gelf_getverneed (verneed_data, vn_offset,
2439 : &verneed_mem));
2440 : }
2441 :
2442 955 : if (vernaux != NULL && vernaux->vna_other == *versym)
2443 : {
2444 2865 : printf ("@%s (%u)",
2445 : elf_strptr (ebl->elf, verneed_stridx,
2446 955 : vernaux->vna_name),
2447 : (unsigned int) vernaux->vna_other);
2448 955 : 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 367 : if (check_def && *versym != 0x8001)
2457 : {
2458 : /* We must test both. */
2459 367 : size_t vd_offset = 0;
2460 :
2461 : GElf_Verdef verdef_mem;
2462 367 : GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
2463 : &verdef_mem);
2464 2617 : while (verdef != NULL)
2465 : {
2466 2250 : if (verdef->vd_ndx == (*versym & 0x7fff))
2467 : /* Found the definition. */
2468 : break;
2469 :
2470 1883 : vd_offset += verdef->vd_next;
2471 : verdef = (verdef->vd_next == 0
2472 : ? NULL
2473 1883 : : gelf_getverdef (verdef_data, vd_offset,
2474 : &verdef_mem));
2475 : }
2476 :
2477 367 : if (verdef != NULL)
2478 : {
2479 : GElf_Verdaux verdaux_mem;
2480 367 : GElf_Verdaux *verdaux
2481 367 : = gelf_getverdaux (verdef_data,
2482 367 : vd_offset + verdef->vd_aux,
2483 : &verdaux_mem);
2484 :
2485 367 : if (verdaux != NULL)
2486 367 : printf ((*versym & 0x8000) ? "@%s" : "@@%s",
2487 : elf_strptr (ebl->elf, verdef_stridx,
2488 367 : verdaux->vda_name));
2489 : }
2490 : }
2491 : }
2492 : }
2493 :
2494 17094 : 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 930 : 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 866 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2512 :
2513 866 : if (likely (shdr != NULL))
2514 : {
2515 866 : if (shdr->sh_type == SHT_GNU_verneed)
2516 12 : handle_verneed (ebl, scn, shdr);
2517 854 : else if (shdr->sh_type == SHT_GNU_verdef)
2518 4 : handle_verdef (ebl, scn, shdr);
2519 850 : 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 132 : get_ver_flags (unsigned int flags)
2528 : {
2529 : static char buf[32];
2530 : char *endp;
2531 :
2532 132 : if (flags == 0)
2533 127 : 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 41 : for (int cnt = shdr->sh_info; --cnt >= 0; )
2673 : {
2674 : /* Get the data at the next offset. */
2675 : GElf_Verdef defmem;
2676 37 : GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
2677 37 : if (unlikely (def == NULL))
2678 : break;
2679 :
2680 37 : unsigned int auxoffset = offset + def->vd_aux;
2681 : GElf_Verdaux auxmem;
2682 37 : GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
2683 37 : if (unlikely (aux == NULL))
2684 : break;
2685 :
2686 259 : printf (gettext ("\
2687 : %#06x: Version: %hd Flags: %s Index: %hd Cnt: %hd Name: %s\n"),
2688 37 : offset, def->vd_version,
2689 37 : get_ver_flags (def->vd_flags),
2690 37 : def->vd_ndx,
2691 37 : def->vd_cnt,
2692 74 : elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2693 :
2694 37 : auxoffset += aux->vda_next;
2695 37 : for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
2696 : {
2697 29 : aux = gelf_getverdaux (data, auxoffset, &auxmem);
2698 29 : if (unlikely (aux == NULL))
2699 : break;
2700 :
2701 87 : printf (gettext (" %#06x: Parent %d: %s\n"),
2702 : auxoffset, cnt2,
2703 58 : elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2704 :
2705 29 : if (aux->vda_next == 0)
2706 : break;
2707 :
2708 0 : auxoffset += aux->vda_next;
2709 : }
2710 :
2711 : /* Find the next offset. */
2712 37 : if (def->vd_next == 0)
2713 : break;
2714 33 : 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 440 : while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
2744 : {
2745 : GElf_Shdr vershdr_mem;
2746 428 : GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
2747 :
2748 428 : if (likely (vershdr != NULL))
2749 : {
2750 428 : if (vershdr->sh_type == SHT_GNU_verdef)
2751 : defscn = verscn;
2752 424 : 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 33 : 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 37 : def = gelf_getverdef (defdata, offset, &defmem);
2787 37 : if (unlikely (def == NULL))
2788 : break;
2789 :
2790 37 : nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
2791 :
2792 37 : if (def->vd_next == 0)
2793 : break;
2794 33 : 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 33 : 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 37 : GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
2882 37 : if (unlikely (def == NULL))
2883 : break;
2884 :
2885 : GElf_Verdaux auxmem;
2886 37 : GElf_Verdaux *aux = gelf_getverdaux (defdata,
2887 37 : offset + def->vd_aux,
2888 : &auxmem);
2889 37 : if (unlikely (aux == NULL))
2890 : break;
2891 :
2892 37 : vername[def->vd_ndx & 0x7fff]
2893 74 : = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
2894 37 : filename[def->vd_ndx & 0x7fff] = NULL;
2895 :
2896 37 : if (def->vd_next == 0)
2897 : break;
2898 33 : 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 190 : = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
2932 95 : filename[aux->vna_other & 0x7fff]
2933 190 : = 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 1487 : for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
2977 : {
2978 1475 : if (cnt % 2 == 0)
2979 : printf ("\n %4d:", cnt);
2980 :
2981 : GElf_Versym symmem;
2982 1475 : GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
2983 1475 : if (sym == NULL)
2984 : break;
2985 :
2986 1475 : switch (*sym)
2987 : {
2988 : ssize_t n;
2989 125 : case 0:
2990 125 : fputs_unlocked (gettext (" 0 *local* "),
2991 : stdout);
2992 : break;
2993 :
2994 41 : case 1:
2995 41 : fputs_unlocked (gettext (" 1 *global* "),
2996 : stdout);
2997 : break;
2998 :
2999 1309 : default:
3000 5236 : n = printf ("%4d%c%s",
3001 1309 : *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
3002 : (vername != NULL
3003 1309 : && (unsigned int) (*sym & 0x7fff) < nvername)
3004 1309 : ? vername[*sym & 0x7fff] : "???");
3005 1309 : if ((unsigned int) (*sym & 0x7fff) < nvername
3006 1309 : && filename != NULL && filename[*sym & 0x7fff] != NULL)
3007 1884 : n += printf ("(%s)", filename[*sym & 0x7fff]);
3008 1309 : 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 67 : for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
3066 : {
3067 55 : nzero_counts += counts[cnt] * cnt;
3068 165 : printf (gettext ("\
3069 : %7d %6" PRIu32 " %5.1f%% %5.1f%%\n"),
3070 55 : (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
3071 55 : (nzero_counts * 100.0) / nsyms);
3072 : }
3073 :
3074 : Elf32_Word acc = 0;
3075 55 : for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
3076 : {
3077 55 : acc += cnt;
3078 55 : 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 0 : 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 0 : 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 0 : 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 226 : Elf32_Word inner = bucket[cnt] - symbias;
3262 : do
3263 : {
3264 438 : ++nsyms;
3265 438 : if (maxlength < ++lengths[cnt])
3266 55 : ++maxlength;
3267 438 : if (inner >= max_nsyms)
3268 : goto invalid_data;
3269 : }
3270 438 : 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 898 : 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 866 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3323 :
3324 866 : if (likely (shdr != NULL))
3325 : {
3326 866 : 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 866 : 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 866 : 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 961 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3368 : {
3369 : GElf_Shdr shdr_mem;
3370 925 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3371 :
3372 925 : 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 961 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3431 : {
3432 : GElf_Shdr shdr_mem;
3433 925 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3434 :
3435 925 : if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
3436 922 : && (shdr->sh_type != SHT_ARM_ATTRIBUTES
3437 1 : || ehdr->e_machine != EM_ARM)))
3438 921 : 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 0 : default:
3524 : /* Unknown subsection, print and skip. */
3525 0 : printf (gettext (" %-4u %12" PRIu32 "\n"),
3526 : subsection_tag, subsection_len);
3527 : break;
3528 :
3529 4 : case 1: /* Tag_File */
3530 4 : printf (gettext (" File: %11" PRIu32 "\n"),
3531 : subsection_len);
3532 :
3533 26 : while (r < q)
3534 22 : {
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 626734 : 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 626734 : GElf_Off off = 0;
3616 1880188 : const char *name = (print_address_names && ! print_unresolved_addresses)
3617 626628 : ? dwfl_module_addrinfo (dwflmod, address, &off, &sym, NULL, NULL, NULL)
3618 1253362 : : NULL;
3619 :
3620 : const char *scn;
3621 626734 : if (print_unresolved_addresses)
3622 : {
3623 92 : address = raw;
3624 92 : scn = NULL;
3625 : }
3626 : else
3627 : {
3628 : /* Relativize the address. */
3629 626642 : int n = dwfl_module_relocations (dwflmod);
3630 626642 : 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 166214 : : dwfl_module_relocation_info (dwflmod, i, NULL));
3635 : }
3636 :
3637 : char *result;
3638 626734 : if ((name != NULL
3639 603043 : ? (off != 0
3640 : ? (scn != NULL
3641 : ? (address_size == 0
3642 90530 : ? asprintf (&result,
3643 45265 : gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
3644 : scn, address, name, off)
3645 319281 : : asprintf (&result,
3646 106427 : gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
3647 106427 : scn, 2 + address_size * 2, address,
3648 : name, off))
3649 : : (address_size == 0
3650 225712 : ? asprintf (&result,
3651 112856 : gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
3652 : address, name, off)
3653 936441 : : asprintf (&result,
3654 312147 : gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
3655 312147 : 2 + address_size * 2, address,
3656 : name, off)))
3657 : : (scn != NULL
3658 : ? (address_size == 0
3659 4354 : ? asprintf (&result,
3660 2177 : gettext ("%s+%#" PRIx64 " <%s>"),
3661 : scn, address, name)
3662 16410 : : asprintf (&result,
3663 5470 : gettext ("%s+%#0*" PRIx64 " <%s>"),
3664 5470 : scn, 2 + address_size * 2, address, name))
3665 : : (address_size == 0
3666 8072 : ? asprintf (&result,
3667 4036 : gettext ("%#" PRIx64 " <%s>"),
3668 : address, name)
3669 43995 : : asprintf (&result,
3670 14665 : gettext ("%#0*" PRIx64 " <%s>"),
3671 14665 : 2 + address_size * 2, address, name))))
3672 : : (scn != NULL
3673 : ? (address_size == 0
3674 4120 : ? asprintf (&result,
3675 2060 : gettext ("%s+%#" PRIx64),
3676 : scn, address)
3677 14445 : : asprintf (&result,
3678 4815 : gettext ("%s+%#0*" PRIx64),
3679 4815 : scn, 2 + address_size * 2, address))
3680 : : (address_size == 0
3681 4588 : ? asprintf (&result,
3682 : "%#" PRIx64,
3683 : address)
3684 43566 : : asprintf (&result,
3685 : "%#0*" PRIx64,
3686 1871033 : 2 + address_size * 2, address)))) < 0)
3687 0 : error (EXIT_FAILURE, 0, _("memory exhausted"));
3688 :
3689 626734 : return result;
3690 : }
3691 :
3692 : static const char *
3693 860146 : dwarf_tag_string (unsigned int tag)
3694 : {
3695 860146 : 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 0 : default:
3701 0 : return NULL;
3702 : }
3703 : }
3704 :
3705 :
3706 : static const char *
3707 3034732 : dwarf_attr_string (unsigned int attrnum)
3708 : {
3709 3034732 : 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 0 : default:
3715 0 : return NULL;
3716 : }
3717 : }
3718 :
3719 :
3720 : static const char *
3721 3034732 : dwarf_form_string (unsigned int form)
3722 : {
3723 3034732 : 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 0 : default:
3729 0 : return NULL;
3730 : }
3731 : }
3732 :
3733 :
3734 : static const char *
3735 1294 : dwarf_lang_string (unsigned int lang)
3736 : {
3737 1294 : 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 0 : 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 2943 : if (likely (code < sizeof (known) / sizeof (known[0])))
3759 2943 : 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 18838 : if (likely (code < sizeof (known) / sizeof (known[0])))
3776 18838 : 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_defaulted_string (unsigned int code)
3801 : {
3802 : static const char *const known[] =
3803 : {
3804 : #define DWARF_ONE_KNOWN_DW_DEFAULTED(NAME, CODE) [CODE] = #NAME,
3805 : DWARF_ALL_KNOWN_DW_DEFAULTED
3806 : #undef DWARF_ONE_KNOWN_DW_DEFAULTED
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_visibility_string (unsigned int code)
3818 : {
3819 : static const char *const known[] =
3820 : {
3821 : #define DWARF_ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
3822 : DWARF_ALL_KNOWN_DW_VIS
3823 : #undef DWARF_ONE_KNOWN_DW_VIS
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_virtuality_string (unsigned int code)
3835 : {
3836 : static const char *const known[] =
3837 : {
3838 : #define DWARF_ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
3839 : DWARF_ALL_KNOWN_DW_VIRTUALITY
3840 : #undef DWARF_ONE_KNOWN_DW_VIRTUALITY
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_identifier_case_string (unsigned int code)
3852 : {
3853 : static const char *const known[] =
3854 : {
3855 : #define DWARF_ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
3856 : DWARF_ALL_KNOWN_DW_ID
3857 : #undef DWARF_ONE_KNOWN_DW_ID
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_calling_convention_string (unsigned int code)
3869 : {
3870 : static const char *const known[] =
3871 : {
3872 : #define DWARF_ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
3873 : DWARF_ALL_KNOWN_DW_CC
3874 : #undef DWARF_ONE_KNOWN_DW_CC
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_ordering_string (unsigned int code)
3886 : {
3887 : static const char *const known[] =
3888 : {
3889 : #define DWARF_ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
3890 : DWARF_ALL_KNOWN_DW_ORD
3891 : #undef DWARF_ONE_KNOWN_DW_ORD
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_discr_list_string (unsigned int code)
3903 : {
3904 : static const char *const known[] =
3905 : {
3906 : #define DWARF_ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
3907 : DWARF_ALL_KNOWN_DW_DSC
3908 : #undef DWARF_ONE_KNOWN_DW_DSC
3909 : };
3910 :
3911 0 : if (likely (code < sizeof (known) / sizeof (known[0])))
3912 0 : return known[code];
3913 :
3914 : return NULL;
3915 : }
3916 :
3917 :
3918 : static const char *
3919 : dwarf_locexpr_opcode_string (unsigned int code)
3920 : {
3921 : static const char *const known[] =
3922 : {
3923 : /* Normally we can't affort building huge table of 64K entries,
3924 : most of them zero, just because there are a couple defined
3925 : values at the far end. In case of opcodes, it's OK. */
3926 : #define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
3927 : DWARF_ALL_KNOWN_DW_OP
3928 : #undef DWARF_ONE_KNOWN_DW_OP
3929 : };
3930 :
3931 401094 : if (likely (code < sizeof (known) / sizeof (known[0])))
3932 401094 : return known[code];
3933 :
3934 : return NULL;
3935 : }
3936 :
3937 :
3938 : /* Used by all dwarf_foo_name functions. */
3939 : static const char *
3940 6952685 : string_or_unknown (const char *known, unsigned int code,
3941 : unsigned int lo_user, unsigned int hi_user,
3942 : bool print_unknown_num)
3943 : {
3944 : static char unknown_buf[20];
3945 :
3946 6952685 : if (likely (known != NULL))
3947 : return known;
3948 :
3949 0 : if (lo_user != 0 && code >= lo_user && code <= hi_user)
3950 : {
3951 0 : snprintf (unknown_buf, sizeof unknown_buf, "lo_user+%#x",
3952 : code - lo_user);
3953 0 : return unknown_buf;
3954 : }
3955 :
3956 0 : if (print_unknown_num)
3957 : {
3958 0 : snprintf (unknown_buf, sizeof unknown_buf, "??? (%#x)", code);
3959 0 : return unknown_buf;
3960 : }
3961 :
3962 : return "???";
3963 : }
3964 :
3965 :
3966 : static const char *
3967 860146 : dwarf_tag_name (unsigned int tag)
3968 : {
3969 860146 : const char *ret = dwarf_tag_string (tag);
3970 860146 : return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true);
3971 : }
3972 :
3973 : static const char *
3974 3034732 : dwarf_attr_name (unsigned int attr)
3975 : {
3976 3034732 : const char *ret = dwarf_attr_string (attr);
3977 3034732 : return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true);
3978 : }
3979 :
3980 :
3981 : static const char *
3982 3034732 : dwarf_form_name (unsigned int form)
3983 : {
3984 3034732 : const char *ret = dwarf_form_string (form);
3985 3034732 : return string_or_unknown (ret, form, 0, 0, true);
3986 : }
3987 :
3988 :
3989 : static const char *
3990 1294 : dwarf_lang_name (unsigned int lang)
3991 : {
3992 1294 : const char *ret = dwarf_lang_string (lang);
3993 1294 : return string_or_unknown (ret, lang, DW_LANG_lo_user, DW_LANG_hi_user, false);
3994 : }
3995 :
3996 :
3997 : static const char *
3998 : dwarf_inline_name (unsigned int code)
3999 : {
4000 2943 : const char *ret = dwarf_inline_string (code);
4001 2943 : return string_or_unknown (ret, code, 0, 0, false);
4002 : }
4003 :
4004 :
4005 : static const char *
4006 : dwarf_encoding_name (unsigned int code)
4007 : {
4008 18838 : const char *ret = dwarf_encoding_string (code);
4009 18838 : return string_or_unknown (ret, code, DW_ATE_lo_user, DW_ATE_hi_user, false);
4010 : }
4011 :
4012 :
4013 : static const char *
4014 : dwarf_access_name (unsigned int code)
4015 : {
4016 0 : const char *ret = dwarf_access_string (code);
4017 0 : return string_or_unknown (ret, code, 0, 0, false);
4018 : }
4019 :
4020 :
4021 : static const char *
4022 : dwarf_defaulted_name (unsigned int code)
4023 : {
4024 0 : const char *ret = dwarf_defaulted_string (code);
4025 0 : return string_or_unknown (ret, code, 0, 0, false);
4026 : }
4027 :
4028 :
4029 : static const char *
4030 : dwarf_visibility_name (unsigned int code)
4031 : {
4032 0 : const char *ret = dwarf_visibility_string (code);
4033 0 : return string_or_unknown (ret, code, 0, 0, false);
4034 : }
4035 :
4036 :
4037 : static const char *
4038 : dwarf_virtuality_name (unsigned int code)
4039 : {
4040 0 : const char *ret = dwarf_virtuality_string (code);
4041 0 : return string_or_unknown (ret, code, 0, 0, false);
4042 : }
4043 :
4044 :
4045 : static const char *
4046 : dwarf_identifier_case_name (unsigned int code)
4047 : {
4048 0 : const char *ret = dwarf_identifier_case_string (code);
4049 0 : return string_or_unknown (ret, code, 0, 0, false);
4050 : }
4051 :
4052 :
4053 : static const char *
4054 : dwarf_calling_convention_name (unsigned int code)
4055 : {
4056 0 : const char *ret = dwarf_calling_convention_string (code);
4057 0 : return string_or_unknown (ret, code, DW_CC_lo_user, DW_CC_hi_user, false);
4058 : }
4059 :
4060 :
4061 : static const char *
4062 : dwarf_ordering_name (unsigned int code)
4063 : {
4064 0 : const char *ret = dwarf_ordering_string (code);
4065 0 : return string_or_unknown (ret, code, 0, 0, false);
4066 : }
4067 :
4068 :
4069 : static const char *
4070 : dwarf_discr_list_name (unsigned int code)
4071 : {
4072 0 : const char *ret = dwarf_discr_list_string (code);
4073 0 : return string_or_unknown (ret, code, 0, 0, false);
4074 : }
4075 :
4076 :
4077 : static void
4078 144 : print_block (size_t n, const void *block)
4079 : {
4080 144 : if (n == 0)
4081 0 : puts (_("empty block"));
4082 : else
4083 : {
4084 288 : printf (_("%zu byte block:"), n);
4085 144 : const unsigned char *data = block;
4086 : do
4087 4804 : printf (" %02x", *data++);
4088 2402 : while (--n > 0);
4089 : putchar ('\n');
4090 : }
4091 144 : }
4092 :
4093 : static void
4094 281119 : print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
4095 : unsigned int vers, unsigned int addrsize, unsigned int offset_size,
4096 : struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data)
4097 : {
4098 281119 : const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
4099 :
4100 281119 : if (len == 0)
4101 : {
4102 : printf ("%*s(empty)\n", indent, "");
4103 : return;
4104 : }
4105 :
4106 : #define NEED(n) if (len < (Dwarf_Word) (n)) goto invalid
4107 : #define CONSUME(n) NEED (n); else len -= (n)
4108 :
4109 : Dwarf_Word offset = 0;
4110 682213 : while (len-- > 0)
4111 : {
4112 401094 : uint_fast8_t op = *data++;
4113 :
4114 802188 : const char *op_name = dwarf_locexpr_opcode_string (op);
4115 401094 : if (unlikely (op_name == NULL))
4116 : {
4117 : static char buf[20];
4118 0 : if (op >= DW_OP_lo_user)
4119 0 : snprintf (buf, sizeof buf, "lo_user+%#x", op - DW_OP_lo_user);
4120 : else
4121 0 : snprintf (buf, sizeof buf, "??? (%#x)", op);
4122 : op_name = buf;
4123 : }
4124 :
4125 401094 : switch (op)
4126 : {
4127 7579 : case DW_OP_addr:;
4128 : /* Address operand. */
4129 : Dwarf_Word addr;
4130 7579 : NEED (addrsize);
4131 7579 : if (addrsize == 4)
4132 28 : addr = read_4ubyte_unaligned (dbg, data);
4133 7561 : else if (addrsize == 8)
4134 7579 : addr = read_8ubyte_unaligned (dbg, data);
4135 : else
4136 : goto invalid;
4137 7579 : data += addrsize;
4138 7579 : CONSUME (addrsize);
4139 :
4140 7579 : char *a = format_dwarf_addr (dwflmod, 0, addr, addr);
4141 7579 : printf ("%*s[%4" PRIuMAX "] %s %s\n",
4142 : indent, "", (uintmax_t) offset, op_name, a);
4143 7579 : free (a);
4144 :
4145 7579 : offset += 1 + addrsize;
4146 7579 : break;
4147 :
4148 0 : case DW_OP_call_ref:
4149 : /* Offset operand. */
4150 0 : if (ref_size != 4 && ref_size != 8)
4151 : goto invalid; /* Cannot be used in CFA. */
4152 0 : NEED (ref_size);
4153 0 : if (ref_size == 4)
4154 0 : addr = read_4ubyte_unaligned (dbg, data);
4155 : else
4156 0 : addr = read_8ubyte_unaligned (dbg, data);
4157 0 : data += ref_size;
4158 0 : CONSUME (ref_size);
4159 :
4160 0 : printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
4161 : indent, "", (uintmax_t) offset,
4162 : op_name, (uintmax_t) addr);
4163 0 : offset += 1 + ref_size;
4164 0 : break;
4165 :
4166 10604 : case DW_OP_deref_size:
4167 : case DW_OP_xderef_size:
4168 : case DW_OP_pick:
4169 : case DW_OP_const1u:
4170 : // XXX value might be modified by relocation
4171 10604 : NEED (1);
4172 21208 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
4173 : indent, "", (uintmax_t) offset,
4174 10604 : op_name, *((uint8_t *) data));
4175 10604 : ++data;
4176 10604 : --len;
4177 10604 : offset += 2;
4178 10604 : break;
4179 :
4180 1016 : case DW_OP_const2u:
4181 1016 : NEED (2);
4182 : // XXX value might be modified by relocation
4183 3048 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
4184 : indent, "", (uintmax_t) offset,
4185 2032 : op_name, read_2ubyte_unaligned (dbg, data));
4186 1016 : CONSUME (2);
4187 1016 : data += 2;
4188 1016 : offset += 3;
4189 1016 : break;
4190 :
4191 582 : case DW_OP_const4u:
4192 582 : NEED (4);
4193 : // XXX value might be modified by relocation
4194 1746 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
4195 : indent, "", (uintmax_t) offset,
4196 1164 : op_name, read_4ubyte_unaligned (dbg, data));
4197 582 : CONSUME (4);
4198 582 : data += 4;
4199 582 : offset += 5;
4200 582 : break;
4201 :
4202 59 : case DW_OP_const8u:
4203 59 : NEED (8);
4204 : // XXX value might be modified by relocation
4205 177 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
4206 : indent, "", (uintmax_t) offset,
4207 118 : op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
4208 59 : CONSUME (8);
4209 59 : data += 8;
4210 59 : offset += 9;
4211 59 : break;
4212 :
4213 1835 : case DW_OP_const1s:
4214 1835 : NEED (1);
4215 : // XXX value might be modified by relocation
4216 3670 : printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
4217 : indent, "", (uintmax_t) offset,
4218 1835 : op_name, *((int8_t *) data));
4219 1835 : ++data;
4220 1835 : --len;
4221 1835 : offset += 2;
4222 1835 : break;
4223 :
4224 5 : case DW_OP_const2s:
4225 5 : NEED (2);
4226 : // XXX value might be modified by relocation
4227 15 : printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
4228 : indent, "", (uintmax_t) offset,
4229 10 : op_name, read_2sbyte_unaligned (dbg, data));
4230 5 : CONSUME (2);
4231 5 : data += 2;
4232 5 : offset += 3;
4233 5 : break;
4234 :
4235 0 : case DW_OP_const4s:
4236 0 : NEED (4);
4237 : // XXX value might be modified by relocation
4238 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
4239 : indent, "", (uintmax_t) offset,
4240 0 : op_name, read_4sbyte_unaligned (dbg, data));
4241 0 : CONSUME (4);
4242 0 : data += 4;
4243 0 : offset += 5;
4244 0 : break;
4245 :
4246 0 : case DW_OP_const8s:
4247 0 : NEED (8);
4248 : // XXX value might be modified by relocation
4249 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
4250 : indent, "", (uintmax_t) offset,
4251 0 : op_name, read_8sbyte_unaligned (dbg, data));
4252 0 : CONSUME (8);
4253 0 : data += 8;
4254 0 : offset += 9;
4255 0 : break;
4256 :
4257 8473 : case DW_OP_piece:
4258 : case DW_OP_regx:
4259 : case DW_OP_plus_uconst:
4260 : case DW_OP_constu:;
4261 8473 : const unsigned char *start = data;
4262 : uint64_t uleb;
4263 8473 : NEED (1);
4264 8473 : get_uleb128 (uleb, data, data + len);
4265 8473 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
4266 : indent, "", (uintmax_t) offset, op_name, uleb);
4267 16946 : CONSUME (data - start);
4268 8473 : offset += 1 + (data - start);
4269 8473 : break;
4270 :
4271 0 : case DW_OP_bit_piece:
4272 0 : start = data;
4273 : uint64_t uleb2;
4274 0 : NEED (1);
4275 0 : get_uleb128 (uleb, data, data + len);
4276 : NEED (1);
4277 0 : get_uleb128 (uleb2, data, data + len);
4278 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
4279 : indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
4280 0 : CONSUME (data - start);
4281 0 : offset += 1 + (data - start);
4282 0 : break;
4283 :
4284 71355 : case DW_OP_fbreg:
4285 : case DW_OP_breg0 ... DW_OP_breg31:
4286 : case DW_OP_consts:
4287 71355 : start = data;
4288 : int64_t sleb;
4289 71355 : NEED (1);
4290 71355 : get_sleb128 (sleb, data, data + len);
4291 71355 : printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
4292 : indent, "", (uintmax_t) offset, op_name, sleb);
4293 142710 : CONSUME (data - start);
4294 71355 : offset += 1 + (data - start);
4295 71355 : break;
4296 :
4297 0 : case DW_OP_bregx:
4298 0 : start = data;
4299 0 : NEED (1);
4300 0 : get_uleb128 (uleb, data, data + len);
4301 : NEED (1);
4302 0 : get_sleb128 (sleb, data, data + len);
4303 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
4304 : indent, "", (uintmax_t) offset, op_name, uleb, sleb);
4305 0 : CONSUME (data - start);
4306 0 : offset += 1 + (data - start);
4307 0 : break;
4308 :
4309 0 : case DW_OP_call2:
4310 0 : NEED (2);
4311 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
4312 : indent, "", (uintmax_t) offset, op_name,
4313 0 : read_2ubyte_unaligned (dbg, data));
4314 0 : CONSUME (2);
4315 0 : offset += 3;
4316 0 : break;
4317 :
4318 0 : case DW_OP_call4:
4319 0 : NEED (4);
4320 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
4321 : indent, "", (uintmax_t) offset, op_name,
4322 0 : read_4ubyte_unaligned (dbg, data));
4323 0 : CONSUME (4);
4324 0 : offset += 5;
4325 0 : break;
4326 :
4327 198 : case DW_OP_skip:
4328 : case DW_OP_bra:
4329 198 : NEED (2);
4330 198 : printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
4331 : indent, "", (uintmax_t) offset, op_name,
4332 198 : (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
4333 198 : CONSUME (2);
4334 198 : data += 2;
4335 198 : offset += 3;
4336 198 : break;
4337 :
4338 127 : case DW_OP_implicit_value:
4339 127 : start = data;
4340 127 : NEED (1);
4341 127 : get_uleb128 (uleb, data, data + len);
4342 127 : printf ("%*s[%4" PRIuMAX "] %s: ",
4343 : indent, "", (uintmax_t) offset, op_name);
4344 127 : NEED (uleb);
4345 127 : print_block (uleb, data);
4346 127 : data += uleb;
4347 254 : CONSUME (data - start);
4348 127 : offset += 1 + (data - start);
4349 127 : break;
4350 :
4351 3340 : case DW_OP_GNU_implicit_pointer:
4352 : /* DIE offset operand. */
4353 3340 : start = data;
4354 3340 : NEED (ref_size);
4355 3340 : if (ref_size != 4 && ref_size != 8)
4356 : goto invalid; /* Cannot be used in CFA. */
4357 3340 : if (ref_size == 4)
4358 3340 : addr = read_4ubyte_unaligned (dbg, data);
4359 : else
4360 0 : addr = read_8ubyte_unaligned (dbg, data);
4361 3340 : data += ref_size;
4362 : /* Byte offset operand. */
4363 3340 : NEED (1);
4364 3340 : get_sleb128 (sleb, data, data + len);
4365 :
4366 6680 : printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
4367 : indent, "", (intmax_t) offset,
4368 : op_name, (uintmax_t) addr, sleb);
4369 6680 : CONSUME (data - start);
4370 3340 : offset += 1 + (data - start);
4371 3340 : break;
4372 :
4373 22504 : case DW_OP_GNU_entry_value:
4374 : /* Size plus expression block. */
4375 22504 : start = data;
4376 22504 : NEED (1);
4377 22504 : get_uleb128 (uleb, data, data + len);
4378 22504 : printf ("%*s[%4" PRIuMAX "] %s:\n",
4379 : indent, "", (uintmax_t) offset, op_name);
4380 22504 : NEED (uleb);
4381 22504 : print_ops (dwflmod, dbg, indent + 6, indent + 6, vers,
4382 : addrsize, offset_size, cu, uleb, data);
4383 22504 : data += uleb;
4384 45008 : CONSUME (data - start);
4385 22504 : offset += 1 + (data - start);
4386 22504 : break;
4387 :
4388 1 : case DW_OP_GNU_const_type:
4389 : /* uleb128 CU relative DW_TAG_base_type DIE offset, 1-byte
4390 : unsigned size plus block. */
4391 1 : start = data;
4392 1 : NEED (1);
4393 1 : get_uleb128 (uleb, data, data + len);
4394 1 : if (! print_unresolved_addresses && cu != NULL)
4395 1 : uleb += cu->start;
4396 : NEED (1);
4397 1 : uint8_t usize = *(uint8_t *) data++;
4398 1 : NEED (usize);
4399 1 : printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] ",
4400 : indent, "", (uintmax_t) offset, op_name, uleb);
4401 1 : print_block (usize, data);
4402 1 : data += usize;
4403 2 : CONSUME (data - start);
4404 1 : offset += 1 + (data - start);
4405 1 : break;
4406 :
4407 0 : case DW_OP_GNU_regval_type:
4408 : /* uleb128 register number, uleb128 CU relative
4409 : DW_TAG_base_type DIE offset. */
4410 0 : start = data;
4411 0 : NEED (1);
4412 0 : get_uleb128 (uleb, data, data + len);
4413 : NEED (1);
4414 0 : get_uleb128 (uleb2, data, data + len);
4415 0 : if (! print_unresolved_addresses && cu != NULL)
4416 0 : uleb2 += cu->start;
4417 0 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
4418 : indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
4419 0 : CONSUME (data - start);
4420 0 : offset += 1 + (data - start);
4421 0 : break;
4422 :
4423 6 : case DW_OP_GNU_deref_type:
4424 : /* 1-byte unsigned size of value, uleb128 CU relative
4425 : DW_TAG_base_type DIE offset. */
4426 6 : start = data;
4427 6 : NEED (1);
4428 6 : usize = *(uint8_t *) data++;
4429 : NEED (1);
4430 6 : get_uleb128 (uleb, data, data + len);
4431 6 : if (! print_unresolved_addresses && cu != NULL)
4432 6 : uleb += cu->start;
4433 12 : printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
4434 : indent, "", (uintmax_t) offset,
4435 : op_name, usize, uleb);
4436 12 : CONSUME (data - start);
4437 6 : offset += 1 + (data - start);
4438 6 : break;
4439 :
4440 147 : case DW_OP_GNU_convert:
4441 : case DW_OP_GNU_reinterpret:
4442 : /* uleb128 CU relative offset to DW_TAG_base_type, or zero
4443 : for conversion to untyped. */
4444 147 : start = data;
4445 147 : NEED (1);
4446 147 : get_uleb128 (uleb, data, data + len);
4447 147 : if (uleb != 0 && ! print_unresolved_addresses && cu != NULL)
4448 99 : uleb += cu->start;
4449 147 : printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
4450 : indent, "", (uintmax_t) offset, op_name, uleb);
4451 294 : CONSUME (data - start);
4452 147 : offset += 1 + (data - start);
4453 147 : break;
4454 :
4455 21 : case DW_OP_GNU_parameter_ref:
4456 : /* 4 byte CU relative reference to the abstract optimized away
4457 : DW_TAG_formal_parameter. */
4458 21 : NEED (4);
4459 21 : uintmax_t param_off = (uintmax_t) read_4ubyte_unaligned (dbg, data);
4460 21 : if (! print_unresolved_addresses && cu != NULL)
4461 21 : param_off += cu->start;
4462 21 : printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
4463 : indent, "", (uintmax_t) offset, op_name, param_off);
4464 21 : CONSUME (4);
4465 21 : data += 4;
4466 21 : offset += 5;
4467 21 : break;
4468 :
4469 273242 : default:
4470 : /* No Operand. */
4471 273242 : printf ("%*s[%4" PRIuMAX "] %s\n",
4472 : indent, "", (uintmax_t) offset, op_name);
4473 273242 : ++offset;
4474 273242 : break;
4475 : }
4476 :
4477 401094 : indent = indentrest;
4478 401094 : continue;
4479 :
4480 0 : invalid:
4481 0 : printf (gettext ("%*s[%4" PRIuMAX "] %s <TRUNCATED>\n"),
4482 : indent, "", (uintmax_t) offset, op_name);
4483 : break;
4484 : }
4485 : }
4486 :
4487 :
4488 : struct listptr
4489 : {
4490 : Dwarf_Off offset:(64 - 3);
4491 : bool addr64:1;
4492 : bool dwarf64:1;
4493 : bool warned:1;
4494 : struct Dwarf_CU *cu;
4495 : };
4496 :
4497 : #define listptr_offset_size(p) ((p)->dwarf64 ? 8 : 4)
4498 : #define listptr_address_size(p) ((p)->addr64 ? 8 : 4)
4499 :
4500 : static Dwarf_Addr
4501 58808 : listptr_base (struct listptr *p)
4502 : {
4503 : Dwarf_Addr base;
4504 117616 : Dwarf_Die cu = CUDIE (p->cu);
4505 : /* Find the base address of the compilation unit. It will normally
4506 : be specified by DW_AT_low_pc. In DWARF-3 draft 4, the base
4507 : address could be overridden by DW_AT_entry_pc. It's been
4508 : removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc for
4509 : compilation units with discontinuous ranges. */
4510 58808 : if (unlikely (dwarf_lowpc (&cu, &base) != 0))
4511 : {
4512 : Dwarf_Attribute attr_mem;
4513 0 : if (dwarf_formaddr (dwarf_attr (&cu, DW_AT_entry_pc, &attr_mem),
4514 : &base) != 0)
4515 0 : base = 0;
4516 : }
4517 58808 : return base;
4518 : }
4519 :
4520 : static int
4521 321562 : compare_listptr (const void *a, const void *b, void *arg)
4522 : {
4523 321562 : const char *name = arg;
4524 321562 : struct listptr *p1 = (void *) a;
4525 321562 : struct listptr *p2 = (void *) b;
4526 :
4527 321562 : if (p1->offset < p2->offset)
4528 : return -1;
4529 19410 : if (p1->offset > p2->offset)
4530 : return 1;
4531 :
4532 3718 : if (!p1->warned && !p2->warned)
4533 : {
4534 3718 : if (p1->addr64 != p2->addr64)
4535 : {
4536 0 : p1->warned = p2->warned = true;
4537 0 : error (0, 0,
4538 0 : gettext ("%s %#" PRIx64 " used with different address sizes"),
4539 : name, (uint64_t) p1->offset);
4540 : }
4541 3718 : if (p1->dwarf64 != p2->dwarf64)
4542 : {
4543 0 : p1->warned = p2->warned = true;
4544 0 : error (0, 0,
4545 0 : gettext ("%s %#" PRIx64 " used with different offset sizes"),
4546 0 : name, (uint64_t) p1->offset);
4547 : }
4548 3718 : if (listptr_base (p1) != listptr_base (p2))
4549 : {
4550 0 : p1->warned = p2->warned = true;
4551 0 : error (0, 0,
4552 0 : gettext ("%s %#" PRIx64 " used with different base addresses"),
4553 0 : name, (uint64_t) p1->offset);
4554 : }
4555 : }
4556 :
4557 : return 0;
4558 : }
4559 :
4560 : struct listptr_table
4561 : {
4562 : size_t n;
4563 : size_t alloc;
4564 : struct listptr *table;
4565 : };
4566 :
4567 : static struct listptr_table known_loclistptr;
4568 : static struct listptr_table known_rangelistptr;
4569 :
4570 : static void
4571 : reset_listptr (struct listptr_table *table)
4572 : {
4573 178 : free (table->table);
4574 178 : table->table = NULL;
4575 178 : table->n = table->alloc = 0;
4576 : }
4577 :
4578 : /* Returns false if offset doesn't fit. See struct listptr. */
4579 : static bool
4580 54977 : notice_listptr (enum section_e section, struct listptr_table *table,
4581 : uint_fast8_t address_size, uint_fast8_t offset_size,
4582 : struct Dwarf_CU *cu, Dwarf_Off offset)
4583 : {
4584 54977 : if (print_debug_sections & section)
4585 : {
4586 54970 : if (table->n == table->alloc)
4587 : {
4588 157 : if (table->alloc == 0)
4589 55 : table->alloc = 128;
4590 : else
4591 102 : table->alloc *= 2;
4592 157 : table->table = xrealloc (table->table,
4593 157 : table->alloc * sizeof table->table[0]);
4594 : }
4595 :
4596 54970 : struct listptr *p = &table->table[table->n++];
4597 :
4598 109940 : *p = (struct listptr)
4599 : {
4600 54970 : .addr64 = address_size == 8,
4601 54970 : .dwarf64 = offset_size == 8,
4602 : .offset = offset,
4603 : .cu = cu
4604 : };
4605 :
4606 54970 : if (p->offset != offset)
4607 : {
4608 0 : table->n--;
4609 0 : return false;
4610 : }
4611 : }
4612 : return true;
4613 : }
4614 :
4615 : static void
4616 : sort_listptr (struct listptr_table *table, const char *name)
4617 : {
4618 55 : if (table->n > 0)
4619 55 : qsort_r (table->table, table->n, sizeof table->table[0],
4620 : &compare_listptr, (void *) name);
4621 : }
4622 :
4623 : static bool
4624 51372 : skip_listptr_hole (struct listptr_table *table, size_t *idxp,
4625 : uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
4626 : Dwarf_Addr *base, struct Dwarf_CU **cu, ptrdiff_t offset,
4627 : unsigned char **readp, unsigned char *endp)
4628 : {
4629 51372 : if (table->n == 0)
4630 : return false;
4631 :
4632 106287 : while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
4633 54915 : ++*idxp;
4634 :
4635 51372 : struct listptr *p = &table->table[*idxp];
4636 :
4637 51372 : if (*idxp == table->n
4638 51372 : || p->offset >= (Dwarf_Off) (endp - *readp + offset))
4639 : {
4640 0 : *readp = endp;
4641 0 : printf (gettext (" [%6tx] <UNUSED GARBAGE IN REST OF SECTION>\n"),
4642 : offset);
4643 : return true;
4644 : }
4645 :
4646 51372 : if (p->offset != (Dwarf_Off) offset)
4647 : {
4648 0 : *readp += p->offset - offset;
4649 0 : printf (gettext (" [%6tx] <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
4650 : offset, (Dwarf_Off) p->offset - offset);
4651 : return true;
4652 : }
4653 :
4654 51372 : if (address_sizep != NULL)
4655 51372 : *address_sizep = listptr_address_size (p);
4656 51372 : if (offset_sizep != NULL)
4657 42545 : *offset_sizep = listptr_offset_size (p);
4658 51372 : if (base != NULL)
4659 51372 : *base = listptr_base (p);
4660 51372 : if (cu != NULL)
4661 42545 : *cu = p->cu;
4662 :
4663 : return false;
4664 : }
4665 :
4666 :
4667 : static void
4668 34 : print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
4669 : Ebl *ebl, GElf_Ehdr *ehdr,
4670 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
4671 : {
4672 68 : const size_t sh_size = (dbg->sectiondata[IDX_debug_abbrev] ?
4673 34 : dbg->sectiondata[IDX_debug_abbrev]->d_size : 0);
4674 :
4675 102 : printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
4676 : " [ Code]\n"),
4677 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4678 34 : (uint64_t) shdr->sh_offset);
4679 :
4680 34 : Dwarf_Off offset = 0;
4681 34 : while (offset < sh_size)
4682 : {
4683 1271 : printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
4684 : offset);
4685 :
4686 : while (1)
4687 65837 : {
4688 : size_t length;
4689 : Dwarf_Abbrev abbrev;
4690 :
4691 67108 : int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
4692 67108 : if (res != 0)
4693 : {
4694 1271 : if (unlikely (res < 0))
4695 : {
4696 0 : printf (gettext ("\
4697 : *** error while reading abbreviation: %s\n"),
4698 : dwarf_errmsg (-1));
4699 0 : return;
4700 : }
4701 :
4702 : /* This is the NUL byte at the end of the section. */
4703 1271 : ++offset;
4704 1271 : break;
4705 : }
4706 :
4707 : /* We know these calls can never fail. */
4708 65837 : unsigned int code = dwarf_getabbrevcode (&abbrev);
4709 65837 : unsigned int tag = dwarf_getabbrevtag (&abbrev);
4710 65837 : int has_children = dwarf_abbrevhaschildren (&abbrev);
4711 :
4712 131674 : printf (gettext (" [%5u] offset: %" PRId64
4713 : ", children: %s, tag: %s\n"),
4714 : code, (int64_t) offset,
4715 : has_children ? gettext ("yes") : gettext ("no"),
4716 : dwarf_tag_name (tag));
4717 :
4718 65837 : size_t cnt = 0;
4719 : unsigned int name;
4720 : unsigned int form;
4721 : Dwarf_Off enoffset;
4722 384974 : while (dwarf_getabbrevattr (&abbrev, cnt,
4723 : &name, &form, &enoffset) == 0)
4724 : {
4725 506600 : printf (" attr: %s, form: %s, offset: %#" PRIx64 "\n",
4726 : dwarf_attr_name (name), dwarf_form_name (form),
4727 : (uint64_t) enoffset);
4728 :
4729 253300 : ++cnt;
4730 : }
4731 :
4732 65837 : offset += length;
4733 : }
4734 : }
4735 : }
4736 :
4737 :
4738 : /* Print content of DWARF .debug_aranges section. We fortunately do
4739 : not have to know a bit about the structure of the section, libdwarf
4740 : takes care of it. */
4741 : static void
4742 1 : print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4743 : GElf_Shdr *shdr, Dwarf *dbg)
4744 : {
4745 : Dwarf_Aranges *aranges;
4746 : size_t cnt;
4747 1 : if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
4748 : {
4749 0 : error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
4750 : dwarf_errmsg (-1));
4751 0 : return;
4752 : }
4753 :
4754 : GElf_Shdr glink_mem;
4755 : GElf_Shdr *glink;
4756 1 : glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
4757 1 : if (glink == NULL)
4758 : {
4759 0 : error (0, 0, gettext ("invalid sh_link value in section %zu"),
4760 : elf_ndxscn (scn));
4761 : return;
4762 : }
4763 :
4764 4 : printf (ngettext ("\
4765 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
4766 : "\
4767 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
4768 : cnt),
4769 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4770 1 : (uint64_t) shdr->sh_offset, cnt);
4771 :
4772 : /* Compute floor(log16(cnt)). */
4773 1 : size_t tmp = cnt;
4774 1 : int digits = 1;
4775 2 : while (tmp >= 16)
4776 : {
4777 0 : ++digits;
4778 0 : tmp >>= 4;
4779 : }
4780 :
4781 5 : for (size_t n = 0; n < cnt; ++n)
4782 : {
4783 5 : Dwarf_Arange *runp = dwarf_onearange (aranges, n);
4784 5 : if (unlikely (runp == NULL))
4785 : {
4786 0 : printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
4787 0 : return;
4788 : }
4789 :
4790 : Dwarf_Addr start;
4791 : Dwarf_Word length;
4792 : Dwarf_Off offset;
4793 :
4794 5 : if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
4795 0 : printf (gettext (" [%*zu] ???\n"), digits, n);
4796 : else
4797 10 : printf (gettext (" [%*zu] start: %0#*" PRIx64
4798 : ", length: %5" PRIu64 ", CU DIE offset: %6"
4799 : PRId64 "\n"),
4800 5 : digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
4801 : (uint64_t) start, (uint64_t) length, (int64_t) offset);
4802 : }
4803 : }
4804 :
4805 :
4806 : /* Print content of DWARF .debug_aranges section. */
4807 : static void
4808 38 : print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
4809 : Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4810 : GElf_Shdr *shdr, Dwarf *dbg)
4811 : {
4812 38 : if (decodedaranges)
4813 : {
4814 1 : print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg);
4815 1 : return;
4816 : }
4817 :
4818 37 : Elf_Data *data = dbg->sectiondata[IDX_debug_aranges];
4819 :
4820 37 : if (unlikely (data == NULL))
4821 : {
4822 0 : error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
4823 : elf_errmsg (-1));
4824 : return;
4825 : }
4826 :
4827 111 : printf (gettext ("\
4828 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
4829 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4830 37 : (uint64_t) shdr->sh_offset);
4831 :
4832 37 : const unsigned char *readp = data->d_buf;
4833 37 : const unsigned char *readendp = readp + data->d_size;
4834 :
4835 1342 : while (readp < readendp)
4836 : {
4837 1268 : const unsigned char *hdrstart = readp;
4838 1268 : size_t start_offset = hdrstart - (const unsigned char *) data->d_buf;
4839 :
4840 2536 : printf (gettext ("\nTable at offset %zu:\n"), start_offset);
4841 1268 : if (readp + 4 > readendp)
4842 : {
4843 0 : invalid_data:
4844 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
4845 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
4846 : return;
4847 : }
4848 :
4849 1282 : Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
4850 1268 : unsigned int length_bytes = 4;
4851 1268 : if (length == DWARF3_LENGTH_64_BIT)
4852 : {
4853 0 : if (readp + 8 > readendp)
4854 : goto invalid_data;
4855 0 : length = read_8ubyte_unaligned_inc (dbg, readp);
4856 0 : length_bytes = 8;
4857 : }
4858 :
4859 1268 : const unsigned char *nexthdr = readp + length;
4860 2536 : printf (gettext ("\n Length: %6" PRIu64 "\n"),
4861 : (uint64_t) length);
4862 :
4863 1268 : if (unlikely (length > (size_t) (readendp - readp)))
4864 : goto invalid_data;
4865 :
4866 1268 : if (length == 0)
4867 0 : continue;
4868 :
4869 1268 : if (readp + 2 > readendp)
4870 : goto invalid_data;
4871 1268 : uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, readp);
4872 2536 : printf (gettext (" DWARF version: %6" PRIuFAST16 "\n"),
4873 : version);
4874 1268 : if (version != 2)
4875 : {
4876 0 : error (0, 0, gettext ("unsupported aranges version"));
4877 : goto next_table;
4878 : }
4879 :
4880 : Dwarf_Word offset;
4881 1268 : if (readp + length_bytes > readendp)
4882 : goto invalid_data;
4883 1268 : if (length_bytes == 8)
4884 0 : offset = read_8ubyte_unaligned_inc (dbg, readp);
4885 : else
4886 1282 : offset = read_4ubyte_unaligned_inc (dbg, readp);
4887 2536 : printf (gettext (" CU offset: %6" PRIx64 "\n"),
4888 : (uint64_t) offset);
4889 :
4890 1268 : if (readp + 1 > readendp)
4891 : goto invalid_data;
4892 1268 : unsigned int address_size = *readp++;
4893 2536 : printf (gettext (" Address size: %6" PRIu64 "\n"),
4894 : (uint64_t) address_size);
4895 1268 : if (address_size != 4 && address_size != 8)
4896 : {
4897 0 : error (0, 0, gettext ("unsupported address size"));
4898 : goto next_table;
4899 : }
4900 :
4901 1268 : unsigned int segment_size = *readp++;
4902 2536 : printf (gettext (" Segment size: %6" PRIu64 "\n\n"),
4903 : (uint64_t) segment_size);
4904 1268 : if (segment_size != 0 && segment_size != 4 && segment_size != 8)
4905 : {
4906 0 : error (0, 0, gettext ("unsupported segment size"));
4907 : goto next_table;
4908 : }
4909 :
4910 : /* Round the address to the next multiple of 2*address_size. */
4911 2536 : readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
4912 1268 : % (2 * address_size));
4913 :
4914 3863 : while (readp < nexthdr)
4915 : {
4916 : Dwarf_Word range_address;
4917 : Dwarf_Word range_length;
4918 2595 : Dwarf_Word segment = 0;
4919 2595 : if (readp + 2 * address_size + segment_size > readendp)
4920 : goto invalid_data;
4921 2595 : if (address_size == 4)
4922 : {
4923 36 : range_address = read_4ubyte_unaligned_inc (dbg, readp);
4924 36 : range_length = read_4ubyte_unaligned_inc (dbg, readp);
4925 : }
4926 : else
4927 : {
4928 2585 : range_address = read_8ubyte_unaligned_inc (dbg, readp);
4929 2585 : range_length = read_8ubyte_unaligned_inc (dbg, readp);
4930 : }
4931 :
4932 2595 : if (segment_size == 4)
4933 0 : segment = read_4ubyte_unaligned_inc (dbg, readp);
4934 2595 : else if (segment_size == 8)
4935 0 : segment = read_8ubyte_unaligned_inc (dbg, readp);
4936 :
4937 2595 : if (range_address == 0 && range_length == 0 && segment == 0)
4938 : break;
4939 :
4940 1327 : char *b = format_dwarf_addr (dwflmod, address_size, range_address,
4941 : range_address);
4942 1327 : char *e = format_dwarf_addr (dwflmod, address_size,
4943 1327 : range_address + range_length - 1,
4944 : range_length);
4945 1327 : if (segment_size != 0)
4946 0 : printf (gettext (" %s..%s (%" PRIx64 ")\n"), b, e,
4947 : (uint64_t) segment);
4948 : else
4949 1327 : printf (gettext (" %s..%s\n"), b, e);
4950 1327 : free (b);
4951 1327 : free (e);
4952 : }
4953 :
4954 1268 : next_table:
4955 1268 : if (readp != nexthdr)
4956 : {
4957 0 : size_t padding = nexthdr - readp;
4958 0 : printf (gettext (" %zu padding bytes\n"), padding);
4959 0 : readp = nexthdr;
4960 : }
4961 : }
4962 : }
4963 :
4964 :
4965 : /* Print content of DWARF .debug_ranges section. */
4966 : static void
4967 25 : print_debug_ranges_section (Dwfl_Module *dwflmod,
4968 : Ebl *ebl, GElf_Ehdr *ehdr,
4969 : Elf_Scn *scn, GElf_Shdr *shdr,
4970 : Dwarf *dbg)
4971 : {
4972 25 : Elf_Data *data = dbg->sectiondata[IDX_debug_ranges];
4973 :
4974 25 : if (unlikely (data == NULL))
4975 : {
4976 0 : error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
4977 : elf_errmsg (-1));
4978 0 : return;
4979 : }
4980 :
4981 75 : printf (gettext ("\
4982 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
4983 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4984 25 : (uint64_t) shdr->sh_offset);
4985 :
4986 50 : sort_listptr (&known_rangelistptr, "rangelistptr");
4987 25 : size_t listptr_idx = 0;
4988 :
4989 25 : uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
4990 :
4991 25 : bool first = true;
4992 25 : Dwarf_Addr base = 0;
4993 25 : unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
4994 25 : unsigned char *readp = data->d_buf;
4995 36757 : while (readp < endp)
4996 : {
4997 36707 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
4998 :
4999 36707 : if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
5000 : &address_size, NULL, &base, NULL,
5001 : offset, &readp, endp))
5002 0 : continue;
5003 :
5004 36707 : if (unlikely (data->d_size - offset < (size_t) address_size * 2))
5005 : {
5006 0 : printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
5007 : break;
5008 : }
5009 :
5010 : Dwarf_Addr begin;
5011 : Dwarf_Addr end;
5012 36707 : if (address_size == 8)
5013 : {
5014 36707 : begin = read_8ubyte_unaligned_inc (dbg, readp);
5015 36707 : end = read_8ubyte_unaligned_inc (dbg, readp);
5016 : }
5017 : else
5018 : {
5019 0 : begin = read_4ubyte_unaligned_inc (dbg, readp);
5020 0 : end = read_4ubyte_unaligned_inc (dbg, readp);
5021 0 : if (begin == (Dwarf_Addr) (uint32_t) -1)
5022 : begin = (Dwarf_Addr) -1l;
5023 : }
5024 :
5025 36707 : if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
5026 : {
5027 0 : char *b = format_dwarf_addr (dwflmod, address_size, end, end);
5028 0 : printf (gettext (" [%6tx] base address %s\n"), offset, b);
5029 0 : free (b);
5030 0 : base = end;
5031 : }
5032 36707 : else if (begin == 0 && end == 0) /* End of list entry. */
5033 : {
5034 8827 : if (first)
5035 0 : printf (gettext (" [%6tx] empty list\n"), offset);
5036 : first = true;
5037 : }
5038 : else
5039 : {
5040 27880 : char *b = format_dwarf_addr (dwflmod, address_size, base + begin,
5041 : begin);
5042 27880 : char *e = format_dwarf_addr (dwflmod, address_size, base + end,
5043 : end);
5044 : /* We have an address range entry. */
5045 27880 : if (first) /* First address range entry in a list. */
5046 8827 : printf (gettext (" [%6tx] %s..%s\n"), offset, b, e);
5047 : else
5048 19053 : printf (gettext (" %s..%s\n"), b, e);
5049 27880 : free (b);
5050 27880 : free (e);
5051 :
5052 27880 : first = false;
5053 : }
5054 : }
5055 : }
5056 :
5057 : #define REGNAMESZ 16
5058 : static const char *
5059 10545 : register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
5060 : char name[REGNAMESZ], int *bits, int *type)
5061 : {
5062 : const char *set;
5063 : const char *pfx;
5064 : int ignore;
5065 10545 : ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
5066 : bits ?: &ignore, type ?: &ignore);
5067 10545 : if (n <= 0)
5068 : {
5069 0 : if (loc != NULL)
5070 0 : snprintf (name, REGNAMESZ, "reg%u", loc->regno);
5071 : else
5072 : snprintf (name, REGNAMESZ, "??? 0x%x", regno);
5073 0 : if (bits != NULL)
5074 0 : *bits = loc != NULL ? loc->bits : 0;
5075 0 : if (type != NULL)
5076 0 : *type = DW_ATE_unsigned;
5077 0 : set = "??? unrecognized";
5078 : }
5079 : else
5080 : {
5081 10545 : if (bits != NULL && *bits <= 0)
5082 0 : *bits = loc != NULL ? loc->bits : 0;
5083 10545 : if (type != NULL && *type == DW_ATE_void)
5084 0 : *type = DW_ATE_unsigned;
5085 :
5086 : }
5087 10545 : return set;
5088 : }
5089 :
5090 : static const unsigned char *
5091 32 : read_encoded (unsigned int encoding, const unsigned char *readp,
5092 : const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
5093 : {
5094 32 : if ((encoding & 0xf) == DW_EH_PE_absptr)
5095 0 : encoding = gelf_getclass (dbg->elf) == ELFCLASS32
5096 0 : ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
5097 :
5098 32 : switch (encoding & 0xf)
5099 : {
5100 0 : case DW_EH_PE_uleb128:
5101 0 : get_uleb128 (*res, readp, endp);
5102 : break;
5103 0 : case DW_EH_PE_sleb128:
5104 0 : get_sleb128 (*res, readp, endp);
5105 : break;
5106 0 : case DW_EH_PE_udata2:
5107 0 : if (readp + 2 > endp)
5108 : goto invalid;
5109 0 : *res = read_2ubyte_unaligned_inc (dbg, readp);
5110 : break;
5111 16 : case DW_EH_PE_udata4:
5112 16 : if (readp + 4 > endp)
5113 : goto invalid;
5114 16 : *res = read_4ubyte_unaligned_inc (dbg, readp);
5115 : break;
5116 0 : case DW_EH_PE_udata8:
5117 0 : if (readp + 8 > endp)
5118 : goto invalid;
5119 0 : *res = read_8ubyte_unaligned_inc (dbg, readp);
5120 : break;
5121 0 : case DW_EH_PE_sdata2:
5122 0 : if (readp + 2 > endp)
5123 : goto invalid;
5124 0 : *res = read_2sbyte_unaligned_inc (dbg, readp);
5125 : break;
5126 16 : case DW_EH_PE_sdata4:
5127 16 : if (readp + 4 > endp)
5128 : goto invalid;
5129 16 : *res = read_4sbyte_unaligned_inc (dbg, readp);
5130 : break;
5131 0 : case DW_EH_PE_sdata8:
5132 0 : if (readp + 8 > endp)
5133 : goto invalid;
5134 0 : *res = read_8sbyte_unaligned_inc (dbg, readp);
5135 : break;
5136 : default:
5137 0 : invalid:
5138 : error (1, 0,
5139 0 : gettext ("invalid encoding"));
5140 : }
5141 :
5142 32 : return readp;
5143 : }
5144 :
5145 :
5146 : static void
5147 5569 : print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
5148 : Dwarf_Word vma_base, unsigned int code_align,
5149 : int data_align,
5150 : unsigned int version, unsigned int ptr_size,
5151 : unsigned int encoding,
5152 : Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
5153 : {
5154 : char regnamebuf[REGNAMESZ];
5155 : const char *regname (unsigned int regno)
5156 : {
5157 9759 : register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
5158 : return regnamebuf;
5159 : }
5160 :
5161 5569 : puts ("\n Program:");
5162 5569 : Dwarf_Word pc = vma_base;
5163 110443 : while (readp < endp)
5164 : {
5165 99305 : unsigned int opcode = *readp++;
5166 :
5167 99305 : if (opcode < DW_CFA_advance_loc)
5168 : /* Extended opcode. */
5169 63240 : switch (opcode)
5170 : {
5171 : uint64_t op1;
5172 : int64_t sop1;
5173 : uint64_t op2;
5174 : int64_t sop2;
5175 :
5176 28539 : case DW_CFA_nop:
5177 28539 : puts (" nop");
5178 91779 : break;
5179 0 : case DW_CFA_set_loc:
5180 0 : if ((uint64_t) (endp - readp) < 1)
5181 : goto invalid;
5182 0 : readp = read_encoded (encoding, readp, endp, &op1, dbg);
5183 0 : printf (" set_loc %#" PRIx64 " to %#" PRIx64 "\n",
5184 0 : op1, pc = vma_base + op1);
5185 : break;
5186 1879 : case DW_CFA_advance_loc1:
5187 1879 : if ((uint64_t) (endp - readp) < 1)
5188 : goto invalid;
5189 3758 : printf (" advance_loc1 %u to %#" PRIx64 "\n",
5190 1879 : *readp, pc += *readp * code_align);
5191 1879 : ++readp;
5192 1879 : break;
5193 773 : case DW_CFA_advance_loc2:
5194 773 : if ((uint64_t) (endp - readp) < 2)
5195 : goto invalid;
5196 773 : op1 = read_2ubyte_unaligned_inc (dbg, readp);
5197 773 : printf (" advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
5198 773 : op1, pc += op1 * code_align);
5199 : break;
5200 24 : case DW_CFA_advance_loc4:
5201 24 : if ((uint64_t) (endp - readp) < 4)
5202 : goto invalid;
5203 48 : op1 = read_4ubyte_unaligned_inc (dbg, readp);
5204 24 : printf (" advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
5205 24 : op1, pc += op1 * code_align);
5206 : break;
5207 4 : case DW_CFA_offset_extended:
5208 4 : if ((uint64_t) (endp - readp) < 1)
5209 : goto invalid;
5210 4 : get_uleb128 (op1, readp, endp);
5211 4 : if ((uint64_t) (endp - readp) < 1)
5212 : goto invalid;
5213 4 : get_uleb128 (op2, readp, endp);
5214 8 : printf (" offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
5215 : "\n",
5216 : op1, regname (op1), op2 * data_align);
5217 : break;
5218 0 : case DW_CFA_restore_extended:
5219 0 : if ((uint64_t) (endp - readp) < 1)
5220 : goto invalid;
5221 0 : get_uleb128 (op1, readp, endp);
5222 0 : printf (" restore_extended r%" PRIu64 " (%s)\n",
5223 : op1, regname (op1));
5224 : break;
5225 8 : case DW_CFA_undefined:
5226 8 : if ((uint64_t) (endp - readp) < 1)
5227 : goto invalid;
5228 8 : get_uleb128 (op1, readp, endp);
5229 16 : printf (" undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
5230 : break;
5231 0 : case DW_CFA_same_value:
5232 0 : if ((uint64_t) (endp - readp) < 1)
5233 : goto invalid;
5234 0 : get_uleb128 (op1, readp, endp);
5235 0 : printf (" same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
5236 : break;
5237 0 : case DW_CFA_register:
5238 0 : if ((uint64_t) (endp - readp) < 1)
5239 : goto invalid;
5240 0 : get_uleb128 (op1, readp, endp);
5241 0 : if ((uint64_t) (endp - readp) < 1)
5242 : goto invalid;
5243 0 : get_uleb128 (op2, readp, endp);
5244 0 : printf (" register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
5245 : op1, regname (op1), op2, regname (op2));
5246 : break;
5247 2976 : case DW_CFA_remember_state:
5248 2976 : puts (" remember_state");
5249 2976 : break;
5250 2976 : case DW_CFA_restore_state:
5251 2976 : puts (" restore_state");
5252 2976 : break;
5253 128 : case DW_CFA_def_cfa:
5254 128 : if ((uint64_t) (endp - readp) < 1)
5255 : goto invalid;
5256 128 : get_uleb128 (op1, readp, endp);
5257 128 : if ((uint64_t) (endp - readp) < 1)
5258 : goto invalid;
5259 128 : get_uleb128 (op2, readp, endp);
5260 256 : printf (" def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
5261 : op1, regname (op1), op2);
5262 : break;
5263 45 : case DW_CFA_def_cfa_register:
5264 45 : if ((uint64_t) (endp - readp) < 1)
5265 : goto invalid;
5266 45 : get_uleb128 (op1, readp, endp);
5267 90 : printf (" def_cfa_register r%" PRIu64 " (%s)\n",
5268 : op1, regname (op1));
5269 : break;
5270 25858 : case DW_CFA_def_cfa_offset:
5271 25858 : if ((uint64_t) (endp - readp) < 1)
5272 : goto invalid;
5273 25858 : get_uleb128 (op1, readp, endp);
5274 25858 : printf (" def_cfa_offset %" PRIu64 "\n", op1);
5275 : break;
5276 14 : case DW_CFA_def_cfa_expression:
5277 14 : if ((uint64_t) (endp - readp) < 1)
5278 : goto invalid;
5279 14 : get_uleb128 (op1, readp, endp); /* Length of DW_FORM_block. */
5280 28 : printf (" def_cfa_expression %" PRIu64 "\n", op1);
5281 14 : if ((uint64_t) (endp - readp) < op1)
5282 : {
5283 0 : invalid:
5284 0 : fputs (gettext (" <INVALID DATA>\n"), stdout);
5285 0 : return;
5286 : }
5287 14 : print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
5288 : op1, readp);
5289 14 : readp += op1;
5290 14 : break;
5291 0 : case DW_CFA_expression:
5292 0 : if ((uint64_t) (endp - readp) < 1)
5293 : goto invalid;
5294 0 : get_uleb128 (op1, readp, endp);
5295 0 : if ((uint64_t) (endp - readp) < 1)
5296 : goto invalid;
5297 0 : get_uleb128 (op2, readp, endp); /* Length of DW_FORM_block. */
5298 0 : printf (" expression r%" PRIu64 " (%s) \n",
5299 : op1, regname (op1));
5300 0 : if ((uint64_t) (endp - readp) < op2)
5301 : goto invalid;
5302 0 : print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
5303 : op2, readp);
5304 0 : readp += op2;
5305 0 : break;
5306 16 : case DW_CFA_offset_extended_sf:
5307 16 : if ((uint64_t) (endp - readp) < 1)
5308 : goto invalid;
5309 16 : get_uleb128 (op1, readp, endp);
5310 16 : if ((uint64_t) (endp - readp) < 1)
5311 : goto invalid;
5312 16 : get_sleb128 (sop2, readp, endp);
5313 32 : printf (" offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
5314 : PRId64 "\n",
5315 : op1, regname (op1), sop2 * data_align);
5316 : break;
5317 0 : case DW_CFA_def_cfa_sf:
5318 0 : if ((uint64_t) (endp - readp) < 1)
5319 : goto invalid;
5320 0 : get_uleb128 (op1, readp, endp);
5321 0 : if ((uint64_t) (endp - readp) < 1)
5322 : goto invalid;
5323 0 : get_sleb128 (sop2, readp, endp);
5324 0 : printf (" def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
5325 : op1, regname (op1), sop2 * data_align);
5326 : break;
5327 0 : case DW_CFA_def_cfa_offset_sf:
5328 0 : if ((uint64_t) (endp - readp) < 1)
5329 : goto invalid;
5330 0 : get_sleb128 (sop1, readp, endp);
5331 0 : printf (" def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
5332 : break;
5333 0 : case DW_CFA_val_offset:
5334 0 : if ((uint64_t) (endp - readp) < 1)
5335 : goto invalid;
5336 0 : get_uleb128 (op1, readp, endp);
5337 0 : if ((uint64_t) (endp - readp) < 1)
5338 : goto invalid;
5339 0 : get_uleb128 (op2, readp, endp);
5340 0 : printf (" val_offset %" PRIu64 " at offset %" PRIu64 "\n",
5341 : op1, op2 * data_align);
5342 : break;
5343 0 : case DW_CFA_val_offset_sf:
5344 0 : if ((uint64_t) (endp - readp) < 1)
5345 : goto invalid;
5346 0 : get_uleb128 (op1, readp, endp);
5347 0 : if ((uint64_t) (endp - readp) < 1)
5348 : goto invalid;
5349 0 : get_sleb128 (sop2, readp, endp);
5350 0 : printf (" val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
5351 : op1, sop2 * data_align);
5352 : break;
5353 0 : case DW_CFA_val_expression:
5354 0 : if ((uint64_t) (endp - readp) < 1)
5355 : goto invalid;
5356 0 : get_uleb128 (op1, readp, endp);
5357 0 : if ((uint64_t) (endp - readp) < 1)
5358 : goto invalid;
5359 0 : get_uleb128 (op2, readp, endp); /* Length of DW_FORM_block. */
5360 0 : printf (" val_expression r%" PRIu64 " (%s)\n",
5361 : op1, regname (op1));
5362 0 : if ((uint64_t) (endp - readp) < op2)
5363 : goto invalid;
5364 0 : print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0,
5365 : NULL, op2, readp);
5366 0 : readp += op2;
5367 0 : break;
5368 0 : case DW_CFA_MIPS_advance_loc8:
5369 0 : if ((uint64_t) (endp - readp) < 8)
5370 : goto invalid;
5371 0 : op1 = read_8ubyte_unaligned_inc (dbg, readp);
5372 0 : printf (" MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
5373 0 : op1, pc += op1 * code_align);
5374 : break;
5375 0 : case DW_CFA_GNU_window_save:
5376 0 : puts (" GNU_window_save");
5377 0 : break;
5378 0 : case DW_CFA_GNU_args_size:
5379 0 : if ((uint64_t) (endp - readp) < 1)
5380 : goto invalid;
5381 0 : get_uleb128 (op1, readp, endp);
5382 0 : printf (" args_size %" PRIu64 "\n", op1);
5383 : break;
5384 0 : default:
5385 : printf (" ??? (%u)\n", opcode);
5386 : break;
5387 : }
5388 36065 : else if (opcode < DW_CFA_offset)
5389 26507 : printf (" advance_loc %u to %#" PRIx64 "\n",
5390 26507 : opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
5391 9558 : else if (opcode < DW_CFA_restore)
5392 : {
5393 : uint64_t offset;
5394 8186 : if ((uint64_t) (endp - readp) < 1)
5395 : goto invalid;
5396 8186 : get_uleb128 (offset, readp, endp);
5397 16372 : printf (" offset r%u (%s) at cfa%+" PRId64 "\n",
5398 : opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
5399 : }
5400 : else
5401 2744 : printf (" restore r%u (%s)\n",
5402 : opcode & 0x3f, regname (opcode & 0x3f));
5403 : }
5404 : }
5405 :
5406 :
5407 : static unsigned int
5408 5503 : encoded_ptr_size (int encoding, unsigned int ptr_size)
5409 : {
5410 5503 : switch (encoding & 7)
5411 : {
5412 : case DW_EH_PE_udata4:
5413 : return 4;
5414 0 : case DW_EH_PE_udata8:
5415 0 : return 8;
5416 34 : case 0:
5417 34 : return ptr_size;
5418 : }
5419 :
5420 0 : fprintf (stderr, "Unsupported pointer encoding: %#x, "
5421 : "assuming pointer size of %d.\n", encoding, ptr_size);
5422 0 : return ptr_size;
5423 : }
5424 :
5425 :
5426 : static unsigned int
5427 88 : print_encoding (unsigned int val)
5428 : {
5429 88 : switch (val & 0xf)
5430 : {
5431 0 : case DW_EH_PE_absptr:
5432 0 : fputs ("absptr", stdout);
5433 0 : break;
5434 0 : case DW_EH_PE_uleb128:
5435 0 : fputs ("uleb128", stdout);
5436 0 : break;
5437 0 : case DW_EH_PE_udata2:
5438 0 : fputs ("udata2", stdout);
5439 0 : break;
5440 16 : case DW_EH_PE_udata4:
5441 16 : fputs ("udata4", stdout);
5442 16 : break;
5443 0 : case DW_EH_PE_udata8:
5444 0 : fputs ("udata8", stdout);
5445 0 : break;
5446 0 : case DW_EH_PE_sleb128:
5447 0 : fputs ("sleb128", stdout);
5448 0 : break;
5449 0 : case DW_EH_PE_sdata2:
5450 0 : fputs ("sdata2", stdout);
5451 0 : break;
5452 72 : case DW_EH_PE_sdata4:
5453 72 : fputs ("sdata4", stdout);
5454 72 : break;
5455 0 : case DW_EH_PE_sdata8:
5456 0 : fputs ("sdata8", stdout);
5457 0 : break;
5458 : default:
5459 : /* We did not use any of the bits after all. */
5460 : return val;
5461 : }
5462 :
5463 88 : return val & ~0xf;
5464 : }
5465 :
5466 :
5467 : static unsigned int
5468 72 : print_relinfo (unsigned int val)
5469 : {
5470 72 : switch (val & 0x70)
5471 : {
5472 56 : case DW_EH_PE_pcrel:
5473 56 : fputs ("pcrel", stdout);
5474 56 : break;
5475 0 : case DW_EH_PE_textrel:
5476 0 : fputs ("textrel", stdout);
5477 0 : break;
5478 16 : case DW_EH_PE_datarel:
5479 16 : fputs ("datarel", stdout);
5480 16 : break;
5481 0 : case DW_EH_PE_funcrel:
5482 0 : fputs ("funcrel", stdout);
5483 0 : break;
5484 0 : case DW_EH_PE_aligned:
5485 0 : fputs ("aligned", stdout);
5486 0 : break;
5487 : default:
5488 : return val;
5489 : }
5490 :
5491 72 : return val & ~0x70;
5492 : }
5493 :
5494 :
5495 : static void
5496 88 : print_encoding_base (const char *pfx, unsigned int fde_encoding)
5497 : {
5498 88 : printf ("(%s", pfx);
5499 :
5500 88 : if (fde_encoding == DW_EH_PE_omit)
5501 0 : puts ("omit)");
5502 : else
5503 : {
5504 88 : unsigned int w = fde_encoding;
5505 :
5506 88 : w = print_encoding (w);
5507 :
5508 88 : if (w & 0x70)
5509 : {
5510 72 : if (w != fde_encoding)
5511 72 : fputc_unlocked (' ', stdout);
5512 :
5513 72 : w = print_relinfo (w);
5514 : }
5515 :
5516 88 : if (w != 0)
5517 0 : printf ("%s%x", w != fde_encoding ? " " : "", w);
5518 :
5519 88 : puts (")");
5520 : }
5521 88 : }
5522 :
5523 :
5524 : static void
5525 42 : print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
5526 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5527 : {
5528 : size_t shstrndx;
5529 : /* We know this call will succeed since it did in the caller. */
5530 42 : (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
5531 42 : const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
5532 :
5533 : /* Needed if we find PC-relative addresses. */
5534 : GElf_Addr bias;
5535 42 : if (dwfl_module_getelf (dwflmod, &bias) == NULL)
5536 : {
5537 0 : error (0, 0, gettext ("cannot get ELF: %s"), dwfl_errmsg (-1));
5538 0 : return;
5539 : }
5540 :
5541 42 : bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
5542 42 : Elf_Data *data = (is_eh_frame
5543 : ? elf_rawdata (scn, NULL)
5544 42 : : dbg->sectiondata[IDX_debug_frame]);
5545 :
5546 42 : if (unlikely (data == NULL))
5547 : {
5548 0 : error (0, 0, gettext ("cannot get %s content: %s"),
5549 : scnname, elf_errmsg (-1));
5550 : return;
5551 : }
5552 :
5553 42 : if (is_eh_frame)
5554 28 : printf (gettext ("\
5555 : \nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5556 28 : elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
5557 : else
5558 14 : printf (gettext ("\
5559 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5560 14 : elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
5561 :
5562 : struct cieinfo
5563 : {
5564 : ptrdiff_t cie_offset;
5565 : const char *augmentation;
5566 : unsigned int code_alignment_factor;
5567 : unsigned int data_alignment_factor;
5568 : uint8_t address_size;
5569 : uint8_t fde_encoding;
5570 : uint8_t lsda_encoding;
5571 : struct cieinfo *next;
5572 42 : } *cies = NULL;
5573 :
5574 42 : const unsigned char *readp = data->d_buf;
5575 42 : const unsigned char *const dataend = ((unsigned char *) data->d_buf
5576 42 : + data->d_size);
5577 5669 : while (readp < dataend)
5578 : {
5579 5585 : if (unlikely (readp + 4 > dataend))
5580 : {
5581 0 : invalid_data:
5582 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
5583 : elf_ndxscn (scn), scnname);
5584 : return;
5585 : }
5586 :
5587 : /* At the beginning there must be a CIE. There can be multiple,
5588 : hence we test tis in a loop. */
5589 5585 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
5590 :
5591 5617 : Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
5592 5585 : unsigned int length = 4;
5593 5585 : if (unlikely (unit_length == 0xffffffff))
5594 : {
5595 0 : if (unlikely (readp + 8 > dataend))
5596 : goto invalid_data;
5597 :
5598 0 : unit_length = read_8ubyte_unaligned_inc (dbg, readp);
5599 0 : length = 8;
5600 : }
5601 :
5602 5585 : if (unlikely (unit_length == 0))
5603 : {
5604 32 : printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
5605 16 : continue;
5606 : }
5607 :
5608 5569 : Dwarf_Word maxsize = dataend - readp;
5609 5569 : if (unlikely (unit_length > maxsize))
5610 : goto invalid_data;
5611 :
5612 5569 : unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5613 :
5614 5569 : ptrdiff_t start = readp - (unsigned char *) data->d_buf;
5615 5569 : const unsigned char *const cieend = readp + unit_length;
5616 11138 : if (unlikely (cieend > dataend || readp + 8 > dataend))
5617 : goto invalid_data;
5618 :
5619 : Dwarf_Off cie_id;
5620 5569 : if (length == 4)
5621 : {
5622 5601 : cie_id = read_4ubyte_unaligned_inc (dbg, readp);
5623 5569 : if (!is_eh_frame && cie_id == DW_CIE_ID_32)
5624 24 : cie_id = DW_CIE_ID_64;
5625 : }
5626 : else
5627 0 : cie_id = read_8ubyte_unaligned_inc (dbg, readp);
5628 :
5629 5569 : uint_fast8_t version = 2;
5630 : unsigned int code_alignment_factor;
5631 : int data_alignment_factor;
5632 5569 : unsigned int fde_encoding = 0;
5633 5569 : unsigned int lsda_encoding = 0;
5634 5569 : Dwarf_Word initial_location = 0;
5635 5569 : Dwarf_Word vma_base = 0;
5636 :
5637 5569 : if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
5638 : {
5639 66 : version = *readp++;
5640 66 : const char *const augmentation = (const char *) readp;
5641 66 : readp = memchr (readp, '\0', cieend - readp);
5642 66 : if (unlikely (readp == NULL))
5643 : goto invalid_data;
5644 66 : ++readp;
5645 :
5646 66 : uint_fast8_t segment_size = 0;
5647 66 : if (version >= 4)
5648 : {
5649 0 : if (cieend - readp < 5)
5650 : goto invalid_data;
5651 0 : ptr_size = *readp++;
5652 0 : segment_size = *readp++;
5653 : }
5654 :
5655 66 : if (cieend - readp < 1)
5656 : goto invalid_data;
5657 66 : get_uleb128 (code_alignment_factor, readp, cieend);
5658 66 : if (cieend - readp < 1)
5659 : goto invalid_data;
5660 66 : get_sleb128 (data_alignment_factor, readp, cieend);
5661 :
5662 : /* In some variant for unwind data there is another field. */
5663 66 : if (strcmp (augmentation, "eh") == 0)
5664 0 : readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5665 :
5666 : unsigned int return_address_register;
5667 66 : if (cieend - readp < 1)
5668 : goto invalid_data;
5669 66 : if (unlikely (version == 1))
5670 54 : return_address_register = *readp++;
5671 : else
5672 12 : get_uleb128 (return_address_register, readp, cieend);
5673 :
5674 132 : printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
5675 : " CIE_id: %" PRIu64 "\n"
5676 : " version: %u\n"
5677 : " augmentation: \"%s\"\n",
5678 : offset, (uint64_t) unit_length, (uint64_t) cie_id,
5679 : version, augmentation);
5680 66 : if (version >= 4)
5681 0 : printf (" address_size: %u\n"
5682 : " segment_size: %u\n",
5683 : ptr_size, segment_size);
5684 66 : printf (" code_alignment_factor: %u\n"
5685 : " data_alignment_factor: %d\n"
5686 : " return_address_register: %u\n",
5687 : code_alignment_factor,
5688 : data_alignment_factor, return_address_register);
5689 :
5690 66 : if (augmentation[0] == 'z')
5691 : {
5692 : unsigned int augmentationlen;
5693 40 : get_uleb128 (augmentationlen, readp, cieend);
5694 :
5695 40 : if (augmentationlen > (size_t) (cieend - readp))
5696 : {
5697 0 : error (0, 0, gettext ("invalid augmentation length"));
5698 0 : readp = cieend;
5699 0 : continue;
5700 : }
5701 :
5702 40 : const char *hdr = "Augmentation data:";
5703 40 : const char *cp = augmentation + 1;
5704 120 : while (*cp != '\0' && cp < augmentation + augmentationlen + 1)
5705 : {
5706 80 : printf (" %-26s%#x ", hdr, *readp);
5707 40 : hdr = "";
5708 :
5709 40 : if (*cp == 'R')
5710 : {
5711 40 : fde_encoding = *readp++;
5712 40 : print_encoding_base (gettext ("FDE address encoding: "),
5713 : fde_encoding);
5714 : }
5715 0 : else if (*cp == 'L')
5716 : {
5717 0 : lsda_encoding = *readp++;
5718 0 : print_encoding_base (gettext ("LSDA pointer encoding: "),
5719 : lsda_encoding);
5720 : }
5721 0 : else if (*cp == 'P')
5722 : {
5723 : /* Personality. This field usually has a relocation
5724 : attached pointing to __gcc_personality_v0. */
5725 0 : const unsigned char *startp = readp;
5726 0 : unsigned int encoding = *readp++;
5727 0 : uint64_t val = 0;
5728 0 : readp = read_encoded (encoding, readp,
5729 0 : readp - 1 + augmentationlen,
5730 : &val, dbg);
5731 :
5732 0 : while (++startp < readp)
5733 0 : printf ("%#x ", *startp);
5734 :
5735 0 : putchar ('(');
5736 0 : print_encoding (encoding);
5737 0 : putchar (' ');
5738 0 : switch (encoding & 0xf)
5739 : {
5740 0 : case DW_EH_PE_sleb128:
5741 : case DW_EH_PE_sdata2:
5742 : case DW_EH_PE_sdata4:
5743 0 : printf ("%" PRId64 ")\n", val);
5744 : break;
5745 0 : default:
5746 0 : printf ("%#" PRIx64 ")\n", val);
5747 : break;
5748 : }
5749 : }
5750 : else
5751 0 : printf ("(%x)\n", *readp++);
5752 :
5753 40 : ++cp;
5754 : }
5755 : }
5756 :
5757 66 : if (likely (ptr_size == 4 || ptr_size == 8))
5758 : {
5759 66 : struct cieinfo *newp = alloca (sizeof (*newp));
5760 66 : newp->cie_offset = offset;
5761 66 : newp->augmentation = augmentation;
5762 66 : newp->fde_encoding = fde_encoding;
5763 66 : newp->lsda_encoding = lsda_encoding;
5764 66 : newp->address_size = ptr_size;
5765 66 : newp->code_alignment_factor = code_alignment_factor;
5766 66 : newp->data_alignment_factor = data_alignment_factor;
5767 66 : newp->next = cies;
5768 66 : cies = newp;
5769 : }
5770 : }
5771 : else
5772 : {
5773 : struct cieinfo *cie = cies;
5774 5503 : while (cie != NULL)
5775 11006 : if (is_eh_frame
5776 5475 : ? ((Dwarf_Off) start - cie_id) == (Dwarf_Off) cie->cie_offset
5777 28 : : cie_id == (Dwarf_Off) cie->cie_offset)
5778 : break;
5779 : else
5780 0 : cie = cie->next;
5781 5503 : if (unlikely (cie == NULL))
5782 : {
5783 0 : puts ("invalid CIE reference in FDE");
5784 0 : return;
5785 : }
5786 :
5787 : /* Initialize from CIE data. */
5788 5503 : fde_encoding = cie->fde_encoding;
5789 5503 : lsda_encoding = cie->lsda_encoding;
5790 5503 : ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
5791 5503 : code_alignment_factor = cie->code_alignment_factor;
5792 5503 : data_alignment_factor = cie->data_alignment_factor;
5793 :
5794 5503 : const unsigned char *base = readp;
5795 : // XXX There are sometimes relocations for this value
5796 5519 : initial_location = read_addr_unaligned_inc (ptr_size, dbg, readp);
5797 5503 : Dwarf_Word address_range
5798 5519 : = read_addr_unaligned_inc (ptr_size, dbg, readp);
5799 :
5800 : /* pcrel for an FDE address is relative to the runtime
5801 : address of the start_address field itself. Sign extend
5802 : if necessary to make sure the calculation is done on the
5803 : full 64 bit address even when initial_location only holds
5804 : the lower 32 bits. */
5805 5503 : Dwarf_Addr pc_start = initial_location;
5806 5503 : if (ptr_size == 4)
5807 5473 : pc_start = (uint64_t) (int32_t) pc_start;
5808 5503 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
5809 10938 : pc_start += ((uint64_t) shdr->sh_addr
5810 5469 : + (base - (const unsigned char *) data->d_buf)
5811 5469 : - bias);
5812 :
5813 5503 : char *a = format_dwarf_addr (dwflmod, cie->address_size,
5814 : pc_start, initial_location);
5815 11006 : printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
5816 : " CIE_pointer: %" PRIu64 "\n"
5817 : " initial_location: %s",
5818 : offset, (uint64_t) unit_length,
5819 : cie->cie_offset, (uint64_t) cie_id, a);
5820 5503 : free (a);
5821 5503 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
5822 : {
5823 10938 : vma_base = (((uint64_t) shdr->sh_offset
5824 5469 : + (base - (const unsigned char *) data->d_buf)
5825 5469 : + (uint64_t) initial_location)
5826 : & (ptr_size == 4
5827 : ? UINT64_C (0xffffffff)
5828 5469 : : UINT64_C (0xffffffffffffffff)));
5829 5469 : printf (gettext (" (offset: %#" PRIx64 ")"),
5830 : (uint64_t) vma_base);
5831 : }
5832 :
5833 5503 : printf ("\n address_range: %#" PRIx64,
5834 : (uint64_t) address_range);
5835 5503 : if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
5836 5469 : printf (gettext (" (end offset: %#" PRIx64 ")"),
5837 5469 : ((uint64_t) vma_base + (uint64_t) address_range)
5838 : & (ptr_size == 4
5839 : ? UINT64_C (0xffffffff)
5840 5469 : : UINT64_C (0xffffffffffffffff)));
5841 5503 : putchar ('\n');
5842 :
5843 5503 : if (cie->augmentation[0] == 'z')
5844 : {
5845 : unsigned int augmentationlen;
5846 5469 : if (cieend - readp < 1)
5847 : goto invalid_data;
5848 5469 : get_uleb128 (augmentationlen, readp, cieend);
5849 :
5850 5469 : if (augmentationlen > (size_t) (cieend - readp))
5851 : {
5852 0 : error (0, 0, gettext ("invalid augmentation length"));
5853 0 : readp = cieend;
5854 0 : continue;
5855 : }
5856 :
5857 5469 : if (augmentationlen > 0)
5858 : {
5859 0 : const char *hdr = "Augmentation data:";
5860 0 : const char *cp = cie->augmentation + 1;
5861 0 : unsigned int u = 0;
5862 0 : while (*cp != '\0'
5863 0 : && cp < cie->augmentation + augmentationlen + 1)
5864 : {
5865 0 : if (*cp == 'L')
5866 : {
5867 : uint64_t lsda_pointer;
5868 0 : const unsigned char *p
5869 0 : = read_encoded (lsda_encoding, &readp[u],
5870 : &readp[augmentationlen],
5871 : &lsda_pointer, dbg);
5872 0 : u = p - readp;
5873 0 : printf (gettext ("\
5874 : %-26sLSDA pointer: %#" PRIx64 "\n"),
5875 : hdr, lsda_pointer);
5876 0 : hdr = "";
5877 : }
5878 0 : ++cp;
5879 : }
5880 :
5881 0 : while (u < augmentationlen)
5882 : {
5883 0 : printf (" %-26s%#x\n", hdr, readp[u++]);
5884 0 : hdr = "";
5885 : }
5886 : }
5887 :
5888 5469 : readp += augmentationlen;
5889 : }
5890 : }
5891 :
5892 : /* Handle the initialization instructions. */
5893 5569 : if (ptr_size != 4 && ptr_size !=8)
5894 : printf ("invalid CIE pointer size (%u), must be 4 or 8.\n", ptr_size);
5895 : else
5896 5569 : print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
5897 : data_alignment_factor, version, ptr_size,
5898 : fde_encoding, dwflmod, ebl, dbg);
5899 5569 : readp = cieend;
5900 : }
5901 : }
5902 :
5903 :
5904 : struct attrcb_args
5905 : {
5906 : Dwfl_Module *dwflmod;
5907 : Dwarf *dbg;
5908 : Dwarf_Die *die;
5909 : int level;
5910 : bool silent;
5911 : unsigned int version;
5912 : unsigned int addrsize;
5913 : unsigned int offset_size;
5914 : struct Dwarf_CU *cu;
5915 : };
5916 :
5917 :
5918 : static int
5919 2782169 : attr_callback (Dwarf_Attribute *attrp, void *arg)
5920 : {
5921 2782169 : struct attrcb_args *cbargs = (struct attrcb_args *) arg;
5922 2782169 : const int level = cbargs->level;
5923 :
5924 2782169 : unsigned int attr = dwarf_whatattr (attrp);
5925 2782169 : if (unlikely (attr == 0))
5926 : {
5927 0 : if (!cbargs->silent)
5928 0 : error (0, 0, gettext ("cannot get attribute code: %s"),
5929 : dwarf_errmsg (-1));
5930 : return DWARF_CB_ABORT;
5931 : }
5932 :
5933 2782169 : unsigned int form = dwarf_whatform (attrp);
5934 2782169 : if (unlikely (form == 0))
5935 : {
5936 0 : if (!cbargs->silent)
5937 0 : error (0, 0, gettext ("cannot get attribute form: %s"),
5938 : dwarf_errmsg (-1));
5939 : return DWARF_CB_ABORT;
5940 : }
5941 :
5942 2782169 : switch (form)
5943 : {
5944 42676 : case DW_FORM_addr:
5945 42676 : if (!cbargs->silent)
5946 : {
5947 : Dwarf_Addr addr;
5948 42624 : if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
5949 : {
5950 0 : attrval_out:
5951 0 : if (!cbargs->silent)
5952 0 : error (0, 0, gettext ("cannot get attribute value: %s"),
5953 : dwarf_errmsg (-1));
5954 0 : return DWARF_CB_ABORT;
5955 : }
5956 42624 : char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize,
5957 : addr, addr);
5958 85248 : printf (" %*s%-20s (%s) %s\n",
5959 : (int) (level * 2), "", dwarf_attr_name (attr),
5960 : dwarf_form_name (form), a);
5961 42624 : free (a);
5962 : }
5963 2491704 : break;
5964 :
5965 517346 : case DW_FORM_indirect:
5966 : case DW_FORM_strp:
5967 : case DW_FORM_string:
5968 : case DW_FORM_GNU_strp_alt:
5969 517346 : if (cbargs->silent)
5970 : break;
5971 517200 : const char *str = dwarf_formstring (attrp);
5972 517200 : if (unlikely (str == NULL))
5973 : goto attrval_out;
5974 517200 : printf (" %*s%-20s (%s) \"%s\"\n",
5975 : (int) (level * 2), "", dwarf_attr_name (attr),
5976 : dwarf_form_name (form), str);
5977 : break;
5978 :
5979 664165 : case DW_FORM_ref_addr:
5980 : case DW_FORM_ref_udata:
5981 : case DW_FORM_ref8:
5982 : case DW_FORM_ref4:
5983 : case DW_FORM_ref2:
5984 : case DW_FORM_ref1:
5985 : case DW_FORM_GNU_ref_alt:
5986 664165 : if (cbargs->silent)
5987 : break;
5988 : Dwarf_Die ref;
5989 664031 : if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
5990 : goto attrval_out;
5991 :
5992 664031 : printf (" %*s%-20s (%s) [%6" PRIxMAX "]\n",
5993 : (int) (level * 2), "", dwarf_attr_name (attr),
5994 664031 : dwarf_form_name (form), (uintmax_t) dwarf_dieoffset (&ref));
5995 : break;
5996 :
5997 0 : case DW_FORM_ref_sig8:
5998 0 : if (cbargs->silent)
5999 : break;
6000 0 : printf (" %*s%-20s (%s) {%6" PRIx64 "}\n",
6001 : (int) (level * 2), "", dwarf_attr_name (attr),
6002 : dwarf_form_name (form),
6003 0 : (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
6004 : break;
6005 :
6006 1385560 : case DW_FORM_sec_offset:
6007 : case DW_FORM_udata:
6008 : case DW_FORM_sdata:
6009 : case DW_FORM_data8:
6010 : case DW_FORM_data4:
6011 : case DW_FORM_data2:
6012 : case DW_FORM_data1:;
6013 : Dwarf_Word num;
6014 1385560 : if (unlikely (dwarf_formudata (attrp, &num) != 0))
6015 : goto attrval_out;
6016 :
6017 1385560 : const char *valuestr = NULL;
6018 1385560 : switch (attr)
6019 : {
6020 : /* This case can take either a constant or a loclistptr. */
6021 235488 : case DW_AT_data_member_location:
6022 235488 : if (form != DW_FORM_sec_offset
6023 235488 : && (cbargs->version >= 4
6024 23806 : || (form != DW_FORM_data4 && form != DW_FORM_data8)))
6025 : {
6026 235488 : if (!cbargs->silent)
6027 235488 : printf (" %*s%-20s (%s) %" PRIxMAX "\n",
6028 : (int) (level * 2), "", dwarf_attr_name (attr),
6029 : dwarf_form_name (form), (uintmax_t) num);
6030 : return DWARF_CB_OK;
6031 : }
6032 : /* else fallthrough */
6033 :
6034 : /* These cases always take a loclistptr and no constant. */
6035 : case DW_AT_location:
6036 : case DW_AT_data_location:
6037 : case DW_AT_vtable_elem_location:
6038 : case DW_AT_string_length:
6039 : case DW_AT_use_location:
6040 : case DW_AT_frame_base:
6041 : case DW_AT_return_addr:
6042 : case DW_AT_static_link:
6043 : case DW_AT_GNU_call_site_value:
6044 : case DW_AT_GNU_call_site_data_value:
6045 : case DW_AT_GNU_call_site_target:
6046 : case DW_AT_GNU_call_site_target_clobbered:
6047 16 : {
6048 132309 : bool nlpt = notice_listptr (section_loc, &known_loclistptr,
6049 88206 : cbargs->addrsize, cbargs->offset_size,
6050 : cbargs->cu, num);
6051 44103 : if (!cbargs->silent)
6052 44087 : printf (" %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n",
6053 : (int) (level * 2), "", dwarf_attr_name (attr),
6054 : dwarf_form_name (form), (uintmax_t) num,
6055 : nlpt ? "" : " <WARNING offset too big>");
6056 : }
6057 : return DWARF_CB_OK;
6058 :
6059 10874 : case DW_AT_ranges:
6060 10 : {
6061 32622 : bool nlpt = notice_listptr (section_ranges, &known_rangelistptr,
6062 21748 : cbargs->addrsize, cbargs->offset_size,
6063 : cbargs->cu, num);
6064 10874 : if (!cbargs->silent)
6065 10864 : printf (" %*s%-20s (%s) range list [%6" PRIxMAX "]%s\n",
6066 : (int) (level * 2), "", dwarf_attr_name (attr),
6067 : dwarf_form_name (form), (uintmax_t) num,
6068 : nlpt ? "" : " <WARNING offset too big>");
6069 : }
6070 : return DWARF_CB_OK;
6071 :
6072 1294 : case DW_AT_language:
6073 1294 : valuestr = dwarf_lang_name (num);
6074 1294 : break;
6075 18838 : case DW_AT_encoding:
6076 37676 : valuestr = dwarf_encoding_name (num);
6077 18838 : break;
6078 0 : case DW_AT_accessibility:
6079 0 : valuestr = dwarf_access_name (num);
6080 0 : break;
6081 0 : case DW_AT_defaulted:
6082 0 : valuestr = dwarf_defaulted_name (num);
6083 0 : break;
6084 0 : case DW_AT_visibility:
6085 0 : valuestr = dwarf_visibility_name (num);
6086 0 : break;
6087 0 : case DW_AT_virtuality:
6088 0 : valuestr = dwarf_virtuality_name (num);
6089 0 : break;
6090 0 : case DW_AT_identifier_case:
6091 0 : valuestr = dwarf_identifier_case_name (num);
6092 0 : break;
6093 0 : case DW_AT_calling_convention:
6094 0 : valuestr = dwarf_calling_convention_name (num);
6095 0 : break;
6096 2943 : case DW_AT_inline:
6097 5886 : valuestr = dwarf_inline_name (num);
6098 2943 : break;
6099 0 : case DW_AT_ordering:
6100 0 : valuestr = dwarf_ordering_name (num);
6101 0 : break;
6102 0 : case DW_AT_discr_list:
6103 0 : valuestr = dwarf_discr_list_name (num);
6104 0 : break;
6105 : default:
6106 : /* Nothing. */
6107 : break;
6108 : }
6109 :
6110 1095095 : if (cbargs->silent)
6111 : break;
6112 :
6113 : /* When highpc is in constant form it is relative to lowpc.
6114 : In that case also show the address. */
6115 : Dwarf_Addr highpc;
6116 1094794 : if (attr == DW_AT_high_pc && dwarf_highpc (cbargs->die, &highpc) == 0)
6117 15240 : {
6118 15240 : char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize,
6119 : highpc, highpc);
6120 30480 : printf (" %*s%-20s (%s) %" PRIuMAX " (%s)\n",
6121 : (int) (level * 2), "", dwarf_attr_name (attr),
6122 : dwarf_form_name (form), (uintmax_t) num, a);
6123 15240 : free (a);
6124 : }
6125 : else
6126 1079554 : {
6127 1079554 : Dwarf_Sword snum = 0;
6128 1079554 : if (form == DW_FORM_sdata)
6129 1209 : if (unlikely (dwarf_formsdata (attrp, &snum) != 0))
6130 : goto attrval_out;
6131 :
6132 1079554 : if (valuestr == NULL)
6133 : {
6134 2113068 : printf (" %*s%-20s (%s)",
6135 : (int) (level * 2), "", dwarf_attr_name (attr),
6136 : dwarf_form_name (form));
6137 1056534 : if (form == DW_FORM_sdata)
6138 1209 : printf (" %" PRIdMAX "\n", (intmax_t) snum);
6139 : else
6140 1055325 : printf (" %" PRIuMAX "\n", (uintmax_t) num);
6141 : }
6142 : else
6143 : {
6144 46040 : printf (" %*s%-20s (%s) %s",
6145 : (int) (level * 2), "", dwarf_attr_name (attr),
6146 : dwarf_form_name (form), valuestr);
6147 23020 : if (form == DW_FORM_sdata)
6148 0 : printf (" (%" PRIdMAX ")\n", (intmax_t) snum);
6149 : else
6150 23020 : printf (" (%" PRIuMAX ")\n", (uintmax_t) num);
6151 : }
6152 : }
6153 : break;
6154 :
6155 9081 : case DW_FORM_flag:
6156 9081 : if (cbargs->silent)
6157 : break;
6158 : bool flag;
6159 9048 : if (unlikely (dwarf_formflag (attrp, &flag) != 0))
6160 : goto attrval_out;
6161 :
6162 9048 : printf (" %*s%-20s (%s) %s\n",
6163 : (int) (level * 2), "", dwarf_attr_name (attr),
6164 9048 : dwarf_form_name (form), flag ? gettext ("yes") : gettext ("no"));
6165 : break;
6166 :
6167 72797 : case DW_FORM_flag_present:
6168 72797 : if (cbargs->silent)
6169 : break;
6170 72788 : printf (" %*s%-20s (%s) %s\n",
6171 : (int) (level * 2), "", dwarf_attr_name (attr),
6172 : dwarf_form_name (form), gettext ("yes"));
6173 : break;
6174 :
6175 90544 : case DW_FORM_exprloc:
6176 : case DW_FORM_block4:
6177 : case DW_FORM_block2:
6178 : case DW_FORM_block1:
6179 : case DW_FORM_block:
6180 90544 : if (cbargs->silent)
6181 : break;
6182 : Dwarf_Block block;
6183 90508 : if (unlikely (dwarf_formblock (attrp, &block) != 0))
6184 : goto attrval_out;
6185 :
6186 181016 : printf (" %*s%-20s (%s) ",
6187 : (int) (level * 2), "", dwarf_attr_name (attr),
6188 : dwarf_form_name (form));
6189 :
6190 90508 : switch (attr)
6191 : {
6192 16 : default:
6193 16 : if (form != DW_FORM_exprloc)
6194 : {
6195 16 : print_block (block.length, block.data);
6196 16 : break;
6197 : }
6198 : /* Fall through. */
6199 :
6200 : case DW_AT_location:
6201 : case DW_AT_data_location:
6202 : case DW_AT_data_member_location:
6203 : case DW_AT_vtable_elem_location:
6204 : case DW_AT_string_length:
6205 : case DW_AT_use_location:
6206 : case DW_AT_frame_base:
6207 : case DW_AT_return_addr:
6208 : case DW_AT_static_link:
6209 : case DW_AT_allocated:
6210 : case DW_AT_associated:
6211 : case DW_AT_bit_size:
6212 : case DW_AT_bit_offset:
6213 : case DW_AT_bit_stride:
6214 : case DW_AT_byte_size:
6215 : case DW_AT_byte_stride:
6216 : case DW_AT_count:
6217 : case DW_AT_lower_bound:
6218 : case DW_AT_upper_bound:
6219 : case DW_AT_GNU_call_site_value:
6220 : case DW_AT_GNU_call_site_data_value:
6221 : case DW_AT_GNU_call_site_target:
6222 : case DW_AT_GNU_call_site_target_clobbered:
6223 90492 : putchar ('\n');
6224 180984 : print_ops (cbargs->dwflmod, cbargs->dbg,
6225 90492 : 12 + level * 2, 12 + level * 2,
6226 : cbargs->version, cbargs->addrsize, cbargs->offset_size,
6227 90492 : attrp->cu, block.length, block.data);
6228 90492 : break;
6229 : }
6230 : break;
6231 :
6232 0 : default:
6233 0 : if (cbargs->silent)
6234 : break;
6235 0 : printf (" %*s%-20s (form: %#x) ???\n",
6236 : (int) (level * 2), "", dwarf_attr_name (attr),
6237 : (int) form);
6238 : break;
6239 : }
6240 :
6241 2491704 : return DWARF_CB_OK;
6242 : }
6243 :
6244 : static void
6245 54 : print_debug_units (Dwfl_Module *dwflmod,
6246 : Ebl *ebl, GElf_Ehdr *ehdr,
6247 : Elf_Scn *scn, GElf_Shdr *shdr,
6248 : Dwarf *dbg, bool debug_types)
6249 : {
6250 54 : const bool silent = !(print_debug_sections & section_info);
6251 108 : const char *secname = section_name (ebl, ehdr, shdr);
6252 :
6253 54 : if (!silent)
6254 44 : printf (gettext ("\
6255 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
6256 44 : elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
6257 :
6258 : /* If the section is empty we don't have to do anything. */
6259 54 : if (!silent && shdr->sh_size == 0)
6260 0 : return;
6261 :
6262 54 : int maxdies = 20;
6263 54 : Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
6264 :
6265 54 : Dwarf_Off offset = 0;
6266 :
6267 : /* New compilation unit. */
6268 : size_t cuhl;
6269 : Dwarf_Half version;
6270 : Dwarf_Off abbroffset;
6271 : uint8_t addrsize;
6272 : uint8_t offsize;
6273 : Dwarf_Off nextcu;
6274 : uint64_t typesig;
6275 : Dwarf_Off typeoff;
6276 2642 : next_cu:
6277 1348 : if (dwarf_next_unit (dbg, offset, &nextcu, &cuhl, &version,
6278 : &abbroffset, &addrsize, &offsize,
6279 : debug_types ? &typesig : NULL,
6280 : debug_types ? &typeoff : NULL) != 0)
6281 : goto do_return;
6282 :
6283 1294 : if (!silent)
6284 : {
6285 1281 : if (debug_types)
6286 0 : printf (gettext (" Type unit at offset %" PRIu64 ":\n"
6287 : " Version: %" PRIu16 ", Abbreviation section offset: %"
6288 : PRIu64 ", Address size: %" PRIu8
6289 : ", Offset size: %" PRIu8
6290 : "\n Type signature: %#" PRIx64
6291 : ", Type offset: %#" PRIx64 "\n"),
6292 : (uint64_t) offset, version, abbroffset, addrsize, offsize,
6293 : typesig, (uint64_t) typeoff);
6294 : else
6295 1281 : printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
6296 : " Version: %" PRIu16 ", Abbreviation section offset: %"
6297 : PRIu64 ", Address size: %" PRIu8
6298 : ", Offset size: %" PRIu8 "\n"),
6299 : (uint64_t) offset, version, abbroffset, addrsize, offsize);
6300 : }
6301 :
6302 1294 : struct attrcb_args args =
6303 : {
6304 : .dwflmod = dwflmod,
6305 : .dbg = dbg,
6306 : .silent = silent,
6307 : .version = version,
6308 : .addrsize = addrsize,
6309 : .offset_size = offsize
6310 : };
6311 :
6312 1294 : offset += cuhl;
6313 :
6314 1294 : int level = 0;
6315 :
6316 1294 : if (unlikely ((debug_types ? dwarf_offdie_types : dwarf_offdie)
6317 : (dbg, offset, &dies[level]) == NULL))
6318 : {
6319 0 : if (!silent)
6320 0 : error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
6321 : " in section '%s': %s"),
6322 : (uint64_t) offset, secname, dwarf_errmsg (-1));
6323 : goto do_return;
6324 : }
6325 :
6326 1294 : args.cu = dies[0].cu;
6327 :
6328 : do
6329 : {
6330 794470 : offset = dwarf_dieoffset (&dies[level]);
6331 794470 : if (unlikely (offset == ~0ul))
6332 : {
6333 0 : if (!silent)
6334 0 : error (0, 0, gettext ("cannot get DIE offset: %s"),
6335 : dwarf_errmsg (-1));
6336 : goto do_return;
6337 : }
6338 :
6339 794470 : int tag = dwarf_tag (&dies[level]);
6340 794470 : if (unlikely (tag == DW_TAG_invalid))
6341 : {
6342 0 : if (!silent)
6343 0 : error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
6344 : " in section '%s': %s"),
6345 : (uint64_t) offset, secname, dwarf_errmsg (-1));
6346 : goto do_return;
6347 : }
6348 :
6349 794470 : if (!silent)
6350 794309 : printf (" [%6" PRIx64 "] %*s%s\n",
6351 : (uint64_t) offset, (int) (level * 2), "",
6352 : dwarf_tag_name (tag));
6353 :
6354 : /* Print the attribute values. */
6355 794470 : args.level = level;
6356 794470 : args.die = &dies[level];
6357 794470 : (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
6358 :
6359 : /* Make room for the next level's DIE. */
6360 794470 : if (level + 1 == maxdies)
6361 0 : dies = (Dwarf_Die *) xrealloc (dies,
6362 0 : (maxdies += 10)
6363 : * sizeof (Dwarf_Die));
6364 :
6365 794470 : int res = dwarf_child (&dies[level], &dies[level + 1]);
6366 794470 : if (res > 0)
6367 : {
6368 794470 : while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
6369 112632 : if (level-- == 0)
6370 : break;
6371 :
6372 683132 : if (unlikely (res == -1))
6373 : {
6374 0 : if (!silent)
6375 0 : error (0, 0, gettext ("cannot get next DIE: %s\n"),
6376 : dwarf_errmsg (-1));
6377 : goto do_return;
6378 : }
6379 : }
6380 111338 : else if (unlikely (res < 0))
6381 : {
6382 0 : if (!silent)
6383 0 : error (0, 0, gettext ("cannot get next DIE: %s"),
6384 : dwarf_errmsg (-1));
6385 : goto do_return;
6386 : }
6387 : else
6388 : ++level;
6389 : }
6390 794470 : while (level >= 0);
6391 :
6392 1294 : offset = nextcu;
6393 1294 : if (offset != 0)
6394 : goto next_cu;
6395 :
6396 54 : do_return:
6397 54 : free (dies);
6398 : }
6399 :
6400 : static void
6401 54 : print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
6402 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6403 : {
6404 54 : print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
6405 54 : }
6406 :
6407 : static void
6408 0 : print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
6409 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6410 : {
6411 0 : print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
6412 0 : }
6413 :
6414 :
6415 : static void
6416 1 : print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
6417 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6418 : {
6419 3 : printf (gettext ("\
6420 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n\n"),
6421 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6422 1 : (uint64_t) shdr->sh_offset);
6423 :
6424 1 : size_t address_size
6425 1 : = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6426 :
6427 : Dwarf_Off cuoffset;
6428 1 : Dwarf_Off ncuoffset = 0;
6429 : size_t hsize;
6430 5 : while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
6431 : NULL, NULL, NULL) == 0)
6432 : {
6433 : Dwarf_Die cudie;
6434 3 : if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
6435 0 : continue;
6436 :
6437 : size_t nlines;
6438 : Dwarf_Lines *lines;
6439 3 : if (dwarf_getsrclines (&cudie, &lines, &nlines) != 0)
6440 0 : continue;
6441 :
6442 6 : printf (" CU [%" PRIx64 "] %s\n",
6443 : dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
6444 3 : printf (" line:col SBPE* disc isa op address"
6445 : " (Statement Block Prologue Epilogue *End)\n");
6446 3 : const char *last_file = "";
6447 42 : for (size_t n = 0; n < nlines; n++)
6448 : {
6449 39 : Dwarf_Line *line = dwarf_onesrcline (lines, n);
6450 39 : if (line == NULL)
6451 : {
6452 0 : printf (" dwarf_onesrcline: %s\n", dwarf_errmsg (-1));
6453 0 : continue;
6454 : }
6455 : Dwarf_Word mtime, length;
6456 39 : const char *file = dwarf_linesrc (line, &mtime, &length);
6457 39 : if (file == NULL)
6458 : {
6459 0 : printf (" <%s> (mtime: ?, length: ?)\n", dwarf_errmsg (-1));
6460 0 : last_file = "";
6461 : }
6462 39 : else if (strcmp (last_file, file) != 0)
6463 : {
6464 6 : printf (" %s (mtime: %" PRIu64 ", length: %" PRIu64 ")\n",
6465 : file, mtime, length);
6466 3 : last_file = file;
6467 : }
6468 :
6469 : int lineno, colno;
6470 : bool statement, endseq, block, prologue_end, epilogue_begin;
6471 : unsigned int lineop, isa, disc;
6472 : Dwarf_Addr address;
6473 39 : dwarf_lineaddr (line, &address);
6474 39 : dwarf_lineno (line, &lineno);
6475 39 : dwarf_linecol (line, &colno);
6476 39 : dwarf_lineop_index (line, &lineop);
6477 39 : dwarf_linebeginstatement (line, &statement);
6478 39 : dwarf_lineendsequence (line, &endseq);
6479 39 : dwarf_lineblock (line, &block);
6480 39 : dwarf_lineprologueend (line, &prologue_end);
6481 39 : dwarf_lineepiloguebegin (line, &epilogue_begin);
6482 39 : dwarf_lineisa (line, &isa);
6483 39 : dwarf_linediscriminator (line, &disc);
6484 :
6485 : /* End sequence is special, it is one byte past. */
6486 78 : char *a = format_dwarf_addr (dwflmod, address_size,
6487 39 : address - (endseq ? 1 : 0), address);
6488 273 : printf (" %4d:%-3d %c%c%c%c%c %4d %3d %2d %s\n",
6489 : lineno, colno,
6490 39 : (statement ? 'S' : ' '),
6491 39 : (block ? 'B' : ' '),
6492 39 : (prologue_end ? 'P' : ' '),
6493 39 : (epilogue_begin ? 'E' : ' '),
6494 39 : (endseq ? '*' : ' '),
6495 : disc, isa, lineop, a);
6496 39 : free (a);
6497 :
6498 39 : if (endseq)
6499 : printf("\n");
6500 : }
6501 : }
6502 1 : }
6503 :
6504 :
6505 : static void
6506 38 : print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
6507 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6508 : {
6509 38 : if (decodedline)
6510 : {
6511 1 : print_decoded_line_section (dwflmod, ebl, ehdr, scn, shdr, dbg);
6512 1 : return;
6513 : }
6514 :
6515 111 : printf (gettext ("\
6516 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6517 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6518 37 : (uint64_t) shdr->sh_offset);
6519 :
6520 37 : if (shdr->sh_size == 0)
6521 : return;
6522 :
6523 : /* There is no functionality in libdw to read the information in the
6524 : way it is represented here. Hardcode the decoder. */
6525 37 : Elf_Data *data = dbg->sectiondata[IDX_debug_line];
6526 37 : if (unlikely (data == NULL || data->d_buf == NULL))
6527 : {
6528 0 : error (0, 0, gettext ("cannot get line data section data: %s"),
6529 : elf_errmsg (-1));
6530 : return;
6531 : }
6532 :
6533 37 : const unsigned char *linep = (const unsigned char *) data->d_buf;
6534 : const unsigned char *lineendp;
6535 :
6536 1350 : while (linep
6537 1313 : < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
6538 : {
6539 1276 : size_t start_offset = linep - (const unsigned char *) data->d_buf;
6540 :
6541 2552 : printf (gettext ("\nTable at offset %zu:\n"), start_offset);
6542 :
6543 1276 : if (unlikely (linep + 4 > lineendp))
6544 : goto invalid_data;
6545 1294 : Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
6546 1276 : unsigned int length = 4;
6547 1276 : if (unlikely (unit_length == 0xffffffff))
6548 : {
6549 0 : if (unlikely (linep + 8 > lineendp))
6550 : {
6551 0 : invalid_data:
6552 0 : error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
6553 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
6554 0 : return;
6555 : }
6556 0 : unit_length = read_8ubyte_unaligned_inc (dbg, linep);
6557 0 : length = 8;
6558 : }
6559 :
6560 : /* Check whether we have enough room in the section. */
6561 2552 : if (unlikely (unit_length > (size_t) (lineendp - linep)
6562 : || unit_length < 2 + length + 5 * 1))
6563 : goto invalid_data;
6564 1276 : lineendp = linep + unit_length;
6565 :
6566 : /* The next element of the header is the version identifier. */
6567 1276 : uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
6568 :
6569 : /* Next comes the header length. */
6570 : Dwarf_Word header_length;
6571 1276 : if (length == 4)
6572 1294 : header_length = read_4ubyte_unaligned_inc (dbg, linep);
6573 : else
6574 0 : header_length = read_8ubyte_unaligned_inc (dbg, linep);
6575 : //const unsigned char *header_start = linep;
6576 :
6577 : /* Next the minimum instruction length. */
6578 1276 : uint_fast8_t minimum_instr_len = *linep++;
6579 :
6580 : /* Next the maximum operations per instruction, in version 4 format. */
6581 1276 : uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++;
6582 :
6583 : /* Then the flag determining the default value of the is_stmt
6584 : register. */
6585 1276 : uint_fast8_t default_is_stmt = *linep++;
6586 :
6587 : /* Now the line base. */
6588 1276 : int_fast8_t line_base = *((const int_fast8_t *) linep);
6589 1276 : ++linep;
6590 :
6591 : /* And the line range. */
6592 1276 : uint_fast8_t line_range = *linep++;
6593 :
6594 : /* The opcode base. */
6595 1276 : uint_fast8_t opcode_base = *linep++;
6596 :
6597 : /* Print what we got so far. */
6598 2552 : printf (gettext ("\n"
6599 : " Length: %" PRIu64 "\n"
6600 : " DWARF version: %" PRIuFAST16 "\n"
6601 : " Prologue length: %" PRIu64 "\n"
6602 : " Minimum instruction length: %" PRIuFAST8 "\n"
6603 : " Maximum operations per instruction: %" PRIuFAST8 "\n"
6604 : " Initial value if '%s': %" PRIuFAST8 "\n"
6605 : " Line base: %" PRIdFAST8 "\n"
6606 : " Line range: %" PRIuFAST8 "\n"
6607 : " Opcode base: %" PRIuFAST8 "\n"
6608 : "\n"
6609 : "Opcodes:\n"),
6610 : (uint64_t) unit_length, version, (uint64_t) header_length,
6611 : minimum_instr_len, max_ops_per_instr,
6612 : "is_stmt", default_is_stmt, line_base,
6613 : line_range, opcode_base);
6614 :
6615 1276 : if (unlikely (linep + opcode_base - 1 >= lineendp))
6616 : {
6617 0 : invalid_unit:
6618 0 : error (0, 0,
6619 0 : gettext ("invalid data at offset %tu in section [%zu] '%s'"),
6620 0 : linep - (const unsigned char *) data->d_buf,
6621 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
6622 0 : linep = lineendp;
6623 0 : continue;
6624 : }
6625 1276 : int opcode_base_l10 = 1;
6626 1276 : unsigned int tmp = opcode_base;
6627 3826 : while (tmp > 10)
6628 : {
6629 1274 : tmp /= 10;
6630 1274 : ++opcode_base_l10;
6631 : }
6632 1276 : const uint8_t *standard_opcode_lengths = linep - 1;
6633 16582 : for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
6634 30612 : printf (ngettext (" [%*" PRIuFAST8 "] %hhu argument\n",
6635 : " [%*" PRIuFAST8 "] %hhu arguments\n",
6636 : (int) linep[cnt - 1]),
6637 15306 : opcode_base_l10, cnt, linep[cnt - 1]);
6638 1276 : linep += opcode_base - 1;
6639 1276 : if (unlikely (linep >= lineendp))
6640 : goto invalid_unit;
6641 :
6642 1276 : puts (gettext ("\nDirectory table:"));
6643 10824 : while (*linep != 0)
6644 : {
6645 8272 : unsigned char *endp = memchr (linep, '\0', lineendp - linep);
6646 8272 : if (unlikely (endp == NULL))
6647 : goto invalid_unit;
6648 :
6649 16544 : printf (" %s\n", (char *) linep);
6650 :
6651 8272 : linep = endp + 1;
6652 : }
6653 : /* Skip the final NUL byte. */
6654 1276 : ++linep;
6655 :
6656 1276 : if (unlikely (linep >= lineendp))
6657 : goto invalid_unit;
6658 1276 : puts (gettext ("\nFile name table:\n"
6659 : " Entry Dir Time Size Name"));
6660 23377 : for (unsigned int cnt = 1; *linep != 0; ++cnt)
6661 : {
6662 : /* First comes the file name. */
6663 22101 : char *fname = (char *) linep;
6664 22101 : unsigned char *endp = memchr (fname, '\0', lineendp - linep);
6665 22101 : if (unlikely (endp == NULL))
6666 : goto invalid_unit;
6667 22101 : linep = endp + 1;
6668 :
6669 : /* Then the index. */
6670 : unsigned int diridx;
6671 22101 : if (lineendp - linep < 1)
6672 : goto invalid_unit;
6673 22101 : get_uleb128 (diridx, linep, lineendp);
6674 :
6675 : /* Next comes the modification time. */
6676 : unsigned int mtime;
6677 22101 : if (lineendp - linep < 1)
6678 : goto invalid_unit;
6679 22101 : get_uleb128 (mtime, linep, lineendp);
6680 :
6681 : /* Finally the length of the file. */
6682 : unsigned int fsize;
6683 22101 : if (lineendp - linep < 1)
6684 : goto invalid_unit;
6685 22101 : get_uleb128 (fsize, linep, lineendp);
6686 :
6687 22101 : printf (" %-5u %-5u %-9u %-9u %s\n",
6688 : cnt, diridx, mtime, fsize, fname);
6689 : }
6690 : /* Skip the final NUL byte. */
6691 1276 : ++linep;
6692 :
6693 1276 : puts (gettext ("\nLine number statements:"));
6694 : Dwarf_Word address = 0;
6695 : unsigned int op_index = 0;
6696 1276 : size_t line = 1;
6697 1276 : uint_fast8_t is_stmt = default_is_stmt;
6698 :
6699 : /* Default address value, in case we do not find the CU. */
6700 1276 : size_t address_size
6701 1276 : = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6702 :
6703 : /* Determine the CU this block is for. */
6704 : Dwarf_Off cuoffset;
6705 1276 : Dwarf_Off ncuoffset = 0;
6706 : size_t hsize;
6707 95842 : while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
6708 : NULL, NULL, NULL) == 0)
6709 : {
6710 : Dwarf_Die cudie;
6711 94566 : if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
6712 0 : continue;
6713 : Dwarf_Attribute stmt_list;
6714 94566 : if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
6715 0 : continue;
6716 : Dwarf_Word lineoff;
6717 94566 : if (dwarf_formudata (&stmt_list, &lineoff) != 0)
6718 0 : continue;
6719 94566 : if (lineoff == start_offset)
6720 : {
6721 : /* Found the CU. */
6722 1276 : address_size = cudie.cu->address_size;
6723 1276 : break;
6724 : }
6725 : }
6726 :
6727 : /* Apply the "operation advance" from a special opcode
6728 : or DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */
6729 : unsigned int op_addr_advance;
6730 : bool show_op_index;
6731 : inline void advance_pc (unsigned int op_advance)
6732 : {
6733 319556 : op_addr_advance = minimum_instr_len * ((op_index + op_advance)
6734 159778 : / max_ops_per_instr);
6735 159778 : address += op_advance;
6736 319556 : show_op_index = (op_index > 0 ||
6737 159778 : (op_index + op_advance) % max_ops_per_instr > 0);
6738 159778 : op_index = (op_index + op_advance) % max_ops_per_instr;
6739 : }
6740 :
6741 1276 : if (max_ops_per_instr == 0)
6742 : {
6743 0 : error (0, 0,
6744 0 : gettext ("invalid maximum operations per instruction is zero"));
6745 0 : linep = lineendp;
6746 0 : continue;
6747 : }
6748 :
6749 258877 : while (linep < lineendp)
6750 : {
6751 257601 : size_t offset = linep - (const unsigned char *) data->d_buf;
6752 : unsigned int u128;
6753 : int s128;
6754 :
6755 : /* Read the opcode. */
6756 257601 : unsigned int opcode = *linep++;
6757 :
6758 257601 : printf (" [%6" PRIx64 "]", (uint64_t)offset);
6759 : /* Is this a special opcode? */
6760 257601 : if (likely (opcode >= opcode_base))
6761 : {
6762 118654 : if (unlikely (line_range == 0))
6763 : goto invalid_unit;
6764 :
6765 : /* Yes. Handling this is quite easy since the opcode value
6766 : is computed with
6767 :
6768 : opcode = (desired line increment - line_base)
6769 : + (line_range * address advance) + opcode_base
6770 : */
6771 118654 : int line_increment = (line_base
6772 118654 : + (opcode - opcode_base) % line_range);
6773 :
6774 : /* Perform the increments. */
6775 118654 : line += line_increment;
6776 237308 : advance_pc ((opcode - opcode_base) / line_range);
6777 :
6778 118654 : char *a = format_dwarf_addr (dwflmod, 0, address, address);
6779 118654 : if (show_op_index)
6780 0 : printf (gettext ("\
6781 : special opcode %u: address+%u = %s, op_index = %u, line%+d = %zu\n"),
6782 : opcode, op_addr_advance, a, op_index,
6783 : line_increment, line);
6784 : else
6785 118654 : printf (gettext ("\
6786 : special opcode %u: address+%u = %s, line%+d = %zu\n"),
6787 : opcode, op_addr_advance, a, line_increment, line);
6788 118654 : free (a);
6789 : }
6790 138947 : else if (opcode == 0)
6791 : {
6792 : /* This an extended opcode. */
6793 14604 : if (unlikely (linep + 2 > lineendp))
6794 : goto invalid_unit;
6795 :
6796 : /* The length. */
6797 14604 : unsigned int len = *linep++;
6798 :
6799 14604 : if (unlikely (linep + len > lineendp))
6800 : goto invalid_unit;
6801 :
6802 : /* The sub-opcode. */
6803 14604 : opcode = *linep++;
6804 :
6805 29208 : printf (gettext (" extended opcode %u: "), opcode);
6806 :
6807 14604 : switch (opcode)
6808 : {
6809 1311 : case DW_LNE_end_sequence:
6810 1311 : puts (gettext (" end of sequence"));
6811 :
6812 : /* Reset the registers we care about. */
6813 : address = 0;
6814 : op_index = 0;
6815 1311 : line = 1;
6816 1311 : is_stmt = default_is_stmt;
6817 1311 : break;
6818 :
6819 1331 : case DW_LNE_set_address:
6820 : op_index = 0;
6821 1331 : if (unlikely ((size_t) (lineendp - linep) < address_size))
6822 : goto invalid_unit;
6823 1331 : if (address_size == 4)
6824 17 : address = read_4ubyte_unaligned_inc (dbg, linep);
6825 : else
6826 1326 : address = read_8ubyte_unaligned_inc (dbg, linep);
6827 : {
6828 1331 : char *a = format_dwarf_addr (dwflmod, 0, address, address);
6829 2662 : printf (gettext (" set address to %s\n"), a);
6830 1331 : free (a);
6831 : }
6832 1331 : break;
6833 :
6834 0 : case DW_LNE_define_file:
6835 : {
6836 0 : char *fname = (char *) linep;
6837 0 : unsigned char *endp = memchr (linep, '\0',
6838 0 : lineendp - linep);
6839 0 : if (unlikely (endp == NULL))
6840 : goto invalid_unit;
6841 0 : linep = endp + 1;
6842 :
6843 : unsigned int diridx;
6844 0 : if (lineendp - linep < 1)
6845 : goto invalid_unit;
6846 0 : get_uleb128 (diridx, linep, lineendp);
6847 : Dwarf_Word mtime;
6848 0 : if (lineendp - linep < 1)
6849 : goto invalid_unit;
6850 0 : get_uleb128 (mtime, linep, lineendp);
6851 : Dwarf_Word filelength;
6852 0 : if (lineendp - linep < 1)
6853 : goto invalid_unit;
6854 0 : get_uleb128 (filelength, linep, lineendp);
6855 :
6856 0 : printf (gettext ("\
6857 : define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
6858 : diridx, (uint64_t) mtime, (uint64_t) filelength,
6859 : fname);
6860 : }
6861 : break;
6862 :
6863 11962 : case DW_LNE_set_discriminator:
6864 : /* Takes one ULEB128 parameter, the discriminator. */
6865 11962 : if (unlikely (standard_opcode_lengths[opcode] != 1))
6866 : goto invalid_unit;
6867 :
6868 11962 : get_uleb128 (u128, linep, lineendp);
6869 11962 : printf (gettext (" set discriminator to %u\n"), u128);
6870 : break;
6871 :
6872 0 : default:
6873 : /* Unknown, ignore it. */
6874 0 : puts (gettext (" unknown opcode"));
6875 0 : linep += len - 1;
6876 0 : break;
6877 : }
6878 : }
6879 124343 : else if (opcode <= DW_LNS_set_isa)
6880 : {
6881 : /* This is a known standard opcode. */
6882 124343 : switch (opcode)
6883 : {
6884 8731 : case DW_LNS_copy:
6885 : /* Takes no argument. */
6886 8731 : puts (gettext (" copy"));
6887 8731 : break;
6888 :
6889 12660 : case DW_LNS_advance_pc:
6890 : /* Takes one uleb128 parameter which is added to the
6891 : address. */
6892 12660 : get_uleb128 (u128, linep, lineendp);
6893 12660 : advance_pc (u128);
6894 : {
6895 12660 : char *a = format_dwarf_addr (dwflmod, 0, address, address);
6896 12660 : if (show_op_index)
6897 0 : printf (gettext ("\
6898 : advance address by %u to %s, op_index to %u\n"),
6899 : op_addr_advance, a, op_index);
6900 : else
6901 12660 : printf (gettext (" advance address by %u to %s\n"),
6902 : op_addr_advance, a);
6903 12660 : free (a);
6904 : }
6905 12660 : break;
6906 :
6907 50744 : case DW_LNS_advance_line:
6908 : /* Takes one sleb128 parameter which is added to the
6909 : line. */
6910 50744 : get_sleb128 (s128, linep, lineendp);
6911 50744 : line += s128;
6912 50744 : printf (gettext ("\
6913 : advance line by constant %d to %" PRId64 "\n"),
6914 : s128, (int64_t) line);
6915 : break;
6916 :
6917 18920 : case DW_LNS_set_file:
6918 : /* Takes one uleb128 parameter which is stored in file. */
6919 18920 : get_uleb128 (u128, linep, lineendp);
6920 18920 : printf (gettext (" set file to %" PRIu64 "\n"),
6921 : (uint64_t) u128);
6922 : break;
6923 :
6924 0 : case DW_LNS_set_column:
6925 : /* Takes one uleb128 parameter which is stored in column. */
6926 0 : if (unlikely (standard_opcode_lengths[opcode] != 1))
6927 : goto invalid_unit;
6928 :
6929 0 : get_uleb128 (u128, linep, lineendp);
6930 0 : printf (gettext (" set column to %" PRIu64 "\n"),
6931 : (uint64_t) u128);
6932 : break;
6933 :
6934 4824 : case DW_LNS_negate_stmt:
6935 : /* Takes no argument. */
6936 4824 : is_stmt = 1 - is_stmt;
6937 4824 : printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
6938 : "is_stmt", is_stmt);
6939 : break;
6940 :
6941 0 : case DW_LNS_set_basic_block:
6942 : /* Takes no argument. */
6943 0 : puts (gettext (" set basic block flag"));
6944 0 : break;
6945 :
6946 28464 : case DW_LNS_const_add_pc:
6947 : /* Takes no argument. */
6948 :
6949 28464 : if (unlikely (line_range == 0))
6950 : goto invalid_unit;
6951 :
6952 56928 : advance_pc ((255 - opcode_base) / line_range);
6953 : {
6954 28464 : char *a = format_dwarf_addr (dwflmod, 0, address, address);
6955 28464 : if (show_op_index)
6956 0 : printf (gettext ("\
6957 : advance address by constant %u to %s, op_index to %u\n"),
6958 : op_addr_advance, a, op_index);
6959 : else
6960 28464 : printf (gettext ("\
6961 : advance address by constant %u to %s\n"),
6962 : op_addr_advance, a);
6963 28464 : free (a);
6964 : }
6965 28464 : break;
6966 :
6967 0 : case DW_LNS_fixed_advance_pc:
6968 : /* Takes one 16 bit parameter which is added to the
6969 : address. */
6970 0 : if (unlikely (standard_opcode_lengths[opcode] != 1))
6971 : goto invalid_unit;
6972 :
6973 0 : u128 = read_2ubyte_unaligned_inc (dbg, linep);
6974 0 : address += u128;
6975 : op_index = 0;
6976 : {
6977 0 : char *a = format_dwarf_addr (dwflmod, 0, address, address);
6978 0 : printf (gettext ("\
6979 : advance address by fixed value %u to %s\n"),
6980 : u128, a);
6981 0 : free (a);
6982 : }
6983 0 : break;
6984 :
6985 0 : case DW_LNS_set_prologue_end:
6986 : /* Takes no argument. */
6987 0 : puts (gettext (" set prologue end flag"));
6988 0 : break;
6989 :
6990 0 : case DW_LNS_set_epilogue_begin:
6991 : /* Takes no argument. */
6992 0 : puts (gettext (" set epilogue begin flag"));
6993 0 : break;
6994 :
6995 0 : case DW_LNS_set_isa:
6996 : /* Takes one uleb128 parameter which is stored in isa. */
6997 0 : if (unlikely (standard_opcode_lengths[opcode] != 1))
6998 : goto invalid_unit;
6999 :
7000 0 : get_uleb128 (u128, linep, lineendp);
7001 0 : printf (gettext (" set isa to %u\n"), u128);
7002 : break;
7003 : }
7004 : }
7005 : else
7006 : {
7007 : /* This is a new opcode the generator but not we know about.
7008 : Read the parameters associated with it but then discard
7009 : everything. Read all the parameters for this opcode. */
7010 0 : printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
7011 : " unknown opcode with %" PRIu8 " parameters:",
7012 : standard_opcode_lengths[opcode]),
7013 0 : standard_opcode_lengths[opcode]);
7014 0 : for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
7015 : {
7016 0 : get_uleb128 (u128, linep, lineendp);
7017 0 : if (n != standard_opcode_lengths[opcode])
7018 0 : putc_unlocked (',', stdout);
7019 0 : printf (" %u", u128);
7020 : }
7021 :
7022 : /* Next round, ignore this opcode. */
7023 0 : continue;
7024 : }
7025 : }
7026 : }
7027 :
7028 : /* There must only be one data block. */
7029 37 : assert (elf_getdata (scn, data) == NULL);
7030 : }
7031 :
7032 :
7033 : static void
7034 30 : print_debug_loc_section (Dwfl_Module *dwflmod,
7035 : Ebl *ebl, GElf_Ehdr *ehdr,
7036 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7037 : {
7038 30 : Elf_Data *data = dbg->sectiondata[IDX_debug_loc];
7039 :
7040 30 : if (unlikely (data == NULL))
7041 : {
7042 0 : error (0, 0, gettext ("cannot get .debug_loc content: %s"),
7043 : elf_errmsg (-1));
7044 0 : return;
7045 : }
7046 :
7047 90 : printf (gettext ("\
7048 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
7049 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7050 30 : (uint64_t) shdr->sh_offset);
7051 :
7052 60 : sort_listptr (&known_loclistptr, "loclistptr");
7053 30 : size_t listptr_idx = 0;
7054 :
7055 30 : uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
7056 30 : uint_fast8_t offset_size = 4;
7057 :
7058 30 : bool first = true;
7059 30 : struct Dwarf_CU *cu = NULL;
7060 30 : Dwarf_Addr base = 0;
7061 30 : unsigned char *readp = data->d_buf;
7062 30 : unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
7063 210714 : while (readp < endp)
7064 : {
7065 210654 : ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
7066 :
7067 210654 : if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx,
7068 : &address_size, &offset_size, &base,
7069 : &cu, offset, &readp, endp))
7070 0 : continue;
7071 :
7072 210654 : if (unlikely (data->d_size - offset < (size_t) address_size * 2))
7073 : {
7074 0 : printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
7075 : break;
7076 : }
7077 :
7078 : Dwarf_Addr begin;
7079 : Dwarf_Addr end;
7080 210654 : if (address_size == 8)
7081 : {
7082 210654 : begin = read_8ubyte_unaligned_inc (dbg, readp);
7083 210654 : end = read_8ubyte_unaligned_inc (dbg, readp);
7084 : }
7085 : else
7086 : {
7087 0 : begin = read_4ubyte_unaligned_inc (dbg, readp);
7088 0 : end = read_4ubyte_unaligned_inc (dbg, readp);
7089 0 : if (begin == (Dwarf_Addr) (uint32_t) -1)
7090 : begin = (Dwarf_Addr) -1l;
7091 : }
7092 :
7093 210654 : if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
7094 : {
7095 0 : char *b = format_dwarf_addr (dwflmod, address_size, end, end);
7096 0 : printf (gettext (" [%6tx] base address %s\n"), offset, b);
7097 0 : free (b);
7098 0 : base = end;
7099 : }
7100 210654 : else if (begin == 0 && end == 0) /* End of list entry. */
7101 : {
7102 42545 : if (first)
7103 0 : printf (gettext (" [%6tx] empty list\n"), offset);
7104 : first = true;
7105 : }
7106 : else
7107 : {
7108 : /* We have a location expression entry. */
7109 168109 : uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
7110 :
7111 168109 : char *b = format_dwarf_addr (dwflmod, address_size, base + begin,
7112 : begin);
7113 168109 : char *e = format_dwarf_addr (dwflmod, address_size, base + end,
7114 : end);
7115 :
7116 168109 : if (first) /* First entry in a list. */
7117 42545 : printf (gettext (" [%6tx] %s..%s"), offset, b, e);
7118 : else
7119 125564 : printf (gettext (" %s..%s"), b, e);
7120 :
7121 168109 : free (b);
7122 168109 : free (e);
7123 :
7124 168109 : if (endp - readp <= (ptrdiff_t) len)
7125 : {
7126 0 : fputs (gettext (" <INVALID DATA>\n"), stdout);
7127 0 : break;
7128 : }
7129 :
7130 168109 : print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
7131 : 3 /*XXX*/, address_size, offset_size, cu, len, readp);
7132 :
7133 168109 : first = false;
7134 168109 : readp += len;
7135 : }
7136 : }
7137 : }
7138 :
7139 : struct mac_culist
7140 : {
7141 : Dwarf_Die die;
7142 : Dwarf_Off offset;
7143 : Dwarf_Files *files;
7144 : struct mac_culist *next;
7145 : };
7146 :
7147 :
7148 : static int
7149 0 : mac_compare (const void *p1, const void *p2)
7150 : {
7151 0 : struct mac_culist *m1 = (struct mac_culist *) p1;
7152 0 : struct mac_culist *m2 = (struct mac_culist *) p2;
7153 :
7154 0 : if (m1->offset < m2->offset)
7155 : return -1;
7156 0 : if (m1->offset > m2->offset)
7157 : return 1;
7158 0 : return 0;
7159 : }
7160 :
7161 :
7162 : static void
7163 0 : print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
7164 : Ebl *ebl, GElf_Ehdr *ehdr,
7165 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7166 : {
7167 0 : printf (gettext ("\
7168 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
7169 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7170 0 : (uint64_t) shdr->sh_offset);
7171 0 : putc_unlocked ('\n', stdout);
7172 :
7173 : /* There is no function in libdw to iterate over the raw content of
7174 : the section but it is easy enough to do. */
7175 0 : Elf_Data *data = dbg->sectiondata[IDX_debug_macinfo];
7176 0 : if (unlikely (data == NULL || data->d_buf == NULL))
7177 : {
7178 0 : error (0, 0, gettext ("cannot get macro information section data: %s"),
7179 : elf_errmsg (-1));
7180 0 : return;
7181 : }
7182 :
7183 : /* Get the source file information for all CUs. */
7184 : Dwarf_Off offset;
7185 0 : Dwarf_Off ncu = 0;
7186 : size_t hsize;
7187 0 : struct mac_culist *culist = NULL;
7188 0 : size_t nculist = 0;
7189 0 : while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
7190 : {
7191 : Dwarf_Die cudie;
7192 0 : if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
7193 0 : continue;
7194 :
7195 : Dwarf_Attribute attr;
7196 0 : if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
7197 0 : continue;
7198 :
7199 : Dwarf_Word macoff;
7200 0 : if (dwarf_formudata (&attr, &macoff) != 0)
7201 0 : continue;
7202 :
7203 0 : struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
7204 0 : newp->die = cudie;
7205 0 : newp->offset = macoff;
7206 0 : newp->files = NULL;
7207 0 : newp->next = culist;
7208 0 : culist = newp;
7209 0 : ++nculist;
7210 : }
7211 :
7212 : /* Convert the list into an array for easier consumption. */
7213 0 : struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
7214 : * sizeof (*cus));
7215 : /* Add sentinel. */
7216 0 : cus[nculist].offset = data->d_size;
7217 0 : cus[nculist].files = (Dwarf_Files *) -1l;
7218 0 : if (nculist > 0)
7219 : {
7220 0 : for (size_t cnt = nculist - 1; culist != NULL; --cnt)
7221 : {
7222 0 : assert (cnt < nculist);
7223 0 : cus[cnt] = *culist;
7224 0 : culist = culist->next;
7225 : }
7226 :
7227 : /* Sort the array according to the offset in the .debug_macinfo
7228 : section. Note we keep the sentinel at the end. */
7229 0 : qsort (cus, nculist, sizeof (*cus), mac_compare);
7230 : }
7231 :
7232 0 : const unsigned char *readp = (const unsigned char *) data->d_buf;
7233 0 : const unsigned char *readendp = readp + data->d_size;
7234 0 : int level = 1;
7235 :
7236 0 : while (readp < readendp)
7237 : {
7238 0 : unsigned int opcode = *readp++;
7239 : unsigned int u128;
7240 : unsigned int u128_2;
7241 : const unsigned char *endp;
7242 :
7243 0 : switch (opcode)
7244 : {
7245 0 : case DW_MACINFO_define:
7246 : case DW_MACINFO_undef:
7247 : case DW_MACINFO_vendor_ext:
7248 : /* For the first two opcodes the parameters are
7249 : line, string
7250 : For the latter
7251 : number, string.
7252 : We can treat these cases together. */
7253 0 : get_uleb128 (u128, readp, readendp);
7254 :
7255 0 : endp = memchr (readp, '\0', readendp - readp);
7256 0 : if (unlikely (endp == NULL))
7257 : {
7258 0 : printf (gettext ("\
7259 : %*s*** non-terminated string at end of section"),
7260 : level, "");
7261 : return;
7262 : }
7263 :
7264 0 : if (opcode == DW_MACINFO_define)
7265 0 : printf ("%*s#define %s, line %u\n",
7266 : level, "", (char *) readp, u128);
7267 0 : else if (opcode == DW_MACINFO_undef)
7268 0 : printf ("%*s#undef %s, line %u\n",
7269 : level, "", (char *) readp, u128);
7270 : else
7271 0 : printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
7272 :
7273 0 : readp = endp + 1;
7274 0 : break;
7275 :
7276 0 : case DW_MACINFO_start_file:
7277 : /* The two parameters are line and file index, in this order. */
7278 0 : get_uleb128 (u128, readp, readendp);
7279 0 : if (readendp - readp < 1)
7280 : {
7281 0 : printf (gettext ("\
7282 : %*s*** missing DW_MACINFO_start_file argument at end of section"),
7283 : level, "");
7284 : return;
7285 : }
7286 0 : get_uleb128 (u128_2, readp, readendp);
7287 :
7288 : /* Find the CU DIE for this file. */
7289 0 : size_t macoff = readp - (const unsigned char *) data->d_buf;
7290 0 : const char *fname = "???";
7291 0 : if (macoff >= cus[0].offset)
7292 : {
7293 0 : while (macoff >= cus[1].offset && cus[1].offset != data->d_size)
7294 0 : ++cus;
7295 :
7296 0 : if (cus[0].files == NULL
7297 0 : && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
7298 0 : cus[0].files = (Dwarf_Files *) -1l;
7299 :
7300 0 : if (cus[0].files != (Dwarf_Files *) -1l)
7301 0 : fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
7302 0 : ?: "???");
7303 : }
7304 :
7305 0 : printf ("%*sstart_file %u, [%u] %s\n",
7306 : level, "", u128, u128_2, fname);
7307 0 : ++level;
7308 0 : break;
7309 :
7310 0 : case DW_MACINFO_end_file:
7311 0 : --level;
7312 : printf ("%*send_file\n", level, "");
7313 : /* Nothing more to do. */
7314 : break;
7315 :
7316 0 : default:
7317 : // XXX gcc seems to generate files with a trailing zero.
7318 0 : if (unlikely (opcode != 0 || readp != readendp))
7319 : printf ("%*s*** invalid opcode %u\n", level, "", opcode);
7320 : break;
7321 : }
7322 : }
7323 : }
7324 :
7325 :
7326 : static void
7327 3 : print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
7328 : Ebl *ebl, GElf_Ehdr *ehdr,
7329 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7330 : {
7331 9 : printf (gettext ("\
7332 : \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
7333 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7334 3 : (uint64_t) shdr->sh_offset);
7335 6 : putc_unlocked ('\n', stdout);
7336 :
7337 3 : Elf_Data *data = dbg->sectiondata[IDX_debug_macro];
7338 3 : if (unlikely (data == NULL || data->d_buf == NULL))
7339 : {
7340 0 : error (0, 0, gettext ("cannot get macro information section data: %s"),
7341 : elf_errmsg (-1));
7342 0 : return;
7343 : }
7344 :
7345 : /* Get the source file information for all CUs. Uses same
7346 : datastructure as macinfo. But uses offset field to directly
7347 : match .debug_line offset. And just stored in a list. */
7348 : Dwarf_Off offset;
7349 3 : Dwarf_Off ncu = 0;
7350 : size_t hsize;
7351 3 : struct mac_culist *culist = NULL;
7352 3 : size_t nculist = 0;
7353 10 : while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
7354 : {
7355 : Dwarf_Die cudie;
7356 4 : if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
7357 0 : continue;
7358 :
7359 : Dwarf_Attribute attr;
7360 4 : if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL)
7361 0 : continue;
7362 :
7363 : Dwarf_Word lineoff;
7364 4 : if (dwarf_formudata (&attr, &lineoff) != 0)
7365 0 : continue;
7366 :
7367 4 : struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
7368 4 : newp->die = cudie;
7369 4 : newp->offset = lineoff;
7370 4 : newp->files = NULL;
7371 4 : newp->next = culist;
7372 4 : culist = newp;
7373 4 : ++nculist;
7374 : }
7375 :
7376 3 : const unsigned char *readp = (const unsigned char *) data->d_buf;
7377 3 : const unsigned char *readendp = readp + data->d_size;
7378 :
7379 14 : while (readp < readendp)
7380 : {
7381 16 : printf (gettext (" Offset: 0x%" PRIx64 "\n"),
7382 8 : (uint64_t) (readp - (const unsigned char *) data->d_buf));
7383 :
7384 : // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
7385 : // optional vendor extension macro entry table.
7386 8 : if (readp + 2 > readendp)
7387 : {
7388 0 : invalid_data:
7389 0 : error (0, 0, gettext ("invalid data"));
7390 0 : return;
7391 : }
7392 8 : const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
7393 16 : printf (gettext (" Version: %" PRIu16 "\n"), vers);
7394 :
7395 : // Version 4 is the GNU extension for DWARF4. DWARF5 will use version
7396 : // 5 when it gets standardized.
7397 8 : if (vers != 4 && vers != 5)
7398 : {
7399 0 : printf (gettext (" unknown version, cannot parse section\n"));
7400 : return;
7401 : }
7402 :
7403 8 : if (readp + 1 > readendp)
7404 : goto invalid_data;
7405 8 : const unsigned char flag = *readp++;
7406 16 : printf (gettext (" Flag: 0x%" PRIx8 "\n"), flag);
7407 :
7408 8 : unsigned int offset_len = (flag & 0x01) ? 8 : 4;
7409 16 : printf (gettext (" Offset length: %" PRIu8 "\n"), offset_len);
7410 8 : Dwarf_Off line_offset = -1;
7411 8 : if (flag & 0x02)
7412 : {
7413 4 : if (offset_len == 8)
7414 0 : line_offset = read_8ubyte_unaligned_inc (dbg, readp);
7415 : else
7416 4 : line_offset = read_4ubyte_unaligned_inc (dbg, readp);
7417 4 : printf (gettext (" .debug_line offset: 0x%" PRIx64 "\n"),
7418 : line_offset);
7419 : }
7420 :
7421 : const unsigned char *vendor[DW_MACRO_hi_user - DW_MACRO_lo_user];
7422 8 : memset (vendor, 0, sizeof vendor);
7423 8 : if (flag & 0x04)
7424 : {
7425 : // 1 byte length, for each item, 1 byte opcode, uleb128 number
7426 : // of arguments, for each argument 1 byte form code.
7427 0 : if (readp + 1 > readendp)
7428 : goto invalid_data;
7429 0 : unsigned int tlen = *readp++;
7430 0 : printf (gettext (" extension opcode table, %" PRIu8 " items:\n"),
7431 : tlen);
7432 0 : for (unsigned int i = 0; i < tlen; i++)
7433 : {
7434 0 : if (readp + 1 > readendp)
7435 : goto invalid_data;
7436 0 : unsigned int opcode = *readp++;
7437 0 : printf (gettext (" [%" PRIx8 "]"), opcode);
7438 0 : if (opcode < DW_MACRO_lo_user
7439 0 : || opcode > DW_MACRO_hi_user)
7440 : goto invalid_data;
7441 : // Record the start of description for this vendor opcode.
7442 : // uleb128 nr args, 1 byte per arg form.
7443 0 : vendor[opcode - DW_MACRO_lo_user] = readp;
7444 0 : if (readp + 1 > readendp)
7445 : goto invalid_data;
7446 0 : unsigned int args = *readp++;
7447 0 : if (args > 0)
7448 : {
7449 0 : printf (gettext (" %" PRIu8 " arguments:"), args);
7450 0 : while (args > 0)
7451 : {
7452 0 : if (readp + 1 > readendp)
7453 : goto invalid_data;
7454 0 : unsigned int form = *readp++;
7455 0 : printf (" %s", dwarf_form_string (form));
7456 0 : if (form != DW_FORM_data1
7457 0 : && form != DW_FORM_data2
7458 : && form != DW_FORM_data4
7459 0 : && form != DW_FORM_data8
7460 0 : && form != DW_FORM_sdata
7461 0 : && form != DW_FORM_udata
7462 : && form != DW_FORM_block
7463 0 : && form != DW_FORM_block1
7464 : && form != DW_FORM_block2
7465 0 : && form != DW_FORM_block4
7466 0 : && form != DW_FORM_flag
7467 0 : && form != DW_FORM_string
7468 0 : && form != DW_FORM_strp
7469 0 : && form != DW_FORM_sec_offset)
7470 : goto invalid_data;
7471 0 : args--;
7472 0 : if (args > 0)
7473 : putchar_unlocked (',');
7474 : }
7475 : }
7476 : else
7477 0 : printf (gettext (" no arguments."));
7478 0 : putchar_unlocked ('\n');
7479 : }
7480 : }
7481 8 : putchar_unlocked ('\n');
7482 :
7483 8 : int level = 1;
7484 8 : if (readp + 1 > readendp)
7485 : goto invalid_data;
7486 8 : unsigned int opcode = *readp++;
7487 743 : while (opcode != 0)
7488 : {
7489 : unsigned int u128;
7490 : unsigned int u128_2;
7491 : const unsigned char *endp;
7492 : uint64_t off;
7493 :
7494 727 : switch (opcode)
7495 : {
7496 6 : case DW_MACRO_start_file:
7497 6 : get_uleb128 (u128, readp, readendp);
7498 6 : if (readp >= readendp)
7499 : goto invalid_data;
7500 6 : get_uleb128 (u128_2, readp, readendp);
7501 :
7502 : /* Find the CU DIE that matches this line offset. */
7503 6 : const char *fname = "???";
7504 6 : if (line_offset != (Dwarf_Off) -1)
7505 : {
7506 : struct mac_culist *cu = culist;
7507 8 : while (cu != NULL && line_offset != cu->offset)
7508 2 : cu = cu->next;
7509 6 : if (cu != NULL)
7510 : {
7511 6 : if (cu->files == NULL
7512 4 : && dwarf_getsrcfiles (&cu->die, &cu->files,
7513 : NULL) != 0)
7514 0 : cu->files = (Dwarf_Files *) -1l;
7515 :
7516 6 : if (cu->files != (Dwarf_Files *) -1l)
7517 6 : fname = (dwarf_filesrc (cu->files, u128_2,
7518 6 : NULL, NULL) ?: "???");
7519 : }
7520 : }
7521 6 : printf ("%*sstart_file %u, [%u] %s\n",
7522 : level, "", u128, u128_2, fname);
7523 6 : ++level;
7524 6 : break;
7525 :
7526 6 : case DW_MACRO_end_file:
7527 6 : --level;
7528 : printf ("%*send_file\n", level, "");
7529 : break;
7530 :
7531 1 : case DW_MACRO_define:
7532 1 : get_uleb128 (u128, readp, readendp);
7533 1 : endp = memchr (readp, '\0', readendp - readp);
7534 1 : if (endp == NULL)
7535 : goto invalid_data;
7536 2 : printf ("%*s#define %s, line %u\n",
7537 : level, "", readp, u128);
7538 1 : readp = endp + 1;
7539 1 : break;
7540 :
7541 0 : case DW_MACRO_undef:
7542 0 : get_uleb128 (u128, readp, readendp);
7543 0 : endp = memchr (readp, '\0', readendp - readp);
7544 0 : if (endp == NULL)
7545 : goto invalid_data;
7546 0 : printf ("%*s#undef %s, line %u\n",
7547 : level, "", readp, u128);
7548 0 : readp = endp + 1;
7549 0 : break;
7550 :
7551 707 : case DW_MACRO_define_strp:
7552 707 : get_uleb128 (u128, readp, readendp);
7553 707 : if (readp + offset_len > readendp)
7554 : goto invalid_data;
7555 707 : if (offset_len == 8)
7556 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
7557 : else
7558 707 : off = read_4ubyte_unaligned_inc (dbg, readp);
7559 707 : printf ("%*s#define %s, line %u (indirect)\n",
7560 : level, "", dwarf_getstring (dbg, off, NULL), u128);
7561 : break;
7562 :
7563 1 : case DW_MACRO_undef_strp:
7564 1 : get_uleb128 (u128, readp, readendp);
7565 1 : if (readp + offset_len > readendp)
7566 : goto invalid_data;
7567 1 : if (offset_len == 8)
7568 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
7569 : else
7570 1 : off = read_4ubyte_unaligned_inc (dbg, readp);
7571 1 : printf ("%*s#undef %s, line %u (indirect)\n",
7572 : level, "", dwarf_getstring (dbg, off, NULL), u128);
7573 : break;
7574 :
7575 6 : case DW_MACRO_import:
7576 6 : if (readp + offset_len > readendp)
7577 : goto invalid_data;
7578 6 : if (offset_len == 8)
7579 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
7580 : else
7581 6 : off = read_4ubyte_unaligned_inc (dbg, readp);
7582 : printf ("%*s#include offset 0x%" PRIx64 "\n",
7583 : level, "", off);
7584 : break;
7585 :
7586 0 : case DW_MACRO_define_sup:
7587 0 : get_uleb128 (u128, readp, readendp);
7588 0 : if (readp + offset_len > readendp)
7589 : goto invalid_data;
7590 0 : if (offset_len == 8)
7591 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
7592 : else
7593 0 : off = read_4ubyte_unaligned_inc (dbg, readp);
7594 : // Needs support for reading from supplementary object file.
7595 : printf ("%*s#define <str-at-0x%" PRIx64 ">, line %u (sup)\n",
7596 : level, "", off, u128);
7597 : break;
7598 :
7599 0 : case DW_MACRO_undef_sup:
7600 0 : get_uleb128 (u128, readp, readendp);
7601 0 : if (readp + offset_len > readendp)
7602 : goto invalid_data;
7603 0 : if (offset_len == 8)
7604 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
7605 : else
7606 0 : off = read_4ubyte_unaligned_inc (dbg, readp);
7607 : // Needs support for reading from supplementary object file.
7608 : printf ("%*s#undef <str-at-0x%" PRIx64 ">, line %u (sup)\n",
7609 : level, "", off, u128);
7610 : break;
7611 :
7612 0 : case DW_MACRO_import_sup:
7613 0 : if (readp + offset_len > readendp)
7614 : goto invalid_data;
7615 0 : if (offset_len == 8)
7616 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
7617 : else
7618 0 : off = read_4ubyte_unaligned_inc (dbg, readp);
7619 : printf ("%*s#include offset 0x%" PRIx64 " (sup)\n",
7620 : level, "", off);
7621 : break;
7622 :
7623 0 : case DW_MACRO_define_strx:
7624 0 : get_uleb128 (u128, readp, readendp);
7625 0 : if (readp + offset_len > readendp)
7626 : goto invalid_data;
7627 0 : if (offset_len == 8)
7628 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
7629 : else
7630 0 : off = read_4ubyte_unaligned_inc (dbg, readp);
7631 : // Needs support for reading indirect string offset table
7632 : printf ("%*s#define <str-at-0x%" PRIx64 ">, line %u (strx)\n",
7633 : level, "", off, u128);
7634 : break;
7635 :
7636 0 : case DW_MACRO_undef_strx:
7637 0 : get_uleb128 (u128, readp, readendp);
7638 0 : if (readp + offset_len > readendp)
7639 : goto invalid_data;
7640 0 : if (offset_len == 8)
7641 0 : off = read_8ubyte_unaligned_inc (dbg, readp);
7642 : else
7643 0 : off = read_4ubyte_unaligned_inc (dbg, readp);
7644 : // Needs support for reading indirect string offset table.
7645 : printf ("%*s#undef <str-at-0x%" PRIx64 ">, line %u (strx)\n",
7646 : level, "", off, u128);
7647 : break;
7648 :
7649 0 : default:
7650 0 : printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
7651 0 : if (opcode < DW_MACRO_lo_user
7652 : || opcode > DW_MACRO_lo_user
7653 0 : || vendor[opcode - DW_MACRO_lo_user] == NULL)
7654 : goto invalid_data;
7655 :
7656 : const unsigned char *op_desc;
7657 0 : op_desc = vendor[opcode - DW_MACRO_lo_user];
7658 :
7659 : // Just skip the arguments, we cannot really interpret them,
7660 : // but print as much as we can.
7661 0 : unsigned int args = *op_desc++;
7662 0 : while (args > 0)
7663 0 : {
7664 0 : unsigned int form = *op_desc++;
7665 : Dwarf_Word val;
7666 0 : switch (form)
7667 : {
7668 0 : case DW_FORM_data1:
7669 0 : if (readp + 1 > readendp)
7670 : goto invalid_data;
7671 0 : val = *readp++;
7672 0 : printf (" %" PRIx8, (unsigned int) val);
7673 : break;
7674 :
7675 0 : case DW_FORM_data2:
7676 0 : if (readp + 2 > readendp)
7677 : goto invalid_data;
7678 0 : val = read_2ubyte_unaligned_inc (dbg, readp);
7679 0 : printf(" %" PRIx16, (unsigned int) val);
7680 : break;
7681 :
7682 0 : case DW_FORM_data4:
7683 0 : if (readp + 4 > readendp)
7684 : goto invalid_data;
7685 0 : val = read_4ubyte_unaligned_inc (dbg, readp);
7686 0 : printf (" %" PRIx32, (unsigned int) val);
7687 : break;
7688 :
7689 0 : case DW_FORM_data8:
7690 0 : if (readp + 8 > readendp)
7691 : goto invalid_data;
7692 0 : val = read_8ubyte_unaligned_inc (dbg, readp);
7693 : printf (" %" PRIx64, val);
7694 : break;
7695 :
7696 0 : case DW_FORM_sdata:
7697 0 : get_sleb128 (val, readp, readendp);
7698 : printf (" %" PRIx64, val);
7699 : break;
7700 :
7701 0 : case DW_FORM_udata:
7702 0 : get_uleb128 (val, readp, readendp);
7703 : printf (" %" PRIx64, val);
7704 : break;
7705 :
7706 0 : case DW_FORM_block:
7707 0 : get_uleb128 (val, readp, readendp);
7708 0 : printf (" block[%" PRIu64 "]", val);
7709 0 : if (readp + val > readendp)
7710 : goto invalid_data;
7711 0 : readp += val;
7712 0 : break;
7713 :
7714 0 : case DW_FORM_block1:
7715 0 : if (readp + 1 > readendp)
7716 : goto invalid_data;
7717 0 : val = *readp++;
7718 0 : printf (" block[%" PRIu64 "]", val);
7719 0 : if (readp + val > readendp)
7720 : goto invalid_data;
7721 : break;
7722 :
7723 0 : case DW_FORM_block2:
7724 0 : if (readp + 2 > readendp)
7725 : goto invalid_data;
7726 0 : val = read_2ubyte_unaligned_inc (dbg, readp);
7727 0 : printf (" block[%" PRIu64 "]", val);
7728 0 : if (readp + val > readendp)
7729 : goto invalid_data;
7730 : break;
7731 :
7732 0 : case DW_FORM_block4:
7733 0 : if (readp + 2 > readendp)
7734 : goto invalid_data;
7735 0 : val =read_4ubyte_unaligned_inc (dbg, readp);
7736 0 : printf (" block[%" PRIu64 "]", val);
7737 0 : if (readp + val > readendp)
7738 : goto invalid_data;
7739 : break;
7740 :
7741 0 : case DW_FORM_flag:
7742 0 : if (readp + 1 > readendp)
7743 : goto invalid_data;
7744 0 : val = *readp++;
7745 0 : printf (" %s", val != 0 ? gettext ("yes") : gettext ("no"));
7746 : break;
7747 :
7748 0 : case DW_FORM_string:
7749 0 : endp = memchr (readp, '\0', readendp - readp);
7750 0 : if (endp == NULL)
7751 : goto invalid_data;
7752 0 : printf (" %s", readp);
7753 0 : readp = endp + 1;
7754 0 : break;
7755 :
7756 0 : case DW_FORM_strp:
7757 0 : if (readp + offset_len > readendp)
7758 : goto invalid_data;
7759 0 : if (offset_len == 8)
7760 0 : val = read_8ubyte_unaligned_inc (dbg, readp);
7761 : else
7762 0 : val = read_4ubyte_unaligned_inc (dbg, readp);
7763 0 : printf (" %s", dwarf_getstring (dbg, val, NULL));
7764 : break;
7765 :
7766 0 : case DW_FORM_sec_offset:
7767 0 : if (readp + offset_len > readendp)
7768 : goto invalid_data;
7769 0 : if (offset_len == 8)
7770 0 : val = read_8ubyte_unaligned_inc (dbg, readp);
7771 : else
7772 0 : val = read_4ubyte_unaligned_inc (dbg, readp);
7773 : printf (" %" PRIx64, val);
7774 : break;
7775 :
7776 0 : default:
7777 0 : error (0, 0, gettext ("vendor opcode not verified?"));
7778 : return;
7779 : }
7780 :
7781 0 : args--;
7782 0 : if (args > 0)
7783 : putchar_unlocked (',');
7784 : }
7785 : putchar_unlocked ('\n');
7786 : }
7787 :
7788 727 : if (readp + 1 > readendp)
7789 : goto invalid_data;
7790 727 : opcode = *readp++;
7791 727 : if (opcode == 0)
7792 : putchar_unlocked ('\n');
7793 : }
7794 : }
7795 : }
7796 :
7797 :
7798 : /* Callback for printing global names. */
7799 : static int
7800 34 : print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
7801 : void *arg)
7802 : {
7803 34 : int *np = (int *) arg;
7804 :
7805 102 : printf (gettext (" [%5d] DIE offset: %6" PRId64
7806 : ", CU DIE offset: %6" PRId64 ", name: %s\n"),
7807 34 : (*np)++, global->die_offset, global->cu_offset, global->name);
7808 :
7809 34 : return 0;
7810 : }
7811 :
7812 :
7813 : /* Print the known exported symbols in the DWARF section '.debug_pubnames'. */
7814 : static void
7815 8 : print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
7816 : Ebl *ebl, GElf_Ehdr *ehdr,
7817 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7818 : {
7819 24 : printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
7820 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7821 8 : (uint64_t) shdr->sh_offset);
7822 :
7823 8 : int n = 0;
7824 8 : (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
7825 8 : }
7826 :
7827 : /* Print the content of the DWARF string section '.debug_str'. */
7828 : static void
7829 34 : print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
7830 : Ebl *ebl, GElf_Ehdr *ehdr,
7831 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7832 : {
7833 68 : const size_t sh_size = (dbg->sectiondata[IDX_debug_str] ?
7834 34 : dbg->sectiondata[IDX_debug_str]->d_size : 0);
7835 :
7836 : /* Compute floor(log16(shdr->sh_size)). */
7837 34 : GElf_Addr tmp = sh_size;
7838 34 : int digits = 1;
7839 165 : while (tmp >= 16)
7840 : {
7841 97 : ++digits;
7842 97 : tmp >>= 4;
7843 : }
7844 34 : digits = MAX (4, digits);
7845 :
7846 136 : printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
7847 : " %*s String\n"),
7848 : elf_ndxscn (scn),
7849 34 : section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset,
7850 : /* TRANS: the debugstr| prefix makes the string unique. */
7851 34 : digits + 2, sgettext ("debugstr|Offset"));
7852 :
7853 34 : Dwarf_Off offset = 0;
7854 60740 : while (offset < sh_size)
7855 : {
7856 : size_t len;
7857 60672 : const char *str = dwarf_getstring (dbg, offset, &len);
7858 60672 : if (unlikely (str == NULL))
7859 : {
7860 0 : printf (gettext (" *** error while reading strings: %s\n"),
7861 : dwarf_errmsg (-1));
7862 0 : break;
7863 : }
7864 :
7865 60672 : printf (" [%*" PRIx64 "] \"%s\"\n", digits, (uint64_t) offset, str);
7866 :
7867 60672 : offset += len + 1;
7868 : }
7869 34 : }
7870 :
7871 :
7872 : /* Print the content of the call frame search table section
7873 : '.eh_frame_hdr'. */
7874 : static void
7875 16 : print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
7876 : Ebl *ebl __attribute__ ((unused)),
7877 : GElf_Ehdr *ehdr __attribute__ ((unused)),
7878 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7879 : {
7880 32 : printf (gettext ("\
7881 : \nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
7882 : elf_ndxscn (scn));
7883 :
7884 16 : Elf_Data *data = elf_rawdata (scn, NULL);
7885 :
7886 16 : if (unlikely (data == NULL))
7887 : {
7888 0 : error (0, 0, gettext ("cannot get %s content: %s"),
7889 : ".eh_frame_hdr", elf_errmsg (-1));
7890 0 : return;
7891 : }
7892 :
7893 16 : const unsigned char *readp = data->d_buf;
7894 16 : const unsigned char *const dataend = ((unsigned char *) data->d_buf
7895 16 : + data->d_size);
7896 :
7897 16 : if (unlikely (readp + 4 > dataend))
7898 : {
7899 0 : invalid_data:
7900 0 : error (0, 0, gettext ("invalid data"));
7901 : return;
7902 : }
7903 :
7904 16 : unsigned int version = *readp++;
7905 16 : unsigned int eh_frame_ptr_enc = *readp++;
7906 16 : unsigned int fde_count_enc = *readp++;
7907 16 : unsigned int table_enc = *readp++;
7908 :
7909 16 : printf (" version: %u\n"
7910 : " eh_frame_ptr_enc: %#x ",
7911 : version, eh_frame_ptr_enc);
7912 16 : print_encoding_base ("", eh_frame_ptr_enc);
7913 16 : printf (" fde_count_enc: %#x ", fde_count_enc);
7914 16 : print_encoding_base ("", fde_count_enc);
7915 16 : printf (" table_enc: %#x ", table_enc);
7916 16 : print_encoding_base ("", table_enc);
7917 :
7918 16 : uint64_t eh_frame_ptr = 0;
7919 16 : if (eh_frame_ptr_enc != DW_EH_PE_omit)
7920 : {
7921 16 : readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
7922 : dbg);
7923 16 : if (unlikely (readp == NULL))
7924 : goto invalid_data;
7925 :
7926 32 : printf (" eh_frame_ptr: %#" PRIx64, eh_frame_ptr);
7927 16 : if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
7928 16 : printf (" (offset: %#" PRIx64 ")",
7929 : /* +4 because of the 4 byte header of the section. */
7930 16 : (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
7931 :
7932 : putchar_unlocked ('\n');
7933 : }
7934 :
7935 16 : uint64_t fde_count = 0;
7936 16 : if (fde_count_enc != DW_EH_PE_omit)
7937 : {
7938 16 : readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
7939 16 : if (unlikely (readp == NULL))
7940 : goto invalid_data;
7941 :
7942 16 : printf (" fde_count: %" PRIu64 "\n", fde_count);
7943 : }
7944 :
7945 16 : if (fde_count == 0 || table_enc == DW_EH_PE_omit)
7946 : return;
7947 :
7948 16 : puts (" Table:");
7949 :
7950 : /* Optimize for the most common case. */
7951 16 : if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
7952 5392 : while (fde_count > 0 && readp + 8 <= dataend)
7953 : {
7954 5376 : int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
7955 10752 : uint64_t initial_offset = ((uint64_t) shdr->sh_offset
7956 5376 : + (int64_t) initial_location);
7957 5376 : int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
7958 : // XXX Possibly print symbol name or section offset for initial_offset
7959 5376 : printf (" %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
7960 : " fde=[%6" PRIx64 "]\n",
7961 : initial_location, initial_offset,
7962 5376 : address, address - (eh_frame_ptr + 4));
7963 : }
7964 : else
7965 : while (0 && readp < dataend)
7966 : {
7967 :
7968 : }
7969 : }
7970 :
7971 :
7972 : /* Print the content of the exception handling table section
7973 : '.eh_frame_hdr'. */
7974 : static void
7975 0 : print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
7976 : Ebl *ebl __attribute__ ((unused)),
7977 : GElf_Ehdr *ehdr __attribute__ ((unused)),
7978 : Elf_Scn *scn,
7979 : GElf_Shdr *shdr __attribute__ ((unused)),
7980 : Dwarf *dbg __attribute__ ((unused)))
7981 : {
7982 0 : printf (gettext ("\
7983 : \nException handling table section [%2zu] '.gcc_except_table':\n"),
7984 : elf_ndxscn (scn));
7985 :
7986 0 : Elf_Data *data = elf_rawdata (scn, NULL);
7987 :
7988 0 : if (unlikely (data == NULL))
7989 : {
7990 0 : error (0, 0, gettext ("cannot get %s content: %s"),
7991 : ".gcc_except_table", elf_errmsg (-1));
7992 0 : return;
7993 : }
7994 :
7995 0 : const unsigned char *readp = data->d_buf;
7996 0 : const unsigned char *const dataend = readp + data->d_size;
7997 :
7998 0 : if (unlikely (readp + 1 > dataend))
7999 : {
8000 0 : invalid_data:
8001 0 : error (0, 0, gettext ("invalid data"));
8002 : return;
8003 : }
8004 0 : unsigned int lpstart_encoding = *readp++;
8005 0 : printf (gettext (" LPStart encoding: %#x "), lpstart_encoding);
8006 0 : print_encoding_base ("", lpstart_encoding);
8007 0 : if (lpstart_encoding != DW_EH_PE_omit)
8008 : {
8009 : uint64_t lpstart;
8010 0 : readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
8011 0 : printf (" LPStart: %#" PRIx64 "\n", lpstart);
8012 : }
8013 :
8014 0 : if (unlikely (readp + 1 > dataend))
8015 : goto invalid_data;
8016 0 : unsigned int ttype_encoding = *readp++;
8017 0 : printf (gettext (" TType encoding: %#x "), ttype_encoding);
8018 0 : print_encoding_base ("", ttype_encoding);
8019 0 : const unsigned char *ttype_base = NULL;
8020 0 : if (ttype_encoding != DW_EH_PE_omit)
8021 : {
8022 : unsigned int ttype_base_offset;
8023 0 : get_uleb128 (ttype_base_offset, readp, dataend);
8024 0 : printf (" TType base offset: %#x\n", ttype_base_offset);
8025 0 : if ((size_t) (dataend - readp) > ttype_base_offset)
8026 0 : ttype_base = readp + ttype_base_offset;
8027 : }
8028 :
8029 0 : if (unlikely (readp + 1 > dataend))
8030 : goto invalid_data;
8031 0 : unsigned int call_site_encoding = *readp++;
8032 0 : printf (gettext (" Call site encoding: %#x "), call_site_encoding);
8033 0 : print_encoding_base ("", call_site_encoding);
8034 : unsigned int call_site_table_len;
8035 0 : get_uleb128 (call_site_table_len, readp, dataend);
8036 :
8037 0 : const unsigned char *const action_table = readp + call_site_table_len;
8038 0 : if (unlikely (action_table > dataend))
8039 : goto invalid_data;
8040 : unsigned int u = 0;
8041 : unsigned int max_action = 0;
8042 0 : while (readp < action_table)
8043 : {
8044 0 : if (u == 0)
8045 0 : puts (gettext ("\n Call site table:"));
8046 :
8047 : uint64_t call_site_start;
8048 0 : readp = read_encoded (call_site_encoding, readp, dataend,
8049 : &call_site_start, dbg);
8050 : uint64_t call_site_length;
8051 0 : readp = read_encoded (call_site_encoding, readp, dataend,
8052 : &call_site_length, dbg);
8053 : uint64_t landing_pad;
8054 0 : readp = read_encoded (call_site_encoding, readp, dataend,
8055 : &landing_pad, dbg);
8056 : unsigned int action;
8057 0 : get_uleb128 (action, readp, dataend);
8058 0 : max_action = MAX (action, max_action);
8059 0 : printf (gettext (" [%4u] Call site start: %#" PRIx64 "\n"
8060 : " Call site length: %" PRIu64 "\n"
8061 : " Landing pad: %#" PRIx64 "\n"
8062 : " Action: %u\n"),
8063 : u++, call_site_start, call_site_length, landing_pad, action);
8064 : }
8065 0 : if (readp != action_table)
8066 : goto invalid_data;
8067 :
8068 0 : unsigned int max_ar_filter = 0;
8069 0 : if (max_action > 0)
8070 : {
8071 0 : puts ("\n Action table:");
8072 :
8073 0 : size_t maxdata = (size_t) (dataend - action_table);
8074 0 : if (max_action > maxdata || maxdata - max_action < 1)
8075 : {
8076 0 : invalid_action_table:
8077 0 : fputs (gettext (" <INVALID DATA>\n"), stdout);
8078 0 : return;
8079 : }
8080 :
8081 0 : const unsigned char *const action_table_end
8082 0 : = action_table + max_action + 1;
8083 :
8084 0 : u = 0;
8085 : do
8086 : {
8087 : int ar_filter;
8088 0 : get_sleb128 (ar_filter, readp, action_table_end);
8089 0 : if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
8090 0 : max_ar_filter = ar_filter;
8091 : int ar_disp;
8092 0 : if (readp >= action_table_end)
8093 : goto invalid_action_table;
8094 0 : get_sleb128 (ar_disp, readp, action_table_end);
8095 :
8096 0 : printf (" [%4u] ar_filter: % d\n"
8097 : " ar_disp: % -5d",
8098 : u, ar_filter, ar_disp);
8099 0 : if (abs (ar_disp) & 1)
8100 0 : printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
8101 0 : else if (ar_disp != 0)
8102 0 : puts (" -> ???");
8103 : else
8104 : putchar_unlocked ('\n');
8105 0 : ++u;
8106 : }
8107 0 : while (readp < action_table_end);
8108 : }
8109 :
8110 0 : if (max_ar_filter > 0 && ttype_base != NULL)
8111 : {
8112 : unsigned char dsize;
8113 0 : puts ("\n TType table:");
8114 :
8115 : // XXX Not *4, size of encoding;
8116 : switch (ttype_encoding & 7)
8117 : {
8118 : case DW_EH_PE_udata2:
8119 : case DW_EH_PE_sdata2:
8120 : dsize = 2;
8121 : break;
8122 : case DW_EH_PE_udata4:
8123 : case DW_EH_PE_sdata4:
8124 : dsize = 4;
8125 : break;
8126 : case DW_EH_PE_udata8:
8127 : case DW_EH_PE_sdata8:
8128 : dsize = 8;
8129 : break;
8130 0 : default:
8131 0 : dsize = 0;
8132 0 : error (1, 0, gettext ("invalid TType encoding"));
8133 : }
8134 :
8135 0 : if (max_ar_filter
8136 0 : > (size_t) (ttype_base - (const unsigned char *) data->d_buf) / dsize)
8137 : goto invalid_data;
8138 :
8139 0 : readp = ttype_base - max_ar_filter * dsize;
8140 : do
8141 : {
8142 : uint64_t ttype;
8143 0 : readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
8144 : dbg);
8145 0 : printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
8146 : }
8147 0 : while (readp < ttype_base);
8148 : }
8149 : }
8150 :
8151 : /* Print the content of the '.gdb_index' section.
8152 : http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
8153 : */
8154 : static void
8155 2 : print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
8156 : Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
8157 : {
8158 6 : printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
8159 : " contains %" PRId64 " bytes :\n"),
8160 : elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
8161 2 : (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
8162 :
8163 2 : Elf_Data *data = elf_rawdata (scn, NULL);
8164 :
8165 2 : if (unlikely (data == NULL))
8166 : {
8167 0 : error (0, 0, gettext ("cannot get %s content: %s"),
8168 : ".gdb_index", elf_errmsg (-1));
8169 0 : return;
8170 : }
8171 :
8172 : // .gdb_index is always in little endian.
8173 2 : Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
8174 2 : dbg = &dummy_dbg;
8175 :
8176 2 : const unsigned char *readp = data->d_buf;
8177 2 : const unsigned char *const dataend = readp + data->d_size;
8178 :
8179 2 : if (unlikely (readp + 4 > dataend))
8180 : {
8181 0 : invalid_data:
8182 0 : error (0, 0, gettext ("invalid data"));
8183 : return;
8184 : }
8185 :
8186 2 : int32_t vers = read_4ubyte_unaligned (dbg, readp);
8187 4 : printf (gettext (" Version: %" PRId32 "\n"), vers);
8188 :
8189 : // The only difference between version 4 and version 5 is the
8190 : // hash used for generating the table. Version 6 contains symbols
8191 : // for inlined functions, older versions didn't. Version 7 adds
8192 : // symbol kinds. Version 8 just indicates that it correctly includes
8193 : // TUs for symbols.
8194 2 : if (vers < 4 || vers > 8)
8195 : {
8196 0 : printf (gettext (" unknown version, cannot parse section\n"));
8197 : return;
8198 : }
8199 :
8200 2 : readp += 4;
8201 2 : if (unlikely (readp + 4 > dataend))
8202 : goto invalid_data;
8203 :
8204 2 : uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
8205 4 : printf (gettext (" CU offset: %#" PRIx32 "\n"), cu_off);
8206 :
8207 2 : readp += 4;
8208 2 : if (unlikely (readp + 4 > dataend))
8209 : goto invalid_data;
8210 :
8211 2 : uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
8212 4 : printf (gettext (" TU offset: %#" PRIx32 "\n"), tu_off);
8213 :
8214 2 : readp += 4;
8215 2 : if (unlikely (readp + 4 > dataend))
8216 : goto invalid_data;
8217 :
8218 2 : uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
8219 4 : printf (gettext (" address offset: %#" PRIx32 "\n"), addr_off);
8220 :
8221 2 : readp += 4;
8222 2 : if (unlikely (readp + 4 > dataend))
8223 : goto invalid_data;
8224 :
8225 2 : uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
8226 4 : printf (gettext (" symbol offset: %#" PRIx32 "\n"), sym_off);
8227 :
8228 2 : readp += 4;
8229 2 : if (unlikely (readp + 4 > dataend))
8230 : goto invalid_data;
8231 :
8232 2 : uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
8233 4 : printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
8234 :
8235 2 : if (unlikely ((size_t) (dataend - (const unsigned char *) data->d_buf)
8236 : < const_off))
8237 : goto invalid_data;
8238 :
8239 2 : readp = data->d_buf + cu_off;
8240 :
8241 2 : const unsigned char *nextp = data->d_buf + tu_off;
8242 2 : if (tu_off >= data->d_size)
8243 : goto invalid_data;
8244 :
8245 2 : size_t cu_nr = (nextp - readp) / 16;
8246 :
8247 4 : printf (gettext ("\n CU list at offset %#" PRIx32
8248 : " contains %zu entries:\n"),
8249 : cu_off, cu_nr);
8250 :
8251 2 : size_t n = 0;
8252 8 : while (dataend - readp >= 16 && n < cu_nr)
8253 : {
8254 4 : uint64_t off = read_8ubyte_unaligned (dbg, readp);
8255 4 : readp += 8;
8256 :
8257 4 : uint64_t len = read_8ubyte_unaligned (dbg, readp);
8258 4 : readp += 8;
8259 :
8260 4 : printf (" [%4zu] start: %0#8" PRIx64
8261 : ", length: %5" PRIu64 "\n", n, off, len);
8262 4 : n++;
8263 : }
8264 :
8265 2 : readp = data->d_buf + tu_off;
8266 2 : nextp = data->d_buf + addr_off;
8267 2 : if (addr_off >= data->d_size)
8268 : goto invalid_data;
8269 :
8270 2 : size_t tu_nr = (nextp - readp) / 24;
8271 :
8272 4 : printf (gettext ("\n TU list at offset %#" PRIx32
8273 : " contains %zu entries:\n"),
8274 : tu_off, tu_nr);
8275 :
8276 2 : n = 0;
8277 6 : while (dataend - readp >= 24 && n < tu_nr)
8278 : {
8279 2 : uint64_t off = read_8ubyte_unaligned (dbg, readp);
8280 2 : readp += 8;
8281 :
8282 2 : uint64_t type = read_8ubyte_unaligned (dbg, readp);
8283 2 : readp += 8;
8284 :
8285 2 : uint64_t sig = read_8ubyte_unaligned (dbg, readp);
8286 2 : readp += 8;
8287 :
8288 2 : printf (" [%4zu] CU offset: %5" PRId64
8289 : ", type offset: %5" PRId64
8290 : ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
8291 2 : n++;
8292 : }
8293 :
8294 2 : readp = data->d_buf + addr_off;
8295 2 : nextp = data->d_buf + sym_off;
8296 2 : if (sym_off >= data->d_size)
8297 : goto invalid_data;
8298 :
8299 2 : size_t addr_nr = (nextp - readp) / 20;
8300 :
8301 4 : printf (gettext ("\n Address list at offset %#" PRIx32
8302 : " contains %zu entries:\n"),
8303 : addr_off, addr_nr);
8304 :
8305 2 : n = 0;
8306 8 : while (dataend - readp >= 20 && n < addr_nr)
8307 : {
8308 4 : uint64_t low = read_8ubyte_unaligned (dbg, readp);
8309 4 : readp += 8;
8310 :
8311 4 : uint64_t high = read_8ubyte_unaligned (dbg, readp);
8312 4 : readp += 8;
8313 :
8314 4 : uint32_t idx = read_4ubyte_unaligned (dbg, readp);
8315 4 : readp += 4;
8316 :
8317 4 : char *l = format_dwarf_addr (dwflmod, 8, low, low);
8318 4 : char *h = format_dwarf_addr (dwflmod, 8, high - 1, high);
8319 4 : printf (" [%4zu] %s..%s, CU index: %5" PRId32 "\n",
8320 : n, l, h, idx);
8321 4 : free (l);
8322 4 : free (h);
8323 4 : n++;
8324 : }
8325 :
8326 2 : const unsigned char *const_start = data->d_buf + const_off;
8327 2 : if (const_off >= data->d_size)
8328 : goto invalid_data;
8329 :
8330 2 : readp = data->d_buf + sym_off;
8331 2 : nextp = const_start;
8332 2 : size_t sym_nr = (nextp - readp) / 8;
8333 :
8334 4 : printf (gettext ("\n Symbol table at offset %#" PRIx32
8335 : " contains %zu slots:\n"),
8336 : addr_off, sym_nr);
8337 :
8338 2 : n = 0;
8339 2052 : while (dataend - readp >= 8 && n < sym_nr)
8340 : {
8341 2048 : uint32_t name = read_4ubyte_unaligned (dbg, readp);
8342 2048 : readp += 4;
8343 :
8344 2048 : uint32_t vector = read_4ubyte_unaligned (dbg, readp);
8345 2048 : readp += 4;
8346 :
8347 2048 : if (name != 0 || vector != 0)
8348 : {
8349 14 : const unsigned char *sym = const_start + name;
8350 28 : if (unlikely ((size_t) (dataend - const_start) < name
8351 : || memchr (sym, '\0', dataend - sym) == NULL))
8352 : goto invalid_data;
8353 :
8354 14 : printf (" [%4zu] symbol: %s, CUs: ", n, sym);
8355 :
8356 14 : const unsigned char *readcus = const_start + vector;
8357 14 : if (unlikely ((size_t) (dataend - const_start) < vector))
8358 : goto invalid_data;
8359 14 : uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
8360 44 : while (cus--)
8361 : {
8362 : uint32_t cu_kind, cu, kind;
8363 : bool is_static;
8364 16 : readcus += 4;
8365 16 : if (unlikely (readcus + 4 > dataend))
8366 : goto invalid_data;
8367 16 : cu_kind = read_4ubyte_unaligned (dbg, readcus);
8368 16 : cu = cu_kind & ((1 << 24) - 1);
8369 16 : kind = (cu_kind >> 28) & 7;
8370 16 : is_static = cu_kind & (1U << 31);
8371 16 : if (cu > cu_nr - 1)
8372 2 : printf ("%" PRId32 "T", cu - (uint32_t) cu_nr);
8373 : else
8374 : printf ("%" PRId32, cu);
8375 16 : if (kind != 0)
8376 : {
8377 8 : printf (" (");
8378 8 : switch (kind)
8379 : {
8380 3 : case 1:
8381 : printf ("type");
8382 : break;
8383 2 : case 2:
8384 : printf ("var");
8385 : break;
8386 3 : case 3:
8387 : printf ("func");
8388 : break;
8389 0 : case 4:
8390 : printf ("other");
8391 : break;
8392 0 : default:
8393 : printf ("unknown-0x%" PRIx32, kind);
8394 : break;
8395 : }
8396 8 : printf (":%c)", (is_static ? 'S' : 'G'));
8397 : }
8398 16 : if (cus > 0)
8399 : printf (", ");
8400 : }
8401 : printf ("\n");
8402 : }
8403 2048 : n++;
8404 : }
8405 : }
8406 :
8407 : static void
8408 89 : print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
8409 : {
8410 : /* Before we start the real work get a debug context descriptor. */
8411 : Dwarf_Addr dwbias;
8412 89 : Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
8413 267 : Dwarf dummy_dbg =
8414 : {
8415 89 : .elf = ebl->elf,
8416 89 : .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
8417 : };
8418 89 : if (dbg == NULL)
8419 : {
8420 20 : if ((print_debug_sections & ~section_exception) != 0)
8421 0 : error (0, 0, gettext ("cannot get debug context descriptor: %s"),
8422 : dwfl_errmsg (-1));
8423 : dbg = &dummy_dbg;
8424 : }
8425 :
8426 : /* Get the section header string table index. */
8427 : size_t shstrndx;
8428 89 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
8429 : error (EXIT_FAILURE, 0,
8430 0 : gettext ("cannot get section header string table index"));
8431 :
8432 : /* Look through all the sections for the debugging sections to print. */
8433 : Elf_Scn *scn = NULL;
8434 2871 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
8435 : {
8436 : GElf_Shdr shdr_mem;
8437 2782 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
8438 :
8439 2782 : if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
8440 : {
8441 : static const struct
8442 : {
8443 : const char *name;
8444 : enum section_e bitmask;
8445 : void (*fp) (Dwfl_Module *, Ebl *,
8446 : GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
8447 : } debug_sections[] =
8448 : {
8449 : #define NEW_SECTION(name) \
8450 : { ".debug_" #name, section_##name, print_debug_##name##_section }
8451 : NEW_SECTION (abbrev),
8452 : NEW_SECTION (aranges),
8453 : NEW_SECTION (frame),
8454 : NEW_SECTION (info),
8455 : NEW_SECTION (types),
8456 : NEW_SECTION (line),
8457 : NEW_SECTION (loc),
8458 : NEW_SECTION (pubnames),
8459 : NEW_SECTION (str),
8460 : NEW_SECTION (macinfo),
8461 : NEW_SECTION (macro),
8462 : NEW_SECTION (ranges),
8463 : { ".eh_frame", section_frame | section_exception,
8464 : print_debug_frame_section },
8465 : { ".eh_frame_hdr", section_frame | section_exception,
8466 : print_debug_frame_hdr_section },
8467 : { ".gcc_except_table", section_frame | section_exception,
8468 : print_debug_exception_table },
8469 : { ".gdb_index", section_gdb_index, print_gdb_index_section }
8470 : };
8471 1331 : const int ndebug_sections = (sizeof (debug_sections)
8472 : / sizeof (debug_sections[0]));
8473 1331 : const char *name = elf_strptr (ebl->elf, shstrndx,
8474 1331 : shdr->sh_name);
8475 1331 : if (name == NULL)
8476 0 : continue;
8477 :
8478 : int n;
8479 15367 : for (n = 0; n < ndebug_sections; ++n)
8480 15955 : if (strcmp (name, debug_sections[n].name) == 0
8481 15429 : || (name[0] == '.' && name[1] == 'z'
8482 358 : && debug_sections[n].name[1] == 'd'
8483 358 : && strcmp (&name[2], &debug_sections[n].name[1]) == 0)
8484 : )
8485 : {
8486 1176 : if ((print_debug_sections | implicit_debug_sections)
8487 588 : & debug_sections[n].bitmask)
8488 324 : debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
8489 : break;
8490 : }
8491 : }
8492 : }
8493 :
8494 89 : reset_listptr (&known_loclistptr);
8495 89 : reset_listptr (&known_rangelistptr);
8496 89 : }
8497 :
8498 :
8499 : #define ITEM_INDENT 4
8500 : #define WRAP_COLUMN 75
8501 :
8502 : /* Print "NAME: FORMAT", wrapping when output text would make the line
8503 : exceed WRAP_COLUMN. Unpadded numbers look better for the core items
8504 : but this function is also used for registers which should be printed
8505 : aligned. Fortunately registers output uses fixed fields width (such
8506 : as %11d) for the alignment.
8507 :
8508 : Line breaks should not depend on the particular values although that
8509 : may happen in some cases of the core items. */
8510 :
8511 : static unsigned int
8512 : __attribute__ ((format (printf, 6, 7)))
8513 761 : print_core_item (unsigned int colno, char sep, unsigned int wrap,
8514 : size_t name_width, const char *name, const char *format, ...)
8515 : {
8516 761 : size_t len = strlen (name);
8517 761 : if (name_width < len)
8518 368 : name_width = len;
8519 :
8520 : char *out;
8521 : va_list ap;
8522 761 : va_start (ap, format);
8523 761 : int out_len = vasprintf (&out, format, ap);
8524 761 : va_end (ap);
8525 761 : if (out_len == -1)
8526 0 : error (EXIT_FAILURE, 0, _("memory exhausted"));
8527 :
8528 761 : size_t n = name_width + sizeof ": " - 1 + out_len;
8529 :
8530 761 : if (colno == 0)
8531 : {
8532 48 : printf ("%*s", ITEM_INDENT, "");
8533 48 : colno = ITEM_INDENT + n;
8534 : }
8535 713 : else if (colno + 2 + n < wrap)
8536 : {
8537 866 : printf ("%c ", sep);
8538 433 : colno += 2 + n;
8539 : }
8540 : else
8541 : {
8542 280 : printf ("\n%*s", ITEM_INDENT, "");
8543 280 : colno = ITEM_INDENT + n;
8544 : }
8545 :
8546 1522 : printf ("%s: %*s%s", name, (int) (name_width - len), "", out);
8547 :
8548 761 : free (out);
8549 :
8550 761 : return colno;
8551 : }
8552 :
8553 : static const void *
8554 838 : convert (Elf *core, Elf_Type type, uint_fast16_t count,
8555 : void *value, const void *data, size_t size)
8556 : {
8557 1676 : Elf_Data valuedata =
8558 : {
8559 : .d_type = type,
8560 : .d_buf = value,
8561 838 : .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
8562 : .d_version = EV_CURRENT,
8563 : };
8564 838 : Elf_Data indata =
8565 : {
8566 : .d_type = type,
8567 : .d_buf = (void *) data,
8568 : .d_size = valuedata.d_size,
8569 : .d_version = EV_CURRENT,
8570 : };
8571 :
8572 1676 : Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
8573 1676 : ? elf32_xlatetom : elf64_xlatetom)
8574 838 : (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
8575 838 : if (d == NULL)
8576 0 : error (EXIT_FAILURE, 0,
8577 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
8578 :
8579 838 : return data + indata.d_size;
8580 : }
8581 :
8582 : typedef uint8_t GElf_Byte;
8583 :
8584 : static unsigned int
8585 371 : handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
8586 : unsigned int colno, size_t *repeated_size)
8587 : {
8588 371 : uint_fast16_t count = item->count ?: 1;
8589 : /* Ebl_Core_Item count is always a small number.
8590 : Make sure the backend didn't put in some large bogus value. */
8591 56 : assert (count < 128);
8592 :
8593 : #define TYPES \
8594 : DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8); \
8595 : DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16); \
8596 : DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32); \
8597 : DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32); \
8598 : DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64); \
8599 : DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64)
8600 :
8601 : #define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name
8602 : typedef union { TYPES; } value_t;
8603 371 : void *data = alloca (count * sizeof (value_t));
8604 : #undef DO_TYPE
8605 :
8606 : #define DO_TYPE(NAME, Name, hex, dec) \
8607 : GElf_##Name *value_##Name __attribute__((unused)) = data
8608 371 : TYPES;
8609 : #undef DO_TYPE
8610 :
8611 371 : size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
8612 371 : size_t convsize = size;
8613 371 : if (repeated_size != NULL)
8614 : {
8615 1 : if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
8616 : {
8617 0 : data = alloca (*repeated_size);
8618 0 : count *= *repeated_size / size;
8619 0 : convsize = count * size;
8620 0 : *repeated_size -= convsize;
8621 : }
8622 1 : else if (item->count != 0 || item->format != '\n')
8623 0 : *repeated_size -= size;
8624 : }
8625 :
8626 371 : convert (core, item->type, count, data, desc + item->offset, convsize);
8627 :
8628 371 : Elf_Type type = item->type;
8629 371 : if (type == ELF_T_ADDR)
8630 0 : type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
8631 :
8632 371 : switch (item->format)
8633 : {
8634 175 : case 'd':
8635 175 : assert (count == 1);
8636 175 : switch (type)
8637 : {
8638 : #define DO_TYPE(NAME, Name, hex, dec) \
8639 : case ELF_T_##NAME: \
8640 : colno = print_core_item (colno, ',', WRAP_COLUMN, \
8641 : 0, item->name, dec, value_##Name[0]); \
8642 : break
8643 24 : TYPES;
8644 : #undef DO_TYPE
8645 0 : default:
8646 0 : abort ();
8647 : }
8648 : break;
8649 :
8650 109 : case 'x':
8651 109 : assert (count == 1);
8652 109 : switch (type)
8653 : {
8654 : #define DO_TYPE(NAME, Name, hex, dec) \
8655 : case ELF_T_##NAME: \
8656 : colno = print_core_item (colno, ',', WRAP_COLUMN, \
8657 : 0, item->name, hex, value_##Name[0]); \
8658 : break
8659 0 : TYPES;
8660 : #undef DO_TYPE
8661 0 : default:
8662 0 : abort ();
8663 : }
8664 : break;
8665 :
8666 20 : case 'b':
8667 : case 'B':
8668 20 : assert (size % sizeof (unsigned int) == 0);
8669 20 : unsigned int nbits = count * size * 8;
8670 20 : unsigned int pop = 0;
8671 50 : for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
8672 30 : pop += __builtin_popcount (*i);
8673 20 : bool negate = pop > nbits / 2;
8674 20 : const unsigned int bias = item->format == 'b';
8675 :
8676 40 : {
8677 20 : char printed[(negate ? nbits - pop : pop) * 16 + 1];
8678 20 : char *p = printed;
8679 20 : *p = '\0';
8680 :
8681 : if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
8682 : {
8683 : assert (size == sizeof (unsigned int) * 2);
8684 : for (unsigned int *i = data;
8685 : (void *) i < data + count * size; i += 2)
8686 : {
8687 : unsigned int w = i[1];
8688 : i[1] = i[0];
8689 : i[0] = w;
8690 : }
8691 : }
8692 :
8693 20 : unsigned int lastbit = 0;
8694 20 : unsigned int run = 0;
8695 70 : for (const unsigned int *i = data;
8696 30 : (void *) i < data + count * size; ++i)
8697 : {
8698 30 : unsigned int bit = ((void *) i - data) * 8;
8699 30 : unsigned int w = negate ? ~*i : *i;
8700 30 : while (w != 0)
8701 : {
8702 : /* Note that a right shift equal to (or greater than)
8703 : the number of bits of w is undefined behaviour. In
8704 : particular when the least significant bit is bit 32
8705 : (w = 0x8000000) then w >>= n is undefined. So
8706 : explicitly handle that case separately. */
8707 0 : unsigned int n = ffs (w);
8708 0 : if (n < sizeof (w) * 8)
8709 0 : w >>= n;
8710 : else
8711 : w = 0;
8712 0 : bit += n;
8713 :
8714 0 : if (lastbit != 0 && lastbit + 1 == bit)
8715 0 : ++run;
8716 : else
8717 : {
8718 0 : if (lastbit == 0)
8719 0 : p += sprintf (p, "%u", bit - bias);
8720 0 : else if (run == 0)
8721 0 : p += sprintf (p, ",%u", bit - bias);
8722 : else
8723 0 : p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
8724 : run = 0;
8725 : }
8726 :
8727 : lastbit = bit;
8728 : }
8729 : }
8730 20 : if (lastbit > 0 && run > 0 && lastbit + 1 != nbits)
8731 0 : p += sprintf (p, "-%u", lastbit - bias);
8732 :
8733 20 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
8734 : negate ? "~<%s>" : "<%s>", printed);
8735 : }
8736 20 : break;
8737 :
8738 40 : case 'T':
8739 : case (char) ('T'|0x80):
8740 40 : assert (count == 2);
8741 : Dwarf_Word sec;
8742 : Dwarf_Word usec;
8743 40 : switch (type)
8744 : {
8745 : #define DO_TYPE(NAME, Name, hex, dec) \
8746 : case ELF_T_##NAME: \
8747 : sec = value_##Name[0]; \
8748 : usec = value_##Name[1]; \
8749 : break
8750 0 : TYPES;
8751 : #undef DO_TYPE
8752 0 : default:
8753 0 : abort ();
8754 : }
8755 40 : if (unlikely (item->format == (char) ('T'|0x80)))
8756 : {
8757 : /* This is a hack for an ill-considered 64-bit ABI where
8758 : tv_usec is actually a 32-bit field with 32 bits of padding
8759 : rounding out struct timeval. We've already converted it as
8760 : a 64-bit field. For little-endian, this just means the
8761 : high half is the padding; it's presumably zero, but should
8762 : be ignored anyway. For big-endian, it means the 32-bit
8763 : field went into the high half of USEC. */
8764 : GElf_Ehdr ehdr_mem;
8765 0 : GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
8766 0 : if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
8767 0 : usec >>= 32;
8768 : else
8769 0 : usec &= UINT32_MAX;
8770 : }
8771 40 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
8772 : "%" PRIu64 ".%.6" PRIu64, sec, usec);
8773 40 : break;
8774 :
8775 8 : case 'c':
8776 8 : assert (count == 1);
8777 8 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
8778 8 : "%c", value_Byte[0]);
8779 8 : break;
8780 :
8781 16 : case 's':
8782 16 : colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
8783 : "%.*s", (int) count, value_Byte);
8784 16 : break;
8785 :
8786 1 : case '\n':
8787 : /* This is a list of strings separated by '\n'. */
8788 1 : assert (item->count == 0);
8789 1 : assert (repeated_size != NULL);
8790 1 : assert (item->name == NULL);
8791 1 : if (unlikely (item->offset >= *repeated_size))
8792 : break;
8793 :
8794 1 : const char *s = desc + item->offset;
8795 1 : size = *repeated_size - item->offset;
8796 1 : *repeated_size = 0;
8797 49 : while (size > 0)
8798 : {
8799 48 : const char *eol = memchr (s, '\n', size);
8800 48 : int len = size;
8801 48 : if (eol != NULL)
8802 47 : len = eol - s;
8803 48 : printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
8804 48 : if (eol == NULL)
8805 : break;
8806 47 : size -= eol + 1 - s;
8807 47 : s = eol + 1;
8808 : }
8809 :
8810 : colno = WRAP_COLUMN;
8811 : break;
8812 :
8813 : case 'h':
8814 : break;
8815 :
8816 0 : default:
8817 0 : error (0, 0, "XXX not handling format '%c' for %s",
8818 : item->format, item->name);
8819 : break;
8820 : }
8821 :
8822 : #undef TYPES
8823 :
8824 371 : return colno;
8825 : }
8826 :
8827 :
8828 : /* Sort items by group, and by layout offset within each group. */
8829 : static int
8830 827 : compare_core_items (const void *a, const void *b)
8831 : {
8832 827 : const Ebl_Core_Item *const *p1 = a;
8833 827 : const Ebl_Core_Item *const *p2 = b;
8834 827 : const Ebl_Core_Item *item1 = *p1;
8835 827 : const Ebl_Core_Item *item2 = *p2;
8836 :
8837 827 : return ((item1->group == item2->group ? 0
8838 827 : : strcmp (item1->group, item2->group))
8839 391 : ?: (int) item1->offset - (int) item2->offset);
8840 : }
8841 :
8842 : /* Sort item groups by layout offset of the first item in the group. */
8843 : static int
8844 126 : compare_core_item_groups (const void *a, const void *b)
8845 : {
8846 126 : const Ebl_Core_Item *const *const *p1 = a;
8847 126 : const Ebl_Core_Item *const *const *p2 = b;
8848 126 : const Ebl_Core_Item *const *group1 = *p1;
8849 126 : const Ebl_Core_Item *const *group2 = *p2;
8850 126 : const Ebl_Core_Item *item1 = *group1;
8851 126 : const Ebl_Core_Item *item2 = *group2;
8852 :
8853 126 : return (int) item1->offset - (int) item2->offset;
8854 : }
8855 :
8856 : static unsigned int
8857 35 : handle_core_items (Elf *core, const void *desc, size_t descsz,
8858 : const Ebl_Core_Item *items, size_t nitems)
8859 : {
8860 35 : if (nitems == 0)
8861 : return 0;
8862 32 : unsigned int colno = 0;
8863 :
8864 : /* FORMAT '\n' makes sense to be present only as a single item as it
8865 : processes all the data of a note. FORMATs 'b' and 'B' have a special case
8866 : if present as a single item but they can be also processed with other
8867 : items below. */
8868 32 : if (nitems == 1 && (items[0].format == '\n' || items[0].format == 'b'
8869 8 : || items[0].format == 'B'))
8870 : {
8871 1 : assert (items[0].offset == 0);
8872 1 : size_t size = descsz;
8873 1 : colno = handle_core_item (core, items, desc, colno, &size);
8874 : /* If SIZE is not zero here there is some remaining data. But we do not
8875 : know how to process it anyway. */
8876 : return colno;
8877 : }
8878 362 : for (size_t i = 0; i < nitems; ++i)
8879 362 : assert (items[i].format != '\n');
8880 :
8881 : /* Sort to collect the groups together. */
8882 31 : const Ebl_Core_Item *sorted_items[nitems];
8883 393 : for (size_t i = 0; i < nitems; ++i)
8884 362 : sorted_items[i] = &items[i];
8885 31 : qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
8886 :
8887 : /* Collect the unique groups and sort them. */
8888 31 : const Ebl_Core_Item **groups[nitems];
8889 31 : groups[0] = &sorted_items[0];
8890 31 : size_t ngroups = 1;
8891 362 : for (size_t i = 1; i < nitems; ++i)
8892 331 : if (sorted_items[i]->group != sorted_items[i - 1]->group
8893 68 : && strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
8894 68 : groups[ngroups++] = &sorted_items[i];
8895 31 : qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
8896 :
8897 : /* Write out all the groups. */
8898 31 : const void *last = desc;
8899 : do
8900 : {
8901 134 : for (size_t i = 0; i < ngroups; ++i)
8902 : {
8903 572 : for (const Ebl_Core_Item **item = groups[i];
8904 471 : (item < &sorted_items[nitems]
8905 438 : && ((*item)->group == groups[i][0]->group
8906 68 : || !strcmp ((*item)->group, groups[i][0]->group)));
8907 370 : ++item)
8908 370 : colno = handle_core_item (core, *item, desc, colno, NULL);
8909 :
8910 : /* Force a line break at the end of the group. */
8911 101 : colno = WRAP_COLUMN;
8912 : }
8913 :
8914 33 : if (descsz == 0)
8915 : break;
8916 :
8917 : /* This set of items consumed a certain amount of the note's data.
8918 : If there is more data there, we have another unit of the same size.
8919 : Loop to print that out too. */
8920 19 : const Ebl_Core_Item *item = &items[nitems - 1];
8921 38 : size_t eltsz = item->offset + gelf_fsize (core, item->type,
8922 19 : item->count ?: 1, EV_CURRENT);
8923 :
8924 19 : int reps = -1;
8925 : do
8926 : {
8927 19 : ++reps;
8928 19 : desc += eltsz;
8929 19 : descsz -= eltsz;
8930 : }
8931 19 : while (descsz >= eltsz && !memcmp (desc, last, eltsz));
8932 :
8933 19 : if (reps == 1)
8934 : {
8935 : /* For just one repeat, print it unabridged twice. */
8936 : desc -= eltsz;
8937 : descsz += eltsz;
8938 : }
8939 19 : else if (reps > 1)
8940 0 : printf (gettext ("\n%*s... <repeats %u more times> ..."),
8941 : ITEM_INDENT, "", reps);
8942 :
8943 19 : last = desc;
8944 : }
8945 19 : while (descsz > 0);
8946 :
8947 : return colno;
8948 : }
8949 :
8950 : static unsigned int
8951 : handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
8952 : unsigned int colno)
8953 : {
8954 0 : desc += regloc->offset;
8955 :
8956 0 : abort (); /* XXX */
8957 : return colno;
8958 : }
8959 :
8960 :
8961 : static unsigned int
8962 161 : handle_core_register (Ebl *ebl, Elf *core, int maxregname,
8963 : const Ebl_Register_Location *regloc, const void *desc,
8964 : unsigned int colno)
8965 : {
8966 161 : if (regloc->bits % 8 != 0)
8967 0 : return handle_bit_registers (regloc, desc, colno);
8968 :
8969 161 : desc += regloc->offset;
8970 :
8971 554 : for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
8972 : {
8973 : char name[REGNAMESZ];
8974 : int bits;
8975 : int type;
8976 393 : register_info (ebl, reg, regloc, name, &bits, &type);
8977 :
8978 : #define TYPES \
8979 : BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8); \
8980 : BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16); \
8981 : BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32); \
8982 : BITS (64, XWORD, "%20" PRId64, " 0x%.16" PRIx64)
8983 :
8984 : #define BITS(bits, xtype, sfmt, ufmt) \
8985 : uint##bits##_t b##bits; int##bits##_t b##bits##s
8986 : union { TYPES; uint64_t b128[2]; } value;
8987 : #undef BITS
8988 :
8989 393 : switch (type)
8990 : {
8991 305 : case DW_ATE_unsigned:
8992 : case DW_ATE_signed:
8993 : case DW_ATE_address:
8994 305 : switch (bits)
8995 : {
8996 : #define BITS(bits, xtype, sfmt, ufmt) \
8997 : case bits: \
8998 : desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0); \
8999 : if (type == DW_ATE_signed) \
9000 : colno = print_core_item (colno, ' ', WRAP_COLUMN, \
9001 : maxregname, name, \
9002 : sfmt, value.b##bits##s); \
9003 : else \
9004 : colno = print_core_item (colno, ' ', WRAP_COLUMN, \
9005 : maxregname, name, \
9006 : ufmt, value.b##bits); \
9007 : break
9008 :
9009 0 : TYPES;
9010 :
9011 48 : case 128:
9012 48 : assert (type == DW_ATE_unsigned);
9013 48 : desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
9014 48 : int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
9015 96 : colno = print_core_item (colno, ' ', WRAP_COLUMN,
9016 : maxregname, name,
9017 : "0x%.16" PRIx64 "%.16" PRIx64,
9018 48 : value.b128[!be], value.b128[be]);
9019 48 : break;
9020 :
9021 0 : default:
9022 0 : abort ();
9023 : #undef BITS
9024 : }
9025 : break;
9026 :
9027 88 : default:
9028 : /* Print each byte in hex, the whole thing in native byte order. */
9029 88 : assert (bits % 8 == 0);
9030 88 : const uint8_t *bytes = desc;
9031 88 : desc += bits / 8;
9032 88 : char hex[bits / 4 + 1];
9033 88 : hex[bits / 4] = '\0';
9034 88 : int incr = 1;
9035 88 : if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
9036 : {
9037 48 : bytes += bits / 8 - 1;
9038 48 : incr = -1;
9039 : }
9040 88 : size_t idx = 0;
9041 872 : for (char *h = hex; bits > 0; bits -= 8, idx += incr)
9042 : {
9043 784 : *h++ = "0123456789abcdef"[bytes[idx] >> 4];
9044 784 : *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
9045 : }
9046 88 : colno = print_core_item (colno, ' ', WRAP_COLUMN,
9047 : maxregname, name, "0x%s", hex);
9048 : break;
9049 : }
9050 393 : desc += regloc->pad;
9051 :
9052 : #undef TYPES
9053 : }
9054 :
9055 : return colno;
9056 : }
9057 :
9058 :
9059 : struct register_info
9060 : {
9061 : const Ebl_Register_Location *regloc;
9062 : const char *set;
9063 : char name[REGNAMESZ];
9064 : int regno;
9065 : int bits;
9066 : int type;
9067 : };
9068 :
9069 : static int
9070 : register_bitpos (const struct register_info *r)
9071 : {
9072 1916 : return (r->regloc->offset * 8
9073 3832 : + ((r->regno - r->regloc->regno)
9074 1916 : * (r->regloc->bits + r->regloc->pad * 8)));
9075 : }
9076 :
9077 : static int
9078 987 : compare_sets_by_info (const struct register_info *r1,
9079 : const struct register_info *r2)
9080 : {
9081 987 : return ((int) r2->bits - (int) r1->bits
9082 2903 : ?: register_bitpos (r1) - register_bitpos (r2));
9083 : }
9084 :
9085 : /* Sort registers by set, and by size and layout offset within each set. */
9086 : static int
9087 4489 : compare_registers (const void *a, const void *b)
9088 : {
9089 4489 : const struct register_info *r1 = a;
9090 4489 : const struct register_info *r2 = b;
9091 :
9092 : /* Unused elements sort last. */
9093 4489 : if (r1->regloc == NULL)
9094 3278 : return r2->regloc == NULL ? 0 : 1;
9095 1211 : if (r2->regloc == NULL)
9096 : return -1;
9097 :
9098 1046 : return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
9099 79 : ?: compare_sets_by_info (r1, r2));
9100 : }
9101 :
9102 : /* Sort register sets by layout offset of the first register in the set. */
9103 : static int
9104 20 : compare_register_sets (const void *a, const void *b)
9105 : {
9106 20 : const struct register_info *const *p1 = a;
9107 20 : const struct register_info *const *p2 = b;
9108 20 : return compare_sets_by_info (*p1, *p2);
9109 : }
9110 :
9111 : static unsigned int
9112 35 : handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
9113 : const Ebl_Register_Location *reglocs, size_t nregloc)
9114 : {
9115 35 : if (nregloc == 0)
9116 : return 0;
9117 :
9118 17 : ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
9119 17 : if (maxnreg <= 0)
9120 : {
9121 0 : for (size_t i = 0; i < nregloc; ++i)
9122 0 : if (maxnreg < reglocs[i].regno + reglocs[i].count)
9123 0 : maxnreg = reglocs[i].regno + reglocs[i].count;
9124 0 : assert (maxnreg > 0);
9125 : }
9126 :
9127 17 : struct register_info regs[maxnreg];
9128 34 : memset (regs, 0, sizeof regs);
9129 :
9130 : /* Sort to collect the sets together. */
9131 17 : int maxreg = 0;
9132 178 : for (size_t i = 0; i < nregloc; ++i)
9133 715 : for (int reg = reglocs[i].regno;
9134 554 : reg < reglocs[i].regno + reglocs[i].count;
9135 393 : ++reg)
9136 : {
9137 393 : assert (reg < maxnreg);
9138 393 : if (reg > maxreg)
9139 199 : maxreg = reg;
9140 393 : struct register_info *info = ®s[reg];
9141 393 : info->regloc = ®locs[i];
9142 393 : info->regno = reg;
9143 786 : info->set = register_info (ebl, reg, ®locs[i],
9144 393 : info->name, &info->bits, &info->type);
9145 : }
9146 17 : qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
9147 :
9148 : /* Collect the unique sets and sort them. */
9149 802 : inline bool same_set (const struct register_info *a,
9150 : const struct register_info *b)
9151 : {
9152 1604 : return (a < ®s[maxnreg] && a->regloc != NULL
9153 802 : && b < ®s[maxnreg] && b->regloc != NULL
9154 785 : && a->bits == b->bits
9155 1569 : && (a->set == b->set || !strcmp (a->set, b->set)));
9156 : }
9157 17 : struct register_info *sets[maxreg + 1];
9158 17 : sets[0] = ®s[0];
9159 17 : size_t nsets = 1;
9160 1247 : for (int i = 1; i <= maxreg; ++i)
9161 1230 : if (regs[i].regloc != NULL && !same_set (®s[i], ®s[i - 1]))
9162 16 : sets[nsets++] = ®s[i];
9163 17 : qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
9164 :
9165 : /* Write out all the sets. */
9166 17 : unsigned int colno = 0;
9167 50 : for (size_t i = 0; i < nsets; ++i)
9168 : {
9169 : /* Find the longest name of a register in this set. */
9170 33 : size_t maxname = 0;
9171 : const struct register_info *end;
9172 426 : for (end = sets[i]; same_set (sets[i], end); ++end)
9173 : {
9174 393 : size_t len = strlen (end->name);
9175 393 : if (len > maxname)
9176 50 : maxname = len;
9177 : }
9178 :
9179 194 : for (const struct register_info *reg = sets[i];
9180 : reg < end;
9181 161 : reg += reg->regloc->count ?: 1)
9182 161 : colno = handle_core_register (ebl, core, maxname,
9183 : reg->regloc, desc, colno);
9184 :
9185 : /* Force a line break at the end of the group. */
9186 33 : colno = WRAP_COLUMN;
9187 : }
9188 :
9189 : return colno;
9190 : }
9191 :
9192 : static void
9193 8 : handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
9194 : {
9195 8 : Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
9196 8 : if (data == NULL)
9197 0 : elf_error:
9198 0 : error (EXIT_FAILURE, 0,
9199 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
9200 :
9201 8 : const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
9202 158 : for (size_t i = 0; i < nauxv; ++i)
9203 : {
9204 : GElf_auxv_t av_mem;
9205 150 : GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
9206 150 : if (av == NULL)
9207 : goto elf_error;
9208 :
9209 : const char *name;
9210 : const char *fmt;
9211 150 : if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
9212 : {
9213 : /* Unknown type. */
9214 0 : if (av->a_un.a_val == 0)
9215 0 : printf (" %" PRIu64 "\n", av->a_type);
9216 : else
9217 0 : printf (" %" PRIu64 ": %#" PRIx64 "\n",
9218 : av->a_type, av->a_un.a_val);
9219 : }
9220 : else
9221 150 : switch (fmt[0])
9222 : {
9223 8 : case '\0': /* Normally zero. */
9224 8 : if (av->a_un.a_val == 0)
9225 : {
9226 8 : printf (" %s\n", name);
9227 : break;
9228 : }
9229 : /* Fall through */
9230 : case 'x': /* hex */
9231 : case 'p': /* address */
9232 : case 's': /* address of string */
9233 66 : printf (" %s: %#" PRIx64 "\n", name, av->a_un.a_val);
9234 : break;
9235 72 : case 'u':
9236 72 : printf (" %s: %" PRIu64 "\n", name, av->a_un.a_val);
9237 : break;
9238 0 : case 'd':
9239 0 : printf (" %s: %" PRId64 "\n", name, av->a_un.a_val);
9240 : break;
9241 :
9242 4 : case 'b':
9243 8 : printf (" %s: %#" PRIx64 " ", name, av->a_un.a_val);
9244 4 : GElf_Xword bit = 1;
9245 4 : const char *pfx = "<";
9246 110 : for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
9247 : {
9248 106 : if (av->a_un.a_val & bit)
9249 : {
9250 77 : printf ("%s%s", pfx, p);
9251 77 : pfx = " ";
9252 : }
9253 106 : bit <<= 1;
9254 : }
9255 : printf (">\n");
9256 : break;
9257 :
9258 0 : default:
9259 0 : abort ();
9260 : }
9261 : }
9262 8 : }
9263 :
9264 : static bool
9265 : buf_has_data (unsigned char const *ptr, unsigned char const *end, size_t sz)
9266 : {
9267 162 : return ptr < end && (size_t) (end - ptr) >= sz;
9268 : }
9269 :
9270 : static bool
9271 15 : buf_read_int (Elf *core, unsigned char const **ptrp, unsigned char const *end,
9272 : int *retp)
9273 : {
9274 30 : if (! buf_has_data (*ptrp, end, 4))
9275 : return false;
9276 :
9277 15 : *ptrp = convert (core, ELF_T_WORD, 1, retp, *ptrp, 4);
9278 15 : return true;
9279 : }
9280 :
9281 : static bool
9282 147 : buf_read_ulong (Elf *core, unsigned char const **ptrp, unsigned char const *end,
9283 : uint64_t *retp)
9284 : {
9285 147 : size_t sz = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
9286 294 : if (! buf_has_data (*ptrp, end, sz))
9287 : return false;
9288 :
9289 : union
9290 : {
9291 : uint64_t u64;
9292 : uint32_t u32;
9293 : } u;
9294 :
9295 147 : *ptrp = convert (core, ELF_T_ADDR, 1, &u, *ptrp, sz);
9296 :
9297 147 : if (sz == 4)
9298 93 : *retp = u.u32;
9299 : else
9300 54 : *retp = u.u64;
9301 : return true;
9302 : }
9303 :
9304 : static void
9305 5 : handle_siginfo_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
9306 : {
9307 5 : Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
9308 5 : if (data == NULL)
9309 0 : error (EXIT_FAILURE, 0,
9310 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
9311 :
9312 5 : unsigned char const *ptr = data->d_buf;
9313 5 : unsigned char const *const end = data->d_buf + data->d_size;
9314 :
9315 : /* Siginfo head is three ints: signal number, error number, origin
9316 : code. */
9317 : int si_signo, si_errno, si_code;
9318 5 : if (! buf_read_int (core, &ptr, end, &si_signo)
9319 5 : || ! buf_read_int (core, &ptr, end, &si_errno)
9320 5 : || ! buf_read_int (core, &ptr, end, &si_code))
9321 : {
9322 0 : fail:
9323 0 : printf (" Not enough data in NT_SIGINFO note.\n");
9324 0 : return;
9325 : }
9326 :
9327 : /* Next is a pointer-aligned union of structures. On 64-bit
9328 : machines, that implies a word of padding. */
9329 5 : if (gelf_getclass (core) == ELFCLASS64)
9330 2 : ptr += 4;
9331 :
9332 10 : printf (" si_signo: %d, si_errno: %d, si_code: %d\n",
9333 : si_signo, si_errno, si_code);
9334 :
9335 5 : if (si_code > 0)
9336 5 : switch (si_signo)
9337 : {
9338 5 : case SIGILL:
9339 : case SIGFPE:
9340 : case SIGSEGV:
9341 : case SIGBUS:
9342 : {
9343 : uint64_t addr;
9344 5 : if (! buf_read_ulong (core, &ptr, end, &addr))
9345 : goto fail;
9346 10 : printf (" fault address: %#" PRIx64 "\n", addr);
9347 5 : break;
9348 : }
9349 : default:
9350 : ;
9351 : }
9352 0 : else if (si_code == SI_USER)
9353 : {
9354 : int pid, uid;
9355 0 : if (! buf_read_int (core, &ptr, end, &pid)
9356 0 : || ! buf_read_int (core, &ptr, end, &uid))
9357 : goto fail;
9358 0 : printf (" sender PID: %d, sender UID: %d\n", pid, uid);
9359 : }
9360 : }
9361 :
9362 : static void
9363 5 : handle_file_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
9364 : {
9365 5 : Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
9366 5 : if (data == NULL)
9367 0 : error (EXIT_FAILURE, 0,
9368 0 : gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
9369 :
9370 5 : unsigned char const *ptr = data->d_buf;
9371 5 : unsigned char const *const end = data->d_buf + data->d_size;
9372 :
9373 : uint64_t count, page_size;
9374 5 : if (! buf_read_ulong (core, &ptr, end, &count)
9375 5 : || ! buf_read_ulong (core, &ptr, end, &page_size))
9376 : {
9377 0 : fail:
9378 0 : printf (" Not enough data in NT_FILE note.\n");
9379 0 : return;
9380 : }
9381 :
9382 5 : size_t addrsize = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
9383 5 : uint64_t maxcount = (size_t) (end - ptr) / (3 * addrsize);
9384 5 : if (count > maxcount)
9385 : goto fail;
9386 :
9387 : /* Where file names are stored. */
9388 5 : unsigned char const *const fstart = ptr + 3 * count * addrsize;
9389 5 : char const *fptr = (char *) fstart;
9390 :
9391 10 : printf (" %" PRId64 " files:\n", count);
9392 49 : for (uint64_t i = 0; i < count; ++i)
9393 : {
9394 : uint64_t mstart, mend, moffset;
9395 44 : if (! buf_read_ulong (core, &ptr, fstart, &mstart)
9396 44 : || ! buf_read_ulong (core, &ptr, fstart, &mend)
9397 44 : || ! buf_read_ulong (core, &ptr, fstart, &moffset))
9398 : goto fail;
9399 :
9400 44 : const char *fnext = memchr (fptr, '\0', (char *) end - fptr);
9401 44 : if (fnext == NULL)
9402 : goto fail;
9403 :
9404 88 : int ct = printf (" %08" PRIx64 "-%08" PRIx64
9405 : " %08" PRIx64 " %" PRId64,
9406 : mstart, mend, moffset * page_size, mend - mstart);
9407 88 : printf ("%*s%s\n", ct > 50 ? 3 : 53 - ct, "", fptr);
9408 :
9409 44 : fptr = fnext + 1;
9410 : }
9411 : }
9412 :
9413 : static void
9414 36 : handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
9415 : const char *name, const void *desc)
9416 : {
9417 : GElf_Word regs_offset;
9418 : size_t nregloc;
9419 : const Ebl_Register_Location *reglocs;
9420 : size_t nitems;
9421 : const Ebl_Core_Item *items;
9422 :
9423 36 : if (! ebl_core_note (ebl, nhdr, name,
9424 : ®s_offset, &nregloc, ®locs, &nitems, &items))
9425 1 : return;
9426 :
9427 : /* Pass 0 for DESCSZ when there are registers in the note,
9428 : so that the ITEMS array does not describe the whole thing.
9429 : For non-register notes, the actual descsz might be a multiple
9430 : of the unit size, not just exactly the unit size. */
9431 88 : unsigned int colno = handle_core_items (ebl->elf, desc,
9432 53 : nregloc == 0 ? nhdr->n_descsz : 0,
9433 : items, nitems);
9434 35 : if (colno != 0)
9435 : putchar_unlocked ('\n');
9436 :
9437 35 : colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
9438 : reglocs, nregloc);
9439 35 : if (colno != 0)
9440 : putchar_unlocked ('\n');
9441 : }
9442 :
9443 : static void
9444 42 : handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
9445 : GElf_Off start, Elf_Data *data)
9446 : {
9447 42 : fputs_unlocked (gettext (" Owner Data size Type\n"), stdout);
9448 :
9449 42 : if (data == NULL)
9450 : goto bad_note;
9451 :
9452 : size_t offset = 0;
9453 : GElf_Nhdr nhdr;
9454 : size_t name_offset;
9455 : size_t desc_offset;
9456 130 : while (offset < data->d_size
9457 88 : && (offset = gelf_getnote (data, offset,
9458 : &nhdr, &name_offset, &desc_offset)) > 0)
9459 : {
9460 88 : const char *name = nhdr.n_namesz == 0 ? "" : data->d_buf + name_offset;
9461 88 : const char *desc = data->d_buf + desc_offset;
9462 :
9463 : char buf[100];
9464 : char buf2[100];
9465 352 : printf (gettext (" %-13.*s %9" PRId32 " %s\n"),
9466 88 : (int) nhdr.n_namesz, name, nhdr.n_descsz,
9467 88 : ehdr->e_type == ET_CORE
9468 54 : ? ebl_core_note_type_name (ebl, nhdr.n_type,
9469 : buf, sizeof (buf))
9470 34 : : ebl_object_note_type_name (ebl, name, nhdr.n_type,
9471 : buf2, sizeof (buf2)));
9472 :
9473 : /* Filter out invalid entries. */
9474 : if (memchr (name, '\0', nhdr.n_namesz) != NULL
9475 : /* XXX For now help broken Linux kernels. */
9476 : || 1)
9477 : {
9478 88 : if (ehdr->e_type == ET_CORE)
9479 : {
9480 54 : if (nhdr.n_type == NT_AUXV
9481 8 : && (nhdr.n_namesz == 4 /* Broken old Linux kernels. */
9482 8 : || (nhdr.n_namesz == 5 && name[4] == '\0'))
9483 8 : && !memcmp (name, "CORE", 4))
9484 8 : handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
9485 : start + desc_offset);
9486 46 : else if (nhdr.n_namesz == 5 && strcmp (name, "CORE") == 0)
9487 34 : switch (nhdr.n_type)
9488 : {
9489 5 : case NT_SIGINFO:
9490 5 : handle_siginfo_note (ebl->elf, nhdr.n_descsz,
9491 : start + desc_offset);
9492 : break;
9493 :
9494 5 : case NT_FILE:
9495 5 : handle_file_note (ebl->elf, nhdr.n_descsz,
9496 : start + desc_offset);
9497 : break;
9498 :
9499 24 : default:
9500 24 : handle_core_note (ebl, &nhdr, name, desc);
9501 : }
9502 : else
9503 12 : handle_core_note (ebl, &nhdr, name, desc);
9504 : }
9505 : else
9506 34 : ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc);
9507 : }
9508 : }
9509 :
9510 42 : if (offset == data->d_size)
9511 42 : return;
9512 :
9513 0 : bad_note:
9514 0 : error (EXIT_FAILURE, 0,
9515 0 : gettext ("cannot get content of note section: %s"),
9516 : elf_errmsg (-1));
9517 : }
9518 :
9519 : static void
9520 42 : handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
9521 : {
9522 : /* If we have section headers, just look for SHT_NOTE sections.
9523 : In a debuginfo file, the program headers are not reliable. */
9524 42 : if (shnum != 0)
9525 : {
9526 : /* Get the section header string table index. */
9527 : size_t shstrndx;
9528 33 : if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
9529 : error (EXIT_FAILURE, 0,
9530 0 : gettext ("cannot get section header string table index"));
9531 :
9532 : Elf_Scn *scn = NULL;
9533 919 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
9534 : {
9535 : GElf_Shdr shdr_mem;
9536 886 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
9537 :
9538 886 : if (shdr == NULL || shdr->sh_type != SHT_NOTE)
9539 : /* Not what we are looking for. */
9540 853 : continue;
9541 :
9542 99 : printf (gettext ("\
9543 : \nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
9544 : elf_ndxscn (scn),
9545 33 : elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
9546 : shdr->sh_size, shdr->sh_offset);
9547 :
9548 33 : handle_notes_data (ebl, ehdr, shdr->sh_offset,
9549 : elf_getdata (scn, NULL));
9550 : }
9551 : return;
9552 : }
9553 :
9554 : /* We have to look through the program header to find the note
9555 : sections. There can be more than one. */
9556 102 : for (size_t cnt = 0; cnt < phnum; ++cnt)
9557 : {
9558 : GElf_Phdr mem;
9559 102 : GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
9560 :
9561 102 : if (phdr == NULL || phdr->p_type != PT_NOTE)
9562 : /* Not what we are looking for. */
9563 93 : continue;
9564 :
9565 18 : printf (gettext ("\
9566 : \nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
9567 : phdr->p_filesz, phdr->p_offset);
9568 :
9569 18 : handle_notes_data (ebl, ehdr, phdr->p_offset,
9570 : elf_getdata_rawchunk (ebl->elf,
9571 9 : phdr->p_offset, phdr->p_filesz,
9572 : ELF_T_NHDR));
9573 : }
9574 : }
9575 :
9576 :
9577 : static void
9578 5 : hex_dump (const uint8_t *data, size_t len)
9579 : {
9580 5 : size_t pos = 0;
9581 31 : while (pos < len)
9582 : {
9583 21 : printf (" 0x%08zx ", pos);
9584 :
9585 21 : const size_t chunk = MIN (len - pos, 16);
9586 :
9587 342 : for (size_t i = 0; i < chunk; ++i)
9588 321 : if (i % 4 == 3)
9589 80 : printf ("%02x ", data[pos + i]);
9590 : else
9591 241 : printf ("%02x", data[pos + i]);
9592 :
9593 21 : if (chunk < 16)
9594 1 : printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
9595 :
9596 321 : for (size_t i = 0; i < chunk; ++i)
9597 : {
9598 321 : unsigned char b = data[pos + i];
9599 642 : printf ("%c", isprint (b) ? b : '.');
9600 : }
9601 :
9602 21 : putchar ('\n');
9603 21 : pos += chunk;
9604 : }
9605 5 : }
9606 :
9607 : static void
9608 5 : dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
9609 : {
9610 5 : if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
9611 0 : printf (gettext ("\nSection [%zu] '%s' has no data to dump.\n"),
9612 : elf_ndxscn (scn), name);
9613 : else
9614 : {
9615 5 : if (print_decompress)
9616 : {
9617 : /* We try to decompress the section, but keep the old shdr around
9618 : so we can show both the original shdr size and the uncompressed
9619 : data size. */
9620 4 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
9621 : {
9622 2 : if (elf_compress (scn, 0, 0) < 0)
9623 0 : printf ("WARNING: %s [%zd]\n",
9624 : gettext ("Couldn't uncompress section"),
9625 : elf_ndxscn (scn));
9626 : }
9627 2 : else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
9628 : {
9629 2 : if (elf_compress_gnu (scn, 0, 0) < 0)
9630 0 : printf ("WARNING: %s [%zd]\n",
9631 : gettext ("Couldn't uncompress section"),
9632 : elf_ndxscn (scn));
9633 : }
9634 : }
9635 :
9636 5 : Elf_Data *data = elf_rawdata (scn, NULL);
9637 5 : if (data == NULL)
9638 0 : error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
9639 : elf_ndxscn (scn), name, elf_errmsg (-1));
9640 : else
9641 : {
9642 5 : if (data->d_size == shdr->sh_size)
9643 1 : printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
9644 : " bytes at offset %#0" PRIx64 ":\n"),
9645 : elf_ndxscn (scn), name,
9646 : shdr->sh_size, shdr->sh_offset);
9647 : else
9648 4 : printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
9649 : " bytes (%zd uncompressed) at offset %#0"
9650 : PRIx64 ":\n"),
9651 : elf_ndxscn (scn), name,
9652 : shdr->sh_size, data->d_size, shdr->sh_offset);
9653 5 : hex_dump (data->d_buf, data->d_size);
9654 : }
9655 : }
9656 5 : }
9657 :
9658 : static void
9659 75 : print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
9660 : {
9661 75 : if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
9662 0 : printf (gettext ("\nSection [%zu] '%s' has no strings to dump.\n"),
9663 : elf_ndxscn (scn), name);
9664 : else
9665 : {
9666 75 : if (print_decompress)
9667 : {
9668 : /* We try to decompress the section, but keep the old shdr around
9669 : so we can show both the original shdr size and the uncompressed
9670 : data size. */
9671 1 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
9672 : {
9673 0 : if (elf_compress (scn, 0, 0) < 0)
9674 0 : printf ("WARNING: %s [%zd]\n",
9675 : gettext ("Couldn't uncompress section"),
9676 : elf_ndxscn (scn));
9677 : }
9678 1 : else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
9679 : {
9680 1 : if (elf_compress_gnu (scn, 0, 0) < 0)
9681 0 : printf ("WARNING: %s [%zd]\n",
9682 : gettext ("Couldn't uncompress section"),
9683 : elf_ndxscn (scn));
9684 : }
9685 : }
9686 :
9687 75 : Elf_Data *data = elf_rawdata (scn, NULL);
9688 75 : if (data == NULL)
9689 0 : error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
9690 : elf_ndxscn (scn), name, elf_errmsg (-1));
9691 : else
9692 : {
9693 75 : if (data->d_size == shdr->sh_size)
9694 74 : printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
9695 : " bytes at offset %#0" PRIx64 ":\n"),
9696 : elf_ndxscn (scn), name,
9697 : shdr->sh_size, shdr->sh_offset);
9698 : else
9699 1 : printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
9700 : " bytes (%zd uncompressed) at offset %#0"
9701 : PRIx64 ":\n"),
9702 : elf_ndxscn (scn), name,
9703 : shdr->sh_size, data->d_size, shdr->sh_offset);
9704 :
9705 75 : const char *start = data->d_buf;
9706 75 : const char *const limit = start + data->d_size;
9707 : do
9708 : {
9709 16349 : const char *end = memchr (start, '\0', limit - start);
9710 16349 : const size_t pos = start - (const char *) data->d_buf;
9711 16349 : if (unlikely (end == NULL))
9712 : {
9713 0 : printf (" [%6zx]- %.*s\n",
9714 : pos, (int) (limit - start), start);
9715 : break;
9716 : }
9717 16349 : printf (" [%6zx] %s\n", pos, start);
9718 16349 : start = end + 1;
9719 16349 : } while (start < limit);
9720 : }
9721 : }
9722 75 : }
9723 :
9724 : static void
9725 38 : for_each_section_argument (Elf *elf, const struct section_argument *list,
9726 : void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
9727 : const char *name))
9728 : {
9729 : /* Get the section header string table index. */
9730 : size_t shstrndx;
9731 38 : if (elf_getshdrstrndx (elf, &shstrndx) < 0)
9732 : error (EXIT_FAILURE, 0,
9733 0 : gettext ("cannot get section header string table index"));
9734 :
9735 102 : for (const struct section_argument *a = list; a != NULL; a = a->next)
9736 : {
9737 : Elf_Scn *scn;
9738 : GElf_Shdr shdr_mem;
9739 102 : const char *name = NULL;
9740 :
9741 102 : char *endp = NULL;
9742 102 : unsigned long int shndx = strtoul (a->arg, &endp, 0);
9743 102 : if (endp != a->arg && *endp == '\0')
9744 : {
9745 0 : scn = elf_getscn (elf, shndx);
9746 0 : if (scn == NULL)
9747 : {
9748 0 : error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
9749 0 : continue;
9750 : }
9751 :
9752 0 : if (gelf_getshdr (scn, &shdr_mem) == NULL)
9753 0 : error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
9754 : elf_errmsg (-1));
9755 0 : name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
9756 : }
9757 : else
9758 : {
9759 : /* Need to look up the section by name. */
9760 : scn = NULL;
9761 : bool found = false;
9762 2778 : while ((scn = elf_nextscn (elf, scn)) != NULL)
9763 : {
9764 2676 : if (gelf_getshdr (scn, &shdr_mem) == NULL)
9765 0 : continue;
9766 2676 : name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
9767 2676 : if (name == NULL)
9768 0 : continue;
9769 2676 : if (!strcmp (name, a->arg))
9770 : {
9771 80 : found = true;
9772 80 : (*dump) (scn, &shdr_mem, name);
9773 : }
9774 : }
9775 :
9776 102 : if (unlikely (!found) && !a->implicit)
9777 0 : error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
9778 : }
9779 : }
9780 38 : }
9781 :
9782 : static void
9783 : dump_data (Ebl *ebl)
9784 : {
9785 5 : for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
9786 : }
9787 :
9788 : static void
9789 : dump_strings (Ebl *ebl)
9790 : {
9791 33 : for_each_section_argument (ebl->elf, string_sections, &print_string_section);
9792 : }
9793 :
9794 : static void
9795 0 : print_strings (Ebl *ebl)
9796 : {
9797 : /* Get the section header string table index. */
9798 : size_t shstrndx;
9799 0 : if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
9800 : error (EXIT_FAILURE, 0,
9801 0 : gettext ("cannot get section header string table index"));
9802 :
9803 : Elf_Scn *scn;
9804 : GElf_Shdr shdr_mem;
9805 : const char *name;
9806 : scn = NULL;
9807 0 : while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
9808 : {
9809 0 : if (gelf_getshdr (scn, &shdr_mem) == NULL)
9810 0 : continue;
9811 :
9812 0 : if (shdr_mem.sh_type != SHT_PROGBITS
9813 0 : || !(shdr_mem.sh_flags & SHF_STRINGS))
9814 0 : continue;
9815 :
9816 0 : name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
9817 0 : if (name == NULL)
9818 0 : continue;
9819 :
9820 0 : print_string_section (scn, &shdr_mem, name);
9821 : }
9822 0 : }
9823 :
9824 : static void
9825 2 : dump_archive_index (Elf *elf, const char *fname)
9826 : {
9827 : size_t narsym;
9828 2 : const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
9829 2 : if (arsym == NULL)
9830 : {
9831 0 : int result = elf_errno ();
9832 0 : if (unlikely (result != ELF_E_NO_INDEX))
9833 0 : error (EXIT_FAILURE, 0,
9834 0 : gettext ("cannot get symbol index of archive '%s': %s"),
9835 : fname, elf_errmsg (result));
9836 : else
9837 0 : printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
9838 0 : return;
9839 : }
9840 :
9841 4 : printf (gettext ("\nIndex of archive '%s' has %zu entries:\n"),
9842 : fname, narsym);
9843 :
9844 2 : size_t as_off = 0;
9845 11 : for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
9846 : {
9847 9 : if (s->as_off != as_off)
9848 : {
9849 6 : as_off = s->as_off;
9850 :
9851 6 : Elf *subelf = NULL;
9852 6 : if (unlikely (elf_rand (elf, as_off) == 0)
9853 6 : || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
9854 : == NULL))
9855 : #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
9856 : while (1)
9857 : #endif
9858 0 : error (EXIT_FAILURE, 0,
9859 0 : gettext ("cannot extract member at offset %zu in '%s': %s"),
9860 : as_off, fname, elf_errmsg (-1));
9861 :
9862 6 : const Elf_Arhdr *h = elf_getarhdr (subelf);
9863 :
9864 12 : printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
9865 :
9866 6 : elf_end (subelf);
9867 : }
9868 :
9869 18 : printf ("\t%s\n", s->as_name);
9870 : }
9871 : }
9872 :
9873 : #include "debugpred.h"
|