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