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