1 /* Print information from ELF file in human-readable form.
2 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
3 Written by Ulrich Drepper <drepper@redhat.com>, 1999.
4
5 This program is Open Source software; you can redistribute it and/or
6 modify it under the terms of the Open Software License version 1.0 as
7 published by the Open Source Initiative.
8
9 You should have received a copy of the Open Software License along
10 with this program; if not, you may obtain a copy of the Open Software
11 License version 1.0 from http://www.opensource.org/licenses/osl.php or
12 by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13 3001 King Ranch Road, Ukiah, CA 95482. */
14
15 #ifdef HAVE_CONFIG_H
16 # include <config.h>
17 #endif
18
19 #include <argp.h>
20 #include <assert.h>
21 #include <dwarf.h>
22 #include <errno.h>
23 #include <error.h>
24 #include <fcntl.h>
25 #include <gelf.h>
26 #include <inttypes.h>
27 #include <langinfo.h>
28 #include <libdw.h>
29 #include <libebl.h>
30 #include <libintl.h>
31 #include <locale.h>
32 #include <stdbool.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <time.h>
36 #include <unistd.h>
37 #include <sys/param.h>
38
39 #include <system.h>
40 #include "../libdw/libdwP.h"
41 #include "../libdw/memory-access.h"
42
43
44 /* Name and version of program. */
45 static void print_version (FILE *stream, struct argp_state *state);
46 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
47
48 /* Definitions of arguments for argp functions. */
49 static const struct argp_option options[] =
50 {
51 { NULL, 0, NULL, 0, N_("Output selection:") },
52 { "all", 'a', NULL, 0, N_("Equivalent to: -h -l") },
53 { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment") },
54 { "file-header", 'h', NULL, 0, N_("Display the ELF file header") },
55 { "histogram", 'I', NULL, 0,
56 N_("Display histogram of bucket list lengths") },
57 { "program-headers", 'l', NULL, 0, N_("Display the program headers") },
58 { "relocs", 'r', NULL, 0, N_("Display relocations") },
59 { "section-headers", 'S', NULL, 0, N_("Display the sections' header") },
60 { "symbols", 's', NULL, 0, N_("Display the symbol table") },
61 { "version-info", 'V', NULL, 0, N_("Display versioning information") },
62 { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
63 N_("Display DWARF section content. SECTION can be one of abbrev, "
64 "aranges, frame, info, loc, line, pubnames, str, or macinfo.") },
65 { "notes", 'n', NULL, 0, N_("Display the core notes") },
66 { "arch-specific", 'A', NULL, 0,
67 N_("Display architecture specific information (if any)") },
68
69 { NULL, 0, NULL, 0, N_("Output control:") },
70
71 { NULL, 0, NULL, 0, NULL }
72 };
73
74 /* Short description of program. */
75 static const char doc[] = N_("\
76 Print information from ELF file in human-readable form.");
77
78 /* Strings for arguments in help texts. */
79 static const char args_doc[] = N_("FILE...");
80
81 /* Prototype for option handler. */
82 static error_t parse_opt (int key, char *arg, struct argp_state *state);
83
84 /* Function to print some extra text in the help message. */
85 static char *more_help (int key, const char *text, void *input);
86
87 /* Data structure to communicate with argp functions. */
88 static struct argp argp =
89 {
90 options, parse_opt, args_doc, doc, NULL, more_help
91 };
92
93
94 /* Flags set by the option controlling the output. */
95
96 /* True if any of the control options is set. */
97 static bool any_control_option;
98
99 /* True if dynamic segment should be printed. */
100 static bool print_dynamic_table;
101
102 /* True if the file header should be printed. */
103 static bool print_file_header;
104
105 /* True if the program headers should be printed. */
106 static bool print_program_header;
107
108 /* True if relocations should be printed. */
109 static bool print_relocations;
110
111 /* True if the section headers should be printed. */
112 static bool print_section_header;
113
114 /* True if the symbol table should be printed. */
115 static bool print_symbol_table;
116
117 /* True if the version information should be printed. */
118 static bool print_version_info;
119
120 /* True if section groups should be printed. */
121 static bool print_section_groups;
122
123 /* True if bucket list length histogram should be printed. */
124 static bool print_histogram;
125
126 /* True if the architecture specific data should be printed. */
127 static bool print_arch;
128
129 /* True if note section content should be printed. */
130 static bool print_notes;
131
132 /* Select printing of debugging sections. */
133 static enum section_e
134 {
135 section_abbrev = 1, /* .debug_abbrev */
136 section_aranges = 2, /* .debug_aranges */
137 section_frame = 4, /* .debug_frame or .eh_frame */
138 section_info = 8, /* .debug_info */
139 section_line = 16, /* .debug_line */
140 section_loc = 32, /* .debug_loc */
141 section_pubnames = 64,/* .debug_pubnames */
142 section_str = 128, /* .debug_str */
143 section_macinfo = 256,/* .debug_macinfo */
144 section_all = (section_abbrev | section_aranges | section_frame
145 | section_info | section_line | section_loc
146 | section_pubnames | section_str | section_macinfo)
147 } print_debug_sections;
148
149 /* Number of sections in the file. */
150 static size_t shnum;
151
152
153 /* Declarations of local functions. */
154 static void process_file (int fd, Elf *elf, const char *prefix,
155 const char *fname, bool only_one);
156 static void process_elf_file (Elf *elf, const char *prefix, const char *fname,
157 bool only_one);
158 static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
159 static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
160 static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
161 static void print_scngrp (Ebl *ebl, GElf_Ehdr *ehdr);
162 static void print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr);
163 static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
164 static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
165 GElf_Shdr *shdr);
166 static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
167 GElf_Shdr *shdr);
168 static void print_symtab (Ebl *ebl, GElf_Ehdr *ehdr, int type);
169 static void handle_symtab (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
170 GElf_Shdr *shdr);
171 static void print_verinfo (Ebl *ebl, GElf_Ehdr *ehdr);
172 static void handle_verneed (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
173 GElf_Shdr *shdr);
174 static void handle_verdef (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
175 GElf_Shdr *shdr);
176 static void handle_versym (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
177 GElf_Shdr *shdr);
178 static void print_debug (Ebl *ebl, GElf_Ehdr *ehdr);
179 static void handle_hash (Ebl *ebl, GElf_Ehdr *ehdr);
180 static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
181 static void print_liblist (Ebl *ebl, GElf_Ehdr *ehdr);
182
183
184 int
main(int argc,char * argv[])185 main (int argc, char *argv[])
186 {
187 int remaining;
188 bool only_one;
189
190 /* Set locale. */
191 setlocale (LC_ALL, "");
192
193 /* Initialize the message catalog. */
194 textdomain (PACKAGE);
195
196 /* Parse and process arguments. */
197 argp_parse (&argp, argc, argv, 0, &remaining, NULL);
198
199 /* If no control option or no ELF file is given punt. */
200 if ((any_control_option == 0 && print_debug_sections == 0)
201 || remaining >= argc)
202 {
203 argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
204 program_invocation_short_name);
205 exit (1);
206 }
207
208 /* Before we start tell the ELF library which version we are using. */
209 elf_version (EV_CURRENT);
210
211 /* Now process all the files given at the command line. */
212 only_one = remaining + 1 == argc;
213 do
214 {
215 int fd;
216 Elf *elf;
217
218 /* Open the file. */
219 fd = open (argv[remaining], O_RDONLY);
220 if (fd == -1)
221 {
222 error (0, errno, gettext ("cannot open input file"));
223 continue;
224 }
225
226 /* Create an `Elf' descriptor. */
227 elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
228 if (elf == NULL)
229 error (0, 0, gettext ("cannot generate Elf descriptor: %s\n"),
230 elf_errmsg (-1));
231 else
232 {
233 process_file (fd, elf, NULL, argv[remaining], only_one);
234
235 /* Now we can close the descriptor. */
236 if (elf_end (elf) != 0)
237 error (0, 0, gettext ("error while closing Elf descriptor: %s"),
238 elf_errmsg (-1));
239 }
240
241 close (fd);
242 }
243 while (++remaining < argc);
244
245 return error_message_count != 0;
246 }
247
248
249 /* Handle program arguments. */
250 static error_t
parse_opt(int key,char * arg,struct argp_state * state)251 parse_opt (int key, char *arg, struct argp_state *state)
252 {
253 switch (key)
254 {
255 case 'a':
256 print_file_header = true;
257 print_program_header = true;
258 print_relocations = true;
259 print_section_header = true;
260 print_symbol_table = true;
261 print_version_info = true;
262 print_dynamic_table = true;
263 print_section_groups = true;
264 print_histogram = true;
265 print_arch = true;
266 print_notes = true;
267 any_control_option = true;
268 break;
269 case 'A':
270 print_arch = true;
271 any_control_option = true;
272 break;
273 case 'd':
274 print_dynamic_table = true;
275 any_control_option = true;
276 break;
277 case 'g':
278 print_section_groups = true;
279 any_control_option = true;
280 break;
281 case 'h':
282 print_file_header = true;
283 any_control_option = true;
284 break;
285 case 'I':
286 print_histogram = true;
287 any_control_option = true;
288 break;
289 case 'l':
290 print_program_header = true;
291 any_control_option = true;
292 break;
293 case 'n':
294 print_notes = true;
295 any_control_option = true;
296 break;
297 case 'r':
298 print_relocations = true;
299 any_control_option = true;
300 break;
301 case 'S':
302 print_section_header = true;
303 any_control_option = true;
304 break;
305 case 's':
306 print_symbol_table = true;
307 any_control_option = true;
308 break;
309 case 'V':
310 print_version_info = true;
311 any_control_option = true;
312 break;
313 case 'w':
314 if (arg == NULL)
315 print_debug_sections = section_all;
316 else if (strcmp (arg, "abbrev") == 0)
317 print_debug_sections |= section_abbrev;
318 else if (strcmp (arg, "aranges") == 0)
319 print_debug_sections |= section_aranges;
320 else if (strcmp (arg, "frame") == 0)
321 print_debug_sections |= section_frame;
322 else if (strcmp (arg, "info") == 0)
323 print_debug_sections |= section_info;
324 else if (strcmp (arg, "loc") == 0)
325 print_debug_sections |= section_loc;
326 else if (strcmp (arg, "line") == 0)
327 print_debug_sections |= section_line;
328 else if (strcmp (arg, "pubnames") == 0)
329 print_debug_sections |= section_pubnames;
330 else if (strcmp (arg, "str") == 0)
331 print_debug_sections |= section_str;
332 else if (strcmp (arg, "macinfo") == 0)
333 print_debug_sections |= section_macinfo;
334 else
335 {
336 fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
337 arg);
338 argp_help (&argp, stderr, ARGP_HELP_SEE,
339 program_invocation_short_name);
340 exit (1);
341 }
342 break;
343 default:
344 return ARGP_ERR_UNKNOWN;
345 }
346 return 0;
347 }
348
349
350 static char *
more_help(int key,const char * text,void * input)351 more_help (int key, const char *text, void *input)
352 {
353 char *buf;
354
355 switch (key)
356 {
357 case ARGP_KEY_HELP_EXTRA:
358 /* We print some extra information. */
359 if (asprintf (&buf, gettext ("Please report bugs to %s.\n"),
360 PACKAGE_BUGREPORT) < 0)
361 buf = NULL;
362 return buf;
363
364 default:
365 break;
366 }
367 return (char *) text;
368 }
369
370
371 /* Print the version information. */
372 static void
print_version(FILE * stream,struct argp_state * state)373 print_version (FILE *stream, struct argp_state *state)
374 {
375 fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, VERSION);
376 fprintf (stream, gettext ("\
377 Copyright (C) %s Red Hat, Inc.\n\
378 This is free software; see the source for copying conditions. There is NO\n\
379 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
380 "), "2004");
381 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
382 }
383
384
385 /* Process one file. */
386 static void
process_file(int fd,Elf * elf,const char * prefix,const char * fname,bool only_one)387 process_file (int fd, Elf *elf, const char *prefix, const char *fname,
388 bool only_one)
389 {
390 /* We can handle two types of files: ELF files and archives. */
391 Elf_Kind kind = elf_kind (elf);
392 struct stat64 st;
393
394 switch (kind)
395 {
396 case ELF_K_ELF:
397 /* Yes! It's an ELF file. */
398 process_elf_file (elf, prefix, fname, only_one);
399 break;
400
401 case ELF_K_AR:
402 {
403 Elf *subelf;
404 Elf_Cmd cmd = ELF_C_READ_MMAP;
405 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
406 size_t fname_len = strlen (fname) + 1;
407 char new_prefix[prefix_len + 1 + fname_len];
408 char *cp = new_prefix;
409
410 /* Create the full name of the file. */
411 if (prefix != NULL)
412 {
413 cp = mempcpy (cp, prefix, prefix_len);
414 *cp++ = ':';
415 }
416 memcpy (cp, fname, fname_len);
417
418 /* It's an archive. We process each file in it. */
419 while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
420 {
421 kind = elf_kind (subelf);
422
423 /* Call this function recursively. */
424 if (kind == ELF_K_ELF || kind == ELF_K_AR)
425 {
426 Elf_Arhdr *arhdr = elf_getarhdr (subelf);
427 assert (arhdr != NULL);
428
429 process_file (fd, subelf, new_prefix, arhdr->ar_name, false);
430 }
431
432 /* Get next archive element. */
433 cmd = elf_next (subelf);
434 if (elf_end (subelf) != 0)
435 error (0, 0,
436 gettext (" error while freeing sub-ELF descriptor: %s\n"),
437 elf_errmsg (-1));
438 }
439 }
440 break;
441
442 default:
443 if (fstat64 (fd, &st) != 0)
444 error (0, errno, gettext ("cannot stat input file"));
445 else if (st.st_size == 0)
446 error (0, 0, gettext ("input file is empty"));
447 else
448 /* We cannot do anything. */
449 error (0, 0, gettext ("\
450 Not an ELF file - it has the wrong magic bytes at the start"));
451 break;
452 }
453 }
454
455
456 /* Process one file. */
457 static void
process_elf_file(Elf * elf,const char * prefix,const char * fname,bool only_one)458 process_elf_file (Elf *elf, const char *prefix, const char *fname,
459 bool only_one)
460 {
461 GElf_Ehdr ehdr_mem;
462 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
463 Ebl *ebl;
464
465 /* Print the file name. */
466 if (!only_one)
467 {
468 if (prefix != NULL)
469 printf ("\n%s(%s):\n\n", prefix, fname);
470 else
471 printf ("\n%s:\n\n", fname);
472 }
473
474 if (ehdr == NULL)
475 {
476 error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
477 return;
478 }
479
480 ebl = ebl_openbackend (elf);
481 if (ebl == NULL)
482 {
483 error (0, errno, gettext ("cannot create EBL handle"));
484 return;
485 }
486
487 /* Determine the number of sections. */
488 if (elf_getshnum (ebl->elf, &shnum) < 0)
489 error (EXIT_FAILURE, 0,
490 gettext ("cannot determine number of sections: %s"),
491 elf_errmsg (-1));
492
493 if (print_file_header)
494 print_ehdr (ebl, ehdr);
495 if (print_section_header)
496 print_shdr (ebl, ehdr);
497 if (print_program_header)
498 print_phdr (ebl, ehdr);
499 if (print_section_groups)
500 print_scngrp (ebl, ehdr);
501 if (print_dynamic_table)
502 print_dynamic (ebl, ehdr);
503 if (print_relocations)
504 print_relocs (ebl, ehdr);
505 if (print_histogram)
506 handle_hash (ebl, ehdr);
507 if (print_symbol_table)
508 print_symtab (ebl, ehdr, SHT_DYNSYM);
509 if (print_version_info)
510 print_verinfo (ebl, ehdr);
511 if (print_symbol_table)
512 print_symtab (ebl, ehdr, SHT_SYMTAB);
513 if (print_arch)
514 print_liblist (ebl, ehdr);
515 if (print_debug_sections != 0)
516 print_debug (ebl, ehdr);
517 if (print_notes)
518 handle_notes (ebl, ehdr);
519
520 ebl_closebackend (ebl);
521 }
522
523
524 /* Print file type. */
525 static void
print_file_type(unsigned short int e_type)526 print_file_type (unsigned short int e_type)
527 {
528 if (e_type <= ET_CORE)
529 {
530 static const char *knowntypes[] =
531 {
532 N_("NONE (None)"),
533 N_("REL (Relocatable file)"),
534 N_("EXEC (Executable file)"),
535 N_("DYN (Shared object file)"),
536 N_("CORE (Core file)")
537 };
538 puts (gettext (knowntypes[e_type]));
539 }
540 else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
541 printf (gettext ("OS Specific: (%x)\n"), e_type);
542 else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
543 printf (gettext ("Processor Specific: (%x)\n"), e_type);
544 else
545 puts ("???");
546 }
547
548
549 /* Print ELF header. */
550 static void
print_ehdr(Ebl * ebl,GElf_Ehdr * ehdr)551 print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
552 {
553 char buf[512];
554 size_t cnt;
555
556 fputs_unlocked (gettext ("ELF Header:\n Magic: "), stdout);
557 for (cnt = 0; cnt < EI_NIDENT; ++cnt)
558 printf (" %02hhx", ehdr->e_ident[cnt]);
559
560 printf (gettext ("\n Class: %s\n"),
561 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
562 : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
563 : "\?\?\?");
564
565 printf (gettext (" Data: %s\n"),
566 ehdr->e_ident[EI_DATA] == ELFDATA2LSB
567 ? "2's complement, little endian"
568 : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
569 ? "2's complement, big endian" : "\?\?\?");
570
571 printf (gettext (" Version: %hhd %s\n"),
572 ehdr->e_ident[EI_VERSION],
573 ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
574 : "(\?\?\?)");
575
576 printf (gettext (" OS/ABI: %s\n"),
577 ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
578
579 printf (gettext (" ABI Version: %hhd\n"),
580 ehdr->e_ident[EI_ABIVERSION]);
581
582 fputs_unlocked (gettext (" Type: "), stdout);
583 print_file_type (ehdr->e_type);
584
585 printf (gettext (" Machine: %s\n"), ebl->name);
586
587 printf (gettext (" Version: %d %s\n"),
588 ehdr->e_version,
589 ehdr->e_version == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
590
591 printf (gettext (" Entry point address: %#" PRIx64 "\n"),
592 ehdr->e_entry);
593
594 printf (gettext (" Start of program headers: %" PRId64 " %s\n"),
595 ehdr->e_phoff, gettext ("(bytes into file)"));
596
597 printf (gettext (" Start of section headers: %" PRId64 " %s\n"),
598 ehdr->e_shoff, gettext ("(bytes into file)"));
599
600 printf (gettext (" Flags: %s\n"),
601 ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
602
603 printf (gettext (" Size of this header: %" PRId16 " %s\n"),
604 ehdr->e_ehsize, gettext ("(bytes)"));
605
606 printf (gettext (" Size of program header entries: %" PRId16 " %s\n"),
607 ehdr->e_phentsize, gettext ("(bytes)"));
608
609 printf (gettext (" Number of program headers entries: %" PRId16 "\n"),
610 ehdr->e_phnum);
611
612 printf (gettext (" Size of section header entries: %" PRId16 " %s\n"),
613 ehdr->e_shentsize, gettext ("(bytes)"));
614
615 printf (gettext (" Number of section headers entries: %" PRId16),
616 ehdr->e_shnum);
617 if (ehdr->e_shnum == 0)
618 {
619 GElf_Shdr shdr_mem;
620 GElf_Shdr *shdr;
621
622 shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
623 if (shdr != NULL)
624 printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
625 (uint32_t) shdr->sh_size);
626 else
627 fputs_unlocked (gettext (" ([0] not available)"), stdout);
628 }
629 fputc_unlocked ('\n', stdout);
630
631 if (ehdr->e_shstrndx == SHN_XINDEX)
632 {
633 GElf_Shdr shdr_mem;
634 GElf_Shdr *shdr;
635
636 shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
637 if (shdr != NULL)
638 /* We managed to get the zeroth section. */
639 snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
640 (uint32_t) shdr->sh_link);
641 else
642 {
643 strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
644 buf[sizeof (buf) - 1] = '\0';
645 }
646
647 printf (gettext (" Section header string table index: XINDEX%s\n\n"),
648 buf);
649 }
650 else
651 printf (gettext (" Section header string table index: %" PRId16 "\n\n"),
652 ehdr->e_shstrndx);
653 }
654
655
656 static const char *
get_visibility_type(int value)657 get_visibility_type (int value)
658 {
659 switch (value)
660 {
661 case STV_DEFAULT:
662 return "DEFAULT";
663 case STV_INTERNAL:
664 return "INTERNAL";
665 case STV_HIDDEN:
666 return "HIDDEN";
667 case STV_PROTECTED:
668 return "PROTECTED";
669 default:
670 return "???";
671 }
672 }
673
674
675 /* Print the section headers. */
676 static void
print_shdr(Ebl * ebl,GElf_Ehdr * ehdr)677 print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
678 {
679 size_t cnt;
680 size_t shstrndx;
681
682 if (! print_file_header)
683 printf (gettext ("\
684 There are %d section headers, starting at offset %#" PRIx64 ":\n\
685 \n"),
686 ehdr->e_shnum, ehdr->e_shoff);
687
688 /* Get the section header string table index. */
689 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
690 error (EXIT_FAILURE, 0,
691 gettext ("cannot get section header string table index"));
692
693 puts (gettext ("Section Headers:"));
694
695 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
696 puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
697 else
698 puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
699
700 for (cnt = 0; cnt < shnum; ++cnt)
701 {
702 char buf[128];
703 char flagbuf[20];
704 char *cp;
705 Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
706 GElf_Shdr shdr_mem;
707 GElf_Shdr *shdr;
708
709 if (scn == NULL)
710 error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
711 elf_errmsg (-1));
712
713 /* Get the section header. */
714 shdr = gelf_getshdr (scn, &shdr_mem);
715 if (shdr == NULL)
716 error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
717 elf_errmsg (-1));
718
719 cp = flagbuf;
720 if (shdr->sh_flags & SHF_WRITE)
721 *cp++ = 'W';
722 if (shdr->sh_flags & SHF_ALLOC)
723 *cp++ = 'A';
724 if (shdr->sh_flags & SHF_EXECINSTR)
725 *cp++ = 'X';
726 if (shdr->sh_flags & SHF_MERGE)
727 *cp++ = 'M';
728 if (shdr->sh_flags & SHF_STRINGS)
729 *cp++ = 'S';
730 if (shdr->sh_flags & SHF_INFO_LINK)
731 *cp++ = 'I';
732 if (shdr->sh_flags & SHF_LINK_ORDER)
733 *cp++ = 'L';
734 if (shdr->sh_flags & SHF_OS_NONCONFORMING)
735 *cp++ = 'N';
736 if (shdr->sh_flags & SHF_GROUP)
737 *cp++ = 'G';
738 if (shdr->sh_flags & SHF_TLS)
739 *cp++ = 'T';
740 if (shdr->sh_flags & SHF_ORDERED)
741 *cp++ = 'O';
742 if (shdr->sh_flags & SHF_EXCLUDE)
743 *cp++ = 'E';
744 *cp = '\0';
745
746 printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
747 " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
748 " %2" PRId64 "\n",
749 cnt,
750 elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
751 ?: "<corrupt>",
752 ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
753 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
754 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
755 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
756 shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
757 shdr->sh_addralign);
758 }
759
760 fputc_unlocked ('\n', stdout);
761 }
762
763
764 /* Print the program header. */
765 static void
print_phdr(Ebl * ebl,GElf_Ehdr * ehdr)766 print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
767 {
768 size_t cnt;
769 size_t shstrndx;
770
771 if (ehdr->e_phnum == 0)
772 /* No program header, this is OK in relocatable objects. */
773 return;
774
775 puts (gettext ("Program Headers:"));
776 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
777 puts (gettext ("\
778 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
779 else
780 puts (gettext ("\
781 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
782
783 /* Process all program headers. */
784 bool has_relro = false;
785 GElf_Addr relro_from = 0;
786 GElf_Addr relro_to = 0;
787 for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
788 {
789 char buf[128];
790 GElf_Phdr mem;
791 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
792
793 /* If for some reason the header cannot be returned show this. */
794 if (phdr == NULL)
795 {
796 puts (" ???");
797 continue;
798 }
799
800 printf (" %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
801 " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
802 ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
803 phdr->p_offset,
804 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
805 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
806 phdr->p_filesz,
807 phdr->p_memsz,
808 phdr->p_flags & PF_R ? 'R' : ' ',
809 phdr->p_flags & PF_W ? 'W' : ' ',
810 phdr->p_flags & PF_X ? 'E' : ' ',
811 phdr->p_align);
812
813 if (phdr->p_type == PT_INTERP)
814 {
815 /* We can show the user the name of the interpreter. */
816 size_t maxsize;
817 char *filedata = elf_rawfile (ebl->elf, &maxsize);
818
819 if (filedata != NULL && phdr->p_offset < maxsize)
820 printf (gettext ("\t[Requesting program interpreter: %s]\n"),
821 filedata + phdr->p_offset);
822 }
823 else if (phdr->p_type == PT_GNU_RELRO)
824 {
825 has_relro = true;
826 relro_from = phdr->p_vaddr;
827 relro_to = relro_from + phdr->p_memsz;
828 }
829 }
830
831 /* Get the section header string table index. */
832 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
833 error (EXIT_FAILURE, 0,
834 gettext ("cannot get section header string table index"));
835
836 puts (gettext ("\n Section to Segment mapping:\n Segment Sections..."));
837
838 for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
839 {
840 GElf_Phdr phdr_mem;
841 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
842 size_t inner;
843
844 /* Print the segment number. */
845 printf (" %2.2zu ", cnt);
846
847 /* This must not happen. */
848 if (phdr == NULL)
849 error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
850 elf_errmsg (-1));
851
852 /* Iterate over the sections. */
853 bool in_relro = false;
854 for (inner = 1; inner < shnum; ++inner)
855 {
856 Elf_Scn *scn = elf_getscn (ebl->elf, inner);
857 GElf_Shdr shdr_mem;
858 GElf_Shdr *shdr;
859
860 /* It should not happen. */
861 if (scn == NULL)
862 error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
863 elf_errmsg (-1));
864
865 /* Get the section header. */
866 shdr = gelf_getshdr (scn, &shdr_mem);
867 if (shdr == NULL)
868 error (EXIT_FAILURE, 0,
869 gettext ("cannot get section header: %s"),
870 elf_errmsg (-1));
871
872 if (shdr->sh_size > 0
873 /* Compare allocated sections by VMA, unallocated
874 sections by file offset. */
875 && (shdr->sh_flags & SHF_ALLOC
876 ? (shdr->sh_addr >= phdr->p_vaddr
877 && (shdr->sh_addr + shdr->sh_size
878 <= phdr->p_vaddr + phdr->p_memsz))
879 : (shdr->sh_offset >= phdr->p_offset
880 && (shdr->sh_offset + shdr->sh_size
881 <= phdr->p_offset + phdr->p_filesz))))
882 {
883 if (has_relro && !in_relro
884 && shdr->sh_addr >= relro_from
885 && shdr->sh_addr + shdr->sh_size <= relro_to)
886 {
887 fputs_unlocked (" [RELRO:", stdout);
888 in_relro = true;
889 }
890 else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
891 {
892 fputs_unlocked ("]", stdout);
893 in_relro = false;
894 }
895 else if (has_relro && in_relro
896 && shdr->sh_addr + shdr->sh_size > relro_to)
897 fputs_unlocked ("] <RELRO:", stdout);
898
899 printf (" %s",
900 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
901
902 /* Signal that this sectin is only partially covered. */
903 if (has_relro && in_relro
904 && shdr->sh_addr + shdr->sh_size > relro_to)
905 {
906 fputs_unlocked (">", stdout);
907 in_relro = false;
908 }
909 }
910 }
911 if (in_relro)
912 fputs_unlocked ("]", stdout);
913
914 /* Finish the line. */
915 fputc_unlocked ('\n', stdout);
916 }
917 }
918
919
920 static void
handle_scngrp(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)921 handle_scngrp (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
922 {
923 Elf_Data *data;
924 Elf32_Word *grpref;
925 Elf_Scn *symscn;
926 GElf_Shdr symshdr_mem;
927 GElf_Shdr *symshdr;
928 Elf_Data *symdata;
929 GElf_Sym sym_mem;
930 size_t cnt;
931 size_t shstrndx;
932
933 /* Get the data of the section. */
934 data = elf_getdata (scn, NULL);
935
936 symscn = elf_getscn (ebl->elf, shdr->sh_link);
937 symshdr = gelf_getshdr (symscn, &symshdr_mem);
938 symdata = elf_getdata (symscn, NULL);
939
940 if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
941 || symdata == NULL)
942 return;
943
944 /* Get the section header string table index. */
945 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
946 error (EXIT_FAILURE, 0,
947 gettext ("cannot get section header string table index"));
948
949 grpref = (Elf32_Word *) data->d_buf;
950
951 printf ((grpref[0] & GRP_COMDAT)
952 ? ngettext ("\
953 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
954 "\
955 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
956 data->d_size / sizeof (Elf32_Word) - 1)
957 : ngettext ("\
958 \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
959 \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
960 data->d_size / sizeof (Elf32_Word) - 1),
961 elf_ndxscn (scn),
962 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
963 elf_strptr (ebl->elf, symshdr->sh_link,
964 gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name)
965 ?: gettext ("<INVALID SYMBOL>"),
966 data->d_size / sizeof (Elf32_Word) - 1);
967
968 for (cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
969 {
970 GElf_Shdr grpshdr_mem;
971 GElf_Shdr *grpshdr;
972
973 grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
974 &grpshdr_mem);
975
976 if (grpshdr == NULL)
977 printf (gettext (" [%2u] <INVALID SECTION>\n"), grpref[cnt]);
978 else
979 printf (" [%2u] %s\n",
980 grpref[cnt],
981 elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name)
982 ?: gettext ("<INVALID SECTION>"));
983 }
984 }
985
986
987 static void
print_scngrp(Ebl * ebl,GElf_Ehdr * ehdr)988 print_scngrp (Ebl *ebl, GElf_Ehdr *ehdr)
989 {
990 /* Find all relocation sections and handle them. */
991 Elf_Scn *scn = NULL;
992
993 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
994 {
995 /* Handle the section if it is a symbol table. */
996 GElf_Shdr shdr_mem;
997 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
998
999 if (shdr != NULL && shdr->sh_type == SHT_GROUP)
1000 handle_scngrp (ebl, ehdr, scn, shdr);
1001 }
1002 }
1003
1004
1005 static const struct flags
1006 {
1007 int mask;
1008 const char *str;
1009 } dt_flags[] =
1010 {
1011 { DF_ORIGIN, "ORIGIN" },
1012 { DF_SYMBOLIC, "SYMBOLIC" },
1013 { DF_TEXTREL, "TEXTREL" },
1014 { DF_BIND_NOW, "BIND_NOW" },
1015 { DF_STATIC_TLS, "STATIC_TLS" }
1016 };
1017 static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
1018
1019 static const struct flags dt_flags_1[] =
1020 {
1021 { DF_1_NOW, "NOW" },
1022 { DF_1_GLOBAL, "GLOBAL" },
1023 { DF_1_GROUP, "GROUP" },
1024 { DF_1_NODELETE, "NODELETE" },
1025 { DF_1_LOADFLTR, "LOADFLTR" },
1026 { DF_1_INITFIRST, "INITFIRST" },
1027 { DF_1_NOOPEN, "NOOPEN" },
1028 { DF_1_ORIGIN, "ORIGIN" },
1029 { DF_1_DIRECT, "DIRECT" },
1030 { DF_1_TRANS, "TRANS" },
1031 { DF_1_INTERPOSE, "INTERPOSE" },
1032 { DF_1_NODEFLIB, "NODEFLIB" },
1033 { DF_1_NODUMP, "NODUMP" },
1034 { DF_1_CONFALT, "CONFALT" },
1035 { DF_1_ENDFILTEE, "ENDFILTEE" },
1036 { DF_1_DISPRELDNE, "DISPRELDNE" },
1037 { DF_1_DISPRELPND, "DISPRELPND" },
1038 };
1039 static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
1040
1041 static const struct flags dt_feature_1[] =
1042 {
1043 { DTF_1_PARINIT, "PARINIT" },
1044 { DTF_1_CONFEXP, "CONFEXP" }
1045 };
1046 static const int ndt_feature_1 = (sizeof (dt_feature_1)
1047 / sizeof (dt_feature_1[0]));
1048
1049 static const struct flags dt_posflag_1[] =
1050 {
1051 { DF_P1_LAZYLOAD, "LAZYLOAD" },
1052 { DF_P1_GROUPPERM, "GROUPPERM" }
1053 };
1054 static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
1055 / sizeof (dt_posflag_1[0]));
1056
1057
1058 static void
print_flags(int class,GElf_Xword d_val,const struct flags * flags,int nflags)1059 print_flags (int class, GElf_Xword d_val, const struct flags *flags,
1060 int nflags)
1061 {
1062 bool first = true;
1063 int cnt;
1064
1065 for (cnt = 0; cnt < nflags; ++cnt)
1066 if (d_val & flags[cnt].mask)
1067 {
1068 if (!first)
1069 putchar_unlocked (' ');
1070 fputs_unlocked (flags[cnt].str, stdout);
1071 d_val &= ~flags[cnt].mask;
1072 first = false;
1073 }
1074
1075 if (d_val != 0)
1076 {
1077 if (!first)
1078 putchar_unlocked (' ');
1079 printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
1080 }
1081
1082 putchar_unlocked ('\n');
1083 }
1084
1085
1086 static void
print_dt_flags(int class,GElf_Xword d_val)1087 print_dt_flags (int class, GElf_Xword d_val)
1088 {
1089 print_flags (class, d_val, dt_flags, ndt_flags);
1090 }
1091
1092
1093 static void
print_dt_flags_1(int class,GElf_Xword d_val)1094 print_dt_flags_1 (int class, GElf_Xword d_val)
1095 {
1096 print_flags (class, d_val, dt_flags_1, ndt_flags_1);
1097 }
1098
1099
1100 static void
print_dt_feature_1(int class,GElf_Xword d_val)1101 print_dt_feature_1 (int class, GElf_Xword d_val)
1102 {
1103 print_flags (class, d_val, dt_feature_1, ndt_feature_1);
1104 }
1105
1106
1107 static void
print_dt_posflag_1(int class,GElf_Xword d_val)1108 print_dt_posflag_1 (int class, GElf_Xword d_val)
1109 {
1110 print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
1111 }
1112
1113
1114 static void
handle_dynamic(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)1115 handle_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1116 {
1117 int class = gelf_getclass (ebl->elf);
1118 GElf_Shdr glink;
1119 Elf_Data *data;
1120 size_t cnt;
1121 size_t shstrndx;
1122
1123 /* Get the data of the section. */
1124 data = elf_getdata (scn, NULL);
1125 if (data == NULL)
1126 return;
1127
1128 /* Get the section header string table index. */
1129 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
1130 error (EXIT_FAILURE, 0,
1131 gettext ("cannot get section header string table index"));
1132
1133 printf (ngettext ("\
1134 \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1135 "\
1136 \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1137 shdr->sh_size / shdr->sh_entsize),
1138 (unsigned long int) (shdr->sh_size / shdr->sh_entsize),
1139 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
1140 shdr->sh_offset,
1141 (int) shdr->sh_link,
1142 elf_strptr (ebl->elf, shstrndx,
1143 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1144 &glink)->sh_name));
1145 fputs_unlocked (gettext (" Type Value\n"), stdout);
1146
1147 for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1148 {
1149 char buf[64];
1150 GElf_Dyn dynmem;
1151 GElf_Dyn *dyn;
1152
1153 dyn = gelf_getdyn (data, cnt, &dynmem);
1154 if (dyn == NULL)
1155 break;
1156
1157 printf (" %-17s ",
1158 ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
1159
1160 switch (dyn->d_tag)
1161 {
1162 case DT_NULL:
1163 case DT_DEBUG:
1164 case DT_BIND_NOW:
1165 case DT_TEXTREL:
1166 /* No further output. */
1167 fputc ('\n', stdout);
1168 break;
1169
1170 case DT_NEEDED:
1171 printf (gettext ("Shared library: [%s]\n"),
1172 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1173 break;
1174
1175 case DT_SONAME:
1176 printf (gettext ("Library soname: [%s]\n"),
1177 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1178 break;
1179
1180 case DT_RPATH:
1181 printf (gettext ("Library rpath: [%s]\n"),
1182 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1183 break;
1184
1185 case DT_RUNPATH:
1186 printf (gettext ("Library runpath: [%s]\n"),
1187 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1188 break;
1189
1190 case DT_PLTRELSZ:
1191 case DT_RELASZ:
1192 case DT_STRSZ:
1193 case DT_RELSZ:
1194 case DT_RELAENT:
1195 case DT_SYMENT:
1196 case DT_RELENT:
1197 case DT_PLTPADSZ:
1198 case DT_MOVEENT:
1199 case DT_MOVESZ:
1200 case DT_INIT_ARRAYSZ:
1201 case DT_FINI_ARRAYSZ:
1202 case DT_SYMINSZ:
1203 case DT_SYMINENT:
1204 case DT_GNU_CONFLICTSZ:
1205 case DT_GNU_LIBLISTSZ:
1206 printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
1207 break;
1208
1209 case DT_VERDEFNUM:
1210 case DT_VERNEEDNUM:
1211 case DT_RELACOUNT:
1212 case DT_RELCOUNT:
1213 printf ("%" PRId64 "\n", dyn->d_un.d_val);
1214 break;
1215
1216 case DT_PLTREL:
1217 puts (ebl_dynamic_tag_name (ebl, dyn->d_un.d_val, NULL, 0));
1218 break;
1219
1220 case DT_FLAGS:
1221 print_dt_flags (class, dyn->d_un.d_val);
1222 break;
1223
1224 case DT_FLAGS_1:
1225 print_dt_flags_1 (class, dyn->d_un.d_val);
1226 break;
1227
1228 case DT_FEATURE_1:
1229 print_dt_feature_1 (class, dyn->d_un.d_val);
1230 break;
1231
1232 case DT_POSFLAG_1:
1233 print_dt_posflag_1 (class, dyn->d_un.d_val);
1234 break;
1235
1236 default:
1237 printf ("%#0*" PRIx64 "\n",
1238 class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
1239 break;
1240 }
1241 }
1242 }
1243
1244
1245 /* Print the dynamic segment. */
1246 static void
print_dynamic(Ebl * ebl,GElf_Ehdr * ehdr)1247 print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr)
1248 {
1249 /* Find all relocation sections and handle them. */
1250 Elf_Scn *scn = NULL;
1251
1252 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1253 {
1254 /* Handle the section if it is a symbol table. */
1255 GElf_Shdr shdr_mem;
1256 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1257
1258 if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
1259 {
1260 handle_dynamic (ebl, ehdr, scn, shdr);
1261 break;
1262 }
1263 }
1264 }
1265
1266
1267 /* Print relocations. */
1268 static void
print_relocs(Ebl * ebl,GElf_Ehdr * ehdr)1269 print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
1270 {
1271 /* Find all relocation sections and handle them. */
1272 Elf_Scn *scn = NULL;
1273
1274 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1275 {
1276 /* Handle the section if it is a symbol table. */
1277 GElf_Shdr shdr_mem;
1278 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1279
1280 if (shdr != NULL)
1281 {
1282 if (shdr->sh_type == SHT_REL)
1283 handle_relocs_rel (ebl, ehdr, scn, shdr);
1284 else if (shdr->sh_type == SHT_RELA)
1285 handle_relocs_rela (ebl, ehdr, scn, shdr);
1286 }
1287 }
1288 }
1289
1290
1291 /* Handle a relocation section. */
1292 static void
handle_relocs_rel(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)1293 handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1294 {
1295 int class = gelf_getclass (ebl->elf);
1296 int nentries = shdr->sh_size / shdr->sh_entsize;
1297 int cnt;
1298 Elf_Data *data;
1299 Elf_Scn *symscn;
1300 GElf_Shdr symshdr_mem;
1301 GElf_Shdr *symshdr;
1302 Elf_Data *symdata;
1303 GElf_Shdr destshdr_mem;
1304 GElf_Shdr *destshdr;
1305 Elf_Scn *xndxscn;
1306 Elf_Data *xndxdata = NULL;
1307 size_t shstrndx;
1308
1309 /* Get the data of the section. */
1310 data = elf_getdata (scn, NULL);
1311 if (data == NULL)
1312 return;
1313
1314 /* Get the symbol table information. */
1315 symscn = elf_getscn (ebl->elf, shdr->sh_link);
1316 symshdr = gelf_getshdr (symscn, &symshdr_mem);
1317 symdata = elf_getdata (symscn, NULL);
1318
1319 /* Get the section header of the section the relocations are for. */
1320 destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1321 &destshdr_mem);
1322
1323 if (symshdr == NULL || symdata == NULL || destshdr == NULL)
1324 {
1325 printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1326 shdr->sh_offset);
1327 return;
1328 }
1329
1330 /* Search for the optional extended section index table. */
1331 xndxscn = NULL;
1332 while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
1333 {
1334 GElf_Shdr xndxshdr_mem;
1335 GElf_Shdr *xndxshdr;
1336
1337 xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
1338 if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
1339 && xndxshdr->sh_link == elf_ndxscn (symscn))
1340 {
1341 /* Found it. */
1342 xndxdata = elf_getdata (xndxscn, NULL);
1343 break;
1344 }
1345 }
1346
1347 /* Get the section header string table index. */
1348 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
1349 error (EXIT_FAILURE, 0,
1350 gettext ("cannot get section header string table index"));
1351
1352 if (shdr->sh_info != 0)
1353 printf (ngettext ("\
1354 \nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1355 "\
1356 \nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1357 nentries),
1358 (unsigned int) elf_ndxscn (scn),
1359 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1360 (unsigned int) shdr->sh_info,
1361 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1362 shdr->sh_offset,
1363 nentries);
1364 else
1365 /* The .rel.dyn section does not refer to a specific section but
1366 instead of section index zero. Do not try to print a section
1367 name. */
1368 printf (ngettext ("\
1369 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1370 "\
1371 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1372 nentries),
1373 (unsigned int) elf_ndxscn (scn),
1374 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1375 shdr->sh_offset,
1376 nentries);
1377 fputs_unlocked (class == ELFCLASS32
1378 ? gettext ("\
1379 Offset Type Value Name\n")
1380 : gettext ("\
1381 Offset Type Value Name\n"),
1382 stdout);
1383
1384 for (cnt = 0; cnt < nentries; ++cnt)
1385 {
1386 GElf_Rel relmem;
1387 GElf_Rel *rel;
1388
1389 rel = gelf_getrel (data, cnt, &relmem);
1390 if (rel != NULL)
1391 {
1392 char buf[128];
1393 GElf_Sym symmem;
1394 GElf_Sym *sym;
1395 Elf32_Word xndx;
1396
1397 sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (rel->r_info),
1398 &symmem, &xndx);
1399 if (sym == NULL)
1400 printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
1401 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1402 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1403 /* Avoid the leading R_ which isn't carrying any
1404 information. */
1405 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1406 buf, sizeof (buf)) + 2
1407 : gettext ("<INVALID RELOC>"),
1408 gettext ("INVALID SYMBOL"),
1409 (long int) GELF_R_SYM (rel->r_info));
1410 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1411 printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
1412 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1413 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1414 /* Avoid the leading R_ which isn't carrying any
1415 information. */
1416 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1417 buf, sizeof (buf)) + 2
1418 : gettext ("<INVALID RELOC>"),
1419 class == ELFCLASS32 ? 10 : 18, sym->st_value,
1420 elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1421 else
1422 {
1423 destshdr = gelf_getshdr (elf_getscn (ebl->elf,
1424 sym->st_shndx == SHN_XINDEX
1425 ? xndx : sym->st_shndx),
1426 &destshdr_mem);
1427
1428 if (shdr == NULL)
1429 printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
1430 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1431 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1432 /* Avoid the leading R_ which isn't carrying any
1433 information. */
1434 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1435 buf, sizeof (buf)) + 2
1436 : gettext ("<INVALID RELOC>"),
1437 gettext ("INVALID SECTION"),
1438 (long int) (sym->st_shndx == SHN_XINDEX
1439 ? xndx : sym->st_shndx));
1440 else
1441 printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
1442 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1443 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1444 /* Avoid the leading R_ which isn't carrying any
1445 information. */
1446 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1447 buf, sizeof (buf)) + 2
1448 : gettext ("<INVALID RELOC>"),
1449 class == ELFCLASS32 ? 10 : 18, sym->st_value,
1450 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1451 }
1452 }
1453 }
1454 }
1455
1456
1457 /* Handle a relocation section. */
1458 static void
handle_relocs_rela(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)1459 handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1460 {
1461 int class = gelf_getclass (ebl->elf);
1462 int nentries = shdr->sh_size / shdr->sh_entsize;
1463
1464 /* Get the data of the section. */
1465 Elf_Data *data = elf_getdata (scn, NULL);
1466 if (data == NULL)
1467 return;
1468
1469 /* Get the symbol table information. */
1470 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1471 GElf_Shdr symshdr_mem;
1472 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1473 Elf_Data *symdata = elf_getdata (symscn, NULL);
1474
1475 /* Get the section header of the section the relocations are for. */
1476 GElf_Shdr destshdr_mem;
1477 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1478 &destshdr_mem);
1479
1480 if (symshdr == NULL || symdata == NULL || destshdr == NULL)
1481 {
1482 printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1483 shdr->sh_offset);
1484 return;
1485 }
1486
1487 /* Search for the optional extended section index table. */
1488 Elf_Data *xndxdata = NULL;
1489 Elf_Scn *xndxscn = NULL;
1490 while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
1491 {
1492 GElf_Shdr xndxshdr_mem;
1493 GElf_Shdr *xndxshdr;
1494
1495 xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
1496 if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
1497 && xndxshdr->sh_link == elf_ndxscn (symscn))
1498 {
1499 /* Found it. */
1500 xndxdata = elf_getdata (xndxscn, NULL);
1501 break;
1502 }
1503 }
1504
1505 /* Get the section header string table index. */
1506 size_t shstrndx;
1507 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
1508 error (EXIT_FAILURE, 0,
1509 gettext ("cannot get section header string table index"));
1510
1511 printf (ngettext ("\
1512 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1513 "\
1514 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1515 nentries),
1516 elf_ndxscn (scn),
1517 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1518 (unsigned int) shdr->sh_info,
1519 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1520 shdr->sh_offset,
1521 nentries);
1522 fputs_unlocked (class == ELFCLASS32
1523 ? gettext ("\
1524 Offset Type Value Addend Name\n")
1525 : gettext ("\
1526 Offset Type Value Addend Name\n"),
1527 stdout);
1528
1529 for (int cnt = 0; cnt < nentries; ++cnt)
1530 {
1531 GElf_Rela relmem;
1532 GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
1533 if (rel != NULL)
1534 {
1535 char buf[64];
1536 GElf_Sym symmem;
1537 GElf_Sym *sym;
1538 Elf32_Word xndx;
1539
1540 sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (rel->r_info),
1541 &symmem, &xndx);
1542
1543 if (sym == NULL)
1544 printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
1545 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1546 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1547 /* Avoid the leading R_ which isn't carrying any
1548 information. */
1549 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1550 buf, sizeof (buf)) + 2
1551 : gettext ("<INVALID RELOC>"),
1552 gettext ("INVALID SYMBOL"),
1553 (long int) GELF_R_SYM (rel->r_info));
1554 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1555 printf ("\
1556 %#0*" PRIx64 " %-15s %#0*" PRIx64 " +%5" PRId64 " %s\n",
1557 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1558 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1559 /* Avoid the leading R_ which isn't carrying any
1560 information. */
1561 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1562 buf, sizeof (buf)) + 2
1563 : gettext ("<INVALID RELOC>"),
1564 class == ELFCLASS32 ? 10 : 18, sym->st_value,
1565 rel->r_addend,
1566 elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1567 else
1568 {
1569 destshdr = gelf_getshdr (elf_getscn (ebl->elf,
1570 sym->st_shndx == SHN_XINDEX
1571 ? xndx : sym->st_shndx),
1572 &destshdr_mem);
1573
1574 if (shdr == NULL)
1575 printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
1576 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1577 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1578 /* Avoid the leading R_ which isn't carrying any
1579 information. */
1580 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1581 buf, sizeof (buf)) + 2
1582 : gettext ("<INVALID RELOC>"),
1583 gettext ("INVALID SECTION"),
1584 (long int) (sym->st_shndx == SHN_XINDEX
1585 ? xndx : sym->st_shndx));
1586 else
1587 printf ("\
1588 %#0*" PRIx64 " %-15s %#0*" PRIx64 " +%5" PRId64 " %s\n",
1589 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1590 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1591 /* Avoid the leading R_ which isn't carrying any
1592 information. */
1593 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1594 buf, sizeof (buf)) + 2
1595 : gettext ("<INVALID RELOC>"),
1596 class == ELFCLASS32 ? 10 : 18, sym->st_value,
1597 rel->r_addend,
1598 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1599 }
1600 }
1601 }
1602 }
1603
1604
1605 /* Print the program header. */
1606 static void
print_symtab(Ebl * ebl,GElf_Ehdr * ehdr,int type)1607 print_symtab (Ebl *ebl, GElf_Ehdr *ehdr, int type)
1608 {
1609 /* Find the symbol table(s). For this we have to search through the
1610 section table. */
1611 Elf_Scn *scn = NULL;
1612
1613 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1614 {
1615 /* Handle the section if it is a symbol table. */
1616 GElf_Shdr shdr_mem;
1617 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1618
1619 if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
1620 handle_symtab (ebl, ehdr, scn, shdr);
1621 }
1622 }
1623
1624
1625 static void
handle_symtab(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)1626 handle_symtab (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1627 {
1628 Elf_Data *versym_data = NULL;
1629 Elf_Data *verneed_data = NULL;
1630 Elf_Data *verdef_data = NULL;
1631 Elf_Data *xndx_data = NULL;
1632 Elf_Scn *runscn;
1633 Elf_Data *data;
1634 int class = gelf_getclass (ebl->elf);
1635 unsigned int nsyms;
1636 unsigned int cnt;
1637 Elf32_Word verneed_stridx = 0;
1638 Elf32_Word verdef_stridx = 0;
1639 GElf_Shdr glink;
1640 size_t shstrndx;
1641
1642 /* Get the data of the section. */
1643 data = elf_getdata (scn, NULL);
1644 if (data == NULL)
1645 return;
1646
1647 /* Find out whether we have other sections we might need. */
1648 runscn = NULL;
1649 while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
1650 {
1651 GElf_Shdr runshdr_mem;
1652 GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
1653
1654 if (runshdr != NULL)
1655 {
1656 if (runshdr->sh_type == SHT_GNU_versym
1657 && runshdr->sh_link == elf_ndxscn (scn))
1658 /* Bingo, found the version information. Now get the data. */
1659 versym_data = elf_getdata (runscn, NULL);
1660 else if (runshdr->sh_type == SHT_GNU_verneed)
1661 {
1662 /* This is the information about the needed versions. */
1663 verneed_data = elf_getdata (runscn, NULL);
1664 verneed_stridx = runshdr->sh_link;
1665 }
1666 else if (runshdr->sh_type == SHT_GNU_verdef)
1667 {
1668 /* This is the information about the defined versions. */
1669 verdef_data = elf_getdata (runscn, NULL);
1670 verdef_stridx = runshdr->sh_link;
1671 }
1672 else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
1673 && runshdr->sh_link == elf_ndxscn (scn))
1674 /* Extended section index. */
1675 xndx_data = elf_getdata (runscn, NULL);
1676 }
1677 }
1678
1679 /* Get the section header string table index. */
1680 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
1681 error (EXIT_FAILURE, 0,
1682 gettext ("cannot get section header string table index"));
1683
1684 /* Now we can compute the number of entries in the section. */
1685 nsyms = data->d_size / (class == ELFCLASS32
1686 ? sizeof (Elf32_Sym) : sizeof (Elf64_Sym));
1687
1688 printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
1689 "\nSymbol table [%2u] '%s' contains %u entries:\n",
1690 nsyms),
1691 (unsigned int) elf_ndxscn (scn),
1692 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
1693 printf (ngettext (" %lu local symbol String table: [%2u] '%s'\n",
1694 " %lu local symbols String table: [%2u] '%s'\n",
1695 shdr->sh_info),
1696 (unsigned long int) shdr->sh_info,
1697 (unsigned int) shdr->sh_link,
1698 elf_strptr (ebl->elf, shstrndx,
1699 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1700 &glink)->sh_name));
1701
1702 fputs_unlocked (class == ELFCLASS32
1703 ? gettext ("\
1704 Num: Value Size Type Bind Vis Ndx Name\n")
1705 : gettext ("\
1706 Num: Value Size Type Bind Vis Ndx Name\n"),
1707 stdout);
1708
1709 for (cnt = 0; cnt < nsyms; ++cnt)
1710 {
1711 char typebuf[64];
1712 char bindbuf[64];
1713 char scnbuf[64];
1714 Elf32_Word xndx;
1715 GElf_Sym sym_mem;
1716 GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
1717
1718 if (sym == NULL)
1719 continue;
1720
1721 /* Determine the real section index. */
1722 if (sym->st_shndx != SHN_XINDEX)
1723 xndx = sym->st_shndx;
1724
1725 printf (gettext ("\
1726 %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
1727 cnt,
1728 class == ELFCLASS32 ? 8 : 16,
1729 sym->st_value,
1730 sym->st_size,
1731 ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
1732 typebuf, sizeof (typebuf)),
1733 ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
1734 bindbuf, sizeof (bindbuf)),
1735 get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
1736 ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
1737 sizeof (scnbuf), NULL, shnum),
1738 elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
1739
1740 if (versym_data != NULL)
1741 {
1742 /* Get the version information. */
1743 GElf_Versym versym_mem;
1744 GElf_Versym *versym;
1745
1746 versym = gelf_getversym (versym_data, cnt, &versym_mem);
1747
1748 if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
1749 {
1750 bool is_nobits = false;
1751 bool check_def = xndx != SHN_UNDEF;
1752
1753 if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
1754 {
1755 GElf_Shdr symshdr_mem;
1756 GElf_Shdr *symshdr =
1757 gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
1758
1759 is_nobits = (symshdr != NULL
1760 && symshdr->sh_type == SHT_NOBITS);
1761 }
1762
1763 if (is_nobits || ! check_def)
1764 {
1765 /* We must test both. */
1766 GElf_Verneed verneed_mem;
1767 GElf_Verneed *verneed;
1768 GElf_Vernaux vernaux_mem;
1769 GElf_Vernaux *vernaux = NULL;
1770 size_t vn_offset = 0;
1771
1772 verneed = gelf_getverneed (verneed_data, 0, &verneed_mem);
1773 while (verneed != NULL)
1774 {
1775 size_t vna_offset = vn_offset;
1776
1777 vernaux = gelf_getvernaux (verneed_data,
1778 vna_offset += verneed->vn_aux,
1779 &vernaux_mem);
1780 while (vernaux != NULL
1781 && vernaux->vna_other != *versym
1782 && vernaux->vna_next != 0)
1783 {
1784 /* Update the offset. */
1785 vna_offset += vernaux->vna_next;
1786
1787 vernaux = (vernaux->vna_next == 0
1788 ? NULL
1789 : gelf_getvernaux (verneed_data,
1790 vna_offset,
1791 &vernaux_mem));
1792 }
1793
1794 /* Check whether we found the version. */
1795 if (vernaux != NULL && vernaux->vna_other == *versym)
1796 /* Found it. */
1797 break;
1798
1799 vn_offset += verneed->vn_next;
1800 verneed = (verneed->vn_next == 0
1801 ? NULL
1802 : gelf_getverneed (verneed_data, vn_offset,
1803 &verneed_mem));
1804 }
1805
1806 if (vernaux != NULL && vernaux->vna_other == *versym)
1807 {
1808 printf ("@%s (%u)",
1809 elf_strptr (ebl->elf, verneed_stridx,
1810 vernaux->vna_name),
1811 (unsigned int) vernaux->vna_other);
1812 check_def = 0;
1813 }
1814 else if (! is_nobits)
1815 error (0, 0, gettext ("bad dynamic symbol"));
1816 else
1817 check_def = 1;
1818 }
1819
1820 if (check_def && *versym != 0x8001)
1821 {
1822 /* We must test both. */
1823 GElf_Verdef verdef_mem;
1824 GElf_Verdef *verdef;
1825 size_t vd_offset = 0;
1826
1827 verdef = gelf_getverdef (verdef_data, 0, &verdef_mem);
1828 while (verdef != NULL)
1829 {
1830 if (verdef->vd_ndx == (*versym & 0x7fff))
1831 /* Found the definition. */
1832 break;
1833
1834 vd_offset += verdef->vd_next;
1835 verdef = (verdef->vd_next == 0
1836 ? NULL
1837 : gelf_getverdef (verdef_data, vd_offset,
1838 &verdef_mem));
1839 }
1840
1841 if (verdef != NULL)
1842 {
1843 GElf_Verdaux verdaux_mem;
1844 GElf_Verdaux *verdaux;
1845
1846 verdaux = gelf_getverdaux (verdef_data,
1847 vd_offset + verdef->vd_aux,
1848 &verdaux_mem);
1849
1850 if (verdaux != NULL)
1851 printf ((*versym & 0x8000) ? "@%s" : "@@%s",
1852 elf_strptr (ebl->elf, verdef_stridx,
1853 verdaux->vda_name));
1854 }
1855 }
1856 }
1857 }
1858
1859 putchar ('\n');
1860 }
1861 }
1862
1863
1864 /* Print version information. */
1865 static void
print_verinfo(Ebl * ebl,GElf_Ehdr * ehdr)1866 print_verinfo (Ebl *ebl, GElf_Ehdr *ehdr)
1867 {
1868 /* Find the version information sections. For this we have to
1869 search through the section table. */
1870 Elf_Scn *scn = NULL;
1871
1872 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1873 {
1874 /* Handle the section if it is part of the versioning handling. */
1875 GElf_Shdr shdr_mem;
1876 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1877
1878 if (shdr != NULL)
1879 {
1880 if (shdr->sh_type == SHT_GNU_verneed)
1881 handle_verneed (ebl, ehdr, scn, shdr);
1882 else if (shdr->sh_type == SHT_GNU_verdef)
1883 handle_verdef (ebl, ehdr, scn, shdr);
1884 else if (shdr->sh_type == SHT_GNU_versym)
1885 handle_versym (ebl, ehdr, scn, shdr);
1886 }
1887 }
1888 }
1889
1890
1891 static const char *
get_ver_flags(unsigned int flags)1892 get_ver_flags (unsigned int flags)
1893 {
1894 static char buf[32];
1895 char *endp;
1896
1897 if (flags == 0)
1898 return gettext ("none");
1899
1900 if (flags & VER_FLG_BASE)
1901 endp = stpcpy (buf, "BASE ");
1902 else
1903 endp = buf;
1904
1905 if (flags & VER_FLG_WEAK)
1906 {
1907 if (endp != buf)
1908 endp = stpcpy (endp, "| ");
1909
1910 endp = stpcpy (endp, "WEAK ");
1911 }
1912
1913 if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
1914 {
1915 strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
1916 buf[sizeof (buf) - 1] = '\0';
1917 }
1918
1919 return buf;
1920 }
1921
1922
1923 static void
handle_verneed(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)1924 handle_verneed (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
1925 {
1926 Elf_Data *data;
1927 int class = gelf_getclass (ebl->elf);
1928 GElf_Shdr glink;
1929 int cnt;
1930 unsigned int offset;
1931 size_t shstrndx;
1932
1933 /* Get the data of the section. */
1934 data = elf_getdata (scn, NULL);
1935 if (data == NULL)
1936 return;
1937
1938 /* Get the section header string table index. */
1939 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
1940 error (EXIT_FAILURE, 0,
1941 gettext ("cannot get section header string table index"));
1942
1943 printf (ngettext ("\
1944 \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1945 "\
1946 \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1947 shdr->sh_info),
1948 (unsigned int) elf_ndxscn (scn),
1949 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
1950 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
1951 shdr->sh_offset,
1952 (unsigned int) shdr->sh_link,
1953 elf_strptr (ebl->elf, shstrndx,
1954 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1955 &glink)->sh_name));
1956
1957 offset = 0;
1958 for (cnt = shdr->sh_info; --cnt >= 0; )
1959 {
1960 GElf_Verneed needmem;
1961 GElf_Verneed *need;
1962 unsigned int auxoffset;
1963 int cnt2;
1964
1965 /* Get the data at the next offset. */
1966 need = gelf_getverneed (data, offset, &needmem);
1967 if (need == NULL)
1968 break;
1969
1970 printf (gettext (" %#06x: Version: %hu File: %s Cnt: %hu\n"),
1971 offset, (unsigned short int) need->vn_version,
1972 elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
1973 (unsigned short int) need->vn_cnt);
1974
1975 auxoffset = offset + need->vn_aux;
1976 for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
1977 {
1978 GElf_Vernaux auxmem;
1979 GElf_Vernaux *aux;
1980
1981 aux = gelf_getvernaux (data, auxoffset, &auxmem);
1982 if (aux == NULL)
1983 break;
1984
1985 printf (gettext (" %#06x: Name: %s Flags: %s Version: %hu\n"),
1986 auxoffset,
1987 elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
1988 get_ver_flags (aux->vna_flags),
1989 (unsigned short int) aux->vna_other);
1990
1991 auxoffset += aux->vna_next;
1992 }
1993
1994 /* Find the next offset. */
1995 offset += need->vn_next;
1996 }
1997 }
1998
1999
2000 static void
handle_verdef(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)2001 handle_verdef (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
2002 {
2003 Elf_Data *data;
2004 int class = gelf_getclass (ebl->elf);
2005 GElf_Shdr glink;
2006 int cnt;
2007 unsigned int offset;
2008 size_t shstrndx;
2009
2010 /* Get the data of the section. */
2011 data = elf_getdata (scn, NULL);
2012 if (data == NULL)
2013 return;
2014
2015 /* Get the section header string table index. */
2016 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
2017 error (EXIT_FAILURE, 0,
2018 gettext ("cannot get section header string table index"));
2019
2020 printf (ngettext ("\
2021 \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2022 "\
2023 \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2024 shdr->sh_info),
2025 (unsigned int) elf_ndxscn (scn),
2026 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2027 shdr->sh_info,
2028 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2029 shdr->sh_offset,
2030 (unsigned int) shdr->sh_link,
2031 elf_strptr (ebl->elf, shstrndx,
2032 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2033 &glink)->sh_name));
2034
2035 offset = 0;
2036 for (cnt = shdr->sh_info; --cnt >= 0; )
2037 {
2038 GElf_Verdef defmem;
2039 GElf_Verdef *def;
2040 GElf_Verdaux auxmem;
2041 GElf_Verdaux *aux;
2042 unsigned int auxoffset;
2043 int cnt2;
2044
2045 /* Get the data at the next offset. */
2046 def = gelf_getverdef (data, offset, &defmem);
2047 if (def == NULL)
2048 break;
2049
2050 auxoffset = offset + def->vd_aux;
2051 aux = gelf_getverdaux (data, auxoffset, &auxmem);
2052 if (aux == NULL)
2053 break;
2054
2055 printf (gettext ("\
2056 %#06x: Version: %hd Flags: %s Index: %hd Cnt: %hd Name: %s\n"),
2057 offset, def->vd_version,
2058 get_ver_flags (def->vd_flags),
2059 def->vd_ndx,
2060 def->vd_cnt,
2061 elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2062
2063 auxoffset += aux->vda_next;
2064 for (cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
2065 {
2066 aux = gelf_getverdaux (data, auxoffset, &auxmem);
2067 if (aux == NULL)
2068 break;
2069
2070 printf (gettext (" %#06x: Parent %d: %s\n"),
2071 auxoffset, cnt2,
2072 elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2073
2074 auxoffset += aux->vda_next;
2075 }
2076
2077 /* Find the next offset. */
2078 offset += def->vd_next;
2079 }
2080 }
2081
2082
2083 static void
handle_versym(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)2084 handle_versym (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
2085 {
2086 Elf_Data *data;
2087 int class = gelf_getclass (ebl->elf);
2088 Elf_Scn *verscn;
2089 GElf_Shdr glink;
2090 Elf_Scn *defscn;
2091 Elf_Scn *needscn;
2092 const char **vername;
2093 const char **filename;
2094 size_t nvername;
2095 unsigned int cnt;
2096 size_t shstrndx;
2097
2098 /* Get the data of the section. */
2099 data = elf_getdata (scn, NULL);
2100 if (data == NULL)
2101 return;
2102
2103 /* Get the section header string table index. */
2104 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
2105 error (EXIT_FAILURE, 0,
2106 gettext ("cannot get section header string table index"));
2107
2108 /* We have to find the version definition section and extract the
2109 version names. */
2110 defscn = NULL;
2111 needscn = NULL;
2112
2113 verscn = NULL;
2114 while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
2115 {
2116 GElf_Shdr vershdr_mem;
2117 GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
2118
2119 if (vershdr != NULL)
2120 {
2121 if (vershdr->sh_type == SHT_GNU_verdef)
2122 defscn = verscn;
2123 else if (vershdr->sh_type == SHT_GNU_verneed)
2124 needscn = verscn;
2125 }
2126 }
2127
2128 if (defscn != NULL || needscn != NULL)
2129 {
2130 /* We have a version information (better should have). Now get
2131 the version names. First find the maximum version number. */
2132 nvername = 0;
2133 if (defscn != NULL)
2134 {
2135 /* Run through the version definitions and find the highest
2136 index. */
2137 unsigned int offset = 0;
2138 Elf_Data *defdata;
2139 GElf_Shdr defshdrmem;
2140 GElf_Shdr *defshdr;
2141
2142 defdata = elf_getdata (defscn, NULL);
2143 if (defdata == NULL)
2144 return;
2145
2146 defshdr = gelf_getshdr (defscn, &defshdrmem);
2147 if (defshdr == NULL)
2148 return;
2149
2150 for (cnt = 0; cnt < defshdr->sh_info; ++cnt)
2151 {
2152 GElf_Verdef defmem;
2153 GElf_Verdef *def;
2154
2155 /* Get the data at the next offset. */
2156 def = gelf_getverdef (defdata, offset, &defmem);
2157 if (def == NULL)
2158 break;
2159
2160 nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
2161
2162 offset += def->vd_next;
2163 }
2164 }
2165 if (needscn != NULL)
2166 {
2167 unsigned int offset = 0;
2168 Elf_Data *needdata;
2169 GElf_Shdr needshdrmem;
2170 GElf_Shdr *needshdr;
2171
2172 needdata = elf_getdata (needscn, NULL);
2173 if (needdata == NULL)
2174 return;
2175
2176 needshdr = gelf_getshdr (needscn, &needshdrmem);
2177 if (needshdr == NULL)
2178 return;
2179
2180 for (cnt = 0; cnt < needshdr->sh_info; ++cnt)
2181 {
2182 GElf_Verneed needmem;
2183 GElf_Verneed *need;
2184 unsigned int auxoffset;
2185 int cnt2;
2186
2187 /* Get the data at the next offset. */
2188 need = gelf_getverneed (needdata, offset, &needmem);
2189 if (need == NULL)
2190 break;
2191
2192 /* Run through the auxiliary entries. */
2193 auxoffset = offset + need->vn_aux;
2194 for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
2195 {
2196 GElf_Vernaux auxmem;
2197 GElf_Vernaux *aux;
2198
2199 aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
2200 if (aux == NULL)
2201 break;
2202
2203 nvername = MAX (nvername,
2204 (size_t) (aux->vna_other & 0x7fff));
2205
2206 auxoffset += aux->vna_next;
2207 }
2208
2209 offset += need->vn_next;
2210 }
2211 }
2212
2213 /* This is the number of versions we know about. */
2214 ++nvername;
2215
2216 /* Allocate the array. */
2217 vername = (const char **) alloca (nvername * sizeof (const char *));
2218 filename = (const char **) alloca (nvername * sizeof (const char *));
2219
2220 /* Run through the data structures again and collect the strings. */
2221 if (defscn != NULL)
2222 {
2223 /* Run through the version definitions and find the highest
2224 index. */
2225 unsigned int offset = 0;
2226 Elf_Data *defdata;
2227 GElf_Shdr defshdrmem;
2228 GElf_Shdr *defshdr;
2229
2230 defdata = elf_getdata (defscn, NULL);
2231 if (defdata == NULL)
2232 return;
2233
2234 defshdr = gelf_getshdr (defscn, &defshdrmem);
2235 if (defshdr == NULL)
2236 return;
2237
2238 for (cnt = 0; cnt < defshdr->sh_info; ++cnt)
2239 {
2240 GElf_Verdef defmem;
2241 GElf_Verdef *def;
2242 GElf_Verdaux auxmem;
2243 GElf_Verdaux *aux;
2244
2245 /* Get the data at the next offset. */
2246 def = gelf_getverdef (defdata, offset, &defmem);
2247 if (def == NULL)
2248 break;
2249
2250 aux = gelf_getverdaux (defdata, offset + def->vd_aux, &auxmem);
2251 if (aux == NULL)
2252 break;
2253
2254 vername[def->vd_ndx & 0x7fff]
2255 = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
2256 filename[def->vd_ndx & 0x7fff] = NULL;
2257
2258 offset += def->vd_next;
2259 }
2260 }
2261 if (needscn != NULL)
2262 {
2263 unsigned int offset = 0;
2264 Elf_Data *needdata;
2265 GElf_Shdr needshdrmem;
2266 GElf_Shdr *needshdr;
2267
2268 needdata = elf_getdata (needscn, NULL);
2269 if (needdata == NULL)
2270 return;
2271
2272 needshdr = gelf_getshdr (needscn, &needshdrmem);
2273 if (needshdr == NULL)
2274 return;
2275
2276 for (cnt = 0; cnt < needshdr->sh_info; ++cnt)
2277 {
2278 GElf_Verneed needmem;
2279 GElf_Verneed *need;
2280 unsigned int auxoffset;
2281 int cnt2;
2282
2283 /* Get the data at the next offset. */
2284 need = gelf_getverneed (needdata, offset, &needmem);
2285 if (need == NULL)
2286 break;
2287
2288 /* Run through the auxiliary entries. */
2289 auxoffset = offset + need->vn_aux;
2290 for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
2291 {
2292 GElf_Vernaux auxmem;
2293 GElf_Vernaux *aux;
2294
2295 aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
2296 if (aux == NULL)
2297 break;
2298
2299 vername[aux->vna_other & 0x7fff]
2300 = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
2301 filename[aux->vna_other & 0x7fff]
2302 = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
2303
2304 auxoffset += aux->vna_next;
2305 }
2306
2307 offset += need->vn_next;
2308 }
2309 }
2310 }
2311 else
2312 {
2313 vername = NULL;
2314 nvername = 1;
2315 filename = NULL;
2316 }
2317
2318 /* Print the header. */
2319 printf (ngettext ("\
2320 \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
2321 "\
2322 \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
2323 shdr->sh_size / shdr->sh_entsize),
2324 (unsigned int) elf_ndxscn (scn),
2325 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2326 (int) (shdr->sh_size / shdr->sh_entsize),
2327 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2328 shdr->sh_offset,
2329 (unsigned int) shdr->sh_link,
2330 elf_strptr (ebl->elf, shstrndx,
2331 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2332 &glink)->sh_name));
2333
2334 /* Now we can finally look at the actual contents of this section. */
2335 for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
2336 {
2337 GElf_Versym symmem;
2338 GElf_Versym *sym;
2339 ssize_t n;
2340
2341 if (cnt % 2 == 0)
2342 printf ("\n %4d:", cnt);
2343
2344 sym = gelf_getversym (data, cnt, &symmem);
2345 if (sym == NULL)
2346 break;
2347
2348 switch (*sym)
2349 {
2350 case 0:
2351 fputs_unlocked (gettext (" 0 *local* "),
2352 stdout);
2353 break;
2354
2355 case 1:
2356 fputs_unlocked (gettext (" 1 *global* "),
2357 stdout);
2358 break;
2359
2360 default:
2361 n = printf ("%4d%c%s",
2362 *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
2363 (unsigned int) (*sym & 0x7fff) < nvername
2364 ? vername[*sym & 0x7fff] : "???");
2365 if ((unsigned int) (*sym & 0x7fff) < nvername
2366 && filename[*sym & 0x7fff] != NULL)
2367 n += printf ("(%s)", filename[*sym & 0x7fff]);
2368 printf ("%*s", MAX (0, 33 - (int) n), " ");
2369 break;
2370 }
2371 }
2372 putchar ('\n');
2373 }
2374
2375
2376 static void
handle_hash(Ebl * ebl,GElf_Ehdr * ehdr)2377 handle_hash (Ebl *ebl, GElf_Ehdr *ehdr)
2378 {
2379 /* Find the symbol table(s). For this we have to search through the
2380 section table. */
2381 Elf_Scn *scn = NULL;
2382 size_t shstrndx;
2383
2384 /* Get the section header string table index. */
2385 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
2386 error (EXIT_FAILURE, 0,
2387 gettext ("cannot get section header string table index"));
2388
2389 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2390 {
2391 /* Handle the section if it is a symbol table. */
2392 GElf_Shdr shdr_mem;
2393 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2394
2395 if (shdr != NULL && shdr->sh_type == SHT_HASH)
2396 {
2397 Elf_Data *data = elf_getdata (scn, NULL);
2398 Elf32_Word nbucket;
2399 Elf32_Word nchain;
2400 Elf32_Word *bucket;
2401 Elf32_Word *chain;
2402 uint32_t *lengths;
2403 uint32_t *counts;
2404 Elf32_Word cnt;
2405 Elf32_Word maxlength = 0;
2406 Elf32_Word nsyms = 0;
2407 uint64_t nzero_counts = 0;
2408 GElf_Shdr glink;
2409
2410 if (data == NULL)
2411 {
2412 error (0, 0, gettext ("cannot get data for section %d: %s"),
2413 (int) elf_ndxscn (scn), elf_errmsg (-1));
2414 continue;
2415 }
2416
2417 nbucket = ((Elf32_Word *) data->d_buf)[0];
2418 nchain = ((Elf32_Word *) data->d_buf)[1];
2419 bucket = &((Elf32_Word *) data->d_buf)[2];
2420 chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
2421
2422 printf (ngettext ("\
2423 \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",
2424 "\
2425 \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",
2426 nbucket),
2427 (unsigned int) elf_ndxscn (scn),
2428 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2429 (int) nbucket,
2430 gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
2431 shdr->sh_addr,
2432 shdr->sh_offset,
2433 (unsigned int) shdr->sh_link,
2434 elf_strptr (ebl->elf, shstrndx,
2435 gelf_getshdr (elf_getscn (ebl->elf,
2436 shdr->sh_link),
2437 &glink)->sh_name));
2438
2439 lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2440
2441 for (cnt = 0; cnt < nbucket; ++cnt)
2442 if (bucket[cnt] != 0)
2443 {
2444 Elf32_Word inner;
2445
2446 inner = bucket[cnt];
2447 while (inner > 0 && inner < nchain)
2448 {
2449 ++nsyms;
2450 if (maxlength < ++lengths[cnt])
2451 ++maxlength;
2452
2453 inner = chain[inner];
2454 }
2455 }
2456
2457 counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
2458
2459 for (cnt = 0; cnt < nbucket; ++cnt)
2460 ++counts[lengths[cnt]];
2461
2462 if (nbucket > 0)
2463 {
2464 uint64_t success = 0;
2465 Elf32_Word acc;
2466
2467 puts (gettext (" Length Number % of total Coverage"));
2468 printf (gettext (" 0 %6" PRIu32 " %5.1f%%\n"),
2469 counts[0], (counts[0] * 100.0) / nbucket);
2470
2471 for (cnt = 1; cnt <= maxlength; ++cnt)
2472 {
2473 nzero_counts += counts[cnt] * cnt;
2474 printf (gettext ("\
2475 %7d %6" PRIu32 " %5.1f%% %5.1f%%\n"),
2476 (int) cnt,
2477 counts[cnt], (counts[cnt] * 100.0) / nbucket,
2478 (nzero_counts * 100.0) / nsyms);
2479 }
2480
2481 acc = 0;
2482 for (cnt = 1; cnt <= maxlength; ++cnt)
2483 {
2484 acc += cnt;
2485 success += counts[cnt] * acc;
2486 }
2487
2488 printf (gettext ("\
2489 Average number of tests: successful lookup: %f\n\
2490 unsuccessful lookup: %f\n"),
2491 (double) success / (double) nzero_counts,
2492 (double) nzero_counts / (double) nbucket);
2493 }
2494
2495 free (counts);
2496 free (lengths);
2497 }
2498 }
2499 }
2500
2501
2502 static void
print_liblist(Ebl * ebl,GElf_Ehdr * ehdr)2503 print_liblist (Ebl *ebl, GElf_Ehdr *ehdr)
2504 {
2505 /* Find the library list sections. For this we have to search
2506 through the section table. */
2507 Elf_Scn *scn = NULL;
2508
2509 /* Get the section header string table index. */
2510 size_t shstrndx;
2511 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
2512 error (EXIT_FAILURE, 0,
2513 gettext ("cannot get section header string table index"));
2514
2515 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2516 {
2517 GElf_Shdr shdr_mem;
2518 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2519
2520 if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
2521 {
2522 int nentries = shdr->sh_size / shdr->sh_entsize;
2523 printf (ngettext ("\
2524 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2525 "\
2526 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2527 nentries),
2528 elf_ndxscn (scn),
2529 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2530 shdr->sh_offset,
2531 nentries);
2532
2533 Elf_Data *data = elf_getdata (scn, NULL);
2534 if (data == NULL)
2535 return;
2536
2537 puts (gettext ("\
2538 Library Time Stamp Checksum Version Flags"));
2539
2540 for (int cnt = 0; cnt < nentries; ++cnt)
2541 {
2542 GElf_Lib lib_mem;
2543 GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
2544 if (lib == NULL)
2545 continue;
2546
2547 time_t t = (time_t) lib->l_time_stamp;
2548 struct tm *tm = gmtime (&t);
2549 if (tm == NULL)
2550 continue;
2551
2552 printf (" [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
2553 cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
2554 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
2555 tm->tm_hour, tm->tm_min, tm->tm_sec,
2556 (unsigned int) lib->l_checksum,
2557 (unsigned int) lib->l_version,
2558 (unsigned int) lib->l_flags);
2559 }
2560 }
2561 }
2562 }
2563
2564
2565 static const char *
dwarf_tag_string(unsigned int tag)2566 dwarf_tag_string (unsigned int tag)
2567 {
2568 static const char *known_tags[] =
2569 {
2570 [DW_TAG_array_type] = "array_type",
2571 [DW_TAG_class_type] = "class_type",
2572 [DW_TAG_entry_point] = "entry_point",
2573 [DW_TAG_enumeration_type] = "enumeration_type",
2574 [DW_TAG_formal_parameter] = "formal_parameter",
2575 [DW_TAG_imported_declaration] = "imported_declaration",
2576 [DW_TAG_label] = "label",
2577 [DW_TAG_lexical_block] = "lexical_block",
2578 [DW_TAG_member] = "member",
2579 [DW_TAG_pointer_type] = "pointer_type",
2580 [DW_TAG_reference_type] = "reference_type",
2581 [DW_TAG_compile_unit] = "compile_unit",
2582 [DW_TAG_string_type] = "string_type",
2583 [DW_TAG_structure_type] = "structure_type",
2584 [DW_TAG_subroutine_type] = "subroutine_type",
2585 [DW_TAG_typedef] = "typedef",
2586 [DW_TAG_union_type] = "union_type",
2587 [DW_TAG_unspecified_parameters] = "unspecified_parameters",
2588 [DW_TAG_variant] = "variant",
2589 [DW_TAG_common_block] = "common_block",
2590 [DW_TAG_common_inclusion] = "common_inclusion",
2591 [DW_TAG_inheritance] = "inheritance",
2592 [DW_TAG_inlined_subroutine] = "inlined_subroutine",
2593 [DW_TAG_module] = "module",
2594 [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
2595 [DW_TAG_set_type] = "set_type",
2596 [DW_TAG_subrange_type] = "subrange_type",
2597 [DW_TAG_with_stmt] = "with_stmt",
2598 [DW_TAG_access_declaration] = "access_declaration",
2599 [DW_TAG_base_type] = "base_type",
2600 [DW_TAG_catch_block] = "catch_block",
2601 [DW_TAG_const_type] = "const_type",
2602 [DW_TAG_constant] = "constant",
2603 [DW_TAG_enumerator] = "enumerator",
2604 [DW_TAG_file_type] = "file_type",
2605 [DW_TAG_friend] = "friend",
2606 [DW_TAG_namelist] = "namelist",
2607 [DW_TAG_namelist_item] = "namelist_item",
2608 [DW_TAG_packed_type] = "packed_type",
2609 [DW_TAG_subprogram] = "subprogram",
2610 [DW_TAG_template_type_param] = "template_type_param",
2611 [DW_TAG_template_value_param] = "template_value_param",
2612 [DW_TAG_thrown_type] = "thrown_type",
2613 [DW_TAG_try_block] = "try_block",
2614 [DW_TAG_variant_part] = "variant_part",
2615 [DW_TAG_variable] = "variable",
2616 [DW_TAG_volatile_type] = "volatile_type",
2617 };
2618 const unsigned int nknown_tags = (sizeof (known_tags)
2619 / sizeof (known_tags[0]));
2620 static char buf[40];
2621 const char *result = NULL;
2622
2623 if (tag < nknown_tags)
2624 result = known_tags[tag];
2625
2626 if (result == NULL)
2627 /* There are a few known extensions. */
2628 switch (tag)
2629 {
2630 case DW_TAG_MIPS_loop:
2631 result = "MIPS_loop";
2632 break;
2633
2634 case DW_TAG_format_label:
2635 result = "format_label";
2636 break;
2637
2638 case DW_TAG_function_template:
2639 result = "function_template";
2640 break;
2641
2642 case DW_TAG_class_template:
2643 result = "class_template";
2644 break;
2645
2646 default:
2647 if (tag < DW_TAG_lo_user)
2648 snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag);
2649 else
2650 snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag);
2651 result = buf;
2652 break;
2653 }
2654
2655 return result;
2656 }
2657
2658
2659 static const char *
dwarf_attr_string(unsigned int attrnum)2660 dwarf_attr_string (unsigned int attrnum)
2661 {
2662 static const char *known_attrs[] =
2663 {
2664 [DW_AT_sibling] = "sibling",
2665 [DW_AT_location] = "location",
2666 [DW_AT_name] = "name",
2667 [DW_AT_ordering] = "ordering",
2668 [DW_AT_subscr_data] = "subscr_data",
2669 [DW_AT_byte_size] = "byte_size",
2670 [DW_AT_bit_offset] = "bit_offset",
2671 [DW_AT_bit_size] = "bit_size",
2672 [DW_AT_element_list] = "element_list",
2673 [DW_AT_stmt_list] = "stmt_list",
2674 [DW_AT_low_pc] = "low_pc",
2675 [DW_AT_high_pc] = "high_pc",
2676 [DW_AT_language] = "language",
2677 [DW_AT_member] = "member",
2678 [DW_AT_discr] = "discr",
2679 [DW_AT_discr_value] = "discr_value",
2680 [DW_AT_visibility] = "visibility",
2681 [DW_AT_import] = "import",
2682 [DW_AT_string_length] = "string_length",
2683 [DW_AT_common_reference] = "common_reference",
2684 [DW_AT_comp_dir] = "comp_dir",
2685 [DW_AT_const_value] = "const_value",
2686 [DW_AT_containing_type] = "containing_type",
2687 [DW_AT_default_value] = "default_value",
2688 [DW_AT_inline] = "inline",
2689 [DW_AT_is_optional] = "is_optional",
2690 [DW_AT_lower_bound] = "lower_bound",
2691 [DW_AT_producer] = "producer",
2692 [DW_AT_prototyped] = "prototyped",
2693 [DW_AT_return_addr] = "return_addr",
2694 [DW_AT_start_scope] = "start_scope",
2695 [DW_AT_stride_size] = "stride_size",
2696 [DW_AT_upper_bound] = "upper_bound",
2697 [DW_AT_abstract_origin] = "abstract_origin",
2698 [DW_AT_accessibility] = "accessibility",
2699 [DW_AT_address_class] = "address_class",
2700 [DW_AT_artificial] = "artificial",
2701 [DW_AT_base_types] = "base_types",
2702 [DW_AT_calling_convention] = "calling_convention",
2703 [DW_AT_count] = "count",
2704 [DW_AT_data_member_location] = "data_member_location",
2705 [DW_AT_decl_column] = "decl_column",
2706 [DW_AT_decl_file] = "decl_file",
2707 [DW_AT_decl_line] = "decl_line",
2708 [DW_AT_declaration] = "declaration",
2709 [DW_AT_discr_list] = "discr_list",
2710 [DW_AT_encoding] = "encoding",
2711 [DW_AT_external] = "external",
2712 [DW_AT_frame_base] = "frame_base",
2713 [DW_AT_friend] = "friend",
2714 [DW_AT_identifier_case] = "identifier_case",
2715 [DW_AT_macro_info] = "macro_info",
2716 [DW_AT_namelist_items] = "namelist_items",
2717 [DW_AT_priority] = "priority",
2718 [DW_AT_segment] = "segment",
2719 [DW_AT_specification] = "specification",
2720 [DW_AT_static_link] = "static_link",
2721 [DW_AT_type] = "type",
2722 [DW_AT_use_location] = "use_location",
2723 [DW_AT_variable_parameter] = "variable_parameter",
2724 [DW_AT_virtuality] = "virtuality",
2725 [DW_AT_vtable_elem_location] = "vtable_elem_location"
2726 };
2727 const unsigned int nknown_attrs = (sizeof (known_attrs)
2728 / sizeof (known_attrs[0]));
2729 static char buf[40];
2730 const char *result = NULL;
2731
2732 if (attrnum < nknown_attrs)
2733 result = known_attrs[attrnum];
2734
2735 if (result == NULL)
2736 /* There are a few known extensions. */
2737 switch (attrnum)
2738 {
2739 case DW_AT_MIPS_fde:
2740 result = "MIPS_fde";
2741 break;
2742
2743 case DW_AT_MIPS_loop_begin:
2744 result = "MIPS_loop_begin";
2745 break;
2746
2747 case DW_AT_MIPS_tail_loop_begin:
2748 result = "MIPS_tail_loop_begin";
2749 break;
2750
2751 case DW_AT_MIPS_epilog_begin:
2752 result = "MIPS_epilog_begin";
2753 break;
2754
2755 case DW_AT_MIPS_loop_unroll_factor:
2756 result = "MIPS_loop_unroll_factor";
2757 break;
2758
2759 case DW_AT_MIPS_software_pipeline_depth:
2760 result = "MIPS_software_pipeline_depth";
2761 break;
2762
2763 case DW_AT_MIPS_linkage_name:
2764 result = "MIPS_linkage_name";
2765 break;
2766
2767 case DW_AT_MIPS_stride:
2768 result = "MIPS_stride";
2769 break;
2770
2771 case DW_AT_MIPS_abstract_name:
2772 result = "MIPS_abstract_name";
2773 break;
2774
2775 case DW_AT_MIPS_clone_origin:
2776 result = "MIPS_clone_origin";
2777 break;
2778
2779 case DW_AT_MIPS_has_inlines:
2780 result = "MIPS_has_inlines";
2781 break;
2782
2783 case DW_AT_MIPS_stride_byte:
2784 result = "MIPS_stride_byte";
2785 break;
2786
2787 case DW_AT_MIPS_stride_elem:
2788 result = "MIPS_stride_elem";
2789 break;
2790
2791 case DW_AT_MIPS_ptr_dopetype:
2792 result = "MIPS_ptr_dopetype";
2793 break;
2794
2795 case DW_AT_MIPS_allocatable_dopetype:
2796 result = "MIPS_allocatable_dopetype";
2797 break;
2798
2799 case DW_AT_MIPS_assumed_shape_dopetype:
2800 result = "MIPS_assumed_shape_dopetype";
2801 break;
2802
2803 case DW_AT_MIPS_assumed_size:
2804 result = "MIPS_assumed_size";
2805 break;
2806
2807 case DW_AT_sf_names:
2808 result = "sf_names";
2809 break;
2810
2811 case DW_AT_src_info:
2812 result = "src_info";
2813 break;
2814
2815 case DW_AT_mac_info:
2816 result = "mac_info";
2817 break;
2818
2819 case DW_AT_src_coords:
2820 result = "src_coords";
2821 break;
2822
2823 case DW_AT_body_begin:
2824 result = "body_begin";
2825 break;
2826
2827 case DW_AT_body_end:
2828 result = "body_end";
2829 break;
2830
2831 default:
2832 if (attrnum < DW_AT_lo_user)
2833 snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"),
2834 attrnum);
2835 else
2836 snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"),
2837 attrnum);
2838 result = buf;
2839 break;
2840 }
2841
2842 return result;
2843 }
2844
2845
2846 static const char *
dwarf_form_string(unsigned int form)2847 dwarf_form_string (unsigned int form)
2848 {
2849 static const char *known_forms[] =
2850 {
2851 [DW_FORM_addr] = "addr",
2852 [DW_FORM_block2] = "block2",
2853 [DW_FORM_block4] = "block4",
2854 [DW_FORM_data2] = "data2",
2855 [DW_FORM_data4] = "data4",
2856 [DW_FORM_data8] = "data8",
2857 [DW_FORM_string] = "string",
2858 [DW_FORM_block] = "block",
2859 [DW_FORM_block1] = "block1",
2860 [DW_FORM_data1] = "data1",
2861 [DW_FORM_flag] = "flag",
2862 [DW_FORM_sdata] = "sdata",
2863 [DW_FORM_strp] = "strp",
2864 [DW_FORM_udata] = "udata",
2865 [DW_FORM_ref_addr] = "ref_addr",
2866 [DW_FORM_ref1] = "ref1",
2867 [DW_FORM_ref2] = "ref2",
2868 [DW_FORM_ref4] = "ref4",
2869 [DW_FORM_ref8] = "ref8",
2870 [DW_FORM_ref_udata] = "ref_udata",
2871 [DW_FORM_indirect] = "indirect"
2872 };
2873 const unsigned int nknown_forms = (sizeof (known_forms)
2874 / sizeof (known_forms[0]));
2875 static char buf[40];
2876 const char *result = NULL;
2877
2878 if (form < nknown_forms)
2879 result = known_forms[form];
2880
2881 if (result == NULL)
2882 snprintf (buf, sizeof buf, gettext ("unknown form %" PRIx64),
2883 (uint64_t) form);
2884
2885 return result;
2886 }
2887
2888
2889 static const char *
dwarf_lang_string(unsigned int lang)2890 dwarf_lang_string (unsigned int lang)
2891 {
2892 static const char *known[] =
2893 {
2894 [DW_LANG_C89] = "ISO C89",
2895 [DW_LANG_C] = "C",
2896 [DW_LANG_Ada83] = "Ada83",
2897 [DW_LANG_C_plus_plus ] = "C++",
2898 [DW_LANG_Cobol74] = "Cobol74",
2899 [DW_LANG_Cobol85] = "Cobol85",
2900 [DW_LANG_Fortran77] = "Fortran77",
2901 [DW_LANG_Fortran90] = "Fortran90",
2902 [DW_LANG_Pascal83] = "Pascal83",
2903 [DW_LANG_Modula2] = "Modula2",
2904 [DW_LANG_Java] = "Java",
2905 [DW_LANG_C99] = "ISO C99",
2906 [DW_LANG_Ada95] = "Ada95",
2907 [DW_LANG_Fortran95] = "Fortran95",
2908 [DW_LANG_PL1] = "PL1"
2909 };
2910
2911 if (lang < sizeof (known) / sizeof (known[0]))
2912 return known[lang];
2913 else if (lang == DW_LANG_Mips_Assembler)
2914 /* This language tag is used for assembler in general. */
2915 return "Assembler";
2916
2917 if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user)
2918 {
2919 static char buf[100];
2920 snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user);
2921 return buf;
2922 }
2923
2924 return "???";
2925 }
2926
2927
2928 static void
print_ops(Dwarf * dbg,int level,unsigned int addrsize,Dwarf_Word len,unsigned char * data)2929 print_ops (Dwarf *dbg, int level, unsigned int addrsize, Dwarf_Word len,
2930 unsigned char *data)
2931 {
2932 static const char *known[] =
2933 {
2934 [DW_OP_addr] = "addr",
2935 [DW_OP_deref] = "deref",
2936 [DW_OP_const1u] = "const1u",
2937 [DW_OP_const1s] = "const1s",
2938 [DW_OP_const2u] = "const2u",
2939 [DW_OP_const2s] = "const2s",
2940 [DW_OP_const4u] = "const4u",
2941 [DW_OP_const4s] = "const4s",
2942 [DW_OP_const8u] = "const8u",
2943 [DW_OP_const8s] = "const8s",
2944 [DW_OP_constu] = "constu",
2945 [DW_OP_consts] = "consts",
2946 [DW_OP_dup] = "dup",
2947 [DW_OP_drop] = "drop",
2948 [DW_OP_over] = "over",
2949 [DW_OP_pick] = "pick",
2950 [DW_OP_swap] = "swap",
2951 [DW_OP_rot] = "rot",
2952 [DW_OP_xderef] = "xderef",
2953 [DW_OP_abs] = "abs",
2954 [DW_OP_and] = "and",
2955 [DW_OP_div] = "div",
2956 [DW_OP_minus] = "minus",
2957 [DW_OP_mod] = "mod",
2958 [DW_OP_mul] = "mul",
2959 [DW_OP_neg] = "neg",
2960 [DW_OP_not] = "not",
2961 [DW_OP_or] = "or",
2962 [DW_OP_plus] = "plus",
2963 [DW_OP_plus_uconst] = "plus_uconst",
2964 [DW_OP_shl] = "shl",
2965 [DW_OP_shr] = "shr",
2966 [DW_OP_shra] = "shra",
2967 [DW_OP_xor] = "xor",
2968 [DW_OP_bra] = "bra",
2969 [DW_OP_eq] = "eq",
2970 [DW_OP_ge] = "ge",
2971 [DW_OP_gt] = "gt",
2972 [DW_OP_le] = "le",
2973 [DW_OP_lt] = "lt",
2974 [DW_OP_ne] = "ne",
2975 [DW_OP_skip] = "skip",
2976 [DW_OP_lit0] = "lit0",
2977 [DW_OP_lit1] = "lit1",
2978 [DW_OP_lit2] = "lit2",
2979 [DW_OP_lit3] = "lit3",
2980 [DW_OP_lit4] = "lit4",
2981 [DW_OP_lit5] = "lit5",
2982 [DW_OP_lit6] = "lit6",
2983 [DW_OP_lit7] = "lit7",
2984 [DW_OP_lit8] = "lit8",
2985 [DW_OP_lit9] = "lit9",
2986 [DW_OP_lit10] = "lit10",
2987 [DW_OP_lit11] = "lit11",
2988 [DW_OP_lit12] = "lit12",
2989 [DW_OP_lit13] = "lit13",
2990 [DW_OP_lit14] = "lit14",
2991 [DW_OP_lit15] = "lit15",
2992 [DW_OP_lit16] = "lit16",
2993 [DW_OP_lit17] = "lit17",
2994 [DW_OP_lit18] = "lit18",
2995 [DW_OP_lit19] = "lit19",
2996 [DW_OP_lit20] = "lit20",
2997 [DW_OP_lit21] = "lit21",
2998 [DW_OP_lit22] = "lit22",
2999 [DW_OP_lit23] = "lit23",
3000 [DW_OP_lit24] = "lit24",
3001 [DW_OP_lit25] = "lit25",
3002 [DW_OP_lit26] = "lit26",
3003 [DW_OP_lit27] = "lit27",
3004 [DW_OP_lit28] = "lit28",
3005 [DW_OP_lit29] = "lit29",
3006 [DW_OP_lit30] = "lit30",
3007 [DW_OP_lit31] = "lit31",
3008 [DW_OP_reg0] = "reg0",
3009 [DW_OP_reg1] = "reg1",
3010 [DW_OP_reg2] = "reg2",
3011 [DW_OP_reg3] = "reg3",
3012 [DW_OP_reg4] = "reg4",
3013 [DW_OP_reg5] = "reg5",
3014 [DW_OP_reg6] = "reg6",
3015 [DW_OP_reg7] = "reg7",
3016 [DW_OP_reg8] = "reg8",
3017 [DW_OP_reg9] = "reg9",
3018 [DW_OP_reg10] = "reg10",
3019 [DW_OP_reg11] = "reg11",
3020 [DW_OP_reg12] = "reg12",
3021 [DW_OP_reg13] = "reg13",
3022 [DW_OP_reg14] = "reg14",
3023 [DW_OP_reg15] = "reg15",
3024 [DW_OP_reg16] = "reg16",
3025 [DW_OP_reg17] = "reg17",
3026 [DW_OP_reg18] = "reg18",
3027 [DW_OP_reg19] = "reg19",
3028 [DW_OP_reg20] = "reg20",
3029 [DW_OP_reg21] = "reg21",
3030 [DW_OP_reg22] = "reg22",
3031 [DW_OP_reg23] = "reg23",
3032 [DW_OP_reg24] = "reg24",
3033 [DW_OP_reg25] = "reg25",
3034 [DW_OP_reg26] = "reg26",
3035 [DW_OP_reg27] = "reg27",
3036 [DW_OP_reg28] = "reg28",
3037 [DW_OP_reg29] = "reg29",
3038 [DW_OP_reg30] = "reg30",
3039 [DW_OP_reg31] = "reg31",
3040 [DW_OP_breg0] = "breg0",
3041 [DW_OP_breg1] = "breg1",
3042 [DW_OP_breg2] = "breg2",
3043 [DW_OP_breg3] = "breg3",
3044 [DW_OP_breg4] = "breg4",
3045 [DW_OP_breg5] = "breg5",
3046 [DW_OP_breg6] = "breg6",
3047 [DW_OP_breg7] = "breg7",
3048 [DW_OP_breg8] = "breg8",
3049 [DW_OP_breg9] = "breg9",
3050 [DW_OP_breg10] = "breg10",
3051 [DW_OP_breg11] = "breg11",
3052 [DW_OP_breg12] = "breg12",
3053 [DW_OP_breg13] = "breg13",
3054 [DW_OP_breg14] = "breg14",
3055 [DW_OP_breg15] = "breg15",
3056 [DW_OP_breg16] = "breg16",
3057 [DW_OP_breg17] = "breg17",
3058 [DW_OP_breg18] = "breg18",
3059 [DW_OP_breg19] = "breg19",
3060 [DW_OP_breg20] = "breg20",
3061 [DW_OP_breg21] = "breg21",
3062 [DW_OP_breg22] = "breg22",
3063 [DW_OP_breg23] = "breg23",
3064 [DW_OP_breg24] = "breg24",
3065 [DW_OP_breg25] = "breg25",
3066 [DW_OP_breg26] = "breg26",
3067 [DW_OP_breg27] = "breg27",
3068 [DW_OP_breg28] = "breg28",
3069 [DW_OP_breg29] = "breg29",
3070 [DW_OP_breg30] = "breg30",
3071 [DW_OP_breg31] = "breg31",
3072 [DW_OP_regx] = "regx",
3073 [DW_OP_fbreg] = "fbreg",
3074 [DW_OP_bregx] = "bregx",
3075 [DW_OP_piece] = "piece",
3076 [DW_OP_deref_size] = "deref_size",
3077 [DW_OP_xderef_size] = "xderef_size",
3078 [DW_OP_nop] = "nop",
3079 [DW_OP_push_object_address] = "push_object_address",
3080 [DW_OP_call2] = "call2",
3081 [DW_OP_call4] = "call4",
3082 [DW_OP_call_ref] = "call_ref",
3083 };
3084
3085 Dwarf_Word offset = 0;
3086 while (len-- > 0)
3087 {
3088 size_t op = *((unsigned char *) data);
3089 ++data;
3090
3091 switch (op)
3092 {
3093 case DW_OP_call_ref:
3094 case DW_OP_addr:;
3095 /* Address operand. */
3096 Dwarf_Word addr;
3097 if (addrsize == 4)
3098 addr = read_4ubyte_unaligned (dbg, data);
3099 else
3100 {
3101 assert (addrsize == 8);
3102 addr = read_8ubyte_unaligned (dbg, data);
3103 }
3104 data += addrsize;
3105 len -= addrsize;
3106
3107 printf (" %*s [%4" PRIuMAX "] %s %" PRIuMAX "\n",
3108 (int) (20 + level * 2), "", (uintmax_t) offset,
3109 known[op] ?: "???", (uintmax_t) addr);
3110 offset += 1 + addrsize;
3111 break;
3112
3113 case DW_OP_deref_size: /* XXX Correct? */
3114 case DW_OP_xderef_size: /* XXX Correct? */
3115 case DW_OP_pick:
3116 case DW_OP_const1u:
3117 printf (" %*s [%4" PRIuMAX "] %s %" PRIu8 "\n",
3118 (int) (20 + level * 2), "", (uintmax_t) offset,
3119 known[op] ?: "???", *((uint8_t *) data));
3120 ++data;
3121 --len;
3122 offset += 2;
3123 break;
3124
3125 case DW_OP_const2u:
3126 printf (" %*s [%4" PRIuMAX "] %s %" PRIu16 "\n",
3127 (int) (20 + level * 2), "", (uintmax_t) offset,
3128 known[op] ?: "???", read_2ubyte_unaligned (dbg, data));
3129 len -= 2;
3130 data += 2;
3131 offset += 3;
3132 break;
3133
3134 case DW_OP_const4u:
3135 printf (" %*s [%4" PRIuMAX "] %s %" PRIu32 "\n",
3136 (int) (20 + level * 2), "", (uintmax_t) offset,
3137 known[op] ?: "???", read_4ubyte_unaligned (dbg, data));
3138 len -= 4;
3139 data += 4;
3140 offset += 5;
3141 break;
3142
3143 case DW_OP_const8u:
3144 printf (" %*s [%4" PRIuMAX "] %s %" PRIu64 "\n",
3145 (int) (20 + level * 2), "", (uintmax_t) offset,
3146 known[op] ?: "???", read_8ubyte_unaligned (dbg, data));
3147 len -= 8;
3148 data += 8;
3149 offset += 9;
3150 break;
3151
3152 case DW_OP_const1s:
3153 printf (" %*s [%4" PRIuMAX "] %s %" PRId8 "\n",
3154 (int) (20 + level * 2), "", (uintmax_t) offset,
3155 known[op] ?: "???", *((int8_t *) data));
3156 ++data;
3157 --len;
3158 offset += 2;
3159 break;
3160
3161 case DW_OP_const2s:
3162 printf (" %*s [%4" PRIuMAX "] %s %" PRId16 "\n",
3163 (int) (20 + level * 2), "", (uintmax_t) offset,
3164 known[op] ?: "???", read_2sbyte_unaligned (dbg, data));
3165 len -= 2;
3166 data += 2;
3167 offset += 3;
3168 break;
3169
3170 case DW_OP_const4s:
3171 printf (" %*s [%4" PRIuMAX "] %s %" PRId32 "\n",
3172 (int) (20 + level * 2), "", (uintmax_t) offset,
3173 known[op] ?: "???", read_4sbyte_unaligned (dbg, data));
3174 len -= 4;
3175 data += 4;
3176 offset += 5;
3177 break;
3178
3179 case DW_OP_const8s:
3180 printf (" %*s [%4" PRIuMAX "] %s %" PRId64 "\n",
3181 (int) (20 + level * 2), "", (uintmax_t) offset,
3182 known[op] ?: "???", read_8sbyte_unaligned (dbg, data));
3183 len -= 8;
3184 data += 8;
3185 offset += 9;
3186 break;
3187
3188 case DW_OP_piece: /* XXX Correct? */
3189 case DW_OP_regx:
3190 case DW_OP_plus_uconst:
3191 case DW_OP_constu:;
3192 unsigned char *start = data;
3193 unsigned int uleb;
3194 get_uleb128 (uleb, data);
3195 printf (" %*s [%4" PRIuMAX "] %s %u\n",
3196 (int) (20 + level * 2), "", (uintmax_t) offset,
3197 known[op] ?: "???", uleb);
3198 len -= data - start;
3199 offset += 1 + (data - start);
3200 break;
3201
3202 case DW_OP_fbreg:
3203 case DW_OP_breg0 ... DW_OP_breg31:
3204 case DW_OP_consts:
3205 start = data;
3206 unsigned int sleb;
3207 get_sleb128 (sleb, data);
3208 printf (" %*s [%4" PRIuMAX "] %s %d\n",
3209 (int) (20 + level * 2), "", (uintmax_t) offset,
3210 known[op] ?: "???", sleb);
3211 len -= data - start;
3212 offset += 1 + (data - start);
3213 break;
3214
3215 case DW_OP_bregx:
3216 start = data;
3217 get_uleb128 (uleb, data);
3218 get_sleb128 (sleb, data);
3219 printf (" %*s [%4" PRIuMAX "] %s %u %d\n",
3220 (int) (20 + level * 2), "", (uintmax_t) offset,
3221 known[op] ?: "???", uleb, sleb);
3222 len -= data - start;
3223 offset += 1 + (data - start);
3224 break;
3225
3226 case DW_OP_call2:
3227 case DW_OP_call4:
3228 case DW_OP_skip:
3229 case DW_OP_bra:
3230 printf (" %*s [%4" PRIuMAX "] %s %" PRIuMAX "\n",
3231 (int) (20 + level * 2), "", (uintmax_t) offset,
3232 known[op] ?: "???",
3233 (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
3234 len -= 2;
3235 data += 2;
3236 offset += 3;
3237 break;
3238
3239 default:
3240 /* No Operand. */
3241 printf (" %*s [%4" PRIuMAX "] %s\n",
3242 (int) (20 + level * 2), "", (uintmax_t) offset,
3243 known[op] ?: "???");
3244 ++offset;
3245 break;
3246 }
3247 }
3248 }
3249
3250
3251 static void
print_debug_abbrev_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)3252 print_debug_abbrev_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
3253 GElf_Shdr *shdr, Dwarf *dbg)
3254 {
3255 printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
3256 " [ Code]\n"),
3257 ".debug_abbrev", (uint64_t) shdr->sh_offset);
3258
3259 Dwarf_Off offset = 0;
3260 while (1)
3261 {
3262 size_t length;
3263 Dwarf_Abbrev abbrev;
3264
3265 if (dwarf_offabbrev (dbg, offset, &length, &abbrev) != 0)
3266 {
3267 printf (gettext (" *** error while reading abbreviation: %s\n"),
3268 dwarf_errmsg (-1));
3269 break;
3270 }
3271
3272 if (length == 1)
3273 /* This is the NUL byte at the end of the section. */
3274 break;
3275
3276 /* We know these calls can never fail. */
3277 unsigned int code = dwarf_getabbrevcode (&abbrev);
3278 unsigned int tag = dwarf_getabbrevtag (&abbrev);
3279 int has_children = dwarf_abbrevhaschildren (&abbrev);
3280
3281 printf (gettext (" [%5u] offset: %" PRId64
3282 ", children: %s, tag: %s\n"),
3283 code, (int64_t) offset,
3284 has_children ? gettext ("yes") : gettext ("no"),
3285 dwarf_tag_string (tag));
3286
3287 size_t cnt = 0;
3288 unsigned int name;
3289 unsigned int form;
3290 Dwarf_Off enoffset;
3291 while (dwarf_getabbrevattr (&abbrev, cnt, &name, &form, &enoffset) == 0)
3292 {
3293 printf (" attr: %s, form: %s, offset: %#" PRIx64 "\n",
3294 dwarf_attr_string (name), dwarf_form_string (form),
3295 (uint64_t) enoffset);
3296
3297 ++cnt;
3298 }
3299
3300 offset += length;
3301 }
3302 }
3303
3304
3305 /* Print content of DWARF .debug_aranges section. We fortunately do
3306 not have to know a bit about the structure of the section, libdwarf
3307 takes care of it. */
3308 static void
print_debug_aranges_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)3309 print_debug_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
3310 GElf_Shdr *shdr, Dwarf *dbg)
3311 {
3312 Dwarf_Aranges *aranges;
3313 size_t cnt;
3314 if (dwarf_getaranges (dbg, &aranges, &cnt) != 0)
3315 {
3316 error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
3317 dwarf_errmsg (-1));
3318 return;
3319 }
3320
3321 printf (ngettext ("\
3322 \nDWARF section '%s' at offset %#" PRIx64 " contains %zu entry:\n",
3323 "\
3324 \nDWARF section '%s' at offset %#" PRIx64 " contains %zu entries:\n",
3325 cnt),
3326 ".debug_aranges", (uint64_t) shdr->sh_offset, cnt);
3327
3328 /* Compute floor(log16(cnt)). */
3329 size_t tmp = cnt;
3330 int digits = 1;
3331 while (tmp >= 16)
3332 {
3333 ++digits;
3334 tmp >>= 4;
3335 }
3336
3337 for (size_t n = 0; n < cnt; ++n)
3338 {
3339 Dwarf_Arange *runp = dwarf_onearange (aranges, n);
3340 if (runp == NULL)
3341 {
3342 printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
3343 return;
3344 }
3345
3346 Dwarf_Addr start;
3347 Dwarf_Word length;
3348 Dwarf_Off offset;
3349
3350 if (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0)
3351 printf (gettext (" [%*zu] ???\n"), digits, n);
3352 else
3353 printf (gettext (" [%*zu] start: %0#*" PRIx64
3354 ", length: %5" PRIu64 ", CU DIE offset: %6"
3355 PRId64 "\n"),
3356 digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
3357 (uint64_t) start, (uint64_t) length, (int64_t) offset);
3358 }
3359 }
3360
3361
3362 static void
print_debug_frame_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)3363 print_debug_frame_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
3364 GElf_Shdr *shdr, Dwarf *dbg)
3365 {
3366 }
3367
3368
3369 struct attrcb_args
3370 {
3371 Dwarf *dbg;
3372 int level;
3373 unsigned int addrsize;
3374 Dwarf_Off cu_offset;
3375 };
3376
3377
3378 static int
attr_callback(Dwarf_Attribute * attrp,void * arg)3379 attr_callback (Dwarf_Attribute *attrp, void *arg)
3380 {
3381 struct attrcb_args *cbargs = (struct attrcb_args *) arg;
3382 const int level = cbargs->level;
3383
3384 unsigned int attr = dwarf_whatattr (attrp);
3385 if (unlikely (attr == 0))
3386 {
3387 error (0, 0, gettext ("cannot get attribute code: %s"),
3388 dwarf_errmsg (-1));
3389 return DWARF_CB_ABORT;
3390 }
3391
3392 unsigned int form = dwarf_whatform (attrp);
3393 if (unlikely (form == 0))
3394 {
3395 error (0, 0, gettext ("cannot get attribute form: %s"),
3396 dwarf_errmsg (-1));
3397 return DWARF_CB_ABORT;
3398 }
3399
3400 switch (form)
3401 {
3402 case DW_FORM_addr:;
3403 Dwarf_Addr addr;
3404 if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
3405 {
3406 attrval_out:
3407 error (0, 0, gettext ("cannot get attribute value: %s"),
3408 dwarf_errmsg (-1));
3409 return DWARF_CB_ABORT;
3410 }
3411 printf (" %*s%-20s %#0*" PRIxMAX "\n",
3412 (int) (level * 2), "", dwarf_attr_string (attr),
3413 (int) (cbargs->addrsize * 2), (uintmax_t) addr);
3414 break;
3415
3416 case DW_FORM_indirect:
3417 case DW_FORM_strp:
3418 case DW_FORM_string:;
3419 const char *str = dwarf_formstring (attrp);
3420 if (unlikely (str == NULL))
3421 goto attrval_out;
3422 printf (" %*s%-20s \"%s\"\n",
3423 (int) (level * 2), "", dwarf_attr_string (attr), str);
3424 break;
3425
3426 case DW_FORM_ref_addr:
3427 case DW_FORM_ref_udata:
3428 case DW_FORM_ref8:
3429 case DW_FORM_ref4:
3430 case DW_FORM_ref2:
3431 case DW_FORM_ref1:;
3432 Dwarf_Off ref;
3433 if (unlikely (dwarf_formref (attrp, &ref) != 0))
3434 goto attrval_out;
3435
3436 printf (" %*s%-20s [%6" PRIxMAX "]\n",
3437 (int) (level * 2), "", dwarf_attr_string (attr),
3438 (uintmax_t) (ref + cbargs->cu_offset));
3439 break;
3440
3441 case DW_FORM_udata:
3442 case DW_FORM_sdata:
3443 case DW_FORM_data8:
3444 case DW_FORM_data4:
3445 case DW_FORM_data2:
3446 case DW_FORM_data1:;
3447 Dwarf_Word num;
3448 if (unlikely (dwarf_formudata (attrp, &num) != 0))
3449 goto attrval_out;
3450
3451 if (attr == DW_AT_language)
3452 {
3453 printf (" %*s%-20s %s (%d)\n",
3454 (int) (level * 2), "", dwarf_attr_string (attr),
3455 dwarf_lang_string (num), (int) num);
3456 break;
3457 }
3458
3459 printf (" %*s%-20s %" PRIuMAX "\n",
3460 (int) (level * 2), "", dwarf_attr_string (attr),
3461 (uintmax_t) num);
3462 break;
3463
3464 case DW_FORM_flag:;
3465 bool flag;
3466 if (unlikely (dwarf_formflag (attrp, &flag) != 0))
3467 goto attrval_out;
3468
3469 printf (" %*s%-20s %s\n",
3470 (int) (level * 2), "", dwarf_attr_string (attr),
3471 nl_langinfo (flag ? YESSTR : NOSTR));
3472 break;
3473
3474 case DW_FORM_block4:
3475 case DW_FORM_block2:
3476 case DW_FORM_block1:
3477 case DW_FORM_block:;
3478 Dwarf_Block block;
3479 if (unlikely (dwarf_formblock (attrp, &block) != 0))
3480 goto attrval_out;
3481
3482 printf (" %*s%-20s %" PRIxMAX " byte block\n",
3483 (int) (level * 2), "", dwarf_attr_string (attr),
3484 (uintmax_t) block.length);
3485
3486 if (attr == DW_AT_data_member_location)
3487 print_ops (cbargs->dbg, level, cbargs->addrsize, block.length,
3488 block.data);
3489 break;
3490
3491 default:
3492 printf (" %*s%-20s [form: %d] ???\n",
3493 (int) (level * 2), "", dwarf_attr_string (attr),
3494 (int) form);
3495 break;
3496 }
3497
3498 return DWARF_CB_OK;
3499 }
3500
3501
3502 static void
print_debug_info_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)3503 print_debug_info_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
3504 GElf_Shdr *shdr, Dwarf *dbg)
3505 {
3506 printf (gettext ("\
3507 \nDWARF section '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
3508 ".debug_info", (uint64_t) shdr->sh_offset);
3509
3510 /* If the section is empty we don't have to do anything. */
3511 if (shdr->sh_size == 0)
3512 return;
3513
3514 size_t maxdies = 20;
3515 Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
3516
3517 Dwarf_Off offset = 0;
3518
3519 /* New compilation unit. */
3520 size_t cuhl;
3521 //Dwarf_Half version;
3522 Dwarf_Off abbroffset;
3523 uint8_t addrsize;
3524 uint8_t offsize;
3525 Dwarf_Off nextcu;
3526 next_cu:
3527 if (dwarf_nextcu (dbg, offset, &nextcu, &cuhl, &abbroffset, &addrsize,
3528 &offsize) != 0)
3529 goto do_return;
3530
3531 printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
3532 " Version: %" PRIu16 ", Abbreviation section offset: %"
3533 PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8 "\n"),
3534 (uint64_t) offset, /*version*/2, abbroffset, addrsize, offsize);
3535
3536
3537 struct attrcb_args args;
3538 args.dbg = dbg;
3539 args.addrsize = addrsize;
3540 args.cu_offset = offset;
3541
3542 offset += cuhl;
3543
3544 int level = 0;
3545
3546 if (unlikely (dwarf_offdie (dbg, offset, &dies[level]) == NULL))
3547 {
3548 error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
3549 " in section '%s': %s"),
3550 (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
3551 goto do_return;
3552 }
3553
3554 do
3555 {
3556 offset = dwarf_dieoffset (&dies[level]);
3557 if (offset == -1l)
3558 {
3559 error (0, 0, gettext ("cannot get DIE offset: %s"),
3560 dwarf_errmsg (-1));
3561 goto do_return;
3562 }
3563
3564 int tag = dwarf_tag (&dies[level]);
3565 if (tag == DW_TAG_invalid)
3566 {
3567 error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
3568 " in section '%s': %s"),
3569 (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
3570 goto do_return;
3571 }
3572
3573 static const char *const lowtags[] =
3574 {
3575 [DW_TAG_array_type] = "array_type",
3576 [DW_TAG_class_type] = "class_type",
3577 [DW_TAG_entry_point] = "entry_point",
3578 [DW_TAG_enumeration_type] = "enumeration_type",
3579 [DW_TAG_formal_parameter] = "formal_parameter",
3580 [DW_TAG_imported_declaration] = "imported_declaration",
3581 [DW_TAG_label] = "label",
3582 [DW_TAG_lexical_block] = "lexical_block",
3583 [DW_TAG_member] = "member",
3584 [DW_TAG_pointer_type] = "pointer_type",
3585 [DW_TAG_reference_type] = "reference_type",
3586 [DW_TAG_compile_unit] = "compile_unit",
3587 [DW_TAG_string_type] = "string_type",
3588 [DW_TAG_structure_type] = "structure_type",
3589 [DW_TAG_subroutine_type] = "subroutine_type",
3590 [DW_TAG_typedef] = "typedef",
3591 [DW_TAG_union_type] = "union_type",
3592 [DW_TAG_unspecified_parameters] = "unspecified_parameters",
3593 [DW_TAG_variant] = "variant",
3594 [DW_TAG_common_block] = "common_block",
3595 [DW_TAG_common_inclusion] = "common_inclusion",
3596 [DW_TAG_inheritance] = "inheritance",
3597 [DW_TAG_inlined_subroutine] = "inlined_subroutine",
3598 [DW_TAG_module] = "module",
3599 [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
3600 [DW_TAG_set_type] = "set_type",
3601 [DW_TAG_subrange_type] = "subrange_type",
3602 [DW_TAG_with_stmt] = "with_stmt",
3603 [DW_TAG_access_declaration] = "access_declaration",
3604 [DW_TAG_base_type] = "base_type",
3605 [DW_TAG_catch_block] = "catch_block",
3606 [DW_TAG_const_type] = "const_type",
3607 [DW_TAG_constant] = "constant",
3608 [DW_TAG_enumerator] = "enumerator",
3609 [DW_TAG_file_type] = "file_type",
3610 [DW_TAG_friend] = "friend",
3611 [DW_TAG_namelist] = "namelist",
3612 [DW_TAG_namelist_item] = "namelist_item",
3613 [DW_TAG_packed_type] = "packed_type",
3614 [DW_TAG_subprogram] = "subprogram",
3615 [DW_TAG_template_type_param] = "template_type_param",
3616 [DW_TAG_template_value_param] = "template_value_param",
3617 [DW_TAG_thrown_type] = "thrown_type",
3618 [DW_TAG_try_block] = "try_block",
3619 [DW_TAG_variant_part] = "variant_part",
3620 [DW_TAG_variable] = "variable",
3621 [DW_TAG_volatile_type] = "volatile_type"
3622 };
3623
3624 const char *tagstr;
3625 switch (tag)
3626 {
3627 case DW_TAG_lo_user:
3628 tagstr = "lo_user";
3629 break;
3630
3631 case DW_TAG_MIPS_loop:
3632 tagstr = "MIPS_loop";
3633 break;
3634
3635 case DW_TAG_format_label:
3636 tagstr = "format_label";
3637 break;
3638
3639 case DW_TAG_function_template:
3640 tagstr = "function_template";
3641 break;
3642
3643 case DW_TAG_class_template:
3644 tagstr = "class_template";
3645 break;
3646 case DW_TAG_hi_user:
3647 tagstr = "hi_user";
3648 break;
3649
3650 default:
3651 if (tag < sizeof (lowtags) / sizeof (lowtags[0]))
3652 tagstr = lowtags[tag];
3653 else
3654 tagstr = "???";
3655 break;
3656 }
3657
3658 printf (" [%6" PRIx64 "] %*s%s\n",
3659 (uint64_t) offset, (int) (level * 2), "", tagstr);
3660
3661 /* Print the attribute values. */
3662 args.level = level;
3663 (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
3664
3665 /* Make room for the next level's DIE. */
3666 if (level + 1 == maxdies)
3667 dies = (Dwarf_Die *) xrealloc (dies,
3668 (maxdies += 10)
3669 * sizeof (Dwarf_Die));
3670
3671 int res = dwarf_child (&dies[level], &dies[level + 1]);
3672 if (res > 0)
3673 {
3674 while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
3675 if (level-- == 0)
3676 break;
3677
3678 if (res == -1)
3679 {
3680 error (0, 0, gettext ("cannot get next DIE: %s\n"),
3681 dwarf_errmsg (-1));
3682 goto do_return;
3683 }
3684 }
3685 else if (unlikely (res < 0))
3686 {
3687 error (0, 0, gettext ("cannot get next DIE: %s"),
3688 dwarf_errmsg (-1));
3689 goto do_return;
3690 }
3691 else
3692 ++level;
3693 }
3694 while (level >= 0);
3695
3696 offset = nextcu;
3697 if (offset != 0)
3698 goto next_cu;
3699
3700 do_return:
3701 free (dies);
3702 }
3703
3704
3705 static void
print_debug_line_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)3706 print_debug_line_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
3707 GElf_Shdr *shdr, Dwarf *dbg)
3708 {
3709 printf (gettext ("\
3710 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
3711 ".debug_line", (uint64_t) shdr->sh_offset);
3712
3713 if (shdr->sh_size == 0)
3714 return;
3715
3716 /* There is no functionality in libdw to read the information in the
3717 way it is represented here. Hardcode the decoder. */
3718 Elf_Data *data = elf_getdata (scn, NULL);
3719 if (data == NULL || data->d_buf == NULL)
3720 {
3721 error (0, 0, gettext ("cannot get line data section data: %s"),
3722 elf_errmsg (-1));
3723 return;
3724 }
3725
3726 const unsigned char *linep = (const unsigned char *) data->d_buf;
3727 const unsigned char *lineendp;
3728
3729 while (linep
3730 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
3731 {
3732 size_t start_offset = linep - (const unsigned char *) data->d_buf;
3733
3734 Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
3735 unsigned int length = 4;
3736 if (unlikely (unit_length == 0xffffffff))
3737 {
3738 if (unlikely (linep + 8 > lineendp))
3739 {
3740 invalid_data:
3741 error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
3742 elf_ndxscn (scn), ".debug_line");
3743 return;
3744 }
3745 unit_length = read_8ubyte_unaligned_inc (dbg, linep);
3746 length = 8;
3747 }
3748
3749 /* Check whether we have enough room in the section. */
3750 if (unit_length < 2 + length + 5 * 1
3751 || unlikely (linep + unit_length > lineendp))
3752 goto invalid_data;
3753 lineendp = linep + unit_length;
3754
3755 /* The next element of the header is the version identifier. */
3756 uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
3757
3758 /* Next comes the header length. */
3759 Dwarf_Word header_length;
3760 if (length == 4)
3761 header_length = read_4ubyte_unaligned_inc (dbg, linep);
3762 else
3763 header_length = read_8ubyte_unaligned_inc (dbg, linep);
3764 //const unsigned char *header_start = linep;
3765
3766 /* Next the minimum instruction length. */
3767 uint_fast8_t minimum_instr_len = *linep++;
3768
3769 /* Then the flag determining the default value of the is_stmt
3770 register. */
3771 uint_fast8_t default_is_stmt = *linep++;
3772
3773 /* Now the line base. */
3774 int_fast8_t line_base = *((const int_fast8_t *) linep);
3775 ++linep;
3776
3777 /* And the line range. */
3778 uint_fast8_t line_range = *linep++;
3779
3780 /* The opcode base. */
3781 uint_fast8_t opcode_base = *linep++;
3782
3783 /* Print what we got so far. */
3784 printf (gettext ("\n"
3785 " Length: %" PRIu64 "\n"
3786 " DWARF version: %" PRIuFAST16 "\n"
3787 " Prologue length: %" PRIu64 "\n"
3788 " Minimum instruction length: %" PRIuFAST8 "\n"
3789 " Initial value if '%s': %" PRIuFAST8 "\n"
3790 " Line base: %" PRIdFAST8 "\n"
3791 " Line range: %" PRIuFAST8 "\n"
3792 " Opcode base: %" PRIuFAST8 "\n"
3793 "\n"
3794 "Opcodes:\n"),
3795 (uint64_t) unit_length, version, (uint64_t) header_length,
3796 minimum_instr_len, "is_stmt", default_is_stmt, line_base,
3797 line_range, opcode_base);
3798
3799 if (unlikely (linep + opcode_base - 1 >= lineendp))
3800 goto invalid_data;
3801 int opcode_base_l10 = 1;
3802 unsigned int tmp = opcode_base;
3803 while (tmp > 10)
3804 {
3805 tmp /= 10;
3806 ++opcode_base_l10;
3807 }
3808 const uint8_t *standard_opcode_lengths = linep - 1;
3809 for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
3810 printf (ngettext (" [%*" PRIuFAST8 "] %hhu argument\n",
3811 " [%*" PRIuFAST8 "] %hhu arguments\n",
3812 (int) linep[cnt - 1]),
3813 opcode_base_l10, cnt, linep[cnt - 1]);
3814 linep += opcode_base - 1;
3815 if (unlikely (linep >= lineendp))
3816 goto invalid_data;
3817
3818 puts (gettext ("\nDirectory table:"));
3819 while (*linep != 0)
3820 {
3821 unsigned char *endp = memchr (linep, '\0', lineendp - linep);
3822 if (endp == NULL)
3823 goto invalid_data;
3824
3825 printf (" %s\n", (char *) linep);
3826
3827 linep = endp + 1;
3828 }
3829 /* Skip the final NUL byte. */
3830 ++linep;
3831
3832 if (unlikely (linep >= lineendp))
3833 goto invalid_data;
3834 puts (gettext ("\nFile name table:\n"
3835 " Entry Dir Time Size Name"));
3836 for (unsigned int cnt = 1; *linep != 0; ++cnt)
3837 {
3838 /* First comes the file name. */
3839 char *fname = (char *) linep;
3840 unsigned char *endp = memchr (fname, '\0', lineendp - linep);
3841 if (endp == NULL)
3842 goto invalid_data;
3843 linep = endp + 1;
3844
3845 /* Then the index. */
3846 unsigned int diridx;
3847 get_uleb128 (diridx, linep);
3848
3849 /* Next comes the modification time. */
3850 unsigned int mtime;
3851 get_uleb128 (mtime, linep);
3852
3853 /* Finally the length of the file. */
3854 unsigned int fsize;
3855 get_uleb128 (fsize, linep);
3856
3857 printf (" %-5u %-5u %-9u %-9u %s\n",
3858 cnt, diridx, mtime, fsize, fname);
3859 }
3860 /* Skip the final NUL byte. */
3861 ++linep;
3862
3863 puts (gettext ("\nLine number statements:"));
3864 Dwarf_Word address = 0;
3865 size_t line = 1;
3866 uint_fast8_t is_stmt = default_is_stmt;
3867
3868 /* Default address value, in case we do not find the CU. */
3869 size_t address_size
3870 = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
3871
3872 /* Determine the CU this block is for. */
3873 Dwarf_Off cuoffset;
3874 Dwarf_Off ncuoffset = 0;
3875 size_t hsize;
3876 while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
3877 NULL, NULL, NULL) == 0)
3878 {
3879 Dwarf_Die cudie;
3880 if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
3881 continue;
3882 Dwarf_Attribute stmt_list;
3883 if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
3884 continue;
3885 Dwarf_Word lineoff;
3886 if (dwarf_formudata (&stmt_list, &lineoff) != 0)
3887 continue;
3888 if (lineoff == start_offset)
3889 {
3890 /* Found the CU. */
3891 address_size = cudie.cu->address_size;
3892 break;
3893 }
3894 }
3895
3896 while (linep < lineendp)
3897 {
3898 unsigned int u128;
3899 int s128;
3900
3901 /* Read the opcode. */
3902 unsigned int opcode = *linep++;
3903
3904 /* Is this a special opcode? */
3905 if (likely (opcode >= opcode_base))
3906 {
3907 /* Yes. Handling this is quite easy since the opcode value
3908 is computed with
3909
3910 opcode = (desired line increment - line_base)
3911 + (line_range * address advance) + opcode_base
3912 */
3913 int line_increment = (line_base
3914 + (opcode - opcode_base) % line_range);
3915 unsigned int address_increment = (minimum_instr_len
3916 * ((opcode - opcode_base)
3917 / line_range));
3918
3919 /* Perform the increments. */
3920 line += line_increment;
3921 address += address_increment;
3922
3923 printf (gettext ("\
3924 special opcode %u: address+%u = %#" PRIx64 ", line%+d = %zu\n"),
3925 opcode, address_increment, (uint64_t) address,
3926 line_increment, line);
3927 }
3928 else if (opcode == 0)
3929 {
3930 /* This an extended opcode. */
3931 if (unlikely (linep + 2 > lineendp))
3932 goto invalid_data;
3933
3934 /* The length. */
3935 unsigned int len = *linep++;
3936
3937 if (unlikely (linep + len > lineendp))
3938 goto invalid_data;
3939
3940 /* The sub-opcode. */
3941 opcode = *linep++;
3942
3943 printf (gettext (" extended opcode %u: "), opcode);
3944
3945 switch (opcode)
3946 {
3947 case DW_LNE_end_sequence:
3948 puts (gettext ("end of sequence"));
3949
3950 /* Reset the registers we care about. */
3951 address = 0;
3952 line = 1;
3953 is_stmt = default_is_stmt;
3954 break;
3955
3956 case DW_LNE_set_address:
3957 if (address_size == 4)
3958 address = read_4ubyte_unaligned_inc (dbg, linep);
3959 else
3960 address = read_8ubyte_unaligned_inc (dbg, linep);
3961 printf (gettext ("set address to %#" PRIx64 "\n"),
3962 (uint64_t) address);
3963 break;
3964
3965 case DW_LNE_define_file:
3966 {
3967 char *fname = (char *) linep;
3968 unsigned char *endp = memchr (linep, '\0',
3969 lineendp - linep);
3970 if (endp == NULL)
3971 goto invalid_data;
3972 linep = endp + 1;
3973
3974 unsigned int diridx;
3975 get_uleb128 (diridx, linep);
3976 Dwarf_Word mtime;
3977 get_uleb128 (mtime, linep);
3978 Dwarf_Word filelength;
3979 get_uleb128 (filelength, linep);
3980
3981 printf (gettext ("\
3982 define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
3983 diridx, (uint64_t) mtime, (uint64_t) filelength,
3984 fname);
3985 }
3986 break;
3987
3988 default:
3989 /* Unknown, ignore it. */
3990 puts (gettext ("unknown opcode"));
3991 linep += len - 1;
3992 break;
3993 }
3994 }
3995 else if (opcode <= DW_LNS_set_epilog_begin)
3996 {
3997 /* This is a known standard opcode. */
3998 switch (opcode)
3999 {
4000 case DW_LNS_copy:
4001 /* Takes no argument. */
4002 puts (gettext (" copy"));
4003 break;
4004
4005 case DW_LNS_advance_pc:
4006 /* Takes one uleb128 parameter which is added to the
4007 address. */
4008 get_uleb128 (u128, linep);
4009 address += minimum_instr_len * u128;
4010 printf (gettext ("\
4011 advance address by %u to %#" PRIx64 "\n"),
4012 u128, (uint64_t) address);
4013 break;
4014
4015 case DW_LNS_advance_line:
4016 /* Takes one sleb128 parameter which is added to the
4017 line. */
4018 get_sleb128 (s128, linep);
4019 line += s128;
4020 printf (gettext ("\
4021 advance line by constant %d to %" PRId64 "\n"),
4022 s128, (int64_t) line);
4023 break;
4024
4025 case DW_LNS_set_file:
4026 /* Takes one uleb128 parameter which is stored in file. */
4027 get_uleb128 (u128, linep);
4028 printf (gettext (" set file to %" PRIu64 "\n"),
4029 (uint64_t) u128);
4030 break;
4031
4032 case DW_LNS_set_column:
4033 /* Takes one uleb128 parameter which is stored in column. */
4034 if (unlikely (standard_opcode_lengths[opcode] != 1))
4035 goto invalid_data;
4036
4037 get_uleb128 (u128, linep);
4038 printf (gettext (" set column to %" PRIu64 "\n"),
4039 (uint64_t) u128);
4040 break;
4041
4042 case DW_LNS_negate_stmt:
4043 /* Takes no argument. */
4044 is_stmt = 1 - is_stmt;
4045 printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
4046 "is_stmt", is_stmt);
4047 break;
4048
4049 case DW_LNS_set_basic_block:
4050 /* Takes no argument. */
4051 puts (gettext (" set basic block flag"));
4052 break;
4053
4054 case DW_LNS_const_add_pc:
4055 /* Takes no argument. */
4056 u128 = (minimum_instr_len
4057 * ((255 - opcode_base) / line_range));
4058 address += u128;
4059 printf (gettext ("\
4060 advance address by constant %u to %#" PRIx64 "\n"),
4061 u128, (uint64_t) address);
4062 break;
4063
4064 case DW_LNS_fixed_advance_pc:
4065 /* Takes one 16 bit parameter which is added to the
4066 address. */
4067 if (unlikely (standard_opcode_lengths[opcode] != 1))
4068 goto invalid_data;
4069
4070 u128 = read_2ubyte_unaligned_inc (dbg, linep);
4071 address += u128;
4072 printf (gettext ("\
4073 advance address by fixed value %u to %#" PRIx64 "\n"),
4074 u128, (uint64_t) address);
4075 break;
4076
4077 case DW_LNS_set_prologue_end:
4078 /* Takes no argument. */
4079 puts (gettext (" set prologue end flag"));
4080 break;
4081
4082 case DW_LNS_set_epilog_begin:
4083 /* Takes no argument. */
4084 puts (gettext (" set epilogue begin flag"));
4085 break;
4086 }
4087 }
4088 else
4089 {
4090 /* This is a new opcode the generator but not we know about.
4091 Read the parameters associated with it but then discard
4092 everything. Read all the parameters for this opcode. */
4093 printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
4094 " unknown opcode with %" PRIu8 " parameters:",
4095 standard_opcode_lengths[opcode]),
4096 standard_opcode_lengths[opcode]);
4097 for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
4098 {
4099 get_uleb128 (u128, linep);
4100 if (n != standard_opcode_lengths[opcode])
4101 putc_unlocked (',', stdout);
4102 printf (" %u", u128);
4103 }
4104
4105 /* Next round, ignore this opcode. */
4106 continue;
4107 }
4108 }
4109 }
4110
4111 /* There must only be one data block. */
4112 assert (elf_getdata (scn, data) == NULL);
4113 }
4114
4115
4116 static void
print_debug_loc_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)4117 print_debug_loc_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4118 GElf_Shdr *shdr, Dwarf *dbg)
4119 {
4120 printf (gettext ("\
4121 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
4122 ".debug_loc", (uint64_t) shdr->sh_offset);
4123
4124 // XXX add something
4125 }
4126
4127
4128 struct mac_culist
4129 {
4130 Dwarf_Die die;
4131 Dwarf_Off offset;
4132 Dwarf_Files *files;
4133 struct mac_culist *next;
4134 };
4135
4136
4137 static int
mac_compare(const void * p1,const void * p2)4138 mac_compare (const void *p1, const void *p2)
4139 {
4140 struct mac_culist *m1 = (struct mac_culist *) p1;
4141 struct mac_culist *m2 = (struct mac_culist *) p2;
4142
4143 if (m1->offset < m2->offset)
4144 return -1;
4145 if (m1->offset > m2->offset)
4146 return 1;
4147 return 0;
4148 }
4149
4150
4151 static void
print_debug_macinfo_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)4152 print_debug_macinfo_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4153 GElf_Shdr *shdr, Dwarf *dbg)
4154 {
4155 printf (gettext ("\
4156 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
4157 ".debug_macinfo", (uint64_t) shdr->sh_offset);
4158 putc_unlocked ('\n', stdout);
4159
4160 /* There is no function in libdw to iterate over the raw content of
4161 the section but it is easy enough to do. */
4162 Elf_Data *data = elf_getdata (scn, NULL);
4163 if (data == NULL || data->d_buf == NULL)
4164 {
4165 error (0, 0, gettext ("cannot get macro information section data: %s"),
4166 elf_errmsg (-1));
4167 return;
4168 }
4169
4170 /* Get the source file information for all CUs. */
4171 Dwarf_Off offset;
4172 Dwarf_Off ncu = 0;
4173 size_t hsize;
4174 struct mac_culist *culist = NULL;
4175 size_t nculist = 0;
4176 while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
4177 {
4178 Dwarf_Die cudie;
4179 if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
4180 continue;
4181
4182 Dwarf_Attribute attr;
4183 if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
4184 continue;
4185
4186 Dwarf_Word macoff;
4187 if (dwarf_formudata (&attr, &macoff) != 0)
4188 continue;
4189
4190 struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
4191 newp->die = cudie;
4192 newp->offset = macoff;
4193 newp->files = NULL;
4194 newp->next = culist;
4195 culist = newp;
4196 ++nculist;
4197 }
4198
4199 /* Convert the list into an array for easier consumption. */
4200 struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
4201 * sizeof (*cus));
4202 /* Add sentinel. */
4203 cus[nculist].offset = data->d_size;
4204 if (nculist > 0)
4205 {
4206 for (size_t cnt = nculist - 1; culist != NULL; --cnt)
4207 {
4208 assert (cnt < nculist);
4209 cus[cnt] = *culist;
4210 culist = culist->next;
4211 }
4212
4213 /* Sort the array according to the offset in the .debug_macinfo
4214 section. Note we keep the sentinel at the end. */
4215 qsort (cus, nculist, sizeof (*cus), mac_compare);
4216 }
4217
4218 const unsigned char *readp = (const unsigned char *) data->d_buf;
4219 const unsigned char *readendp = readp + data->d_size;
4220 int level = 1;
4221
4222 while (readp < readendp)
4223 {
4224 unsigned int opcode = *readp++;
4225 unsigned int u128;
4226 unsigned int u128_2;
4227 const unsigned char *endp;
4228
4229 switch (opcode)
4230 {
4231 case DW_MACINFO_define:
4232 case DW_MACINFO_undef:
4233 case DW_MACINFO_vendor_ext:
4234 /* For the first two opcodes the parameters are
4235 line, string
4236 For the latter
4237 number, string.
4238 We can treat these cases together. */
4239 get_uleb128 (u128, readp);
4240
4241 endp = memchr (readp, '\0', readendp - readp);
4242 if (endp == NULL)
4243 {
4244 printf (gettext ("\
4245 %*s*** non-terminated string at end of section"),
4246 level, "");
4247 return;
4248 }
4249
4250 if (opcode == DW_MACINFO_define)
4251 printf ("%*s#define %s, line %u\n",
4252 level, "", (char *) readp, u128);
4253 else if (opcode == DW_MACINFO_undef)
4254 printf ("%*s#undef %s, line %u\n",
4255 level, "", (char *) readp, u128);
4256 else
4257 printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
4258
4259 readp = endp + 1;
4260 break;
4261
4262 case DW_MACINFO_start_file:
4263 /* The two parameters are line and file index, in this order. */
4264 get_uleb128 (u128, readp);
4265 get_uleb128 (u128_2, readp);
4266
4267 /* Find the CU DIE for this file. */
4268 ptrdiff_t macoff = readp - (const unsigned char *) data->d_buf;
4269 const char *fname = "???";
4270 if (macoff >= cus[0].offset)
4271 {
4272 while (macoff >= cus[1].offset)
4273 ++cus;
4274
4275 if (cus[0].files == NULL
4276 && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
4277 cus[0].files = (Dwarf_Files *) -1l;
4278
4279 if (cus[0].files != (Dwarf_Files *) -1l)
4280 fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
4281 ?: "???");
4282 }
4283
4284 printf ("%*sstart_file %u, [%u] %s\n",
4285 level, "", u128, u128_2, fname);
4286 ++level;
4287 break;
4288
4289 case DW_MACINFO_end_file:
4290 --level;
4291 printf ("%*send_file\n", level, "");
4292 /* Nothing more to do. */
4293 break;
4294
4295 default:
4296 // XXX gcc seems to generate files with a trailing zero.
4297 if (opcode != 0 || readp != readendp)
4298 printf ("%*s*** invalid opcode %u\n", level, "", opcode);
4299 break;
4300 }
4301 }
4302 }
4303
4304
4305 /* Callback for printing global names. */
4306 static int
print_pubnames(Dwarf * dbg,Dwarf_Global * global,void * arg)4307 print_pubnames (Dwarf *dbg, Dwarf_Global *global, void *arg)
4308 {
4309 int *np = (int *) arg;
4310
4311 printf (gettext (" [%5d] DIE offset: %6" PRId64
4312 ", CU DIE offset: %6" PRId64 ", name: %s\n"),
4313 (*np)++, global->die_offset, global->cu_offset, global->name);
4314
4315 return 0;
4316 }
4317
4318
4319 /* Print the known exported symbols in the DWARF section '.debug_pubnames'. */
4320 static void
print_debug_pubnames_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)4321 print_debug_pubnames_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4322 GElf_Shdr *shdr, Dwarf *dbg)
4323 {
4324 printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
4325 ".debug_pubnames", (uint64_t) shdr->sh_offset);
4326
4327 int n = 0;
4328 (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
4329 }
4330
4331 /* Print the content of the DWARF string section '.debug_str'. */
4332 static void
print_debug_str_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)4333 print_debug_str_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4334 GElf_Shdr *shdr, Dwarf *dbg)
4335 {
4336 /* Compute floor(log16(shdr->sh_size)). */
4337 GElf_Addr tmp = shdr->sh_size;
4338 int digits = 1;
4339 while (tmp >= 16)
4340 {
4341 ++digits;
4342 tmp >>= 4;
4343 }
4344 digits = MAX (4, digits);
4345
4346 printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
4347 " %*s String\n"),
4348 ".debug_str", (uint64_t) shdr->sh_offset,
4349 /* TRANS: the debugstr| prefix makes the string unique. */
4350 digits + 2, sgettext ("debugstr|Offset"));
4351
4352 Dwarf_Off offset = 0;
4353 while (offset < shdr->sh_size)
4354 {
4355 size_t len;
4356 const char *str = dwarf_getstring (dbg, offset, &len);
4357 if (str == NULL)
4358 {
4359 printf (gettext (" *** error while reading strings: %s\n"),
4360 dwarf_errmsg (-1));
4361 break;
4362 }
4363
4364 printf (" [%*" PRIx64 "] \"%s\"\n", digits, (uint64_t) offset, str);
4365
4366 offset += len + 1;
4367 }
4368 }
4369
4370
4371 static void
print_debug(Ebl * ebl,GElf_Ehdr * ehdr)4372 print_debug (Ebl *ebl, GElf_Ehdr *ehdr)
4373 {
4374 /* Find the version information sections. For this we have to
4375 search through the section table. */
4376 Dwarf *dbg;
4377 Elf_Scn *scn;
4378 size_t shstrndx;
4379
4380 /* Before we start the real work get a debug context descriptor. */
4381 dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
4382 if (dbg == NULL)
4383 {
4384 error (0, 0, gettext ("cannot get debug context descriptor: %s"),
4385 dwarf_errmsg (-1));
4386 return;
4387 }
4388
4389 /* Get the section header string table index. */
4390 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
4391 error (EXIT_FAILURE, 0,
4392 gettext ("cannot get section header string table index"));
4393
4394 scn = NULL;
4395 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
4396 {
4397 /* Handle the section if it is part of the versioning handling. */
4398 GElf_Shdr shdr_mem;
4399 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
4400
4401 if (shdr != NULL || shdr->sh_type != SHT_PROGBITS)
4402 {
4403 static const struct
4404 {
4405 const char *name;
4406 enum section_e bitmask;
4407 void (*fp) (Ebl *, GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
4408 } debug_sections[] =
4409 {
4410 #define NEW_SECTION(name) \
4411 { ".debug_" #name, section_##name, print_debug_##name##_section }
4412 NEW_SECTION (abbrev),
4413 NEW_SECTION (aranges),
4414 NEW_SECTION (frame),
4415 NEW_SECTION (info),
4416 NEW_SECTION (line),
4417 NEW_SECTION (loc),
4418 NEW_SECTION (pubnames),
4419 NEW_SECTION (str),
4420 NEW_SECTION (macinfo),
4421 { ".eh_frame", section_frame, print_debug_frame_section }
4422 };
4423 const int ndebug_sections = (sizeof (debug_sections)
4424 / sizeof (debug_sections[0]));
4425 const char *name = elf_strptr (ebl->elf, shstrndx,
4426 shdr->sh_name);
4427 int n;
4428
4429 for (n = 0; n < ndebug_sections; ++n)
4430 if (strcmp (name, debug_sections[n].name) == 0)
4431 {
4432 if (print_debug_sections & debug_sections[n].bitmask)
4433 debug_sections[n].fp (ebl, ehdr, scn, shdr, dbg);
4434 break;
4435 }
4436 }
4437 }
4438
4439 /* We are done with the DWARF handling. */
4440 dwarf_end (dbg);
4441 }
4442
4443
4444 static void
handle_notes(Ebl * ebl,GElf_Ehdr * ehdr)4445 handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
4446 {
4447 int class = gelf_getclass (ebl->elf);
4448 size_t cnt;
4449
4450 /* We have to look through the program header to find the note
4451 sections. There can be more than one. */
4452 for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
4453 {
4454 GElf_Phdr mem;
4455 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
4456
4457 if (phdr == NULL || phdr->p_type != PT_NOTE)
4458 /* Not what we are looking for. */
4459 continue;
4460
4461 printf (gettext ("\
4462 \nNote segment of %" PRId64 " bytes at offset %#0" PRIx64 ":\n"),
4463 phdr->p_filesz, phdr->p_offset);
4464
4465 char *notemem = gelf_rawchunk (ebl->elf, phdr->p_offset, phdr->p_filesz);
4466 if (notemem == NULL)
4467 error (EXIT_FAILURE, 0,
4468 gettext ("cannot get content of note section: %s"),
4469 elf_errmsg (-1));
4470
4471 fputs_unlocked (gettext (" Owner Data size Type\n"), stdout);
4472
4473
4474 /* Handle the note section content. It consists of one or more
4475 entries each of which consists of five parts:
4476
4477 - a 32-bit name length
4478 - a 32-bit descriptor length
4479 - a 32-bit type field
4480 - the NUL-terminated name, length as specified in the first field
4481 - the descriptor, length as specified in the second field
4482
4483 The variable sized fields are padded to 32- or 64-bits
4484 depending on whether the file is a 32- or 64-bit ELF file.
4485 */
4486 size_t align = class == ELFCLASS32 ? 4 : 8;
4487 #define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1))
4488
4489 size_t idx = 0;
4490 while (idx < phdr->p_filesz)
4491 {
4492 /* XXX Handle 64-bit note section entries correctly. */
4493 struct
4494 {
4495 uint32_t namesz;
4496 uint32_t descsz;
4497 uint32_t type;
4498 char name[0];
4499 } *noteentry = (__typeof (noteentry)) (notemem + idx);
4500
4501 if (idx + 12 > phdr->p_filesz
4502 || (idx + 12 + ALIGNED_LEN (noteentry->namesz)
4503 + ALIGNED_LEN (noteentry->descsz) > phdr->p_filesz))
4504 /* This entry isn't completely contained in the note
4505 section. Ignore it. */
4506 break;
4507
4508 char buf[100];
4509 char buf2[100];
4510 printf (gettext (" %-13.*s %9" PRId32 " %s\n"),
4511 (int) noteentry->namesz, noteentry->name,
4512 noteentry->descsz,
4513 ehdr->e_type == ET_CORE
4514 ? ebl_core_note_type_name (ebl, noteentry->type,
4515 buf, sizeof (buf))
4516 : ebl_object_note_type_name (ebl, noteentry->type,
4517 buf2, sizeof (buf2)));
4518
4519 /* Filter out invalid entries. */
4520 if (memchr (noteentry->name, '\0', noteentry->namesz) != NULL
4521 /* XXX For now help broken Linux kernels. */
4522 || 1)
4523 {
4524 if (ehdr->e_type == ET_CORE)
4525 ebl_core_note (ebl, noteentry->name, noteentry->type,
4526 noteentry->descsz,
4527 ¬eentry->name[ALIGNED_LEN (noteentry->namesz)]);
4528 else
4529 ebl_object_note (ebl, noteentry->name, noteentry->type,
4530 noteentry->descsz,
4531 ¬eentry->name[ALIGNED_LEN (noteentry->namesz)]);
4532 }
4533
4534 /* Move to the next entry. */
4535 idx += (12 + ALIGNED_LEN (noteentry->namesz)
4536 + ALIGNED_LEN (noteentry->descsz));
4537 }
4538
4539 gelf_freechunk (ebl->elf, notemem);
4540 }
4541 }
4542