blob: aab8b5ccd6508baedfb11fc59649ceaee40ce120 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Print information from ELF file in human-readable form.
Petr Machata7f617342015-03-18 19:42:02 +01002 Copyright (C) 1999-2015 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004 Written by Ulrich Drepper <drepper@redhat.com>, 1999.
5
Mark Wielaardde2ed972012-06-05 17:15:16 +02006 This file is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000010
Mark Wielaardde2ed972012-06-05 17:15:16 +020011 elfutils is distributed in the hope that it will be useful, but
Ulrich Drepper361df7d2006-04-04 21:38:57 +000012 WITHOUT ANY WARRANTY; without even the implied warranty of
Mark Wielaardde2ed972012-06-05 17:15:16 +020013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
Ulrich Drepper361df7d2006-04-04 21:38:57 +000015
Mark Wielaardde2ed972012-06-05 17:15:16 +020016 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000018
19#ifdef HAVE_CONFIG_H
20# include <config.h>
21#endif
22
23#include <argp.h>
24#include <assert.h>
Ulrich Drepperc98bcc72007-08-04 17:06:14 +000025#include <ctype.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000026#include <dwarf.h>
27#include <errno.h>
28#include <error.h>
29#include <fcntl.h>
30#include <gelf.h>
31#include <inttypes.h>
32#include <langinfo.h>
33#include <libdw.h>
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000034#include <libdwfl.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000035#include <libintl.h>
36#include <locale.h>
Roland McGrathcb6d8652007-08-23 08:10:54 +000037#include <stdarg.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000038#include <stdbool.h>
39#include <stdlib.h>
40#include <string.h>
41#include <time.h>
42#include <unistd.h>
43#include <sys/param.h>
Roland McGrathb337b1f2010-01-15 01:02:27 -080044#include <sys/stat.h>
Petr Machataab224102013-09-26 00:39:34 +020045#include <signal.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000046
47#include <system.h>
Roland McGrath59ea7f32007-10-04 08:50:09 +000048#include "../libelf/libelfP.h"
Roland McGrath059c83e2008-02-21 06:19:39 +000049#include "../libelf/common.h"
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000050#include "../libebl/libeblP.h"
51#include "../libdw/libdwP.h"
Roland McGrathe4c22ea2007-10-23 13:07:39 +000052#include "../libdwfl/libdwflP.h"
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000053#include "../libdw/memory-access.h"
54
Mark Wielaardf31c4412012-08-17 00:35:03 +020055#include "../libdw/known-dwarf.h"
56
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000057
58/* Name and version of program. */
59static void print_version (FILE *stream, struct argp_state *state);
Ulrich Drepperfdc93e12009-01-17 11:47:10 -080060ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000061
62/* Bug report address. */
Ulrich Drepperfdc93e12009-01-17 11:47:10 -080063ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000064
Mark Wielaard6d258ce2013-01-16 15:19:20 +010065/* argp key value for --elf-section, non-ascii. */
66#define ELF_INPUT_SECTION 256
67
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000068/* Definitions of arguments for argp functions. */
69static const struct argp_option options[] =
70{
Mark Wielaard6d258ce2013-01-16 15:19:20 +010071 { NULL, 0, NULL, 0, N_("ELF input selection:"), 0 },
72 { "elf-section", ELF_INPUT_SECTION, "SECTION", OPTION_ARG_OPTIONAL,
73 N_("Use the named SECTION (default .gnu_debugdata) as (compressed) ELF "
74 "input data"), 0 },
Roland McGratha7422be2010-01-04 20:29:33 -080075 { NULL, 0, NULL, 0, N_("ELF output selection:"), 0 },
76 { "all", 'a', NULL, 0,
77 N_("All these plus -p .strtab -p .dynstr -p .comment"), 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000078 { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
79 { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
80 { "histogram", 'I', NULL, 0,
81 N_("Display histogram of bucket list lengths"), 0 },
82 { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
Roland McGrath60fc84c2007-08-03 21:59:15 +000083 { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000084 { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
Roland McGratha7422be2010-01-04 20:29:33 -080085 { "section-headers", 'S', NULL, 0, N_("Display the sections' headers"), 0 },
Roland McGrath60fc84c2007-08-03 21:59:15 +000086 { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000087 { "symbols", 's', NULL, 0, N_("Display the symbol table"), 0 },
88 { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
Roland McGratha7422be2010-01-04 20:29:33 -080089 { "notes", 'n', NULL, 0, N_("Display the ELF notes"), 0 },
90 { "arch-specific", 'A', NULL, 0,
91 N_("Display architecture specific information, if any"), 0 },
92 { "exception", 'e', NULL, 0,
93 N_("Display sections for exception handling"), 0 },
94
95 { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000096 { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
97 N_("Display DWARF section content. SECTION can be one of abbrev, "
Mark Wielaard1a094202013-03-25 14:48:06 +010098 "aranges, decodedaranges, frame, gdb_index, info, loc, line, "
99 "decodedline, ranges, pubnames, str, macinfo, macro or exception"), 0 },
Roland McGrath60fc84c2007-08-03 21:59:15 +0000100 { "hex-dump", 'x', "SECTION", 0,
101 N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
Roland McGrathc76f0b02007-09-27 07:31:33 +0000102 { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
103 N_("Print string contents of sections"), 0 },
104 { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
Roland McGrath59ea7f32007-10-04 08:50:09 +0000105 { "archive-index", 'c', NULL, 0,
106 N_("Display the symbol index of an archive"), 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000107
108 { NULL, 0, NULL, 0, N_("Output control:"), 0 },
Roland McGrath5dbccdb2009-06-28 14:48:02 -0700109 { "numeric-addresses", 'N', NULL, 0,
110 N_("Do not find symbol names for addresses in DWARF data"), 0 },
Mark Wielaard10186a12013-01-24 11:29:21 +0100111 { "unresolved-address-offsets", 'U', NULL, 0,
112 N_("Display just offsets instead of resolving values to addresses in DWARF data"), 0 },
Roland McGrathbd754192011-07-09 05:33:37 -0700113 { "wide", 'W', NULL, 0,
114 N_("Ignored for compatibility (lines always wide)"), 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000115 { NULL, 0, NULL, 0, NULL, 0 }
116};
117
118/* Short description of program. */
119static const char doc[] = N_("\
120Print information from ELF file in human-readable form.");
121
122/* Strings for arguments in help texts. */
123static const char args_doc[] = N_("FILE...");
124
125/* Prototype for option handler. */
126static error_t parse_opt (int key, char *arg, struct argp_state *state);
127
128/* Data structure to communicate with argp functions. */
129static struct argp argp =
130{
131 options, parse_opt, args_doc, doc, NULL, NULL, NULL
132};
133
Mark Wielaard6d258ce2013-01-16 15:19:20 +0100134/* If non-null, the section from which we should read to (compressed) ELF. */
135static const char *elf_input_section = NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000136
137/* Flags set by the option controlling the output. */
138
139/* True if dynamic segment should be printed. */
140static bool print_dynamic_table;
141
142/* True if the file header should be printed. */
143static bool print_file_header;
144
145/* True if the program headers should be printed. */
146static bool print_program_header;
147
148/* True if relocations should be printed. */
149static bool print_relocations;
150
151/* True if the section headers should be printed. */
152static bool print_section_header;
153
154/* True if the symbol table should be printed. */
155static bool print_symbol_table;
156
157/* True if the version information should be printed. */
158static bool print_version_info;
159
160/* True if section groups should be printed. */
161static bool print_section_groups;
162
163/* True if bucket list length histogram should be printed. */
164static bool print_histogram;
165
166/* True if the architecture specific data should be printed. */
167static bool print_arch;
168
169/* True if note section content should be printed. */
170static bool print_notes;
171
Roland McGrath60fc84c2007-08-03 21:59:15 +0000172/* True if SHF_STRINGS section content should be printed. */
173static bool print_string_sections;
174
Roland McGrath59ea7f32007-10-04 08:50:09 +0000175/* True if archive index should be printed. */
176static bool print_archive_index;
177
178/* True if any of the control options except print_archive_index is set. */
179static bool any_control_option;
180
Roland McGrath5dbccdb2009-06-28 14:48:02 -0700181/* True if we should print addresses from DWARF in symbolic form. */
182static bool print_address_names = true;
183
Mark Wielaard10186a12013-01-24 11:29:21 +0100184/* True if we should print raw values instead of relativized addresses. */
185static bool print_unresolved_addresses = false;
186
Mark Wielaardb79788c2013-03-25 11:45:22 +0100187/* True if we should print the .debug_aranges section using libdw. */
188static bool decodedaranges = false;
189
Mark Wielaard1a094202013-03-25 14:48:06 +0100190/* True if we should print the .debug_aranges section using libdw. */
191static bool decodedline = false;
192
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000193/* Select printing of debugging sections. */
194static enum section_e
195{
Ulrich Drepperb006fbf2009-01-16 03:08:25 -0800196 section_abbrev = 1, /* .debug_abbrev */
197 section_aranges = 2, /* .debug_aranges */
198 section_frame = 4, /* .debug_frame or .eh_frame & al. */
Roland McGrath2b1f0952010-06-20 17:55:50 -0700199 section_info = 8, /* .debug_info, .debug_types */
200 section_types = section_info,
Ulrich Drepperb006fbf2009-01-16 03:08:25 -0800201 section_line = 16, /* .debug_line */
202 section_loc = 32, /* .debug_loc */
203 section_pubnames = 64, /* .debug_pubnames */
204 section_str = 128, /* .debug_str */
205 section_macinfo = 256, /* .debug_macinfo */
206 section_ranges = 512, /* .debug_ranges */
207 section_exception = 1024, /* .eh_frame & al. */
Mark Wielaard093a1d32011-04-14 23:47:26 +0200208 section_gdb_index = 2048, /* .gdb_index */
Mark Wielaarde9b23882012-06-29 22:30:15 +0200209 section_macro = 4096, /* .debug_macro */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000210 section_all = (section_abbrev | section_aranges | section_frame
211 | section_info | section_line | section_loc
212 | section_pubnames | section_str | section_macinfo
Mark Wielaarde9b23882012-06-29 22:30:15 +0200213 | section_ranges | section_exception | section_gdb_index
214 | section_macro)
Roland McGrath2e79deb2010-01-04 20:36:10 -0800215} print_debug_sections, implicit_debug_sections;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000216
Roland McGrath60fc84c2007-08-03 21:59:15 +0000217/* Select hex dumping of sections. */
218static struct section_argument *dump_data_sections;
219static struct section_argument **dump_data_sections_tail = &dump_data_sections;
220
Roland McGrathc76f0b02007-09-27 07:31:33 +0000221/* Select string dumping of sections. */
222static struct section_argument *string_sections;
223static struct section_argument **string_sections_tail = &string_sections;
224
Roland McGrath60fc84c2007-08-03 21:59:15 +0000225struct section_argument
226{
227 struct section_argument *next;
228 const char *arg;
Roland McGrathe4061d02010-01-04 20:25:09 -0800229 bool implicit;
Roland McGrath60fc84c2007-08-03 21:59:15 +0000230};
231
Roland McGrath8111da02010-01-07 20:31:59 -0800232/* Numbers of sections and program headers in the file. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000233static size_t shnum;
Roland McGrath8111da02010-01-07 20:31:59 -0800234static size_t phnum;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000235
236
237/* Declarations of local functions. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000238static void process_file (int fd, const char *fname, bool only_one);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000239static void process_elf_file (Dwfl_Module *dwflmod, int fd);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000240static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
241static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
242static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
243static void print_scngrp (Ebl *ebl);
Roland McGrath8111da02010-01-07 20:31:59 -0800244static void print_dynamic (Ebl *ebl);
Ulrich Drepperb47d2902009-06-01 07:38:32 -0700245static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
246static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
247 GElf_Shdr *shdr);
248static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
249 GElf_Shdr *shdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000250static void print_symtab (Ebl *ebl, int type);
251static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
252static void print_verinfo (Ebl *ebl);
253static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
254static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
255static void handle_versym (Ebl *ebl, Elf_Scn *scn,
256 GElf_Shdr *shdr);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000257static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000258static void handle_hash (Ebl *ebl);
259static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
260static void print_liblist (Ebl *ebl);
Roland McGrath059c83e2008-02-21 06:19:39 +0000261static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
Roland McGrath60fc84c2007-08-03 21:59:15 +0000262static void dump_data (Ebl *ebl);
Roland McGrathc76f0b02007-09-27 07:31:33 +0000263static void dump_strings (Ebl *ebl);
Roland McGrath60fc84c2007-08-03 21:59:15 +0000264static void print_strings (Ebl *ebl);
Roland McGrath59ea7f32007-10-04 08:50:09 +0000265static void dump_archive_index (Elf *, const char *);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000266
267
268int
269main (int argc, char *argv[])
270{
271 /* Set locale. */
272 setlocale (LC_ALL, "");
273
274 /* Initialize the message catalog. */
Ulrich Drepperb0243862007-06-06 00:09:36 +0000275 textdomain (PACKAGE_TARNAME);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000276
277 /* Parse and process arguments. */
278 int remaining;
279 argp_parse (&argp, argc, argv, 0, &remaining, NULL);
280
281 /* Before we start tell the ELF library which version we are using. */
282 elf_version (EV_CURRENT);
283
284 /* Now process all the files given at the command line. */
285 bool only_one = remaining + 1 == argc;
286 do
287 {
288 /* Open the file. */
289 int fd = open (argv[remaining], O_RDONLY);
290 if (fd == -1)
291 {
292 error (0, errno, gettext ("cannot open input file"));
293 continue;
294 }
295
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000296 process_file (fd, argv[remaining], only_one);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000297
298 close (fd);
299 }
300 while (++remaining < argc);
301
302 return error_message_count != 0;
303}
304
305
306/* Handle program arguments. */
307static error_t
308parse_opt (int key, char *arg,
309 struct argp_state *state __attribute__ ((unused)))
310{
Roland McGrathe4061d02010-01-04 20:25:09 -0800311 void add_dump_section (const char *name, bool implicit)
Ulrich Drepperd7285e12009-01-23 16:10:44 -0800312 {
313 struct section_argument *a = xmalloc (sizeof *a);
314 a->arg = name;
315 a->next = NULL;
Roland McGrathe4061d02010-01-04 20:25:09 -0800316 a->implicit = implicit;
Ulrich Drepperd7285e12009-01-23 16:10:44 -0800317 struct section_argument ***tailp
318 = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
319 **tailp = a;
320 *tailp = &a->next;
321 }
322
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000323 switch (key)
324 {
325 case 'a':
326 print_file_header = true;
327 print_program_header = true;
328 print_relocations = true;
329 print_section_header = true;
330 print_symbol_table = true;
331 print_version_info = true;
332 print_dynamic_table = true;
333 print_section_groups = true;
334 print_histogram = true;
335 print_arch = true;
336 print_notes = true;
Roland McGrath2e79deb2010-01-04 20:36:10 -0800337 implicit_debug_sections |= section_exception;
Roland McGrathe4061d02010-01-04 20:25:09 -0800338 add_dump_section (".strtab", true);
339 add_dump_section (".dynstr", true);
340 add_dump_section (".comment", true);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000341 any_control_option = true;
342 break;
343 case 'A':
344 print_arch = true;
345 any_control_option = true;
346 break;
347 case 'd':
348 print_dynamic_table = true;
349 any_control_option = true;
350 break;
Ulrich Drepperb006fbf2009-01-16 03:08:25 -0800351 case 'e':
352 print_debug_sections |= section_exception;
353 any_control_option = true;
354 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000355 case 'g':
356 print_section_groups = true;
357 any_control_option = true;
358 break;
359 case 'h':
360 print_file_header = true;
361 any_control_option = true;
362 break;
363 case 'I':
364 print_histogram = true;
365 any_control_option = true;
366 break;
367 case 'l':
368 print_program_header = true;
369 any_control_option = true;
370 break;
371 case 'n':
372 print_notes = true;
373 any_control_option = true;
374 break;
375 case 'r':
376 print_relocations = true;
377 any_control_option = true;
378 break;
379 case 'S':
380 print_section_header = true;
381 any_control_option = true;
382 break;
383 case 's':
384 print_symbol_table = true;
385 any_control_option = true;
386 break;
387 case 'V':
388 print_version_info = true;
389 any_control_option = true;
390 break;
Roland McGrath59ea7f32007-10-04 08:50:09 +0000391 case 'c':
392 print_archive_index = true;
393 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000394 case 'w':
395 if (arg == NULL)
396 print_debug_sections = section_all;
397 else if (strcmp (arg, "abbrev") == 0)
398 print_debug_sections |= section_abbrev;
399 else if (strcmp (arg, "aranges") == 0)
400 print_debug_sections |= section_aranges;
Mark Wielaardb79788c2013-03-25 11:45:22 +0100401 else if (strcmp (arg, "decodedaranges") == 0)
402 {
403 print_debug_sections |= section_aranges;
404 decodedaranges = true;
405 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000406 else if (strcmp (arg, "ranges") == 0)
Roland McGrathfa144952010-08-30 19:22:41 -0700407 {
408 print_debug_sections |= section_ranges;
409 implicit_debug_sections |= section_info;
410 }
Ulrich Drepperac194d02009-01-06 00:30:01 -0800411 else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000412 print_debug_sections |= section_frame;
413 else if (strcmp (arg, "info") == 0)
414 print_debug_sections |= section_info;
415 else if (strcmp (arg, "loc") == 0)
Roland McGrathfa144952010-08-30 19:22:41 -0700416 {
417 print_debug_sections |= section_loc;
418 implicit_debug_sections |= section_info;
419 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000420 else if (strcmp (arg, "line") == 0)
421 print_debug_sections |= section_line;
Mark Wielaard1a094202013-03-25 14:48:06 +0100422 else if (strcmp (arg, "decodedline") == 0)
423 {
424 print_debug_sections |= section_line;
425 decodedline = true;
426 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000427 else if (strcmp (arg, "pubnames") == 0)
428 print_debug_sections |= section_pubnames;
429 else if (strcmp (arg, "str") == 0)
430 print_debug_sections |= section_str;
431 else if (strcmp (arg, "macinfo") == 0)
432 print_debug_sections |= section_macinfo;
Mark Wielaarde9b23882012-06-29 22:30:15 +0200433 else if (strcmp (arg, "macro") == 0)
434 print_debug_sections |= section_macro;
Ulrich Drepperb006fbf2009-01-16 03:08:25 -0800435 else if (strcmp (arg, "exception") == 0)
436 print_debug_sections |= section_exception;
Mark Wielaard093a1d32011-04-14 23:47:26 +0200437 else if (strcmp (arg, "gdb_index") == 0)
438 print_debug_sections |= section_gdb_index;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000439 else
440 {
441 fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
442 arg);
443 argp_help (&argp, stderr, ARGP_HELP_SEE,
444 program_invocation_short_name);
445 exit (1);
446 }
447 any_control_option = true;
448 break;
Roland McGrathc76f0b02007-09-27 07:31:33 +0000449 case 'p':
450 any_control_option = true;
451 if (arg == NULL)
452 {
453 print_string_sections = true;
454 break;
455 }
456 /* Fall through. */
Roland McGrath60fc84c2007-08-03 21:59:15 +0000457 case 'x':
Roland McGrathe4061d02010-01-04 20:25:09 -0800458 add_dump_section (arg, false);
Roland McGrath60fc84c2007-08-03 21:59:15 +0000459 any_control_option = true;
460 break;
Roland McGrath5dbccdb2009-06-28 14:48:02 -0700461 case 'N':
462 print_address_names = false;
463 break;
Mark Wielaard10186a12013-01-24 11:29:21 +0100464 case 'U':
465 print_unresolved_addresses = true;
466 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000467 case ARGP_KEY_NO_ARGS:
468 fputs (gettext ("Missing file name.\n"), stderr);
469 goto do_argp_help;
470 case ARGP_KEY_FINI:
Roland McGrath59ea7f32007-10-04 08:50:09 +0000471 if (! any_control_option && ! print_archive_index)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000472 {
473 fputs (gettext ("No operation specified.\n"), stderr);
474 do_argp_help:
Ulrich Drepper5ee720c2009-02-01 16:18:18 -0800475 argp_help (&argp, stderr, ARGP_HELP_SEE,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000476 program_invocation_short_name);
Ulrich Drepper5ee720c2009-02-01 16:18:18 -0800477 exit (EXIT_FAILURE);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000478 }
479 break;
Roland McGrathbd754192011-07-09 05:33:37 -0700480 case 'W': /* Ignored. */
481 break;
Mark Wielaard6d258ce2013-01-16 15:19:20 +0100482 case ELF_INPUT_SECTION:
483 if (arg == NULL)
484 elf_input_section = ".gnu_debugdata";
485 else
486 elf_input_section = arg;
487 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000488 default:
489 return ARGP_ERR_UNKNOWN;
490 }
491 return 0;
492}
493
494
495/* Print the version information. */
496static void
497print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
498{
Ulrich Drepperb0243862007-06-06 00:09:36 +0000499 fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000500 fprintf (stream, gettext ("\
501Copyright (C) %s Red Hat, Inc.\n\
502This is free software; see the source for copying conditions. There is NO\n\
503warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
Ulrich Drepper3a64a302012-01-21 18:19:24 -0500504"), "2012");
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000505 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
506}
507
508
Mark Wielaard6d258ce2013-01-16 15:19:20 +0100509/* Create a file descriptor to read the data from the
510 elf_input_section given a file descriptor to an ELF file. */
511static int
512open_input_section (int fd)
513{
514 size_t shnums;
515 size_t cnt;
516 size_t shstrndx;
517 Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
518 if (elf == NULL)
519 {
520 error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
521 elf_errmsg (-1));
522 return -1;
523 }
524
525 if (elf_getshdrnum (elf, &shnums) < 0)
526 {
527 error (0, 0, gettext ("cannot determine number of sections: %s"),
528 elf_errmsg (-1));
529 open_error:
530 elf_end (elf);
531 return -1;
532 }
533
534 if (elf_getshdrstrndx (elf, &shstrndx) < 0)
535 {
536 error (0, 0, gettext ("cannot get section header string table index"));
537 goto open_error;
538 }
539
540 for (cnt = 0; cnt < shnums; ++cnt)
541 {
542 Elf_Scn *scn = elf_getscn (elf, cnt);
543 if (scn == NULL)
544 {
545 error (0, 0, gettext ("cannot get section: %s"),
546 elf_errmsg (-1));
547 goto open_error;
548 }
549
550 GElf_Shdr shdr_mem;
551 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
552 if (unlikely (shdr == NULL))
553 {
554 error (0, 0, gettext ("cannot get section header: %s"),
555 elf_errmsg (-1));
556 goto open_error;
557 }
558
559 const char *sname = elf_strptr (elf, shstrndx, shdr->sh_name);
560 if (sname == NULL)
561 {
562 error (0, 0, gettext ("cannot get section name"));
563 goto open_error;
564 }
565
566 if (strcmp (sname, elf_input_section) == 0)
567 {
568 Elf_Data *data = elf_rawdata (scn, NULL);
569 if (data == NULL)
570 {
571 error (0, 0, gettext ("cannot get %s content: %s"),
572 sname, elf_errmsg (-1));
573 goto open_error;
574 }
575
576 /* Create (and immediately unlink) a temporary file to store
577 section data in to create a file descriptor for it. */
578 const char *tmpdir = getenv ("TMPDIR") ?: P_tmpdir;
579 static const char suffix[] = "/readelfXXXXXX";
580 int tmplen = strlen (tmpdir) + sizeof (suffix);
581 char *tempname = alloca (tmplen);
582 sprintf (tempname, "%s%s", tmpdir, suffix);
583
584 int sfd = mkstemp (tempname);
585 if (sfd == -1)
586 {
587 error (0, 0, gettext ("cannot create temp file '%s'"),
588 tempname);
589 goto open_error;
590 }
591 unlink (tempname);
592
593 ssize_t size = data->d_size;
594 if (write_retry (sfd, data->d_buf, size) != size)
595 {
596 error (0, 0, gettext ("cannot write section data"));
597 goto open_error;
598 }
599
600 if (elf_end (elf) != 0)
601 {
602 error (0, 0, gettext ("error while closing Elf descriptor: %s"),
603 elf_errmsg (-1));
604 return -1;
605 }
606
607 if (lseek (sfd, 0, SEEK_SET) == -1)
608 {
609 error (0, 0, gettext ("error while rewinding file descriptor"));
610 return -1;
611 }
612
613 return sfd;
614 }
615 }
616
617 /* Named section not found. */
618 if (elf_end (elf) != 0)
619 error (0, 0, gettext ("error while closing Elf descriptor: %s"),
620 elf_errmsg (-1));
621 return -1;
622}
623
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000624/* Check if the file is an archive, and if so dump its index. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000625static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000626check_archive_index (int fd, const char *fname, bool only_one)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000627{
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000628 /* Create an `Elf' descriptor. */
629 Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
630 if (elf == NULL)
631 error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
632 elf_errmsg (-1));
633 else
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000634 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000635 if (elf_kind (elf) == ELF_K_AR)
636 {
637 if (!only_one)
638 printf ("\n%s:\n\n", fname);
639 dump_archive_index (elf, fname);
640 }
641 else
Roland McGrath59ea7f32007-10-04 08:50:09 +0000642 error (0, 0,
643 gettext ("'%s' is not an archive, cannot print archive index"),
644 fname);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000645
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000646 /* Now we can close the descriptor. */
647 if (elf_end (elf) != 0)
648 error (0, 0, gettext ("error while closing Elf descriptor: %s"),
649 elf_errmsg (-1));
650 }
651}
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000652
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000653/* Trivial callback used for checking if we opened an archive. */
654static int
655count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
656 void **userdata __attribute__ ((unused)),
657 const char *name __attribute__ ((unused)),
658 Dwarf_Addr base __attribute__ ((unused)),
659 void *arg)
660{
Roland McGratha845f682008-12-03 03:41:58 +0000661 if (*(bool *) arg)
662 return DWARF_CB_ABORT;
663 *(bool *) arg = true;
664 return DWARF_CB_OK;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000665}
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000666
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000667struct process_dwflmod_args
668{
669 int fd;
670 bool only_one;
671};
672
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000673static int
674process_dwflmod (Dwfl_Module *dwflmod,
675 void **userdata __attribute__ ((unused)),
676 const char *name __attribute__ ((unused)),
677 Dwarf_Addr base __attribute__ ((unused)),
678 void *arg)
679{
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000680 const struct process_dwflmod_args *a = arg;
Roland McGrath59ea7f32007-10-04 08:50:09 +0000681
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000682 /* Print the file name. */
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000683 if (!a->only_one)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000684 {
685 const char *fname;
686 dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000687
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000688 printf ("\n%s:\n\n", fname);
689 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000690
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000691 process_elf_file (dwflmod, a->fd);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000692
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000693 return DWARF_CB_OK;
694}
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000695
Mark Wielaarddf85bf92014-05-01 14:48:27 +0200696/* Stub libdwfl callback, only the ELF handle already open is ever used.
697 Only used for finding the alternate debug file if the Dwarf comes from
698 the main file. We are not interested in separate debuginfo. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000699static int
Mark Wielaarddf85bf92014-05-01 14:48:27 +0200700find_no_debuginfo (Dwfl_Module *mod,
701 void **userdata,
702 const char *modname,
703 Dwarf_Addr base,
704 const char *file_name,
705 const char *debuglink_file,
706 GElf_Word debuglink_crc,
707 char **debuginfo_file_name)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000708{
Mark Wielaarddf85bf92014-05-01 14:48:27 +0200709 Dwarf_Addr dwbias;
710 dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
711
712 /* We are only interested if the Dwarf has been setup on the main
713 elf file but is only missing the alternate debug link. If dwbias
714 hasn't even been setup, this is searching for separate debuginfo
715 for the main elf. We don't care in that case. */
716 if (dwbias == (Dwarf_Addr) -1)
717 return -1;
718
719 return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
720 file_name, debuglink_file,
721 debuglink_crc, debuginfo_file_name);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000722}
723
724/* Process one input file. */
725static void
726process_file (int fd, const char *fname, bool only_one)
727{
728 if (print_archive_index)
729 check_archive_index (fd, fname, only_one);
730
731 if (!any_control_option)
732 return;
733
Mark Wielaard6d258ce2013-01-16 15:19:20 +0100734 if (elf_input_section != NULL)
735 {
736 /* Replace fname and fd with section content. */
737 char *fnname = alloca (strlen (fname) + strlen (elf_input_section) + 2);
738 sprintf (fnname, "%s:%s", fname, elf_input_section);
739 fd = open_input_section (fd);
740 if (fd == -1)
741 {
742 error (0, 0, gettext ("No such section '%s' in '%s'"),
743 elf_input_section, fname);
744 return;
745 }
746 fname = fnname;
747 }
748
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000749 /* Duplicate an fd for dwfl_report_offline to swallow. */
750 int dwfl_fd = dup (fd);
751 if (unlikely (dwfl_fd < 0))
752 error (EXIT_FAILURE, errno, "dup");
753
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000754 /* Use libdwfl in a trivial way to open the libdw handle for us.
755 This takes care of applying relocations to DWARF data in ET_REL files. */
756 static const Dwfl_Callbacks callbacks =
757 {
758 .section_address = dwfl_offline_section_address,
759 .find_debuginfo = find_no_debuginfo
760 };
761 Dwfl *dwfl = dwfl_begin (&callbacks);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000762 if (likely (dwfl != NULL))
763 /* Let 0 be the logical address of the file (or first in archive). */
764 dwfl->offline_next_address = 0;
765 if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000766 {
767 struct stat64 st;
Roland McGrath890081b2010-02-26 17:57:50 -0800768 if (fstat64 (dwfl_fd, &st) != 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000769 error (0, errno, gettext ("cannot stat input file"));
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000770 else if (unlikely (st.st_size == 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000771 error (0, 0, gettext ("input file is empty"));
772 else
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000773 error (0, 0, gettext ("failed reading '%s': %s"),
774 fname, dwfl_errmsg (-1));
Roland McGrath890081b2010-02-26 17:57:50 -0800775 close (dwfl_fd); /* Consumed on success, not on failure. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000776 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000777 else
778 {
779 dwfl_report_end (dwfl, NULL, NULL);
780
781 if (only_one)
Roland McGratha845f682008-12-03 03:41:58 +0000782 {
783 /* Clear ONLY_ONE if we have multiple modules, from an archive. */
784 bool seen = false;
785 only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
786 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000787
788 /* Process the one or more modules gleaned from this file. */
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000789 struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
790 dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000791 }
792 dwfl_end (dwfl);
Mark Wielaard6d258ce2013-01-16 15:19:20 +0100793
794 /* Need to close the replaced fd if we created it. Caller takes
795 care of original. */
796 if (elf_input_section != NULL)
797 close (fd);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000798}
799
800
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000801/* Process one ELF file. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000802static void
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000803process_elf_file (Dwfl_Module *dwflmod, int fd)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000804{
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000805 GElf_Addr dwflbias;
806 Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
807
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000808 GElf_Ehdr ehdr_mem;
809 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000810
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000811 if (ehdr == NULL)
812 {
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000813 elf_error:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000814 error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
815 return;
816 }
817
Ulrich Drepperd0449522005-09-03 07:23:52 +0000818 Ebl *ebl = ebl_openbackend (elf);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000819 if (unlikely (ebl == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000820 {
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000821 ebl_error:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000822 error (0, errno, gettext ("cannot create EBL handle"));
823 return;
824 }
825
826 /* Determine the number of sections. */
Ulrich Drepperf1894932009-06-13 15:55:42 -0700827 if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000828 error (EXIT_FAILURE, 0,
829 gettext ("cannot determine number of sections: %s"),
830 elf_errmsg (-1));
831
Roland McGrath8111da02010-01-07 20:31:59 -0800832 /* Determine the number of phdrs. */
833 if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
834 error (EXIT_FAILURE, 0,
835 gettext ("cannot determine number of program headers: %s"),
836 elf_errmsg (-1));
837
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000838 /* For an ET_REL file, libdwfl has adjusted the in-core shdrs
839 and may have applied relocation to some sections.
840 So we need to get a fresh Elf handle on the file to display those. */
841 bool print_unrelocated = (print_section_header
842 || print_relocations
843 || dump_data_sections != NULL
844 || print_notes);
845
846 Elf *pure_elf = NULL;
847 Ebl *pure_ebl = ebl;
848 if (ehdr->e_type == ET_REL && print_unrelocated)
849 {
850 /* Read the file afresh. */
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000851 off64_t aroff = elf_getaroff (elf);
Ulrich Drepperfbc708d2008-01-21 18:44:55 +0000852 pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000853 if (aroff > 0)
854 {
855 /* Archive member. */
856 (void) elf_rand (pure_elf, aroff);
857 Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
858 elf_end (pure_elf);
859 pure_elf = armem;
860 }
861 if (pure_elf == NULL)
862 goto elf_error;
863 pure_ebl = ebl_openbackend (pure_elf);
864 if (pure_ebl == NULL)
865 goto ebl_error;
866 }
867
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000868 if (print_file_header)
869 print_ehdr (ebl, ehdr);
870 if (print_section_header)
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000871 print_shdr (pure_ebl, ehdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000872 if (print_program_header)
873 print_phdr (ebl, ehdr);
874 if (print_section_groups)
875 print_scngrp (ebl);
876 if (print_dynamic_table)
Roland McGrath8111da02010-01-07 20:31:59 -0800877 print_dynamic (ebl);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000878 if (print_relocations)
Ulrich Drepperb47d2902009-06-01 07:38:32 -0700879 print_relocs (pure_ebl, ehdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000880 if (print_histogram)
881 handle_hash (ebl);
882 if (print_symbol_table)
883 print_symtab (ebl, SHT_DYNSYM);
884 if (print_version_info)
885 print_verinfo (ebl);
886 if (print_symbol_table)
887 print_symtab (ebl, SHT_SYMTAB);
888 if (print_arch)
889 print_liblist (ebl);
Roland McGrath059c83e2008-02-21 06:19:39 +0000890 if (print_arch)
891 print_attributes (ebl, ehdr);
Roland McGrath60fc84c2007-08-03 21:59:15 +0000892 if (dump_data_sections != NULL)
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000893 dump_data (pure_ebl);
Roland McGrathc76f0b02007-09-27 07:31:33 +0000894 if (string_sections != NULL)
895 dump_strings (ebl);
Roland McGrath2e79deb2010-01-04 20:36:10 -0800896 if ((print_debug_sections | implicit_debug_sections) != 0)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000897 print_debug (dwflmod, ebl, ehdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000898 if (print_notes)
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000899 handle_notes (pure_ebl, ehdr);
Roland McGrath60fc84c2007-08-03 21:59:15 +0000900 if (print_string_sections)
901 print_strings (ebl);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000902
903 ebl_closebackend (ebl);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000904
905 if (pure_ebl != ebl)
906 {
907 ebl_closebackend (pure_ebl);
908 elf_end (pure_elf);
909 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000910}
911
912
913/* Print file type. */
914static void
915print_file_type (unsigned short int e_type)
916{
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000917 if (likely (e_type <= ET_CORE))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000918 {
Ulrich Drepper8b383102007-02-16 00:31:57 +0000919 static const char *const knowntypes[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000920 {
921 N_("NONE (None)"),
922 N_("REL (Relocatable file)"),
923 N_("EXEC (Executable file)"),
924 N_("DYN (Shared object file)"),
925 N_("CORE (Core file)")
926 };
927 puts (gettext (knowntypes[e_type]));
928 }
929 else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
930 printf (gettext ("OS Specific: (%x)\n"), e_type);
931 else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
932 printf (gettext ("Processor Specific: (%x)\n"), e_type);
933 else
934 puts ("???");
935}
936
937
938/* Print ELF header. */
939static void
940print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
941{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000942 fputs_unlocked (gettext ("ELF Header:\n Magic: "), stdout);
Ulrich Drepperd0449522005-09-03 07:23:52 +0000943 for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000944 printf (" %02hhx", ehdr->e_ident[cnt]);
945
946 printf (gettext ("\n Class: %s\n"),
947 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
948 : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
949 : "\?\?\?");
950
951 printf (gettext (" Data: %s\n"),
952 ehdr->e_ident[EI_DATA] == ELFDATA2LSB
953 ? "2's complement, little endian"
954 : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
955 ? "2's complement, big endian" : "\?\?\?");
956
Ulrich Drepper41a99082006-05-28 00:01:43 +0000957 printf (gettext (" Ident Version: %hhd %s\n"),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000958 ehdr->e_ident[EI_VERSION],
959 ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
960 : "(\?\?\?)");
961
Ulrich Drepperd0449522005-09-03 07:23:52 +0000962 char buf[512];
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000963 printf (gettext (" OS/ABI: %s\n"),
964 ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
965
966 printf (gettext (" ABI Version: %hhd\n"),
967 ehdr->e_ident[EI_ABIVERSION]);
968
969 fputs_unlocked (gettext (" Type: "), stdout);
970 print_file_type (ehdr->e_type);
971
972 printf (gettext (" Machine: %s\n"), ebl->name);
973
974 printf (gettext (" Version: %d %s\n"),
975 ehdr->e_version,
976 ehdr->e_version == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
977
978 printf (gettext (" Entry point address: %#" PRIx64 "\n"),
979 ehdr->e_entry);
980
981 printf (gettext (" Start of program headers: %" PRId64 " %s\n"),
982 ehdr->e_phoff, gettext ("(bytes into file)"));
983
984 printf (gettext (" Start of section headers: %" PRId64 " %s\n"),
985 ehdr->e_shoff, gettext ("(bytes into file)"));
986
987 printf (gettext (" Flags: %s\n"),
988 ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
989
990 printf (gettext (" Size of this header: %" PRId16 " %s\n"),
991 ehdr->e_ehsize, gettext ("(bytes)"));
992
993 printf (gettext (" Size of program header entries: %" PRId16 " %s\n"),
994 ehdr->e_phentsize, gettext ("(bytes)"));
995
Roland McGrath8111da02010-01-07 20:31:59 -0800996 printf (gettext (" Number of program headers entries: %" PRId16),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000997 ehdr->e_phnum);
Roland McGrath8111da02010-01-07 20:31:59 -0800998 if (ehdr->e_phnum == PN_XNUM)
999 {
1000 GElf_Shdr shdr_mem;
1001 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
1002 if (shdr != NULL)
1003 printf (gettext (" (%" PRIu32 " in [0].sh_info)"),
1004 (uint32_t) shdr->sh_info);
1005 else
1006 fputs_unlocked (gettext (" ([0] not available)"), stdout);
1007 }
1008 fputc_unlocked ('\n', stdout);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001009
1010 printf (gettext (" Size of section header entries: %" PRId16 " %s\n"),
1011 ehdr->e_shentsize, gettext ("(bytes)"));
1012
1013 printf (gettext (" Number of section headers entries: %" PRId16),
1014 ehdr->e_shnum);
1015 if (ehdr->e_shnum == 0)
1016 {
1017 GElf_Shdr shdr_mem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001018 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001019 if (shdr != NULL)
1020 printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
1021 (uint32_t) shdr->sh_size);
1022 else
1023 fputs_unlocked (gettext (" ([0] not available)"), stdout);
1024 }
1025 fputc_unlocked ('\n', stdout);
1026
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001027 if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001028 {
1029 GElf_Shdr shdr_mem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001030 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001031 if (shdr != NULL)
1032 /* We managed to get the zeroth section. */
1033 snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
1034 (uint32_t) shdr->sh_link);
1035 else
1036 {
1037 strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
1038 buf[sizeof (buf) - 1] = '\0';
1039 }
1040
1041 printf (gettext (" Section header string table index: XINDEX%s\n\n"),
1042 buf);
1043 }
1044 else
1045 printf (gettext (" Section header string table index: %" PRId16 "\n\n"),
1046 ehdr->e_shstrndx);
1047}
1048
1049
1050static const char *
1051get_visibility_type (int value)
1052{
1053 switch (value)
1054 {
1055 case STV_DEFAULT:
1056 return "DEFAULT";
1057 case STV_INTERNAL:
1058 return "INTERNAL";
1059 case STV_HIDDEN:
1060 return "HIDDEN";
1061 case STV_PROTECTED:
1062 return "PROTECTED";
1063 default:
1064 return "???";
1065 }
1066}
1067
1068
1069/* Print the section headers. */
1070static void
1071print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
1072{
1073 size_t cnt;
1074 size_t shstrndx;
1075
1076 if (! print_file_header)
1077 printf (gettext ("\
1078There are %d section headers, starting at offset %#" PRIx64 ":\n\
1079\n"),
1080 ehdr->e_shnum, ehdr->e_shoff);
1081
1082 /* Get the section header string table index. */
Ulrich Drepperf1894932009-06-13 15:55:42 -07001083 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001084 error (EXIT_FAILURE, 0,
1085 gettext ("cannot get section header string table index"));
1086
1087 puts (gettext ("Section Headers:"));
1088
1089 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1090 puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
1091 else
1092 puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
1093
1094 for (cnt = 0; cnt < shnum; ++cnt)
1095 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001096 Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001097
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001098 if (unlikely (scn == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001099 error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
1100 elf_errmsg (-1));
1101
1102 /* Get the section header. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001103 GElf_Shdr shdr_mem;
1104 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001105 if (unlikely (shdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001106 error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
1107 elf_errmsg (-1));
1108
Ulrich Drepperd0449522005-09-03 07:23:52 +00001109 char flagbuf[20];
1110 char *cp = flagbuf;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001111 if (shdr->sh_flags & SHF_WRITE)
1112 *cp++ = 'W';
1113 if (shdr->sh_flags & SHF_ALLOC)
1114 *cp++ = 'A';
1115 if (shdr->sh_flags & SHF_EXECINSTR)
1116 *cp++ = 'X';
1117 if (shdr->sh_flags & SHF_MERGE)
1118 *cp++ = 'M';
1119 if (shdr->sh_flags & SHF_STRINGS)
1120 *cp++ = 'S';
1121 if (shdr->sh_flags & SHF_INFO_LINK)
1122 *cp++ = 'I';
1123 if (shdr->sh_flags & SHF_LINK_ORDER)
1124 *cp++ = 'L';
1125 if (shdr->sh_flags & SHF_OS_NONCONFORMING)
1126 *cp++ = 'N';
1127 if (shdr->sh_flags & SHF_GROUP)
1128 *cp++ = 'G';
1129 if (shdr->sh_flags & SHF_TLS)
1130 *cp++ = 'T';
1131 if (shdr->sh_flags & SHF_ORDERED)
1132 *cp++ = 'O';
1133 if (shdr->sh_flags & SHF_EXCLUDE)
1134 *cp++ = 'E';
1135 *cp = '\0';
1136
Ulrich Drepperd0449522005-09-03 07:23:52 +00001137 char buf[128];
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001138 printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
1139 " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
1140 " %2" PRId64 "\n",
1141 cnt,
1142 elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
1143 ?: "<corrupt>",
1144 ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
1145 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
1146 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
1147 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
1148 shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
1149 shdr->sh_addralign);
1150 }
1151
1152 fputc_unlocked ('\n', stdout);
1153}
1154
1155
1156/* Print the program header. */
1157static void
1158print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
1159{
Mark Wielaard712c8fa2014-11-22 23:08:48 +01001160 if (phnum == 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001161 /* No program header, this is OK in relocatable objects. */
1162 return;
1163
1164 puts (gettext ("Program Headers:"));
1165 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1166 puts (gettext ("\
1167 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
1168 else
1169 puts (gettext ("\
1170 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
1171
1172 /* Process all program headers. */
1173 bool has_relro = false;
1174 GElf_Addr relro_from = 0;
1175 GElf_Addr relro_to = 0;
Roland McGrath8111da02010-01-07 20:31:59 -08001176 for (size_t cnt = 0; cnt < phnum; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001177 {
1178 char buf[128];
1179 GElf_Phdr mem;
1180 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
1181
1182 /* If for some reason the header cannot be returned show this. */
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001183 if (unlikely (phdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001184 {
1185 puts (" ???");
1186 continue;
1187 }
1188
1189 printf (" %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
1190 " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
1191 ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
1192 phdr->p_offset,
1193 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
1194 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
1195 phdr->p_filesz,
1196 phdr->p_memsz,
1197 phdr->p_flags & PF_R ? 'R' : ' ',
1198 phdr->p_flags & PF_W ? 'W' : ' ',
1199 phdr->p_flags & PF_X ? 'E' : ' ',
1200 phdr->p_align);
1201
1202 if (phdr->p_type == PT_INTERP)
1203 {
Mark Wielaardcb7b2d62014-02-24 17:44:42 +01001204 /* If we are sure the file offset is valid then we can show
1205 the user the name of the interpreter. We check whether
1206 there is a section at the file offset. Normally there
1207 would be a section called ".interp". But in separate
1208 .debug files it is a NOBITS section (and so doesn't match
1209 with gelf_offscn). Which probably means the offset is
1210 not valid another reason could be because the ELF file
1211 just doesn't contain any section headers, in that case
1212 just play it safe and don't display anything. */
1213
1214 Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
1215 GElf_Shdr shdr_mem;
1216 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1217
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001218 size_t maxsize;
1219 char *filedata = elf_rawfile (ebl->elf, &maxsize);
1220
Mark Wielaardcb7b2d62014-02-24 17:44:42 +01001221 if (shdr != NULL && shdr->sh_type == SHT_PROGBITS
1222 && filedata != NULL && phdr->p_offset < maxsize
Mark Wielaard43c9c2d2014-02-07 14:23:24 +01001223 && phdr->p_filesz <= maxsize - phdr->p_offset
1224 && memchr (filedata + phdr->p_offset, '\0',
1225 phdr->p_filesz) != NULL)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001226 printf (gettext ("\t[Requesting program interpreter: %s]\n"),
1227 filedata + phdr->p_offset);
1228 }
1229 else if (phdr->p_type == PT_GNU_RELRO)
1230 {
1231 has_relro = true;
1232 relro_from = phdr->p_vaddr;
1233 relro_to = relro_from + phdr->p_memsz;
1234 }
1235 }
1236
Roland McGrath9a847e12009-01-22 19:55:00 -08001237 if (ehdr->e_shnum == 0)
1238 /* No sections in the file. Punt. */
1239 return;
1240
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001241 /* Get the section header string table index. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001242 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001243 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001244 error (EXIT_FAILURE, 0,
1245 gettext ("cannot get section header string table index"));
1246
1247 puts (gettext ("\n Section to Segment mapping:\n Segment Sections..."));
1248
Roland McGrath8111da02010-01-07 20:31:59 -08001249 for (size_t cnt = 0; cnt < phnum; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001250 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001251 /* Print the segment number. */
1252 printf (" %2.2zu ", cnt);
1253
Ulrich Drepperd0449522005-09-03 07:23:52 +00001254 GElf_Phdr phdr_mem;
1255 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001256 /* This must not happen. */
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001257 if (unlikely (phdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001258 error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
1259 elf_errmsg (-1));
1260
1261 /* Iterate over the sections. */
1262 bool in_relro = false;
1263 bool in_ro = false;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001264 for (size_t inner = 1; inner < shnum; ++inner)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001265 {
1266 Elf_Scn *scn = elf_getscn (ebl->elf, inner);
Ulrich Drepperd0449522005-09-03 07:23:52 +00001267 /* This should not happen. */
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001268 if (unlikely (scn == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001269 error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
1270 elf_errmsg (-1));
1271
1272 /* Get the section header. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001273 GElf_Shdr shdr_mem;
1274 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001275 if (unlikely (shdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001276 error (EXIT_FAILURE, 0,
1277 gettext ("cannot get section header: %s"),
1278 elf_errmsg (-1));
1279
1280 if (shdr->sh_size > 0
1281 /* Compare allocated sections by VMA, unallocated
1282 sections by file offset. */
1283 && (shdr->sh_flags & SHF_ALLOC
1284 ? (shdr->sh_addr >= phdr->p_vaddr
1285 && (shdr->sh_addr + shdr->sh_size
1286 <= phdr->p_vaddr + phdr->p_memsz))
1287 : (shdr->sh_offset >= phdr->p_offset
1288 && (shdr->sh_offset + shdr->sh_size
1289 <= phdr->p_offset + phdr->p_filesz))))
1290 {
1291 if (has_relro && !in_relro
1292 && shdr->sh_addr >= relro_from
1293 && shdr->sh_addr + shdr->sh_size <= relro_to)
1294 {
1295 fputs_unlocked (" [RELRO:", stdout);
1296 in_relro = true;
1297 }
1298 else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
1299 {
1300 fputs_unlocked ("]", stdout);
1301 in_relro = false;
1302 }
1303 else if (has_relro && in_relro
1304 && shdr->sh_addr + shdr->sh_size > relro_to)
1305 fputs_unlocked ("] <RELRO:", stdout);
1306 else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
1307 {
1308 if (!in_ro)
1309 {
1310 fputs_unlocked (" [RO:", stdout);
1311 in_ro = true;
1312 }
1313 }
1314 else
1315 {
1316 /* Determine the segment this section is part of. */
1317 size_t cnt2;
Mark Wielaard222cd822015-06-18 20:24:39 +02001318 GElf_Phdr phdr2_mem;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001319 GElf_Phdr *phdr2 = NULL;
Roland McGrath8111da02010-01-07 20:31:59 -08001320 for (cnt2 = 0; cnt2 < phnum; ++cnt2)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001321 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001322 phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
1323
1324 if (phdr2 != NULL && phdr2->p_type == PT_LOAD
1325 && shdr->sh_addr >= phdr2->p_vaddr
1326 && (shdr->sh_addr + shdr->sh_size
1327 <= phdr2->p_vaddr + phdr2->p_memsz))
1328 break;
1329 }
1330
Roland McGrath8111da02010-01-07 20:31:59 -08001331 if (cnt2 < phnum)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001332 {
1333 if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
1334 {
1335 fputs_unlocked (" [RO:", stdout);
1336 in_ro = true;
1337 }
1338 else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
1339 {
1340 fputs_unlocked ("]", stdout);
1341 in_ro = false;
1342 }
1343 }
1344 }
1345
1346 printf (" %s",
1347 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1348
1349 /* Signal that this sectin is only partially covered. */
1350 if (has_relro && in_relro
1351 && shdr->sh_addr + shdr->sh_size > relro_to)
1352 {
1353 fputs_unlocked (">", stdout);
1354 in_relro = false;
1355 }
1356 }
1357 }
1358 if (in_relro || in_ro)
1359 fputs_unlocked ("]", stdout);
1360
1361 /* Finish the line. */
1362 fputc_unlocked ('\n', stdout);
1363 }
1364}
1365
1366
Roland McGrath725aad52011-02-23 19:52:46 -08001367static const char *
1368section_name (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr)
1369{
1370 return elf_strptr (ebl->elf, ehdr->e_shstrndx, shdr->sh_name) ?: "???";
1371}
1372
1373
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001374static void
1375handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1376{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001377 /* Get the data of the section. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001378 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001379
Ulrich Drepperd0449522005-09-03 07:23:52 +00001380 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1381 GElf_Shdr symshdr_mem;
1382 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1383 Elf_Data *symdata = elf_getdata (symscn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001384
1385 if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
1386 || symdata == NULL)
1387 return;
1388
1389 /* Get the section header string table index. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001390 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001391 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001392 error (EXIT_FAILURE, 0,
1393 gettext ("cannot get section header string table index"));
1394
Ulrich Drepperd0449522005-09-03 07:23:52 +00001395 Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001396
Ulrich Drepperd0449522005-09-03 07:23:52 +00001397 GElf_Sym sym_mem;
Roland McGrath7d5b3012014-01-17 17:11:39 +01001398 GElf_Sym *sym = gelf_getsym (symdata, shdr->sh_info, &sym_mem);
1399
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001400 printf ((grpref[0] & GRP_COMDAT)
1401 ? ngettext ("\
1402\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
1403 "\
1404\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1405 data->d_size / sizeof (Elf32_Word) - 1)
1406 : ngettext ("\
1407\nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
1408\nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1409 data->d_size / sizeof (Elf32_Word) - 1),
1410 elf_ndxscn (scn),
1411 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
Roland McGrath7d5b3012014-01-17 17:11:39 +01001412 (sym == NULL ? NULL
1413 : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001414 ?: gettext ("<INVALID SYMBOL>"),
1415 data->d_size / sizeof (Elf32_Word) - 1);
1416
Ulrich Drepperd0449522005-09-03 07:23:52 +00001417 for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001418 {
1419 GElf_Shdr grpshdr_mem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001420 GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
1421 &grpshdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001422
Ulrich Drepperd0449522005-09-03 07:23:52 +00001423 const char *str;
1424 printf (" [%2u] %s\n",
1425 grpref[cnt],
1426 grpshdr != NULL
1427 && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
1428 ? str : gettext ("<INVALID SECTION>"));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001429 }
1430}
1431
1432
1433static void
1434print_scngrp (Ebl *ebl)
1435{
1436 /* Find all relocation sections and handle them. */
1437 Elf_Scn *scn = NULL;
1438
1439 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1440 {
1441 /* Handle the section if it is a symbol table. */
1442 GElf_Shdr shdr_mem;
1443 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1444
1445 if (shdr != NULL && shdr->sh_type == SHT_GROUP)
1446 handle_scngrp (ebl, scn, shdr);
1447 }
1448}
1449
1450
1451static const struct flags
1452{
1453 int mask;
1454 const char *str;
1455} dt_flags[] =
1456 {
1457 { DF_ORIGIN, "ORIGIN" },
1458 { DF_SYMBOLIC, "SYMBOLIC" },
1459 { DF_TEXTREL, "TEXTREL" },
1460 { DF_BIND_NOW, "BIND_NOW" },
1461 { DF_STATIC_TLS, "STATIC_TLS" }
1462 };
1463static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
1464
1465static const struct flags dt_flags_1[] =
1466 {
1467 { DF_1_NOW, "NOW" },
1468 { DF_1_GLOBAL, "GLOBAL" },
1469 { DF_1_GROUP, "GROUP" },
1470 { DF_1_NODELETE, "NODELETE" },
1471 { DF_1_LOADFLTR, "LOADFLTR" },
1472 { DF_1_INITFIRST, "INITFIRST" },
1473 { DF_1_NOOPEN, "NOOPEN" },
1474 { DF_1_ORIGIN, "ORIGIN" },
1475 { DF_1_DIRECT, "DIRECT" },
1476 { DF_1_TRANS, "TRANS" },
1477 { DF_1_INTERPOSE, "INTERPOSE" },
1478 { DF_1_NODEFLIB, "NODEFLIB" },
1479 { DF_1_NODUMP, "NODUMP" },
1480 { DF_1_CONFALT, "CONFALT" },
1481 { DF_1_ENDFILTEE, "ENDFILTEE" },
1482 { DF_1_DISPRELDNE, "DISPRELDNE" },
1483 { DF_1_DISPRELPND, "DISPRELPND" },
1484 };
1485static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
1486
1487static const struct flags dt_feature_1[] =
1488 {
1489 { DTF_1_PARINIT, "PARINIT" },
1490 { DTF_1_CONFEXP, "CONFEXP" }
1491 };
1492static const int ndt_feature_1 = (sizeof (dt_feature_1)
1493 / sizeof (dt_feature_1[0]));
1494
1495static const struct flags dt_posflag_1[] =
1496 {
1497 { DF_P1_LAZYLOAD, "LAZYLOAD" },
1498 { DF_P1_GROUPPERM, "GROUPPERM" }
1499 };
1500static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
1501 / sizeof (dt_posflag_1[0]));
1502
1503
1504static void
1505print_flags (int class, GElf_Xword d_val, const struct flags *flags,
1506 int nflags)
1507{
1508 bool first = true;
1509 int cnt;
1510
1511 for (cnt = 0; cnt < nflags; ++cnt)
1512 if (d_val & flags[cnt].mask)
1513 {
1514 if (!first)
1515 putchar_unlocked (' ');
1516 fputs_unlocked (flags[cnt].str, stdout);
1517 d_val &= ~flags[cnt].mask;
1518 first = false;
1519 }
1520
1521 if (d_val != 0)
1522 {
1523 if (!first)
1524 putchar_unlocked (' ');
1525 printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
1526 }
1527
1528 putchar_unlocked ('\n');
1529}
1530
1531
1532static void
1533print_dt_flags (int class, GElf_Xword d_val)
1534{
1535 print_flags (class, d_val, dt_flags, ndt_flags);
1536}
1537
1538
1539static void
1540print_dt_flags_1 (int class, GElf_Xword d_val)
1541{
1542 print_flags (class, d_val, dt_flags_1, ndt_flags_1);
1543}
1544
1545
1546static void
1547print_dt_feature_1 (int class, GElf_Xword d_val)
1548{
1549 print_flags (class, d_val, dt_feature_1, ndt_feature_1);
1550}
1551
1552
1553static void
1554print_dt_posflag_1 (int class, GElf_Xword d_val)
1555{
1556 print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
1557}
1558
1559
1560static void
1561handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1562{
1563 int class = gelf_getclass (ebl->elf);
Roland McGrath7d5b3012014-01-17 17:11:39 +01001564 GElf_Shdr glink_mem;
1565 GElf_Shdr *glink;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001566 Elf_Data *data;
1567 size_t cnt;
1568 size_t shstrndx;
Petr Machataced66872014-01-17 17:00:12 +01001569 size_t sh_entsize;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001570
1571 /* Get the data of the section. */
1572 data = elf_getdata (scn, NULL);
1573 if (data == NULL)
1574 return;
1575
1576 /* Get the section header string table index. */
Ulrich Drepperf1894932009-06-13 15:55:42 -07001577 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001578 error (EXIT_FAILURE, 0,
1579 gettext ("cannot get section header string table index"));
1580
Petr Machataced66872014-01-17 17:00:12 +01001581 sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT);
1582
1583 glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
1584 if (glink == NULL)
1585 error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"),
1586 elf_ndxscn (scn));
1587
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001588 printf (ngettext ("\
1589\nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1590 "\
1591\nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
Petr Machataced66872014-01-17 17:00:12 +01001592 shdr->sh_size / sh_entsize),
1593 (unsigned long int) (shdr->sh_size / sh_entsize),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001594 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
1595 shdr->sh_offset,
1596 (int) shdr->sh_link,
Roland McGrath7d5b3012014-01-17 17:11:39 +01001597 elf_strptr (ebl->elf, shstrndx, glink->sh_name));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001598 fputs_unlocked (gettext (" Type Value\n"), stdout);
1599
Petr Machataced66872014-01-17 17:00:12 +01001600 for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001601 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001602 GElf_Dyn dynmem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001603 GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001604 if (dyn == NULL)
1605 break;
1606
Ulrich Drepperd0449522005-09-03 07:23:52 +00001607 char buf[64];
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001608 printf (" %-17s ",
1609 ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
1610
1611 switch (dyn->d_tag)
1612 {
1613 case DT_NULL:
1614 case DT_DEBUG:
1615 case DT_BIND_NOW:
1616 case DT_TEXTREL:
1617 /* No further output. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001618 fputc_unlocked ('\n', stdout);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001619 break;
1620
1621 case DT_NEEDED:
1622 printf (gettext ("Shared library: [%s]\n"),
1623 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1624 break;
1625
1626 case DT_SONAME:
1627 printf (gettext ("Library soname: [%s]\n"),
1628 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1629 break;
1630
1631 case DT_RPATH:
1632 printf (gettext ("Library rpath: [%s]\n"),
1633 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1634 break;
1635
1636 case DT_RUNPATH:
1637 printf (gettext ("Library runpath: [%s]\n"),
1638 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1639 break;
1640
1641 case DT_PLTRELSZ:
1642 case DT_RELASZ:
1643 case DT_STRSZ:
1644 case DT_RELSZ:
1645 case DT_RELAENT:
1646 case DT_SYMENT:
1647 case DT_RELENT:
1648 case DT_PLTPADSZ:
1649 case DT_MOVEENT:
1650 case DT_MOVESZ:
1651 case DT_INIT_ARRAYSZ:
1652 case DT_FINI_ARRAYSZ:
1653 case DT_SYMINSZ:
1654 case DT_SYMINENT:
1655 case DT_GNU_CONFLICTSZ:
1656 case DT_GNU_LIBLISTSZ:
1657 printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
1658 break;
1659
1660 case DT_VERDEFNUM:
1661 case DT_VERNEEDNUM:
1662 case DT_RELACOUNT:
1663 case DT_RELCOUNT:
1664 printf ("%" PRId64 "\n", dyn->d_un.d_val);
1665 break;
1666
Marek Polacek44de92a2011-03-22 01:07:20 +01001667 case DT_PLTREL:;
1668 const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
1669 NULL, 0);
1670 puts (tagname ?: "???");
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001671 break;
1672
1673 case DT_FLAGS:
1674 print_dt_flags (class, dyn->d_un.d_val);
1675 break;
1676
1677 case DT_FLAGS_1:
1678 print_dt_flags_1 (class, dyn->d_un.d_val);
1679 break;
1680
1681 case DT_FEATURE_1:
1682 print_dt_feature_1 (class, dyn->d_un.d_val);
1683 break;
1684
1685 case DT_POSFLAG_1:
1686 print_dt_posflag_1 (class, dyn->d_un.d_val);
1687 break;
1688
1689 default:
1690 printf ("%#0*" PRIx64 "\n",
1691 class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
1692 break;
1693 }
1694 }
1695}
1696
1697
1698/* Print the dynamic segment. */
1699static void
Roland McGrath8111da02010-01-07 20:31:59 -08001700print_dynamic (Ebl *ebl)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001701{
Roland McGrath8111da02010-01-07 20:31:59 -08001702 for (size_t i = 0; i < phnum; ++i)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001703 {
Ulrich Drepperdbace232005-08-06 01:37:23 +00001704 GElf_Phdr phdr_mem;
1705 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001706
Ulrich Drepperdbace232005-08-06 01:37:23 +00001707 if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001708 {
Ulrich Drepperdbace232005-08-06 01:37:23 +00001709 Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
1710 GElf_Shdr shdr_mem;
1711 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1712 if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
1713 handle_dynamic (ebl, scn, shdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001714 break;
1715 }
1716 }
1717}
1718
1719
1720/* Print relocations. */
1721static void
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001722print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001723{
1724 /* Find all relocation sections and handle them. */
1725 Elf_Scn *scn = NULL;
1726
1727 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1728 {
1729 /* Handle the section if it is a symbol table. */
1730 GElf_Shdr shdr_mem;
1731 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1732
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001733 if (likely (shdr != NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001734 {
1735 if (shdr->sh_type == SHT_REL)
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001736 handle_relocs_rel (ebl, ehdr, scn, shdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001737 else if (shdr->sh_type == SHT_RELA)
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001738 handle_relocs_rela (ebl, ehdr, scn, shdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001739 }
1740 }
1741}
1742
1743
1744/* Handle a relocation section. */
1745static void
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001746handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001747{
1748 int class = gelf_getclass (ebl->elf);
Petr Machataced66872014-01-17 17:00:12 +01001749 size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
1750 int nentries = shdr->sh_size / sh_entsize;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001751
1752 /* Get the data of the section. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001753 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001754 if (data == NULL)
1755 return;
1756
1757 /* Get the symbol table information. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001758 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1759 GElf_Shdr symshdr_mem;
1760 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1761 Elf_Data *symdata = elf_getdata (symscn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001762
1763 /* Get the section header of the section the relocations are for. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001764 GElf_Shdr destshdr_mem;
1765 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1766 &destshdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001767
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001768 if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001769 {
1770 printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1771 shdr->sh_offset);
1772 return;
1773 }
1774
1775 /* Search for the optional extended section index table. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001776 Elf_Data *xndxdata = NULL;
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001777 int xndxscnidx = elf_scnshndx (scn);
1778 if (unlikely (xndxscnidx > 0))
1779 xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001780
1781 /* Get the section header string table index. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001782 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001783 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001784 error (EXIT_FAILURE, 0,
1785 gettext ("cannot get section header string table index"));
1786
1787 if (shdr->sh_info != 0)
1788 printf (ngettext ("\
Ulrich Drepper351bf202009-01-15 20:18:40 -08001789\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001790 "\
Ulrich Drepper351bf202009-01-15 20:18:40 -08001791\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001792 nentries),
Ulrich Drepper351bf202009-01-15 20:18:40 -08001793 elf_ndxscn (scn),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001794 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1795 (unsigned int) shdr->sh_info,
1796 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1797 shdr->sh_offset,
1798 nentries);
1799 else
1800 /* The .rel.dyn section does not refer to a specific section but
1801 instead of section index zero. Do not try to print a section
1802 name. */
1803 printf (ngettext ("\
1804\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1805 "\
1806\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1807 nentries),
1808 (unsigned int) elf_ndxscn (scn),
1809 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1810 shdr->sh_offset,
1811 nentries);
1812 fputs_unlocked (class == ELFCLASS32
1813 ? gettext ("\
1814 Offset Type Value Name\n")
1815 : gettext ("\
1816 Offset Type Value Name\n"),
1817 stdout);
1818
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001819 int is_statically_linked = 0;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001820 for (int cnt = 0; cnt < nentries; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001821 {
1822 GElf_Rel relmem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001823 GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001824 if (likely (rel != NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001825 {
1826 char buf[128];
1827 GElf_Sym symmem;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001828 Elf32_Word xndx;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001829 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1830 GELF_R_SYM (rel->r_info),
1831 &symmem, &xndx);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001832 if (unlikely (sym == NULL))
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001833 {
1834 /* As a special case we have to handle relocations in static
1835 executables. This only happens for IRELATIVE relocations
1836 (so far). There is no symbol table. */
1837 if (is_statically_linked == 0)
1838 {
1839 /* Find the program header and look for a PT_INTERP entry. */
1840 is_statically_linked = -1;
1841 if (ehdr->e_type == ET_EXEC)
1842 {
1843 is_statically_linked = 1;
1844
Roland McGrath8111da02010-01-07 20:31:59 -08001845 for (size_t inner = 0; inner < phnum; ++inner)
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001846 {
1847 GElf_Phdr phdr_mem;
1848 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
1849 &phdr_mem);
1850 if (phdr != NULL && phdr->p_type == PT_INTERP)
1851 {
1852 is_statically_linked = -1;
1853 break;
1854 }
1855 }
1856 }
1857 }
1858
1859 if (is_statically_linked > 0 && shdr->sh_link == 0)
1860 printf ("\
1861 %#0*" PRIx64 " %-20s %*s %s\n",
1862 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1863 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1864 /* Avoid the leading R_ which isn't carrying any
1865 information. */
1866 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1867 buf, sizeof (buf)) + 2
1868 : gettext ("<INVALID RELOC>"),
1869 class == ELFCLASS32 ? 10 : 18, "",
1870 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1871 else
1872 printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
1873 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1874 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1875 /* Avoid the leading R_ which isn't carrying any
1876 information. */
1877 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1878 buf, sizeof (buf)) + 2
1879 : gettext ("<INVALID RELOC>"),
1880 gettext ("INVALID SYMBOL"),
1881 (long int) GELF_R_SYM (rel->r_info));
1882 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001883 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1884 printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
1885 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001886 likely (ebl_reloc_type_check (ebl,
1887 GELF_R_TYPE (rel->r_info)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001888 /* Avoid the leading R_ which isn't carrying any
1889 information. */
1890 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1891 buf, sizeof (buf)) + 2
1892 : gettext ("<INVALID RELOC>"),
1893 class == ELFCLASS32 ? 10 : 18, sym->st_value,
1894 elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1895 else
1896 {
Mark Wielaard98755612014-11-28 22:22:16 +01001897 /* This is a relocation against a STT_SECTION symbol. */
1898 GElf_Shdr secshdr_mem;
1899 GElf_Shdr *secshdr;
1900 secshdr = gelf_getshdr (elf_getscn (ebl->elf,
1901 sym->st_shndx == SHN_XINDEX
1902 ? xndx : sym->st_shndx),
1903 &secshdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001904
Mark Wielaard98755612014-11-28 22:22:16 +01001905 if (unlikely (secshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001906 printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
1907 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1908 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1909 /* Avoid the leading R_ which isn't carrying any
1910 information. */
1911 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1912 buf, sizeof (buf)) + 2
1913 : gettext ("<INVALID RELOC>"),
1914 gettext ("INVALID SECTION"),
1915 (long int) (sym->st_shndx == SHN_XINDEX
1916 ? xndx : sym->st_shndx));
1917 else
1918 printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
1919 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1920 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1921 /* Avoid the leading R_ which isn't carrying any
1922 information. */
1923 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1924 buf, sizeof (buf)) + 2
1925 : gettext ("<INVALID RELOC>"),
1926 class == ELFCLASS32 ? 10 : 18, sym->st_value,
Mark Wielaard98755612014-11-28 22:22:16 +01001927 elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001928 }
1929 }
1930 }
1931}
1932
1933
1934/* Handle a relocation section. */
1935static void
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001936handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001937{
1938 int class = gelf_getclass (ebl->elf);
Petr Machataced66872014-01-17 17:00:12 +01001939 size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
1940 int nentries = shdr->sh_size / sh_entsize;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001941
1942 /* Get the data of the section. */
1943 Elf_Data *data = elf_getdata (scn, NULL);
1944 if (data == NULL)
1945 return;
1946
1947 /* Get the symbol table information. */
1948 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1949 GElf_Shdr symshdr_mem;
1950 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1951 Elf_Data *symdata = elf_getdata (symscn, NULL);
1952
1953 /* Get the section header of the section the relocations are for. */
1954 GElf_Shdr destshdr_mem;
1955 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1956 &destshdr_mem);
1957
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001958 if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001959 {
1960 printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1961 shdr->sh_offset);
1962 return;
1963 }
1964
1965 /* Search for the optional extended section index table. */
1966 Elf_Data *xndxdata = NULL;
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001967 int xndxscnidx = elf_scnshndx (scn);
1968 if (unlikely (xndxscnidx > 0))
1969 xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001970
1971 /* Get the section header string table index. */
1972 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001973 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001974 error (EXIT_FAILURE, 0,
1975 gettext ("cannot get section header string table index"));
1976
Mark Wielaardeb4811d2014-05-26 22:54:38 +02001977 if (shdr->sh_info != 0)
1978 printf (ngettext ("\
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001979\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1980 "\
1981\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1982 nentries),
1983 elf_ndxscn (scn),
1984 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1985 (unsigned int) shdr->sh_info,
1986 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1987 shdr->sh_offset,
1988 nentries);
Mark Wielaardeb4811d2014-05-26 22:54:38 +02001989 else
1990 /* The .rela.dyn section does not refer to a specific section but
1991 instead of section index zero. Do not try to print a section
1992 name. */
1993 printf (ngettext ("\
1994\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1995 "\
1996\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1997 nentries),
1998 (unsigned int) elf_ndxscn (scn),
1999 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2000 shdr->sh_offset,
2001 nentries);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002002 fputs_unlocked (class == ELFCLASS32
2003 ? gettext ("\
2004 Offset Type Value Addend Name\n")
2005 : gettext ("\
2006 Offset Type Value Addend Name\n"),
2007 stdout);
2008
Ulrich Drepperb47d2902009-06-01 07:38:32 -07002009 int is_statically_linked = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002010 for (int cnt = 0; cnt < nentries; ++cnt)
2011 {
2012 GElf_Rela relmem;
2013 GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002014 if (likely (rel != NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002015 {
2016 char buf[64];
2017 GElf_Sym symmem;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002018 Elf32_Word xndx;
Ulrich Drepperd0449522005-09-03 07:23:52 +00002019 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
2020 GELF_R_SYM (rel->r_info),
2021 &symmem, &xndx);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002022
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002023 if (unlikely (sym == NULL))
Ulrich Drepperb47d2902009-06-01 07:38:32 -07002024 {
2025 /* As a special case we have to handle relocations in static
2026 executables. This only happens for IRELATIVE relocations
2027 (so far). There is no symbol table. */
2028 if (is_statically_linked == 0)
2029 {
2030 /* Find the program header and look for a PT_INTERP entry. */
2031 is_statically_linked = -1;
2032 if (ehdr->e_type == ET_EXEC)
2033 {
2034 is_statically_linked = 1;
2035
Roland McGrath8111da02010-01-07 20:31:59 -08002036 for (size_t inner = 0; inner < phnum; ++inner)
Ulrich Drepperb47d2902009-06-01 07:38:32 -07002037 {
2038 GElf_Phdr phdr_mem;
2039 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
2040 &phdr_mem);
2041 if (phdr != NULL && phdr->p_type == PT_INTERP)
2042 {
2043 is_statically_linked = -1;
2044 break;
2045 }
2046 }
2047 }
2048 }
2049
2050 if (is_statically_linked > 0 && shdr->sh_link == 0)
2051 printf ("\
2052 %#0*" PRIx64 " %-15s %*s %#6" PRIx64 " %s\n",
2053 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2054 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2055 /* Avoid the leading R_ which isn't carrying any
2056 information. */
2057 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2058 buf, sizeof (buf)) + 2
2059 : gettext ("<INVALID RELOC>"),
2060 class == ELFCLASS32 ? 10 : 18, "",
2061 rel->r_addend,
2062 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
2063 else
2064 printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
2065 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2066 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2067 /* Avoid the leading R_ which isn't carrying any
2068 information. */
2069 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2070 buf, sizeof (buf)) + 2
2071 : gettext ("<INVALID RELOC>"),
2072 gettext ("INVALID SYMBOL"),
2073 (long int) GELF_R_SYM (rel->r_info));
2074 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002075 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
2076 printf ("\
Ulrich Drepper2cb8e732006-05-27 21:57:27 +00002077 %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002078 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002079 likely (ebl_reloc_type_check (ebl,
2080 GELF_R_TYPE (rel->r_info)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002081 /* Avoid the leading R_ which isn't carrying any
2082 information. */
2083 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2084 buf, sizeof (buf)) + 2
2085 : gettext ("<INVALID RELOC>"),
2086 class == ELFCLASS32 ? 10 : 18, sym->st_value,
2087 rel->r_addend,
2088 elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
2089 else
2090 {
Mark Wielaard98755612014-11-28 22:22:16 +01002091 /* This is a relocation against a STT_SECTION symbol. */
2092 GElf_Shdr secshdr_mem;
2093 GElf_Shdr *secshdr;
2094 secshdr = gelf_getshdr (elf_getscn (ebl->elf,
2095 sym->st_shndx == SHN_XINDEX
2096 ? xndx : sym->st_shndx),
2097 &secshdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002098
Mark Wielaard98755612014-11-28 22:22:16 +01002099 if (unlikely (secshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002100 printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
2101 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2102 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2103 /* Avoid the leading R_ which isn't carrying any
2104 information. */
2105 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2106 buf, sizeof (buf)) + 2
2107 : gettext ("<INVALID RELOC>"),
2108 gettext ("INVALID SECTION"),
2109 (long int) (sym->st_shndx == SHN_XINDEX
2110 ? xndx : sym->st_shndx));
2111 else
2112 printf ("\
Ulrich Drepper2cb8e732006-05-27 21:57:27 +00002113 %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002114 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2115 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2116 /* Avoid the leading R_ which isn't carrying any
2117 information. */
2118 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2119 buf, sizeof (buf)) + 2
2120 : gettext ("<INVALID RELOC>"),
2121 class == ELFCLASS32 ? 10 : 18, sym->st_value,
2122 rel->r_addend,
Mark Wielaard98755612014-11-28 22:22:16 +01002123 elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002124 }
2125 }
2126 }
2127}
2128
2129
2130/* Print the program header. */
2131static void
2132print_symtab (Ebl *ebl, int type)
2133{
2134 /* Find the symbol table(s). For this we have to search through the
2135 section table. */
2136 Elf_Scn *scn = NULL;
2137
2138 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2139 {
2140 /* Handle the section if it is a symbol table. */
2141 GElf_Shdr shdr_mem;
2142 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2143
2144 if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
2145 handle_symtab (ebl, scn, shdr);
2146 }
2147}
2148
2149
2150static void
2151handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2152{
2153 Elf_Data *versym_data = NULL;
2154 Elf_Data *verneed_data = NULL;
2155 Elf_Data *verdef_data = NULL;
2156 Elf_Data *xndx_data = NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002157 int class = gelf_getclass (ebl->elf);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002158 Elf32_Word verneed_stridx = 0;
2159 Elf32_Word verdef_stridx = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002160
2161 /* Get the data of the section. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00002162 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002163 if (data == NULL)
2164 return;
2165
2166 /* Find out whether we have other sections we might need. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00002167 Elf_Scn *runscn = NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002168 while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
2169 {
2170 GElf_Shdr runshdr_mem;
2171 GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
2172
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002173 if (likely (runshdr != NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002174 {
2175 if (runshdr->sh_type == SHT_GNU_versym
2176 && runshdr->sh_link == elf_ndxscn (scn))
2177 /* Bingo, found the version information. Now get the data. */
2178 versym_data = elf_getdata (runscn, NULL);
2179 else if (runshdr->sh_type == SHT_GNU_verneed)
2180 {
2181 /* This is the information about the needed versions. */
2182 verneed_data = elf_getdata (runscn, NULL);
2183 verneed_stridx = runshdr->sh_link;
2184 }
2185 else if (runshdr->sh_type == SHT_GNU_verdef)
2186 {
2187 /* This is the information about the defined versions. */
2188 verdef_data = elf_getdata (runscn, NULL);
2189 verdef_stridx = runshdr->sh_link;
2190 }
2191 else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
2192 && runshdr->sh_link == elf_ndxscn (scn))
2193 /* Extended section index. */
2194 xndx_data = elf_getdata (runscn, NULL);
2195 }
2196 }
2197
2198 /* Get the section header string table index. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00002199 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07002200 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002201 error (EXIT_FAILURE, 0,
2202 gettext ("cannot get section header string table index"));
2203
Roland McGrath7d5b3012014-01-17 17:11:39 +01002204 GElf_Shdr glink_mem;
2205 GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2206 &glink_mem);
2207 if (glink == NULL)
2208 error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"),
2209 elf_ndxscn (scn));
2210
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002211 /* Now we can compute the number of entries in the section. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00002212 unsigned int nsyms = data->d_size / (class == ELFCLASS32
2213 ? sizeof (Elf32_Sym)
2214 : sizeof (Elf64_Sym));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002215
2216 printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
2217 "\nSymbol table [%2u] '%s' contains %u entries:\n",
2218 nsyms),
2219 (unsigned int) elf_ndxscn (scn),
2220 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
2221 printf (ngettext (" %lu local symbol String table: [%2u] '%s'\n",
2222 " %lu local symbols String table: [%2u] '%s'\n",
2223 shdr->sh_info),
2224 (unsigned long int) shdr->sh_info,
2225 (unsigned int) shdr->sh_link,
Roland McGrath7d5b3012014-01-17 17:11:39 +01002226 elf_strptr (ebl->elf, shstrndx, glink->sh_name));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002227
2228 fputs_unlocked (class == ELFCLASS32
2229 ? gettext ("\
2230 Num: Value Size Type Bind Vis Ndx Name\n")
2231 : gettext ("\
2232 Num: Value Size Type Bind Vis Ndx Name\n"),
2233 stdout);
2234
Ulrich Drepperd0449522005-09-03 07:23:52 +00002235 for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002236 {
2237 char typebuf[64];
2238 char bindbuf[64];
2239 char scnbuf[64];
2240 Elf32_Word xndx;
2241 GElf_Sym sym_mem;
2242 GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
2243
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002244 if (unlikely (sym == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002245 continue;
2246
2247 /* Determine the real section index. */
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002248 if (likely (sym->st_shndx != SHN_XINDEX))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002249 xndx = sym->st_shndx;
2250
2251 printf (gettext ("\
2252%5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
2253 cnt,
2254 class == ELFCLASS32 ? 8 : 16,
2255 sym->st_value,
2256 sym->st_size,
2257 ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
2258 typebuf, sizeof (typebuf)),
2259 ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
2260 bindbuf, sizeof (bindbuf)),
2261 get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
2262 ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
2263 sizeof (scnbuf), NULL, shnum),
2264 elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
2265
2266 if (versym_data != NULL)
2267 {
2268 /* Get the version information. */
2269 GElf_Versym versym_mem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00002270 GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002271
2272 if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
2273 {
2274 bool is_nobits = false;
2275 bool check_def = xndx != SHN_UNDEF;
2276
2277 if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
2278 {
2279 GElf_Shdr symshdr_mem;
2280 GElf_Shdr *symshdr =
2281 gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
2282
2283 is_nobits = (symshdr != NULL
2284 && symshdr->sh_type == SHT_NOBITS);
2285 }
2286
2287 if (is_nobits || ! check_def)
2288 {
2289 /* We must test both. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002290 GElf_Vernaux vernaux_mem;
2291 GElf_Vernaux *vernaux = NULL;
2292 size_t vn_offset = 0;
2293
Ulrich Drepperd0449522005-09-03 07:23:52 +00002294 GElf_Verneed verneed_mem;
2295 GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
2296 &verneed_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002297 while (verneed != NULL)
2298 {
2299 size_t vna_offset = vn_offset;
2300
2301 vernaux = gelf_getvernaux (verneed_data,
2302 vna_offset += verneed->vn_aux,
2303 &vernaux_mem);
2304 while (vernaux != NULL
2305 && vernaux->vna_other != *versym
2306 && vernaux->vna_next != 0)
2307 {
2308 /* Update the offset. */
2309 vna_offset += vernaux->vna_next;
2310
2311 vernaux = (vernaux->vna_next == 0
2312 ? NULL
2313 : gelf_getvernaux (verneed_data,
2314 vna_offset,
2315 &vernaux_mem));
2316 }
2317
2318 /* Check whether we found the version. */
2319 if (vernaux != NULL && vernaux->vna_other == *versym)
2320 /* Found it. */
2321 break;
2322
2323 vn_offset += verneed->vn_next;
2324 verneed = (verneed->vn_next == 0
2325 ? NULL
2326 : gelf_getverneed (verneed_data, vn_offset,
2327 &verneed_mem));
2328 }
2329
2330 if (vernaux != NULL && vernaux->vna_other == *versym)
2331 {
2332 printf ("@%s (%u)",
2333 elf_strptr (ebl->elf, verneed_stridx,
2334 vernaux->vna_name),
2335 (unsigned int) vernaux->vna_other);
2336 check_def = 0;
2337 }
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002338 else if (unlikely (! is_nobits))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002339 error (0, 0, gettext ("bad dynamic symbol"));
2340 else
2341 check_def = 1;
2342 }
2343
2344 if (check_def && *versym != 0x8001)
2345 {
2346 /* We must test both. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002347 size_t vd_offset = 0;
2348
Ulrich Drepperd0449522005-09-03 07:23:52 +00002349 GElf_Verdef verdef_mem;
2350 GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
2351 &verdef_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002352 while (verdef != NULL)
2353 {
2354 if (verdef->vd_ndx == (*versym & 0x7fff))
2355 /* Found the definition. */
2356 break;
2357
2358 vd_offset += verdef->vd_next;
2359 verdef = (verdef->vd_next == 0
2360 ? NULL
2361 : gelf_getverdef (verdef_data, vd_offset,
2362 &verdef_mem));
2363 }
2364
2365 if (verdef != NULL)
2366 {
2367 GElf_Verdaux verdaux_mem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00002368 GElf_Verdaux *verdaux
2369 = gelf_getverdaux (verdef_data,
2370 vd_offset + verdef->vd_aux,
2371 &verdaux_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002372
2373 if (verdaux != NULL)
2374 printf ((*versym & 0x8000) ? "@%s" : "@@%s",
2375 elf_strptr (ebl->elf, verdef_stridx,
2376 verdaux->vda_name));
2377 }
2378 }
2379 }
2380 }
2381
Ulrich Drepperd0449522005-09-03 07:23:52 +00002382 putchar_unlocked ('\n');
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002383 }
2384}
2385
2386
2387/* Print version information. */
2388static void
2389print_verinfo (Ebl *ebl)
2390{
2391 /* Find the version information sections. For this we have to
2392 search through the section table. */
2393 Elf_Scn *scn = NULL;
2394
2395 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2396 {
2397 /* Handle the section if it is part of the versioning handling. */
2398 GElf_Shdr shdr_mem;
2399 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2400
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002401 if (likely (shdr != NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002402 {
2403 if (shdr->sh_type == SHT_GNU_verneed)
2404 handle_verneed (ebl, scn, shdr);
2405 else if (shdr->sh_type == SHT_GNU_verdef)
2406 handle_verdef (ebl, scn, shdr);
2407 else if (shdr->sh_type == SHT_GNU_versym)
2408 handle_versym (ebl, scn, shdr);
2409 }
2410 }
2411}
2412
2413
2414static const char *
2415get_ver_flags (unsigned int flags)
2416{
2417 static char buf[32];
2418 char *endp;
2419
2420 if (flags == 0)
2421 return gettext ("none");
2422
2423 if (flags & VER_FLG_BASE)
2424 endp = stpcpy (buf, "BASE ");
2425 else
2426 endp = buf;
2427
2428 if (flags & VER_FLG_WEAK)
2429 {
2430 if (endp != buf)
Ulrich Drepper173ade82010-05-28 07:39:49 -07002431 endp = stpcpy (endp, "| ");
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002432
2433 endp = stpcpy (endp, "WEAK ");
2434 }
2435
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002436 if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002437 {
2438 strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
2439 buf[sizeof (buf) - 1] = '\0';
2440 }
2441
2442 return buf;
2443}
2444
2445
2446static void
2447handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2448{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002449 int class = gelf_getclass (ebl->elf);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002450
2451 /* Get the data of the section. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002452 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002453 if (data == NULL)
2454 return;
2455
2456 /* Get the section header string table index. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002457 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07002458 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002459 error (EXIT_FAILURE, 0,
2460 gettext ("cannot get section header string table index"));
2461
Roland McGrath7d5b3012014-01-17 17:11:39 +01002462 GElf_Shdr glink_mem;
2463 GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2464 &glink_mem);
2465 if (glink == NULL)
2466 error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"),
2467 elf_ndxscn (scn));
2468
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002469 printf (ngettext ("\
2470\nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2471 "\
2472\nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2473 shdr->sh_info),
2474 (unsigned int) elf_ndxscn (scn),
2475 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
2476 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2477 shdr->sh_offset,
2478 (unsigned int) shdr->sh_link,
Roland McGrath7d5b3012014-01-17 17:11:39 +01002479 elf_strptr (ebl->elf, shstrndx, glink->sh_name));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002480
Ulrich Drepperdbace232005-08-06 01:37:23 +00002481 unsigned int offset = 0;
2482 for (int cnt = shdr->sh_info; --cnt >= 0; )
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002483 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002484 /* Get the data at the next offset. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002485 GElf_Verneed needmem;
2486 GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002487 if (unlikely (need == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002488 break;
2489
2490 printf (gettext (" %#06x: Version: %hu File: %s Cnt: %hu\n"),
2491 offset, (unsigned short int) need->vn_version,
2492 elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
2493 (unsigned short int) need->vn_cnt);
2494
Ulrich Drepperdbace232005-08-06 01:37:23 +00002495 unsigned int auxoffset = offset + need->vn_aux;
2496 for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002497 {
2498 GElf_Vernaux auxmem;
Ulrich Drepperdbace232005-08-06 01:37:23 +00002499 GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002500 if (unlikely (aux == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002501 break;
2502
2503 printf (gettext (" %#06x: Name: %s Flags: %s Version: %hu\n"),
2504 auxoffset,
2505 elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
2506 get_ver_flags (aux->vna_flags),
2507 (unsigned short int) aux->vna_other);
2508
Mark Wielaard3b3a1912014-11-17 23:35:28 +01002509 if (aux->vna_next == 0)
2510 break;
2511
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002512 auxoffset += aux->vna_next;
2513 }
2514
2515 /* Find the next offset. */
Mark Wielaard3b3a1912014-11-17 23:35:28 +01002516 if (need->vn_next == 0)
2517 break;
2518
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002519 offset += need->vn_next;
2520 }
2521}
2522
2523
2524static void
2525handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2526{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002527 /* Get the data of the section. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002528 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002529 if (data == NULL)
2530 return;
2531
2532 /* Get the section header string table index. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002533 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07002534 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002535 error (EXIT_FAILURE, 0,
2536 gettext ("cannot get section header string table index"));
2537
Roland McGrath7d5b3012014-01-17 17:11:39 +01002538 GElf_Shdr glink_mem;
2539 GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2540 &glink_mem);
2541 if (glink == NULL)
2542 error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"),
2543 elf_ndxscn (scn));
2544
Ulrich Drepperdbace232005-08-06 01:37:23 +00002545 int class = gelf_getclass (ebl->elf);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002546 printf (ngettext ("\
2547\nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2548 "\
2549\nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2550 shdr->sh_info),
2551 (unsigned int) elf_ndxscn (scn),
2552 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2553 shdr->sh_info,
2554 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2555 shdr->sh_offset,
2556 (unsigned int) shdr->sh_link,
Roland McGrath7d5b3012014-01-17 17:11:39 +01002557 elf_strptr (ebl->elf, shstrndx, glink->sh_name));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002558
Ulrich Drepperdbace232005-08-06 01:37:23 +00002559 unsigned int offset = 0;
2560 for (int cnt = shdr->sh_info; --cnt >= 0; )
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002561 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002562 /* Get the data at the next offset. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002563 GElf_Verdef defmem;
2564 GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002565 if (unlikely (def == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002566 break;
2567
Ulrich Drepperdbace232005-08-06 01:37:23 +00002568 unsigned int auxoffset = offset + def->vd_aux;
2569 GElf_Verdaux auxmem;
2570 GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002571 if (unlikely (aux == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002572 break;
2573
2574 printf (gettext ("\
2575 %#06x: Version: %hd Flags: %s Index: %hd Cnt: %hd Name: %s\n"),
2576 offset, def->vd_version,
2577 get_ver_flags (def->vd_flags),
2578 def->vd_ndx,
2579 def->vd_cnt,
2580 elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2581
2582 auxoffset += aux->vda_next;
Ulrich Drepperdbace232005-08-06 01:37:23 +00002583 for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002584 {
2585 aux = gelf_getverdaux (data, auxoffset, &auxmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002586 if (unlikely (aux == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002587 break;
2588
2589 printf (gettext (" %#06x: Parent %d: %s\n"),
2590 auxoffset, cnt2,
2591 elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2592
Mark Wielaard3b3a1912014-11-17 23:35:28 +01002593 if (aux->vda_next == 0)
2594 break;
2595
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002596 auxoffset += aux->vda_next;
2597 }
2598
2599 /* Find the next offset. */
Mark Wielaard3b3a1912014-11-17 23:35:28 +01002600 if (def->vd_next == 0)
2601 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002602 offset += def->vd_next;
2603 }
2604}
2605
2606
2607static void
2608handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2609{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002610 int class = gelf_getclass (ebl->elf);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002611 const char **vername;
2612 const char **filename;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002613
2614 /* Get the data of the section. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002615 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002616 if (data == NULL)
2617 return;
2618
2619 /* Get the section header string table index. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002620 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07002621 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002622 error (EXIT_FAILURE, 0,
2623 gettext ("cannot get section header string table index"));
2624
2625 /* We have to find the version definition section and extract the
2626 version names. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002627 Elf_Scn *defscn = NULL;
2628 Elf_Scn *needscn = NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002629
Ulrich Drepperdbace232005-08-06 01:37:23 +00002630 Elf_Scn *verscn = NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002631 while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
2632 {
2633 GElf_Shdr vershdr_mem;
2634 GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
2635
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002636 if (likely (vershdr != NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002637 {
2638 if (vershdr->sh_type == SHT_GNU_verdef)
2639 defscn = verscn;
2640 else if (vershdr->sh_type == SHT_GNU_verneed)
2641 needscn = verscn;
2642 }
2643 }
2644
Ulrich Drepperdbace232005-08-06 01:37:23 +00002645 size_t nvername;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002646 if (defscn != NULL || needscn != NULL)
2647 {
2648 /* We have a version information (better should have). Now get
2649 the version names. First find the maximum version number. */
2650 nvername = 0;
2651 if (defscn != NULL)
2652 {
2653 /* Run through the version definitions and find the highest
2654 index. */
2655 unsigned int offset = 0;
2656 Elf_Data *defdata;
2657 GElf_Shdr defshdrmem;
2658 GElf_Shdr *defshdr;
2659
2660 defdata = elf_getdata (defscn, NULL);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002661 if (unlikely (defdata == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002662 return;
2663
2664 defshdr = gelf_getshdr (defscn, &defshdrmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002665 if (unlikely (defshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002666 return;
2667
Ulrich Drepperdbace232005-08-06 01:37:23 +00002668 for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002669 {
2670 GElf_Verdef defmem;
2671 GElf_Verdef *def;
2672
2673 /* Get the data at the next offset. */
2674 def = gelf_getverdef (defdata, offset, &defmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002675 if (unlikely (def == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002676 break;
2677
2678 nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
2679
Mark Wielaard3b3a1912014-11-17 23:35:28 +01002680 if (def->vd_next == 0)
2681 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002682 offset += def->vd_next;
2683 }
2684 }
2685 if (needscn != NULL)
2686 {
2687 unsigned int offset = 0;
2688 Elf_Data *needdata;
2689 GElf_Shdr needshdrmem;
2690 GElf_Shdr *needshdr;
2691
2692 needdata = elf_getdata (needscn, NULL);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002693 if (unlikely (needdata == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002694 return;
2695
2696 needshdr = gelf_getshdr (needscn, &needshdrmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002697 if (unlikely (needshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002698 return;
2699
Ulrich Drepperdbace232005-08-06 01:37:23 +00002700 for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002701 {
2702 GElf_Verneed needmem;
2703 GElf_Verneed *need;
2704 unsigned int auxoffset;
2705 int cnt2;
2706
2707 /* Get the data at the next offset. */
2708 need = gelf_getverneed (needdata, offset, &needmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002709 if (unlikely (need == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002710 break;
2711
2712 /* Run through the auxiliary entries. */
2713 auxoffset = offset + need->vn_aux;
2714 for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
2715 {
2716 GElf_Vernaux auxmem;
2717 GElf_Vernaux *aux;
2718
2719 aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002720 if (unlikely (aux == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002721 break;
2722
2723 nvername = MAX (nvername,
2724 (size_t) (aux->vna_other & 0x7fff));
2725
Mark Wielaard3b3a1912014-11-17 23:35:28 +01002726 if (aux->vna_next == 0)
2727 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002728 auxoffset += aux->vna_next;
2729 }
2730
Mark Wielaard3b3a1912014-11-17 23:35:28 +01002731 if (need->vn_next == 0)
2732 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002733 offset += need->vn_next;
2734 }
2735 }
2736
2737 /* This is the number of versions we know about. */
2738 ++nvername;
2739
2740 /* Allocate the array. */
2741 vername = (const char **) alloca (nvername * sizeof (const char *));
Mark Wielaardd8b96822014-11-08 14:04:27 +01002742 memset(vername, 0, nvername * sizeof (const char *));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002743 filename = (const char **) alloca (nvername * sizeof (const char *));
Mark Wielaardd8b96822014-11-08 14:04:27 +01002744 memset(filename, 0, nvername * sizeof (const char *));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002745
2746 /* Run through the data structures again and collect the strings. */
2747 if (defscn != NULL)
2748 {
2749 /* Run through the version definitions and find the highest
2750 index. */
2751 unsigned int offset = 0;
2752 Elf_Data *defdata;
2753 GElf_Shdr defshdrmem;
2754 GElf_Shdr *defshdr;
2755
2756 defdata = elf_getdata (defscn, NULL);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002757 if (unlikely (defdata == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002758 return;
2759
2760 defshdr = gelf_getshdr (defscn, &defshdrmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002761 if (unlikely (defshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002762 return;
2763
Ulrich Drepperdbace232005-08-06 01:37:23 +00002764 for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002765 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002766
2767 /* Get the data at the next offset. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00002768 GElf_Verdef defmem;
2769 GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
Mark Wielaardad87d272014-11-14 12:24:28 +01002770 if (unlikely (def == NULL))
2771 break;
2772
Ulrich Drepperd0449522005-09-03 07:23:52 +00002773 GElf_Verdaux auxmem;
2774 GElf_Verdaux *aux = gelf_getverdaux (defdata,
2775 offset + def->vd_aux,
2776 &auxmem);
Mark Wielaardad87d272014-11-14 12:24:28 +01002777 if (unlikely (aux == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002778 break;
2779
2780 vername[def->vd_ndx & 0x7fff]
2781 = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
2782 filename[def->vd_ndx & 0x7fff] = NULL;
2783
Mark Wielaard3b3a1912014-11-17 23:35:28 +01002784 if (def->vd_next == 0)
2785 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002786 offset += def->vd_next;
2787 }
2788 }
2789 if (needscn != NULL)
2790 {
2791 unsigned int offset = 0;
Ulrich Drepperd0449522005-09-03 07:23:52 +00002792
2793 Elf_Data *needdata = elf_getdata (needscn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002794 GElf_Shdr needshdrmem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00002795 GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002796 if (unlikely (needdata == NULL || needshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002797 return;
2798
Ulrich Drepperdbace232005-08-06 01:37:23 +00002799 for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002800 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002801 /* Get the data at the next offset. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00002802 GElf_Verneed needmem;
2803 GElf_Verneed *need = gelf_getverneed (needdata, offset,
2804 &needmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002805 if (unlikely (need == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002806 break;
2807
2808 /* Run through the auxiliary entries. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00002809 unsigned int auxoffset = offset + need->vn_aux;
2810 for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002811 {
2812 GElf_Vernaux auxmem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00002813 GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
2814 &auxmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002815 if (unlikely (aux == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002816 break;
2817
2818 vername[aux->vna_other & 0x7fff]
2819 = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
2820 filename[aux->vna_other & 0x7fff]
2821 = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
2822
Mark Wielaard3b3a1912014-11-17 23:35:28 +01002823 if (aux->vna_next == 0)
2824 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002825 auxoffset += aux->vna_next;
2826 }
2827
Mark Wielaard3b3a1912014-11-17 23:35:28 +01002828 if (need->vn_next == 0)
2829 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002830 offset += need->vn_next;
2831 }
2832 }
2833 }
2834 else
2835 {
2836 vername = NULL;
2837 nvername = 1;
2838 filename = NULL;
2839 }
2840
Petr Machataced66872014-01-17 17:00:12 +01002841 GElf_Shdr glink_mem;
2842 GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2843 &glink_mem);
2844 size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_HALF, 1, EV_CURRENT);
2845 if (glink == NULL)
2846 error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"),
2847 elf_ndxscn (scn));
2848
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002849 /* Print the header. */
2850 printf (ngettext ("\
2851\nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
2852 "\
2853\nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
Petr Machataced66872014-01-17 17:00:12 +01002854 shdr->sh_size / sh_entsize),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002855 (unsigned int) elf_ndxscn (scn),
2856 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
Petr Machataced66872014-01-17 17:00:12 +01002857 (int) (shdr->sh_size / sh_entsize),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002858 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2859 shdr->sh_offset,
2860 (unsigned int) shdr->sh_link,
Roland McGrath7d5b3012014-01-17 17:11:39 +01002861 elf_strptr (ebl->elf, shstrndx, glink->sh_name));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002862
2863 /* Now we can finally look at the actual contents of this section. */
Petr Machataced66872014-01-17 17:00:12 +01002864 for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002865 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002866 if (cnt % 2 == 0)
2867 printf ("\n %4d:", cnt);
2868
Ulrich Drepperd0449522005-09-03 07:23:52 +00002869 GElf_Versym symmem;
2870 GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002871 if (sym == NULL)
2872 break;
2873
2874 switch (*sym)
2875 {
Ulrich Drepperd0449522005-09-03 07:23:52 +00002876 ssize_t n;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002877 case 0:
2878 fputs_unlocked (gettext (" 0 *local* "),
2879 stdout);
2880 break;
2881
2882 case 1:
2883 fputs_unlocked (gettext (" 1 *global* "),
2884 stdout);
2885 break;
2886
2887 default:
2888 n = printf ("%4d%c%s",
2889 *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
Mark Wielaard3b3a1912014-11-17 23:35:28 +01002890 (vername != NULL
2891 && (unsigned int) (*sym & 0x7fff) < nvername)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002892 ? vername[*sym & 0x7fff] : "???");
2893 if ((unsigned int) (*sym & 0x7fff) < nvername
Mark Wielaard3b3a1912014-11-17 23:35:28 +01002894 && filename != NULL && filename[*sym & 0x7fff] != NULL)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002895 n += printf ("(%s)", filename[*sym & 0x7fff]);
2896 printf ("%*s", MAX (0, 33 - (int) n), " ");
2897 break;
2898 }
2899 }
Ulrich Drepperd0449522005-09-03 07:23:52 +00002900 putchar_unlocked ('\n');
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002901}
2902
2903
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002904static void
2905print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
2906 uint_fast32_t maxlength, Elf32_Word nbucket,
Ulrich Drepper8ae58142006-07-12 05:22:32 +00002907 uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002908{
2909 uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
2910
2911 for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2912 ++counts[lengths[cnt]];
2913
Roland McGrath7d5b3012014-01-17 17:11:39 +01002914 GElf_Shdr glink_mem;
2915 GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf,
2916 shdr->sh_link),
2917 &glink_mem);
2918 if (glink == NULL)
2919 {
2920 error (0, 0, gettext ("invalid sh_link value in section %Zu"),
2921 elf_ndxscn (scn));
2922 return;
2923 }
2924
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002925 printf (ngettext ("\
2926\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",
2927 "\
2928\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",
2929 nbucket),
2930 (unsigned int) elf_ndxscn (scn),
2931 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2932 (int) nbucket,
2933 gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
2934 shdr->sh_addr,
2935 shdr->sh_offset,
2936 (unsigned int) shdr->sh_link,
Roland McGrath7d5b3012014-01-17 17:11:39 +01002937 elf_strptr (ebl->elf, shstrndx, glink->sh_name));
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002938
Ulrich Drepper8ae58142006-07-12 05:22:32 +00002939 if (extrastr != NULL)
2940 fputs (extrastr, stdout);
2941
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002942 if (likely (nbucket > 0))
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002943 {
2944 uint64_t success = 0;
2945
Roland McGrath3b495d82010-04-06 12:58:32 -07002946 /* xgettext:no-c-format */
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002947 fputs_unlocked (gettext ("\
2948 Length Number % of total Coverage\n"), stdout);
2949 printf (gettext (" 0 %6" PRIu32 " %5.1f%%\n"),
2950 counts[0], (counts[0] * 100.0) / nbucket);
2951
2952 uint64_t nzero_counts = 0;
2953 for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
2954 {
2955 nzero_counts += counts[cnt] * cnt;
2956 printf (gettext ("\
2957%7d %6" PRIu32 " %5.1f%% %5.1f%%\n"),
2958 (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
2959 (nzero_counts * 100.0) / nsyms);
2960 }
2961
2962 Elf32_Word acc = 0;
2963 for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
2964 {
2965 acc += cnt;
2966 success += counts[cnt] * acc;
2967 }
2968
2969 printf (gettext ("\
2970 Average number of tests: successful lookup: %f\n\
Ulrich Drepper173ade82010-05-28 07:39:49 -07002971 unsuccessful lookup: %f\n"),
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002972 (double) success / (double) nzero_counts,
2973 (double) nzero_counts / (double) nbucket);
2974 }
2975
2976 free (counts);
2977}
2978
2979
2980/* This function handles the traditional System V-style hash table format. */
2981static void
2982handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2983{
2984 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002985 if (unlikely (data == NULL))
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002986 {
2987 error (0, 0, gettext ("cannot get data for section %d: %s"),
2988 (int) elf_ndxscn (scn), elf_errmsg (-1));
2989 return;
2990 }
2991
Mark Wielaard6b246e02014-11-07 12:54:02 +01002992 if (unlikely (data->d_size < 2 * sizeof (Elf32_Word)))
2993 {
2994 invalid_data:
2995 error (0, 0, gettext ("invalid data in sysv.hash section %d"),
2996 (int) elf_ndxscn (scn));
2997 return;
2998 }
2999
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003000 Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
3001 Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
Mark Wielaard6b246e02014-11-07 12:54:02 +01003002
3003 uint64_t used_buf = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
3004 if (used_buf > data->d_size)
3005 goto invalid_data;
3006
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003007 Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
3008 Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
3009
3010 uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
3011
3012 uint_fast32_t maxlength = 0;
3013 uint_fast32_t nsyms = 0;
3014 for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
3015 {
3016 Elf32_Word inner = bucket[cnt];
3017 while (inner > 0 && inner < nchain)
3018 {
3019 ++nsyms;
3020 if (maxlength < ++lengths[cnt])
3021 ++maxlength;
3022
3023 inner = chain[inner];
3024 }
3025 }
3026
3027 print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
Ulrich Drepper8ae58142006-07-12 05:22:32 +00003028 lengths, NULL);
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003029
3030 free (lengths);
3031}
3032
3033
3034/* This function handles the incorrect, System V-style hash table
3035 format some 64-bit architectures use. */
3036static void
3037handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
3038{
3039 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003040 if (unlikely (data == NULL))
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003041 {
3042 error (0, 0, gettext ("cannot get data for section %d: %s"),
3043 (int) elf_ndxscn (scn), elf_errmsg (-1));
3044 return;
3045 }
3046
Mark Wielaard6b246e02014-11-07 12:54:02 +01003047 if (unlikely (data->d_size < 2 * sizeof (Elf64_Xword)))
3048 {
3049 invalid_data:
3050 error (0, 0, gettext ("invalid data in sysv.hash64 section %d"),
3051 (int) elf_ndxscn (scn));
3052 return;
3053 }
3054
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003055 Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
3056 Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
Mark Wielaard6b246e02014-11-07 12:54:02 +01003057
Mark Wielaard0ed4f982014-11-30 21:03:57 +01003058 uint64_t maxwords = data->d_size / sizeof (Elf64_Xword);
3059 if (maxwords < 2
3060 || maxwords - 2 < nbucket
3061 || maxwords - 2 - nbucket < nchain)
Mark Wielaard6b246e02014-11-07 12:54:02 +01003062 goto invalid_data;
3063
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003064 Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
3065 Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
3066
3067 uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
3068
3069 uint_fast32_t maxlength = 0;
3070 uint_fast32_t nsyms = 0;
3071 for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
3072 {
3073 Elf64_Xword inner = bucket[cnt];
3074 while (inner > 0 && inner < nchain)
3075 {
3076 ++nsyms;
3077 if (maxlength < ++lengths[cnt])
3078 ++maxlength;
3079
3080 inner = chain[inner];
3081 }
3082 }
3083
3084 print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
Ulrich Drepper8ae58142006-07-12 05:22:32 +00003085 lengths, NULL);
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003086
3087 free (lengths);
3088}
3089
3090
3091/* This function handles the GNU-style hash table format. */
3092static void
3093handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
3094{
Mark Wielaard90a7bd22015-06-18 10:57:53 +02003095 uint32_t *lengths = NULL;
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003096 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003097 if (unlikely (data == NULL))
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003098 {
3099 error (0, 0, gettext ("cannot get data for section %d: %s"),
3100 (int) elf_ndxscn (scn), elf_errmsg (-1));
3101 return;
3102 }
3103
Mark Wielaard6b246e02014-11-07 12:54:02 +01003104 if (unlikely (data->d_size < 4 * sizeof (Elf32_Word)))
3105 {
3106 invalid_data:
Mark Wielaard90a7bd22015-06-18 10:57:53 +02003107 free (lengths);
Mark Wielaard6b246e02014-11-07 12:54:02 +01003108 error (0, 0, gettext ("invalid data in gnu.hash section %d"),
3109 (int) elf_ndxscn (scn));
3110 return;
3111 }
3112
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003113 Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
3114 Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
Ulrich Drepper8ae58142006-07-12 05:22:32 +00003115
3116 /* Next comes the size of the bitmap. It's measured in words for
3117 the architecture. It's 32 bits for 32 bit archs, and 64 bits for
Mark Wielaard6b246e02014-11-07 12:54:02 +01003118 64 bit archs. There is always a bloom filter present, so zero is
3119 an invalid value. */
Ulrich Drepper8ae58142006-07-12 05:22:32 +00003120 Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
3121 if (gelf_getclass (ebl->elf) == ELFCLASS64)
3122 bitmask_words *= 2;
3123
Mark Wielaard6b246e02014-11-07 12:54:02 +01003124 if (bitmask_words == 0)
3125 goto invalid_data;
3126
Ulrich Drepper8ae58142006-07-12 05:22:32 +00003127 Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003128
Mark Wielaard6b246e02014-11-07 12:54:02 +01003129 /* Is there still room for the sym chain?
3130 Use uint64_t calculation to prevent 32bit overlow. */
3131 uint64_t used_buf = (4ULL + bitmask_words + nbucket) * sizeof (Elf32_Word);
3132 uint32_t max_nsyms = (data->d_size - used_buf) / sizeof (Elf32_Word);
3133 if (used_buf > data->d_size)
3134 goto invalid_data;
3135
Mark Wielaard90a7bd22015-06-18 10:57:53 +02003136 lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003137
Ulrich Drepper8ae58142006-07-12 05:22:32 +00003138 Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
3139 Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
3140 Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
3141 + nbucket];
3142
3143 /* Compute distribution of chain lengths. */
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003144 uint_fast32_t maxlength = 0;
3145 uint_fast32_t nsyms = 0;
3146 for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
Ulrich Drepper8ae58142006-07-12 05:22:32 +00003147 if (bucket[cnt] != 0)
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003148 {
Ulrich Drepper8ae58142006-07-12 05:22:32 +00003149 Elf32_Word inner = bucket[cnt] - symbias;
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003150 do
3151 {
3152 ++nsyms;
3153 if (maxlength < ++lengths[cnt])
3154 ++maxlength;
Mark Wielaard6b246e02014-11-07 12:54:02 +01003155 if (inner > max_nsyms)
3156 goto invalid_data;
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003157 }
3158 while ((chain[inner++] & 1) == 0);
3159 }
3160
Ulrich Drepper8ae58142006-07-12 05:22:32 +00003161 /* Count bits in bitmask. */
3162 uint_fast32_t nbits = 0;
3163 for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
3164 {
3165 uint_fast32_t word = bitmask[cnt];
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003166
Ulrich Drepper8ae58142006-07-12 05:22:32 +00003167 word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
3168 word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
3169 word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
3170 word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
3171 nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
3172 }
3173
3174 char *str;
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003175 if (unlikely (asprintf (&str, gettext ("\
Ulrich Drepper8ae58142006-07-12 05:22:32 +00003176 Symbol Bias: %u\n\
3177 Bitmask Size: %zu bytes %" PRIuFAST32 "%% bits set 2nd hash shift: %u\n"),
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003178 (unsigned int) symbias,
3179 bitmask_words * sizeof (Elf32_Word),
3180 ((nbits * 100 + 50)
3181 / (uint_fast32_t) (bitmask_words
3182 * sizeof (Elf32_Word) * 8)),
3183 (unsigned int) shift) == -1))
Ulrich Drepper8ae58142006-07-12 05:22:32 +00003184 error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
3185
3186 print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
3187 lengths, str);
3188
3189 free (str);
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003190 free (lengths);
3191}
3192
3193
Ulrich Drepperd0449522005-09-03 07:23:52 +00003194/* Find the symbol table(s). For this we have to search through the
3195 section table. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003196static void
3197handle_hash (Ebl *ebl)
3198{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003199 /* Get the section header string table index. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00003200 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07003201 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003202 error (EXIT_FAILURE, 0,
3203 gettext ("cannot get section header string table index"));
3204
Ulrich Drepperd0449522005-09-03 07:23:52 +00003205 Elf_Scn *scn = NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003206 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3207 {
3208 /* Handle the section if it is a symbol table. */
3209 GElf_Shdr shdr_mem;
3210 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3211
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003212 if (likely (shdr != NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003213 {
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003214 if (shdr->sh_type == SHT_HASH)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003215 {
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003216 if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
3217 handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
3218 else
3219 handle_sysv_hash (ebl, scn, shdr, shstrndx);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003220 }
Ulrich Drepper28ed8952006-07-07 03:43:47 +00003221 else if (shdr->sh_type == SHT_GNU_HASH)
3222 handle_gnu_hash (ebl, scn, shdr, shstrndx);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003223 }
3224 }
3225}
3226
3227
3228static void
3229print_liblist (Ebl *ebl)
3230{
3231 /* Find the library list sections. For this we have to search
3232 through the section table. */
3233 Elf_Scn *scn = NULL;
3234
3235 /* Get the section header string table index. */
3236 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07003237 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003238 error (EXIT_FAILURE, 0,
3239 gettext ("cannot get section header string table index"));
3240
3241 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3242 {
3243 GElf_Shdr shdr_mem;
3244 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3245
3246 if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
3247 {
Petr Machataced66872014-01-17 17:00:12 +01003248 size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_LIB, 1, EV_CURRENT);
3249 int nentries = shdr->sh_size / sh_entsize;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003250 printf (ngettext ("\
3251\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
3252 "\
3253\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
3254 nentries),
3255 elf_ndxscn (scn),
3256 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3257 shdr->sh_offset,
3258 nentries);
3259
3260 Elf_Data *data = elf_getdata (scn, NULL);
3261 if (data == NULL)
3262 return;
3263
3264 puts (gettext ("\
3265 Library Time Stamp Checksum Version Flags"));
3266
3267 for (int cnt = 0; cnt < nentries; ++cnt)
3268 {
3269 GElf_Lib lib_mem;
3270 GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003271 if (unlikely (lib == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003272 continue;
3273
3274 time_t t = (time_t) lib->l_time_stamp;
3275 struct tm *tm = gmtime (&t);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003276 if (unlikely (tm == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003277 continue;
3278
3279 printf (" [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
3280 cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
3281 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
3282 tm->tm_hour, tm->tm_min, tm->tm_sec,
3283 (unsigned int) lib->l_checksum,
3284 (unsigned int) lib->l_version,
3285 (unsigned int) lib->l_flags);
3286 }
3287 }
3288 }
3289}
3290
Roland McGrath059c83e2008-02-21 06:19:39 +00003291static void
3292print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
3293{
3294 /* Find the object attributes sections. For this we have to search
3295 through the section table. */
3296 Elf_Scn *scn = NULL;
3297
3298 /* Get the section header string table index. */
3299 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07003300 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Roland McGrath059c83e2008-02-21 06:19:39 +00003301 error (EXIT_FAILURE, 0,
3302 gettext ("cannot get section header string table index"));
3303
3304 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3305 {
3306 GElf_Shdr shdr_mem;
3307 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3308
Roland McGratheb9ba472009-04-14 18:44:45 -07003309 if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
3310 && (shdr->sh_type != SHT_ARM_ATTRIBUTES
3311 || ehdr->e_machine != EM_ARM)))
Roland McGrath059c83e2008-02-21 06:19:39 +00003312 continue;
3313
3314 printf (gettext ("\
3315\nObject attributes section [%2zu] '%s' of %" PRIu64
3316 " bytes at offset %#0" PRIx64 ":\n"),
3317 elf_ndxscn (scn),
3318 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3319 shdr->sh_size, shdr->sh_offset);
3320
3321 Elf_Data *data = elf_rawdata (scn, NULL);
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003322 if (unlikely (data == NULL || data->d_size == 0))
Roland McGrath059c83e2008-02-21 06:19:39 +00003323 return;
3324
3325 const unsigned char *p = data->d_buf;
3326
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003327 /* There is only one 'version', A. */
Roland McGrath059c83e2008-02-21 06:19:39 +00003328 if (unlikely (*p++ != 'A'))
3329 return;
3330
3331 fputs_unlocked (gettext (" Owner Size\n"), stdout);
3332
3333 inline size_t left (void)
3334 {
3335 return (const unsigned char *) data->d_buf + data->d_size - p;
3336 }
3337
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003338 /* Loop over the sections. */
Roland McGrath059c83e2008-02-21 06:19:39 +00003339 while (left () >= 4)
3340 {
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003341 /* Section length. */
Roland McGrath059c83e2008-02-21 06:19:39 +00003342 uint32_t len;
3343 memcpy (&len, p, sizeof len);
3344
3345 if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3346 CONVERT (len);
3347
3348 if (unlikely (len > left ()))
3349 break;
3350
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003351 /* Section vendor name. */
Roland McGrath059c83e2008-02-21 06:19:39 +00003352 const unsigned char *name = p + sizeof len;
3353 p += len;
3354
3355 unsigned const char *q = memchr (name, '\0', len);
3356 if (unlikely (q == NULL))
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003357 break;
Roland McGrath059c83e2008-02-21 06:19:39 +00003358 ++q;
3359
3360 printf (gettext (" %-13s %4" PRIu32 "\n"), name, len);
3361
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003362 bool gnu_vendor = (q - name == sizeof "gnu"
3363 && !memcmp (name, "gnu", sizeof "gnu"));
3364
3365 /* Loop over subsections. */
Roland McGratheb9ba472009-04-14 18:44:45 -07003366 if (shdr->sh_type != SHT_GNU_ATTRIBUTES
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003367 || gnu_vendor)
Roland McGrath059c83e2008-02-21 06:19:39 +00003368 while (q < p)
3369 {
3370 const unsigned char *const sub = q;
3371
3372 unsigned int subsection_tag;
Mark Wielaard7a053472014-12-14 21:48:23 +01003373 get_uleb128 (subsection_tag, q, p);
Roland McGrath059c83e2008-02-21 06:19:39 +00003374 if (unlikely (q >= p))
3375 break;
3376
3377 uint32_t subsection_len;
3378 if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
3379 break;
3380
3381 memcpy (&subsection_len, q, sizeof subsection_len);
3382
3383 if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3384 CONVERT (subsection_len);
3385
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003386 /* Don't overflow, ptrdiff_t might be 32bits, but signed. */
3387 if (unlikely (subsection_len == 0
3388 || subsection_len >= (uint32_t) PTRDIFF_MAX
3389 || p - sub < (ptrdiff_t) subsection_len))
Roland McGrath059c83e2008-02-21 06:19:39 +00003390 break;
3391
3392 const unsigned char *r = q + sizeof subsection_len;
3393 q = sub + subsection_len;
3394
3395 switch (subsection_tag)
3396 {
3397 default:
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003398 /* Unknown subsection, print and skip. */
Roland McGrath059c83e2008-02-21 06:19:39 +00003399 printf (gettext (" %-4u %12" PRIu32 "\n"),
3400 subsection_tag, subsection_len);
3401 break;
3402
3403 case 1: /* Tag_File */
3404 printf (gettext (" File: %11" PRIu32 "\n"),
3405 subsection_len);
3406
3407 while (r < q)
3408 {
3409 unsigned int tag;
Mark Wielaard7a053472014-12-14 21:48:23 +01003410 get_uleb128 (tag, r, q);
Roland McGrath059c83e2008-02-21 06:19:39 +00003411 if (unlikely (r >= q))
3412 break;
3413
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003414 /* GNU style tags have either a uleb128 value,
3415 when lowest bit is not set, or a string
3416 when the lowest bit is set.
3417 "compatibility" (32) is special. It has
3418 both a string and a uleb128 value. For
3419 non-gnu we assume 6 till 31 only take ints.
3420 XXX see arm backend, do we need a separate
3421 hook? */
Roland McGrath059c83e2008-02-21 06:19:39 +00003422 uint64_t value = 0;
3423 const char *string = NULL;
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003424 if (tag == 32 || (tag & 1) == 0
3425 || (! gnu_vendor && (tag > 5 && tag < 32)))
Roland McGrath059c83e2008-02-21 06:19:39 +00003426 {
Mark Wielaard7a053472014-12-14 21:48:23 +01003427 get_uleb128 (value, r, q);
Roland McGrath059c83e2008-02-21 06:19:39 +00003428 if (r > q)
3429 break;
3430 }
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003431 if (tag == 32
3432 || ((tag & 1) != 0
3433 && (gnu_vendor
3434 || (! gnu_vendor && tag > 32)))
3435 || (! gnu_vendor && tag > 3 && tag < 6))
Roland McGrath059c83e2008-02-21 06:19:39 +00003436 {
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003437 string = (const char *) r;
Roland McGrath059c83e2008-02-21 06:19:39 +00003438 r = memchr (r, '\0', q - r);
3439 if (r == NULL)
3440 break;
3441 ++r;
3442 }
3443
3444 const char *tag_name = NULL;
3445 const char *value_name = NULL;
3446 ebl_check_object_attribute (ebl, (const char *) name,
3447 tag, value,
3448 &tag_name, &value_name);
3449
3450 if (tag_name != NULL)
3451 {
3452 if (tag == 32)
3453 printf (gettext (" %s: %" PRId64 ", %s\n"),
3454 tag_name, value, string);
3455 else if (string == NULL && value_name == NULL)
3456 printf (gettext (" %s: %" PRId64 "\n"),
3457 tag_name, value);
3458 else
3459 printf (gettext (" %s: %s\n"),
3460 tag_name, string ?: value_name);
3461 }
3462 else
3463 {
Mark Wielaard9644aaf2014-11-21 23:26:35 +01003464 /* For "gnu" vendor 32 "compatibility" has
3465 already been handled above. */
3466 assert (tag != 32
3467 || strcmp ((const char *) name, "gnu"));
Roland McGrath059c83e2008-02-21 06:19:39 +00003468 if (string == NULL)
3469 printf (gettext (" %u: %" PRId64 "\n"),
3470 tag, value);
3471 else
3472 printf (gettext (" %u: %s\n"),
3473 tag, string);
3474 }
3475 }
3476 }
3477 }
3478 }
3479 }
3480}
3481
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003482
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003483static char *
3484format_dwarf_addr (Dwfl_Module *dwflmod,
Mark Wielaard10186a12013-01-24 11:29:21 +01003485 int address_size, Dwarf_Addr address, Dwarf_Addr raw)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003486{
3487 /* See if there is a name we can give for this address. */
3488 GElf_Sym sym;
Mark Wielaard159ac522013-12-18 11:05:54 +01003489 GElf_Off off = 0;
Mark Wielaard10186a12013-01-24 11:29:21 +01003490 const char *name = (print_address_names && ! print_unresolved_addresses)
Mark Wielaard159ac522013-12-18 11:05:54 +01003491 ? dwfl_module_addrinfo (dwflmod, address, &off, &sym, NULL, NULL, NULL)
3492 : NULL;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003493
Mark Wielaard10186a12013-01-24 11:29:21 +01003494 const char *scn;
3495 if (print_unresolved_addresses)
3496 {
3497 address = raw;
3498 scn = NULL;
3499 }
3500 else
3501 {
3502 /* Relativize the address. */
3503 int n = dwfl_module_relocations (dwflmod);
3504 int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003505
Mark Wielaard10186a12013-01-24 11:29:21 +01003506 /* In an ET_REL file there is a section name to refer to. */
3507 scn = (i < 0 ? NULL
3508 : dwfl_module_relocation_info (dwflmod, i, NULL));
3509 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003510
3511 char *result;
3512 if ((name != NULL
Mark Wielaard159ac522013-12-18 11:05:54 +01003513 ? (off != 0
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003514 ? (scn != NULL
3515 ? (address_size == 0
3516 ? asprintf (&result,
3517 gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
Mark Wielaard159ac522013-12-18 11:05:54 +01003518 scn, address, name, off)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003519 : asprintf (&result,
3520 gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
3521 scn, 2 + address_size * 2, address,
Mark Wielaard159ac522013-12-18 11:05:54 +01003522 name, off))
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003523 : (address_size == 0
3524 ? asprintf (&result,
3525 gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
Mark Wielaard159ac522013-12-18 11:05:54 +01003526 address, name, off)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003527 : asprintf (&result,
3528 gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
3529 2 + address_size * 2, address,
Mark Wielaard159ac522013-12-18 11:05:54 +01003530 name, off)))
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003531 : (scn != NULL
3532 ? (address_size == 0
3533 ? asprintf (&result,
3534 gettext ("%s+%#" PRIx64 " <%s>"),
3535 scn, address, name)
3536 : asprintf (&result,
3537 gettext ("%s+%#0*" PRIx64 " <%s>"),
3538 scn, 2 + address_size * 2, address, name))
3539 : (address_size == 0
3540 ? asprintf (&result,
3541 gettext ("%#" PRIx64 " <%s>"),
3542 address, name)
3543 : asprintf (&result,
3544 gettext ("%#0*" PRIx64 " <%s>"),
3545 2 + address_size * 2, address, name))))
3546 : (scn != NULL
3547 ? (address_size == 0
3548 ? asprintf (&result,
3549 gettext ("%s+%#" PRIx64),
3550 scn, address)
3551 : asprintf (&result,
3552 gettext ("%s+%#0*" PRIx64),
3553 scn, 2 + address_size * 2, address))
3554 : (address_size == 0
3555 ? asprintf (&result,
3556 "%#" PRIx64,
3557 address)
3558 : asprintf (&result,
3559 "%#0*" PRIx64,
3560 2 + address_size * 2, address)))) < 0)
3561 error (EXIT_FAILURE, 0, _("memory exhausted"));
3562
3563 return result;
3564}
3565
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003566static const char *
3567dwarf_tag_string (unsigned int tag)
3568{
Mark Wielaardf31c4412012-08-17 00:35:03 +02003569 switch (tag)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003570 {
Petr Machata7f617342015-03-18 19:42:02 +01003571#define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
3572 DWARF_ALL_KNOWN_DW_TAG
3573#undef DWARF_ONE_KNOWN_DW_TAG
Mark Wielaardf31c4412012-08-17 00:35:03 +02003574 default:
3575 return NULL;
3576 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003577}
3578
3579
3580static const char *
3581dwarf_attr_string (unsigned int attrnum)
3582{
Mark Wielaardf31c4412012-08-17 00:35:03 +02003583 switch (attrnum)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003584 {
Petr Machata7f617342015-03-18 19:42:02 +01003585#define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
3586 DWARF_ALL_KNOWN_DW_AT
3587#undef DWARF_ONE_KNOWN_DW_AT
Mark Wielaardf31c4412012-08-17 00:35:03 +02003588 default:
3589 return NULL;
3590 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003591}
3592
3593
3594static const char *
3595dwarf_form_string (unsigned int form)
3596{
Mark Wielaardf31c4412012-08-17 00:35:03 +02003597 switch (form)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003598 {
Petr Machata7f617342015-03-18 19:42:02 +01003599#define DWARF_ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
3600 DWARF_ALL_KNOWN_DW_FORM
3601#undef DWARF_ONE_KNOWN_DW_FORM
Mark Wielaardf31c4412012-08-17 00:35:03 +02003602 default:
3603 return NULL;
Mark Wielaard775375e2012-06-22 12:02:45 +02003604 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003605}
3606
3607
3608static const char *
3609dwarf_lang_string (unsigned int lang)
3610{
Mark Wielaardf31c4412012-08-17 00:35:03 +02003611 switch (lang)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003612 {
Petr Machata7f617342015-03-18 19:42:02 +01003613#define DWARF_ONE_KNOWN_DW_LANG(NAME, CODE) case CODE: return #NAME;
3614 DWARF_ALL_KNOWN_DW_LANG
3615#undef DWARF_ONE_KNOWN_DW_LANG
Mark Wielaardf31c4412012-08-17 00:35:03 +02003616 default:
3617 return NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003618 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003619}
3620
3621
3622static const char *
3623dwarf_inline_string (unsigned int code)
3624{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003625 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003626 {
Petr Machata7f617342015-03-18 19:42:02 +01003627#define DWARF_ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME,
3628 DWARF_ALL_KNOWN_DW_INL
3629#undef DWARF_ONE_KNOWN_DW_INL
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003630 };
3631
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003632 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003633 return known[code];
3634
Mark Wielaardf31c4412012-08-17 00:35:03 +02003635 return NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003636}
3637
3638
3639static const char *
3640dwarf_encoding_string (unsigned int code)
3641{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003642 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003643 {
Petr Machata7f617342015-03-18 19:42:02 +01003644#define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
3645 DWARF_ALL_KNOWN_DW_ATE
3646#undef DWARF_ONE_KNOWN_DW_ATE
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003647 };
3648
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003649 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003650 return known[code];
3651
Mark Wielaardf31c4412012-08-17 00:35:03 +02003652 return NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003653}
3654
3655
3656static const char *
3657dwarf_access_string (unsigned int code)
3658{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003659 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003660 {
Petr Machata7f617342015-03-18 19:42:02 +01003661#define DWARF_ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME,
3662 DWARF_ALL_KNOWN_DW_ACCESS
3663#undef DWARF_ONE_KNOWN_DW_ACCESS
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003664 };
3665
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003666 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003667 return known[code];
3668
Mark Wielaardf31c4412012-08-17 00:35:03 +02003669 return NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003670}
3671
3672
3673static const char *
3674dwarf_visibility_string (unsigned int code)
3675{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003676 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003677 {
Petr Machata7f617342015-03-18 19:42:02 +01003678#define DWARF_ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
3679 DWARF_ALL_KNOWN_DW_VIS
3680#undef DWARF_ONE_KNOWN_DW_VIS
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003681 };
3682
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003683 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003684 return known[code];
3685
Mark Wielaardf31c4412012-08-17 00:35:03 +02003686 return NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003687}
3688
3689
3690static const char *
3691dwarf_virtuality_string (unsigned int code)
3692{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003693 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003694 {
Petr Machata7f617342015-03-18 19:42:02 +01003695#define DWARF_ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
3696 DWARF_ALL_KNOWN_DW_VIRTUALITY
3697#undef DWARF_ONE_KNOWN_DW_VIRTUALITY
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003698 };
3699
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003700 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003701 return known[code];
3702
Mark Wielaardf31c4412012-08-17 00:35:03 +02003703 return NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003704}
3705
3706
3707static const char *
3708dwarf_identifier_case_string (unsigned int code)
3709{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003710 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003711 {
Petr Machata7f617342015-03-18 19:42:02 +01003712#define DWARF_ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
3713 DWARF_ALL_KNOWN_DW_ID
3714#undef DWARF_ONE_KNOWN_DW_ID
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003715 };
3716
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003717 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003718 return known[code];
3719
Mark Wielaardf31c4412012-08-17 00:35:03 +02003720 return NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003721}
3722
3723
3724static const char *
3725dwarf_calling_convention_string (unsigned int code)
3726{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003727 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003728 {
Petr Machata7f617342015-03-18 19:42:02 +01003729#define DWARF_ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
3730 DWARF_ALL_KNOWN_DW_CC
3731#undef DWARF_ONE_KNOWN_DW_CC
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003732 };
3733
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003734 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003735 return known[code];
3736
Mark Wielaardf31c4412012-08-17 00:35:03 +02003737 return NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003738}
3739
3740
3741static const char *
3742dwarf_ordering_string (unsigned int code)
3743{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003744 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003745 {
Petr Machata7f617342015-03-18 19:42:02 +01003746#define DWARF_ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
3747 DWARF_ALL_KNOWN_DW_ORD
3748#undef DWARF_ONE_KNOWN_DW_ORD
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003749 };
3750
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003751 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003752 return known[code];
3753
Mark Wielaardf31c4412012-08-17 00:35:03 +02003754 return NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003755}
3756
3757
3758static const char *
3759dwarf_discr_list_string (unsigned int code)
3760{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003761 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003762 {
Petr Machata7f617342015-03-18 19:42:02 +01003763#define DWARF_ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
3764 DWARF_ALL_KNOWN_DW_DSC
3765#undef DWARF_ONE_KNOWN_DW_DSC
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003766 };
3767
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003768 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003769 return known[code];
3770
Mark Wielaardf31c4412012-08-17 00:35:03 +02003771 return NULL;
3772}
3773
3774
3775static const char *
3776dwarf_locexpr_opcode_string (unsigned int code)
3777{
3778 static const char *const known[] =
3779 {
3780 /* Normally we can't affort building huge table of 64K entries,
3781 most of them zero, just because there are a couple defined
3782 values at the far end. In case of opcodes, it's OK. */
Petr Machata7f617342015-03-18 19:42:02 +01003783#define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
3784 DWARF_ALL_KNOWN_DW_OP
3785#undef DWARF_ONE_KNOWN_DW_OP
Mark Wielaardf31c4412012-08-17 00:35:03 +02003786 };
3787
3788 if (likely (code < sizeof (known) / sizeof (known[0])))
3789 return known[code];
3790
3791 return NULL;
3792}
3793
3794
3795/* Used by all dwarf_foo_name functions. */
3796static const char *
3797string_or_unknown (const char *known, unsigned int code,
3798 unsigned int lo_user, unsigned int hi_user,
3799 bool print_unknown_num)
3800{
3801 static char unknown_buf[20];
3802
3803 if (likely (known != NULL))
3804 return known;
3805
3806 if (lo_user != 0 && code >= lo_user && code <= hi_user)
3807 {
3808 snprintf (unknown_buf, sizeof unknown_buf, "lo_user+%#x",
3809 code - lo_user);
3810 return unknown_buf;
3811 }
3812
3813 if (print_unknown_num)
3814 {
3815 snprintf (unknown_buf, sizeof unknown_buf, "??? (%#x)", code);
3816 return unknown_buf;
3817 }
3818
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003819 return "???";
3820}
3821
3822
Mark Wielaardf31c4412012-08-17 00:35:03 +02003823static const char *
3824dwarf_tag_name (unsigned int tag)
3825{
3826 const char *ret = dwarf_tag_string (tag);
3827 return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true);
3828}
3829
3830static const char *
3831dwarf_attr_name (unsigned int attr)
3832{
3833 const char *ret = dwarf_attr_string (attr);
3834 return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true);
3835}
3836
3837
3838static const char *
3839dwarf_form_name (unsigned int form)
3840{
3841 const char *ret = dwarf_form_string (form);
3842 return string_or_unknown (ret, form, 0, 0, true);
3843}
3844
3845
3846static const char *
3847dwarf_lang_name (unsigned int lang)
3848{
3849 const char *ret = dwarf_lang_string (lang);
3850 return string_or_unknown (ret, lang, DW_LANG_lo_user, DW_LANG_hi_user, false);
3851}
3852
3853
3854static const char *
3855dwarf_inline_name (unsigned int code)
3856{
3857 const char *ret = dwarf_inline_string (code);
3858 return string_or_unknown (ret, code, 0, 0, false);
3859}
3860
3861
3862static const char *
3863dwarf_encoding_name (unsigned int code)
3864{
3865 const char *ret = dwarf_encoding_string (code);
3866 return string_or_unknown (ret, code, DW_ATE_lo_user, DW_ATE_hi_user, false);
3867}
3868
3869
3870static const char *
3871dwarf_access_name (unsigned int code)
3872{
3873 const char *ret = dwarf_access_string (code);
3874 return string_or_unknown (ret, code, 0, 0, false);
3875}
3876
3877
3878static const char *
3879dwarf_visibility_name (unsigned int code)
3880{
3881 const char *ret = dwarf_visibility_string (code);
3882 return string_or_unknown (ret, code, 0, 0, false);
3883}
3884
3885
3886static const char *
3887dwarf_virtuality_name (unsigned int code)
3888{
3889 const char *ret = dwarf_virtuality_string (code);
3890 return string_or_unknown (ret, code, 0, 0, false);
3891}
3892
3893
3894static const char *
3895dwarf_identifier_case_name (unsigned int code)
3896{
3897 const char *ret = dwarf_identifier_case_string (code);
3898 return string_or_unknown (ret, code, 0, 0, false);
3899}
3900
3901
3902static const char *
3903dwarf_calling_convention_name (unsigned int code)
3904{
3905 const char *ret = dwarf_calling_convention_string (code);
3906 return string_or_unknown (ret, code, DW_CC_lo_user, DW_CC_hi_user, false);
3907}
3908
3909
3910static const char *
3911dwarf_ordering_name (unsigned int code)
3912{
3913 const char *ret = dwarf_ordering_string (code);
3914 return string_or_unknown (ret, code, 0, 0, false);
3915}
3916
3917
3918static const char *
3919dwarf_discr_list_name (unsigned int code)
3920{
3921 const char *ret = dwarf_discr_list_string (code);
3922 return string_or_unknown (ret, code, 0, 0, false);
3923}
3924
3925
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003926static void
Roland McGrathbe4589d2009-07-24 16:23:12 -07003927print_block (size_t n, const void *block)
3928{
3929 if (n == 0)
3930 puts (_("empty block"));
3931 else
3932 {
3933 printf (_("%zu byte block:"), n);
3934 const unsigned char *data = block;
3935 do
3936 printf (" %02x", *data++);
3937 while (--n > 0);
3938 putchar ('\n');
3939 }
3940}
3941
3942static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003943print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
Roland McGrath52604ba2010-07-26 21:29:44 -07003944 unsigned int vers, unsigned int addrsize, unsigned int offset_size,
Mark Wielaard35230222013-07-05 16:44:47 +02003945 struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003946{
Roland McGrath52604ba2010-07-26 21:29:44 -07003947 const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
3948
Roland McGrath51f01282009-01-27 17:08:03 -08003949 if (len == 0)
3950 {
3951 printf ("%*s(empty)\n", indent, "");
3952 return;
3953 }
3954
Roland McGratha1599152010-08-30 04:04:37 -07003955#define NEED(n) if (len < (Dwarf_Word) (n)) goto invalid
3956#define CONSUME(n) NEED (n); else len -= (n)
Roland McGrath51f01282009-01-27 17:08:03 -08003957
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003958 Dwarf_Word offset = 0;
3959 while (len-- > 0)
3960 {
Roland McGrath1a2e8f42007-12-15 23:39:34 +00003961 uint_fast8_t op = *data++;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003962
Mark Wielaardf31c4412012-08-17 00:35:03 +02003963 const char *op_name = dwarf_locexpr_opcode_string (op);
3964 if (unlikely (op_name == NULL))
3965 {
3966 static char buf[20];
3967 if (op >= DW_OP_lo_user)
3968 snprintf (buf, sizeof buf, "lo_user+%#x", op - DW_OP_lo_user);
3969 else
3970 snprintf (buf, sizeof buf, "??? (%#x)", op);
3971 op_name = buf;
3972 }
3973
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003974 switch (op)
3975 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003976 case DW_OP_addr:;
3977 /* Address operand. */
3978 Dwarf_Word addr;
Roland McGrath51f01282009-01-27 17:08:03 -08003979 NEED (addrsize);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003980 if (addrsize == 4)
3981 addr = read_4ubyte_unaligned (dbg, data);
Mark Wielaard198e9492014-12-15 19:05:43 +01003982 else if (addrsize == 8)
3983 addr = read_8ubyte_unaligned (dbg, data);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003984 else
Mark Wielaard198e9492014-12-15 19:05:43 +01003985 goto invalid;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003986 data += addrsize;
Roland McGratha1599152010-08-30 04:04:37 -07003987 CONSUME (addrsize);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003988
Mark Wielaard10186a12013-01-24 11:29:21 +01003989 char *a = format_dwarf_addr (dwflmod, 0, addr, addr);
Roland McGrath688f7fc2010-05-08 03:22:59 -07003990 printf ("%*s[%4" PRIuMAX "] %s %s\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02003991 indent, "", (uintmax_t) offset, op_name, a);
Roland McGrath688f7fc2010-05-08 03:22:59 -07003992 free (a);
3993
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003994 offset += 1 + addrsize;
3995 break;
3996
Roland McGrath688f7fc2010-05-08 03:22:59 -07003997 case DW_OP_call_ref:
3998 /* Offset operand. */
Mark Wielaard198e9492014-12-15 19:05:43 +01003999 if (ref_size != 4 && ref_size != 8)
Mark Wielaard96ddcad2014-12-07 22:45:28 +01004000 goto invalid; /* Cannot be used in CFA. */
Roland McGrath52604ba2010-07-26 21:29:44 -07004001 NEED (ref_size);
4002 if (ref_size == 4)
Roland McGrath688f7fc2010-05-08 03:22:59 -07004003 addr = read_4ubyte_unaligned (dbg, data);
4004 else
Mark Wielaard198e9492014-12-15 19:05:43 +01004005 addr = read_8ubyte_unaligned (dbg, data);
Roland McGrath52604ba2010-07-26 21:29:44 -07004006 data += ref_size;
Roland McGratha1599152010-08-30 04:04:37 -07004007 CONSUME (ref_size);
Roland McGrath688f7fc2010-05-08 03:22:59 -07004008
4009 printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
4010 indent, "", (uintmax_t) offset,
Mark Wielaardf31c4412012-08-17 00:35:03 +02004011 op_name, (uintmax_t) addr);
Roland McGrath52604ba2010-07-26 21:29:44 -07004012 offset += 1 + ref_size;
Roland McGrath688f7fc2010-05-08 03:22:59 -07004013 break;
4014
Roland McGrath060fa052006-03-02 07:51:50 +00004015 case DW_OP_deref_size:
4016 case DW_OP_xderef_size:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004017 case DW_OP_pick:
4018 case DW_OP_const1u:
Ulrich Drepperac194d02009-01-06 00:30:01 -08004019 // XXX value might be modified by relocation
Roland McGrath51f01282009-01-27 17:08:03 -08004020 NEED (1);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004021 printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
4022 indent, "", (uintmax_t) offset,
Mark Wielaardf31c4412012-08-17 00:35:03 +02004023 op_name, *((uint8_t *) data));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004024 ++data;
4025 --len;
4026 offset += 2;
4027 break;
4028
4029 case DW_OP_const2u:
Roland McGrath51f01282009-01-27 17:08:03 -08004030 NEED (2);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004031 // XXX value might be modified by relocation
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004032 printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
4033 indent, "", (uintmax_t) offset,
Mark Wielaardf31c4412012-08-17 00:35:03 +02004034 op_name, read_2ubyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004035 CONSUME (2);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004036 data += 2;
4037 offset += 3;
4038 break;
4039
4040 case DW_OP_const4u:
Roland McGrath51f01282009-01-27 17:08:03 -08004041 NEED (4);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004042 // XXX value might be modified by relocation
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004043 printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
4044 indent, "", (uintmax_t) offset,
Mark Wielaardf31c4412012-08-17 00:35:03 +02004045 op_name, read_4ubyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004046 CONSUME (4);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004047 data += 4;
4048 offset += 5;
4049 break;
4050
4051 case DW_OP_const8u:
Roland McGrath51f01282009-01-27 17:08:03 -08004052 NEED (8);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004053 // XXX value might be modified by relocation
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004054 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
4055 indent, "", (uintmax_t) offset,
Mark Wielaardf31c4412012-08-17 00:35:03 +02004056 op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004057 CONSUME (8);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004058 data += 8;
4059 offset += 9;
4060 break;
4061
4062 case DW_OP_const1s:
Roland McGrath51f01282009-01-27 17:08:03 -08004063 NEED (1);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004064 // XXX value might be modified by relocation
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004065 printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
4066 indent, "", (uintmax_t) offset,
Mark Wielaardf31c4412012-08-17 00:35:03 +02004067 op_name, *((int8_t *) data));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004068 ++data;
4069 --len;
4070 offset += 2;
4071 break;
4072
4073 case DW_OP_const2s:
Roland McGrath51f01282009-01-27 17:08:03 -08004074 NEED (2);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004075 // XXX value might be modified by relocation
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004076 printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
4077 indent, "", (uintmax_t) offset,
Mark Wielaardf31c4412012-08-17 00:35:03 +02004078 op_name, read_2sbyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004079 CONSUME (2);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004080 data += 2;
4081 offset += 3;
4082 break;
4083
4084 case DW_OP_const4s:
Roland McGrath51f01282009-01-27 17:08:03 -08004085 NEED (4);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004086 // XXX value might be modified by relocation
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004087 printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
4088 indent, "", (uintmax_t) offset,
Mark Wielaardf31c4412012-08-17 00:35:03 +02004089 op_name, read_4sbyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004090 CONSUME (4);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004091 data += 4;
4092 offset += 5;
4093 break;
4094
4095 case DW_OP_const8s:
Roland McGrath51f01282009-01-27 17:08:03 -08004096 NEED (8);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004097 // XXX value might be modified by relocation
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004098 printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
4099 indent, "", (uintmax_t) offset,
Mark Wielaardf31c4412012-08-17 00:35:03 +02004100 op_name, read_8sbyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004101 CONSUME (8);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004102 data += 8;
4103 offset += 9;
4104 break;
4105
Roland McGrath060fa052006-03-02 07:51:50 +00004106 case DW_OP_piece:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004107 case DW_OP_regx:
4108 case DW_OP_plus_uconst:
4109 case DW_OP_constu:;
4110 const unsigned char *start = data;
Roland McGrath0c5638c2010-06-21 23:00:35 -07004111 uint64_t uleb;
Roland McGratha1599152010-08-30 04:04:37 -07004112 NEED (1);
Mark Wielaard7a053472014-12-14 21:48:23 +01004113 get_uleb128 (uleb, data, data + len);
Roland McGrath0c5638c2010-06-21 23:00:35 -07004114 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02004115 indent, "", (uintmax_t) offset, op_name, uleb);
Roland McGratha1599152010-08-30 04:04:37 -07004116 CONSUME (data - start);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004117 offset += 1 + (data - start);
4118 break;
4119
Roland McGrath060fa052006-03-02 07:51:50 +00004120 case DW_OP_bit_piece:
4121 start = data;
Roland McGrath0c5638c2010-06-21 23:00:35 -07004122 uint64_t uleb2;
Mark Wielaard7a053472014-12-14 21:48:23 +01004123 NEED (1);
4124 get_uleb128 (uleb, data, data + len);
4125 NEED (1);
4126 get_uleb128 (uleb2, data, data + len);
Roland McGrath0c5638c2010-06-21 23:00:35 -07004127 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02004128 indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
Roland McGratha1599152010-08-30 04:04:37 -07004129 CONSUME (data - start);
Roland McGrath060fa052006-03-02 07:51:50 +00004130 offset += 1 + (data - start);
4131 break;
4132
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004133 case DW_OP_fbreg:
4134 case DW_OP_breg0 ... DW_OP_breg31:
4135 case DW_OP_consts:
4136 start = data;
Roland McGrath0c5638c2010-06-21 23:00:35 -07004137 int64_t sleb;
Roland McGratha1599152010-08-30 04:04:37 -07004138 NEED (1);
Mark Wielaard7a053472014-12-14 21:48:23 +01004139 get_sleb128 (sleb, data, data + len);
Roland McGrath0c5638c2010-06-21 23:00:35 -07004140 printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02004141 indent, "", (uintmax_t) offset, op_name, sleb);
Roland McGratha1599152010-08-30 04:04:37 -07004142 CONSUME (data - start);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004143 offset += 1 + (data - start);
4144 break;
4145
4146 case DW_OP_bregx:
4147 start = data;
Mark Wielaard7a053472014-12-14 21:48:23 +01004148 NEED (1);
4149 get_uleb128 (uleb, data, data + len);
4150 NEED (1);
4151 get_sleb128 (sleb, data, data + len);
Roland McGrath0c5638c2010-06-21 23:00:35 -07004152 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02004153 indent, "", (uintmax_t) offset, op_name, uleb, sleb);
Roland McGratha1599152010-08-30 04:04:37 -07004154 CONSUME (data - start);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004155 offset += 1 + (data - start);
4156 break;
4157
4158 case DW_OP_call2:
Roland McGrath51f01282009-01-27 17:08:03 -08004159 NEED (2);
4160 printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02004161 indent, "", (uintmax_t) offset, op_name,
Roland McGrath51f01282009-01-27 17:08:03 -08004162 read_2ubyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004163 CONSUME (2);
Roland McGrath51f01282009-01-27 17:08:03 -08004164 offset += 3;
4165 break;
4166
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004167 case DW_OP_call4:
Roland McGrath51f01282009-01-27 17:08:03 -08004168 NEED (4);
4169 printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02004170 indent, "", (uintmax_t) offset, op_name,
Roland McGrath51f01282009-01-27 17:08:03 -08004171 read_4ubyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004172 CONSUME (4);
Roland McGrath51f01282009-01-27 17:08:03 -08004173 offset += 5;
4174 break;
4175
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004176 case DW_OP_skip:
4177 case DW_OP_bra:
Roland McGrath51f01282009-01-27 17:08:03 -08004178 NEED (2);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004179 printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02004180 indent, "", (uintmax_t) offset, op_name,
Mark Wielaard7e3bd4f2012-11-16 12:25:04 +01004181 (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
Roland McGratha1599152010-08-30 04:04:37 -07004182 CONSUME (2);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004183 data += 2;
4184 offset += 3;
4185 break;
4186
Mark Wielaarddaf85b22009-07-24 15:49:51 -07004187 case DW_OP_implicit_value:
4188 start = data;
Roland McGratha1599152010-08-30 04:04:37 -07004189 NEED (1);
Mark Wielaard7a053472014-12-14 21:48:23 +01004190 get_uleb128 (uleb, data, data + len);
Roland McGrathbe4589d2009-07-24 16:23:12 -07004191 printf ("%*s[%4" PRIuMAX "] %s: ",
Mark Wielaardf31c4412012-08-17 00:35:03 +02004192 indent, "", (uintmax_t) offset, op_name);
Mark Wielaarddaf85b22009-07-24 15:49:51 -07004193 NEED (uleb);
Roland McGrathbe4589d2009-07-24 16:23:12 -07004194 print_block (uleb, data);
4195 data += uleb;
Roland McGratha1599152010-08-30 04:04:37 -07004196 CONSUME (data - start);
Mark Wielaarddaf85b22009-07-24 15:49:51 -07004197 offset += 1 + (data - start);
4198 break;
4199
Roland McGrath932585d2010-05-08 04:01:14 -07004200 case DW_OP_GNU_implicit_pointer:
4201 /* DIE offset operand. */
4202 start = data;
Mark Wielaard198e9492014-12-15 19:05:43 +01004203 NEED (ref_size);
4204 if (ref_size != 4 && ref_size != 8)
Mark Wielaard96ddcad2014-12-07 22:45:28 +01004205 goto invalid; /* Cannot be used in CFA. */
Roland McGrath932585d2010-05-08 04:01:14 -07004206 if (ref_size == 4)
4207 addr = read_4ubyte_unaligned (dbg, data);
4208 else
Mark Wielaard198e9492014-12-15 19:05:43 +01004209 addr = read_8ubyte_unaligned (dbg, data);
Roland McGrath932585d2010-05-08 04:01:14 -07004210 data += ref_size;
4211 /* Byte offset operand. */
Mark Wielaard7a053472014-12-14 21:48:23 +01004212 NEED (1);
4213 get_sleb128 (sleb, data, data + len);
Roland McGrath932585d2010-05-08 04:01:14 -07004214
Mark Wielaard63d8bfd2013-05-06 15:48:56 +02004215 printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
Roland McGrath932585d2010-05-08 04:01:14 -07004216 indent, "", (intmax_t) offset,
Mark Wielaardf31c4412012-08-17 00:35:03 +02004217 op_name, (uintmax_t) addr, sleb);
Roland McGrath932585d2010-05-08 04:01:14 -07004218 CONSUME (data - start);
4219 offset += 1 + (data - start);
4220 break;
4221
Mark Wielaarde3368c52011-03-22 23:03:31 +01004222 case DW_OP_GNU_entry_value:
4223 /* Size plus expression block. */
4224 start = data;
4225 NEED (1);
Mark Wielaard7a053472014-12-14 21:48:23 +01004226 get_uleb128 (uleb, data, data + len);
Mark Wielaarde3368c52011-03-22 23:03:31 +01004227 printf ("%*s[%4" PRIuMAX "] %s:\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02004228 indent, "", (uintmax_t) offset, op_name);
Mark Wielaarde3368c52011-03-22 23:03:31 +01004229 NEED (uleb);
4230 print_ops (dwflmod, dbg, indent + 6, indent + 6, vers,
Mark Wielaard35230222013-07-05 16:44:47 +02004231 addrsize, offset_size, cu, uleb, data);
Mark Wielaarde3368c52011-03-22 23:03:31 +01004232 data += uleb;
4233 CONSUME (data - start);
4234 offset += 1 + (data - start);
4235 break;
4236
Jakub Jelinek03124242011-05-17 17:00:14 +02004237 case DW_OP_GNU_const_type:
Mark Wielaard1ab6e782013-07-09 23:09:38 +02004238 /* uleb128 CU relative DW_TAG_base_type DIE offset, 1-byte
4239 unsigned size plus block. */
Jakub Jelinek03124242011-05-17 17:00:14 +02004240 start = data;
Mark Wielaard7a053472014-12-14 21:48:23 +01004241 NEED (1);
4242 get_uleb128 (uleb, data, data + len);
Mark Wielaard1ab6e782013-07-09 23:09:38 +02004243 if (! print_unresolved_addresses && cu != NULL)
4244 uleb += cu->start;
Mark Wielaard7a053472014-12-14 21:48:23 +01004245 NEED (1);
Jakub Jelinek03124242011-05-17 17:00:14 +02004246 uint8_t usize = *(uint8_t *) data++;
4247 NEED (usize);
4248 printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] ",
Mark Wielaardf31c4412012-08-17 00:35:03 +02004249 indent, "", (uintmax_t) offset, op_name, uleb);
Jakub Jelinek03124242011-05-17 17:00:14 +02004250 print_block (usize, data);
4251 data += usize;
4252 CONSUME (data - start);
4253 offset += 1 + (data - start);
4254 break;
4255
4256 case DW_OP_GNU_regval_type:
Mark Wielaard1ab6e782013-07-09 23:09:38 +02004257 /* uleb128 register number, uleb128 CU relative
4258 DW_TAG_base_type DIE offset. */
Jakub Jelinek03124242011-05-17 17:00:14 +02004259 start = data;
Mark Wielaard7a053472014-12-14 21:48:23 +01004260 NEED (1);
4261 get_uleb128 (uleb, data, data + len);
4262 NEED (1);
4263 get_uleb128 (uleb2, data, data + len);
Mark Wielaard1ab6e782013-07-09 23:09:38 +02004264 if (! print_unresolved_addresses && cu != NULL)
4265 uleb2 += cu->start;
4266 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02004267 indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
Jakub Jelinek03124242011-05-17 17:00:14 +02004268 CONSUME (data - start);
4269 offset += 1 + (data - start);
4270 break;
4271
4272 case DW_OP_GNU_deref_type:
Mark Wielaard1ab6e782013-07-09 23:09:38 +02004273 /* 1-byte unsigned size of value, uleb128 CU relative
4274 DW_TAG_base_type DIE offset. */
Jakub Jelinek03124242011-05-17 17:00:14 +02004275 start = data;
Mark Wielaard7a053472014-12-14 21:48:23 +01004276 NEED (1);
Jakub Jelinek03124242011-05-17 17:00:14 +02004277 usize = *(uint8_t *) data++;
Mark Wielaard7a053472014-12-14 21:48:23 +01004278 NEED (1);
4279 get_uleb128 (uleb, data, data + len);
Mark Wielaard1ab6e782013-07-09 23:09:38 +02004280 if (! print_unresolved_addresses && cu != NULL)
4281 uleb += cu->start;
Jakub Jelinek03124242011-05-17 17:00:14 +02004282 printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
4283 indent, "", (uintmax_t) offset,
Mark Wielaardf31c4412012-08-17 00:35:03 +02004284 op_name, usize, uleb);
Jakub Jelinek03124242011-05-17 17:00:14 +02004285 CONSUME (data - start);
4286 offset += 1 + (data - start);
4287 break;
4288
4289 case DW_OP_GNU_convert:
4290 case DW_OP_GNU_reinterpret:
Mark Wielaard1ab6e782013-07-09 23:09:38 +02004291 /* uleb128 CU relative offset to DW_TAG_base_type, or zero
4292 for conversion to untyped. */
Jakub Jelinek03124242011-05-17 17:00:14 +02004293 start = data;
4294 NEED (1);
Mark Wielaard7a053472014-12-14 21:48:23 +01004295 get_uleb128 (uleb, data, data + len);
Mark Wielaard1ab6e782013-07-09 23:09:38 +02004296 if (uleb != 0 && ! print_unresolved_addresses && cu != NULL)
4297 uleb += cu->start;
Jakub Jelinek03124242011-05-17 17:00:14 +02004298 printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02004299 indent, "", (uintmax_t) offset, op_name, uleb);
Jakub Jelinek03124242011-05-17 17:00:14 +02004300 CONSUME (data - start);
4301 offset += 1 + (data - start);
4302 break;
4303
Mark Wielaard515fba92012-07-20 00:09:56 +02004304 case DW_OP_GNU_parameter_ref:
4305 /* 4 byte CU relative reference to the abstract optimized away
4306 DW_TAG_formal_parameter. */
4307 NEED (4);
Mark Wielaard35230222013-07-05 16:44:47 +02004308 uintmax_t param_off = (uintmax_t) read_4ubyte_unaligned (dbg, data);
4309 if (! print_unresolved_addresses && cu != NULL)
4310 param_off += cu->start;
Mark Wielaard515fba92012-07-20 00:09:56 +02004311 printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
Mark Wielaard35230222013-07-05 16:44:47 +02004312 indent, "", (uintmax_t) offset, op_name, param_off);
Mark Wielaard515fba92012-07-20 00:09:56 +02004313 CONSUME (4);
4314 data += 4;
4315 offset += 5;
4316 break;
4317
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004318 default:
4319 /* No Operand. */
Mark Wielaardf31c4412012-08-17 00:35:03 +02004320 printf ("%*s[%4" PRIuMAX "] %s\n",
4321 indent, "", (uintmax_t) offset, op_name);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004322 ++offset;
4323 break;
4324 }
4325
4326 indent = indentrest;
Roland McGrath51f01282009-01-27 17:08:03 -08004327 continue;
4328
4329 invalid:
4330 printf (gettext ("%*s[%4" PRIuMAX "] %s <TRUNCATED>\n"),
Mark Wielaardf31c4412012-08-17 00:35:03 +02004331 indent, "", (uintmax_t) offset, op_name);
Roland McGrath51f01282009-01-27 17:08:03 -08004332 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004333 }
4334}
4335
4336
Roland McGrathfa144952010-08-30 19:22:41 -07004337struct listptr
4338{
4339 Dwarf_Off offset:(64 - 3);
4340 bool addr64:1;
4341 bool dwarf64:1;
4342 bool warned:1;
Mark Wielaard35230222013-07-05 16:44:47 +02004343 struct Dwarf_CU *cu;
Roland McGrathfa144952010-08-30 19:22:41 -07004344};
4345
4346#define listptr_offset_size(p) ((p)->dwarf64 ? 8 : 4)
4347#define listptr_address_size(p) ((p)->addr64 ? 8 : 4)
4348
Mark Wielaard35230222013-07-05 16:44:47 +02004349static Dwarf_Addr
4350listptr_base (struct listptr *p)
4351{
4352 Dwarf_Addr base;
4353 Dwarf_Die cu = CUDIE (p->cu);
4354 /* Find the base address of the compilation unit. It will normally
4355 be specified by DW_AT_low_pc. In DWARF-3 draft 4, the base
4356 address could be overridden by DW_AT_entry_pc. It's been
4357 removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc for
4358 compilation units with discontinuous ranges. */
4359 if (unlikely (dwarf_lowpc (&cu, &base) != 0))
4360 {
4361 Dwarf_Attribute attr_mem;
4362 if (dwarf_formaddr (dwarf_attr (&cu, DW_AT_entry_pc, &attr_mem),
4363 &base) != 0)
4364 base = 0;
4365 }
4366 return base;
4367}
4368
Roland McGrathfa144952010-08-30 19:22:41 -07004369static int
4370compare_listptr (const void *a, const void *b, void *arg)
4371{
4372 const char *name = arg;
4373 struct listptr *p1 = (void *) a;
4374 struct listptr *p2 = (void *) b;
4375
4376 if (p1->offset < p2->offset)
4377 return -1;
4378 if (p1->offset > p2->offset)
4379 return 1;
4380
4381 if (!p1->warned && !p2->warned)
4382 {
4383 if (p1->addr64 != p2->addr64)
4384 {
4385 p1->warned = p2->warned = true;
4386 error (0, 0,
4387 gettext ("%s %#" PRIx64 " used with different address sizes"),
4388 name, (uint64_t) p1->offset);
4389 }
4390 if (p1->dwarf64 != p2->dwarf64)
4391 {
4392 p1->warned = p2->warned = true;
4393 error (0, 0,
4394 gettext ("%s %#" PRIx64 " used with different offset sizes"),
4395 name, (uint64_t) p1->offset);
4396 }
Mark Wielaard35230222013-07-05 16:44:47 +02004397 if (listptr_base (p1) != listptr_base (p2))
Mark Wielaard24257102013-01-18 22:19:08 +01004398 {
4399 p1->warned = p2->warned = true;
4400 error (0, 0,
4401 gettext ("%s %#" PRIx64 " used with different base addresses"),
4402 name, (uint64_t) p1->offset);
4403 }
Roland McGrathfa144952010-08-30 19:22:41 -07004404 }
4405
4406 return 0;
4407}
4408
4409struct listptr_table
4410{
4411 size_t n;
4412 size_t alloc;
4413 struct listptr *table;
4414};
4415
4416static struct listptr_table known_loclistptr;
4417static struct listptr_table known_rangelistptr;
4418
4419static void
4420reset_listptr (struct listptr_table *table)
4421{
4422 free (table->table);
Jan Kratochvilfec39992011-02-27 12:01:25 -08004423 table->table = NULL;
Roland McGrathfa144952010-08-30 19:22:41 -07004424 table->n = table->alloc = 0;
4425}
4426
Mark Wielaard6a8a9e32014-12-15 19:43:02 +01004427/* Returns false if offset doesn't fit. See struct listptr. */
4428static bool
Roland McGrathfa144952010-08-30 19:22:41 -07004429notice_listptr (enum section_e section, struct listptr_table *table,
4430 uint_fast8_t address_size, uint_fast8_t offset_size,
Mark Wielaard35230222013-07-05 16:44:47 +02004431 struct Dwarf_CU *cu, Dwarf_Off offset)
Roland McGrathfa144952010-08-30 19:22:41 -07004432{
4433 if (print_debug_sections & section)
4434 {
4435 if (table->n == table->alloc)
4436 {
4437 if (table->alloc == 0)
4438 table->alloc = 128;
4439 else
4440 table->alloc *= 2;
4441 table->table = xrealloc (table->table,
4442 table->alloc * sizeof table->table[0]);
4443 }
4444
4445 struct listptr *p = &table->table[table->n++];
4446
4447 *p = (struct listptr)
4448 {
4449 .addr64 = address_size == 8,
4450 .dwarf64 = offset_size == 8,
Mark Wielaard24257102013-01-18 22:19:08 +01004451 .offset = offset,
Mark Wielaard35230222013-07-05 16:44:47 +02004452 .cu = cu
Roland McGrathfa144952010-08-30 19:22:41 -07004453 };
Mark Wielaard6a8a9e32014-12-15 19:43:02 +01004454
4455 if (p->offset != offset)
4456 {
4457 table->n--;
4458 return false;
4459 }
Roland McGrathfa144952010-08-30 19:22:41 -07004460 }
Mark Wielaard6a8a9e32014-12-15 19:43:02 +01004461 return true;
Roland McGrathfa144952010-08-30 19:22:41 -07004462}
4463
4464static void
4465sort_listptr (struct listptr_table *table, const char *name)
4466{
4467 if (table->n > 0)
4468 qsort_r (table->table, table->n, sizeof table->table[0],
4469 &compare_listptr, (void *) name);
4470}
4471
4472static bool
4473skip_listptr_hole (struct listptr_table *table, size_t *idxp,
4474 uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
Mark Wielaard35230222013-07-05 16:44:47 +02004475 Dwarf_Addr *base, struct Dwarf_CU **cu, ptrdiff_t offset,
Mark Wielaard24257102013-01-18 22:19:08 +01004476 unsigned char **readp, unsigned char *endp)
Roland McGrathfa144952010-08-30 19:22:41 -07004477{
4478 if (table->n == 0)
4479 return false;
4480
4481 while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
4482 ++*idxp;
4483
4484 struct listptr *p = &table->table[*idxp];
4485
4486 if (*idxp == table->n
4487 || p->offset >= (Dwarf_Off) (endp - *readp + offset))
4488 {
4489 *readp = endp;
4490 printf (gettext (" [%6tx] <UNUSED GARBAGE IN REST OF SECTION>\n"),
4491 offset);
4492 return true;
4493 }
4494
4495 if (p->offset != (Dwarf_Off) offset)
4496 {
4497 *readp += p->offset - offset;
4498 printf (gettext (" [%6tx] <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
4499 offset, (Dwarf_Off) p->offset - offset);
4500 return true;
4501 }
4502
4503 if (address_sizep != NULL)
4504 *address_sizep = listptr_address_size (p);
4505 if (offset_sizep != NULL)
4506 *offset_sizep = listptr_offset_size (p);
Mark Wielaard24257102013-01-18 22:19:08 +01004507 if (base != NULL)
Mark Wielaard35230222013-07-05 16:44:47 +02004508 *base = listptr_base (p);
4509 if (cu != NULL)
4510 *cu = p->cu;
Roland McGrathfa144952010-08-30 19:22:41 -07004511
4512 return false;
4513}
4514
4515
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004516static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004517print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Roland McGrath725aad52011-02-23 19:52:46 -08004518 Ebl *ebl, GElf_Ehdr *ehdr,
Ulrich Drepper351bf202009-01-15 20:18:40 -08004519 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004520{
Mark Wielaard61651c12012-03-28 11:20:36 +02004521 const size_t sh_size = (dbg->sectiondata[IDX_debug_abbrev] ?
4522 dbg->sectiondata[IDX_debug_abbrev]->d_size : 0);
4523
Ulrich Drepper351bf202009-01-15 20:18:40 -08004524 printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004525 " [ Code]\n"),
Roland McGrath725aad52011-02-23 19:52:46 -08004526 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4527 (uint64_t) shdr->sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004528
4529 Dwarf_Off offset = 0;
Mark Wielaard61651c12012-03-28 11:20:36 +02004530 while (offset < sh_size)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004531 {
4532 printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
4533 offset);
4534
4535 while (1)
4536 {
4537 size_t length;
4538 Dwarf_Abbrev abbrev;
4539
4540 int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
4541 if (res != 0)
4542 {
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00004543 if (unlikely (res < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004544 {
4545 printf (gettext ("\
4546 *** error while reading abbreviation: %s\n"),
4547 dwarf_errmsg (-1));
4548 return;
4549 }
4550
4551 /* This is the NUL byte at the end of the section. */
4552 ++offset;
4553 break;
4554 }
4555
4556 /* We know these calls can never fail. */
4557 unsigned int code = dwarf_getabbrevcode (&abbrev);
4558 unsigned int tag = dwarf_getabbrevtag (&abbrev);
4559 int has_children = dwarf_abbrevhaschildren (&abbrev);
4560
4561 printf (gettext (" [%5u] offset: %" PRId64
4562 ", children: %s, tag: %s\n"),
4563 code, (int64_t) offset,
4564 has_children ? gettext ("yes") : gettext ("no"),
Mark Wielaardf31c4412012-08-17 00:35:03 +02004565 dwarf_tag_name (tag));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004566
4567 size_t cnt = 0;
4568 unsigned int name;
4569 unsigned int form;
4570 Dwarf_Off enoffset;
4571 while (dwarf_getabbrevattr (&abbrev, cnt,
4572 &name, &form, &enoffset) == 0)
4573 {
4574 printf (" attr: %s, form: %s, offset: %#" PRIx64 "\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02004575 dwarf_attr_name (name), dwarf_form_name (form),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004576 (uint64_t) enoffset);
4577
4578 ++cnt;
4579 }
4580
4581 offset += length;
4582 }
4583 }
4584}
4585
4586
4587/* Print content of DWARF .debug_aranges section. We fortunately do
4588 not have to know a bit about the structure of the section, libdwarf
4589 takes care of it. */
4590static void
Mark Wielaardb79788c2013-03-25 11:45:22 +01004591print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4592 GElf_Shdr *shdr, Dwarf *dbg)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004593{
4594 Dwarf_Aranges *aranges;
4595 size_t cnt;
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00004596 if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004597 {
4598 error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
4599 dwarf_errmsg (-1));
4600 return;
4601 }
4602
Roland McGrath7d5b3012014-01-17 17:11:39 +01004603 GElf_Shdr glink_mem;
4604 GElf_Shdr *glink;
4605 glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
4606 if (glink == NULL)
4607 {
4608 error (0, 0, gettext ("invalid sh_link value in section %Zu"),
4609 elf_ndxscn (scn));
4610 return;
4611 }
4612
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004613 printf (ngettext ("\
Ulrich Drepper351bf202009-01-15 20:18:40 -08004614\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004615 "\
Ulrich Drepper351bf202009-01-15 20:18:40 -08004616\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004617 cnt),
Roland McGrath725aad52011-02-23 19:52:46 -08004618 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4619 (uint64_t) shdr->sh_offset, cnt);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004620
4621 /* Compute floor(log16(cnt)). */
4622 size_t tmp = cnt;
4623 int digits = 1;
4624 while (tmp >= 16)
4625 {
4626 ++digits;
4627 tmp >>= 4;
4628 }
4629
4630 for (size_t n = 0; n < cnt; ++n)
4631 {
4632 Dwarf_Arange *runp = dwarf_onearange (aranges, n);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00004633 if (unlikely (runp == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004634 {
4635 printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
4636 return;
4637 }
4638
4639 Dwarf_Addr start;
4640 Dwarf_Word length;
4641 Dwarf_Off offset;
4642
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00004643 if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004644 printf (gettext (" [%*zu] ???\n"), digits, n);
4645 else
4646 printf (gettext (" [%*zu] start: %0#*" PRIx64
4647 ", length: %5" PRIu64 ", CU DIE offset: %6"
4648 PRId64 "\n"),
4649 digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
4650 (uint64_t) start, (uint64_t) length, (int64_t) offset);
4651 }
4652}
4653
Mark Wielaardb79788c2013-03-25 11:45:22 +01004654
4655/* Print content of DWARF .debug_aranges section. */
4656static void
4657print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
4658 Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
4659 GElf_Shdr *shdr, Dwarf *dbg)
4660{
4661 if (decodedaranges)
4662 {
4663 print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg);
4664 return;
4665 }
4666
Mark Wielaardf7cdc742014-04-09 22:38:07 +02004667 Elf_Data *data = dbg->sectiondata[IDX_debug_aranges];
Mark Wielaardb79788c2013-03-25 11:45:22 +01004668
4669 if (unlikely (data == NULL))
4670 {
4671 error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
4672 elf_errmsg (-1));
4673 return;
4674 }
4675
4676 printf (gettext ("\
4677\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
4678 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4679 (uint64_t) shdr->sh_offset);
4680
4681 const unsigned char *readp = data->d_buf;
4682 const unsigned char *readendp = readp + data->d_size;
4683
4684 while (readp < readendp)
4685 {
4686 const unsigned char *hdrstart = readp;
4687 size_t start_offset = hdrstart - (const unsigned char *) data->d_buf;
4688
4689 printf (gettext ("\nTable at offset %Zu:\n"), start_offset);
4690 if (readp + 4 > readendp)
4691 {
4692 invalid_data:
4693 error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
4694 elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
4695 return;
4696 }
4697
4698 Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
4699 unsigned int length_bytes = 4;
4700 if (length == DWARF3_LENGTH_64_BIT)
4701 {
4702 if (readp + 8 > readendp)
4703 goto invalid_data;
4704 length = read_8ubyte_unaligned_inc (dbg, readp);
4705 length_bytes = 8;
4706 }
4707
4708 const unsigned char *nexthdr = readp + length;
4709 printf (gettext ("\n Length: %6" PRIu64 "\n"),
4710 (uint64_t) length);
4711
Mark Wielaardacb50692014-12-16 16:30:59 +01004712 if (unlikely (length > (size_t) (readendp - readp)))
Mark Wielaardb79788c2013-03-25 11:45:22 +01004713 goto invalid_data;
4714
4715 if (length == 0)
4716 continue;
4717
4718 if (readp + 2 > readendp)
4719 goto invalid_data;
4720 uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, readp);
4721 printf (gettext (" DWARF version: %6" PRIuFAST16 "\n"),
4722 version);
4723 if (version != 2)
4724 {
4725 error (0, 0, gettext ("unsupported aranges version"));
4726 goto next_table;
4727 }
4728
4729 Dwarf_Word offset;
4730 if (readp + length_bytes > readendp)
4731 goto invalid_data;
4732 if (length_bytes == 8)
4733 offset = read_8ubyte_unaligned_inc (dbg, readp);
4734 else
4735 offset = read_4ubyte_unaligned_inc (dbg, readp);
4736 printf (gettext (" CU offset: %6" PRIx64 "\n"),
4737 (uint64_t) offset);
4738
4739 if (readp + 1 > readendp)
4740 goto invalid_data;
4741 unsigned int address_size = *readp++;
4742 printf (gettext (" Address size: %6" PRIu64 "\n"),
4743 (uint64_t) address_size);
4744 if (address_size != 4 && address_size != 8)
4745 {
4746 error (0, 0, gettext ("unsupported address size"));
4747 goto next_table;
4748 }
4749
4750 unsigned int segment_size = *readp++;
4751 printf (gettext (" Segment size: %6" PRIu64 "\n\n"),
4752 (uint64_t) segment_size);
4753 if (segment_size != 0 && segment_size != 4 && segment_size != 8)
4754 {
4755 error (0, 0, gettext ("unsupported segment size"));
4756 goto next_table;
4757 }
4758
4759 /* Round the address to the next multiple of 2*address_size. */
4760 readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
4761 % (2 * address_size));
4762
4763 while (readp < nexthdr)
4764 {
4765 Dwarf_Word range_address;
4766 Dwarf_Word range_length;
4767 Dwarf_Word segment = 0;
4768 if (readp + 2 * address_size + segment_size > readendp)
4769 goto invalid_data;
4770 if (address_size == 4)
4771 {
4772 range_address = read_4ubyte_unaligned_inc (dbg, readp);
4773 range_length = read_4ubyte_unaligned_inc (dbg, readp);
4774 }
4775 else
4776 {
4777 range_address = read_8ubyte_unaligned_inc (dbg, readp);
4778 range_length = read_8ubyte_unaligned_inc (dbg, readp);
4779 }
4780
4781 if (segment_size == 4)
4782 segment = read_4ubyte_unaligned_inc (dbg, readp);
4783 else if (segment_size == 8)
4784 segment = read_8ubyte_unaligned_inc (dbg, readp);
4785
4786 if (range_address == 0 && range_length == 0 && segment == 0)
4787 break;
4788
4789 char *b = format_dwarf_addr (dwflmod, address_size, range_address,
4790 range_address);
4791 char *e = format_dwarf_addr (dwflmod, address_size,
4792 range_address + range_length - 1,
4793 range_length);
4794 if (segment_size != 0)
4795 printf (gettext (" %s..%s (%" PRIx64 ")\n"), b, e,
4796 (uint64_t) segment);
4797 else
4798 printf (gettext (" %s..%s\n"), b, e);
4799 free (b);
4800 free (e);
4801 }
4802
4803 next_table:
4804 if (readp != nexthdr)
4805 {
4806 size_t padding = nexthdr - readp;
4807 printf (gettext (" %Zu padding bytes\n"), padding);
4808 readp = nexthdr;
4809 }
4810 }
4811}
4812
4813
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004814/* Print content of DWARF .debug_ranges section. */
4815static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004816print_debug_ranges_section (Dwfl_Module *dwflmod,
Roland McGrath725aad52011-02-23 19:52:46 -08004817 Ebl *ebl, GElf_Ehdr *ehdr,
4818 Elf_Scn *scn, GElf_Shdr *shdr,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004819 Dwarf *dbg)
4820{
Mark Wielaardf7cdc742014-04-09 22:38:07 +02004821 Elf_Data *data = dbg->sectiondata[IDX_debug_ranges];
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004822
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00004823 if (unlikely (data == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004824 {
4825 error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
4826 elf_errmsg (-1));
4827 return;
4828 }
4829
4830 printf (gettext ("\
Ulrich Drepper351bf202009-01-15 20:18:40 -08004831\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
Roland McGrath725aad52011-02-23 19:52:46 -08004832 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4833 (uint64_t) shdr->sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004834
Roland McGrathfa144952010-08-30 19:22:41 -07004835 sort_listptr (&known_rangelistptr, "rangelistptr");
4836 size_t listptr_idx = 0;
4837
4838 uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004839
4840 bool first = true;
Mark Wielaard24257102013-01-18 22:19:08 +01004841 Dwarf_Addr base = 0;
Roland McGrathfa144952010-08-30 19:22:41 -07004842 unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004843 unsigned char *readp = data->d_buf;
Roland McGrathfa144952010-08-30 19:22:41 -07004844 while (readp < endp)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004845 {
4846 ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
4847
Roland McGrathfa144952010-08-30 19:22:41 -07004848 if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
Mark Wielaard35230222013-07-05 16:44:47 +02004849 &address_size, NULL, &base, NULL,
Roland McGrathfa144952010-08-30 19:22:41 -07004850 offset, &readp, endp))
4851 continue;
4852
Mark Wielaardbe860842013-11-05 13:37:33 +01004853 if (unlikely (data->d_size - offset < (size_t) address_size * 2))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004854 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004855 printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004856 break;
4857 }
4858
4859 Dwarf_Addr begin;
4860 Dwarf_Addr end;
4861 if (address_size == 8)
4862 {
4863 begin = read_8ubyte_unaligned_inc (dbg, readp);
4864 end = read_8ubyte_unaligned_inc (dbg, readp);
4865 }
4866 else
4867 {
4868 begin = read_4ubyte_unaligned_inc (dbg, readp);
4869 end = read_4ubyte_unaligned_inc (dbg, readp);
4870 if (begin == (Dwarf_Addr) (uint32_t) -1)
4871 begin = (Dwarf_Addr) -1l;
4872 }
4873
4874 if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004875 {
Mark Wielaard10186a12013-01-24 11:29:21 +01004876 char *b = format_dwarf_addr (dwflmod, address_size, end, end);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004877 printf (gettext (" [%6tx] base address %s\n"), offset, b);
4878 free (b);
Mark Wielaard24257102013-01-18 22:19:08 +01004879 base = end;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004880 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004881 else if (begin == 0 && end == 0) /* End of list entry. */
Roland McGrathfa144952010-08-30 19:22:41 -07004882 {
4883 if (first)
4884 printf (gettext (" [%6tx] empty list\n"), offset);
4885 first = true;
4886 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004887 else
4888 {
Mark Wielaard10186a12013-01-24 11:29:21 +01004889 char *b = format_dwarf_addr (dwflmod, address_size, base + begin,
4890 begin);
4891 char *e = format_dwarf_addr (dwflmod, address_size, base + end,
4892 end);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004893 /* We have an address range entry. */
4894 if (first) /* First address range entry in a list. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004895 printf (gettext (" [%6tx] %s..%s\n"), offset, b, e);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004896 else
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004897 printf (gettext (" %s..%s\n"), b, e);
4898 free (b);
4899 free (e);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004900
4901 first = false;
4902 }
4903 }
4904}
4905
Roland McGrathdffc33d2009-07-06 16:06:41 -07004906#define REGNAMESZ 16
4907static const char *
4908register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
4909 char name[REGNAMESZ], int *bits, int *type)
4910{
4911 const char *set;
4912 const char *pfx;
4913 int ignore;
4914 ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
4915 bits ?: &ignore, type ?: &ignore);
4916 if (n <= 0)
4917 {
Mark Wielaarde89c5002012-08-27 14:30:05 +02004918 if (loc != NULL)
4919 snprintf (name, REGNAMESZ, "reg%u", loc->regno);
4920 else
4921 snprintf (name, REGNAMESZ, "??? 0x%x", regno);
Roland McGrathdffc33d2009-07-06 16:06:41 -07004922 if (bits != NULL)
Mark Wielaarde89c5002012-08-27 14:30:05 +02004923 *bits = loc != NULL ? loc->bits : 0;
Roland McGrathdffc33d2009-07-06 16:06:41 -07004924 if (type != NULL)
4925 *type = DW_ATE_unsigned;
Roland McGrath46d58272009-07-06 17:57:33 -07004926 set = "??? unrecognized";
4927 }
4928 else
4929 {
4930 if (bits != NULL && *bits <= 0)
Mark Wielaarde89c5002012-08-27 14:30:05 +02004931 *bits = loc != NULL ? loc->bits : 0;
Roland McGrath46d58272009-07-06 17:57:33 -07004932 if (type != NULL && *type == DW_ATE_void)
4933 *type = DW_ATE_unsigned;
4934
Roland McGrathdffc33d2009-07-06 16:06:41 -07004935 }
4936 return set;
4937}
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004938
4939static void
Ulrich Drepperac194d02009-01-06 00:30:01 -08004940print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
4941 Dwarf_Word vma_base, unsigned int code_align,
Roland McGrath52604ba2010-07-26 21:29:44 -07004942 int data_align,
4943 unsigned int version, unsigned int ptr_size,
4944 Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004945{
Roland McGrathdffc33d2009-07-06 16:06:41 -07004946 char regnamebuf[REGNAMESZ];
Ulrich Drepperac194d02009-01-06 00:30:01 -08004947 const char *regname (unsigned int regno)
4948 {
Roland McGrathdffc33d2009-07-06 16:06:41 -07004949 register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
4950 return regnamebuf;
Ulrich Drepperac194d02009-01-06 00:30:01 -08004951 }
4952
4953 puts ("\n Program:");
4954 Dwarf_Word pc = vma_base;
4955 while (readp < endp)
4956 {
4957 unsigned int opcode = *readp++;
4958
4959 if (opcode < DW_CFA_advance_loc)
4960 /* Extended opcode. */
4961 switch (opcode)
4962 {
4963 uint64_t op1;
4964 int64_t sop1;
4965 uint64_t op2;
4966 int64_t sop2;
4967
4968 case DW_CFA_nop:
4969 puts (" nop");
4970 break;
4971 case DW_CFA_set_loc:
Mark Wielaard99a6f222014-12-17 15:07:49 +01004972 if ((uint64_t) (endp - readp) < 1)
4973 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01004974 get_uleb128 (op1, readp, endp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004975 op1 += vma_base;
4976 printf (" set_loc %" PRIu64 "\n", op1 * code_align);
4977 break;
4978 case DW_CFA_advance_loc1:
Mark Wielaard99a6f222014-12-17 15:07:49 +01004979 if ((uint64_t) (endp - readp) < 1)
4980 goto invalid;
Ulrich Drepperac194d02009-01-06 00:30:01 -08004981 printf (" advance_loc1 %u to %#" PRIx64 "\n",
4982 *readp, pc += *readp * code_align);
4983 ++readp;
4984 break;
4985 case DW_CFA_advance_loc2:
Mark Wielaard7a053472014-12-14 21:48:23 +01004986 if ((uint64_t) (endp - readp) < 2)
4987 goto invalid;
Ulrich Drepperac194d02009-01-06 00:30:01 -08004988 op1 = read_2ubyte_unaligned_inc (dbg, readp);
4989 printf (" advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
4990 op1, pc += op1 * code_align);
4991 break;
4992 case DW_CFA_advance_loc4:
Mark Wielaard7a053472014-12-14 21:48:23 +01004993 if ((uint64_t) (endp - readp) < 4)
4994 goto invalid;
Ulrich Drepperac194d02009-01-06 00:30:01 -08004995 op1 = read_4ubyte_unaligned_inc (dbg, readp);
4996 printf (" advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
4997 op1, pc += op1 * code_align);
4998 break;
4999 case DW_CFA_offset_extended:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005000 if ((uint64_t) (endp - readp) < 1)
5001 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005002 get_uleb128 (op1, readp, endp);
5003 if ((uint64_t) (endp - readp) < 1)
5004 goto invalid;
5005 get_uleb128 (op2, readp, endp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005006 printf (" offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
5007 "\n",
5008 op1, regname (op1), op2 * data_align);
5009 break;
5010 case DW_CFA_restore_extended:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005011 if ((uint64_t) (endp - readp) < 1)
5012 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005013 get_uleb128 (op1, readp, endp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005014 printf (" restore_extended r%" PRIu64 " (%s)\n",
5015 op1, regname (op1));
5016 break;
5017 case DW_CFA_undefined:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005018 if ((uint64_t) (endp - readp) < 1)
5019 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005020 get_uleb128 (op1, readp, endp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005021 printf (" undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
5022 break;
5023 case DW_CFA_same_value:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005024 if ((uint64_t) (endp - readp) < 1)
5025 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005026 get_uleb128 (op1, readp, endp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005027 printf (" same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
5028 break;
5029 case DW_CFA_register:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005030 if ((uint64_t) (endp - readp) < 1)
5031 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005032 get_uleb128 (op1, readp, endp);
5033 if ((uint64_t) (endp - readp) < 1)
5034 goto invalid;
5035 get_uleb128 (op2, readp, endp);
Ulrich Drepper8cbc8e62009-02-05 22:13:05 -08005036 printf (" register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
Ulrich Drepperac194d02009-01-06 00:30:01 -08005037 op1, regname (op1), op2, regname (op2));
5038 break;
5039 case DW_CFA_remember_state:
5040 puts (" remember_state");
5041 break;
5042 case DW_CFA_restore_state:
5043 puts (" restore_state");
5044 break;
5045 case DW_CFA_def_cfa:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005046 if ((uint64_t) (endp - readp) < 1)
5047 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005048 get_uleb128 (op1, readp, endp);
5049 if ((uint64_t) (endp - readp) < 1)
5050 goto invalid;
5051 get_uleb128 (op2, readp, endp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005052 printf (" def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
5053 op1, regname (op1), op2);
5054 break;
5055 case DW_CFA_def_cfa_register:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005056 if ((uint64_t) (endp - readp) < 1)
5057 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005058 get_uleb128 (op1, readp, endp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005059 printf (" def_cfa_register r%" PRIu64 " (%s)\n",
5060 op1, regname (op1));
5061 break;
5062 case DW_CFA_def_cfa_offset:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005063 if ((uint64_t) (endp - readp) < 1)
5064 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005065 get_uleb128 (op1, readp, endp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005066 printf (" def_cfa_offset %" PRIu64 "\n", op1);
5067 break;
5068 case DW_CFA_def_cfa_expression:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005069 if ((uint64_t) (endp - readp) < 1)
5070 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005071 get_uleb128 (op1, readp, endp); /* Length of DW_FORM_block. */
Ulrich Drepper411cdb22009-02-05 22:04:26 -08005072 printf (" def_cfa_expression %" PRIu64 "\n", op1);
Mark Wielaard2af7b492014-11-16 11:40:08 +01005073 if ((uint64_t) (endp - readp) < op1)
5074 {
5075 invalid:
5076 fputs (gettext (" <INVALID DATA>\n"), stdout);
5077 return;
5078 }
Mark Wielaard35230222013-07-05 16:44:47 +02005079 print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
5080 op1, readp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005081 readp += op1;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005082 break;
5083 case DW_CFA_expression:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005084 if ((uint64_t) (endp - readp) < 1)
5085 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005086 get_uleb128 (op1, readp, endp);
5087 if ((uint64_t) (endp - readp) < 1)
5088 goto invalid;
5089 get_uleb128 (op2, readp, endp); /* Length of DW_FORM_block. */
Ulrich Drepperb3490b52009-02-05 22:34:30 -08005090 printf (" expression r%" PRIu64 " (%s) \n",
5091 op1, regname (op1));
Mark Wielaardd405f932014-11-18 10:01:48 +01005092 if ((uint64_t) (endp - readp) < op2)
Mark Wielaard2af7b492014-11-16 11:40:08 +01005093 goto invalid;
Mark Wielaard35230222013-07-05 16:44:47 +02005094 print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
5095 op2, readp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005096 readp += op2;
5097 break;
5098 case DW_CFA_offset_extended_sf:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005099 if ((uint64_t) (endp - readp) < 1)
5100 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005101 get_uleb128 (op1, readp, endp);
5102 if ((uint64_t) (endp - readp) < 1)
5103 goto invalid;
5104 get_sleb128 (sop2, readp, endp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005105 printf (" offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
5106 PRId64 "\n",
5107 op1, regname (op1), sop2 * data_align);
5108 break;
5109 case DW_CFA_def_cfa_sf:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005110 if ((uint64_t) (endp - readp) < 1)
5111 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005112 get_uleb128 (op1, readp, endp);
5113 if ((uint64_t) (endp - readp) < 1)
5114 goto invalid;
5115 get_sleb128 (sop2, readp, endp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005116 printf (" def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
5117 op1, regname (op1), sop2 * data_align);
5118 break;
5119 case DW_CFA_def_cfa_offset_sf:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005120 if ((uint64_t) (endp - readp) < 1)
5121 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005122 get_sleb128 (sop1, readp, endp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005123 printf (" def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
5124 break;
5125 case DW_CFA_val_offset:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005126 if ((uint64_t) (endp - readp) < 1)
5127 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005128 get_uleb128 (op1, readp, endp);
5129 if ((uint64_t) (endp - readp) < 1)
5130 goto invalid;
5131 get_uleb128 (op2, readp, endp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005132 printf (" val_offset %" PRIu64 " at offset %" PRIu64 "\n",
5133 op1, op2 * data_align);
5134 break;
5135 case DW_CFA_val_offset_sf:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005136 if ((uint64_t) (endp - readp) < 1)
5137 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005138 get_uleb128 (op1, readp, endp);
5139 if ((uint64_t) (endp - readp) < 1)
5140 goto invalid;
5141 get_sleb128 (sop2, readp, endp);
Ulrich Drepper8cbc8e62009-02-05 22:13:05 -08005142 printf (" val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
Ulrich Drepperac194d02009-01-06 00:30:01 -08005143 op1, sop2 * data_align);
5144 break;
5145 case DW_CFA_val_expression:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005146 if ((uint64_t) (endp - readp) < 1)
5147 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005148 get_uleb128 (op1, readp, endp);
5149 if ((uint64_t) (endp - readp) < 1)
5150 goto invalid;
5151 get_uleb128 (op2, readp, endp); /* Length of DW_FORM_block. */
Ulrich Drepper973a9c72009-02-05 22:56:39 -08005152 printf (" val_expression r%" PRIu64 " (%s)\n",
5153 op1, regname (op1));
Mark Wielaard2af7b492014-11-16 11:40:08 +01005154 if ((uint64_t) (endp - readp) < op2)
5155 goto invalid;
Mark Wielaard35230222013-07-05 16:44:47 +02005156 print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0,
5157 NULL, op2, readp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005158 readp += op2;
5159 break;
5160 case DW_CFA_MIPS_advance_loc8:
Mark Wielaard7a053472014-12-14 21:48:23 +01005161 if ((uint64_t) (endp - readp) < 8)
5162 goto invalid;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005163 op1 = read_8ubyte_unaligned_inc (dbg, readp);
Ulrich Drepper8cbc8e62009-02-05 22:13:05 -08005164 printf (" MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
Ulrich Drepperac194d02009-01-06 00:30:01 -08005165 op1, pc += op1 * code_align);
5166 break;
5167 case DW_CFA_GNU_window_save:
Ulrich Drepper8cbc8e62009-02-05 22:13:05 -08005168 puts (" GNU_window_save");
Ulrich Drepperac194d02009-01-06 00:30:01 -08005169 break;
5170 case DW_CFA_GNU_args_size:
Mark Wielaard99a6f222014-12-17 15:07:49 +01005171 if ((uint64_t) (endp - readp) < 1)
5172 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005173 get_uleb128 (op1, readp, endp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005174 printf (" args_size %" PRIu64 "\n", op1);
5175 break;
5176 default:
5177 printf (" ??? (%u)\n", opcode);
5178 break;
5179 }
5180 else if (opcode < DW_CFA_offset)
5181 printf (" advance_loc %u to %#" PRIx64 "\n",
5182 opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
5183 else if (opcode < DW_CFA_restore)
5184 {
Roland McGrath0c5638c2010-06-21 23:00:35 -07005185 uint64_t offset;
Mark Wielaard99a6f222014-12-17 15:07:49 +01005186 if ((uint64_t) (endp - readp) < 1)
5187 goto invalid;
Mark Wielaard7a053472014-12-14 21:48:23 +01005188 get_uleb128 (offset, readp, endp);
Roland McGrath0c5638c2010-06-21 23:00:35 -07005189 printf (" offset r%u (%s) at cfa%+" PRId64 "\n",
Ulrich Drepperac194d02009-01-06 00:30:01 -08005190 opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
5191 }
5192 else
5193 printf (" restore r%u (%s)\n",
5194 opcode & 0x3f, regname (opcode & 0x3f));
5195 }
5196}
5197
5198
5199static unsigned int
5200encoded_ptr_size (int encoding, unsigned int ptr_size)
5201{
5202 switch (encoding & 7)
5203 {
Petr Machata1498f542014-09-12 19:03:33 +02005204 case DW_EH_PE_udata4:
Ulrich Drepperac194d02009-01-06 00:30:01 -08005205 return 4;
Petr Machata1498f542014-09-12 19:03:33 +02005206 case DW_EH_PE_udata8:
Ulrich Drepperac194d02009-01-06 00:30:01 -08005207 return 8;
Petr Machata1498f542014-09-12 19:03:33 +02005208 case 0:
Ulrich Drepperac194d02009-01-06 00:30:01 -08005209 return ptr_size;
5210 }
Petr Machata1498f542014-09-12 19:03:33 +02005211
5212 fprintf (stderr, "Unsupported pointer encoding: %#x, "
5213 "assuming pointer size of %d.\n", encoding, ptr_size);
5214 return ptr_size;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005215}
5216
5217
Ulrich Drepper351bf202009-01-15 20:18:40 -08005218static unsigned int
5219print_encoding (unsigned int val)
5220{
5221 switch (val & 0xf)
5222 {
5223 case DW_EH_PE_absptr:
5224 fputs ("absptr", stdout);
5225 break;
5226 case DW_EH_PE_uleb128:
5227 fputs ("uleb128", stdout);
5228 break;
5229 case DW_EH_PE_udata2:
5230 fputs ("udata2", stdout);
5231 break;
5232 case DW_EH_PE_udata4:
5233 fputs ("udata4", stdout);
5234 break;
5235 case DW_EH_PE_udata8:
5236 fputs ("udata8", stdout);
5237 break;
5238 case DW_EH_PE_sleb128:
5239 fputs ("sleb128", stdout);
5240 break;
5241 case DW_EH_PE_sdata2:
5242 fputs ("sdata2", stdout);
5243 break;
5244 case DW_EH_PE_sdata4:
5245 fputs ("sdata4", stdout);
5246 break;
5247 case DW_EH_PE_sdata8:
5248 fputs ("sdata8", stdout);
5249 break;
5250 default:
5251 /* We did not use any of the bits after all. */
5252 return val;
5253 }
5254
5255 return val & ~0xf;
5256}
5257
5258
5259static unsigned int
5260print_relinfo (unsigned int val)
5261{
5262 switch (val & 0x70)
5263 {
5264 case DW_EH_PE_pcrel:
5265 fputs ("pcrel", stdout);
5266 break;
5267 case DW_EH_PE_textrel:
5268 fputs ("textrel", stdout);
5269 break;
5270 case DW_EH_PE_datarel:
5271 fputs ("datarel", stdout);
5272 break;
5273 case DW_EH_PE_funcrel:
5274 fputs ("funcrel", stdout);
5275 break;
5276 case DW_EH_PE_aligned:
5277 fputs ("aligned", stdout);
5278 break;
5279 default:
5280 return val;
5281 }
5282
5283 return val & ~0x70;
5284}
5285
5286
5287static void
Ulrich Drepperbc298972009-01-16 11:50:10 -08005288print_encoding_base (const char *pfx, unsigned int fde_encoding)
Ulrich Drepper351bf202009-01-15 20:18:40 -08005289{
Ulrich Drepperbc298972009-01-16 11:50:10 -08005290 printf ("(%s", pfx);
Ulrich Drepper351bf202009-01-15 20:18:40 -08005291
Ulrich Drepper05d2b202009-01-16 17:58:54 -08005292 if (fde_encoding == DW_EH_PE_omit)
5293 puts ("omit)");
5294 else
Ulrich Drepper351bf202009-01-15 20:18:40 -08005295 {
Ulrich Drepper05d2b202009-01-16 17:58:54 -08005296 unsigned int w = fde_encoding;
Ulrich Drepper351bf202009-01-15 20:18:40 -08005297
Roland McGrathf920fd52010-02-02 15:50:15 -08005298 w = print_encoding (w);
Ulrich Drepper05d2b202009-01-16 17:58:54 -08005299
5300 if (w & 0x70)
5301 {
5302 if (w != fde_encoding)
5303 fputc_unlocked (' ', stdout);
5304
5305 w = print_relinfo (w);
5306 }
5307
5308 if (w != 0)
5309 printf ("%s%x", w != fde_encoding ? " " : "", w);
5310
5311 puts (")");
Ulrich Drepper351bf202009-01-15 20:18:40 -08005312 }
Ulrich Drepper351bf202009-01-15 20:18:40 -08005313}
5314
5315
Ulrich Drepperbc298972009-01-16 11:50:10 -08005316static const unsigned char *
5317read_encoded (unsigned int encoding, const unsigned char *readp,
5318 const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
5319{
Roland McGrathf920fd52010-02-02 15:50:15 -08005320 if ((encoding & 0xf) == DW_EH_PE_absptr)
5321 encoding = gelf_getclass (dbg->elf) == ELFCLASS32
5322 ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
5323
Ulrich Drepperbc298972009-01-16 11:50:10 -08005324 switch (encoding & 0xf)
5325 {
5326 case DW_EH_PE_uleb128:
Mark Wielaard7a053472014-12-14 21:48:23 +01005327 get_uleb128 (*res, readp, endp);
Ulrich Drepperbc298972009-01-16 11:50:10 -08005328 break;
5329 case DW_EH_PE_sleb128:
Mark Wielaard7a053472014-12-14 21:48:23 +01005330 get_sleb128 (*res, readp, endp);
Ulrich Drepperbc298972009-01-16 11:50:10 -08005331 break;
5332 case DW_EH_PE_udata2:
5333 if (readp + 2 > endp)
5334 goto invalid;
5335 *res = read_2ubyte_unaligned_inc (dbg, readp);
5336 break;
5337 case DW_EH_PE_udata4:
5338 if (readp + 4 > endp)
5339 goto invalid;
5340 *res = read_4ubyte_unaligned_inc (dbg, readp);
5341 break;
5342 case DW_EH_PE_udata8:
5343 if (readp + 8 > endp)
5344 goto invalid;
5345 *res = read_8ubyte_unaligned_inc (dbg, readp);
5346 break;
5347 case DW_EH_PE_sdata2:
5348 if (readp + 2 > endp)
5349 goto invalid;
5350 *res = read_2sbyte_unaligned_inc (dbg, readp);
5351 break;
5352 case DW_EH_PE_sdata4:
5353 if (readp + 4 > endp)
5354 goto invalid;
5355 *res = read_4sbyte_unaligned_inc (dbg, readp);
5356 break;
5357 case DW_EH_PE_sdata8:
5358 if (readp + 8 > endp)
5359 goto invalid;
5360 *res = read_8sbyte_unaligned_inc (dbg, readp);
5361 break;
5362 default:
5363 invalid:
5364 error (1, 0,
5365 gettext ("invalid encoding"));
5366 }
5367
5368 return readp;
5369}
5370
5371
Ulrich Drepperac194d02009-01-06 00:30:01 -08005372static void
5373print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
5374 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5375{
5376 size_t shstrndx;
5377 /* We know this call will succeed since it did in the caller. */
Ulrich Drepperf1894932009-06-13 15:55:42 -07005378 (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005379 const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
5380
Mark Wielaard00f758c2012-12-21 22:11:44 +01005381 /* Needed if we find PC-relative addresses. */
5382 GElf_Addr bias;
5383 if (dwfl_module_getelf (dwflmod, &bias) == NULL)
5384 {
5385 error (0, 0, gettext ("cannot get ELF: %s"), dwfl_errmsg (-1));
5386 return;
5387 }
5388
Mark Wielaardf7cdc742014-04-09 22:38:07 +02005389 bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
5390 Elf_Data *data = (is_eh_frame
5391 ? elf_rawdata (scn, NULL)
5392 : dbg->sectiondata[IDX_debug_frame]);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005393
5394 if (unlikely (data == NULL))
5395 {
5396 error (0, 0, gettext ("cannot get %s content: %s"),
5397 scnname, elf_errmsg (-1));
5398 return;
5399 }
5400
Ulrich Drepper351bf202009-01-15 20:18:40 -08005401 if (is_eh_frame)
5402 printf (gettext ("\
5403\nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5404 elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
5405 else
5406 printf (gettext ("\
5407\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5408 elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005409
5410 struct cieinfo
5411 {
5412 ptrdiff_t cie_offset;
5413 const char *augmentation;
5414 unsigned int code_alignment_factor;
5415 unsigned int data_alignment_factor;
Roland McGrath599f7f52010-06-20 17:12:43 -07005416 uint8_t address_size;
5417 uint8_t fde_encoding;
5418 uint8_t lsda_encoding;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005419 struct cieinfo *next;
5420 } *cies = NULL;
5421
5422 const unsigned char *readp = data->d_buf;
5423 const unsigned char *const dataend = ((unsigned char *) data->d_buf
5424 + data->d_size);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005425 while (readp < dataend)
5426 {
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005427 if (unlikely (readp + 4 > dataend))
Ulrich Drepperac194d02009-01-06 00:30:01 -08005428 {
5429 invalid_data:
5430 error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
5431 elf_ndxscn (scn), scnname);
5432 return;
5433 }
5434
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005435 /* At the beginning there must be a CIE. There can be multiple,
5436 hence we test tis in a loop. */
5437 ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005438
5439 Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
5440 unsigned int length = 4;
5441 if (unlikely (unit_length == 0xffffffff))
5442 {
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005443 if (unlikely (readp + 8 > dataend))
5444 goto invalid_data;
5445
Ulrich Drepperac194d02009-01-06 00:30:01 -08005446 unit_length = read_8ubyte_unaligned_inc (dbg, readp);
5447 length = 8;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005448 }
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005449
5450 if (unlikely (unit_length == 0))
5451 {
Roland McGrathe9de9b42009-01-22 13:05:40 -08005452 printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005453 continue;
5454 }
5455
Mark Wielaardd1b11632014-11-14 21:42:47 +01005456 Dwarf_Word maxsize = dataend - readp;
5457 if (unlikely (unit_length > maxsize))
5458 goto invalid_data;
5459
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005460 unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5461
Ulrich Drepperac194d02009-01-06 00:30:01 -08005462 ptrdiff_t start = readp - (unsigned char *) data->d_buf;
5463 const unsigned char *const cieend = readp + unit_length;
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005464 if (unlikely (cieend > dataend || readp + 8 > dataend))
Ulrich Drepperac194d02009-01-06 00:30:01 -08005465 goto invalid_data;
5466
Roland McGrath2fb90512009-04-15 14:47:13 -07005467 Dwarf_Off cie_id;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005468 if (length == 4)
Roland McGrath2fb90512009-04-15 14:47:13 -07005469 {
5470 cie_id = read_4ubyte_unaligned_inc (dbg, readp);
5471 if (!is_eh_frame && cie_id == DW_CIE_ID_32)
5472 cie_id = DW_CIE_ID_64;
5473 }
Ulrich Drepperac194d02009-01-06 00:30:01 -08005474 else
5475 cie_id = read_8ubyte_unaligned_inc (dbg, readp);
5476
Roland McGrath52604ba2010-07-26 21:29:44 -07005477 uint_fast8_t version = 2;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005478 unsigned int code_alignment_factor;
5479 int data_alignment_factor;
5480 unsigned int fde_encoding = 0;
Ulrich Drepperbc298972009-01-16 11:50:10 -08005481 unsigned int lsda_encoding = 0;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005482 Dwarf_Word initial_location = 0;
Ulrich Drepper62c46532009-01-24 17:01:08 -08005483 Dwarf_Word vma_base = 0;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005484
Roland McGrath2fb90512009-04-15 14:47:13 -07005485 if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
Ulrich Drepperac194d02009-01-06 00:30:01 -08005486 {
Roland McGrath52604ba2010-07-26 21:29:44 -07005487 version = *readp++;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005488 const char *const augmentation = (const char *) readp;
5489 readp = memchr (readp, '\0', cieend - readp);
5490 if (unlikely (readp == NULL))
5491 goto invalid_data;
5492 ++readp;
Roland McGrath599f7f52010-06-20 17:12:43 -07005493
5494 uint_fast8_t segment_size = 0;
5495 if (version >= 4)
5496 {
5497 if (cieend - readp < 5)
5498 goto invalid_data;
5499 ptr_size = *readp++;
5500 segment_size = *readp++;
5501 }
5502
Mark Wielaard7a053472014-12-14 21:48:23 +01005503 if (cieend - readp < 1)
5504 goto invalid_data;
5505 get_uleb128 (code_alignment_factor, readp, cieend);
5506 if (cieend - readp < 1)
5507 goto invalid_data;
5508 get_sleb128 (data_alignment_factor, readp, cieend);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005509
5510 /* In some variant for unwind data there is another field. */
5511 if (strcmp (augmentation, "eh") == 0)
5512 readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5513
5514 unsigned int return_address_register;
Mark Wielaard7a053472014-12-14 21:48:23 +01005515 if (cieend - readp < 1)
5516 goto invalid_data;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005517 if (unlikely (version == 1))
5518 return_address_register = *readp++;
5519 else
Mark Wielaard7a053472014-12-14 21:48:23 +01005520 get_uleb128 (return_address_register, readp, cieend);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005521
Roland McGrathe9de9b42009-01-22 13:05:40 -08005522 printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
Ulrich Drepperac194d02009-01-06 00:30:01 -08005523 " CIE_id: %" PRIu64 "\n"
5524 " version: %u\n"
Roland McGrath599f7f52010-06-20 17:12:43 -07005525 " augmentation: \"%s\"\n",
5526 offset, (uint64_t) unit_length, (uint64_t) cie_id,
5527 version, augmentation);
5528 if (version >= 4)
5529 printf (" address_size: %u\n"
5530 " segment_size: %u\n",
5531 ptr_size, segment_size);
5532 printf (" code_alignment_factor: %u\n"
Ulrich Drepperac194d02009-01-06 00:30:01 -08005533 " data_alignment_factor: %d\n"
5534 " return_address_register: %u\n",
Roland McGrath599f7f52010-06-20 17:12:43 -07005535 code_alignment_factor,
Ulrich Drepperac194d02009-01-06 00:30:01 -08005536 data_alignment_factor, return_address_register);
5537
5538 if (augmentation[0] == 'z')
5539 {
Ulrich Drepperac194d02009-01-06 00:30:01 -08005540 unsigned int augmentationlen;
Mark Wielaard7a053472014-12-14 21:48:23 +01005541 get_uleb128 (augmentationlen, readp, cieend);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005542
Mark Wielaardcd339292014-12-11 17:21:22 +01005543 if (augmentationlen > (size_t) (cieend - readp))
Mark Wielaardd1b11632014-11-14 21:42:47 +01005544 {
5545 error (0, 0, gettext ("invalid augmentation length"));
5546 readp = cieend;
5547 continue;
5548 }
Roland McGrathf920fd52010-02-02 15:50:15 -08005549
Ulrich Drepperac194d02009-01-06 00:30:01 -08005550 const char *hdr = "Augmentation data:";
5551 const char *cp = augmentation + 1;
Mark Wielaardcd339292014-12-11 17:21:22 +01005552 while (*cp != '\0' && cp < augmentation + augmentationlen + 1)
Ulrich Drepperac194d02009-01-06 00:30:01 -08005553 {
5554 printf (" %-26s%#x ", hdr, *readp);
5555 hdr = "";
5556
5557 if (*cp == 'R')
5558 {
Ulrich Drepperbc298972009-01-16 11:50:10 -08005559 fde_encoding = *readp++;
5560 print_encoding_base (gettext ("FDE address encoding: "),
5561 fde_encoding);
5562 }
5563 else if (*cp == 'L')
5564 {
5565 lsda_encoding = *readp++;
5566 print_encoding_base (gettext ("LSDA pointer encoding: "),
5567 lsda_encoding);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005568 }
5569 else if (*cp == 'P')
5570 {
Ulrich Drepper351bf202009-01-15 20:18:40 -08005571 /* Personality. This field usually has a relocation
5572 attached pointing to __gcc_personality_v0. */
Ulrich Drepperac194d02009-01-06 00:30:01 -08005573 const unsigned char *startp = readp;
5574 unsigned int encoding = *readp++;
5575 uint64_t val = 0;
Roland McGrathf920fd52010-02-02 15:50:15 -08005576 readp = read_encoded (encoding, readp,
5577 readp - 1 + augmentationlen,
5578 &val, dbg);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005579
5580 while (++startp < readp)
5581 printf ("%#x ", *startp);
5582
Roland McGrathf920fd52010-02-02 15:50:15 -08005583 putchar ('(');
5584 print_encoding (encoding);
5585 putchar (' ');
5586 switch (encoding & 0xf)
5587 {
5588 case DW_EH_PE_sleb128:
5589 case DW_EH_PE_sdata2:
5590 case DW_EH_PE_sdata4:
5591 printf ("%" PRId64 ")\n", val);
5592 break;
5593 default:
5594 printf ("%#" PRIx64 ")\n", val);
5595 break;
5596 }
Ulrich Drepperac194d02009-01-06 00:30:01 -08005597 }
5598 else
5599 printf ("(%x)\n", *readp++);
5600
5601 ++cp;
5602 }
Ulrich Drepperac194d02009-01-06 00:30:01 -08005603 }
5604
Roland McGrath599f7f52010-06-20 17:12:43 -07005605 if (likely (ptr_size == 4 || ptr_size == 8))
5606 {
5607 struct cieinfo *newp = alloca (sizeof (*newp));
5608 newp->cie_offset = offset;
5609 newp->augmentation = augmentation;
5610 newp->fde_encoding = fde_encoding;
5611 newp->lsda_encoding = lsda_encoding;
5612 newp->address_size = ptr_size;
5613 newp->code_alignment_factor = code_alignment_factor;
5614 newp->data_alignment_factor = data_alignment_factor;
5615 newp->next = cies;
5616 cies = newp;
5617 }
Ulrich Drepperac194d02009-01-06 00:30:01 -08005618 }
5619 else
5620 {
5621 struct cieinfo *cie = cies;
5622 while (cie != NULL)
Ulrich Drepper351bf202009-01-15 20:18:40 -08005623 if (is_eh_frame
Mark Wielaard32d5b6f2015-04-22 12:47:46 +02005624 ? ((Dwarf_Off) start - cie_id) == (Dwarf_Off) cie->cie_offset
5625 : cie_id == (Dwarf_Off) cie->cie_offset)
Ulrich Drepperac194d02009-01-06 00:30:01 -08005626 break;
5627 else
5628 cie = cie->next;
5629 if (unlikely (cie == NULL))
5630 {
5631 puts ("invalid CIE reference in FDE");
5632 return;
5633 }
5634
5635 /* Initialize from CIE data. */
Ulrich Drepper351bf202009-01-15 20:18:40 -08005636 fde_encoding = cie->fde_encoding;
Ulrich Drepperbc298972009-01-16 11:50:10 -08005637 lsda_encoding = cie->lsda_encoding;
Roland McGrath599f7f52010-06-20 17:12:43 -07005638 ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005639 code_alignment_factor = cie->code_alignment_factor;
5640 data_alignment_factor = cie->data_alignment_factor;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005641
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005642 const unsigned char *base = readp;
Ulrich Drepper351bf202009-01-15 20:18:40 -08005643 // XXX There are sometimes relocations for this value
Petr Machata1498f542014-09-12 19:03:33 +02005644 initial_location = read_addr_unaligned_inc (ptr_size, dbg, readp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005645 Dwarf_Word address_range
Petr Machata1498f542014-09-12 19:03:33 +02005646 = read_addr_unaligned_inc (ptr_size, dbg, readp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005647
Mark Wielaard00f758c2012-12-21 22:11:44 +01005648 /* pcrel for an FDE address is relative to the runtime
5649 address of the start_address field itself. Sign extend
5650 if necessary to make sure the calculation is done on the
5651 full 64 bit address even when initial_location only holds
5652 the lower 32 bits. */
5653 Dwarf_Addr pc_start = initial_location;
5654 if (ptr_size == 4)
5655 pc_start = (uint64_t) (int32_t) pc_start;
5656 if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
5657 pc_start += ((uint64_t) shdr->sh_addr
5658 + (base - (const unsigned char *) data->d_buf)
5659 - bias);
5660
Roland McGrath2f14a312010-07-02 11:16:25 -07005661 char *a = format_dwarf_addr (dwflmod, cie->address_size,
Mark Wielaard10186a12013-01-24 11:29:21 +01005662 pc_start, initial_location);
Roland McGrathe9de9b42009-01-22 13:05:40 -08005663 printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
Ulrich Drepperac194d02009-01-06 00:30:01 -08005664 " CIE_pointer: %" PRIu64 "\n"
Roland McGrath2f14a312010-07-02 11:16:25 -07005665 " initial_location: %s",
Ulrich Drepperac194d02009-01-06 00:30:01 -08005666 offset, (uint64_t) unit_length,
Roland McGrath2f14a312010-07-02 11:16:25 -07005667 cie->cie_offset, (uint64_t) cie_id, a);
5668 free (a);
Ulrich Drepper351bf202009-01-15 20:18:40 -08005669 if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
Ulrich Drepper62c46532009-01-24 17:01:08 -08005670 {
5671 vma_base = (((uint64_t) shdr->sh_offset
5672 + (base - (const unsigned char *) data->d_buf)
5673 + (uint64_t) initial_location)
5674 & (ptr_size == 4
5675 ? UINT64_C (0xffffffff)
5676 : UINT64_C (0xffffffffffffffff)));
5677 printf (gettext (" (offset: %#" PRIx64 ")"),
5678 (uint64_t) vma_base);
5679 }
5680
5681 printf ("\n address_range: %#" PRIx64,
5682 (uint64_t) address_range);
5683 if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
5684 printf (gettext (" (end offset: %#" PRIx64 ")"),
5685 ((uint64_t) vma_base + (uint64_t) address_range)
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005686 & (ptr_size == 4
5687 ? UINT64_C (0xffffffff)
5688 : UINT64_C (0xffffffffffffffff)));
Ulrich Drepper62c46532009-01-24 17:01:08 -08005689 putchar ('\n');
Ulrich Drepperac194d02009-01-06 00:30:01 -08005690
5691 if (cie->augmentation[0] == 'z')
5692 {
5693 unsigned int augmentationlen;
Mark Wielaard7a053472014-12-14 21:48:23 +01005694 if (cieend - readp < 1)
5695 goto invalid_data;
5696 get_uleb128 (augmentationlen, readp, cieend);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005697
Mark Wielaard7a053472014-12-14 21:48:23 +01005698 if (augmentationlen > (size_t) (cieend - readp))
Mark Wielaardd1b11632014-11-14 21:42:47 +01005699 {
5700 error (0, 0, gettext ("invalid augmentation length"));
5701 readp = cieend;
5702 continue;
5703 }
5704
Ulrich Drepper351bf202009-01-15 20:18:40 -08005705 if (augmentationlen > 0)
Ulrich Drepperac194d02009-01-06 00:30:01 -08005706 {
Ulrich Drepper351bf202009-01-15 20:18:40 -08005707 const char *hdr = "Augmentation data:";
5708 const char *cp = cie->augmentation + 1;
Ulrich Drepperbc298972009-01-16 11:50:10 -08005709 unsigned int u = 0;
Mark Wielaardcd339292014-12-11 17:21:22 +01005710 while (*cp != '\0'
5711 && cp < cie->augmentation + augmentationlen + 1)
Ulrich Drepper351bf202009-01-15 20:18:40 -08005712 {
Ulrich Drepperbc298972009-01-16 11:50:10 -08005713 if (*cp == 'L')
5714 {
5715 uint64_t lsda_pointer;
5716 const unsigned char *p
5717 = read_encoded (lsda_encoding, &readp[u],
5718 &readp[augmentationlen],
5719 &lsda_pointer, dbg);
5720 u = p - readp;
5721 printf (gettext ("\
5722 %-26sLSDA pointer: %#" PRIx64 "\n"),
5723 hdr, lsda_pointer);
5724 hdr = "";
5725 }
5726 ++cp;
5727 }
5728
5729 while (u < augmentationlen)
5730 {
5731 printf (" %-26s%#x\n", hdr, readp[u++]);
Ulrich Drepper351bf202009-01-15 20:18:40 -08005732 hdr = "";
5733 }
Ulrich Drepperac194d02009-01-06 00:30:01 -08005734 }
Ulrich Drepperbc298972009-01-16 11:50:10 -08005735
5736 readp += augmentationlen;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005737 }
5738 }
5739
Ulrich Drepperac194d02009-01-06 00:30:01 -08005740 /* Handle the initialization instructions. */
Mark Wielaard7df0da32014-11-17 23:01:34 +01005741 if (ptr_size != 4 && ptr_size !=8)
5742 printf ("invalid CIE pointer size (%u), must be 4 or 8.\n", ptr_size);
5743 else
5744 print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
5745 data_alignment_factor, version, ptr_size,
5746 dwflmod, ebl, dbg);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005747 readp = cieend;
5748 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005749}
5750
5751
5752struct attrcb_args
5753{
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00005754 Dwfl_Module *dwflmod;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005755 Dwarf *dbg;
Mark Wielaarda8c7f052013-03-25 21:11:53 +01005756 Dwarf_Die *die;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005757 int level;
Roland McGrathfa144952010-08-30 19:22:41 -07005758 bool silent;
Roland McGrath52604ba2010-07-26 21:29:44 -07005759 unsigned int version;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005760 unsigned int addrsize;
Roland McGrath688f7fc2010-05-08 03:22:59 -07005761 unsigned int offset_size;
Mark Wielaard35230222013-07-05 16:44:47 +02005762 struct Dwarf_CU *cu;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005763};
5764
5765
5766static int
5767attr_callback (Dwarf_Attribute *attrp, void *arg)
5768{
5769 struct attrcb_args *cbargs = (struct attrcb_args *) arg;
5770 const int level = cbargs->level;
5771
5772 unsigned int attr = dwarf_whatattr (attrp);
5773 if (unlikely (attr == 0))
5774 {
Roland McGrathfa144952010-08-30 19:22:41 -07005775 if (!cbargs->silent)
5776 error (0, 0, gettext ("cannot get attribute code: %s"),
5777 dwarf_errmsg (-1));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005778 return DWARF_CB_ABORT;
5779 }
5780
5781 unsigned int form = dwarf_whatform (attrp);
5782 if (unlikely (form == 0))
5783 {
Roland McGrathfa144952010-08-30 19:22:41 -07005784 if (!cbargs->silent)
5785 error (0, 0, gettext ("cannot get attribute form: %s"),
5786 dwarf_errmsg (-1));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005787 return DWARF_CB_ABORT;
5788 }
5789
5790 switch (form)
5791 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00005792 case DW_FORM_addr:
Roland McGrathfa144952010-08-30 19:22:41 -07005793 if (!cbargs->silent)
5794 {
5795 Dwarf_Addr addr;
5796 if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
5797 {
5798 attrval_out:
5799 if (!cbargs->silent)
5800 error (0, 0, gettext ("cannot get attribute value: %s"),
5801 dwarf_errmsg (-1));
5802 return DWARF_CB_ABORT;
5803 }
Mark Wielaard10186a12013-01-24 11:29:21 +01005804 char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize,
5805 addr, addr);
Roland McGrathfa144952010-08-30 19:22:41 -07005806 printf (" %*s%-20s (%s) %s\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02005807 (int) (level * 2), "", dwarf_attr_name (attr),
5808 dwarf_form_name (form), a);
Roland McGrathfa144952010-08-30 19:22:41 -07005809 free (a);
5810 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005811 break;
5812
5813 case DW_FORM_indirect:
5814 case DW_FORM_strp:
Roland McGrathfa144952010-08-30 19:22:41 -07005815 case DW_FORM_string:
Mark Wielaard775375e2012-06-22 12:02:45 +02005816 case DW_FORM_GNU_strp_alt:
Roland McGrathfa144952010-08-30 19:22:41 -07005817 if (cbargs->silent)
5818 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005819 const char *str = dwarf_formstring (attrp);
5820 if (unlikely (str == NULL))
5821 goto attrval_out;
Ulrich Drepper173ade82010-05-28 07:39:49 -07005822 printf (" %*s%-20s (%s) \"%s\"\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02005823 (int) (level * 2), "", dwarf_attr_name (attr),
5824 dwarf_form_name (form), str);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005825 break;
5826
5827 case DW_FORM_ref_addr:
5828 case DW_FORM_ref_udata:
5829 case DW_FORM_ref8:
5830 case DW_FORM_ref4:
5831 case DW_FORM_ref2:
Mark Wielaard775375e2012-06-22 12:02:45 +02005832 case DW_FORM_ref1:
5833 case DW_FORM_GNU_ref_alt:
Roland McGrathfa144952010-08-30 19:22:41 -07005834 if (cbargs->silent)
5835 break;
Roland McGrathe4c22ea2007-10-23 13:07:39 +00005836 Dwarf_Die ref;
5837 if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005838 goto attrval_out;
5839
Ulrich Drepper173ade82010-05-28 07:39:49 -07005840 printf (" %*s%-20s (%s) [%6" PRIxMAX "]\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02005841 (int) (level * 2), "", dwarf_attr_name (attr),
5842 dwarf_form_name (form), (uintmax_t) dwarf_dieoffset (&ref));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005843 break;
5844
Roland McGrathc8a06732010-06-01 19:52:39 -07005845 case DW_FORM_ref_sig8:
Roland McGrathfa144952010-08-30 19:22:41 -07005846 if (cbargs->silent)
5847 break;
Roland McGrathc8a06732010-06-01 19:52:39 -07005848 printf (" %*s%-20s (%s) {%6" PRIx64 "}\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02005849 (int) (level * 2), "", dwarf_attr_name (attr),
5850 dwarf_form_name (form),
Mark Wielaard50e2d392012-06-22 16:44:54 +02005851 (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
Roland McGrathc8a06732010-06-01 19:52:39 -07005852 break;
5853
Roland McGrath7fac1ce2010-06-01 15:56:58 -07005854 case DW_FORM_sec_offset:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005855 case DW_FORM_udata:
5856 case DW_FORM_sdata:
5857 case DW_FORM_data8:
5858 case DW_FORM_data4:
5859 case DW_FORM_data2:
5860 case DW_FORM_data1:;
5861 Dwarf_Word num;
5862 if (unlikely (dwarf_formudata (attrp, &num) != 0))
5863 goto attrval_out;
5864
5865 const char *valuestr = NULL;
5866 switch (attr)
5867 {
Roland McGrathfa144952010-08-30 19:22:41 -07005868 /* This case can take either a constant or a loclistptr. */
Mark Wielaardf735db12009-07-08 19:18:53 +02005869 case DW_AT_data_member_location:
Roland McGrathfa144952010-08-30 19:22:41 -07005870 if (form != DW_FORM_sec_offset
5871 && (cbargs->version >= 4
5872 || (form != DW_FORM_data4 && form != DW_FORM_data8)))
Mark Wielaardf735db12009-07-08 19:18:53 +02005873 {
Roland McGrathfa144952010-08-30 19:22:41 -07005874 if (!cbargs->silent)
5875 printf (" %*s%-20s (%s) %" PRIxMAX "\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02005876 (int) (level * 2), "", dwarf_attr_name (attr),
5877 dwarf_form_name (form), (uintmax_t) num);
Mark Wielaardf735db12009-07-08 19:18:53 +02005878 return DWARF_CB_OK;
5879 }
5880 /* else fallthrough */
5881
5882 /* These cases always take a loclistptr and no constant. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005883 case DW_AT_location:
Roland McGrath07a696e2007-11-09 22:44:26 +00005884 case DW_AT_data_location:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005885 case DW_AT_vtable_elem_location:
5886 case DW_AT_string_length:
5887 case DW_AT_use_location:
5888 case DW_AT_frame_base:
5889 case DW_AT_return_addr:
5890 case DW_AT_static_link:
Mark Wielaarde3368c52011-03-22 23:03:31 +01005891 case DW_AT_GNU_call_site_value:
5892 case DW_AT_GNU_call_site_data_value:
5893 case DW_AT_GNU_call_site_target:
5894 case DW_AT_GNU_call_site_target_clobbered:
Mark Wielaard6a8a9e32014-12-15 19:43:02 +01005895 {
5896 bool nlpt = notice_listptr (section_loc, &known_loclistptr,
5897 cbargs->addrsize, cbargs->offset_size,
5898 cbargs->cu, num);
5899 if (!cbargs->silent)
5900 printf (" %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n",
5901 (int) (level * 2), "", dwarf_attr_name (attr),
5902 dwarf_form_name (form), (uintmax_t) num,
5903 nlpt ? "" : " <WARNING offset too big>");
5904 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005905 return DWARF_CB_OK;
5906
5907 case DW_AT_ranges:
Mark Wielaard6a8a9e32014-12-15 19:43:02 +01005908 {
5909 bool nlpt = notice_listptr (section_ranges, &known_rangelistptr,
5910 cbargs->addrsize, cbargs->offset_size,
5911 cbargs->cu, num);
5912 if (!cbargs->silent)
5913 printf (" %*s%-20s (%s) range list [%6" PRIxMAX "]%s\n",
5914 (int) (level * 2), "", dwarf_attr_name (attr),
5915 dwarf_form_name (form), (uintmax_t) num,
5916 nlpt ? "" : " <WARNING offset too big>");
5917 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005918 return DWARF_CB_OK;
5919
5920 case DW_AT_language:
Mark Wielaardf31c4412012-08-17 00:35:03 +02005921 valuestr = dwarf_lang_name (num);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005922 break;
5923 case DW_AT_encoding:
Mark Wielaardf31c4412012-08-17 00:35:03 +02005924 valuestr = dwarf_encoding_name (num);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005925 break;
5926 case DW_AT_accessibility:
Mark Wielaardf31c4412012-08-17 00:35:03 +02005927 valuestr = dwarf_access_name (num);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005928 break;
5929 case DW_AT_visibility:
Mark Wielaardf31c4412012-08-17 00:35:03 +02005930 valuestr = dwarf_visibility_name (num);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005931 break;
5932 case DW_AT_virtuality:
Mark Wielaardf31c4412012-08-17 00:35:03 +02005933 valuestr = dwarf_virtuality_name (num);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005934 break;
5935 case DW_AT_identifier_case:
Mark Wielaardf31c4412012-08-17 00:35:03 +02005936 valuestr = dwarf_identifier_case_name (num);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005937 break;
5938 case DW_AT_calling_convention:
Mark Wielaardf31c4412012-08-17 00:35:03 +02005939 valuestr = dwarf_calling_convention_name (num);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005940 break;
5941 case DW_AT_inline:
Mark Wielaardf31c4412012-08-17 00:35:03 +02005942 valuestr = dwarf_inline_name (num);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005943 break;
5944 case DW_AT_ordering:
Mark Wielaardf31c4412012-08-17 00:35:03 +02005945 valuestr = dwarf_ordering_name (num);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005946 break;
5947 case DW_AT_discr_list:
Mark Wielaardf31c4412012-08-17 00:35:03 +02005948 valuestr = dwarf_discr_list_name (num);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005949 break;
5950 default:
5951 /* Nothing. */
5952 break;
5953 }
5954
Roland McGrathfa144952010-08-30 19:22:41 -07005955 if (cbargs->silent)
5956 break;
5957
Mark Wielaarda8c7f052013-03-25 21:11:53 +01005958 /* When highpc is in constant form it is relative to lowpc.
5959 In that case also show the address. */
5960 Dwarf_Addr highpc;
5961 if (attr == DW_AT_high_pc && dwarf_highpc (cbargs->die, &highpc) == 0)
5962 {
5963 char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize,
5964 highpc, highpc);
5965 printf (" %*s%-20s (%s) %" PRIuMAX " (%s)\n",
5966 (int) (level * 2), "", dwarf_attr_name (attr),
5967 dwarf_form_name (form), (uintmax_t) num, a);
5968 free (a);
5969 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005970 else
Mark Wielaardb9207522014-03-05 16:17:54 +01005971 {
5972 Dwarf_Sword snum = 0;
5973 if (form == DW_FORM_sdata)
5974 if (unlikely (dwarf_formsdata (attrp, &snum) != 0))
5975 goto attrval_out;
5976
5977 if (valuestr == NULL)
5978 {
5979 printf (" %*s%-20s (%s)",
5980 (int) (level * 2), "", dwarf_attr_name (attr),
5981 dwarf_form_name (form));
5982 if (form == DW_FORM_sdata)
5983 printf (" %" PRIdMAX "\n", (intmax_t) snum);
5984 else
5985 printf (" %" PRIuMAX "\n", (uintmax_t) num);
5986 }
5987 else
5988 {
5989 printf (" %*s%-20s (%s) %s",
5990 (int) (level * 2), "", dwarf_attr_name (attr),
5991 dwarf_form_name (form), valuestr);
5992 if (form == DW_FORM_sdata)
5993 printf (" (%" PRIdMAX ")\n", (intmax_t) snum);
5994 else
5995 printf (" (%" PRIuMAX ")\n", (uintmax_t) num);
5996 }
5997 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005998 break;
5999
Roland McGrathfa144952010-08-30 19:22:41 -07006000 case DW_FORM_flag:
6001 if (cbargs->silent)
6002 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006003 bool flag;
6004 if (unlikely (dwarf_formflag (attrp, &flag) != 0))
6005 goto attrval_out;
6006
Ulrich Drepper173ade82010-05-28 07:39:49 -07006007 printf (" %*s%-20s (%s) %s\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02006008 (int) (level * 2), "", dwarf_attr_name (attr),
6009 dwarf_form_name (form), nl_langinfo (flag ? YESSTR : NOSTR));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006010 break;
6011
Roland McGrath7fac1ce2010-06-01 15:56:58 -07006012 case DW_FORM_flag_present:
Roland McGrathfa144952010-08-30 19:22:41 -07006013 if (cbargs->silent)
6014 break;
Roland McGrath7fac1ce2010-06-01 15:56:58 -07006015 printf (" %*s%-20s (%s) %s\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02006016 (int) (level * 2), "", dwarf_attr_name (attr),
6017 dwarf_form_name (form), nl_langinfo (YESSTR));
Roland McGrath7fac1ce2010-06-01 15:56:58 -07006018 break;
6019
6020 case DW_FORM_exprloc:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006021 case DW_FORM_block4:
6022 case DW_FORM_block2:
6023 case DW_FORM_block1:
Roland McGrathfa144952010-08-30 19:22:41 -07006024 case DW_FORM_block:
6025 if (cbargs->silent)
6026 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006027 Dwarf_Block block;
6028 if (unlikely (dwarf_formblock (attrp, &block) != 0))
6029 goto attrval_out;
6030
Ulrich Drepper173ade82010-05-28 07:39:49 -07006031 printf (" %*s%-20s (%s) ",
Mark Wielaardf31c4412012-08-17 00:35:03 +02006032 (int) (level * 2), "", dwarf_attr_name (attr),
6033 dwarf_form_name (form));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006034
6035 switch (attr)
6036 {
Roland McGrath7fac1ce2010-06-01 15:56:58 -07006037 default:
6038 if (form != DW_FORM_exprloc)
6039 {
6040 print_block (block.length, block.data);
6041 break;
6042 }
6043 /* Fall through. */
6044
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006045 case DW_AT_location:
Roland McGrath07a696e2007-11-09 22:44:26 +00006046 case DW_AT_data_location:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006047 case DW_AT_data_member_location:
6048 case DW_AT_vtable_elem_location:
6049 case DW_AT_string_length:
6050 case DW_AT_use_location:
6051 case DW_AT_frame_base:
6052 case DW_AT_return_addr:
6053 case DW_AT_static_link:
Roland McGrath1a2e8f42007-12-15 23:39:34 +00006054 case DW_AT_allocated:
6055 case DW_AT_associated:
6056 case DW_AT_bit_size:
6057 case DW_AT_bit_offset:
6058 case DW_AT_bit_stride:
6059 case DW_AT_byte_size:
6060 case DW_AT_byte_stride:
6061 case DW_AT_count:
6062 case DW_AT_lower_bound:
6063 case DW_AT_upper_bound:
Mark Wielaarde3368c52011-03-22 23:03:31 +01006064 case DW_AT_GNU_call_site_value:
6065 case DW_AT_GNU_call_site_data_value:
6066 case DW_AT_GNU_call_site_target:
6067 case DW_AT_GNU_call_site_target_clobbered:
6068 putchar ('\n');
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006069 print_ops (cbargs->dwflmod, cbargs->dbg,
6070 12 + level * 2, 12 + level * 2,
Roland McGrath52604ba2010-07-26 21:29:44 -07006071 cbargs->version, cbargs->addrsize, cbargs->offset_size,
Mark Wielaard35230222013-07-05 16:44:47 +02006072 attrp->cu, block.length, block.data);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006073 break;
6074 }
6075 break;
6076
6077 default:
Roland McGrathfa144952010-08-30 19:22:41 -07006078 if (cbargs->silent)
6079 break;
Ulrich Drepper173ade82010-05-28 07:39:49 -07006080 printf (" %*s%-20s (form: %#x) ???\n",
Mark Wielaardf31c4412012-08-17 00:35:03 +02006081 (int) (level * 2), "", dwarf_attr_name (attr),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006082 (int) form);
6083 break;
6084 }
6085
6086 return DWARF_CB_OK;
6087}
6088
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006089static void
Roland McGrath2b1f0952010-06-20 17:55:50 -07006090print_debug_units (Dwfl_Module *dwflmod,
Roland McGrath725aad52011-02-23 19:52:46 -08006091 Ebl *ebl, GElf_Ehdr *ehdr,
6092 Elf_Scn *scn, GElf_Shdr *shdr,
6093 Dwarf *dbg, bool debug_types)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006094{
Roland McGrathfa144952010-08-30 19:22:41 -07006095 const bool silent = !(print_debug_sections & section_info);
Roland McGrath725aad52011-02-23 19:52:46 -08006096 const char *secname = section_name (ebl, ehdr, shdr);
Roland McGrath2b1f0952010-06-20 17:55:50 -07006097
Roland McGrathfa144952010-08-30 19:22:41 -07006098 if (!silent)
6099 printf (gettext ("\
Ulrich Drepper351bf202009-01-15 20:18:40 -08006100\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
Roland McGrathfa144952010-08-30 19:22:41 -07006101 elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006102
6103 /* If the section is empty we don't have to do anything. */
Roland McGrathfa144952010-08-30 19:22:41 -07006104 if (!silent && shdr->sh_size == 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006105 return;
6106
6107 int maxdies = 20;
6108 Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
6109
6110 Dwarf_Off offset = 0;
6111
6112 /* New compilation unit. */
6113 size_t cuhl;
Roland McGrath2b1f0952010-06-20 17:55:50 -07006114 Dwarf_Half version;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006115 Dwarf_Off abbroffset;
6116 uint8_t addrsize;
6117 uint8_t offsize;
6118 Dwarf_Off nextcu;
Roland McGrath2b1f0952010-06-20 17:55:50 -07006119 uint64_t typesig;
6120 Dwarf_Off typeoff;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006121 next_cu:
Roland McGrath2b1f0952010-06-20 17:55:50 -07006122 if (dwarf_next_unit (dbg, offset, &nextcu, &cuhl, &version,
6123 &abbroffset, &addrsize, &offsize,
6124 debug_types ? &typesig : NULL,
6125 debug_types ? &typeoff : NULL) != 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006126 goto do_return;
6127
Roland McGrathfa144952010-08-30 19:22:41 -07006128 if (!silent)
6129 {
6130 if (debug_types)
6131 printf (gettext (" Type unit at offset %" PRIu64 ":\n"
6132 " Version: %" PRIu16 ", Abbreviation section offset: %"
6133 PRIu64 ", Address size: %" PRIu8
6134 ", Offset size: %" PRIu8
6135 "\n Type signature: %#" PRIx64
6136 ", Type offset: %#" PRIx64 "\n"),
6137 (uint64_t) offset, version, abbroffset, addrsize, offsize,
6138 typesig, (uint64_t) typeoff);
6139 else
6140 printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
6141 " Version: %" PRIu16 ", Abbreviation section offset: %"
6142 PRIu64 ", Address size: %" PRIu8
6143 ", Offset size: %" PRIu8 "\n"),
6144 (uint64_t) offset, version, abbroffset, addrsize, offsize);
6145 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006146
Roland McGrath688f7fc2010-05-08 03:22:59 -07006147 struct attrcb_args args =
6148 {
6149 .dwflmod = dwflmod,
6150 .dbg = dbg,
Roland McGrathfa144952010-08-30 19:22:41 -07006151 .silent = silent,
Roland McGrath52604ba2010-07-26 21:29:44 -07006152 .version = version,
Roland McGrath688f7fc2010-05-08 03:22:59 -07006153 .addrsize = addrsize,
Mark Wielaard24257102013-01-18 22:19:08 +01006154 .offset_size = offsize
Roland McGrath688f7fc2010-05-08 03:22:59 -07006155 };
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006156
6157 offset += cuhl;
6158
6159 int level = 0;
6160
Roland McGrath2b1f0952010-06-20 17:55:50 -07006161 if (unlikely ((debug_types ? dwarf_offdie_types : dwarf_offdie)
6162 (dbg, offset, &dies[level]) == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006163 {
Roland McGrathfa144952010-08-30 19:22:41 -07006164 if (!silent)
6165 error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
6166 " in section '%s': %s"),
6167 (uint64_t) offset, secname, dwarf_errmsg (-1));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006168 goto do_return;
6169 }
6170
Mark Wielaard35230222013-07-05 16:44:47 +02006171 args.cu = dies[0].cu;
Mark Wielaard24257102013-01-18 22:19:08 +01006172
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006173 do
6174 {
6175 offset = dwarf_dieoffset (&dies[level]);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006176 if (unlikely (offset == ~0ul))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006177 {
Roland McGrathfa144952010-08-30 19:22:41 -07006178 if (!silent)
6179 error (0, 0, gettext ("cannot get DIE offset: %s"),
6180 dwarf_errmsg (-1));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006181 goto do_return;
6182 }
6183
6184 int tag = dwarf_tag (&dies[level]);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006185 if (unlikely (tag == DW_TAG_invalid))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006186 {
Roland McGrathfa144952010-08-30 19:22:41 -07006187 if (!silent)
6188 error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
6189 " in section '%s': %s"),
6190 (uint64_t) offset, secname, dwarf_errmsg (-1));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006191 goto do_return;
6192 }
6193
Roland McGrathfa144952010-08-30 19:22:41 -07006194 if (!silent)
6195 printf (" [%6" PRIx64 "] %*s%s\n",
6196 (uint64_t) offset, (int) (level * 2), "",
Mark Wielaardf31c4412012-08-17 00:35:03 +02006197 dwarf_tag_name (tag));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006198
6199 /* Print the attribute values. */
6200 args.level = level;
Mark Wielaarda8c7f052013-03-25 21:11:53 +01006201 args.die = &dies[level];
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006202 (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
6203
6204 /* Make room for the next level's DIE. */
6205 if (level + 1 == maxdies)
6206 dies = (Dwarf_Die *) xrealloc (dies,
6207 (maxdies += 10)
6208 * sizeof (Dwarf_Die));
6209
6210 int res = dwarf_child (&dies[level], &dies[level + 1]);
6211 if (res > 0)
6212 {
6213 while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
Ulrich Drepperc911d5c2008-01-22 05:59:26 +00006214 if (level-- == 0)
6215 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006216
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006217 if (unlikely (res == -1))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006218 {
Roland McGrathfa144952010-08-30 19:22:41 -07006219 if (!silent)
6220 error (0, 0, gettext ("cannot get next DIE: %s\n"),
6221 dwarf_errmsg (-1));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006222 goto do_return;
6223 }
6224 }
6225 else if (unlikely (res < 0))
6226 {
Roland McGrathfa144952010-08-30 19:22:41 -07006227 if (!silent)
6228 error (0, 0, gettext ("cannot get next DIE: %s"),
6229 dwarf_errmsg (-1));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006230 goto do_return;
6231 }
6232 else
6233 ++level;
6234 }
6235 while (level >= 0);
6236
6237 offset = nextcu;
6238 if (offset != 0)
6239 goto next_cu;
6240
6241 do_return:
6242 free (dies);
6243}
6244
Roland McGrath2b1f0952010-06-20 17:55:50 -07006245static void
6246print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
6247 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6248{
6249 print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
6250}
6251
6252static void
6253print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
6254 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6255{
6256 print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
6257}
6258
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006259
6260static void
Mark Wielaard1a094202013-03-25 14:48:06 +01006261print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
6262 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6263{
6264 printf (gettext ("\
6265\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n\n"),
6266 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6267 (uint64_t) shdr->sh_offset);
6268
6269 size_t address_size
6270 = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6271
6272 Dwarf_Off cuoffset;
6273 Dwarf_Off ncuoffset = 0;
6274 size_t hsize;
6275 while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
6276 NULL, NULL, NULL) == 0)
6277 {
6278 Dwarf_Die cudie;
6279 if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
6280 continue;
6281
6282 size_t nlines;
6283 Dwarf_Lines *lines;
6284 if (dwarf_getsrclines (&cudie, &lines, &nlines) != 0)
6285 continue;
6286
6287 printf (" CU [%" PRIx64 "] %s\n",
6288 dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
6289 printf (" line:col SBPE* disc isa op address"
6290 " (Statement Block Prologue Epilogue *End)\n");
6291 const char *last_file = "";
6292 for (size_t n = 0; n < nlines; n++)
6293 {
6294 Dwarf_Line *line = dwarf_onesrcline (lines, n);
Mark Wielaard32270932014-12-16 22:19:08 +01006295 if (line == NULL)
6296 {
6297 printf (" dwarf_onesrcline: %s\n", dwarf_errmsg (-1));
6298 continue;
6299 }
Mark Wielaard1a094202013-03-25 14:48:06 +01006300 Dwarf_Word mtime, length;
6301 const char *file = dwarf_linesrc (line, &mtime, &length);
Mark Wielaard32270932014-12-16 22:19:08 +01006302 if (file == NULL)
6303 {
6304 printf (" <%s> (mtime: ?, length: ?)\n", dwarf_errmsg (-1));
6305 last_file = "";
6306 }
6307 else if (strcmp (last_file, file) != 0)
Mark Wielaard1a094202013-03-25 14:48:06 +01006308 {
6309 printf (" %s (mtime: %" PRIu64 ", length: %" PRIu64 ")\n",
6310 file, mtime, length);
6311 last_file = file;
6312 }
6313
6314 int lineno, colno;
6315 bool statement, endseq, block, prologue_end, epilogue_begin;
6316 unsigned int lineop, isa, disc;
6317 Dwarf_Addr address;
6318 dwarf_lineaddr (line, &address);
6319 dwarf_lineno (line, &lineno);
6320 dwarf_linecol (line, &colno);
6321 dwarf_lineop_index (line, &lineop);
6322 dwarf_linebeginstatement (line, &statement);
6323 dwarf_lineendsequence (line, &endseq);
6324 dwarf_lineblock (line, &block);
6325 dwarf_lineprologueend (line, &prologue_end);
6326 dwarf_lineepiloguebegin (line, &epilogue_begin);
6327 dwarf_lineisa (line, &isa);
6328 dwarf_linediscriminator (line, &disc);
6329
6330 /* End sequence is special, it is one byte past. */
6331 char *a = format_dwarf_addr (dwflmod, address_size,
6332 address - (endseq ? 1 : 0), address);
6333 printf (" %4d:%-3d %c%c%c%c%c %4d %3d %2d %s\n",
6334 lineno, colno,
6335 (statement ? 'S' : ' '),
6336 (block ? 'B' : ' '),
6337 (prologue_end ? 'P' : ' '),
6338 (epilogue_begin ? 'E' : ' '),
6339 (endseq ? '*' : ' '),
6340 disc, isa, lineop, a);
6341 free (a);
6342
6343 if (endseq)
6344 printf("\n");
6345 }
6346 }
6347}
6348
6349
6350static void
Roland McGrath725aad52011-02-23 19:52:46 -08006351print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006352 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6353{
Mark Wielaard1a094202013-03-25 14:48:06 +01006354 if (decodedline)
6355 {
6356 print_decoded_line_section (dwflmod, ebl, ehdr, scn, shdr, dbg);
6357 return;
6358 }
6359
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006360 printf (gettext ("\
Ulrich Drepper351bf202009-01-15 20:18:40 -08006361\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
Roland McGrath725aad52011-02-23 19:52:46 -08006362 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6363 (uint64_t) shdr->sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006364
6365 if (shdr->sh_size == 0)
6366 return;
6367
6368 /* There is no functionality in libdw to read the information in the
6369 way it is represented here. Hardcode the decoder. */
Mark Wielaardf7cdc742014-04-09 22:38:07 +02006370 Elf_Data *data = dbg->sectiondata[IDX_debug_line];
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006371 if (unlikely (data == NULL || data->d_buf == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006372 {
6373 error (0, 0, gettext ("cannot get line data section data: %s"),
6374 elf_errmsg (-1));
6375 return;
6376 }
6377
6378 const unsigned char *linep = (const unsigned char *) data->d_buf;
6379 const unsigned char *lineendp;
6380
6381 while (linep
6382 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
6383 {
6384 size_t start_offset = linep - (const unsigned char *) data->d_buf;
6385
6386 printf (gettext ("\nTable at offset %Zu:\n"), start_offset);
6387
Mark Wielaard9c42b782014-12-15 13:40:18 +01006388 if (unlikely (linep + 4 > lineendp))
6389 goto invalid_data;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006390 Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
6391 unsigned int length = 4;
6392 if (unlikely (unit_length == 0xffffffff))
6393 {
6394 if (unlikely (linep + 8 > lineendp))
6395 {
6396 invalid_data:
6397 error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
Roland McGrath725aad52011-02-23 19:52:46 -08006398 elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006399 return;
6400 }
6401 unit_length = read_8ubyte_unaligned_inc (dbg, linep);
6402 length = 8;
6403 }
6404
6405 /* Check whether we have enough room in the section. */
Mark Wielaardff1ce972014-12-16 16:10:28 +01006406 if (unlikely (unit_length > (size_t) (lineendp - linep)
6407 || unit_length < 2 + length + 5 * 1))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006408 goto invalid_data;
6409 lineendp = linep + unit_length;
6410
6411 /* The next element of the header is the version identifier. */
6412 uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
6413
6414 /* Next comes the header length. */
6415 Dwarf_Word header_length;
6416 if (length == 4)
6417 header_length = read_4ubyte_unaligned_inc (dbg, linep);
6418 else
6419 header_length = read_8ubyte_unaligned_inc (dbg, linep);
6420 //const unsigned char *header_start = linep;
6421
6422 /* Next the minimum instruction length. */
6423 uint_fast8_t minimum_instr_len = *linep++;
6424
Roland McGrathe5251a12010-06-20 16:59:39 -07006425 /* Next the maximum operations per instruction, in version 4 format. */
6426 uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++;
6427
Ulrich Drepper173ade82010-05-28 07:39:49 -07006428 /* Then the flag determining the default value of the is_stmt
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006429 register. */
6430 uint_fast8_t default_is_stmt = *linep++;
6431
6432 /* Now the line base. */
6433 int_fast8_t line_base = *((const int_fast8_t *) linep);
6434 ++linep;
6435
6436 /* And the line range. */
6437 uint_fast8_t line_range = *linep++;
6438
6439 /* The opcode base. */
6440 uint_fast8_t opcode_base = *linep++;
6441
6442 /* Print what we got so far. */
6443 printf (gettext ("\n"
6444 " Length: %" PRIu64 "\n"
6445 " DWARF version: %" PRIuFAST16 "\n"
6446 " Prologue length: %" PRIu64 "\n"
6447 " Minimum instruction length: %" PRIuFAST8 "\n"
Roland McGrathe5251a12010-06-20 16:59:39 -07006448 " Maximum operations per instruction: %" PRIuFAST8 "\n"
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006449 " Initial value if '%s': %" PRIuFAST8 "\n"
6450 " Line base: %" PRIdFAST8 "\n"
6451 " Line range: %" PRIuFAST8 "\n"
6452 " Opcode base: %" PRIuFAST8 "\n"
6453 "\n"
6454 "Opcodes:\n"),
6455 (uint64_t) unit_length, version, (uint64_t) header_length,
Roland McGrathe5251a12010-06-20 16:59:39 -07006456 minimum_instr_len, max_ops_per_instr,
6457 "is_stmt", default_is_stmt, line_base,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006458 line_range, opcode_base);
6459
6460 if (unlikely (linep + opcode_base - 1 >= lineendp))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006461 {
6462 invalid_unit:
6463 error (0, 0,
6464 gettext ("invalid data at offset %tu in section [%zu] '%s'"),
6465 linep - (const unsigned char *) data->d_buf,
Roland McGrath725aad52011-02-23 19:52:46 -08006466 elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006467 linep = lineendp;
6468 continue;
6469 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006470 int opcode_base_l10 = 1;
6471 unsigned int tmp = opcode_base;
6472 while (tmp > 10)
6473 {
6474 tmp /= 10;
6475 ++opcode_base_l10;
6476 }
6477 const uint8_t *standard_opcode_lengths = linep - 1;
6478 for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
6479 printf (ngettext (" [%*" PRIuFAST8 "] %hhu argument\n",
6480 " [%*" PRIuFAST8 "] %hhu arguments\n",
6481 (int) linep[cnt - 1]),
6482 opcode_base_l10, cnt, linep[cnt - 1]);
6483 linep += opcode_base - 1;
6484 if (unlikely (linep >= lineendp))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006485 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006486
6487 puts (gettext ("\nDirectory table:"));
6488 while (*linep != 0)
6489 {
6490 unsigned char *endp = memchr (linep, '\0', lineendp - linep);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006491 if (unlikely (endp == NULL))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006492 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006493
6494 printf (" %s\n", (char *) linep);
6495
6496 linep = endp + 1;
6497 }
6498 /* Skip the final NUL byte. */
6499 ++linep;
6500
6501 if (unlikely (linep >= lineendp))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006502 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006503 puts (gettext ("\nFile name table:\n"
6504 " Entry Dir Time Size Name"));
6505 for (unsigned int cnt = 1; *linep != 0; ++cnt)
6506 {
6507 /* First comes the file name. */
6508 char *fname = (char *) linep;
6509 unsigned char *endp = memchr (fname, '\0', lineendp - linep);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006510 if (unlikely (endp == NULL))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006511 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006512 linep = endp + 1;
6513
6514 /* Then the index. */
6515 unsigned int diridx;
Mark Wielaard7a053472014-12-14 21:48:23 +01006516 if (lineendp - linep < 1)
6517 goto invalid_unit;
6518 get_uleb128 (diridx, linep, lineendp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006519
6520 /* Next comes the modification time. */
6521 unsigned int mtime;
Mark Wielaard7a053472014-12-14 21:48:23 +01006522 if (lineendp - linep < 1)
6523 goto invalid_unit;
6524 get_uleb128 (mtime, linep, lineendp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006525
6526 /* Finally the length of the file. */
6527 unsigned int fsize;
Mark Wielaard7a053472014-12-14 21:48:23 +01006528 if (lineendp - linep < 1)
6529 goto invalid_unit;
6530 get_uleb128 (fsize, linep, lineendp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006531
6532 printf (" %-5u %-5u %-9u %-9u %s\n",
6533 cnt, diridx, mtime, fsize, fname);
6534 }
6535 /* Skip the final NUL byte. */
6536 ++linep;
6537
6538 puts (gettext ("\nLine number statements:"));
6539 Dwarf_Word address = 0;
Roland McGrathe5251a12010-06-20 16:59:39 -07006540 unsigned int op_index = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006541 size_t line = 1;
6542 uint_fast8_t is_stmt = default_is_stmt;
6543
6544 /* Default address value, in case we do not find the CU. */
6545 size_t address_size
6546 = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6547
6548 /* Determine the CU this block is for. */
6549 Dwarf_Off cuoffset;
6550 Dwarf_Off ncuoffset = 0;
6551 size_t hsize;
6552 while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
6553 NULL, NULL, NULL) == 0)
6554 {
6555 Dwarf_Die cudie;
6556 if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
6557 continue;
6558 Dwarf_Attribute stmt_list;
6559 if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
6560 continue;
6561 Dwarf_Word lineoff;
6562 if (dwarf_formudata (&stmt_list, &lineoff) != 0)
6563 continue;
6564 if (lineoff == start_offset)
6565 {
6566 /* Found the CU. */
6567 address_size = cudie.cu->address_size;
6568 break;
6569 }
6570 }
6571
Roland McGrathe5251a12010-06-20 16:59:39 -07006572 /* Apply the "operation advance" from a special opcode
6573 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */
6574 unsigned int op_addr_advance;
6575 bool show_op_index;
6576 inline void advance_pc (unsigned int op_advance)
6577 {
6578 op_addr_advance = minimum_instr_len * ((op_index + op_advance)
6579 / max_ops_per_instr);
6580 address += op_advance;
6581 show_op_index = (op_index > 0 ||
6582 (op_index + op_advance) % max_ops_per_instr > 0);
6583 op_index = (op_index + op_advance) % max_ops_per_instr;
6584 }
6585
Mark Wielaardf0c5ef82014-12-07 23:40:12 +01006586 if (max_ops_per_instr == 0)
6587 {
6588 error (0, 0,
6589 gettext ("invalid maximum operations per instruction is zero"));
6590 linep = lineendp;
6591 continue;
6592 }
6593
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006594 while (linep < lineendp)
6595 {
Petr Machata1879e5b2011-03-25 15:17:04 +01006596 size_t offset = linep - (const unsigned char *) data->d_buf;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006597 unsigned int u128;
6598 int s128;
6599
6600 /* Read the opcode. */
6601 unsigned int opcode = *linep++;
6602
Petr Machata1879e5b2011-03-25 15:17:04 +01006603 printf (" [%6" PRIx64 "]", (uint64_t)offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006604 /* Is this a special opcode? */
6605 if (likely (opcode >= opcode_base))
6606 {
Mark Wielaard020fc022014-11-24 21:54:42 +01006607 if (unlikely (line_range == 0))
6608 goto invalid_unit;
6609
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006610 /* Yes. Handling this is quite easy since the opcode value
6611 is computed with
6612
6613 opcode = (desired line increment - line_base)
Ulrich Drepper173ade82010-05-28 07:39:49 -07006614 + (line_range * address advance) + opcode_base
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006615 */
6616 int line_increment = (line_base
6617 + (opcode - opcode_base) % line_range);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006618
6619 /* Perform the increments. */
6620 line += line_increment;
Roland McGrathe5251a12010-06-20 16:59:39 -07006621 advance_pc ((opcode - opcode_base) / line_range);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006622
Mark Wielaard10186a12013-01-24 11:29:21 +01006623 char *a = format_dwarf_addr (dwflmod, 0, address, address);
Roland McGrathe5251a12010-06-20 16:59:39 -07006624 if (show_op_index)
6625 printf (gettext ("\
6626 special opcode %u: address+%u = %s, op_index = %u, line%+d = %zu\n"),
6627 opcode, op_addr_advance, a, op_index,
6628 line_increment, line);
6629 else
6630 printf (gettext ("\
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006631 special opcode %u: address+%u = %s, line%+d = %zu\n"),
Roland McGrathe5251a12010-06-20 16:59:39 -07006632 opcode, op_addr_advance, a, line_increment, line);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006633 free (a);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006634 }
6635 else if (opcode == 0)
6636 {
6637 /* This an extended opcode. */
6638 if (unlikely (linep + 2 > lineendp))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006639 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006640
6641 /* The length. */
6642 unsigned int len = *linep++;
6643
6644 if (unlikely (linep + len > lineendp))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006645 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006646
6647 /* The sub-opcode. */
6648 opcode = *linep++;
6649
6650 printf (gettext (" extended opcode %u: "), opcode);
6651
6652 switch (opcode)
6653 {
6654 case DW_LNE_end_sequence:
Petr Machata1879e5b2011-03-25 15:17:04 +01006655 puts (gettext (" end of sequence"));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006656
6657 /* Reset the registers we care about. */
6658 address = 0;
Roland McGrathe5251a12010-06-20 16:59:39 -07006659 op_index = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006660 line = 1;
6661 is_stmt = default_is_stmt;
6662 break;
6663
6664 case DW_LNE_set_address:
Roland McGrathe5251a12010-06-20 16:59:39 -07006665 op_index = 0;
Mark Wielaardb171ca42014-12-15 11:35:46 +01006666 if (unlikely ((size_t) (lineendp - linep) < address_size))
6667 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006668 if (address_size == 4)
6669 address = read_4ubyte_unaligned_inc (dbg, linep);
6670 else
6671 address = read_8ubyte_unaligned_inc (dbg, linep);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006672 {
Mark Wielaard10186a12013-01-24 11:29:21 +01006673 char *a = format_dwarf_addr (dwflmod, 0, address, address);
Petr Machata1879e5b2011-03-25 15:17:04 +01006674 printf (gettext (" set address to %s\n"), a);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006675 free (a);
6676 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006677 break;
6678
6679 case DW_LNE_define_file:
6680 {
6681 char *fname = (char *) linep;
6682 unsigned char *endp = memchr (linep, '\0',
6683 lineendp - linep);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006684 if (unlikely (endp == NULL))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006685 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006686 linep = endp + 1;
6687
6688 unsigned int diridx;
Mark Wielaard7a053472014-12-14 21:48:23 +01006689 if (lineendp - linep < 1)
6690 goto invalid_unit;
6691 get_uleb128 (diridx, linep, lineendp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006692 Dwarf_Word mtime;
Mark Wielaard7a053472014-12-14 21:48:23 +01006693 if (lineendp - linep < 1)
6694 goto invalid_unit;
6695 get_uleb128 (mtime, linep, lineendp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006696 Dwarf_Word filelength;
Mark Wielaard7a053472014-12-14 21:48:23 +01006697 if (lineendp - linep < 1)
6698 goto invalid_unit;
6699 get_uleb128 (filelength, linep, lineendp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006700
6701 printf (gettext ("\
Petr Machata1879e5b2011-03-25 15:17:04 +01006702 define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006703 diridx, (uint64_t) mtime, (uint64_t) filelength,
6704 fname);
6705 }
6706 break;
6707
Roland McGrathe5251a12010-06-20 16:59:39 -07006708 case DW_LNE_set_discriminator:
6709 /* Takes one ULEB128 parameter, the discriminator. */
6710 if (unlikely (standard_opcode_lengths[opcode] != 1))
6711 goto invalid_unit;
6712
Mark Wielaard7a053472014-12-14 21:48:23 +01006713 get_uleb128 (u128, linep, lineendp);
Roland McGrathe5251a12010-06-20 16:59:39 -07006714 printf (gettext (" set discriminator to %u\n"), u128);
6715 break;
6716
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006717 default:
6718 /* Unknown, ignore it. */
Petr Machata1879e5b2011-03-25 15:17:04 +01006719 puts (gettext (" unknown opcode"));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006720 linep += len - 1;
6721 break;
6722 }
6723 }
Roland McGrathe5251a12010-06-20 16:59:39 -07006724 else if (opcode <= DW_LNS_set_isa)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006725 {
6726 /* This is a known standard opcode. */
6727 switch (opcode)
6728 {
6729 case DW_LNS_copy:
6730 /* Takes no argument. */
6731 puts (gettext (" copy"));
6732 break;
6733
6734 case DW_LNS_advance_pc:
6735 /* Takes one uleb128 parameter which is added to the
6736 address. */
Mark Wielaard7a053472014-12-14 21:48:23 +01006737 get_uleb128 (u128, linep, lineendp);
Roland McGrathe5251a12010-06-20 16:59:39 -07006738 advance_pc (u128);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006739 {
Mark Wielaard10186a12013-01-24 11:29:21 +01006740 char *a = format_dwarf_addr (dwflmod, 0, address, address);
Roland McGrathe5251a12010-06-20 16:59:39 -07006741 if (show_op_index)
6742 printf (gettext ("\
Petr Machata1879e5b2011-03-25 15:17:04 +01006743 advance address by %u to %s, op_index to %u\n"),
Roland McGrathe5251a12010-06-20 16:59:39 -07006744 op_addr_advance, a, op_index);
6745 else
Petr Machata1879e5b2011-03-25 15:17:04 +01006746 printf (gettext (" advance address by %u to %s\n"),
Roland McGrathe5251a12010-06-20 16:59:39 -07006747 op_addr_advance, a);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006748 free (a);
6749 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006750 break;
6751
6752 case DW_LNS_advance_line:
6753 /* Takes one sleb128 parameter which is added to the
6754 line. */
Mark Wielaard7a053472014-12-14 21:48:23 +01006755 get_sleb128 (s128, linep, lineendp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006756 line += s128;
6757 printf (gettext ("\
6758 advance line by constant %d to %" PRId64 "\n"),
6759 s128, (int64_t) line);
6760 break;
6761
6762 case DW_LNS_set_file:
6763 /* Takes one uleb128 parameter which is stored in file. */
Mark Wielaard7a053472014-12-14 21:48:23 +01006764 get_uleb128 (u128, linep, lineendp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006765 printf (gettext (" set file to %" PRIu64 "\n"),
6766 (uint64_t) u128);
6767 break;
6768
6769 case DW_LNS_set_column:
6770 /* Takes one uleb128 parameter which is stored in column. */
6771 if (unlikely (standard_opcode_lengths[opcode] != 1))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006772 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006773
Mark Wielaard7a053472014-12-14 21:48:23 +01006774 get_uleb128 (u128, linep, lineendp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006775 printf (gettext (" set column to %" PRIu64 "\n"),
6776 (uint64_t) u128);
6777 break;
6778
6779 case DW_LNS_negate_stmt:
6780 /* Takes no argument. */
6781 is_stmt = 1 - is_stmt;
6782 printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
6783 "is_stmt", is_stmt);
6784 break;
6785
6786 case DW_LNS_set_basic_block:
6787 /* Takes no argument. */
6788 puts (gettext (" set basic block flag"));
6789 break;
6790
6791 case DW_LNS_const_add_pc:
6792 /* Takes no argument. */
Mark Wielaard020fc022014-11-24 21:54:42 +01006793
6794 if (unlikely (line_range == 0))
6795 goto invalid_unit;
6796
Roland McGrathe5251a12010-06-20 16:59:39 -07006797 advance_pc ((255 - opcode_base) / line_range);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006798 {
Mark Wielaard10186a12013-01-24 11:29:21 +01006799 char *a = format_dwarf_addr (dwflmod, 0, address, address);
Roland McGrathe5251a12010-06-20 16:59:39 -07006800 if (show_op_index)
6801 printf (gettext ("\
Petr Machata1879e5b2011-03-25 15:17:04 +01006802 advance address by constant %u to %s, op_index to %u\n"),
Roland McGrathe5251a12010-06-20 16:59:39 -07006803 op_addr_advance, a, op_index);
6804 else
6805 printf (gettext ("\
Petr Machata1879e5b2011-03-25 15:17:04 +01006806 advance address by constant %u to %s\n"),
Roland McGrathe5251a12010-06-20 16:59:39 -07006807 op_addr_advance, a);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006808 free (a);
6809 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006810 break;
6811
6812 case DW_LNS_fixed_advance_pc:
6813 /* Takes one 16 bit parameter which is added to the
6814 address. */
6815 if (unlikely (standard_opcode_lengths[opcode] != 1))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006816 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006817
6818 u128 = read_2ubyte_unaligned_inc (dbg, linep);
6819 address += u128;
Roland McGrathe5251a12010-06-20 16:59:39 -07006820 op_index = 0;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006821 {
Mark Wielaard10186a12013-01-24 11:29:21 +01006822 char *a = format_dwarf_addr (dwflmod, 0, address, address);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006823 printf (gettext ("\
Petr Machata1879e5b2011-03-25 15:17:04 +01006824 advance address by fixed value %u to %s\n"),
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006825 u128, a);
6826 free (a);
6827 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006828 break;
6829
6830 case DW_LNS_set_prologue_end:
6831 /* Takes no argument. */
6832 puts (gettext (" set prologue end flag"));
6833 break;
6834
Ulrich Drepper6d5c3bd2005-08-11 04:37:52 +00006835 case DW_LNS_set_epilogue_begin:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006836 /* Takes no argument. */
6837 puts (gettext (" set epilogue begin flag"));
6838 break;
Roland McGrathe5251a12010-06-20 16:59:39 -07006839
6840 case DW_LNS_set_isa:
6841 /* Takes one uleb128 parameter which is stored in isa. */
6842 if (unlikely (standard_opcode_lengths[opcode] != 1))
6843 goto invalid_unit;
6844
Mark Wielaard7a053472014-12-14 21:48:23 +01006845 get_uleb128 (u128, linep, lineendp);
Roland McGrathe5251a12010-06-20 16:59:39 -07006846 printf (gettext (" set isa to %u\n"), u128);
6847 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006848 }
6849 }
6850 else
6851 {
6852 /* This is a new opcode the generator but not we know about.
6853 Read the parameters associated with it but then discard
6854 everything. Read all the parameters for this opcode. */
6855 printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
6856 " unknown opcode with %" PRIu8 " parameters:",
6857 standard_opcode_lengths[opcode]),
6858 standard_opcode_lengths[opcode]);
6859 for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
6860 {
Mark Wielaard7a053472014-12-14 21:48:23 +01006861 get_uleb128 (u128, linep, lineendp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006862 if (n != standard_opcode_lengths[opcode])
6863 putc_unlocked (',', stdout);
6864 printf (" %u", u128);
6865 }
6866
6867 /* Next round, ignore this opcode. */
6868 continue;
6869 }
6870 }
6871 }
6872
6873 /* There must only be one data block. */
6874 assert (elf_getdata (scn, data) == NULL);
6875}
6876
6877
6878static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006879print_debug_loc_section (Dwfl_Module *dwflmod,
Roland McGrath725aad52011-02-23 19:52:46 -08006880 Ebl *ebl, GElf_Ehdr *ehdr,
Ulrich Drepper351bf202009-01-15 20:18:40 -08006881 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006882{
Mark Wielaardf7cdc742014-04-09 22:38:07 +02006883 Elf_Data *data = dbg->sectiondata[IDX_debug_loc];
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006884
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006885 if (unlikely (data == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006886 {
6887 error (0, 0, gettext ("cannot get .debug_loc content: %s"),
6888 elf_errmsg (-1));
6889 return;
6890 }
6891
6892 printf (gettext ("\
Ulrich Drepper351bf202009-01-15 20:18:40 -08006893\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
Roland McGrath725aad52011-02-23 19:52:46 -08006894 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6895 (uint64_t) shdr->sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006896
Roland McGrathfa144952010-08-30 19:22:41 -07006897 sort_listptr (&known_loclistptr, "loclistptr");
6898 size_t listptr_idx = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006899
Roland McGrathfa144952010-08-30 19:22:41 -07006900 uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6901 uint_fast8_t offset_size = 4;
Roland McGrath688f7fc2010-05-08 03:22:59 -07006902
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006903 bool first = true;
Mark Wielaard35230222013-07-05 16:44:47 +02006904 struct Dwarf_CU *cu = NULL;
Mark Wielaard24257102013-01-18 22:19:08 +01006905 Dwarf_Addr base = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006906 unsigned char *readp = data->d_buf;
Roland McGratha1599152010-08-30 04:04:37 -07006907 unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
6908 while (readp < endp)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006909 {
6910 ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
6911
Roland McGrathfa144952010-08-30 19:22:41 -07006912 if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx,
Mark Wielaard24257102013-01-18 22:19:08 +01006913 &address_size, &offset_size, &base,
Mark Wielaard35230222013-07-05 16:44:47 +02006914 &cu, offset, &readp, endp))
Roland McGrathfa144952010-08-30 19:22:41 -07006915 continue;
6916
Mark Wielaardbe860842013-11-05 13:37:33 +01006917 if (unlikely (data->d_size - offset < (size_t) address_size * 2))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006918 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006919 printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006920 break;
6921 }
6922
6923 Dwarf_Addr begin;
6924 Dwarf_Addr end;
6925 if (address_size == 8)
6926 {
6927 begin = read_8ubyte_unaligned_inc (dbg, readp);
6928 end = read_8ubyte_unaligned_inc (dbg, readp);
6929 }
6930 else
6931 {
6932 begin = read_4ubyte_unaligned_inc (dbg, readp);
6933 end = read_4ubyte_unaligned_inc (dbg, readp);
6934 if (begin == (Dwarf_Addr) (uint32_t) -1)
6935 begin = (Dwarf_Addr) -1l;
6936 }
6937
6938 if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006939 {
Mark Wielaard10186a12013-01-24 11:29:21 +01006940 char *b = format_dwarf_addr (dwflmod, address_size, end, end);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006941 printf (gettext (" [%6tx] base address %s\n"), offset, b);
6942 free (b);
Mark Wielaard24257102013-01-18 22:19:08 +01006943 base = end;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006944 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006945 else if (begin == 0 && end == 0) /* End of list entry. */
Roland McGrathfa144952010-08-30 19:22:41 -07006946 {
6947 if (first)
6948 printf (gettext (" [%6tx] empty list\n"), offset);
6949 first = true;
6950 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006951 else
6952 {
6953 /* We have a location expression entry. */
6954 uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
6955
Mark Wielaard10186a12013-01-24 11:29:21 +01006956 char *b = format_dwarf_addr (dwflmod, address_size, base + begin,
6957 begin);
6958 char *e = format_dwarf_addr (dwflmod, address_size, base + end,
6959 end);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006960
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006961 if (first) /* First entry in a list. */
6962 printf (gettext (" [%6tx] %s..%s"), offset, b, e);
6963 else
6964 printf (gettext (" %s..%s"), b, e);
6965
6966 free (b);
6967 free (e);
6968
Roland McGratha1599152010-08-30 04:04:37 -07006969 if (endp - readp <= (ptrdiff_t) len)
6970 {
6971 fputs (gettext (" <INVALID DATA>\n"), stdout);
6972 break;
6973 }
6974
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006975 print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
Mark Wielaard35230222013-07-05 16:44:47 +02006976 3 /*XXX*/, address_size, offset_size, cu, len, readp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006977
6978 first = false;
6979 readp += len;
6980 }
6981 }
6982}
6983
6984struct mac_culist
6985{
6986 Dwarf_Die die;
6987 Dwarf_Off offset;
6988 Dwarf_Files *files;
6989 struct mac_culist *next;
6990};
6991
6992
6993static int
6994mac_compare (const void *p1, const void *p2)
6995{
6996 struct mac_culist *m1 = (struct mac_culist *) p1;
6997 struct mac_culist *m2 = (struct mac_culist *) p2;
6998
6999 if (m1->offset < m2->offset)
7000 return -1;
7001 if (m1->offset > m2->offset)
7002 return 1;
7003 return 0;
7004}
7005
7006
7007static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00007008print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Roland McGrath725aad52011-02-23 19:52:46 -08007009 Ebl *ebl, GElf_Ehdr *ehdr,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007010 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7011{
7012 printf (gettext ("\
Ulrich Drepper351bf202009-01-15 20:18:40 -08007013\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
Roland McGrath725aad52011-02-23 19:52:46 -08007014 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7015 (uint64_t) shdr->sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007016 putc_unlocked ('\n', stdout);
7017
7018 /* There is no function in libdw to iterate over the raw content of
7019 the section but it is easy enough to do. */
Mark Wielaardf7cdc742014-04-09 22:38:07 +02007020 Elf_Data *data = dbg->sectiondata[IDX_debug_macinfo];
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00007021 if (unlikely (data == NULL || data->d_buf == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007022 {
7023 error (0, 0, gettext ("cannot get macro information section data: %s"),
7024 elf_errmsg (-1));
7025 return;
7026 }
7027
7028 /* Get the source file information for all CUs. */
7029 Dwarf_Off offset;
7030 Dwarf_Off ncu = 0;
7031 size_t hsize;
7032 struct mac_culist *culist = NULL;
7033 size_t nculist = 0;
7034 while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
7035 {
7036 Dwarf_Die cudie;
7037 if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
7038 continue;
7039
7040 Dwarf_Attribute attr;
7041 if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
7042 continue;
7043
7044 Dwarf_Word macoff;
7045 if (dwarf_formudata (&attr, &macoff) != 0)
7046 continue;
7047
7048 struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
7049 newp->die = cudie;
7050 newp->offset = macoff;
7051 newp->files = NULL;
7052 newp->next = culist;
7053 culist = newp;
7054 ++nculist;
7055 }
7056
7057 /* Convert the list into an array for easier consumption. */
7058 struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
7059 * sizeof (*cus));
7060 /* Add sentinel. */
7061 cus[nculist].offset = data->d_size;
Mark Wielaard8f2f5802014-12-21 23:02:12 +01007062 cus[nculist].files = (Dwarf_Files *) -1l;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007063 if (nculist > 0)
7064 {
7065 for (size_t cnt = nculist - 1; culist != NULL; --cnt)
7066 {
7067 assert (cnt < nculist);
7068 cus[cnt] = *culist;
7069 culist = culist->next;
7070 }
7071
7072 /* Sort the array according to the offset in the .debug_macinfo
7073 section. Note we keep the sentinel at the end. */
7074 qsort (cus, nculist, sizeof (*cus), mac_compare);
7075 }
7076
7077 const unsigned char *readp = (const unsigned char *) data->d_buf;
7078 const unsigned char *readendp = readp + data->d_size;
7079 int level = 1;
7080
7081 while (readp < readendp)
7082 {
7083 unsigned int opcode = *readp++;
7084 unsigned int u128;
7085 unsigned int u128_2;
7086 const unsigned char *endp;
7087
7088 switch (opcode)
7089 {
7090 case DW_MACINFO_define:
7091 case DW_MACINFO_undef:
7092 case DW_MACINFO_vendor_ext:
7093 /* For the first two opcodes the parameters are
Ulrich Drepper173ade82010-05-28 07:39:49 -07007094 line, string
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007095 For the latter
Ulrich Drepper173ade82010-05-28 07:39:49 -07007096 number, string.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007097 We can treat these cases together. */
Mark Wielaard7a053472014-12-14 21:48:23 +01007098 get_uleb128 (u128, readp, readendp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007099
7100 endp = memchr (readp, '\0', readendp - readp);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00007101 if (unlikely (endp == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007102 {
7103 printf (gettext ("\
7104%*s*** non-terminated string at end of section"),
7105 level, "");
7106 return;
7107 }
7108
7109 if (opcode == DW_MACINFO_define)
7110 printf ("%*s#define %s, line %u\n",
7111 level, "", (char *) readp, u128);
7112 else if (opcode == DW_MACINFO_undef)
7113 printf ("%*s#undef %s, line %u\n",
7114 level, "", (char *) readp, u128);
7115 else
7116 printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
7117
7118 readp = endp + 1;
7119 break;
7120
7121 case DW_MACINFO_start_file:
7122 /* The two parameters are line and file index, in this order. */
Mark Wielaard7a053472014-12-14 21:48:23 +01007123 get_uleb128 (u128, readp, readendp);
7124 if (readendp - readp < 1)
7125 {
7126 printf (gettext ("\
7127%*s*** missing DW_MACINFO_start_file argument at end of section"),
7128 level, "");
7129 return;
7130 }
7131 get_uleb128 (u128_2, readp, readendp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007132
7133 /* Find the CU DIE for this file. */
7134 size_t macoff = readp - (const unsigned char *) data->d_buf;
7135 const char *fname = "???";
7136 if (macoff >= cus[0].offset)
7137 {
Mark Wielaard8f2f5802014-12-21 23:02:12 +01007138 while (macoff >= cus[1].offset && cus[1].offset != data->d_size)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007139 ++cus;
7140
7141 if (cus[0].files == NULL
7142 && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
7143 cus[0].files = (Dwarf_Files *) -1l;
7144
7145 if (cus[0].files != (Dwarf_Files *) -1l)
7146 fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
7147 ?: "???");
7148 }
7149
7150 printf ("%*sstart_file %u, [%u] %s\n",
7151 level, "", u128, u128_2, fname);
7152 ++level;
7153 break;
7154
7155 case DW_MACINFO_end_file:
7156 --level;
7157 printf ("%*send_file\n", level, "");
7158 /* Nothing more to do. */
7159 break;
7160
7161 default:
7162 // XXX gcc seems to generate files with a trailing zero.
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00007163 if (unlikely (opcode != 0 || readp != readendp))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007164 printf ("%*s*** invalid opcode %u\n", level, "", opcode);
7165 break;
7166 }
7167 }
7168}
7169
7170
Mark Wielaarde9b23882012-06-29 22:30:15 +02007171static void
7172print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
7173 Ebl *ebl, GElf_Ehdr *ehdr,
7174 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7175{
7176 printf (gettext ("\
7177\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
7178 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7179 (uint64_t) shdr->sh_offset);
7180 putc_unlocked ('\n', stdout);
7181
Mark Wielaardf7cdc742014-04-09 22:38:07 +02007182 Elf_Data *data = dbg->sectiondata[IDX_debug_macro];
Mark Wielaarde9b23882012-06-29 22:30:15 +02007183 if (unlikely (data == NULL || data->d_buf == NULL))
7184 {
7185 error (0, 0, gettext ("cannot get macro information section data: %s"),
7186 elf_errmsg (-1));
7187 return;
7188 }
7189
7190 /* Get the source file information for all CUs. Uses same
7191 datastructure as macinfo. But uses offset field to directly
7192 match .debug_line offset. And just stored in a list. */
7193 Dwarf_Off offset;
7194 Dwarf_Off ncu = 0;
7195 size_t hsize;
7196 struct mac_culist *culist = NULL;
7197 size_t nculist = 0;
7198 while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
7199 {
7200 Dwarf_Die cudie;
7201 if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
7202 continue;
7203
7204 Dwarf_Attribute attr;
7205 if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL)
7206 continue;
7207
7208 Dwarf_Word lineoff;
7209 if (dwarf_formudata (&attr, &lineoff) != 0)
7210 continue;
7211
7212 struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
7213 newp->die = cudie;
7214 newp->offset = lineoff;
7215 newp->files = NULL;
7216 newp->next = culist;
7217 culist = newp;
7218 ++nculist;
7219 }
7220
7221 const unsigned char *readp = (const unsigned char *) data->d_buf;
7222 const unsigned char *readendp = readp + data->d_size;
7223
7224 while (readp < readendp)
7225 {
Mark Wielaard3e440062012-08-27 15:21:58 +02007226 printf (gettext (" Offset: 0x%" PRIx64 "\n"),
7227 (uint64_t) (readp - (const unsigned char *) data->d_buf));
Mark Wielaarde9b23882012-06-29 22:30:15 +02007228
7229 // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
7230 // optional vendor extension macro entry table.
7231 if (readp + 2 > readendp)
7232 {
7233 invalid_data:
7234 error (0, 0, gettext ("invalid data"));
7235 return;
7236 }
7237 const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
7238 printf (gettext (" Version: %" PRIu16 "\n"), vers);
7239
7240 // Version 4 is the GNU extension for DWARF4. DWARF5 will use version
7241 // 5 when it gets standardized.
7242 if (vers != 4)
7243 {
7244 printf (gettext (" unknown version, cannot parse section\n"));
7245 return;
7246 }
7247
7248 if (readp + 1 > readendp)
7249 goto invalid_data;
7250 const unsigned char flag = *readp++;
7251 printf (gettext (" Flag: 0x%" PRIx8 "\n"), flag);
7252
7253 unsigned int offset_len = (flag & 0x01) ? 8 : 4;
7254 printf (gettext (" Offset length: %" PRIu8 "\n"), offset_len);
7255 Dwarf_Off line_offset = -1;
7256 if (flag & 0x02)
7257 {
7258 if (offset_len == 8)
7259 line_offset = read_8ubyte_unaligned_inc (dbg, readp);
7260 else
7261 line_offset = read_4ubyte_unaligned_inc (dbg, readp);
7262 printf (gettext (" .debug_line offset: 0x%" PRIx64 "\n"),
7263 line_offset);
7264 }
7265
7266 const unsigned char *vendor[DW_MACRO_GNU_hi_user - DW_MACRO_GNU_lo_user];
Mark Wielaard04781c32014-01-14 22:13:43 +01007267 memset (vendor, 0, sizeof vendor);
Mark Wielaarde9b23882012-06-29 22:30:15 +02007268 if (flag & 0x04)
7269 {
7270 // 1 byte length, for each item, 1 byte opcode, uleb128 number
7271 // of arguments, for each argument 1 byte form code.
7272 if (readp + 1 > readendp)
7273 goto invalid_data;
7274 unsigned int tlen = *readp++;
7275 printf (gettext (" extension opcode table, %" PRIu8 " items:\n"),
7276 tlen);
7277 for (unsigned int i = 0; i < tlen; i++)
7278 {
7279 if (readp + 1 > readendp)
7280 goto invalid_data;
7281 unsigned int opcode = *readp++;
7282 printf (gettext (" [%" PRIx8 "]"), opcode);
7283 if (opcode < DW_MACRO_GNU_lo_user
7284 || opcode > DW_MACRO_GNU_hi_user)
7285 goto invalid_data;
7286 // Record the start of description for this vendor opcode.
7287 // uleb128 nr args, 1 byte per arg form.
7288 vendor[opcode - DW_MACRO_GNU_lo_user] = readp;
7289 if (readp + 1 > readendp)
7290 goto invalid_data;
7291 unsigned int args = *readp++;
7292 if (args > 0)
7293 {
7294 printf (gettext (" %" PRIu8 " arguments:"), args);
7295 while (args > 0)
7296 {
7297 if (readp + 1 > readendp)
7298 goto invalid_data;
7299 unsigned int form = *readp++;
7300 printf (" %s", dwarf_form_string (form));
7301 if (form != DW_FORM_data1
7302 && form != DW_FORM_data2
7303 && form != DW_FORM_data4
7304 && form != DW_FORM_data8
7305 && form != DW_FORM_sdata
7306 && form != DW_FORM_udata
7307 && form != DW_FORM_block
7308 && form != DW_FORM_block1
7309 && form != DW_FORM_block2
7310 && form != DW_FORM_block4
7311 && form != DW_FORM_flag
7312 && form != DW_FORM_string
7313 && form != DW_FORM_strp
7314 && form != DW_FORM_sec_offset)
7315 goto invalid_data;
7316 args--;
7317 if (args > 0)
7318 putchar_unlocked (',');
7319 }
7320 }
7321 else
7322 printf (gettext (" no arguments."));
7323 putchar_unlocked ('\n');
7324 }
7325 }
7326 putchar_unlocked ('\n');
7327
7328 int level = 1;
7329 if (readp + 1 > readendp)
7330 goto invalid_data;
7331 unsigned int opcode = *readp++;
7332 while (opcode != 0)
7333 {
7334 unsigned int u128;
7335 unsigned int u128_2;
7336 const unsigned char *endp;
7337 uint64_t off;
7338
7339 switch (opcode)
7340 {
7341 case DW_MACRO_GNU_start_file:
Mark Wielaard7a053472014-12-14 21:48:23 +01007342 get_uleb128 (u128, readp, readendp);
7343 if (readp >= readendp)
7344 goto invalid_data;
7345 get_uleb128 (u128_2, readp, readendp);
Mark Wielaarde9b23882012-06-29 22:30:15 +02007346
7347 /* Find the CU DIE that matches this line offset. */
7348 const char *fname = "???";
7349 if (line_offset != (Dwarf_Off) -1)
7350 {
7351 struct mac_culist *cu = culist;
7352 while (cu != NULL && line_offset != cu->offset)
7353 cu = cu->next;
7354 if (cu != NULL)
7355 {
7356 if (cu->files == NULL
7357 && dwarf_getsrcfiles (&cu->die, &cu->files,
7358 NULL) != 0)
7359 cu->files = (Dwarf_Files *) -1l;
7360
7361 if (cu->files != (Dwarf_Files *) -1l)
7362 fname = (dwarf_filesrc (cu->files, u128_2,
7363 NULL, NULL) ?: "???");
7364 }
7365 }
7366 printf ("%*sstart_file %u, [%u] %s\n",
7367 level, "", u128, u128_2, fname);
7368 ++level;
7369 break;
7370
7371 case DW_MACRO_GNU_end_file:
7372 --level;
7373 printf ("%*send_file\n", level, "");
7374 break;
7375
7376 case DW_MACRO_GNU_define:
Mark Wielaard7a053472014-12-14 21:48:23 +01007377 get_uleb128 (u128, readp, readendp);
Mark Wielaarde9b23882012-06-29 22:30:15 +02007378 endp = memchr (readp, '\0', readendp - readp);
7379 if (endp == NULL)
7380 goto invalid_data;
7381 printf ("%*s#define %s, line %u\n",
7382 level, "", readp, u128);
7383 readp = endp + 1;
7384 break;
7385
7386 case DW_MACRO_GNU_undef:
Mark Wielaard7a053472014-12-14 21:48:23 +01007387 get_uleb128 (u128, readp, readendp);
Mark Wielaarde9b23882012-06-29 22:30:15 +02007388 endp = memchr (readp, '\0', readendp - readp);
7389 if (endp == NULL)
7390 goto invalid_data;
7391 printf ("%*s#undef %s, line %u\n",
7392 level, "", readp, u128);
7393 readp = endp + 1;
7394 break;
7395
7396 case DW_MACRO_GNU_define_indirect:
Mark Wielaard7a053472014-12-14 21:48:23 +01007397 get_uleb128 (u128, readp, readendp);
Mark Wielaarde9b23882012-06-29 22:30:15 +02007398 if (readp + offset_len > readendp)
7399 goto invalid_data;
7400 if (offset_len == 8)
7401 off = read_8ubyte_unaligned_inc (dbg, readp);
7402 else
7403 off = read_4ubyte_unaligned_inc (dbg, readp);
7404 printf ("%*s#define %s, line %u (indirect)\n",
7405 level, "", dwarf_getstring (dbg, off, NULL), u128);
7406 break;
7407
7408 case DW_MACRO_GNU_undef_indirect:
Mark Wielaard7a053472014-12-14 21:48:23 +01007409 get_uleb128 (u128, readp, readendp);
Mark Wielaarde9b23882012-06-29 22:30:15 +02007410 if (readp + offset_len > readendp)
7411 goto invalid_data;
7412 if (offset_len == 8)
7413 off = read_8ubyte_unaligned_inc (dbg, readp);
7414 else
7415 off = read_4ubyte_unaligned_inc (dbg, readp);
7416 printf ("%*s#undef %s, line %u (indirect)\n",
7417 level, "", dwarf_getstring (dbg, off, NULL), u128);
7418 break;
7419
7420 case DW_MACRO_GNU_transparent_include:
7421 if (readp + offset_len > readendp)
7422 goto invalid_data;
7423 if (offset_len == 8)
7424 off = read_8ubyte_unaligned_inc (dbg, readp);
7425 else
7426 off = read_4ubyte_unaligned_inc (dbg, readp);
7427 printf ("%*s#include offset 0x%" PRIx64 "\n",
7428 level, "", off);
7429 break;
7430
7431 default:
7432 printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
7433 if (opcode < DW_MACRO_GNU_lo_user
7434 || opcode > DW_MACRO_GNU_lo_user
7435 || vendor[opcode - DW_MACRO_GNU_lo_user] == NULL)
7436 goto invalid_data;
7437
7438 const unsigned char *op_desc;
7439 op_desc = vendor[opcode - DW_MACRO_GNU_lo_user];
7440
7441 // Just skip the arguments, we cannot really interpret them,
7442 // but print as much as we can.
7443 unsigned int args = *op_desc++;
7444 while (args > 0)
7445 {
7446 unsigned int form = *op_desc++;
7447 Dwarf_Word val;
7448 switch (form)
7449 {
7450 case DW_FORM_data1:
7451 if (readp + 1 > readendp)
7452 goto invalid_data;
7453 val = *readp++;
7454 printf (" %" PRIx8, (unsigned int) val);
7455 break;
7456
7457 case DW_FORM_data2:
7458 if (readp + 2 > readendp)
7459 goto invalid_data;
7460 val = read_2ubyte_unaligned_inc (dbg, readp);
7461 printf(" %" PRIx16, (unsigned int) val);
7462 break;
7463
7464 case DW_FORM_data4:
7465 if (readp + 4 > readendp)
7466 goto invalid_data;
7467 val = read_4ubyte_unaligned_inc (dbg, readp);
7468 printf (" %" PRIx32, (unsigned int) val);
7469 break;
7470
7471 case DW_FORM_data8:
7472 if (readp + 8 > readendp)
7473 goto invalid_data;
7474 val = read_8ubyte_unaligned_inc (dbg, readp);
7475 printf (" %" PRIx64, val);
7476 break;
7477
7478 case DW_FORM_sdata:
Mark Wielaard7a053472014-12-14 21:48:23 +01007479 get_sleb128 (val, readp, readendp);
Mark Wielaarde9b23882012-06-29 22:30:15 +02007480 printf (" %" PRIx64, val);
7481 break;
7482
7483 case DW_FORM_udata:
Mark Wielaard7a053472014-12-14 21:48:23 +01007484 get_uleb128 (val, readp, readendp);
Mark Wielaarde9b23882012-06-29 22:30:15 +02007485 printf (" %" PRIx64, val);
7486 break;
7487
7488 case DW_FORM_block:
Mark Wielaard7a053472014-12-14 21:48:23 +01007489 get_uleb128 (val, readp, readendp);
Mark Wielaarde9b23882012-06-29 22:30:15 +02007490 printf (" block[%" PRIu64 "]", val);
7491 if (readp + val > readendp)
7492 goto invalid_data;
7493 readp += val;
7494 break;
7495
7496 case DW_FORM_block1:
7497 if (readp + 1 > readendp)
7498 goto invalid_data;
7499 val = *readp++;
7500 printf (" block[%" PRIu64 "]", val);
7501 if (readp + val > readendp)
7502 goto invalid_data;
7503 break;
7504
7505 case DW_FORM_block2:
7506 if (readp + 2 > readendp)
7507 goto invalid_data;
7508 val = read_2ubyte_unaligned_inc (dbg, readp);
7509 printf (" block[%" PRIu64 "]", val);
7510 if (readp + val > readendp)
7511 goto invalid_data;
7512 break;
7513
7514 case DW_FORM_block4:
7515 if (readp + 2 > readendp)
7516 goto invalid_data;
7517 val =read_4ubyte_unaligned_inc (dbg, readp);
7518 printf (" block[%" PRIu64 "]", val);
7519 if (readp + val > readendp)
7520 goto invalid_data;
7521 break;
7522
7523 case DW_FORM_flag:
7524 if (readp + 1 > readendp)
7525 goto invalid_data;
7526 val = *readp++;
7527 printf (" %s", nl_langinfo (val != 0 ? YESSTR : NOSTR));
7528 break;
7529
7530 case DW_FORM_string:
7531 endp = memchr (readp, '\0', readendp - readp);
7532 if (endp == NULL)
7533 goto invalid_data;
7534 printf (" %s", readp);
7535 readp = endp + 1;
7536 break;
7537
7538 case DW_FORM_strp:
7539 if (readp + offset_len > readendp)
7540 goto invalid_data;
7541 if (offset_len == 8)
7542 val = read_8ubyte_unaligned_inc (dbg, readp);
7543 else
7544 val = read_4ubyte_unaligned_inc (dbg, readp);
7545 printf (" %s", dwarf_getstring (dbg, val, NULL));
7546 break;
7547
7548 case DW_FORM_sec_offset:
7549 if (readp + offset_len > readendp)
7550 goto invalid_data;
7551 if (offset_len == 8)
7552 val = read_8ubyte_unaligned_inc (dbg, readp);
7553 else
7554 val = read_4ubyte_unaligned_inc (dbg, readp);
7555 printf (" %" PRIx64, val);
7556 break;
7557
7558 default:
7559 error (0, 0, gettext ("vendor opcode not verified?"));
7560 return;
7561 }
7562
7563 args--;
7564 if (args > 0)
7565 putchar_unlocked (',');
7566 }
7567 putchar_unlocked ('\n');
7568 }
7569
7570 if (readp + 1 > readendp)
7571 goto invalid_data;
7572 opcode = *readp++;
7573 if (opcode == 0)
7574 putchar_unlocked ('\n');
7575 }
7576 }
7577}
7578
7579
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007580/* Callback for printing global names. */
7581static int
7582print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
7583 void *arg)
7584{
7585 int *np = (int *) arg;
7586
7587 printf (gettext (" [%5d] DIE offset: %6" PRId64
7588 ", CU DIE offset: %6" PRId64 ", name: %s\n"),
7589 (*np)++, global->die_offset, global->cu_offset, global->name);
7590
7591 return 0;
7592}
7593
7594
7595/* Print the known exported symbols in the DWARF section '.debug_pubnames'. */
7596static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00007597print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Roland McGrath725aad52011-02-23 19:52:46 -08007598 Ebl *ebl, GElf_Ehdr *ehdr,
Ulrich Drepper351bf202009-01-15 20:18:40 -08007599 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007600{
Ulrich Drepper351bf202009-01-15 20:18:40 -08007601 printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
Roland McGrath725aad52011-02-23 19:52:46 -08007602 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7603 (uint64_t) shdr->sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007604
7605 int n = 0;
7606 (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
7607}
7608
7609/* Print the content of the DWARF string section '.debug_str'. */
7610static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00007611print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Roland McGrath725aad52011-02-23 19:52:46 -08007612 Ebl *ebl, GElf_Ehdr *ehdr,
Ulrich Drepper351bf202009-01-15 20:18:40 -08007613 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007614{
Mark Wielaard61651c12012-03-28 11:20:36 +02007615 const size_t sh_size = (dbg->sectiondata[IDX_debug_str] ?
7616 dbg->sectiondata[IDX_debug_str]->d_size : 0);
Roland McGrath725aad52011-02-23 19:52:46 -08007617
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007618 /* Compute floor(log16(shdr->sh_size)). */
Roland McGrath725aad52011-02-23 19:52:46 -08007619 GElf_Addr tmp = sh_size;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007620 int digits = 1;
7621 while (tmp >= 16)
7622 {
7623 ++digits;
7624 tmp >>= 4;
7625 }
7626 digits = MAX (4, digits);
7627
Ulrich Drepper351bf202009-01-15 20:18:40 -08007628 printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007629 " %*s String\n"),
Ulrich Drepper351bf202009-01-15 20:18:40 -08007630 elf_ndxscn (scn),
Roland McGrath725aad52011-02-23 19:52:46 -08007631 section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007632 /* TRANS: the debugstr| prefix makes the string unique. */
7633 digits + 2, sgettext ("debugstr|Offset"));
7634
7635 Dwarf_Off offset = 0;
Roland McGrath725aad52011-02-23 19:52:46 -08007636 while (offset < sh_size)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007637 {
7638 size_t len;
7639 const char *str = dwarf_getstring (dbg, offset, &len);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00007640 if (unlikely (str == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007641 {
7642 printf (gettext (" *** error while reading strings: %s\n"),
7643 dwarf_errmsg (-1));
7644 break;
7645 }
7646
7647 printf (" [%*" PRIx64 "] \"%s\"\n", digits, (uint64_t) offset, str);
7648
7649 offset += len + 1;
7650 }
7651}
7652
Ulrich Drepper351bf202009-01-15 20:18:40 -08007653
Ulrich Drepper351bf202009-01-15 20:18:40 -08007654/* Print the content of the call frame search table section
7655 '.eh_frame_hdr'. */
7656static void
7657print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
7658 Ebl *ebl __attribute__ ((unused)),
7659 GElf_Ehdr *ehdr __attribute__ ((unused)),
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08007660 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
Ulrich Drepper351bf202009-01-15 20:18:40 -08007661{
7662 printf (gettext ("\
7663\nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
7664 elf_ndxscn (scn));
7665
7666 Elf_Data *data = elf_rawdata (scn, NULL);
7667
7668 if (unlikely (data == NULL))
7669 {
7670 error (0, 0, gettext ("cannot get %s content: %s"),
7671 ".eh_frame_hdr", elf_errmsg (-1));
7672 return;
7673 }
7674
7675 const unsigned char *readp = data->d_buf;
7676 const unsigned char *const dataend = ((unsigned char *) data->d_buf
7677 + data->d_size);
7678
7679 if (unlikely (readp + 4 > dataend))
7680 {
7681 invalid_data:
7682 error (0, 0, gettext ("invalid data"));
7683 return;
7684 }
7685
7686 unsigned int version = *readp++;
7687 unsigned int eh_frame_ptr_enc = *readp++;
7688 unsigned int fde_count_enc = *readp++;
7689 unsigned int table_enc = *readp++;
7690
7691 printf (" version: %u\n"
7692 " eh_frame_ptr_enc: %#x ",
7693 version, eh_frame_ptr_enc);
Ulrich Drepperbc298972009-01-16 11:50:10 -08007694 print_encoding_base ("", eh_frame_ptr_enc);
Ulrich Drepper351bf202009-01-15 20:18:40 -08007695 printf (" fde_count_enc: %#x ", fde_count_enc);
Ulrich Drepperbc298972009-01-16 11:50:10 -08007696 print_encoding_base ("", fde_count_enc);
Ulrich Drepper351bf202009-01-15 20:18:40 -08007697 printf (" table_enc: %#x ", table_enc);
Ulrich Drepperbc298972009-01-16 11:50:10 -08007698 print_encoding_base ("", table_enc);
Ulrich Drepper351bf202009-01-15 20:18:40 -08007699
7700 uint64_t eh_frame_ptr = 0;
7701 if (eh_frame_ptr_enc != DW_EH_PE_omit)
7702 {
7703 readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
7704 dbg);
7705 if (unlikely (readp == NULL))
7706 goto invalid_data;
7707
7708 printf (" eh_frame_ptr: %#" PRIx64, eh_frame_ptr);
7709 if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
7710 printf (" (offset: %#" PRIx64 ")",
7711 /* +4 because of the 4 byte header of the section. */
7712 (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
7713
7714 putchar_unlocked ('\n');
7715 }
7716
7717 uint64_t fde_count = 0;
7718 if (fde_count_enc != DW_EH_PE_omit)
7719 {
7720 readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
7721 if (unlikely (readp == NULL))
7722 goto invalid_data;
7723
7724 printf (" fde_count: %" PRIu64 "\n", fde_count);
7725 }
7726
7727 if (fde_count == 0 || table_enc == DW_EH_PE_omit)
7728 return;
7729
7730 puts (" Table:");
7731
7732 /* Optimize for the most common case. */
7733 if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
7734 while (fde_count > 0 && readp + 8 <= dataend)
7735 {
7736 int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
7737 uint64_t initial_offset = ((uint64_t) shdr->sh_offset
7738 + (int64_t) initial_location);
7739 int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
7740 // XXX Possibly print symbol name or section offset for initial_offset
7741 printf (" %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
7742 " fde=[%6" PRIx64 "]\n",
7743 initial_location, initial_offset,
7744 address, address - (eh_frame_ptr + 4));
7745 }
7746 else
7747 while (0 && readp < dataend)
7748 {
7749
7750 }
7751}
7752
7753
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08007754/* Print the content of the exception handling table section
7755 '.eh_frame_hdr'. */
7756static void
7757print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
7758 Ebl *ebl __attribute__ ((unused)),
7759 GElf_Ehdr *ehdr __attribute__ ((unused)),
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007760 Elf_Scn *scn,
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08007761 GElf_Shdr *shdr __attribute__ ((unused)),
7762 Dwarf *dbg __attribute__ ((unused)))
7763{
7764 printf (gettext ("\
7765\nException handling table section [%2zu] '.gcc_except_table':\n"),
7766 elf_ndxscn (scn));
7767
7768 Elf_Data *data = elf_rawdata (scn, NULL);
7769
7770 if (unlikely (data == NULL))
7771 {
7772 error (0, 0, gettext ("cannot get %s content: %s"),
7773 ".gcc_except_table", elf_errmsg (-1));
7774 return;
7775 }
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007776
7777 const unsigned char *readp = data->d_buf;
7778 const unsigned char *const dataend = readp + data->d_size;
7779
7780 if (unlikely (readp + 1 > dataend))
7781 {
7782 invalid_data:
7783 error (0, 0, gettext ("invalid data"));
7784 return;
7785 }
7786 unsigned int lpstart_encoding = *readp++;
7787 printf (gettext (" LPStart encoding: %#x "), lpstart_encoding);
7788 print_encoding_base ("", lpstart_encoding);
7789 if (lpstart_encoding != DW_EH_PE_omit)
7790 {
7791 uint64_t lpstart;
7792 readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
7793 printf (" LPStart: %#" PRIx64 "\n", lpstart);
7794 }
7795
7796 if (unlikely (readp + 1 > dataend))
7797 goto invalid_data;
7798 unsigned int ttype_encoding = *readp++;
7799 printf (gettext (" TType encoding: %#x "), ttype_encoding);
7800 print_encoding_base ("", ttype_encoding);
7801 const unsigned char *ttype_base = NULL;
7802 if (ttype_encoding != DW_EH_PE_omit)
7803 {
7804 unsigned int ttype_base_offset;
Mark Wielaard7a053472014-12-14 21:48:23 +01007805 get_uleb128 (ttype_base_offset, readp, dataend);
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007806 printf (" TType base offset: %#x\n", ttype_base_offset);
Mark Wielaardee5693b2014-12-11 18:26:09 +01007807 if ((size_t) (dataend - readp) > ttype_base_offset)
7808 ttype_base = readp + ttype_base_offset;
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007809 }
7810
7811 if (unlikely (readp + 1 > dataend))
7812 goto invalid_data;
7813 unsigned int call_site_encoding = *readp++;
7814 printf (gettext (" Call site encoding: %#x "), call_site_encoding);
7815 print_encoding_base ("", call_site_encoding);
7816 unsigned int call_site_table_len;
Mark Wielaard7a053472014-12-14 21:48:23 +01007817 get_uleb128 (call_site_table_len, readp, dataend);
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007818
7819 const unsigned char *const action_table = readp + call_site_table_len;
7820 if (unlikely (action_table > dataend))
7821 goto invalid_data;
7822 unsigned int u = 0;
7823 unsigned int max_action = 0;
7824 while (readp < action_table)
7825 {
7826 if (u == 0)
7827 puts (gettext ("\n Call site table:"));
7828
7829 uint64_t call_site_start;
7830 readp = read_encoded (call_site_encoding, readp, dataend,
7831 &call_site_start, dbg);
7832 uint64_t call_site_length;
7833 readp = read_encoded (call_site_encoding, readp, dataend,
7834 &call_site_length, dbg);
7835 uint64_t landing_pad;
7836 readp = read_encoded (call_site_encoding, readp, dataend,
7837 &landing_pad, dbg);
7838 unsigned int action;
Mark Wielaard7a053472014-12-14 21:48:23 +01007839 get_uleb128 (action, readp, dataend);
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007840 max_action = MAX (action, max_action);
7841 printf (gettext (" [%4u] Call site start: %#" PRIx64 "\n"
7842 " Call site length: %" PRIu64 "\n"
7843 " Landing pad: %#" PRIx64 "\n"
7844 " Action: %u\n"),
7845 u++, call_site_start, call_site_length, landing_pad, action);
7846 }
Mark Wielaard990fbe52014-12-08 10:11:43 +01007847 if (readp != action_table)
7848 goto invalid_data;
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007849
7850 unsigned int max_ar_filter = 0;
7851 if (max_action > 0)
7852 {
7853 puts ("\n Action table:");
7854
Mark Wielaardcda1a312014-12-21 22:55:54 +01007855 size_t maxdata = (size_t) (dataend - action_table);
7856 if (max_action > maxdata || maxdata - max_action < 1)
Mark Wielaardee5693b2014-12-11 18:26:09 +01007857 {
Mark Wielaardcda1a312014-12-21 22:55:54 +01007858 invalid_action_table:
Mark Wielaardee5693b2014-12-11 18:26:09 +01007859 fputs (gettext (" <INVALID DATA>\n"), stdout);
7860 return;
7861 }
7862
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007863 const unsigned char *const action_table_end
7864 = action_table + max_action + 1;
7865
7866 u = 0;
7867 do
7868 {
7869 int ar_filter;
Mark Wielaard7a053472014-12-14 21:48:23 +01007870 get_sleb128 (ar_filter, readp, action_table_end);
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007871 if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
7872 max_ar_filter = ar_filter;
7873 int ar_disp;
Mark Wielaardcda1a312014-12-21 22:55:54 +01007874 if (readp >= action_table_end)
7875 goto invalid_action_table;
Mark Wielaard7a053472014-12-14 21:48:23 +01007876 get_sleb128 (ar_disp, readp, action_table_end);
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007877
Ulrich Drepper935edde2009-01-17 16:06:42 -08007878 printf (" [%4u] ar_filter: % d\n"
7879 " ar_disp: % -5d",
7880 u, ar_filter, ar_disp);
7881 if (abs (ar_disp) & 1)
7882 printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
7883 else if (ar_disp != 0)
7884 puts (" -> ???");
7885 else
7886 putchar_unlocked ('\n');
7887 ++u;
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007888 }
7889 while (readp < action_table_end);
7890 }
7891
Mark Wielaardee5693b2014-12-11 18:26:09 +01007892 if (max_ar_filter > 0 && ttype_base != NULL)
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007893 {
Mark Wielaardcda1a312014-12-21 22:55:54 +01007894 unsigned char dsize;
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007895 puts ("\n TType table:");
7896
7897 // XXX Not *4, size of encoding;
7898 switch (ttype_encoding & 7)
7899 {
7900 case DW_EH_PE_udata2:
7901 case DW_EH_PE_sdata2:
Mark Wielaardcda1a312014-12-21 22:55:54 +01007902 dsize = 2;
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007903 break;
7904 case DW_EH_PE_udata4:
7905 case DW_EH_PE_sdata4:
Mark Wielaardcda1a312014-12-21 22:55:54 +01007906 dsize = 4;
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007907 break;
7908 case DW_EH_PE_udata8:
7909 case DW_EH_PE_sdata8:
Mark Wielaardcda1a312014-12-21 22:55:54 +01007910 dsize = 8;
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007911 break;
7912 default:
7913 error (1, 0, gettext ("invalid TType encoding"));
7914 }
7915
Mark Wielaardcda1a312014-12-21 22:55:54 +01007916 if (max_ar_filter
7917 > (size_t) (ttype_base - (const unsigned char *) data->d_buf) / dsize)
7918 goto invalid_data;
7919
7920 readp = ttype_base - max_ar_filter * dsize;
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007921 do
7922 {
7923 uint64_t ttype;
7924 readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
7925 dbg);
7926 printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
7927 }
7928 while (readp < ttype_base);
7929 }
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08007930}
7931
Mark Wielaard093a1d32011-04-14 23:47:26 +02007932/* Print the content of the '.gdb_index' section.
7933 http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
7934*/
7935static void
7936print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
7937 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7938{
7939 printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
7940 " contains %" PRId64 " bytes :\n"),
7941 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7942 (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
7943
7944 Elf_Data *data = elf_rawdata (scn, NULL);
7945
7946 if (unlikely (data == NULL))
7947 {
7948 error (0, 0, gettext ("cannot get %s content: %s"),
7949 ".gdb_index", elf_errmsg (-1));
7950 return;
7951 }
7952
7953 // .gdb_index is always in little endian.
7954 Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
7955 dbg = &dummy_dbg;
7956
7957 const unsigned char *readp = data->d_buf;
7958 const unsigned char *const dataend = readp + data->d_size;
7959
7960 if (unlikely (readp + 4 > dataend))
7961 {
7962 invalid_data:
7963 error (0, 0, gettext ("invalid data"));
7964 return;
7965 }
7966
7967 int32_t vers = read_4ubyte_unaligned (dbg, readp);
7968 printf (gettext (" Version: %" PRId32 "\n"), vers);
7969
7970 // The only difference between version 4 and version 5 is the
Mark Wielaard30bb7142012-03-21 16:05:31 +01007971 // hash used for generating the table. Version 6 contains symbols
Mark Wielaarda73fecc2013-03-18 13:54:50 +01007972 // for inlined functions, older versions didn't. Version 7 adds
7973 // symbol kinds. Version 8 just indicates that it correctly includes
7974 // TUs for symbols.
7975 if (vers < 4 || vers > 8)
Mark Wielaard093a1d32011-04-14 23:47:26 +02007976 {
7977 printf (gettext (" unknown version, cannot parse section\n"));
7978 return;
7979 }
7980
7981 readp += 4;
7982 if (unlikely (readp + 4 > dataend))
7983 goto invalid_data;
7984
7985 uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
7986 printf (gettext (" CU offset: %#" PRIx32 "\n"), cu_off);
7987
7988 readp += 4;
7989 if (unlikely (readp + 4 > dataend))
7990 goto invalid_data;
7991
7992 uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
7993 printf (gettext (" TU offset: %#" PRIx32 "\n"), tu_off);
7994
7995 readp += 4;
7996 if (unlikely (readp + 4 > dataend))
7997 goto invalid_data;
7998
7999 uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
8000 printf (gettext (" address offset: %#" PRIx32 "\n"), addr_off);
8001
8002 readp += 4;
8003 if (unlikely (readp + 4 > dataend))
8004 goto invalid_data;
8005
8006 uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
8007 printf (gettext (" symbol offset: %#" PRIx32 "\n"), sym_off);
8008
8009 readp += 4;
8010 if (unlikely (readp + 4 > dataend))
8011 goto invalid_data;
8012
8013 uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
8014 printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
8015
Mark Wielaard86de7922015-04-17 20:03:44 +02008016 if (unlikely ((size_t) (dataend - (const unsigned char *) data->d_buf)
8017 < const_off))
8018 goto invalid_data;
8019
Mark Wielaard093a1d32011-04-14 23:47:26 +02008020 readp = data->d_buf + cu_off;
8021
8022 const unsigned char *nextp = data->d_buf + tu_off;
Mark Wielaardf333a1c2015-04-22 11:44:32 +02008023 if (tu_off >= data->d_size)
8024 goto invalid_data;
8025
Mark Wielaard84a1e0b2012-06-29 23:38:09 +02008026 size_t cu_nr = (nextp - readp) / 16;
Mark Wielaard093a1d32011-04-14 23:47:26 +02008027
8028 printf (gettext ("\n CU list at offset %#" PRIx32
8029 " contains %zu entries:\n"),
Mark Wielaard84a1e0b2012-06-29 23:38:09 +02008030 cu_off, cu_nr);
Mark Wielaard093a1d32011-04-14 23:47:26 +02008031
8032 size_t n = 0;
Mark Wielaard86de7922015-04-17 20:03:44 +02008033 while (dataend - readp >= 16 && n < cu_nr)
Mark Wielaard093a1d32011-04-14 23:47:26 +02008034 {
8035 uint64_t off = read_8ubyte_unaligned (dbg, readp);
8036 readp += 8;
8037
8038 uint64_t len = read_8ubyte_unaligned (dbg, readp);
8039 readp += 8;
8040
8041 printf (" [%4zu] start: %0#8" PRIx64
8042 ", length: %5" PRIu64 "\n", n, off, len);
8043 n++;
8044 }
8045
8046 readp = data->d_buf + tu_off;
8047 nextp = data->d_buf + addr_off;
Mark Wielaardf333a1c2015-04-22 11:44:32 +02008048 if (addr_off >= data->d_size)
8049 goto invalid_data;
8050
Mark Wielaard84a1e0b2012-06-29 23:38:09 +02008051 size_t tu_nr = (nextp - readp) / 24;
Mark Wielaard093a1d32011-04-14 23:47:26 +02008052
8053 printf (gettext ("\n TU list at offset %#" PRIx32
8054 " contains %zu entries:\n"),
Mark Wielaard84a1e0b2012-06-29 23:38:09 +02008055 tu_off, tu_nr);
Mark Wielaard093a1d32011-04-14 23:47:26 +02008056
8057 n = 0;
Mark Wielaard86de7922015-04-17 20:03:44 +02008058 while (dataend - readp >= 24 && n < tu_nr)
Mark Wielaard093a1d32011-04-14 23:47:26 +02008059 {
8060 uint64_t off = read_8ubyte_unaligned (dbg, readp);
8061 readp += 8;
8062
8063 uint64_t type = read_8ubyte_unaligned (dbg, readp);
8064 readp += 8;
8065
8066 uint64_t sig = read_8ubyte_unaligned (dbg, readp);
8067 readp += 8;
8068
8069 printf (" [%4zu] CU offset: %5" PRId64
8070 ", type offset: %5" PRId64
8071 ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
8072 n++;
8073 }
8074
8075 readp = data->d_buf + addr_off;
8076 nextp = data->d_buf + sym_off;
Mark Wielaardf333a1c2015-04-22 11:44:32 +02008077 if (sym_off >= data->d_size)
8078 goto invalid_data;
8079
Mark Wielaard84a1e0b2012-06-29 23:38:09 +02008080 size_t addr_nr = (nextp - readp) / 20;
Mark Wielaard093a1d32011-04-14 23:47:26 +02008081
8082 printf (gettext ("\n Address list at offset %#" PRIx32
8083 " contains %zu entries:\n"),
Mark Wielaard84a1e0b2012-06-29 23:38:09 +02008084 addr_off, addr_nr);
Mark Wielaard093a1d32011-04-14 23:47:26 +02008085
8086 n = 0;
Mark Wielaard86de7922015-04-17 20:03:44 +02008087 while (dataend - readp >= 20 && n < addr_nr)
Mark Wielaard093a1d32011-04-14 23:47:26 +02008088 {
8089 uint64_t low = read_8ubyte_unaligned (dbg, readp);
8090 readp += 8;
8091
8092 uint64_t high = read_8ubyte_unaligned (dbg, readp);
8093 readp += 8;
8094
8095 uint32_t idx = read_4ubyte_unaligned (dbg, readp);
8096 readp += 4;
8097
Mark Wielaard10186a12013-01-24 11:29:21 +01008098 char *l = format_dwarf_addr (dwflmod, 8, low, low);
8099 char *h = format_dwarf_addr (dwflmod, 8, high - 1, high);
Mark Wielaard093a1d32011-04-14 23:47:26 +02008100 printf (" [%4zu] %s..%s, CU index: %5" PRId32 "\n",
8101 n, l, h, idx);
Mark Wielaard10cd97e2013-03-19 11:43:49 +01008102 free (l);
8103 free (h);
Mark Wielaard093a1d32011-04-14 23:47:26 +02008104 n++;
8105 }
8106
Mark Wielaardf333a1c2015-04-22 11:44:32 +02008107 const unsigned char *const_start = data->d_buf + const_off;
8108 if (const_off >= data->d_size)
8109 goto invalid_data;
8110
Mark Wielaard093a1d32011-04-14 23:47:26 +02008111 readp = data->d_buf + sym_off;
Mark Wielaard86de7922015-04-17 20:03:44 +02008112 nextp = const_start;
Mark Wielaard84a1e0b2012-06-29 23:38:09 +02008113 size_t sym_nr = (nextp - readp) / 8;
Mark Wielaard093a1d32011-04-14 23:47:26 +02008114
8115 printf (gettext ("\n Symbol table at offset %#" PRIx32
8116 " contains %zu slots:\n"),
Mark Wielaard84a1e0b2012-06-29 23:38:09 +02008117 addr_off, sym_nr);
Mark Wielaard093a1d32011-04-14 23:47:26 +02008118
8119 n = 0;
Mark Wielaard86de7922015-04-17 20:03:44 +02008120 while (dataend - readp >= 8 && n < sym_nr)
Mark Wielaard093a1d32011-04-14 23:47:26 +02008121 {
8122 uint32_t name = read_4ubyte_unaligned (dbg, readp);
8123 readp += 4;
8124
8125 uint32_t vector = read_4ubyte_unaligned (dbg, readp);
8126 readp += 4;
8127
8128 if (name != 0 || vector != 0)
8129 {
Mark Wielaard86de7922015-04-17 20:03:44 +02008130 const unsigned char *sym = const_start + name;
8131 if (unlikely ((size_t) (dataend - const_start) < name
Mark Wielaard2323b452014-12-15 15:34:59 +01008132 || memchr (sym, '\0', dataend - sym) == NULL))
Mark Wielaard093a1d32011-04-14 23:47:26 +02008133 goto invalid_data;
8134
8135 printf (" [%4zu] symbol: %s, CUs: ", n, sym);
8136
Mark Wielaard86de7922015-04-17 20:03:44 +02008137 const unsigned char *readcus = const_start + vector;
8138 if (unlikely ((size_t) (dataend - const_start) < vector))
Mark Wielaard093a1d32011-04-14 23:47:26 +02008139 goto invalid_data;
Mark Wielaard093a1d32011-04-14 23:47:26 +02008140 uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
8141 while (cus--)
8142 {
Mark Wielaard84a1e0b2012-06-29 23:38:09 +02008143 uint32_t cu_kind, cu, kind;
8144 bool is_static;
Mark Wielaard093a1d32011-04-14 23:47:26 +02008145 readcus += 4;
Mark Wielaard2323b452014-12-15 15:34:59 +01008146 if (unlikely (readcus + 4 > dataend))
8147 goto invalid_data;
Mark Wielaard84a1e0b2012-06-29 23:38:09 +02008148 cu_kind = read_4ubyte_unaligned (dbg, readcus);
8149 cu = cu_kind & ((1 << 24) - 1);
8150 kind = (cu_kind >> 28) & 7;
Mark Wielaard7c757b32014-04-22 22:23:18 +02008151 is_static = cu_kind & (1U << 31);
Mark Wielaard84a1e0b2012-06-29 23:38:09 +02008152 if (cu > cu_nr - 1)
8153 printf ("%" PRId32 "T", cu - (uint32_t) cu_nr);
8154 else
8155 printf ("%" PRId32, cu);
8156 if (kind != 0)
8157 {
8158 printf (" (");
8159 switch (kind)
8160 {
8161 case 1:
8162 printf ("type");
8163 break;
8164 case 2:
8165 printf ("var");
8166 break;
8167 case 3:
8168 printf ("func");
8169 break;
8170 case 4:
8171 printf ("other");
8172 break;
8173 default:
8174 printf ("unknown-0x%" PRIx32, kind);
8175 break;
8176 }
8177 printf (":%c)", (is_static ? 'S' : 'G'));
8178 }
8179 if (cus > 0)
8180 printf (", ");
Mark Wielaard093a1d32011-04-14 23:47:26 +02008181 }
8182 printf ("\n");
8183 }
8184 n++;
8185 }
8186}
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08008187
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008188static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00008189print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008190{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008191 /* Before we start the real work get a debug context descriptor. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00008192 Dwarf_Addr dwbias;
8193 Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
Roland McGratha065c4b2011-12-20 10:55:01 -08008194 Dwarf dummy_dbg =
8195 {
8196 .elf = ebl->elf,
8197 .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
8198 };
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008199 if (dbg == NULL)
8200 {
Roland McGrath7a5bed82010-06-01 13:44:00 -07008201 if ((print_debug_sections & ~section_exception) != 0)
Roland McGrath2e79deb2010-01-04 20:36:10 -08008202 error (0, 0, gettext ("cannot get debug context descriptor: %s"),
8203 dwfl_errmsg (-1));
Roland McGrath7a5bed82010-06-01 13:44:00 -07008204 dbg = &dummy_dbg;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008205 }
8206
8207 /* Get the section header string table index. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00008208 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07008209 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008210 error (EXIT_FAILURE, 0,
8211 gettext ("cannot get section header string table index"));
8212
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00008213 /* Look through all the sections for the debugging sections to print. */
8214 Elf_Scn *scn = NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008215 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
8216 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008217 GElf_Shdr shdr_mem;
8218 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
8219
Ulrich Drepper903c1162007-02-15 19:40:37 +00008220 if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008221 {
8222 static const struct
8223 {
8224 const char *name;
8225 enum section_e bitmask;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00008226 void (*fp) (Dwfl_Module *, Ebl *,
8227 GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008228 } debug_sections[] =
8229 {
8230#define NEW_SECTION(name) \
8231 { ".debug_" #name, section_##name, print_debug_##name##_section }
8232 NEW_SECTION (abbrev),
8233 NEW_SECTION (aranges),
8234 NEW_SECTION (frame),
8235 NEW_SECTION (info),
Roland McGrath2b1f0952010-06-20 17:55:50 -07008236 NEW_SECTION (types),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008237 NEW_SECTION (line),
8238 NEW_SECTION (loc),
8239 NEW_SECTION (pubnames),
8240 NEW_SECTION (str),
8241 NEW_SECTION (macinfo),
Mark Wielaarde9b23882012-06-29 22:30:15 +02008242 NEW_SECTION (macro),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008243 NEW_SECTION (ranges),
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08008244 { ".eh_frame", section_frame | section_exception,
8245 print_debug_frame_section },
8246 { ".eh_frame_hdr", section_frame | section_exception,
8247 print_debug_frame_hdr_section },
8248 { ".gcc_except_table", section_frame | section_exception,
Mark Wielaard093a1d32011-04-14 23:47:26 +02008249 print_debug_exception_table },
8250 { ".gdb_index", section_gdb_index, print_gdb_index_section }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008251 };
8252 const int ndebug_sections = (sizeof (debug_sections)
8253 / sizeof (debug_sections[0]));
8254 const char *name = elf_strptr (ebl->elf, shstrndx,
8255 shdr->sh_name);
Mark Wielaard903f3342014-05-27 10:25:27 +02008256 if (name == NULL)
8257 continue;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008258
Mark Wielaard903f3342014-05-27 10:25:27 +02008259 int n;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008260 for (n = 0; n < ndebug_sections; ++n)
Roland McGrath725aad52011-02-23 19:52:46 -08008261 if (strcmp (name, debug_sections[n].name) == 0
8262#if USE_ZLIB
8263 || (name[0] == '.' && name[1] == 'z'
8264 && debug_sections[n].name[1] == 'd'
8265 && strcmp (&name[2], &debug_sections[n].name[1]) == 0)
8266#endif
8267 )
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008268 {
Roland McGrath2e79deb2010-01-04 20:36:10 -08008269 if ((print_debug_sections | implicit_debug_sections)
8270 & debug_sections[n].bitmask)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00008271 debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008272 break;
8273 }
8274 }
8275 }
Roland McGrathfa144952010-08-30 19:22:41 -07008276
8277 reset_listptr (&known_loclistptr);
8278 reset_listptr (&known_rangelistptr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008279}
8280
8281
Roland McGrathcb6d8652007-08-23 08:10:54 +00008282#define ITEM_INDENT 4
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008283#define WRAP_COLUMN 75
Roland McGrathcb6d8652007-08-23 08:10:54 +00008284
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008285/* Print "NAME: FORMAT", wrapping when output text would make the line
8286 exceed WRAP_COLUMN. Unpadded numbers look better for the core items
8287 but this function is also used for registers which should be printed
8288 aligned. Fortunately registers output uses fixed fields width (such
8289 as %11d) for the alignment.
8290
8291 Line breaks should not depend on the particular values although that
8292 may happen in some cases of the core items. */
8293
Roland McGrathcb6d8652007-08-23 08:10:54 +00008294static unsigned int
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008295__attribute__ ((format (printf, 6, 7)))
Roland McGrathcb6d8652007-08-23 08:10:54 +00008296print_core_item (unsigned int colno, char sep, unsigned int wrap,
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008297 size_t name_width, const char *name, const char *format, ...)
Roland McGrathcb6d8652007-08-23 08:10:54 +00008298{
8299 size_t len = strlen (name);
8300 if (name_width < len)
8301 name_width = len;
8302
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008303 char *out;
8304 va_list ap;
8305 va_start (ap, format);
8306 int out_len = vasprintf (&out, format, ap);
8307 va_end (ap);
8308 if (out_len == -1)
8309 error (EXIT_FAILURE, 0, _("memory exhausted"));
8310
8311 size_t n = name_width + sizeof ": " - 1 + out_len;
Roland McGrathcb6d8652007-08-23 08:10:54 +00008312
8313 if (colno == 0)
8314 {
8315 printf ("%*s", ITEM_INDENT, "");
8316 colno = ITEM_INDENT + n;
8317 }
8318 else if (colno + 2 + n < wrap)
8319 {
8320 printf ("%c ", sep);
8321 colno += 2 + n;
8322 }
8323 else
8324 {
8325 printf ("\n%*s", ITEM_INDENT, "");
8326 colno = ITEM_INDENT + n;
8327 }
8328
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008329 printf ("%s: %*s%s", name, (int) (name_width - len), "", out);
Roland McGrathcb6d8652007-08-23 08:10:54 +00008330
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008331 free (out);
Roland McGrathcb6d8652007-08-23 08:10:54 +00008332
8333 return colno;
8334}
8335
8336static const void *
8337convert (Elf *core, Elf_Type type, uint_fast16_t count,
Roland McGrath1d8bb252008-08-07 08:39:41 +00008338 void *value, const void *data, size_t size)
Roland McGrathcb6d8652007-08-23 08:10:54 +00008339{
8340 Elf_Data valuedata =
8341 {
8342 .d_type = type,
8343 .d_buf = value,
Roland McGrath1d8bb252008-08-07 08:39:41 +00008344 .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
Roland McGrathcb6d8652007-08-23 08:10:54 +00008345 .d_version = EV_CURRENT,
8346 };
8347 Elf_Data indata =
8348 {
8349 .d_type = type,
8350 .d_buf = (void *) data,
8351 .d_size = valuedata.d_size,
8352 .d_version = EV_CURRENT,
8353 };
8354
8355 Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
8356 ? elf32_xlatetom : elf64_xlatetom)
8357 (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
8358 if (d == NULL)
8359 error (EXIT_FAILURE, 0,
8360 gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
8361
8362 return data + indata.d_size;
8363}
8364
8365typedef uint8_t GElf_Byte;
8366
8367static unsigned int
8368handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
Roland McGrath1d8bb252008-08-07 08:39:41 +00008369 unsigned int colno, size_t *repeated_size)
Roland McGrathcb6d8652007-08-23 08:10:54 +00008370{
8371 uint_fast16_t count = item->count ?: 1;
8372
8373#define TYPES \
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008374 DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8); \
8375 DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16); \
8376 DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32); \
8377 DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32); \
8378 DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64); \
8379 DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64)
Roland McGrathcb6d8652007-08-23 08:10:54 +00008380
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008381#define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name[count]
Roland McGrathcb6d8652007-08-23 08:10:54 +00008382 union { TYPES; } value;
8383#undef DO_TYPE
8384
Roland McGrath1d8bb252008-08-07 08:39:41 +00008385 void *data = &value;
8386 size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
8387 size_t convsize = size;
8388 if (repeated_size != NULL)
8389 {
8390 if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
8391 {
8392 data = alloca (*repeated_size);
8393 count *= *repeated_size / size;
8394 convsize = count * size;
8395 *repeated_size -= convsize;
8396 }
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08008397 else if (item->count != 0 || item->format != '\n')
Roland McGrath1d8bb252008-08-07 08:39:41 +00008398 *repeated_size -= size;
8399 }
8400
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08008401 convert (core, item->type, count, data, desc + item->offset, convsize);
Roland McGrath1d8bb252008-08-07 08:39:41 +00008402
8403 Elf_Type type = item->type;
8404 if (type == ELF_T_ADDR)
8405 type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
Roland McGrathcb6d8652007-08-23 08:10:54 +00008406
8407 switch (item->format)
8408 {
8409 case 'd':
8410 assert (count == 1);
Roland McGrath1d8bb252008-08-07 08:39:41 +00008411 switch (type)
Roland McGrathcb6d8652007-08-23 08:10:54 +00008412 {
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008413#define DO_TYPE(NAME, Name, hex, dec) \
Roland McGrathcb6d8652007-08-23 08:10:54 +00008414 case ELF_T_##NAME: \
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008415 colno = print_core_item (colno, ',', WRAP_COLUMN, \
8416 0, item->name, dec, value.Name[0]); \
Roland McGrathcb6d8652007-08-23 08:10:54 +00008417 break
8418 TYPES;
8419#undef DO_TYPE
8420 default:
8421 abort ();
8422 }
8423 break;
8424
8425 case 'x':
8426 assert (count == 1);
Roland McGrath1d8bb252008-08-07 08:39:41 +00008427 switch (type)
Roland McGrathcb6d8652007-08-23 08:10:54 +00008428 {
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008429#define DO_TYPE(NAME, Name, hex, dec) \
Roland McGrathcb6d8652007-08-23 08:10:54 +00008430 case ELF_T_##NAME: \
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008431 colno = print_core_item (colno, ',', WRAP_COLUMN, \
8432 0, item->name, hex, value.Name[0]); \
Roland McGrathcb6d8652007-08-23 08:10:54 +00008433 break
8434 TYPES;
8435#undef DO_TYPE
8436 default:
8437 abort ();
8438 }
8439 break;
8440
8441 case 'b':
Roland McGrath1d8bb252008-08-07 08:39:41 +00008442 case 'B':
8443 assert (size % sizeof (unsigned int) == 0);
8444 unsigned int nbits = count * size * 8;
8445 unsigned int pop = 0;
8446 for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
8447 pop += __builtin_popcount (*i);
8448 bool negate = pop > nbits / 2;
8449 const unsigned int bias = item->format == 'b';
8450
8451 {
Mark Wielaard7c680a22014-04-22 23:26:34 +02008452 char printed[(negate ? nbits - pop : pop) * 16 + 1];
Roland McGrath1d8bb252008-08-07 08:39:41 +00008453 char *p = printed;
8454 *p = '\0';
8455
8456 if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
8457 {
8458 assert (size == sizeof (unsigned int) * 2);
8459 for (unsigned int *i = data;
8460 (void *) i < data + count * size; i += 2)
8461 {
8462 unsigned int w = i[1];
8463 i[1] = i[0];
8464 i[0] = w;
8465 }
8466 }
8467
8468 unsigned int lastbit = 0;
Jan Kratochvil69a28522012-10-11 21:47:26 +02008469 unsigned int run = 0;
Roland McGrath1d8bb252008-08-07 08:39:41 +00008470 for (const unsigned int *i = data;
8471 (void *) i < data + count * size; ++i)
8472 {
8473 unsigned int bit = ((void *) i - data) * 8;
8474 unsigned int w = negate ? ~*i : *i;
8475 while (w != 0)
8476 {
Mark Wielaardb00a4fa2015-09-03 10:50:58 +02008477 /* Note that a right shift equal to (or greater than)
8478 the number of bits of w is undefined behaviour. In
8479 particular when the least significant bit is bit 32
8480 (w = 0x8000000) then w >>= n is undefined. So
8481 explicitly handle that case separately. */
8482 unsigned int n = ffs (w);
8483 if (n < sizeof (w) * 8)
8484 w >>= n;
8485 else
8486 w = 0;
Roland McGrath1d8bb252008-08-07 08:39:41 +00008487 bit += n;
8488
Jan Kratochvil69a28522012-10-11 21:47:26 +02008489 if (lastbit != 0 && lastbit + 1 == bit)
Roland McGrath62b28b62010-04-14 11:54:06 -07008490 ++run;
8491 else
8492 {
8493 if (lastbit == 0)
8494 p += sprintf (p, "%u", bit - bias);
8495 else if (run == 0)
8496 p += sprintf (p, ",%u", bit - bias);
8497 else
8498 p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
8499 run = 0;
8500 }
Roland McGrath1d8bb252008-08-07 08:39:41 +00008501
8502 lastbit = bit;
8503 }
8504 }
Jan Kratochvil69a28522012-10-11 21:47:26 +02008505 if (lastbit > 0 && run > 0 && lastbit + 1 != nbits)
8506 p += sprintf (p, "-%u", lastbit - bias);
Roland McGrath1d8bb252008-08-07 08:39:41 +00008507
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008508 colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
Roland McGrath1d8bb252008-08-07 08:39:41 +00008509 negate ? "~<%s>" : "<%s>", printed);
8510 }
Roland McGrathcb6d8652007-08-23 08:10:54 +00008511 break;
8512
8513 case 'T':
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00008514 case (char) ('T'|0x80):
Roland McGrathcb6d8652007-08-23 08:10:54 +00008515 assert (count == 2);
8516 Dwarf_Word sec;
8517 Dwarf_Word usec;
Roland McGrath1d8bb252008-08-07 08:39:41 +00008518 switch (type)
Roland McGrathcb6d8652007-08-23 08:10:54 +00008519 {
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008520#define DO_TYPE(NAME, Name, hex, dec) \
Roland McGrathcb6d8652007-08-23 08:10:54 +00008521 case ELF_T_##NAME: \
8522 sec = value.Name[0]; \
8523 usec = value.Name[1]; \
Roland McGrathcb6d8652007-08-23 08:10:54 +00008524 break
8525 TYPES;
8526#undef DO_TYPE
8527 default:
8528 abort ();
8529 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00008530 if (unlikely (item->format == (char) ('T'|0x80)))
8531 {
8532 /* This is a hack for an ill-considered 64-bit ABI where
8533 tv_usec is actually a 32-bit field with 32 bits of padding
8534 rounding out struct timeval. We've already converted it as
8535 a 64-bit field. For little-endian, this just means the
8536 high half is the padding; it's presumably zero, but should
8537 be ignored anyway. For big-endian, it means the 32-bit
8538 field went into the high half of USEC. */
8539 GElf_Ehdr ehdr_mem;
8540 GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
8541 if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
8542 usec >>= 32;
8543 else
8544 usec &= UINT32_MAX;
8545 }
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008546 colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
8547 "%" PRIu64 ".%.6" PRIu64, sec, usec);
Roland McGrathcb6d8652007-08-23 08:10:54 +00008548 break;
8549
8550 case 'c':
8551 assert (count == 1);
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008552 colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
8553 "%c", value.Byte[0]);
Roland McGrathcb6d8652007-08-23 08:10:54 +00008554 break;
8555
8556 case 's':
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008557 colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
8558 "%.*s", (int) count, value.Byte);
Roland McGrathcb6d8652007-08-23 08:10:54 +00008559 break;
8560
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08008561 case '\n':
8562 /* This is a list of strings separated by '\n'. */
8563 assert (item->count == 0);
8564 assert (repeated_size != NULL);
8565 assert (item->name == NULL);
8566 if (unlikely (item->offset >= *repeated_size))
8567 break;
8568
8569 const char *s = desc + item->offset;
8570 size = *repeated_size - item->offset;
8571 *repeated_size = 0;
8572 while (size > 0)
8573 {
8574 const char *eol = memchr (s, '\n', size);
8575 int len = size;
8576 if (eol != NULL)
8577 len = eol - s;
8578 printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
8579 if (eol == NULL)
8580 break;
8581 size -= eol + 1 - s;
8582 s = eol + 1;
8583 }
8584
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008585 colno = WRAP_COLUMN;
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08008586 break;
8587
Petr Machataa47a0962013-11-14 01:07:22 +01008588 case 'h':
8589 break;
8590
Roland McGrathcb6d8652007-08-23 08:10:54 +00008591 default:
8592 error (0, 0, "XXX not handling format '%c' for %s",
8593 item->format, item->name);
8594 break;
8595 }
8596
8597#undef TYPES
8598
8599 return colno;
8600}
8601
8602
8603/* Sort items by group, and by layout offset within each group. */
8604static int
8605compare_core_items (const void *a, const void *b)
8606{
8607 const Ebl_Core_Item *const *p1 = a;
8608 const Ebl_Core_Item *const *p2 = b;
8609 const Ebl_Core_Item *item1 = *p1;
8610 const Ebl_Core_Item *item2 = *p2;
8611
8612 return ((item1->group == item2->group ? 0
8613 : strcmp (item1->group, item2->group))
8614 ?: (int) item1->offset - (int) item2->offset);
8615}
8616
8617/* Sort item groups by layout offset of the first item in the group. */
8618static int
8619compare_core_item_groups (const void *a, const void *b)
8620{
8621 const Ebl_Core_Item *const *const *p1 = a;
8622 const Ebl_Core_Item *const *const *p2 = b;
8623 const Ebl_Core_Item *const *group1 = *p1;
8624 const Ebl_Core_Item *const *group2 = *p2;
8625 const Ebl_Core_Item *item1 = *group1;
8626 const Ebl_Core_Item *item2 = *group2;
8627
8628 return (int) item1->offset - (int) item2->offset;
8629}
8630
8631static unsigned int
Roland McGrath059c83e2008-02-21 06:19:39 +00008632handle_core_items (Elf *core, const void *desc, size_t descsz,
Roland McGrathcb6d8652007-08-23 08:10:54 +00008633 const Ebl_Core_Item *items, size_t nitems)
8634{
8635 if (nitems == 0)
8636 return 0;
Jan Kratochvilc44cce02012-10-10 19:32:05 +02008637 unsigned int colno = 0;
8638
8639 /* FORMAT '\n' makes sense to be present only as a single item as it
8640 processes all the data of a note. FORMATs 'b' and 'B' have a special case
8641 if present as a single item but they can be also processed with other
8642 items below. */
8643 if (nitems == 1 && (items[0].format == '\n' || items[0].format == 'b'
8644 || items[0].format == 'B'))
8645 {
8646 assert (items[0].offset == 0);
8647 size_t size = descsz;
8648 colno = handle_core_item (core, items, desc, colno, &size);
8649 /* If SIZE is not zero here there is some remaining data. But we do not
8650 know how to process it anyway. */
8651 return colno;
8652 }
8653 for (size_t i = 0; i < nitems; ++i)
8654 assert (items[i].format != '\n');
Roland McGrathcb6d8652007-08-23 08:10:54 +00008655
8656 /* Sort to collect the groups together. */
8657 const Ebl_Core_Item *sorted_items[nitems];
8658 for (size_t i = 0; i < nitems; ++i)
8659 sorted_items[i] = &items[i];
8660 qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
8661
8662 /* Collect the unique groups and sort them. */
8663 const Ebl_Core_Item **groups[nitems];
8664 groups[0] = &sorted_items[0];
8665 size_t ngroups = 1;
8666 for (size_t i = 1; i < nitems; ++i)
8667 if (sorted_items[i]->group != sorted_items[i - 1]->group
8668 && strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
8669 groups[ngroups++] = &sorted_items[i];
8670 qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
8671
8672 /* Write out all the groups. */
Roland McGrath1d8bb252008-08-07 08:39:41 +00008673 const void *last = desc;
Roland McGrath059c83e2008-02-21 06:19:39 +00008674 do
8675 {
8676 for (size_t i = 0; i < ngroups; ++i)
8677 {
8678 for (const Ebl_Core_Item **item = groups[i];
8679 (item < &sorted_items[nitems]
8680 && ((*item)->group == groups[i][0]->group
8681 || !strcmp ((*item)->group, groups[i][0]->group)));
8682 ++item)
Roland McGrath1d8bb252008-08-07 08:39:41 +00008683 colno = handle_core_item (core, *item, desc, colno, NULL);
Roland McGrath059c83e2008-02-21 06:19:39 +00008684
8685 /* Force a line break at the end of the group. */
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008686 colno = WRAP_COLUMN;
Roland McGrath059c83e2008-02-21 06:19:39 +00008687 }
8688
8689 if (descsz == 0)
8690 break;
8691
8692 /* This set of items consumed a certain amount of the note's data.
8693 If there is more data there, we have another unit of the same size.
8694 Loop to print that out too. */
8695 const Ebl_Core_Item *item = &items[nitems - 1];
8696 size_t eltsz = item->offset + gelf_fsize (core, item->type,
8697 item->count ?: 1, EV_CURRENT);
Roland McGrath1d8bb252008-08-07 08:39:41 +00008698
8699 int reps = -1;
8700 do
8701 {
8702 ++reps;
8703 desc += eltsz;
8704 descsz -= eltsz;
8705 }
8706 while (descsz >= eltsz && !memcmp (desc, last, eltsz));
8707
8708 if (reps == 1)
8709 {
8710 /* For just one repeat, print it unabridged twice. */
8711 desc -= eltsz;
8712 descsz += eltsz;
8713 }
8714 else if (reps > 1)
8715 printf (gettext ("\n%*s... <repeats %u more times> ..."),
8716 ITEM_INDENT, "", reps);
8717
8718 last = desc;
Roland McGrathcb6d8652007-08-23 08:10:54 +00008719 }
Roland McGrath059c83e2008-02-21 06:19:39 +00008720 while (descsz > 0);
Roland McGrathcb6d8652007-08-23 08:10:54 +00008721
8722 return colno;
8723}
8724
8725static unsigned int
8726handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
8727 unsigned int colno)
8728{
8729 desc += regloc->offset;
8730
8731 abort (); /* XXX */
8732 return colno;
8733}
8734
8735
8736static unsigned int
8737handle_core_register (Ebl *ebl, Elf *core, int maxregname,
8738 const Ebl_Register_Location *regloc, const void *desc,
8739 unsigned int colno)
8740{
8741 if (regloc->bits % 8 != 0)
8742 return handle_bit_registers (regloc, desc, colno);
8743
8744 desc += regloc->offset;
8745
8746 for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
8747 {
Roland McGrathdffc33d2009-07-06 16:06:41 -07008748 char name[REGNAMESZ];
Roland McGrathcb6d8652007-08-23 08:10:54 +00008749 int bits;
8750 int type;
Roland McGrathdffc33d2009-07-06 16:06:41 -07008751 register_info (ebl, reg, regloc, name, &bits, &type);
Roland McGrathcb6d8652007-08-23 08:10:54 +00008752
8753#define TYPES \
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008754 BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8); \
8755 BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16); \
8756 BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32); \
8757 BITS (64, XWORD, "%20" PRId64, " 0x%.16" PRIx64)
Roland McGrathcb6d8652007-08-23 08:10:54 +00008758
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008759#define BITS(bits, xtype, sfmt, ufmt) \
Roland McGrathcb6d8652007-08-23 08:10:54 +00008760 uint##bits##_t b##bits; int##bits##_t b##bits##s
8761 union { TYPES; uint64_t b128[2]; } value;
8762#undef BITS
8763
8764 switch (type)
8765 {
8766 case DW_ATE_unsigned:
8767 case DW_ATE_signed:
8768 case DW_ATE_address:
8769 switch (bits)
8770 {
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008771#define BITS(bits, xtype, sfmt, ufmt) \
Roland McGrathcb6d8652007-08-23 08:10:54 +00008772 case bits: \
Roland McGrath1d8bb252008-08-07 08:39:41 +00008773 desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0); \
Roland McGrathcb6d8652007-08-23 08:10:54 +00008774 if (type == DW_ATE_signed) \
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008775 colno = print_core_item (colno, ' ', WRAP_COLUMN, \
Roland McGrathcb6d8652007-08-23 08:10:54 +00008776 maxregname, name, \
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008777 sfmt, value.b##bits##s); \
Roland McGrathcb6d8652007-08-23 08:10:54 +00008778 else \
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008779 colno = print_core_item (colno, ' ', WRAP_COLUMN, \
Roland McGrathcb6d8652007-08-23 08:10:54 +00008780 maxregname, name, \
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008781 ufmt, value.b##bits); \
Roland McGrathcb6d8652007-08-23 08:10:54 +00008782 break
8783
8784 TYPES;
8785
8786 case 128:
8787 assert (type == DW_ATE_unsigned);
Roland McGrath1d8bb252008-08-07 08:39:41 +00008788 desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
Roland McGrathcb6d8652007-08-23 08:10:54 +00008789 int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008790 colno = print_core_item (colno, ' ', WRAP_COLUMN,
Roland McGrathcb6d8652007-08-23 08:10:54 +00008791 maxregname, name,
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008792 "0x%.16" PRIx64 "%.16" PRIx64,
Roland McGrathcb6d8652007-08-23 08:10:54 +00008793 value.b128[!be], value.b128[be]);
8794 break;
8795
8796 default:
8797 abort ();
8798#undef BITS
8799 }
8800 break;
8801
8802 default:
8803 /* Print each byte in hex, the whole thing in native byte order. */
8804 assert (bits % 8 == 0);
8805 const uint8_t *bytes = desc;
8806 desc += bits / 8;
8807 char hex[bits / 4 + 1];
8808 hex[bits / 4] = '\0';
8809 int incr = 1;
8810 if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
8811 {
8812 bytes += bits / 8 - 1;
8813 incr = -1;
8814 }
8815 size_t idx = 0;
8816 for (char *h = hex; bits > 0; bits -= 8, idx += incr)
8817 {
8818 *h++ = "0123456789abcdef"[bytes[idx] >> 4];
8819 *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
8820 }
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008821 colno = print_core_item (colno, ' ', WRAP_COLUMN,
8822 maxregname, name, "0x%s", hex);
Roland McGrathcb6d8652007-08-23 08:10:54 +00008823 break;
8824 }
8825 desc += regloc->pad;
8826
8827#undef TYPES
8828 }
8829
8830 return colno;
8831}
8832
8833
8834struct register_info
8835{
8836 const Ebl_Register_Location *regloc;
8837 const char *set;
Roland McGrathdffc33d2009-07-06 16:06:41 -07008838 char name[REGNAMESZ];
8839 int regno;
8840 int bits;
8841 int type;
Roland McGrathcb6d8652007-08-23 08:10:54 +00008842};
8843
8844static int
8845register_bitpos (const struct register_info *r)
8846{
8847 return (r->regloc->offset * 8
8848 + ((r->regno - r->regloc->regno)
8849 * (r->regloc->bits + r->regloc->pad * 8)));
8850}
8851
8852static int
8853compare_sets_by_info (const struct register_info *r1,
8854 const struct register_info *r2)
8855{
8856 return ((int) r2->bits - (int) r1->bits
8857 ?: register_bitpos (r1) - register_bitpos (r2));
8858}
8859
8860/* Sort registers by set, and by size and layout offset within each set. */
8861static int
8862compare_registers (const void *a, const void *b)
8863{
8864 const struct register_info *r1 = a;
8865 const struct register_info *r2 = b;
8866
8867 /* Unused elements sort last. */
8868 if (r1->regloc == NULL)
8869 return r2->regloc == NULL ? 0 : 1;
8870 if (r2->regloc == NULL)
8871 return -1;
8872
8873 return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
8874 ?: compare_sets_by_info (r1, r2));
8875}
8876
8877/* Sort register sets by layout offset of the first register in the set. */
8878static int
8879compare_register_sets (const void *a, const void *b)
8880{
8881 const struct register_info *const *p1 = a;
8882 const struct register_info *const *p2 = b;
8883 return compare_sets_by_info (*p1, *p2);
8884}
8885
8886static unsigned int
8887handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
8888 const Ebl_Register_Location *reglocs, size_t nregloc)
8889{
8890 if (nregloc == 0)
8891 return 0;
8892
8893 ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
8894 if (maxnreg <= 0)
Roland McGrathdffc33d2009-07-06 16:06:41 -07008895 {
8896 for (size_t i = 0; i < nregloc; ++i)
8897 if (maxnreg < reglocs[i].regno + reglocs[i].count)
8898 maxnreg = reglocs[i].regno + reglocs[i].count;
8899 assert (maxnreg > 0);
8900 }
Roland McGrathcb6d8652007-08-23 08:10:54 +00008901
8902 struct register_info regs[maxnreg];
8903 memset (regs, 0, sizeof regs);
8904
8905 /* Sort to collect the sets together. */
8906 int maxreg = 0;
8907 for (size_t i = 0; i < nregloc; ++i)
8908 for (int reg = reglocs[i].regno;
8909 reg < reglocs[i].regno + reglocs[i].count;
8910 ++reg)
8911 {
8912 assert (reg < maxnreg);
8913 if (reg > maxreg)
8914 maxreg = reg;
8915 struct register_info *info = &regs[reg];
Roland McGrathcb6d8652007-08-23 08:10:54 +00008916 info->regloc = &reglocs[i];
Roland McGrathf7a6f032009-07-08 14:08:32 -07008917 info->regno = reg;
Roland McGrathdffc33d2009-07-06 16:06:41 -07008918 info->set = register_info (ebl, reg, &reglocs[i],
8919 info->name, &info->bits, &info->type);
Roland McGrathcb6d8652007-08-23 08:10:54 +00008920 }
8921 qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
8922
8923 /* Collect the unique sets and sort them. */
8924 inline bool same_set (const struct register_info *a,
8925 const struct register_info *b)
8926 {
8927 return (a < &regs[maxnreg] && a->regloc != NULL
8928 && b < &regs[maxnreg] && b->regloc != NULL
8929 && a->bits == b->bits
8930 && (a->set == b->set || !strcmp (a->set, b->set)));
8931 }
8932 struct register_info *sets[maxreg + 1];
8933 sets[0] = &regs[0];
8934 size_t nsets = 1;
8935 for (int i = 1; i <= maxreg; ++i)
8936 if (regs[i].regloc != NULL && !same_set (&regs[i], &regs[i - 1]))
8937 sets[nsets++] = &regs[i];
8938 qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
8939
8940 /* Write out all the sets. */
8941 unsigned int colno = 0;
8942 for (size_t i = 0; i < nsets; ++i)
8943 {
8944 /* Find the longest name of a register in this set. */
8945 size_t maxname = 0;
8946 const struct register_info *end;
8947 for (end = sets[i]; same_set (sets[i], end); ++end)
8948 {
8949 size_t len = strlen (end->name);
8950 if (len > maxname)
8951 maxname = len;
8952 }
8953
8954 for (const struct register_info *reg = sets[i];
8955 reg < end;
8956 reg += reg->regloc->count ?: 1)
8957 colno = handle_core_register (ebl, core, maxname,
8958 reg->regloc, desc, colno);
8959
8960 /* Force a line break at the end of the group. */
Jan Kratochvil4bdbb672012-10-10 22:27:58 +02008961 colno = WRAP_COLUMN;
Roland McGrathcb6d8652007-08-23 08:10:54 +00008962 }
8963
8964 return colno;
8965}
8966
8967static void
Roland McGrath59ea7f32007-10-04 08:50:09 +00008968handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
Roland McGrathcb6d8652007-08-23 08:10:54 +00008969{
Roland McGrath59ea7f32007-10-04 08:50:09 +00008970 Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
8971 if (data == NULL)
8972 elf_error:
8973 error (EXIT_FAILURE, 0,
8974 gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
8975
Roland McGrathcb6d8652007-08-23 08:10:54 +00008976 const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
8977 for (size_t i = 0; i < nauxv; ++i)
8978 {
Roland McGrath59ea7f32007-10-04 08:50:09 +00008979 GElf_auxv_t av_mem;
8980 GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
8981 if (av == NULL)
8982 goto elf_error;
Roland McGrathcb6d8652007-08-23 08:10:54 +00008983
8984 const char *name;
8985 const char *fmt;
8986 if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
8987 {
8988 /* Unknown type. */
8989 if (av->a_un.a_val == 0)
8990 printf (" %" PRIu64 "\n", av->a_type);
8991 else
8992 printf (" %" PRIu64 ": %#" PRIx64 "\n",
8993 av->a_type, av->a_un.a_val);
8994 }
8995 else
8996 switch (fmt[0])
8997 {
8998 case '\0': /* Normally zero. */
8999 if (av->a_un.a_val == 0)
9000 {
9001 printf (" %s\n", name);
9002 break;
9003 }
9004 /* Fall through */
9005 case 'x': /* hex */
9006 case 'p': /* address */
9007 case 's': /* address of string */
9008 printf (" %s: %#" PRIx64 "\n", name, av->a_un.a_val);
9009 break;
9010 case 'u':
9011 printf (" %s: %" PRIu64 "\n", name, av->a_un.a_val);
9012 break;
9013 case 'd':
9014 printf (" %s: %" PRId64 "\n", name, av->a_un.a_val);
9015 break;
9016
9017 case 'b':
9018 printf (" %s: %#" PRIx64 " ", name, av->a_un.a_val);
9019 GElf_Xword bit = 1;
9020 const char *pfx = "<";
9021 for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
9022 {
9023 if (av->a_un.a_val & bit)
9024 {
9025 printf ("%s%s", pfx, p);
9026 pfx = " ";
9027 }
9028 bit <<= 1;
9029 }
9030 printf (">\n");
9031 break;
9032
9033 default:
9034 abort ();
9035 }
9036 }
9037}
9038
Petr Machataab224102013-09-26 00:39:34 +02009039static bool
9040buf_has_data (unsigned char const *ptr, unsigned char const *end, size_t sz)
9041{
9042 return ptr < end && (size_t) (end - ptr) >= sz;
9043}
9044
9045static bool
9046buf_read_int (Elf *core, unsigned char const **ptrp, unsigned char const *end,
9047 int *retp)
9048{
9049 if (! buf_has_data (*ptrp, end, 4))
9050 return false;
9051
9052 *ptrp = convert (core, ELF_T_WORD, 1, retp, *ptrp, 4);
9053 return true;
9054}
9055
9056static bool
9057buf_read_ulong (Elf *core, unsigned char const **ptrp, unsigned char const *end,
9058 uint64_t *retp)
9059{
9060 size_t sz = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
9061 if (! buf_has_data (*ptrp, end, sz))
9062 return false;
9063
9064 union
9065 {
9066 uint64_t u64;
9067 uint32_t u32;
9068 } u;
9069
Mark Wielaard110c2732014-04-10 15:02:53 +02009070 *ptrp = convert (core, ELF_T_ADDR, 1, &u, *ptrp, sz);
Petr Machataab224102013-09-26 00:39:34 +02009071
9072 if (sz == 4)
9073 *retp = u.u32;
9074 else
9075 *retp = u.u64;
9076 return true;
9077}
9078
9079static void
9080handle_siginfo_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
9081{
9082 Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
9083 if (data == NULL)
9084 error (EXIT_FAILURE, 0,
9085 gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
9086
9087 unsigned char const *ptr = data->d_buf;
9088 unsigned char const *const end = data->d_buf + data->d_size;
9089
9090 /* Siginfo head is three ints: signal number, error number, origin
9091 code. */
9092 int si_signo, si_errno, si_code;
9093 if (! buf_read_int (core, &ptr, end, &si_signo)
9094 || ! buf_read_int (core, &ptr, end, &si_errno)
9095 || ! buf_read_int (core, &ptr, end, &si_code))
9096 {
9097 fail:
9098 printf (" Not enough data in NT_SIGINFO note.\n");
9099 return;
9100 }
9101
9102 /* Next is a pointer-aligned union of structures. On 64-bit
9103 machines, that implies a word of padding. */
9104 if (gelf_getclass (core) == ELFCLASS64)
9105 ptr += 4;
9106
9107 printf (" si_signo: %d, si_errno: %d, si_code: %d\n",
9108 si_signo, si_errno, si_code);
9109
9110 if (si_code > 0)
9111 switch (si_signo)
9112 {
9113 case SIGILL:
9114 case SIGFPE:
9115 case SIGSEGV:
9116 case SIGBUS:
9117 {
9118 uint64_t addr;
9119 if (! buf_read_ulong (core, &ptr, end, &addr))
9120 goto fail;
9121 printf (" fault address: %#" PRIx64 "\n", addr);
9122 break;
9123 }
9124 default:
9125 ;
9126 }
9127 else if (si_code == SI_USER)
9128 {
9129 int pid, uid;
9130 if (! buf_read_int (core, &ptr, end, &pid)
9131 || ! buf_read_int (core, &ptr, end, &uid))
9132 goto fail;
9133 printf (" sender PID: %d, sender UID: %d\n", pid, uid);
9134 }
9135}
9136
Roland McGrathcb6d8652007-08-23 08:10:54 +00009137static void
Petr Machata0c9ae0c2013-09-26 21:02:22 +02009138handle_file_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
9139{
9140 Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
9141 if (data == NULL)
9142 error (EXIT_FAILURE, 0,
9143 gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
9144
9145 unsigned char const *ptr = data->d_buf;
9146 unsigned char const *const end = data->d_buf + data->d_size;
9147
9148 uint64_t count, page_size;
9149 if (! buf_read_ulong (core, &ptr, end, &count)
9150 || ! buf_read_ulong (core, &ptr, end, &page_size))
9151 {
9152 fail:
9153 printf (" Not enough data in NT_FILE note.\n");
9154 return;
9155 }
9156
Mark Wielaarda0da7562014-12-09 12:58:07 +01009157 size_t addrsize = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
9158 uint64_t maxcount = (size_t) (end - ptr) / (3 * addrsize);
9159 if (count > maxcount)
9160 goto fail;
9161
Petr Machata0c9ae0c2013-09-26 21:02:22 +02009162 /* Where file names are stored. */
Mark Wielaarda0da7562014-12-09 12:58:07 +01009163 unsigned char const *const fstart = ptr + 3 * count * addrsize;
Petr Machata0c9ae0c2013-09-26 21:02:22 +02009164 char const *fptr = (char *) fstart;
9165
9166 printf (" %" PRId64 " files:\n", count);
9167 for (uint64_t i = 0; i < count; ++i)
9168 {
9169 uint64_t mstart, mend, moffset;
9170 if (! buf_read_ulong (core, &ptr, fstart, &mstart)
9171 || ! buf_read_ulong (core, &ptr, fstart, &mend)
9172 || ! buf_read_ulong (core, &ptr, fstart, &moffset))
9173 goto fail;
9174
9175 const char *fnext = memchr (fptr, '\0', (char *) end - fptr);
9176 if (fnext == NULL)
9177 goto fail;
9178
9179 int ct = printf (" %08" PRIx64 "-%08" PRIx64
9180 " %08" PRIx64 " %" PRId64,
9181 mstart, mend, moffset * page_size, mend - mstart);
9182 printf ("%*s%s\n", ct > 50 ? 3 : 53 - ct, "", fptr);
9183
9184 fptr = fnext + 1;
9185 }
9186}
9187
9188static void
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08009189handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
9190 const char *name, const void *desc)
Roland McGrathcb6d8652007-08-23 08:10:54 +00009191{
9192 GElf_Word regs_offset;
9193 size_t nregloc;
9194 const Ebl_Register_Location *reglocs;
9195 size_t nitems;
9196 const Ebl_Core_Item *items;
9197
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08009198 if (! ebl_core_note (ebl, nhdr, name,
Roland McGrathcb6d8652007-08-23 08:10:54 +00009199 &regs_offset, &nregloc, &reglocs, &nitems, &items))
9200 return;
9201
Roland McGrath059c83e2008-02-21 06:19:39 +00009202 /* Pass 0 for DESCSZ when there are registers in the note,
9203 so that the ITEMS array does not describe the whole thing.
9204 For non-register notes, the actual descsz might be a multiple
9205 of the unit size, not just exactly the unit size. */
9206 unsigned int colno = handle_core_items (ebl->elf, desc,
9207 nregloc == 0 ? nhdr->n_descsz : 0,
9208 items, nitems);
Roland McGrathcb6d8652007-08-23 08:10:54 +00009209 if (colno != 0)
9210 putchar_unlocked ('\n');
9211
9212 colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
9213 reglocs, nregloc);
9214 if (colno != 0)
9215 putchar_unlocked ('\n');
9216}
9217
Roland McGrath59ea7f32007-10-04 08:50:09 +00009218static void
9219handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
9220 GElf_Off start, Elf_Data *data)
9221{
9222 fputs_unlocked (gettext (" Owner Data size Type\n"), stdout);
9223
9224 if (data == NULL)
9225 goto bad_note;
9226
9227 size_t offset = 0;
9228 GElf_Nhdr nhdr;
9229 size_t name_offset;
9230 size_t desc_offset;
9231 while (offset < data->d_size
9232 && (offset = gelf_getnote (data, offset,
9233 &nhdr, &name_offset, &desc_offset)) > 0)
9234 {
9235 const char *name = data->d_buf + name_offset;
9236 const char *desc = data->d_buf + desc_offset;
9237
9238 char buf[100];
9239 char buf2[100];
9240 printf (gettext (" %-13.*s %9" PRId32 " %s\n"),
9241 (int) nhdr.n_namesz, name, nhdr.n_descsz,
9242 ehdr->e_type == ET_CORE
9243 ? ebl_core_note_type_name (ebl, nhdr.n_type,
9244 buf, sizeof (buf))
Mark Wielaardbb9d1b42011-04-24 17:53:38 +02009245 : ebl_object_note_type_name (ebl, name, nhdr.n_type,
Roland McGrath59ea7f32007-10-04 08:50:09 +00009246 buf2, sizeof (buf2)));
9247
9248 /* Filter out invalid entries. */
9249 if (memchr (name, '\0', nhdr.n_namesz) != NULL
9250 /* XXX For now help broken Linux kernels. */
9251 || 1)
9252 {
9253 if (ehdr->e_type == ET_CORE)
9254 {
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08009255 if (nhdr.n_type == NT_AUXV
9256 && (nhdr.n_namesz == 4 /* Broken old Linux kernels. */
9257 || (nhdr.n_namesz == 5 && name[4] == '\0'))
9258 && !memcmp (name, "CORE", 4))
Roland McGrath59ea7f32007-10-04 08:50:09 +00009259 handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
9260 start + desc_offset);
Petr Machata0c9ae0c2013-09-26 21:02:22 +02009261 else if (nhdr.n_namesz == 5 && strcmp (name, "CORE") == 0)
9262 switch (nhdr.n_type)
9263 {
9264 case NT_SIGINFO:
9265 handle_siginfo_note (ebl->elf, nhdr.n_descsz,
9266 start + desc_offset);
9267 break;
9268
9269 case NT_FILE:
9270 handle_file_note (ebl->elf, nhdr.n_descsz,
9271 start + desc_offset);
9272 break;
9273
9274 default:
9275 handle_core_note (ebl, &nhdr, name, desc);
9276 }
Roland McGrath59ea7f32007-10-04 08:50:09 +00009277 else
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08009278 handle_core_note (ebl, &nhdr, name, desc);
Roland McGrath59ea7f32007-10-04 08:50:09 +00009279 }
9280 else
9281 ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc);
9282 }
9283 }
9284
9285 if (offset == data->d_size)
9286 return;
9287
9288 bad_note:
9289 error (EXIT_FAILURE, 0,
9290 gettext ("cannot get content of note section: %s"),
9291 elf_errmsg (-1));
9292}
Roland McGrathcb6d8652007-08-23 08:10:54 +00009293
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00009294static void
9295handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
9296{
Roland McGrath59ea7f32007-10-04 08:50:09 +00009297 /* If we have section headers, just look for SHT_NOTE sections.
9298 In a debuginfo file, the program headers are not reliable. */
9299 if (shnum != 0)
9300 {
9301 /* Get the section header string table index. */
9302 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07009303 if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
Roland McGrath59ea7f32007-10-04 08:50:09 +00009304 error (EXIT_FAILURE, 0,
9305 gettext ("cannot get section header string table index"));
9306
9307 Elf_Scn *scn = NULL;
9308 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
9309 {
9310 GElf_Shdr shdr_mem;
9311 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
9312
9313 if (shdr == NULL || shdr->sh_type != SHT_NOTE)
9314 /* Not what we are looking for. */
9315 continue;
9316
9317 printf (gettext ("\
9318\nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
9319 elf_ndxscn (scn),
9320 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
9321 shdr->sh_size, shdr->sh_offset);
9322
9323 handle_notes_data (ebl, ehdr, shdr->sh_offset,
9324 elf_getdata (scn, NULL));
9325 }
9326 return;
9327 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00009328
9329 /* We have to look through the program header to find the note
9330 sections. There can be more than one. */
Roland McGrath8111da02010-01-07 20:31:59 -08009331 for (size_t cnt = 0; cnt < phnum; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00009332 {
9333 GElf_Phdr mem;
9334 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
9335
9336 if (phdr == NULL || phdr->p_type != PT_NOTE)
9337 /* Not what we are looking for. */
9338 continue;
9339
9340 printf (gettext ("\
Roland McGrath59ea7f32007-10-04 08:50:09 +00009341\nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00009342 phdr->p_filesz, phdr->p_offset);
9343
Roland McGrath59ea7f32007-10-04 08:50:09 +00009344 handle_notes_data (ebl, ehdr, phdr->p_offset,
9345 elf_getdata_rawchunk (ebl->elf,
9346 phdr->p_offset, phdr->p_filesz,
9347 ELF_T_NHDR));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00009348 }
9349}
Roland McGrath60fc84c2007-08-03 21:59:15 +00009350
9351
9352static void
9353hex_dump (const uint8_t *data, size_t len)
9354{
9355 size_t pos = 0;
9356 while (pos < len)
9357 {
Roland McGrath241ac022007-10-01 18:21:46 +00009358 printf (" 0x%08Zx ", pos);
Roland McGrath60fc84c2007-08-03 21:59:15 +00009359
9360 const size_t chunk = MIN (len - pos, 16);
9361
9362 for (size_t i = 0; i < chunk; ++i)
9363 if (i % 4 == 3)
9364 printf ("%02x ", data[pos + i]);
9365 else
9366 printf ("%02x", data[pos + i]);
9367
9368 if (chunk < 16)
Roland McGrathe4c22ea2007-10-23 13:07:39 +00009369 printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
Roland McGrath60fc84c2007-08-03 21:59:15 +00009370
9371 for (size_t i = 0; i < chunk; ++i)
9372 {
9373 unsigned char b = data[pos + i];
Ulrich Drepperc98bcc72007-08-04 17:06:14 +00009374 printf ("%c", isprint (b) ? b : '.');
Roland McGrath60fc84c2007-08-03 21:59:15 +00009375 }
9376
9377 putchar ('\n');
9378 pos += chunk;
9379 }
9380}
9381
9382static void
Roland McGrathc76f0b02007-09-27 07:31:33 +00009383dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
9384{
9385 if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
9386 printf (gettext ("\nSection [%Zu] '%s' has no data to dump.\n"),
9387 elf_ndxscn (scn), name);
9388 else
9389 {
9390 Elf_Data *data = elf_rawdata (scn, NULL);
9391 if (data == NULL)
9392 error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
9393 elf_ndxscn (scn), name, elf_errmsg (-1));
9394 else
9395 {
9396 printf (gettext ("\nHex dump of section [%Zu] '%s', %" PRIu64
9397 " bytes at offset %#0" PRIx64 ":\n"),
9398 elf_ndxscn (scn), name,
9399 shdr->sh_size, shdr->sh_offset);
9400 hex_dump (data->d_buf, data->d_size);
9401 }
9402 }
9403}
9404
9405static void
9406print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
9407{
Roland McGrathefa64962009-11-16 01:50:58 -08009408 if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
9409 printf (gettext ("\nSection [%Zu] '%s' has no strings to dump.\n"),
Roland McGrathc76f0b02007-09-27 07:31:33 +00009410 elf_ndxscn (scn), name);
Roland McGrathc76f0b02007-09-27 07:31:33 +00009411 else
9412 {
Roland McGrathefa64962009-11-16 01:50:58 -08009413 Elf_Data *data = elf_rawdata (scn, NULL);
9414 if (data == NULL)
9415 error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
9416 elf_ndxscn (scn), name, elf_errmsg (-1));
9417 else
Roland McGrathc76f0b02007-09-27 07:31:33 +00009418 {
Roland McGrathefa64962009-11-16 01:50:58 -08009419 printf (gettext ("\nString section [%Zu] '%s' contains %" PRIu64
9420 " bytes at offset %#0" PRIx64 ":\n"),
9421 elf_ndxscn (scn), name,
9422 shdr->sh_size, shdr->sh_offset);
9423
9424 const char *start = data->d_buf;
9425 const char *const limit = start + data->d_size;
9426 do
Roland McGrathc76f0b02007-09-27 07:31:33 +00009427 {
Roland McGrathefa64962009-11-16 01:50:58 -08009428 const char *end = memchr (start, '\0', limit - start);
9429 const size_t pos = start - (const char *) data->d_buf;
9430 if (unlikely (end == NULL))
9431 {
9432 printf (" [%6Zx]- %.*s\n",
9433 pos, (int) (limit - start), start);
9434 break;
9435 }
9436 printf (" [%6Zx] %s\n", pos, start);
9437 start = end + 1;
9438 } while (start < limit);
9439 }
Roland McGrathc76f0b02007-09-27 07:31:33 +00009440 }
9441}
9442
9443static void
9444for_each_section_argument (Elf *elf, const struct section_argument *list,
9445 void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
9446 const char *name))
Roland McGrath60fc84c2007-08-03 21:59:15 +00009447{
9448 /* Get the section header string table index. */
9449 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07009450 if (elf_getshdrstrndx (elf, &shstrndx) < 0)
Roland McGrath60fc84c2007-08-03 21:59:15 +00009451 error (EXIT_FAILURE, 0,
9452 gettext ("cannot get section header string table index"));
9453
Roland McGrathc76f0b02007-09-27 07:31:33 +00009454 for (const struct section_argument *a = list; a != NULL; a = a->next)
Roland McGrath60fc84c2007-08-03 21:59:15 +00009455 {
9456 Elf_Scn *scn;
9457 GElf_Shdr shdr_mem;
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00009458 const char *name = NULL;
Roland McGrath60fc84c2007-08-03 21:59:15 +00009459
9460 char *endp = NULL;
9461 unsigned long int shndx = strtoul (a->arg, &endp, 0);
Ulrich Drepperc98bcc72007-08-04 17:06:14 +00009462 if (endp != a->arg && *endp == '\0')
Roland McGrath60fc84c2007-08-03 21:59:15 +00009463 {
Roland McGrathc76f0b02007-09-27 07:31:33 +00009464 scn = elf_getscn (elf, shndx);
Roland McGrath60fc84c2007-08-03 21:59:15 +00009465 if (scn == NULL)
9466 {
9467 error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
9468 continue;
9469 }
9470
9471 if (gelf_getshdr (scn, &shdr_mem) == NULL)
9472 error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
9473 elf_errmsg (-1));
Roland McGrathc76f0b02007-09-27 07:31:33 +00009474 name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
Roland McGrath60fc84c2007-08-03 21:59:15 +00009475 }
9476 else
9477 {
9478 /* Need to look up the section by name. */
9479 scn = NULL;
Roland McGrathf4763cf2010-08-11 13:04:12 -07009480 bool found = false;
Roland McGrathc76f0b02007-09-27 07:31:33 +00009481 while ((scn = elf_nextscn (elf, scn)) != NULL)
Roland McGrath60fc84c2007-08-03 21:59:15 +00009482 {
9483 if (gelf_getshdr (scn, &shdr_mem) == NULL)
9484 continue;
Roland McGrathc76f0b02007-09-27 07:31:33 +00009485 name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
Roland McGrath60fc84c2007-08-03 21:59:15 +00009486 if (name == NULL)
9487 continue;
9488 if (!strcmp (name, a->arg))
Roland McGrathf4763cf2010-08-11 13:04:12 -07009489 {
9490 found = true;
9491 (*dump) (scn, &shdr_mem, name);
9492 }
Roland McGrath60fc84c2007-08-03 21:59:15 +00009493 }
9494
Roland McGrathf4763cf2010-08-11 13:04:12 -07009495 if (unlikely (!found) && !a->implicit)
9496 error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
Roland McGrath60fc84c2007-08-03 21:59:15 +00009497 }
Roland McGrath60fc84c2007-08-03 21:59:15 +00009498 }
9499}
9500
9501static void
Roland McGrathc76f0b02007-09-27 07:31:33 +00009502dump_data (Ebl *ebl)
9503{
9504 for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
9505}
9506
9507static void
9508dump_strings (Ebl *ebl)
9509{
9510 for_each_section_argument (ebl->elf, string_sections, &print_string_section);
9511}
9512
9513static void
Roland McGrath60fc84c2007-08-03 21:59:15 +00009514print_strings (Ebl *ebl)
9515{
9516 /* Get the section header string table index. */
9517 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07009518 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Roland McGrath60fc84c2007-08-03 21:59:15 +00009519 error (EXIT_FAILURE, 0,
9520 gettext ("cannot get section header string table index"));
9521
9522 Elf_Scn *scn;
9523 GElf_Shdr shdr_mem;
9524 const char *name;
9525 scn = NULL;
9526 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
9527 {
9528 if (gelf_getshdr (scn, &shdr_mem) == NULL)
9529 continue;
9530
9531 if (shdr_mem.sh_type != SHT_PROGBITS
9532 || !(shdr_mem.sh_flags & SHF_STRINGS))
9533 continue;
9534
9535 name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
9536 if (name == NULL)
9537 continue;
9538
Roland McGrathc76f0b02007-09-27 07:31:33 +00009539 print_string_section (scn, &shdr_mem, name);
Roland McGrath60fc84c2007-08-03 21:59:15 +00009540 }
9541}
Roland McGrath59ea7f32007-10-04 08:50:09 +00009542
9543static void
9544dump_archive_index (Elf *elf, const char *fname)
9545{
9546 size_t narsym;
9547 const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
9548 if (arsym == NULL)
9549 {
9550 int result = elf_errno ();
Ulrich Drepper3fc3d7b2007-10-04 18:40:28 +00009551 if (unlikely (result != ELF_E_NO_INDEX))
Roland McGrath59ea7f32007-10-04 08:50:09 +00009552 error (EXIT_FAILURE, 0,
9553 gettext ("cannot get symbol index of archive '%s': %s"),
9554 fname, elf_errmsg (result));
9555 else
9556 printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
9557 return;
9558 }
9559
9560 printf (gettext ("\nIndex of archive '%s' has %Zu entries:\n"),
9561 fname, narsym);
9562
9563 size_t as_off = 0;
9564 for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
9565 {
9566 if (s->as_off != as_off)
9567 {
9568 as_off = s->as_off;
9569
9570 Elf *subelf;
Ulrich Drepper3fc3d7b2007-10-04 18:40:28 +00009571 if (unlikely (elf_rand (elf, as_off) == 0)
9572 || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
9573 == NULL))
9574#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
9575 while (1)
9576#endif
9577 error (EXIT_FAILURE, 0,
9578 gettext ("cannot extract member at offset %Zu in '%s': %s"),
9579 as_off, fname, elf_errmsg (-1));
Roland McGrath59ea7f32007-10-04 08:50:09 +00009580
9581 const Elf_Arhdr *h = elf_getarhdr (subelf);
9582
9583 printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
9584
9585 elf_end (subelf);
9586 }
9587
9588 printf ("\t%s\n", s->as_name);
9589 }
9590}
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00009591
9592#include "debugpred.h"