blob: f9f56aadaa28024b39c6ecc00cb26b947c7727c2 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Print information from ELF file in human-readable form.
Ulrich Drepper3a64a302012-01-21 18:19:24 -05002 Copyright (C) 1999-2012 Red Hat, Inc.
Ulrich Drepper361df7d2006-04-04 21:38:57 +00003 This file is part of Red Hat elfutils.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004 Written by Ulrich Drepper <drepper@redhat.com>, 1999.
5
Ulrich Drepper361df7d2006-04-04 21:38:57 +00006 Red Hat elfutils is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by the
8 Free Software Foundation; version 2 of the License.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00009
Ulrich Drepper361df7d2006-04-04 21:38:57 +000010 Red Hat elfutils is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with Red Hat elfutils; if not, write to the Free Software Foundation,
Ulrich Drepper1e9ef502006-04-04 22:29:06 +000017 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
Ulrich Drepper361df7d2006-04-04 21:38:57 +000018
19 Red Hat elfutils is an included package of the Open Invention Network.
20 An included package of the Open Invention Network is a package for which
21 Open Invention Network licensees cross-license their patents. No patent
22 license is granted, either expressly or impliedly, by designation as an
23 included package. Should you wish to participate in the Open Invention
24 Network licensing program, please visit www.openinventionnetwork.com
25 <http://www.openinventionnetwork.com>. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000026
27#ifdef HAVE_CONFIG_H
28# include <config.h>
29#endif
30
31#include <argp.h>
32#include <assert.h>
Ulrich Drepperc98bcc72007-08-04 17:06:14 +000033#include <ctype.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000034#include <dwarf.h>
35#include <errno.h>
36#include <error.h>
37#include <fcntl.h>
38#include <gelf.h>
39#include <inttypes.h>
40#include <langinfo.h>
41#include <libdw.h>
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000042#include <libdwfl.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000043#include <libintl.h>
44#include <locale.h>
Roland McGrathcb6d8652007-08-23 08:10:54 +000045#include <stdarg.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000046#include <stdbool.h>
47#include <stdlib.h>
48#include <string.h>
49#include <time.h>
50#include <unistd.h>
51#include <sys/param.h>
Roland McGrathb337b1f2010-01-15 01:02:27 -080052#include <sys/stat.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000053
54#include <system.h>
Roland McGrath59ea7f32007-10-04 08:50:09 +000055#include "../libelf/libelfP.h"
Roland McGrath059c83e2008-02-21 06:19:39 +000056#include "../libelf/common.h"
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000057#include "../libebl/libeblP.h"
58#include "../libdw/libdwP.h"
Roland McGrathe4c22ea2007-10-23 13:07:39 +000059#include "../libdwfl/libdwflP.h"
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000060#include "../libdw/memory-access.h"
61
62
63/* Name and version of program. */
64static void print_version (FILE *stream, struct argp_state *state);
Ulrich Drepperfdc93e12009-01-17 11:47:10 -080065ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000066
67/* Bug report address. */
Ulrich Drepperfdc93e12009-01-17 11:47:10 -080068ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000069
70/* Definitions of arguments for argp functions. */
71static const struct argp_option options[] =
72{
Roland McGratha7422be2010-01-04 20:29:33 -080073 { NULL, 0, NULL, 0, N_("ELF output selection:"), 0 },
74 { "all", 'a', NULL, 0,
75 N_("All these plus -p .strtab -p .dynstr -p .comment"), 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000076 { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
77 { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
78 { "histogram", 'I', NULL, 0,
79 N_("Display histogram of bucket list lengths"), 0 },
80 { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
Roland McGrath60fc84c2007-08-03 21:59:15 +000081 { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000082 { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
Roland McGratha7422be2010-01-04 20:29:33 -080083 { "section-headers", 'S', NULL, 0, N_("Display the sections' headers"), 0 },
Roland McGrath60fc84c2007-08-03 21:59:15 +000084 { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000085 { "symbols", 's', NULL, 0, N_("Display the symbol table"), 0 },
86 { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
Roland McGratha7422be2010-01-04 20:29:33 -080087 { "notes", 'n', NULL, 0, N_("Display the ELF notes"), 0 },
88 { "arch-specific", 'A', NULL, 0,
89 N_("Display architecture specific information, if any"), 0 },
90 { "exception", 'e', NULL, 0,
91 N_("Display sections for exception handling"), 0 },
92
93 { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000094 { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
95 N_("Display DWARF section content. SECTION can be one of abbrev, "
Mark Wielaard093a1d32011-04-14 23:47:26 +020096 "aranges, frame, gdb_index, info, loc, line, ranges, pubnames, str, "
97 "macinfo, or exception"), 0 },
Roland McGrath60fc84c2007-08-03 21:59:15 +000098 { "hex-dump", 'x', "SECTION", 0,
99 N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
Roland McGrathc76f0b02007-09-27 07:31:33 +0000100 { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
101 N_("Print string contents of sections"), 0 },
102 { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
Roland McGrath59ea7f32007-10-04 08:50:09 +0000103 { "archive-index", 'c', NULL, 0,
104 N_("Display the symbol index of an archive"), 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000105
106 { NULL, 0, NULL, 0, N_("Output control:"), 0 },
Roland McGrath5dbccdb2009-06-28 14:48:02 -0700107 { "numeric-addresses", 'N', NULL, 0,
108 N_("Do not find symbol names for addresses in DWARF data"), 0 },
Roland McGrathbd754192011-07-09 05:33:37 -0700109 { "wide", 'W', NULL, 0,
110 N_("Ignored for compatibility (lines always wide)"), 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000111 { NULL, 0, NULL, 0, NULL, 0 }
112};
113
114/* Short description of program. */
115static const char doc[] = N_("\
116Print information from ELF file in human-readable form.");
117
118/* Strings for arguments in help texts. */
119static const char args_doc[] = N_("FILE...");
120
121/* Prototype for option handler. */
122static error_t parse_opt (int key, char *arg, struct argp_state *state);
123
124/* Data structure to communicate with argp functions. */
125static struct argp argp =
126{
127 options, parse_opt, args_doc, doc, NULL, NULL, NULL
128};
129
130
131/* Flags set by the option controlling the output. */
132
133/* True if dynamic segment should be printed. */
134static bool print_dynamic_table;
135
136/* True if the file header should be printed. */
137static bool print_file_header;
138
139/* True if the program headers should be printed. */
140static bool print_program_header;
141
142/* True if relocations should be printed. */
143static bool print_relocations;
144
145/* True if the section headers should be printed. */
146static bool print_section_header;
147
148/* True if the symbol table should be printed. */
149static bool print_symbol_table;
150
151/* True if the version information should be printed. */
152static bool print_version_info;
153
154/* True if section groups should be printed. */
155static bool print_section_groups;
156
157/* True if bucket list length histogram should be printed. */
158static bool print_histogram;
159
160/* True if the architecture specific data should be printed. */
161static bool print_arch;
162
163/* True if note section content should be printed. */
164static bool print_notes;
165
Roland McGrath60fc84c2007-08-03 21:59:15 +0000166/* True if SHF_STRINGS section content should be printed. */
167static bool print_string_sections;
168
Roland McGrath59ea7f32007-10-04 08:50:09 +0000169/* True if archive index should be printed. */
170static bool print_archive_index;
171
172/* True if any of the control options except print_archive_index is set. */
173static bool any_control_option;
174
Roland McGrath5dbccdb2009-06-28 14:48:02 -0700175/* True if we should print addresses from DWARF in symbolic form. */
176static bool print_address_names = true;
177
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000178/* Select printing of debugging sections. */
179static enum section_e
180{
Ulrich Drepperb006fbf2009-01-16 03:08:25 -0800181 section_abbrev = 1, /* .debug_abbrev */
182 section_aranges = 2, /* .debug_aranges */
183 section_frame = 4, /* .debug_frame or .eh_frame & al. */
Roland McGrath2b1f0952010-06-20 17:55:50 -0700184 section_info = 8, /* .debug_info, .debug_types */
185 section_types = section_info,
Ulrich Drepperb006fbf2009-01-16 03:08:25 -0800186 section_line = 16, /* .debug_line */
187 section_loc = 32, /* .debug_loc */
188 section_pubnames = 64, /* .debug_pubnames */
189 section_str = 128, /* .debug_str */
190 section_macinfo = 256, /* .debug_macinfo */
191 section_ranges = 512, /* .debug_ranges */
192 section_exception = 1024, /* .eh_frame & al. */
Mark Wielaard093a1d32011-04-14 23:47:26 +0200193 section_gdb_index = 2048, /* .gdb_index */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000194 section_all = (section_abbrev | section_aranges | section_frame
195 | section_info | section_line | section_loc
196 | section_pubnames | section_str | section_macinfo
Mark Wielaard093a1d32011-04-14 23:47:26 +0200197 | section_ranges | section_exception | section_gdb_index)
Roland McGrath2e79deb2010-01-04 20:36:10 -0800198} print_debug_sections, implicit_debug_sections;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000199
Roland McGrath60fc84c2007-08-03 21:59:15 +0000200/* Select hex dumping of sections. */
201static struct section_argument *dump_data_sections;
202static struct section_argument **dump_data_sections_tail = &dump_data_sections;
203
Roland McGrathc76f0b02007-09-27 07:31:33 +0000204/* Select string dumping of sections. */
205static struct section_argument *string_sections;
206static struct section_argument **string_sections_tail = &string_sections;
207
Roland McGrath60fc84c2007-08-03 21:59:15 +0000208struct section_argument
209{
210 struct section_argument *next;
211 const char *arg;
Roland McGrathe4061d02010-01-04 20:25:09 -0800212 bool implicit;
Roland McGrath60fc84c2007-08-03 21:59:15 +0000213};
214
Roland McGrath8111da02010-01-07 20:31:59 -0800215/* Numbers of sections and program headers in the file. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000216static size_t shnum;
Roland McGrath8111da02010-01-07 20:31:59 -0800217static size_t phnum;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000218
219
220/* Declarations of local functions. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000221static void process_file (int fd, const char *fname, bool only_one);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000222static void process_elf_file (Dwfl_Module *dwflmod, int fd);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000223static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
224static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
225static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
226static void print_scngrp (Ebl *ebl);
Roland McGrath8111da02010-01-07 20:31:59 -0800227static void print_dynamic (Ebl *ebl);
Ulrich Drepperb47d2902009-06-01 07:38:32 -0700228static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
229static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
230 GElf_Shdr *shdr);
231static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
232 GElf_Shdr *shdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000233static void print_symtab (Ebl *ebl, int type);
234static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
235static void print_verinfo (Ebl *ebl);
236static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
237static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
238static void handle_versym (Ebl *ebl, Elf_Scn *scn,
239 GElf_Shdr *shdr);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000240static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000241static void handle_hash (Ebl *ebl);
242static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
243static void print_liblist (Ebl *ebl);
Roland McGrath059c83e2008-02-21 06:19:39 +0000244static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
Roland McGrath60fc84c2007-08-03 21:59:15 +0000245static void dump_data (Ebl *ebl);
Roland McGrathc76f0b02007-09-27 07:31:33 +0000246static void dump_strings (Ebl *ebl);
Roland McGrath60fc84c2007-08-03 21:59:15 +0000247static void print_strings (Ebl *ebl);
Roland McGrath59ea7f32007-10-04 08:50:09 +0000248static void dump_archive_index (Elf *, const char *);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000249
250
251int
252main (int argc, char *argv[])
253{
254 /* Set locale. */
255 setlocale (LC_ALL, "");
256
257 /* Initialize the message catalog. */
Ulrich Drepperb0243862007-06-06 00:09:36 +0000258 textdomain (PACKAGE_TARNAME);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000259
260 /* Parse and process arguments. */
261 int remaining;
262 argp_parse (&argp, argc, argv, 0, &remaining, NULL);
263
264 /* Before we start tell the ELF library which version we are using. */
265 elf_version (EV_CURRENT);
266
267 /* Now process all the files given at the command line. */
268 bool only_one = remaining + 1 == argc;
269 do
270 {
271 /* Open the file. */
272 int fd = open (argv[remaining], O_RDONLY);
273 if (fd == -1)
274 {
275 error (0, errno, gettext ("cannot open input file"));
276 continue;
277 }
278
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000279 process_file (fd, argv[remaining], only_one);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000280
281 close (fd);
282 }
283 while (++remaining < argc);
284
285 return error_message_count != 0;
286}
287
288
289/* Handle program arguments. */
290static error_t
291parse_opt (int key, char *arg,
292 struct argp_state *state __attribute__ ((unused)))
293{
Roland McGrathe4061d02010-01-04 20:25:09 -0800294 void add_dump_section (const char *name, bool implicit)
Ulrich Drepperd7285e12009-01-23 16:10:44 -0800295 {
296 struct section_argument *a = xmalloc (sizeof *a);
297 a->arg = name;
298 a->next = NULL;
Roland McGrathe4061d02010-01-04 20:25:09 -0800299 a->implicit = implicit;
Ulrich Drepperd7285e12009-01-23 16:10:44 -0800300 struct section_argument ***tailp
301 = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
302 **tailp = a;
303 *tailp = &a->next;
304 }
305
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000306 switch (key)
307 {
308 case 'a':
309 print_file_header = true;
310 print_program_header = true;
311 print_relocations = true;
312 print_section_header = true;
313 print_symbol_table = true;
314 print_version_info = true;
315 print_dynamic_table = true;
316 print_section_groups = true;
317 print_histogram = true;
318 print_arch = true;
319 print_notes = true;
Roland McGrath2e79deb2010-01-04 20:36:10 -0800320 implicit_debug_sections |= section_exception;
Roland McGrathe4061d02010-01-04 20:25:09 -0800321 add_dump_section (".strtab", true);
322 add_dump_section (".dynstr", true);
323 add_dump_section (".comment", true);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000324 any_control_option = true;
325 break;
326 case 'A':
327 print_arch = true;
328 any_control_option = true;
329 break;
330 case 'd':
331 print_dynamic_table = true;
332 any_control_option = true;
333 break;
Ulrich Drepperb006fbf2009-01-16 03:08:25 -0800334 case 'e':
335 print_debug_sections |= section_exception;
336 any_control_option = true;
337 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000338 case 'g':
339 print_section_groups = true;
340 any_control_option = true;
341 break;
342 case 'h':
343 print_file_header = true;
344 any_control_option = true;
345 break;
346 case 'I':
347 print_histogram = true;
348 any_control_option = true;
349 break;
350 case 'l':
351 print_program_header = true;
352 any_control_option = true;
353 break;
354 case 'n':
355 print_notes = true;
356 any_control_option = true;
357 break;
358 case 'r':
359 print_relocations = true;
360 any_control_option = true;
361 break;
362 case 'S':
363 print_section_header = true;
364 any_control_option = true;
365 break;
366 case 's':
367 print_symbol_table = true;
368 any_control_option = true;
369 break;
370 case 'V':
371 print_version_info = true;
372 any_control_option = true;
373 break;
Roland McGrath59ea7f32007-10-04 08:50:09 +0000374 case 'c':
375 print_archive_index = true;
376 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000377 case 'w':
378 if (arg == NULL)
379 print_debug_sections = section_all;
380 else if (strcmp (arg, "abbrev") == 0)
381 print_debug_sections |= section_abbrev;
382 else if (strcmp (arg, "aranges") == 0)
383 print_debug_sections |= section_aranges;
384 else if (strcmp (arg, "ranges") == 0)
Roland McGrathfa144952010-08-30 19:22:41 -0700385 {
386 print_debug_sections |= section_ranges;
387 implicit_debug_sections |= section_info;
388 }
Ulrich Drepperac194d02009-01-06 00:30:01 -0800389 else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000390 print_debug_sections |= section_frame;
391 else if (strcmp (arg, "info") == 0)
392 print_debug_sections |= section_info;
393 else if (strcmp (arg, "loc") == 0)
Roland McGrathfa144952010-08-30 19:22:41 -0700394 {
395 print_debug_sections |= section_loc;
396 implicit_debug_sections |= section_info;
397 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000398 else if (strcmp (arg, "line") == 0)
399 print_debug_sections |= section_line;
400 else if (strcmp (arg, "pubnames") == 0)
401 print_debug_sections |= section_pubnames;
402 else if (strcmp (arg, "str") == 0)
403 print_debug_sections |= section_str;
404 else if (strcmp (arg, "macinfo") == 0)
405 print_debug_sections |= section_macinfo;
Ulrich Drepperb006fbf2009-01-16 03:08:25 -0800406 else if (strcmp (arg, "exception") == 0)
407 print_debug_sections |= section_exception;
Mark Wielaard093a1d32011-04-14 23:47:26 +0200408 else if (strcmp (arg, "gdb_index") == 0)
409 print_debug_sections |= section_gdb_index;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000410 else
411 {
412 fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
413 arg);
414 argp_help (&argp, stderr, ARGP_HELP_SEE,
415 program_invocation_short_name);
416 exit (1);
417 }
418 any_control_option = true;
419 break;
Roland McGrathc76f0b02007-09-27 07:31:33 +0000420 case 'p':
421 any_control_option = true;
422 if (arg == NULL)
423 {
424 print_string_sections = true;
425 break;
426 }
427 /* Fall through. */
Roland McGrath60fc84c2007-08-03 21:59:15 +0000428 case 'x':
Roland McGrathe4061d02010-01-04 20:25:09 -0800429 add_dump_section (arg, false);
Roland McGrath60fc84c2007-08-03 21:59:15 +0000430 any_control_option = true;
431 break;
Roland McGrath5dbccdb2009-06-28 14:48:02 -0700432 case 'N':
433 print_address_names = false;
434 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000435 case ARGP_KEY_NO_ARGS:
436 fputs (gettext ("Missing file name.\n"), stderr);
437 goto do_argp_help;
438 case ARGP_KEY_FINI:
Roland McGrath59ea7f32007-10-04 08:50:09 +0000439 if (! any_control_option && ! print_archive_index)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000440 {
441 fputs (gettext ("No operation specified.\n"), stderr);
442 do_argp_help:
Ulrich Drepper5ee720c2009-02-01 16:18:18 -0800443 argp_help (&argp, stderr, ARGP_HELP_SEE,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000444 program_invocation_short_name);
Ulrich Drepper5ee720c2009-02-01 16:18:18 -0800445 exit (EXIT_FAILURE);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000446 }
447 break;
Roland McGrathbd754192011-07-09 05:33:37 -0700448 case 'W': /* Ignored. */
449 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000450 default:
451 return ARGP_ERR_UNKNOWN;
452 }
453 return 0;
454}
455
456
457/* Print the version information. */
458static void
459print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
460{
Ulrich Drepperb0243862007-06-06 00:09:36 +0000461 fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000462 fprintf (stream, gettext ("\
463Copyright (C) %s Red Hat, Inc.\n\
464This is free software; see the source for copying conditions. There is NO\n\
465warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
Ulrich Drepper3a64a302012-01-21 18:19:24 -0500466"), "2012");
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000467 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
468}
469
470
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000471/* Check if the file is an archive, and if so dump its index. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000472static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000473check_archive_index (int fd, const char *fname, bool only_one)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000474{
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000475 /* Create an `Elf' descriptor. */
476 Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
477 if (elf == NULL)
478 error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
479 elf_errmsg (-1));
480 else
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000481 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000482 if (elf_kind (elf) == ELF_K_AR)
483 {
484 if (!only_one)
485 printf ("\n%s:\n\n", fname);
486 dump_archive_index (elf, fname);
487 }
488 else
Roland McGrath59ea7f32007-10-04 08:50:09 +0000489 error (0, 0,
490 gettext ("'%s' is not an archive, cannot print archive index"),
491 fname);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000492
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000493 /* Now we can close the descriptor. */
494 if (elf_end (elf) != 0)
495 error (0, 0, gettext ("error while closing Elf descriptor: %s"),
496 elf_errmsg (-1));
497 }
498}
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000499
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000500/* Trivial callback used for checking if we opened an archive. */
501static int
502count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
503 void **userdata __attribute__ ((unused)),
504 const char *name __attribute__ ((unused)),
505 Dwarf_Addr base __attribute__ ((unused)),
506 void *arg)
507{
Roland McGratha845f682008-12-03 03:41:58 +0000508 if (*(bool *) arg)
509 return DWARF_CB_ABORT;
510 *(bool *) arg = true;
511 return DWARF_CB_OK;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000512}
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000513
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000514struct process_dwflmod_args
515{
516 int fd;
517 bool only_one;
518};
519
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000520static int
521process_dwflmod (Dwfl_Module *dwflmod,
522 void **userdata __attribute__ ((unused)),
523 const char *name __attribute__ ((unused)),
524 Dwarf_Addr base __attribute__ ((unused)),
525 void *arg)
526{
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000527 const struct process_dwflmod_args *a = arg;
Roland McGrath59ea7f32007-10-04 08:50:09 +0000528
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000529 /* Print the file name. */
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000530 if (!a->only_one)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000531 {
532 const char *fname;
533 dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000534
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000535 printf ("\n%s:\n\n", fname);
536 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000537
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000538 process_elf_file (dwflmod, a->fd);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000539
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000540 return DWARF_CB_OK;
541}
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000542
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000543/* Stub libdwfl callback, only the ELF handle already open is ever used. */
544static int
545find_no_debuginfo (Dwfl_Module *mod __attribute__ ((unused)),
546 void **userdata __attribute__ ((unused)),
547 const char *modname __attribute__ ((unused)),
548 Dwarf_Addr base __attribute__ ((unused)),
549 const char *file_name __attribute__ ((unused)),
550 const char *debuglink_file __attribute__ ((unused)),
551 GElf_Word debuglink_crc __attribute__ ((unused)),
552 char **debuginfo_file_name __attribute__ ((unused)))
553{
554 return -1;
555}
556
557/* Process one input file. */
558static void
559process_file (int fd, const char *fname, bool only_one)
560{
561 if (print_archive_index)
562 check_archive_index (fd, fname, only_one);
563
564 if (!any_control_option)
565 return;
566
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000567 /* Duplicate an fd for dwfl_report_offline to swallow. */
568 int dwfl_fd = dup (fd);
569 if (unlikely (dwfl_fd < 0))
570 error (EXIT_FAILURE, errno, "dup");
571
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000572 /* Use libdwfl in a trivial way to open the libdw handle for us.
573 This takes care of applying relocations to DWARF data in ET_REL files. */
574 static const Dwfl_Callbacks callbacks =
575 {
576 .section_address = dwfl_offline_section_address,
577 .find_debuginfo = find_no_debuginfo
578 };
579 Dwfl *dwfl = dwfl_begin (&callbacks);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000580 if (likely (dwfl != NULL))
581 /* Let 0 be the logical address of the file (or first in archive). */
582 dwfl->offline_next_address = 0;
583 if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000584 {
585 struct stat64 st;
Roland McGrath890081b2010-02-26 17:57:50 -0800586 if (fstat64 (dwfl_fd, &st) != 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000587 error (0, errno, gettext ("cannot stat input file"));
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000588 else if (unlikely (st.st_size == 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000589 error (0, 0, gettext ("input file is empty"));
590 else
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000591 error (0, 0, gettext ("failed reading '%s': %s"),
592 fname, dwfl_errmsg (-1));
Roland McGrath890081b2010-02-26 17:57:50 -0800593 close (dwfl_fd); /* Consumed on success, not on failure. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000594 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000595 else
596 {
597 dwfl_report_end (dwfl, NULL, NULL);
598
599 if (only_one)
Roland McGratha845f682008-12-03 03:41:58 +0000600 {
601 /* Clear ONLY_ONE if we have multiple modules, from an archive. */
602 bool seen = false;
603 only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
604 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000605
606 /* Process the one or more modules gleaned from this file. */
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000607 struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
608 dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000609 }
610 dwfl_end (dwfl);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000611}
612
613
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000614/* Process one ELF file. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000615static void
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000616process_elf_file (Dwfl_Module *dwflmod, int fd)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000617{
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000618 GElf_Addr dwflbias;
619 Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
620
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000621 GElf_Ehdr ehdr_mem;
622 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000623
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000624 if (ehdr == NULL)
625 {
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000626 elf_error:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000627 error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
628 return;
629 }
630
Ulrich Drepperd0449522005-09-03 07:23:52 +0000631 Ebl *ebl = ebl_openbackend (elf);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000632 if (unlikely (ebl == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000633 {
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000634 ebl_error:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000635 error (0, errno, gettext ("cannot create EBL handle"));
636 return;
637 }
638
639 /* Determine the number of sections. */
Ulrich Drepperf1894932009-06-13 15:55:42 -0700640 if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000641 error (EXIT_FAILURE, 0,
642 gettext ("cannot determine number of sections: %s"),
643 elf_errmsg (-1));
644
Roland McGrath8111da02010-01-07 20:31:59 -0800645 /* Determine the number of phdrs. */
646 if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
647 error (EXIT_FAILURE, 0,
648 gettext ("cannot determine number of program headers: %s"),
649 elf_errmsg (-1));
650
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000651 /* For an ET_REL file, libdwfl has adjusted the in-core shdrs
652 and may have applied relocation to some sections.
653 So we need to get a fresh Elf handle on the file to display those. */
654 bool print_unrelocated = (print_section_header
655 || print_relocations
656 || dump_data_sections != NULL
657 || print_notes);
658
659 Elf *pure_elf = NULL;
660 Ebl *pure_ebl = ebl;
661 if (ehdr->e_type == ET_REL && print_unrelocated)
662 {
663 /* Read the file afresh. */
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000664 off64_t aroff = elf_getaroff (elf);
Ulrich Drepperfbc708d2008-01-21 18:44:55 +0000665 pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000666 if (aroff > 0)
667 {
668 /* Archive member. */
669 (void) elf_rand (pure_elf, aroff);
670 Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
671 elf_end (pure_elf);
672 pure_elf = armem;
673 }
674 if (pure_elf == NULL)
675 goto elf_error;
676 pure_ebl = ebl_openbackend (pure_elf);
677 if (pure_ebl == NULL)
678 goto ebl_error;
679 }
680
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000681 if (print_file_header)
682 print_ehdr (ebl, ehdr);
683 if (print_section_header)
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000684 print_shdr (pure_ebl, ehdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000685 if (print_program_header)
686 print_phdr (ebl, ehdr);
687 if (print_section_groups)
688 print_scngrp (ebl);
689 if (print_dynamic_table)
Roland McGrath8111da02010-01-07 20:31:59 -0800690 print_dynamic (ebl);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000691 if (print_relocations)
Ulrich Drepperb47d2902009-06-01 07:38:32 -0700692 print_relocs (pure_ebl, ehdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000693 if (print_histogram)
694 handle_hash (ebl);
695 if (print_symbol_table)
696 print_symtab (ebl, SHT_DYNSYM);
697 if (print_version_info)
698 print_verinfo (ebl);
699 if (print_symbol_table)
700 print_symtab (ebl, SHT_SYMTAB);
701 if (print_arch)
702 print_liblist (ebl);
Roland McGrath059c83e2008-02-21 06:19:39 +0000703 if (print_arch)
704 print_attributes (ebl, ehdr);
Roland McGrath60fc84c2007-08-03 21:59:15 +0000705 if (dump_data_sections != NULL)
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000706 dump_data (pure_ebl);
Roland McGrathc76f0b02007-09-27 07:31:33 +0000707 if (string_sections != NULL)
708 dump_strings (ebl);
Roland McGrath2e79deb2010-01-04 20:36:10 -0800709 if ((print_debug_sections | implicit_debug_sections) != 0)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000710 print_debug (dwflmod, ebl, ehdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000711 if (print_notes)
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000712 handle_notes (pure_ebl, ehdr);
Roland McGrath60fc84c2007-08-03 21:59:15 +0000713 if (print_string_sections)
714 print_strings (ebl);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000715
716 ebl_closebackend (ebl);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000717
718 if (pure_ebl != ebl)
719 {
720 ebl_closebackend (pure_ebl);
721 elf_end (pure_elf);
722 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000723}
724
725
726/* Print file type. */
727static void
728print_file_type (unsigned short int e_type)
729{
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000730 if (likely (e_type <= ET_CORE))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000731 {
Ulrich Drepper8b383102007-02-16 00:31:57 +0000732 static const char *const knowntypes[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000733 {
734 N_("NONE (None)"),
735 N_("REL (Relocatable file)"),
736 N_("EXEC (Executable file)"),
737 N_("DYN (Shared object file)"),
738 N_("CORE (Core file)")
739 };
740 puts (gettext (knowntypes[e_type]));
741 }
742 else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
743 printf (gettext ("OS Specific: (%x)\n"), e_type);
744 else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
745 printf (gettext ("Processor Specific: (%x)\n"), e_type);
746 else
747 puts ("???");
748}
749
750
751/* Print ELF header. */
752static void
753print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
754{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000755 fputs_unlocked (gettext ("ELF Header:\n Magic: "), stdout);
Ulrich Drepperd0449522005-09-03 07:23:52 +0000756 for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000757 printf (" %02hhx", ehdr->e_ident[cnt]);
758
759 printf (gettext ("\n Class: %s\n"),
760 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
761 : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
762 : "\?\?\?");
763
764 printf (gettext (" Data: %s\n"),
765 ehdr->e_ident[EI_DATA] == ELFDATA2LSB
766 ? "2's complement, little endian"
767 : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
768 ? "2's complement, big endian" : "\?\?\?");
769
Ulrich Drepper41a99082006-05-28 00:01:43 +0000770 printf (gettext (" Ident Version: %hhd %s\n"),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000771 ehdr->e_ident[EI_VERSION],
772 ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
773 : "(\?\?\?)");
774
Ulrich Drepperd0449522005-09-03 07:23:52 +0000775 char buf[512];
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000776 printf (gettext (" OS/ABI: %s\n"),
777 ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
778
779 printf (gettext (" ABI Version: %hhd\n"),
780 ehdr->e_ident[EI_ABIVERSION]);
781
782 fputs_unlocked (gettext (" Type: "), stdout);
783 print_file_type (ehdr->e_type);
784
785 printf (gettext (" Machine: %s\n"), ebl->name);
786
787 printf (gettext (" Version: %d %s\n"),
788 ehdr->e_version,
789 ehdr->e_version == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
790
791 printf (gettext (" Entry point address: %#" PRIx64 "\n"),
792 ehdr->e_entry);
793
794 printf (gettext (" Start of program headers: %" PRId64 " %s\n"),
795 ehdr->e_phoff, gettext ("(bytes into file)"));
796
797 printf (gettext (" Start of section headers: %" PRId64 " %s\n"),
798 ehdr->e_shoff, gettext ("(bytes into file)"));
799
800 printf (gettext (" Flags: %s\n"),
801 ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
802
803 printf (gettext (" Size of this header: %" PRId16 " %s\n"),
804 ehdr->e_ehsize, gettext ("(bytes)"));
805
806 printf (gettext (" Size of program header entries: %" PRId16 " %s\n"),
807 ehdr->e_phentsize, gettext ("(bytes)"));
808
Roland McGrath8111da02010-01-07 20:31:59 -0800809 printf (gettext (" Number of program headers entries: %" PRId16),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000810 ehdr->e_phnum);
Roland McGrath8111da02010-01-07 20:31:59 -0800811 if (ehdr->e_phnum == PN_XNUM)
812 {
813 GElf_Shdr shdr_mem;
814 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
815 if (shdr != NULL)
816 printf (gettext (" (%" PRIu32 " in [0].sh_info)"),
817 (uint32_t) shdr->sh_info);
818 else
819 fputs_unlocked (gettext (" ([0] not available)"), stdout);
820 }
821 fputc_unlocked ('\n', stdout);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000822
823 printf (gettext (" Size of section header entries: %" PRId16 " %s\n"),
824 ehdr->e_shentsize, gettext ("(bytes)"));
825
826 printf (gettext (" Number of section headers entries: %" PRId16),
827 ehdr->e_shnum);
828 if (ehdr->e_shnum == 0)
829 {
830 GElf_Shdr shdr_mem;
Ulrich Drepperd0449522005-09-03 07:23:52 +0000831 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000832 if (shdr != NULL)
833 printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
834 (uint32_t) shdr->sh_size);
835 else
836 fputs_unlocked (gettext (" ([0] not available)"), stdout);
837 }
838 fputc_unlocked ('\n', stdout);
839
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000840 if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000841 {
842 GElf_Shdr shdr_mem;
Ulrich Drepperd0449522005-09-03 07:23:52 +0000843 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000844 if (shdr != NULL)
845 /* We managed to get the zeroth section. */
846 snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
847 (uint32_t) shdr->sh_link);
848 else
849 {
850 strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
851 buf[sizeof (buf) - 1] = '\0';
852 }
853
854 printf (gettext (" Section header string table index: XINDEX%s\n\n"),
855 buf);
856 }
857 else
858 printf (gettext (" Section header string table index: %" PRId16 "\n\n"),
859 ehdr->e_shstrndx);
860}
861
862
863static const char *
864get_visibility_type (int value)
865{
866 switch (value)
867 {
868 case STV_DEFAULT:
869 return "DEFAULT";
870 case STV_INTERNAL:
871 return "INTERNAL";
872 case STV_HIDDEN:
873 return "HIDDEN";
874 case STV_PROTECTED:
875 return "PROTECTED";
876 default:
877 return "???";
878 }
879}
880
881
882/* Print the section headers. */
883static void
884print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
885{
886 size_t cnt;
887 size_t shstrndx;
888
889 if (! print_file_header)
890 printf (gettext ("\
891There are %d section headers, starting at offset %#" PRIx64 ":\n\
892\n"),
893 ehdr->e_shnum, ehdr->e_shoff);
894
895 /* Get the section header string table index. */
Ulrich Drepperf1894932009-06-13 15:55:42 -0700896 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000897 error (EXIT_FAILURE, 0,
898 gettext ("cannot get section header string table index"));
899
900 puts (gettext ("Section Headers:"));
901
902 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
903 puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
904 else
905 puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
906
907 for (cnt = 0; cnt < shnum; ++cnt)
908 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000909 Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000910
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000911 if (unlikely (scn == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000912 error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
913 elf_errmsg (-1));
914
915 /* Get the section header. */
Ulrich Drepperd0449522005-09-03 07:23:52 +0000916 GElf_Shdr shdr_mem;
917 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000918 if (unlikely (shdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000919 error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
920 elf_errmsg (-1));
921
Ulrich Drepperd0449522005-09-03 07:23:52 +0000922 char flagbuf[20];
923 char *cp = flagbuf;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000924 if (shdr->sh_flags & SHF_WRITE)
925 *cp++ = 'W';
926 if (shdr->sh_flags & SHF_ALLOC)
927 *cp++ = 'A';
928 if (shdr->sh_flags & SHF_EXECINSTR)
929 *cp++ = 'X';
930 if (shdr->sh_flags & SHF_MERGE)
931 *cp++ = 'M';
932 if (shdr->sh_flags & SHF_STRINGS)
933 *cp++ = 'S';
934 if (shdr->sh_flags & SHF_INFO_LINK)
935 *cp++ = 'I';
936 if (shdr->sh_flags & SHF_LINK_ORDER)
937 *cp++ = 'L';
938 if (shdr->sh_flags & SHF_OS_NONCONFORMING)
939 *cp++ = 'N';
940 if (shdr->sh_flags & SHF_GROUP)
941 *cp++ = 'G';
942 if (shdr->sh_flags & SHF_TLS)
943 *cp++ = 'T';
944 if (shdr->sh_flags & SHF_ORDERED)
945 *cp++ = 'O';
946 if (shdr->sh_flags & SHF_EXCLUDE)
947 *cp++ = 'E';
948 *cp = '\0';
949
Ulrich Drepperd0449522005-09-03 07:23:52 +0000950 char buf[128];
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000951 printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
952 " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
953 " %2" PRId64 "\n",
954 cnt,
955 elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
956 ?: "<corrupt>",
957 ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
958 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
959 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
960 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
961 shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
962 shdr->sh_addralign);
963 }
964
965 fputc_unlocked ('\n', stdout);
966}
967
968
969/* Print the program header. */
970static void
971print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
972{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000973 if (ehdr->e_phnum == 0)
974 /* No program header, this is OK in relocatable objects. */
975 return;
976
977 puts (gettext ("Program Headers:"));
978 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
979 puts (gettext ("\
980 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
981 else
982 puts (gettext ("\
983 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
984
985 /* Process all program headers. */
986 bool has_relro = false;
987 GElf_Addr relro_from = 0;
988 GElf_Addr relro_to = 0;
Roland McGrath8111da02010-01-07 20:31:59 -0800989 for (size_t cnt = 0; cnt < phnum; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000990 {
991 char buf[128];
992 GElf_Phdr mem;
993 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
994
995 /* If for some reason the header cannot be returned show this. */
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000996 if (unlikely (phdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000997 {
998 puts (" ???");
999 continue;
1000 }
1001
1002 printf (" %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
1003 " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
1004 ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
1005 phdr->p_offset,
1006 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
1007 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
1008 phdr->p_filesz,
1009 phdr->p_memsz,
1010 phdr->p_flags & PF_R ? 'R' : ' ',
1011 phdr->p_flags & PF_W ? 'W' : ' ',
1012 phdr->p_flags & PF_X ? 'E' : ' ',
1013 phdr->p_align);
1014
1015 if (phdr->p_type == PT_INTERP)
1016 {
1017 /* We can show the user the name of the interpreter. */
1018 size_t maxsize;
1019 char *filedata = elf_rawfile (ebl->elf, &maxsize);
1020
1021 if (filedata != NULL && phdr->p_offset < maxsize)
1022 printf (gettext ("\t[Requesting program interpreter: %s]\n"),
1023 filedata + phdr->p_offset);
1024 }
1025 else if (phdr->p_type == PT_GNU_RELRO)
1026 {
1027 has_relro = true;
1028 relro_from = phdr->p_vaddr;
1029 relro_to = relro_from + phdr->p_memsz;
1030 }
1031 }
1032
Roland McGrath9a847e12009-01-22 19:55:00 -08001033 if (ehdr->e_shnum == 0)
1034 /* No sections in the file. Punt. */
1035 return;
1036
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001037 /* Get the section header string table index. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001038 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001039 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001040 error (EXIT_FAILURE, 0,
1041 gettext ("cannot get section header string table index"));
1042
1043 puts (gettext ("\n Section to Segment mapping:\n Segment Sections..."));
1044
Roland McGrath8111da02010-01-07 20:31:59 -08001045 for (size_t cnt = 0; cnt < phnum; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001046 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001047 /* Print the segment number. */
1048 printf (" %2.2zu ", cnt);
1049
Ulrich Drepperd0449522005-09-03 07:23:52 +00001050 GElf_Phdr phdr_mem;
1051 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001052 /* This must not happen. */
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001053 if (unlikely (phdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001054 error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
1055 elf_errmsg (-1));
1056
1057 /* Iterate over the sections. */
1058 bool in_relro = false;
1059 bool in_ro = false;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001060 for (size_t inner = 1; inner < shnum; ++inner)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001061 {
1062 Elf_Scn *scn = elf_getscn (ebl->elf, inner);
Ulrich Drepperd0449522005-09-03 07:23:52 +00001063 /* This should not happen. */
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001064 if (unlikely (scn == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001065 error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
1066 elf_errmsg (-1));
1067
1068 /* Get the section header. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001069 GElf_Shdr shdr_mem;
1070 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001071 if (unlikely (shdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001072 error (EXIT_FAILURE, 0,
1073 gettext ("cannot get section header: %s"),
1074 elf_errmsg (-1));
1075
1076 if (shdr->sh_size > 0
1077 /* Compare allocated sections by VMA, unallocated
1078 sections by file offset. */
1079 && (shdr->sh_flags & SHF_ALLOC
1080 ? (shdr->sh_addr >= phdr->p_vaddr
1081 && (shdr->sh_addr + shdr->sh_size
1082 <= phdr->p_vaddr + phdr->p_memsz))
1083 : (shdr->sh_offset >= phdr->p_offset
1084 && (shdr->sh_offset + shdr->sh_size
1085 <= phdr->p_offset + phdr->p_filesz))))
1086 {
1087 if (has_relro && !in_relro
1088 && shdr->sh_addr >= relro_from
1089 && shdr->sh_addr + shdr->sh_size <= relro_to)
1090 {
1091 fputs_unlocked (" [RELRO:", stdout);
1092 in_relro = true;
1093 }
1094 else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
1095 {
1096 fputs_unlocked ("]", stdout);
1097 in_relro = false;
1098 }
1099 else if (has_relro && in_relro
1100 && shdr->sh_addr + shdr->sh_size > relro_to)
1101 fputs_unlocked ("] <RELRO:", stdout);
1102 else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
1103 {
1104 if (!in_ro)
1105 {
1106 fputs_unlocked (" [RO:", stdout);
1107 in_ro = true;
1108 }
1109 }
1110 else
1111 {
1112 /* Determine the segment this section is part of. */
1113 size_t cnt2;
1114 GElf_Phdr *phdr2 = NULL;
Roland McGrath8111da02010-01-07 20:31:59 -08001115 for (cnt2 = 0; cnt2 < phnum; ++cnt2)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001116 {
1117 GElf_Phdr phdr2_mem;
1118 phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
1119
1120 if (phdr2 != NULL && phdr2->p_type == PT_LOAD
1121 && shdr->sh_addr >= phdr2->p_vaddr
1122 && (shdr->sh_addr + shdr->sh_size
1123 <= phdr2->p_vaddr + phdr2->p_memsz))
1124 break;
1125 }
1126
Roland McGrath8111da02010-01-07 20:31:59 -08001127 if (cnt2 < phnum)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001128 {
1129 if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
1130 {
1131 fputs_unlocked (" [RO:", stdout);
1132 in_ro = true;
1133 }
1134 else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
1135 {
1136 fputs_unlocked ("]", stdout);
1137 in_ro = false;
1138 }
1139 }
1140 }
1141
1142 printf (" %s",
1143 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1144
1145 /* Signal that this sectin is only partially covered. */
1146 if (has_relro && in_relro
1147 && shdr->sh_addr + shdr->sh_size > relro_to)
1148 {
1149 fputs_unlocked (">", stdout);
1150 in_relro = false;
1151 }
1152 }
1153 }
1154 if (in_relro || in_ro)
1155 fputs_unlocked ("]", stdout);
1156
1157 /* Finish the line. */
1158 fputc_unlocked ('\n', stdout);
1159 }
1160}
1161
1162
Roland McGrath725aad52011-02-23 19:52:46 -08001163static const char *
1164section_name (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr)
1165{
1166 return elf_strptr (ebl->elf, ehdr->e_shstrndx, shdr->sh_name) ?: "???";
1167}
1168
1169
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001170static void
1171handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1172{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001173 /* Get the data of the section. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001174 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001175
Ulrich Drepperd0449522005-09-03 07:23:52 +00001176 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1177 GElf_Shdr symshdr_mem;
1178 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1179 Elf_Data *symdata = elf_getdata (symscn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001180
1181 if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
1182 || symdata == NULL)
1183 return;
1184
1185 /* Get the section header string table index. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001186 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001187 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001188 error (EXIT_FAILURE, 0,
1189 gettext ("cannot get section header string table index"));
1190
Ulrich Drepperd0449522005-09-03 07:23:52 +00001191 Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001192
Ulrich Drepperd0449522005-09-03 07:23:52 +00001193 GElf_Sym sym_mem;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001194 printf ((grpref[0] & GRP_COMDAT)
1195 ? ngettext ("\
1196\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
1197 "\
1198\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1199 data->d_size / sizeof (Elf32_Word) - 1)
1200 : ngettext ("\
1201\nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
1202\nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1203 data->d_size / sizeof (Elf32_Word) - 1),
1204 elf_ndxscn (scn),
1205 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1206 elf_strptr (ebl->elf, symshdr->sh_link,
1207 gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name)
1208 ?: gettext ("<INVALID SYMBOL>"),
1209 data->d_size / sizeof (Elf32_Word) - 1);
1210
Ulrich Drepperd0449522005-09-03 07:23:52 +00001211 for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001212 {
1213 GElf_Shdr grpshdr_mem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001214 GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
1215 &grpshdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001216
Ulrich Drepperd0449522005-09-03 07:23:52 +00001217 const char *str;
1218 printf (" [%2u] %s\n",
1219 grpref[cnt],
1220 grpshdr != NULL
1221 && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
1222 ? str : gettext ("<INVALID SECTION>"));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001223 }
1224}
1225
1226
1227static void
1228print_scngrp (Ebl *ebl)
1229{
1230 /* Find all relocation sections and handle them. */
1231 Elf_Scn *scn = NULL;
1232
1233 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1234 {
1235 /* Handle the section if it is a symbol table. */
1236 GElf_Shdr shdr_mem;
1237 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1238
1239 if (shdr != NULL && shdr->sh_type == SHT_GROUP)
1240 handle_scngrp (ebl, scn, shdr);
1241 }
1242}
1243
1244
1245static const struct flags
1246{
1247 int mask;
1248 const char *str;
1249} dt_flags[] =
1250 {
1251 { DF_ORIGIN, "ORIGIN" },
1252 { DF_SYMBOLIC, "SYMBOLIC" },
1253 { DF_TEXTREL, "TEXTREL" },
1254 { DF_BIND_NOW, "BIND_NOW" },
1255 { DF_STATIC_TLS, "STATIC_TLS" }
1256 };
1257static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
1258
1259static const struct flags dt_flags_1[] =
1260 {
1261 { DF_1_NOW, "NOW" },
1262 { DF_1_GLOBAL, "GLOBAL" },
1263 { DF_1_GROUP, "GROUP" },
1264 { DF_1_NODELETE, "NODELETE" },
1265 { DF_1_LOADFLTR, "LOADFLTR" },
1266 { DF_1_INITFIRST, "INITFIRST" },
1267 { DF_1_NOOPEN, "NOOPEN" },
1268 { DF_1_ORIGIN, "ORIGIN" },
1269 { DF_1_DIRECT, "DIRECT" },
1270 { DF_1_TRANS, "TRANS" },
1271 { DF_1_INTERPOSE, "INTERPOSE" },
1272 { DF_1_NODEFLIB, "NODEFLIB" },
1273 { DF_1_NODUMP, "NODUMP" },
1274 { DF_1_CONFALT, "CONFALT" },
1275 { DF_1_ENDFILTEE, "ENDFILTEE" },
1276 { DF_1_DISPRELDNE, "DISPRELDNE" },
1277 { DF_1_DISPRELPND, "DISPRELPND" },
1278 };
1279static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
1280
1281static const struct flags dt_feature_1[] =
1282 {
1283 { DTF_1_PARINIT, "PARINIT" },
1284 { DTF_1_CONFEXP, "CONFEXP" }
1285 };
1286static const int ndt_feature_1 = (sizeof (dt_feature_1)
1287 / sizeof (dt_feature_1[0]));
1288
1289static const struct flags dt_posflag_1[] =
1290 {
1291 { DF_P1_LAZYLOAD, "LAZYLOAD" },
1292 { DF_P1_GROUPPERM, "GROUPPERM" }
1293 };
1294static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
1295 / sizeof (dt_posflag_1[0]));
1296
1297
1298static void
1299print_flags (int class, GElf_Xword d_val, const struct flags *flags,
1300 int nflags)
1301{
1302 bool first = true;
1303 int cnt;
1304
1305 for (cnt = 0; cnt < nflags; ++cnt)
1306 if (d_val & flags[cnt].mask)
1307 {
1308 if (!first)
1309 putchar_unlocked (' ');
1310 fputs_unlocked (flags[cnt].str, stdout);
1311 d_val &= ~flags[cnt].mask;
1312 first = false;
1313 }
1314
1315 if (d_val != 0)
1316 {
1317 if (!first)
1318 putchar_unlocked (' ');
1319 printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
1320 }
1321
1322 putchar_unlocked ('\n');
1323}
1324
1325
1326static void
1327print_dt_flags (int class, GElf_Xword d_val)
1328{
1329 print_flags (class, d_val, dt_flags, ndt_flags);
1330}
1331
1332
1333static void
1334print_dt_flags_1 (int class, GElf_Xword d_val)
1335{
1336 print_flags (class, d_val, dt_flags_1, ndt_flags_1);
1337}
1338
1339
1340static void
1341print_dt_feature_1 (int class, GElf_Xword d_val)
1342{
1343 print_flags (class, d_val, dt_feature_1, ndt_feature_1);
1344}
1345
1346
1347static void
1348print_dt_posflag_1 (int class, GElf_Xword d_val)
1349{
1350 print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
1351}
1352
1353
1354static void
1355handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1356{
1357 int class = gelf_getclass (ebl->elf);
1358 GElf_Shdr glink;
1359 Elf_Data *data;
1360 size_t cnt;
1361 size_t shstrndx;
1362
1363 /* Get the data of the section. */
1364 data = elf_getdata (scn, NULL);
1365 if (data == NULL)
1366 return;
1367
1368 /* Get the section header string table index. */
Ulrich Drepperf1894932009-06-13 15:55:42 -07001369 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001370 error (EXIT_FAILURE, 0,
1371 gettext ("cannot get section header string table index"));
1372
1373 printf (ngettext ("\
1374\nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1375 "\
1376\nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
1377 shdr->sh_size / shdr->sh_entsize),
1378 (unsigned long int) (shdr->sh_size / shdr->sh_entsize),
1379 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
1380 shdr->sh_offset,
1381 (int) shdr->sh_link,
1382 elf_strptr (ebl->elf, shstrndx,
1383 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1384 &glink)->sh_name));
1385 fputs_unlocked (gettext (" Type Value\n"), stdout);
1386
1387 for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1388 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001389 GElf_Dyn dynmem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001390 GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001391 if (dyn == NULL)
1392 break;
1393
Ulrich Drepperd0449522005-09-03 07:23:52 +00001394 char buf[64];
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001395 printf (" %-17s ",
1396 ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
1397
1398 switch (dyn->d_tag)
1399 {
1400 case DT_NULL:
1401 case DT_DEBUG:
1402 case DT_BIND_NOW:
1403 case DT_TEXTREL:
1404 /* No further output. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001405 fputc_unlocked ('\n', stdout);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001406 break;
1407
1408 case DT_NEEDED:
1409 printf (gettext ("Shared library: [%s]\n"),
1410 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1411 break;
1412
1413 case DT_SONAME:
1414 printf (gettext ("Library soname: [%s]\n"),
1415 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1416 break;
1417
1418 case DT_RPATH:
1419 printf (gettext ("Library rpath: [%s]\n"),
1420 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1421 break;
1422
1423 case DT_RUNPATH:
1424 printf (gettext ("Library runpath: [%s]\n"),
1425 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1426 break;
1427
1428 case DT_PLTRELSZ:
1429 case DT_RELASZ:
1430 case DT_STRSZ:
1431 case DT_RELSZ:
1432 case DT_RELAENT:
1433 case DT_SYMENT:
1434 case DT_RELENT:
1435 case DT_PLTPADSZ:
1436 case DT_MOVEENT:
1437 case DT_MOVESZ:
1438 case DT_INIT_ARRAYSZ:
1439 case DT_FINI_ARRAYSZ:
1440 case DT_SYMINSZ:
1441 case DT_SYMINENT:
1442 case DT_GNU_CONFLICTSZ:
1443 case DT_GNU_LIBLISTSZ:
1444 printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
1445 break;
1446
1447 case DT_VERDEFNUM:
1448 case DT_VERNEEDNUM:
1449 case DT_RELACOUNT:
1450 case DT_RELCOUNT:
1451 printf ("%" PRId64 "\n", dyn->d_un.d_val);
1452 break;
1453
Marek Polacek44de92a2011-03-22 01:07:20 +01001454 case DT_PLTREL:;
1455 const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
1456 NULL, 0);
1457 puts (tagname ?: "???");
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001458 break;
1459
1460 case DT_FLAGS:
1461 print_dt_flags (class, dyn->d_un.d_val);
1462 break;
1463
1464 case DT_FLAGS_1:
1465 print_dt_flags_1 (class, dyn->d_un.d_val);
1466 break;
1467
1468 case DT_FEATURE_1:
1469 print_dt_feature_1 (class, dyn->d_un.d_val);
1470 break;
1471
1472 case DT_POSFLAG_1:
1473 print_dt_posflag_1 (class, dyn->d_un.d_val);
1474 break;
1475
1476 default:
1477 printf ("%#0*" PRIx64 "\n",
1478 class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
1479 break;
1480 }
1481 }
1482}
1483
1484
1485/* Print the dynamic segment. */
1486static void
Roland McGrath8111da02010-01-07 20:31:59 -08001487print_dynamic (Ebl *ebl)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001488{
Roland McGrath8111da02010-01-07 20:31:59 -08001489 for (size_t i = 0; i < phnum; ++i)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001490 {
Ulrich Drepperdbace232005-08-06 01:37:23 +00001491 GElf_Phdr phdr_mem;
1492 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001493
Ulrich Drepperdbace232005-08-06 01:37:23 +00001494 if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001495 {
Ulrich Drepperdbace232005-08-06 01:37:23 +00001496 Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
1497 GElf_Shdr shdr_mem;
1498 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1499 if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
1500 handle_dynamic (ebl, scn, shdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001501 break;
1502 }
1503 }
1504}
1505
1506
1507/* Print relocations. */
1508static void
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001509print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001510{
1511 /* Find all relocation sections and handle them. */
1512 Elf_Scn *scn = NULL;
1513
1514 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1515 {
1516 /* Handle the section if it is a symbol table. */
1517 GElf_Shdr shdr_mem;
1518 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1519
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001520 if (likely (shdr != NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001521 {
1522 if (shdr->sh_type == SHT_REL)
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001523 handle_relocs_rel (ebl, ehdr, scn, shdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001524 else if (shdr->sh_type == SHT_RELA)
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001525 handle_relocs_rela (ebl, ehdr, scn, shdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001526 }
1527 }
1528}
1529
1530
1531/* Handle a relocation section. */
1532static void
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001533handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001534{
1535 int class = gelf_getclass (ebl->elf);
1536 int nentries = shdr->sh_size / shdr->sh_entsize;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001537
1538 /* Get the data of the section. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001539 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001540 if (data == NULL)
1541 return;
1542
1543 /* Get the symbol table information. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001544 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1545 GElf_Shdr symshdr_mem;
1546 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1547 Elf_Data *symdata = elf_getdata (symscn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001548
1549 /* Get the section header of the section the relocations are for. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001550 GElf_Shdr destshdr_mem;
1551 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1552 &destshdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001553
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001554 if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001555 {
1556 printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1557 shdr->sh_offset);
1558 return;
1559 }
1560
1561 /* Search for the optional extended section index table. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001562 Elf_Data *xndxdata = NULL;
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001563 int xndxscnidx = elf_scnshndx (scn);
1564 if (unlikely (xndxscnidx > 0))
1565 xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001566
1567 /* Get the section header string table index. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001568 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001569 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001570 error (EXIT_FAILURE, 0,
1571 gettext ("cannot get section header string table index"));
1572
1573 if (shdr->sh_info != 0)
1574 printf (ngettext ("\
Ulrich Drepper351bf202009-01-15 20:18:40 -08001575\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001576 "\
Ulrich Drepper351bf202009-01-15 20:18:40 -08001577\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001578 nentries),
Ulrich Drepper351bf202009-01-15 20:18:40 -08001579 elf_ndxscn (scn),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001580 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1581 (unsigned int) shdr->sh_info,
1582 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1583 shdr->sh_offset,
1584 nentries);
1585 else
1586 /* The .rel.dyn section does not refer to a specific section but
1587 instead of section index zero. Do not try to print a section
1588 name. */
1589 printf (ngettext ("\
1590\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1591 "\
1592\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1593 nentries),
1594 (unsigned int) elf_ndxscn (scn),
1595 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1596 shdr->sh_offset,
1597 nentries);
1598 fputs_unlocked (class == ELFCLASS32
1599 ? gettext ("\
1600 Offset Type Value Name\n")
1601 : gettext ("\
1602 Offset Type Value Name\n"),
1603 stdout);
1604
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001605 int is_statically_linked = 0;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001606 for (int cnt = 0; cnt < nentries; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001607 {
1608 GElf_Rel relmem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001609 GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001610 if (likely (rel != NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001611 {
1612 char buf[128];
1613 GElf_Sym symmem;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001614 Elf32_Word xndx;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001615 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1616 GELF_R_SYM (rel->r_info),
1617 &symmem, &xndx);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001618 if (unlikely (sym == NULL))
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001619 {
1620 /* As a special case we have to handle relocations in static
1621 executables. This only happens for IRELATIVE relocations
1622 (so far). There is no symbol table. */
1623 if (is_statically_linked == 0)
1624 {
1625 /* Find the program header and look for a PT_INTERP entry. */
1626 is_statically_linked = -1;
1627 if (ehdr->e_type == ET_EXEC)
1628 {
1629 is_statically_linked = 1;
1630
Roland McGrath8111da02010-01-07 20:31:59 -08001631 for (size_t inner = 0; inner < phnum; ++inner)
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001632 {
1633 GElf_Phdr phdr_mem;
1634 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
1635 &phdr_mem);
1636 if (phdr != NULL && phdr->p_type == PT_INTERP)
1637 {
1638 is_statically_linked = -1;
1639 break;
1640 }
1641 }
1642 }
1643 }
1644
1645 if (is_statically_linked > 0 && shdr->sh_link == 0)
1646 printf ("\
1647 %#0*" PRIx64 " %-20s %*s %s\n",
1648 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1649 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1650 /* Avoid the leading R_ which isn't carrying any
1651 information. */
1652 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1653 buf, sizeof (buf)) + 2
1654 : gettext ("<INVALID RELOC>"),
1655 class == ELFCLASS32 ? 10 : 18, "",
1656 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1657 else
1658 printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
1659 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1660 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1661 /* Avoid the leading R_ which isn't carrying any
1662 information. */
1663 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1664 buf, sizeof (buf)) + 2
1665 : gettext ("<INVALID RELOC>"),
1666 gettext ("INVALID SYMBOL"),
1667 (long int) GELF_R_SYM (rel->r_info));
1668 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001669 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1670 printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
1671 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001672 likely (ebl_reloc_type_check (ebl,
1673 GELF_R_TYPE (rel->r_info)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001674 /* Avoid the leading R_ which isn't carrying any
1675 information. */
1676 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1677 buf, sizeof (buf)) + 2
1678 : gettext ("<INVALID RELOC>"),
1679 class == ELFCLASS32 ? 10 : 18, sym->st_value,
1680 elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1681 else
1682 {
1683 destshdr = gelf_getshdr (elf_getscn (ebl->elf,
1684 sym->st_shndx == SHN_XINDEX
1685 ? xndx : sym->st_shndx),
1686 &destshdr_mem);
1687
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001688 if (unlikely (destshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001689 printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
1690 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1691 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1692 /* Avoid the leading R_ which isn't carrying any
1693 information. */
1694 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1695 buf, sizeof (buf)) + 2
1696 : gettext ("<INVALID RELOC>"),
1697 gettext ("INVALID SECTION"),
1698 (long int) (sym->st_shndx == SHN_XINDEX
1699 ? xndx : sym->st_shndx));
1700 else
1701 printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
1702 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1703 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1704 /* Avoid the leading R_ which isn't carrying any
1705 information. */
1706 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1707 buf, sizeof (buf)) + 2
1708 : gettext ("<INVALID RELOC>"),
1709 class == ELFCLASS32 ? 10 : 18, sym->st_value,
1710 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1711 }
1712 }
1713 }
1714}
1715
1716
1717/* Handle a relocation section. */
1718static void
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001719handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001720{
1721 int class = gelf_getclass (ebl->elf);
1722 int nentries = shdr->sh_size / shdr->sh_entsize;
1723
1724 /* Get the data of the section. */
1725 Elf_Data *data = elf_getdata (scn, NULL);
1726 if (data == NULL)
1727 return;
1728
1729 /* Get the symbol table information. */
1730 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1731 GElf_Shdr symshdr_mem;
1732 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1733 Elf_Data *symdata = elf_getdata (symscn, NULL);
1734
1735 /* Get the section header of the section the relocations are for. */
1736 GElf_Shdr destshdr_mem;
1737 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1738 &destshdr_mem);
1739
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001740 if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001741 {
1742 printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1743 shdr->sh_offset);
1744 return;
1745 }
1746
1747 /* Search for the optional extended section index table. */
1748 Elf_Data *xndxdata = NULL;
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001749 int xndxscnidx = elf_scnshndx (scn);
1750 if (unlikely (xndxscnidx > 0))
1751 xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001752
1753 /* Get the section header string table index. */
1754 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001755 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001756 error (EXIT_FAILURE, 0,
1757 gettext ("cannot get section header string table index"));
1758
1759 printf (ngettext ("\
1760\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1761 "\
1762\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1763 nentries),
1764 elf_ndxscn (scn),
1765 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1766 (unsigned int) shdr->sh_info,
1767 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1768 shdr->sh_offset,
1769 nentries);
1770 fputs_unlocked (class == ELFCLASS32
1771 ? gettext ("\
1772 Offset Type Value Addend Name\n")
1773 : gettext ("\
1774 Offset Type Value Addend Name\n"),
1775 stdout);
1776
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001777 int is_statically_linked = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001778 for (int cnt = 0; cnt < nentries; ++cnt)
1779 {
1780 GElf_Rela relmem;
1781 GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001782 if (likely (rel != NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001783 {
1784 char buf[64];
1785 GElf_Sym symmem;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001786 Elf32_Word xndx;
Ulrich Drepperd0449522005-09-03 07:23:52 +00001787 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1788 GELF_R_SYM (rel->r_info),
1789 &symmem, &xndx);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001790
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001791 if (unlikely (sym == NULL))
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001792 {
1793 /* As a special case we have to handle relocations in static
1794 executables. This only happens for IRELATIVE relocations
1795 (so far). There is no symbol table. */
1796 if (is_statically_linked == 0)
1797 {
1798 /* Find the program header and look for a PT_INTERP entry. */
1799 is_statically_linked = -1;
1800 if (ehdr->e_type == ET_EXEC)
1801 {
1802 is_statically_linked = 1;
1803
Roland McGrath8111da02010-01-07 20:31:59 -08001804 for (size_t inner = 0; inner < phnum; ++inner)
Ulrich Drepperb47d2902009-06-01 07:38:32 -07001805 {
1806 GElf_Phdr phdr_mem;
1807 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
1808 &phdr_mem);
1809 if (phdr != NULL && phdr->p_type == PT_INTERP)
1810 {
1811 is_statically_linked = -1;
1812 break;
1813 }
1814 }
1815 }
1816 }
1817
1818 if (is_statically_linked > 0 && shdr->sh_link == 0)
1819 printf ("\
1820 %#0*" PRIx64 " %-15s %*s %#6" PRIx64 " %s\n",
1821 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1822 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1823 /* Avoid the leading R_ which isn't carrying any
1824 information. */
1825 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1826 buf, sizeof (buf)) + 2
1827 : gettext ("<INVALID RELOC>"),
1828 class == ELFCLASS32 ? 10 : 18, "",
1829 rel->r_addend,
1830 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1831 else
1832 printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
1833 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1834 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1835 /* Avoid the leading R_ which isn't carrying any
1836 information. */
1837 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1838 buf, sizeof (buf)) + 2
1839 : gettext ("<INVALID RELOC>"),
1840 gettext ("INVALID SYMBOL"),
1841 (long int) GELF_R_SYM (rel->r_info));
1842 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001843 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1844 printf ("\
Ulrich Drepper2cb8e732006-05-27 21:57:27 +00001845 %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001846 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001847 likely (ebl_reloc_type_check (ebl,
1848 GELF_R_TYPE (rel->r_info)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001849 /* Avoid the leading R_ which isn't carrying any
1850 information. */
1851 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1852 buf, sizeof (buf)) + 2
1853 : gettext ("<INVALID RELOC>"),
1854 class == ELFCLASS32 ? 10 : 18, sym->st_value,
1855 rel->r_addend,
1856 elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1857 else
1858 {
1859 destshdr = gelf_getshdr (elf_getscn (ebl->elf,
1860 sym->st_shndx == SHN_XINDEX
1861 ? xndx : sym->st_shndx),
1862 &destshdr_mem);
1863
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001864 if (unlikely (shdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001865 printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
1866 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1867 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1868 /* Avoid the leading R_ which isn't carrying any
1869 information. */
1870 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1871 buf, sizeof (buf)) + 2
1872 : gettext ("<INVALID RELOC>"),
1873 gettext ("INVALID SECTION"),
1874 (long int) (sym->st_shndx == SHN_XINDEX
1875 ? xndx : sym->st_shndx));
1876 else
1877 printf ("\
Ulrich Drepper2cb8e732006-05-27 21:57:27 +00001878 %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001879 class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1880 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1881 /* Avoid the leading R_ which isn't carrying any
1882 information. */
1883 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1884 buf, sizeof (buf)) + 2
1885 : gettext ("<INVALID RELOC>"),
1886 class == ELFCLASS32 ? 10 : 18, sym->st_value,
1887 rel->r_addend,
1888 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1889 }
1890 }
1891 }
1892}
1893
1894
1895/* Print the program header. */
1896static void
1897print_symtab (Ebl *ebl, int type)
1898{
1899 /* Find the symbol table(s). For this we have to search through the
1900 section table. */
1901 Elf_Scn *scn = NULL;
1902
1903 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1904 {
1905 /* Handle the section if it is a symbol table. */
1906 GElf_Shdr shdr_mem;
1907 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1908
1909 if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
1910 handle_symtab (ebl, scn, shdr);
1911 }
1912}
1913
1914
1915static void
1916handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1917{
1918 Elf_Data *versym_data = NULL;
1919 Elf_Data *verneed_data = NULL;
1920 Elf_Data *verdef_data = NULL;
1921 Elf_Data *xndx_data = NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001922 int class = gelf_getclass (ebl->elf);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001923 Elf32_Word verneed_stridx = 0;
1924 Elf32_Word verdef_stridx = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001925
1926 /* Get the data of the section. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001927 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001928 if (data == NULL)
1929 return;
1930
1931 /* Find out whether we have other sections we might need. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001932 Elf_Scn *runscn = NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001933 while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
1934 {
1935 GElf_Shdr runshdr_mem;
1936 GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
1937
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001938 if (likely (runshdr != NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001939 {
1940 if (runshdr->sh_type == SHT_GNU_versym
1941 && runshdr->sh_link == elf_ndxscn (scn))
1942 /* Bingo, found the version information. Now get the data. */
1943 versym_data = elf_getdata (runscn, NULL);
1944 else if (runshdr->sh_type == SHT_GNU_verneed)
1945 {
1946 /* This is the information about the needed versions. */
1947 verneed_data = elf_getdata (runscn, NULL);
1948 verneed_stridx = runshdr->sh_link;
1949 }
1950 else if (runshdr->sh_type == SHT_GNU_verdef)
1951 {
1952 /* This is the information about the defined versions. */
1953 verdef_data = elf_getdata (runscn, NULL);
1954 verdef_stridx = runshdr->sh_link;
1955 }
1956 else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
1957 && runshdr->sh_link == elf_ndxscn (scn))
1958 /* Extended section index. */
1959 xndx_data = elf_getdata (runscn, NULL);
1960 }
1961 }
1962
1963 /* Get the section header string table index. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001964 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001965 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001966 error (EXIT_FAILURE, 0,
1967 gettext ("cannot get section header string table index"));
1968
1969 /* Now we can compute the number of entries in the section. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00001970 unsigned int nsyms = data->d_size / (class == ELFCLASS32
1971 ? sizeof (Elf32_Sym)
1972 : sizeof (Elf64_Sym));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001973
1974 printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
1975 "\nSymbol table [%2u] '%s' contains %u entries:\n",
1976 nsyms),
1977 (unsigned int) elf_ndxscn (scn),
1978 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
Ulrich Drepperd0449522005-09-03 07:23:52 +00001979 GElf_Shdr glink;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001980 printf (ngettext (" %lu local symbol String table: [%2u] '%s'\n",
1981 " %lu local symbols String table: [%2u] '%s'\n",
1982 shdr->sh_info),
1983 (unsigned long int) shdr->sh_info,
1984 (unsigned int) shdr->sh_link,
1985 elf_strptr (ebl->elf, shstrndx,
1986 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1987 &glink)->sh_name));
1988
1989 fputs_unlocked (class == ELFCLASS32
1990 ? gettext ("\
1991 Num: Value Size Type Bind Vis Ndx Name\n")
1992 : gettext ("\
1993 Num: Value Size Type Bind Vis Ndx Name\n"),
1994 stdout);
1995
Ulrich Drepperd0449522005-09-03 07:23:52 +00001996 for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001997 {
1998 char typebuf[64];
1999 char bindbuf[64];
2000 char scnbuf[64];
2001 Elf32_Word xndx;
2002 GElf_Sym sym_mem;
2003 GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
2004
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002005 if (unlikely (sym == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002006 continue;
2007
2008 /* Determine the real section index. */
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002009 if (likely (sym->st_shndx != SHN_XINDEX))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002010 xndx = sym->st_shndx;
2011
2012 printf (gettext ("\
2013%5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
2014 cnt,
2015 class == ELFCLASS32 ? 8 : 16,
2016 sym->st_value,
2017 sym->st_size,
2018 ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
2019 typebuf, sizeof (typebuf)),
2020 ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
2021 bindbuf, sizeof (bindbuf)),
2022 get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
2023 ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
2024 sizeof (scnbuf), NULL, shnum),
2025 elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
2026
2027 if (versym_data != NULL)
2028 {
2029 /* Get the version information. */
2030 GElf_Versym versym_mem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00002031 GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002032
2033 if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
2034 {
2035 bool is_nobits = false;
2036 bool check_def = xndx != SHN_UNDEF;
2037
2038 if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
2039 {
2040 GElf_Shdr symshdr_mem;
2041 GElf_Shdr *symshdr =
2042 gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
2043
2044 is_nobits = (symshdr != NULL
2045 && symshdr->sh_type == SHT_NOBITS);
2046 }
2047
2048 if (is_nobits || ! check_def)
2049 {
2050 /* We must test both. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002051 GElf_Vernaux vernaux_mem;
2052 GElf_Vernaux *vernaux = NULL;
2053 size_t vn_offset = 0;
2054
Ulrich Drepperd0449522005-09-03 07:23:52 +00002055 GElf_Verneed verneed_mem;
2056 GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
2057 &verneed_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002058 while (verneed != NULL)
2059 {
2060 size_t vna_offset = vn_offset;
2061
2062 vernaux = gelf_getvernaux (verneed_data,
2063 vna_offset += verneed->vn_aux,
2064 &vernaux_mem);
2065 while (vernaux != NULL
2066 && vernaux->vna_other != *versym
2067 && vernaux->vna_next != 0)
2068 {
2069 /* Update the offset. */
2070 vna_offset += vernaux->vna_next;
2071
2072 vernaux = (vernaux->vna_next == 0
2073 ? NULL
2074 : gelf_getvernaux (verneed_data,
2075 vna_offset,
2076 &vernaux_mem));
2077 }
2078
2079 /* Check whether we found the version. */
2080 if (vernaux != NULL && vernaux->vna_other == *versym)
2081 /* Found it. */
2082 break;
2083
2084 vn_offset += verneed->vn_next;
2085 verneed = (verneed->vn_next == 0
2086 ? NULL
2087 : gelf_getverneed (verneed_data, vn_offset,
2088 &verneed_mem));
2089 }
2090
2091 if (vernaux != NULL && vernaux->vna_other == *versym)
2092 {
2093 printf ("@%s (%u)",
2094 elf_strptr (ebl->elf, verneed_stridx,
2095 vernaux->vna_name),
2096 (unsigned int) vernaux->vna_other);
2097 check_def = 0;
2098 }
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002099 else if (unlikely (! is_nobits))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002100 error (0, 0, gettext ("bad dynamic symbol"));
2101 else
2102 check_def = 1;
2103 }
2104
2105 if (check_def && *versym != 0x8001)
2106 {
2107 /* We must test both. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002108 size_t vd_offset = 0;
2109
Ulrich Drepperd0449522005-09-03 07:23:52 +00002110 GElf_Verdef verdef_mem;
2111 GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
2112 &verdef_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002113 while (verdef != NULL)
2114 {
2115 if (verdef->vd_ndx == (*versym & 0x7fff))
2116 /* Found the definition. */
2117 break;
2118
2119 vd_offset += verdef->vd_next;
2120 verdef = (verdef->vd_next == 0
2121 ? NULL
2122 : gelf_getverdef (verdef_data, vd_offset,
2123 &verdef_mem));
2124 }
2125
2126 if (verdef != NULL)
2127 {
2128 GElf_Verdaux verdaux_mem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00002129 GElf_Verdaux *verdaux
2130 = gelf_getverdaux (verdef_data,
2131 vd_offset + verdef->vd_aux,
2132 &verdaux_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002133
2134 if (verdaux != NULL)
2135 printf ((*versym & 0x8000) ? "@%s" : "@@%s",
2136 elf_strptr (ebl->elf, verdef_stridx,
2137 verdaux->vda_name));
2138 }
2139 }
2140 }
2141 }
2142
Ulrich Drepperd0449522005-09-03 07:23:52 +00002143 putchar_unlocked ('\n');
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002144 }
2145}
2146
2147
2148/* Print version information. */
2149static void
2150print_verinfo (Ebl *ebl)
2151{
2152 /* Find the version information sections. For this we have to
2153 search through the section table. */
2154 Elf_Scn *scn = NULL;
2155
2156 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2157 {
2158 /* Handle the section if it is part of the versioning handling. */
2159 GElf_Shdr shdr_mem;
2160 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2161
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002162 if (likely (shdr != NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002163 {
2164 if (shdr->sh_type == SHT_GNU_verneed)
2165 handle_verneed (ebl, scn, shdr);
2166 else if (shdr->sh_type == SHT_GNU_verdef)
2167 handle_verdef (ebl, scn, shdr);
2168 else if (shdr->sh_type == SHT_GNU_versym)
2169 handle_versym (ebl, scn, shdr);
2170 }
2171 }
2172}
2173
2174
2175static const char *
2176get_ver_flags (unsigned int flags)
2177{
2178 static char buf[32];
2179 char *endp;
2180
2181 if (flags == 0)
2182 return gettext ("none");
2183
2184 if (flags & VER_FLG_BASE)
2185 endp = stpcpy (buf, "BASE ");
2186 else
2187 endp = buf;
2188
2189 if (flags & VER_FLG_WEAK)
2190 {
2191 if (endp != buf)
Ulrich Drepper173ade82010-05-28 07:39:49 -07002192 endp = stpcpy (endp, "| ");
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002193
2194 endp = stpcpy (endp, "WEAK ");
2195 }
2196
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002197 if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002198 {
2199 strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
2200 buf[sizeof (buf) - 1] = '\0';
2201 }
2202
2203 return buf;
2204}
2205
2206
2207static void
2208handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2209{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002210 int class = gelf_getclass (ebl->elf);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002211
2212 /* Get the data of the section. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002213 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002214 if (data == NULL)
2215 return;
2216
2217 /* Get the section header string table index. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002218 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07002219 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002220 error (EXIT_FAILURE, 0,
2221 gettext ("cannot get section header string table index"));
2222
Ulrich Drepperdbace232005-08-06 01:37:23 +00002223 GElf_Shdr glink;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002224 printf (ngettext ("\
2225\nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2226 "\
2227\nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2228 shdr->sh_info),
2229 (unsigned int) elf_ndxscn (scn),
2230 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
2231 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2232 shdr->sh_offset,
2233 (unsigned int) shdr->sh_link,
2234 elf_strptr (ebl->elf, shstrndx,
2235 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2236 &glink)->sh_name));
2237
Ulrich Drepperdbace232005-08-06 01:37:23 +00002238 unsigned int offset = 0;
2239 for (int cnt = shdr->sh_info; --cnt >= 0; )
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002240 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002241 /* Get the data at the next offset. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002242 GElf_Verneed needmem;
2243 GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002244 if (unlikely (need == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002245 break;
2246
2247 printf (gettext (" %#06x: Version: %hu File: %s Cnt: %hu\n"),
2248 offset, (unsigned short int) need->vn_version,
2249 elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
2250 (unsigned short int) need->vn_cnt);
2251
Ulrich Drepperdbace232005-08-06 01:37:23 +00002252 unsigned int auxoffset = offset + need->vn_aux;
2253 for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002254 {
2255 GElf_Vernaux auxmem;
Ulrich Drepperdbace232005-08-06 01:37:23 +00002256 GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002257 if (unlikely (aux == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002258 break;
2259
2260 printf (gettext (" %#06x: Name: %s Flags: %s Version: %hu\n"),
2261 auxoffset,
2262 elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
2263 get_ver_flags (aux->vna_flags),
2264 (unsigned short int) aux->vna_other);
2265
2266 auxoffset += aux->vna_next;
2267 }
2268
2269 /* Find the next offset. */
2270 offset += need->vn_next;
2271 }
2272}
2273
2274
2275static void
2276handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2277{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002278 /* Get the data of the section. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002279 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002280 if (data == NULL)
2281 return;
2282
2283 /* Get the section header string table index. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002284 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07002285 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002286 error (EXIT_FAILURE, 0,
2287 gettext ("cannot get section header string table index"));
2288
Ulrich Drepperdbace232005-08-06 01:37:23 +00002289 int class = gelf_getclass (ebl->elf);
2290 GElf_Shdr glink;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002291 printf (ngettext ("\
2292\nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2293 "\
2294\nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2295 shdr->sh_info),
2296 (unsigned int) elf_ndxscn (scn),
2297 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2298 shdr->sh_info,
2299 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2300 shdr->sh_offset,
2301 (unsigned int) shdr->sh_link,
2302 elf_strptr (ebl->elf, shstrndx,
2303 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2304 &glink)->sh_name));
2305
Ulrich Drepperdbace232005-08-06 01:37:23 +00002306 unsigned int offset = 0;
2307 for (int cnt = shdr->sh_info; --cnt >= 0; )
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002308 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002309 /* Get the data at the next offset. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002310 GElf_Verdef defmem;
2311 GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002312 if (unlikely (def == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002313 break;
2314
Ulrich Drepperdbace232005-08-06 01:37:23 +00002315 unsigned int auxoffset = offset + def->vd_aux;
2316 GElf_Verdaux auxmem;
2317 GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002318 if (unlikely (aux == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002319 break;
2320
2321 printf (gettext ("\
2322 %#06x: Version: %hd Flags: %s Index: %hd Cnt: %hd Name: %s\n"),
2323 offset, def->vd_version,
2324 get_ver_flags (def->vd_flags),
2325 def->vd_ndx,
2326 def->vd_cnt,
2327 elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2328
2329 auxoffset += aux->vda_next;
Ulrich Drepperdbace232005-08-06 01:37:23 +00002330 for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002331 {
2332 aux = gelf_getverdaux (data, auxoffset, &auxmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002333 if (unlikely (aux == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002334 break;
2335
2336 printf (gettext (" %#06x: Parent %d: %s\n"),
2337 auxoffset, cnt2,
2338 elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2339
2340 auxoffset += aux->vda_next;
2341 }
2342
2343 /* Find the next offset. */
2344 offset += def->vd_next;
2345 }
2346}
2347
2348
2349static void
2350handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2351{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002352 int class = gelf_getclass (ebl->elf);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002353 const char **vername;
2354 const char **filename;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002355
2356 /* Get the data of the section. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002357 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002358 if (data == NULL)
2359 return;
2360
2361 /* Get the section header string table index. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002362 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07002363 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002364 error (EXIT_FAILURE, 0,
2365 gettext ("cannot get section header string table index"));
2366
2367 /* We have to find the version definition section and extract the
2368 version names. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002369 Elf_Scn *defscn = NULL;
2370 Elf_Scn *needscn = NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002371
Ulrich Drepperdbace232005-08-06 01:37:23 +00002372 Elf_Scn *verscn = NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002373 while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
2374 {
2375 GElf_Shdr vershdr_mem;
2376 GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
2377
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002378 if (likely (vershdr != NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002379 {
2380 if (vershdr->sh_type == SHT_GNU_verdef)
2381 defscn = verscn;
2382 else if (vershdr->sh_type == SHT_GNU_verneed)
2383 needscn = verscn;
2384 }
2385 }
2386
Ulrich Drepperdbace232005-08-06 01:37:23 +00002387 size_t nvername;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002388 if (defscn != NULL || needscn != NULL)
2389 {
2390 /* We have a version information (better should have). Now get
2391 the version names. First find the maximum version number. */
2392 nvername = 0;
2393 if (defscn != NULL)
2394 {
2395 /* Run through the version definitions and find the highest
2396 index. */
2397 unsigned int offset = 0;
2398 Elf_Data *defdata;
2399 GElf_Shdr defshdrmem;
2400 GElf_Shdr *defshdr;
2401
2402 defdata = elf_getdata (defscn, NULL);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002403 if (unlikely (defdata == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002404 return;
2405
2406 defshdr = gelf_getshdr (defscn, &defshdrmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002407 if (unlikely (defshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002408 return;
2409
Ulrich Drepperdbace232005-08-06 01:37:23 +00002410 for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002411 {
2412 GElf_Verdef defmem;
2413 GElf_Verdef *def;
2414
2415 /* Get the data at the next offset. */
2416 def = gelf_getverdef (defdata, offset, &defmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002417 if (unlikely (def == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002418 break;
2419
2420 nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
2421
2422 offset += def->vd_next;
2423 }
2424 }
2425 if (needscn != NULL)
2426 {
2427 unsigned int offset = 0;
2428 Elf_Data *needdata;
2429 GElf_Shdr needshdrmem;
2430 GElf_Shdr *needshdr;
2431
2432 needdata = elf_getdata (needscn, NULL);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002433 if (unlikely (needdata == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002434 return;
2435
2436 needshdr = gelf_getshdr (needscn, &needshdrmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002437 if (unlikely (needshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002438 return;
2439
Ulrich Drepperdbace232005-08-06 01:37:23 +00002440 for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002441 {
2442 GElf_Verneed needmem;
2443 GElf_Verneed *need;
2444 unsigned int auxoffset;
2445 int cnt2;
2446
2447 /* Get the data at the next offset. */
2448 need = gelf_getverneed (needdata, offset, &needmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002449 if (unlikely (need == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002450 break;
2451
2452 /* Run through the auxiliary entries. */
2453 auxoffset = offset + need->vn_aux;
2454 for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
2455 {
2456 GElf_Vernaux auxmem;
2457 GElf_Vernaux *aux;
2458
2459 aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002460 if (unlikely (aux == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002461 break;
2462
2463 nvername = MAX (nvername,
2464 (size_t) (aux->vna_other & 0x7fff));
2465
2466 auxoffset += aux->vna_next;
2467 }
2468
2469 offset += need->vn_next;
2470 }
2471 }
2472
2473 /* This is the number of versions we know about. */
2474 ++nvername;
2475
2476 /* Allocate the array. */
2477 vername = (const char **) alloca (nvername * sizeof (const char *));
2478 filename = (const char **) alloca (nvername * sizeof (const char *));
2479
2480 /* Run through the data structures again and collect the strings. */
2481 if (defscn != NULL)
2482 {
2483 /* Run through the version definitions and find the highest
2484 index. */
2485 unsigned int offset = 0;
2486 Elf_Data *defdata;
2487 GElf_Shdr defshdrmem;
2488 GElf_Shdr *defshdr;
2489
2490 defdata = elf_getdata (defscn, NULL);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002491 if (unlikely (defdata == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002492 return;
2493
2494 defshdr = gelf_getshdr (defscn, &defshdrmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002495 if (unlikely (defshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002496 return;
2497
Ulrich Drepperdbace232005-08-06 01:37:23 +00002498 for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002499 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002500
2501 /* Get the data at the next offset. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00002502 GElf_Verdef defmem;
2503 GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
2504 GElf_Verdaux auxmem;
2505 GElf_Verdaux *aux = gelf_getverdaux (defdata,
2506 offset + def->vd_aux,
2507 &auxmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002508 if (unlikely (def == NULL || aux == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002509 break;
2510
2511 vername[def->vd_ndx & 0x7fff]
2512 = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
2513 filename[def->vd_ndx & 0x7fff] = NULL;
2514
2515 offset += def->vd_next;
2516 }
2517 }
2518 if (needscn != NULL)
2519 {
2520 unsigned int offset = 0;
Ulrich Drepperd0449522005-09-03 07:23:52 +00002521
2522 Elf_Data *needdata = elf_getdata (needscn, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002523 GElf_Shdr needshdrmem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00002524 GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002525 if (unlikely (needdata == NULL || needshdr == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002526 return;
2527
Ulrich Drepperdbace232005-08-06 01:37:23 +00002528 for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002529 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002530 /* Get the data at the next offset. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00002531 GElf_Verneed needmem;
2532 GElf_Verneed *need = gelf_getverneed (needdata, offset,
2533 &needmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002534 if (unlikely (need == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002535 break;
2536
2537 /* Run through the auxiliary entries. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00002538 unsigned int auxoffset = offset + need->vn_aux;
2539 for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002540 {
2541 GElf_Vernaux auxmem;
Ulrich Drepperd0449522005-09-03 07:23:52 +00002542 GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
2543 &auxmem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002544 if (unlikely (aux == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002545 break;
2546
2547 vername[aux->vna_other & 0x7fff]
2548 = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
2549 filename[aux->vna_other & 0x7fff]
2550 = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
2551
2552 auxoffset += aux->vna_next;
2553 }
2554
2555 offset += need->vn_next;
2556 }
2557 }
2558 }
2559 else
2560 {
2561 vername = NULL;
2562 nvername = 1;
2563 filename = NULL;
2564 }
2565
2566 /* Print the header. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00002567 GElf_Shdr glink;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002568 printf (ngettext ("\
2569\nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
2570 "\
2571\nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
2572 shdr->sh_size / shdr->sh_entsize),
2573 (unsigned int) elf_ndxscn (scn),
2574 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2575 (int) (shdr->sh_size / shdr->sh_entsize),
2576 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2577 shdr->sh_offset,
2578 (unsigned int) shdr->sh_link,
2579 elf_strptr (ebl->elf, shstrndx,
2580 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2581 &glink)->sh_name));
2582
2583 /* Now we can finally look at the actual contents of this section. */
Ulrich Drepperdbace232005-08-06 01:37:23 +00002584 for (unsigned int cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002585 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002586 if (cnt % 2 == 0)
2587 printf ("\n %4d:", cnt);
2588
Ulrich Drepperd0449522005-09-03 07:23:52 +00002589 GElf_Versym symmem;
2590 GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002591 if (sym == NULL)
2592 break;
2593
2594 switch (*sym)
2595 {
Ulrich Drepperd0449522005-09-03 07:23:52 +00002596 ssize_t n;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002597 case 0:
2598 fputs_unlocked (gettext (" 0 *local* "),
2599 stdout);
2600 break;
2601
2602 case 1:
2603 fputs_unlocked (gettext (" 1 *global* "),
2604 stdout);
2605 break;
2606
2607 default:
2608 n = printf ("%4d%c%s",
2609 *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
2610 (unsigned int) (*sym & 0x7fff) < nvername
2611 ? vername[*sym & 0x7fff] : "???");
2612 if ((unsigned int) (*sym & 0x7fff) < nvername
2613 && filename[*sym & 0x7fff] != NULL)
2614 n += printf ("(%s)", filename[*sym & 0x7fff]);
2615 printf ("%*s", MAX (0, 33 - (int) n), " ");
2616 break;
2617 }
2618 }
Ulrich Drepperd0449522005-09-03 07:23:52 +00002619 putchar_unlocked ('\n');
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002620}
2621
2622
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002623static void
2624print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
2625 uint_fast32_t maxlength, Elf32_Word nbucket,
Ulrich Drepper8ae58142006-07-12 05:22:32 +00002626 uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002627{
2628 uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
2629
2630 for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2631 ++counts[lengths[cnt]];
2632
2633 GElf_Shdr glink;
2634 printf (ngettext ("\
2635\nHistogram for bucket list length in section [%2u] '%s' (total of %d bucket):\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2636 "\
2637\nHistogram for bucket list length in section [%2u] '%s' (total of %d buckets):\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
2638 nbucket),
2639 (unsigned int) elf_ndxscn (scn),
2640 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2641 (int) nbucket,
2642 gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
2643 shdr->sh_addr,
2644 shdr->sh_offset,
2645 (unsigned int) shdr->sh_link,
2646 elf_strptr (ebl->elf, shstrndx,
2647 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2648 &glink)->sh_name));
2649
Ulrich Drepper8ae58142006-07-12 05:22:32 +00002650 if (extrastr != NULL)
2651 fputs (extrastr, stdout);
2652
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002653 if (likely (nbucket > 0))
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002654 {
2655 uint64_t success = 0;
2656
Roland McGrath3b495d82010-04-06 12:58:32 -07002657 /* xgettext:no-c-format */
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002658 fputs_unlocked (gettext ("\
2659 Length Number % of total Coverage\n"), stdout);
2660 printf (gettext (" 0 %6" PRIu32 " %5.1f%%\n"),
2661 counts[0], (counts[0] * 100.0) / nbucket);
2662
2663 uint64_t nzero_counts = 0;
2664 for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
2665 {
2666 nzero_counts += counts[cnt] * cnt;
2667 printf (gettext ("\
2668%7d %6" PRIu32 " %5.1f%% %5.1f%%\n"),
2669 (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
2670 (nzero_counts * 100.0) / nsyms);
2671 }
2672
2673 Elf32_Word acc = 0;
2674 for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
2675 {
2676 acc += cnt;
2677 success += counts[cnt] * acc;
2678 }
2679
2680 printf (gettext ("\
2681 Average number of tests: successful lookup: %f\n\
Ulrich Drepper173ade82010-05-28 07:39:49 -07002682 unsuccessful lookup: %f\n"),
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002683 (double) success / (double) nzero_counts,
2684 (double) nzero_counts / (double) nbucket);
2685 }
2686
2687 free (counts);
2688}
2689
2690
2691/* This function handles the traditional System V-style hash table format. */
2692static void
2693handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2694{
2695 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002696 if (unlikely (data == NULL))
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002697 {
2698 error (0, 0, gettext ("cannot get data for section %d: %s"),
2699 (int) elf_ndxscn (scn), elf_errmsg (-1));
2700 return;
2701 }
2702
2703 Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
2704 Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
2705 Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
2706 Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
2707
2708 uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2709
2710 uint_fast32_t maxlength = 0;
2711 uint_fast32_t nsyms = 0;
2712 for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2713 {
2714 Elf32_Word inner = bucket[cnt];
2715 while (inner > 0 && inner < nchain)
2716 {
2717 ++nsyms;
2718 if (maxlength < ++lengths[cnt])
2719 ++maxlength;
2720
2721 inner = chain[inner];
2722 }
2723 }
2724
2725 print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
Ulrich Drepper8ae58142006-07-12 05:22:32 +00002726 lengths, NULL);
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002727
2728 free (lengths);
2729}
2730
2731
2732/* This function handles the incorrect, System V-style hash table
2733 format some 64-bit architectures use. */
2734static void
2735handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2736{
2737 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002738 if (unlikely (data == NULL))
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002739 {
2740 error (0, 0, gettext ("cannot get data for section %d: %s"),
2741 (int) elf_ndxscn (scn), elf_errmsg (-1));
2742 return;
2743 }
2744
2745 Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
2746 Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
2747 Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
2748 Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
2749
2750 uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2751
2752 uint_fast32_t maxlength = 0;
2753 uint_fast32_t nsyms = 0;
2754 for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
2755 {
2756 Elf64_Xword inner = bucket[cnt];
2757 while (inner > 0 && inner < nchain)
2758 {
2759 ++nsyms;
2760 if (maxlength < ++lengths[cnt])
2761 ++maxlength;
2762
2763 inner = chain[inner];
2764 }
2765 }
2766
2767 print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
Ulrich Drepper8ae58142006-07-12 05:22:32 +00002768 lengths, NULL);
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002769
2770 free (lengths);
2771}
2772
2773
2774/* This function handles the GNU-style hash table format. */
2775static void
2776handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2777{
2778 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002779 if (unlikely (data == NULL))
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002780 {
2781 error (0, 0, gettext ("cannot get data for section %d: %s"),
2782 (int) elf_ndxscn (scn), elf_errmsg (-1));
2783 return;
2784 }
2785
2786 Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
2787 Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
Ulrich Drepper8ae58142006-07-12 05:22:32 +00002788
2789 /* Next comes the size of the bitmap. It's measured in words for
2790 the architecture. It's 32 bits for 32 bit archs, and 64 bits for
2791 64 bit archs. */
2792 Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
2793 if (gelf_getclass (ebl->elf) == ELFCLASS64)
2794 bitmask_words *= 2;
2795
2796 Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002797
2798 uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2799
Ulrich Drepper8ae58142006-07-12 05:22:32 +00002800 Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
2801 Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
2802 Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
2803 + nbucket];
2804
2805 /* Compute distribution of chain lengths. */
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002806 uint_fast32_t maxlength = 0;
2807 uint_fast32_t nsyms = 0;
2808 for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
Ulrich Drepper8ae58142006-07-12 05:22:32 +00002809 if (bucket[cnt] != 0)
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002810 {
Ulrich Drepper8ae58142006-07-12 05:22:32 +00002811 Elf32_Word inner = bucket[cnt] - symbias;
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002812 do
2813 {
2814 ++nsyms;
2815 if (maxlength < ++lengths[cnt])
2816 ++maxlength;
2817 }
2818 while ((chain[inner++] & 1) == 0);
2819 }
2820
Ulrich Drepper8ae58142006-07-12 05:22:32 +00002821 /* Count bits in bitmask. */
2822 uint_fast32_t nbits = 0;
2823 for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
2824 {
2825 uint_fast32_t word = bitmask[cnt];
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002826
Ulrich Drepper8ae58142006-07-12 05:22:32 +00002827 word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
2828 word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
2829 word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
2830 word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
2831 nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
2832 }
2833
2834 char *str;
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002835 if (unlikely (asprintf (&str, gettext ("\
Ulrich Drepper8ae58142006-07-12 05:22:32 +00002836 Symbol Bias: %u\n\
2837 Bitmask Size: %zu bytes %" PRIuFAST32 "%% bits set 2nd hash shift: %u\n"),
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002838 (unsigned int) symbias,
2839 bitmask_words * sizeof (Elf32_Word),
2840 ((nbits * 100 + 50)
2841 / (uint_fast32_t) (bitmask_words
2842 * sizeof (Elf32_Word) * 8)),
2843 (unsigned int) shift) == -1))
Ulrich Drepper8ae58142006-07-12 05:22:32 +00002844 error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
2845
2846 print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
2847 lengths, str);
2848
2849 free (str);
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002850 free (lengths);
2851}
2852
2853
Ulrich Drepperd0449522005-09-03 07:23:52 +00002854/* Find the symbol table(s). For this we have to search through the
2855 section table. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002856static void
2857handle_hash (Ebl *ebl)
2858{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002859 /* Get the section header string table index. */
Ulrich Drepperd0449522005-09-03 07:23:52 +00002860 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07002861 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002862 error (EXIT_FAILURE, 0,
2863 gettext ("cannot get section header string table index"));
2864
Ulrich Drepperd0449522005-09-03 07:23:52 +00002865 Elf_Scn *scn = NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002866 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2867 {
2868 /* Handle the section if it is a symbol table. */
2869 GElf_Shdr shdr_mem;
2870 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2871
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002872 if (likely (shdr != NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002873 {
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002874 if (shdr->sh_type == SHT_HASH)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002875 {
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002876 if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
2877 handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
2878 else
2879 handle_sysv_hash (ebl, scn, shdr, shstrndx);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002880 }
Ulrich Drepper28ed8952006-07-07 03:43:47 +00002881 else if (shdr->sh_type == SHT_GNU_HASH)
2882 handle_gnu_hash (ebl, scn, shdr, shstrndx);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002883 }
2884 }
2885}
2886
2887
2888static void
2889print_liblist (Ebl *ebl)
2890{
2891 /* Find the library list sections. For this we have to search
2892 through the section table. */
2893 Elf_Scn *scn = NULL;
2894
2895 /* Get the section header string table index. */
2896 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07002897 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002898 error (EXIT_FAILURE, 0,
2899 gettext ("cannot get section header string table index"));
2900
2901 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2902 {
2903 GElf_Shdr shdr_mem;
2904 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2905
2906 if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
2907 {
2908 int nentries = shdr->sh_size / shdr->sh_entsize;
2909 printf (ngettext ("\
2910\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2911 "\
2912\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2913 nentries),
2914 elf_ndxscn (scn),
2915 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2916 shdr->sh_offset,
2917 nentries);
2918
2919 Elf_Data *data = elf_getdata (scn, NULL);
2920 if (data == NULL)
2921 return;
2922
2923 puts (gettext ("\
2924 Library Time Stamp Checksum Version Flags"));
2925
2926 for (int cnt = 0; cnt < nentries; ++cnt)
2927 {
2928 GElf_Lib lib_mem;
2929 GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002930 if (unlikely (lib == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002931 continue;
2932
2933 time_t t = (time_t) lib->l_time_stamp;
2934 struct tm *tm = gmtime (&t);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002935 if (unlikely (tm == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00002936 continue;
2937
2938 printf (" [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
2939 cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
2940 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
2941 tm->tm_hour, tm->tm_min, tm->tm_sec,
2942 (unsigned int) lib->l_checksum,
2943 (unsigned int) lib->l_version,
2944 (unsigned int) lib->l_flags);
2945 }
2946 }
2947 }
2948}
2949
Roland McGrath059c83e2008-02-21 06:19:39 +00002950static void
2951print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
2952{
2953 /* Find the object attributes sections. For this we have to search
2954 through the section table. */
2955 Elf_Scn *scn = NULL;
2956
2957 /* Get the section header string table index. */
2958 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07002959 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Roland McGrath059c83e2008-02-21 06:19:39 +00002960 error (EXIT_FAILURE, 0,
2961 gettext ("cannot get section header string table index"));
2962
2963 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2964 {
2965 GElf_Shdr shdr_mem;
2966 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2967
Roland McGratheb9ba472009-04-14 18:44:45 -07002968 if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
2969 && (shdr->sh_type != SHT_ARM_ATTRIBUTES
2970 || ehdr->e_machine != EM_ARM)))
Roland McGrath059c83e2008-02-21 06:19:39 +00002971 continue;
2972
2973 printf (gettext ("\
2974\nObject attributes section [%2zu] '%s' of %" PRIu64
2975 " bytes at offset %#0" PRIx64 ":\n"),
2976 elf_ndxscn (scn),
2977 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2978 shdr->sh_size, shdr->sh_offset);
2979
2980 Elf_Data *data = elf_rawdata (scn, NULL);
2981 if (data == NULL)
2982 return;
2983
2984 const unsigned char *p = data->d_buf;
2985
2986 if (unlikely (*p++ != 'A'))
2987 return;
2988
2989 fputs_unlocked (gettext (" Owner Size\n"), stdout);
2990
2991 inline size_t left (void)
2992 {
2993 return (const unsigned char *) data->d_buf + data->d_size - p;
2994 }
2995
2996 while (left () >= 4)
2997 {
2998 uint32_t len;
2999 memcpy (&len, p, sizeof len);
3000
3001 if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3002 CONVERT (len);
3003
3004 if (unlikely (len > left ()))
3005 break;
3006
3007 const unsigned char *name = p + sizeof len;
3008 p += len;
3009
3010 unsigned const char *q = memchr (name, '\0', len);
3011 if (unlikely (q == NULL))
3012 continue;
3013 ++q;
3014
3015 printf (gettext (" %-13s %4" PRIu32 "\n"), name, len);
3016
Roland McGratheb9ba472009-04-14 18:44:45 -07003017 if (shdr->sh_type != SHT_GNU_ATTRIBUTES
3018 || (q - name == sizeof "gnu"
3019 && !memcmp (name, "gnu", sizeof "gnu")))
Roland McGrath059c83e2008-02-21 06:19:39 +00003020 while (q < p)
3021 {
3022 const unsigned char *const sub = q;
3023
3024 unsigned int subsection_tag;
3025 get_uleb128 (subsection_tag, q);
3026 if (unlikely (q >= p))
3027 break;
3028
3029 uint32_t subsection_len;
3030 if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
3031 break;
3032
3033 memcpy (&subsection_len, q, sizeof subsection_len);
3034
3035 if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3036 CONVERT (subsection_len);
3037
Roland McGrath47c5c352008-02-29 10:17:16 +00003038 if (unlikely (p - sub < (ptrdiff_t) subsection_len))
Roland McGrath059c83e2008-02-21 06:19:39 +00003039 break;
3040
3041 const unsigned char *r = q + sizeof subsection_len;
3042 q = sub + subsection_len;
3043
3044 switch (subsection_tag)
3045 {
3046 default:
3047 printf (gettext (" %-4u %12" PRIu32 "\n"),
3048 subsection_tag, subsection_len);
3049 break;
3050
3051 case 1: /* Tag_File */
3052 printf (gettext (" File: %11" PRIu32 "\n"),
3053 subsection_len);
3054
3055 while (r < q)
3056 {
3057 unsigned int tag;
3058 get_uleb128 (tag, r);
3059 if (unlikely (r >= q))
3060 break;
3061
3062 uint64_t value = 0;
3063 const char *string = NULL;
3064 if (tag == 32 || (tag & 1) == 0)
3065 {
3066 get_uleb128 (value, r);
3067 if (r > q)
3068 break;
3069 }
3070 if (tag == 32 || (tag & 1) != 0)
3071 {
3072 r = memchr (r, '\0', q - r);
3073 if (r == NULL)
3074 break;
3075 ++r;
3076 }
3077
3078 const char *tag_name = NULL;
3079 const char *value_name = NULL;
3080 ebl_check_object_attribute (ebl, (const char *) name,
3081 tag, value,
3082 &tag_name, &value_name);
3083
3084 if (tag_name != NULL)
3085 {
3086 if (tag == 32)
3087 printf (gettext (" %s: %" PRId64 ", %s\n"),
3088 tag_name, value, string);
3089 else if (string == NULL && value_name == NULL)
3090 printf (gettext (" %s: %" PRId64 "\n"),
3091 tag_name, value);
3092 else
3093 printf (gettext (" %s: %s\n"),
3094 tag_name, string ?: value_name);
3095 }
3096 else
3097 {
3098 assert (tag != 32);
3099 if (string == NULL)
3100 printf (gettext (" %u: %" PRId64 "\n"),
3101 tag, value);
3102 else
3103 printf (gettext (" %u: %s\n"),
3104 tag, string);
3105 }
3106 }
3107 }
3108 }
3109 }
3110 }
3111}
3112
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003113
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003114static char *
3115format_dwarf_addr (Dwfl_Module *dwflmod,
Roland McGrath671d6d82009-08-23 17:55:05 -07003116 int address_size, Dwarf_Addr address)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003117{
3118 /* See if there is a name we can give for this address. */
3119 GElf_Sym sym;
Roland McGrath5dbccdb2009-06-28 14:48:02 -07003120 const char *name = print_address_names
Roland McGrath671d6d82009-08-23 17:55:05 -07003121 ? dwfl_module_addrsym (dwflmod, address, &sym, NULL) : NULL;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003122 if (name != NULL)
3123 sym.st_value = address - sym.st_value;
3124
3125 /* Relativize the address. */
3126 int n = dwfl_module_relocations (dwflmod);
3127 int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
3128
3129 /* In an ET_REL file there is a section name to refer to. */
3130 const char *scn = (i < 0 ? NULL
3131 : dwfl_module_relocation_info (dwflmod, i, NULL));
3132
3133 char *result;
3134 if ((name != NULL
3135 ? (sym.st_value != 0
3136 ? (scn != NULL
3137 ? (address_size == 0
3138 ? asprintf (&result,
3139 gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
3140 scn, address, name, sym.st_value)
3141 : asprintf (&result,
3142 gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
3143 scn, 2 + address_size * 2, address,
3144 name, sym.st_value))
3145 : (address_size == 0
3146 ? asprintf (&result,
3147 gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
3148 address, name, sym.st_value)
3149 : asprintf (&result,
3150 gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
3151 2 + address_size * 2, address,
3152 name, sym.st_value)))
3153 : (scn != NULL
3154 ? (address_size == 0
3155 ? asprintf (&result,
3156 gettext ("%s+%#" PRIx64 " <%s>"),
3157 scn, address, name)
3158 : asprintf (&result,
3159 gettext ("%s+%#0*" PRIx64 " <%s>"),
3160 scn, 2 + address_size * 2, address, name))
3161 : (address_size == 0
3162 ? asprintf (&result,
3163 gettext ("%#" PRIx64 " <%s>"),
3164 address, name)
3165 : asprintf (&result,
3166 gettext ("%#0*" PRIx64 " <%s>"),
3167 2 + address_size * 2, address, name))))
3168 : (scn != NULL
3169 ? (address_size == 0
3170 ? asprintf (&result,
3171 gettext ("%s+%#" PRIx64),
3172 scn, address)
3173 : asprintf (&result,
3174 gettext ("%s+%#0*" PRIx64),
3175 scn, 2 + address_size * 2, address))
3176 : (address_size == 0
3177 ? asprintf (&result,
3178 "%#" PRIx64,
3179 address)
3180 : asprintf (&result,
3181 "%#0*" PRIx64,
3182 2 + address_size * 2, address)))) < 0)
3183 error (EXIT_FAILURE, 0, _("memory exhausted"));
3184
3185 return result;
3186}
3187
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003188static const char *
3189dwarf_tag_string (unsigned int tag)
3190{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003191 static const char *const known_tags[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003192 {
3193 [DW_TAG_array_type] = "array_type",
3194 [DW_TAG_class_type] = "class_type",
3195 [DW_TAG_entry_point] = "entry_point",
3196 [DW_TAG_enumeration_type] = "enumeration_type",
3197 [DW_TAG_formal_parameter] = "formal_parameter",
3198 [DW_TAG_imported_declaration] = "imported_declaration",
3199 [DW_TAG_label] = "label",
3200 [DW_TAG_lexical_block] = "lexical_block",
3201 [DW_TAG_member] = "member",
3202 [DW_TAG_pointer_type] = "pointer_type",
3203 [DW_TAG_reference_type] = "reference_type",
3204 [DW_TAG_compile_unit] = "compile_unit",
3205 [DW_TAG_string_type] = "string_type",
3206 [DW_TAG_structure_type] = "structure_type",
3207 [DW_TAG_subroutine_type] = "subroutine_type",
3208 [DW_TAG_typedef] = "typedef",
3209 [DW_TAG_union_type] = "union_type",
3210 [DW_TAG_unspecified_parameters] = "unspecified_parameters",
3211 [DW_TAG_variant] = "variant",
3212 [DW_TAG_common_block] = "common_block",
3213 [DW_TAG_common_inclusion] = "common_inclusion",
3214 [DW_TAG_inheritance] = "inheritance",
3215 [DW_TAG_inlined_subroutine] = "inlined_subroutine",
3216 [DW_TAG_module] = "module",
3217 [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
3218 [DW_TAG_set_type] = "set_type",
3219 [DW_TAG_subrange_type] = "subrange_type",
3220 [DW_TAG_with_stmt] = "with_stmt",
3221 [DW_TAG_access_declaration] = "access_declaration",
3222 [DW_TAG_base_type] = "base_type",
3223 [DW_TAG_catch_block] = "catch_block",
3224 [DW_TAG_const_type] = "const_type",
3225 [DW_TAG_constant] = "constant",
3226 [DW_TAG_enumerator] = "enumerator",
3227 [DW_TAG_file_type] = "file_type",
3228 [DW_TAG_friend] = "friend",
3229 [DW_TAG_namelist] = "namelist",
3230 [DW_TAG_namelist_item] = "namelist_item",
3231 [DW_TAG_packed_type] = "packed_type",
3232 [DW_TAG_subprogram] = "subprogram",
Roland McGrath060fa052006-03-02 07:51:50 +00003233 [DW_TAG_template_type_parameter] = "template_type_parameter",
3234 [DW_TAG_template_value_parameter] = "template_value_parameter",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003235 [DW_TAG_thrown_type] = "thrown_type",
3236 [DW_TAG_try_block] = "try_block",
3237 [DW_TAG_variant_part] = "variant_part",
3238 [DW_TAG_variable] = "variable",
3239 [DW_TAG_volatile_type] = "volatile_type",
3240 [DW_TAG_dwarf_procedure] = "dwarf_procedure",
3241 [DW_TAG_restrict_type] = "restrict_type",
3242 [DW_TAG_interface_type] = "interface_type",
3243 [DW_TAG_namespace] = "namespace",
3244 [DW_TAG_imported_module] = "imported_module",
3245 [DW_TAG_unspecified_type] = "unspecified_type",
3246 [DW_TAG_partial_unit] = "partial_unit",
3247 [DW_TAG_imported_unit] = "imported_unit",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003248 [DW_TAG_mutable_type] = "mutable_type",
Roland McGrath060fa052006-03-02 07:51:50 +00003249 [DW_TAG_condition] = "condition",
3250 [DW_TAG_shared_type] = "shared_type",
Roland McGrath0c5638c2010-06-21 23:00:35 -07003251 [DW_TAG_type_unit] = "type_unit",
3252 [DW_TAG_rvalue_reference_type] = "rvalue_reference_type",
3253 [DW_TAG_template_alias] = "template_alias",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003254 };
3255 const unsigned int nknown_tags = (sizeof (known_tags)
3256 / sizeof (known_tags[0]));
3257 static char buf[40];
3258 const char *result = NULL;
3259
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003260 if (likely (tag < nknown_tags))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003261 result = known_tags[tag];
3262
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003263 if (unlikely (result == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003264 /* There are a few known extensions. */
3265 switch (tag)
3266 {
3267 case DW_TAG_MIPS_loop:
3268 result = "MIPS_loop";
3269 break;
3270
3271 case DW_TAG_format_label:
3272 result = "format_label";
3273 break;
3274
3275 case DW_TAG_function_template:
3276 result = "function_template";
3277 break;
3278
3279 case DW_TAG_class_template:
3280 result = "class_template";
3281 break;
3282
Roland McGrath474cb482010-06-22 00:10:54 -07003283 case DW_TAG_GNU_BINCL:
3284 result = "GNU_BINCL";
3285 break;
3286
3287 case DW_TAG_GNU_EINCL:
3288 result = "GNU_EINCL";
3289 break;
3290
3291 case DW_TAG_GNU_template_template_param:
3292 result = "GNU_template_template_param";
3293 break;
3294
3295 case DW_TAG_GNU_template_parameter_pack:
3296 result = "GNU_template_parameter_pack";
3297 break;
3298
3299 case DW_TAG_GNU_formal_parameter_pack:
3300 result = "GNU_formal_parameter_pack";
3301 break;
3302
Mark Wielaarde3368c52011-03-22 23:03:31 +01003303 case DW_TAG_GNU_call_site:
Mark Wielaard69a9b112011-05-17 15:34:02 +02003304 result = "GNU_call_site";
Mark Wielaarde3368c52011-03-22 23:03:31 +01003305 break;
3306
3307 case DW_TAG_GNU_call_site_parameter:
Mark Wielaard69a9b112011-05-17 15:34:02 +02003308 result = "GNU_call_site_parameter";
Mark Wielaarde3368c52011-03-22 23:03:31 +01003309 break;
3310
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003311 default:
3312 if (tag < DW_TAG_lo_user)
3313 snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag);
3314 else
3315 snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag);
3316 result = buf;
3317 break;
3318 }
3319
3320 return result;
3321}
3322
3323
3324static const char *
3325dwarf_attr_string (unsigned int attrnum)
3326{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003327 static const char *const known_attrs[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003328 {
3329 [DW_AT_sibling] = "sibling",
3330 [DW_AT_location] = "location",
3331 [DW_AT_name] = "name",
3332 [DW_AT_ordering] = "ordering",
3333 [DW_AT_subscr_data] = "subscr_data",
3334 [DW_AT_byte_size] = "byte_size",
3335 [DW_AT_bit_offset] = "bit_offset",
3336 [DW_AT_bit_size] = "bit_size",
3337 [DW_AT_element_list] = "element_list",
3338 [DW_AT_stmt_list] = "stmt_list",
3339 [DW_AT_low_pc] = "low_pc",
3340 [DW_AT_high_pc] = "high_pc",
3341 [DW_AT_language] = "language",
3342 [DW_AT_member] = "member",
3343 [DW_AT_discr] = "discr",
3344 [DW_AT_discr_value] = "discr_value",
3345 [DW_AT_visibility] = "visibility",
3346 [DW_AT_import] = "import",
3347 [DW_AT_string_length] = "string_length",
3348 [DW_AT_common_reference] = "common_reference",
3349 [DW_AT_comp_dir] = "comp_dir",
3350 [DW_AT_const_value] = "const_value",
3351 [DW_AT_containing_type] = "containing_type",
3352 [DW_AT_default_value] = "default_value",
3353 [DW_AT_inline] = "inline",
3354 [DW_AT_is_optional] = "is_optional",
3355 [DW_AT_lower_bound] = "lower_bound",
3356 [DW_AT_producer] = "producer",
3357 [DW_AT_prototyped] = "prototyped",
3358 [DW_AT_return_addr] = "return_addr",
3359 [DW_AT_start_scope] = "start_scope",
Roland McGrath060fa052006-03-02 07:51:50 +00003360 [DW_AT_bit_stride] = "bit_stride",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003361 [DW_AT_upper_bound] = "upper_bound",
3362 [DW_AT_abstract_origin] = "abstract_origin",
3363 [DW_AT_accessibility] = "accessibility",
3364 [DW_AT_address_class] = "address_class",
3365 [DW_AT_artificial] = "artificial",
3366 [DW_AT_base_types] = "base_types",
3367 [DW_AT_calling_convention] = "calling_convention",
3368 [DW_AT_count] = "count",
3369 [DW_AT_data_member_location] = "data_member_location",
3370 [DW_AT_decl_column] = "decl_column",
3371 [DW_AT_decl_file] = "decl_file",
3372 [DW_AT_decl_line] = "decl_line",
3373 [DW_AT_declaration] = "declaration",
3374 [DW_AT_discr_list] = "discr_list",
3375 [DW_AT_encoding] = "encoding",
3376 [DW_AT_external] = "external",
3377 [DW_AT_frame_base] = "frame_base",
3378 [DW_AT_friend] = "friend",
3379 [DW_AT_identifier_case] = "identifier_case",
3380 [DW_AT_macro_info] = "macro_info",
Roland McGrath060fa052006-03-02 07:51:50 +00003381 [DW_AT_namelist_item] = "namelist_item",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003382 [DW_AT_priority] = "priority",
3383 [DW_AT_segment] = "segment",
3384 [DW_AT_specification] = "specification",
3385 [DW_AT_static_link] = "static_link",
3386 [DW_AT_type] = "type",
3387 [DW_AT_use_location] = "use_location",
3388 [DW_AT_variable_parameter] = "variable_parameter",
3389 [DW_AT_virtuality] = "virtuality",
3390 [DW_AT_vtable_elem_location] = "vtable_elem_location",
3391 [DW_AT_allocated] = "allocated",
3392 [DW_AT_associated] = "associated",
3393 [DW_AT_data_location] = "data_location",
Roland McGrath060fa052006-03-02 07:51:50 +00003394 [DW_AT_byte_stride] = "byte_stride",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003395 [DW_AT_entry_pc] = "entry_pc",
3396 [DW_AT_use_UTF8] = "use_UTF8",
3397 [DW_AT_extension] = "extension",
3398 [DW_AT_ranges] = "ranges",
3399 [DW_AT_trampoline] = "trampoline",
3400 [DW_AT_call_column] = "call_column",
3401 [DW_AT_call_file] = "call_file",
3402 [DW_AT_call_line] = "call_line",
Roland McGrath060fa052006-03-02 07:51:50 +00003403 [DW_AT_description] = "description",
3404 [DW_AT_binary_scale] = "binary_scale",
3405 [DW_AT_decimal_scale] = "decimal_scale",
3406 [DW_AT_small] = "small",
3407 [DW_AT_decimal_sign] = "decimal_sign",
3408 [DW_AT_digit_count] = "digit_count",
3409 [DW_AT_picture_string] = "picture_string",
3410 [DW_AT_mutable] = "mutable",
3411 [DW_AT_threads_scaled] = "threads_scaled",
3412 [DW_AT_explicit] = "explicit",
3413 [DW_AT_object_pointer] = "object_pointer",
3414 [DW_AT_endianity] = "endianity",
3415 [DW_AT_elemental] = "elemental",
3416 [DW_AT_pure] = "pure",
3417 [DW_AT_recursive] = "recursive",
Roland McGrath474cb482010-06-22 00:10:54 -07003418 [DW_AT_signature] = "signature",
3419 [DW_AT_main_subprogram] = "main_subprogram",
3420 [DW_AT_data_bit_offset] = "data_bit_offset",
3421 [DW_AT_const_expr] = "const_expr",
3422 [DW_AT_enum_class] = "enum_class",
3423 [DW_AT_linkage_name] = "linkage_name",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003424 };
3425 const unsigned int nknown_attrs = (sizeof (known_attrs)
3426 / sizeof (known_attrs[0]));
3427 static char buf[40];
3428 const char *result = NULL;
3429
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003430 if (likely (attrnum < nknown_attrs))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003431 result = known_attrs[attrnum];
3432
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003433 if (unlikely (result == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003434 /* There are a few known extensions. */
3435 switch (attrnum)
3436 {
3437 case DW_AT_MIPS_fde:
3438 result = "MIPS_fde";
3439 break;
3440
3441 case DW_AT_MIPS_loop_begin:
3442 result = "MIPS_loop_begin";
3443 break;
3444
3445 case DW_AT_MIPS_tail_loop_begin:
3446 result = "MIPS_tail_loop_begin";
3447 break;
3448
3449 case DW_AT_MIPS_epilog_begin:
3450 result = "MIPS_epilog_begin";
3451 break;
3452
3453 case DW_AT_MIPS_loop_unroll_factor:
3454 result = "MIPS_loop_unroll_factor";
3455 break;
3456
3457 case DW_AT_MIPS_software_pipeline_depth:
3458 result = "MIPS_software_pipeline_depth";
3459 break;
3460
3461 case DW_AT_MIPS_linkage_name:
3462 result = "MIPS_linkage_name";
3463 break;
3464
3465 case DW_AT_MIPS_stride:
3466 result = "MIPS_stride";
3467 break;
3468
3469 case DW_AT_MIPS_abstract_name:
3470 result = "MIPS_abstract_name";
3471 break;
3472
3473 case DW_AT_MIPS_clone_origin:
3474 result = "MIPS_clone_origin";
3475 break;
3476
3477 case DW_AT_MIPS_has_inlines:
3478 result = "MIPS_has_inlines";
3479 break;
3480
3481 case DW_AT_MIPS_stride_byte:
3482 result = "MIPS_stride_byte";
3483 break;
3484
3485 case DW_AT_MIPS_stride_elem:
3486 result = "MIPS_stride_elem";
3487 break;
3488
3489 case DW_AT_MIPS_ptr_dopetype:
3490 result = "MIPS_ptr_dopetype";
3491 break;
3492
3493 case DW_AT_MIPS_allocatable_dopetype:
3494 result = "MIPS_allocatable_dopetype";
3495 break;
3496
3497 case DW_AT_MIPS_assumed_shape_dopetype:
3498 result = "MIPS_assumed_shape_dopetype";
3499 break;
3500
3501 case DW_AT_MIPS_assumed_size:
3502 result = "MIPS_assumed_size";
3503 break;
3504
3505 case DW_AT_sf_names:
3506 result = "sf_names";
3507 break;
3508
3509 case DW_AT_src_info:
3510 result = "src_info";
3511 break;
3512
3513 case DW_AT_mac_info:
3514 result = "mac_info";
3515 break;
3516
3517 case DW_AT_src_coords:
3518 result = "src_coords";
3519 break;
3520
3521 case DW_AT_body_begin:
3522 result = "body_begin";
3523 break;
3524
3525 case DW_AT_body_end:
3526 result = "body_end";
3527 break;
3528
Roland McGrath019d9fb2010-01-05 13:36:07 -08003529 case DW_AT_GNU_vector:
3530 result = "GNU_vector";
3531 break;
3532
Mark Wielaardcf454ab2011-02-25 12:58:54 +01003533 case DW_AT_GNU_guarded_by:
3534 result = "GNU_guarded_by";
3535 break;
3536
3537 case DW_AT_GNU_pt_guarded_by:
3538 result = "GNU_pt_guarded_by";
3539 break;
3540
3541 case DW_AT_GNU_guarded:
3542 result = "GNU_guarded";
3543 break;
3544
3545 case DW_AT_GNU_pt_guarded:
3546 result = "GNU_pt_guarded";
3547 break;
3548
3549 case DW_AT_GNU_locks_excluded:
3550 result = "GNU_locks_excluded";
3551 break;
3552
3553 case DW_AT_GNU_exclusive_locks_required:
3554 result = "GNU_exclusive_locks_required";
3555 break;
3556
3557 case DW_AT_GNU_shared_locks_required:
3558 result = "GNU_shared_locks_required";
3559 break;
3560
Roland McGrath47c53232011-02-23 09:23:08 -08003561 case DW_AT_GNU_odr_signature:
3562 result = "GNU_odr_signature";
3563 break;
3564
Roland McGrath019d9fb2010-01-05 13:36:07 -08003565 case DW_AT_GNU_template_name:
3566 result = "GNU_template_name";
3567 break;
3568
Mark Wielaarde3368c52011-03-22 23:03:31 +01003569 case DW_AT_GNU_call_site_value:
3570 result = "GNU_call_site_value";
3571 break;
3572
3573 case DW_AT_GNU_call_site_data_value:
3574 result = "GNU_call_site_data_value";
3575 break;
3576
3577 case DW_AT_GNU_call_site_target:
3578 result = "GNU_call_site_target";
3579 break;
3580
3581 case DW_AT_GNU_call_site_target_clobbered:
3582 result = "GNU_call_site_target_clobbered";
3583 break;
3584
3585 case DW_AT_GNU_tail_call:
3586 result = "GNU_tail_call";
3587 break;
3588
3589 case DW_AT_GNU_all_tail_call_sites:
3590 result = "GNU_all_tail_call_sites";
3591 break;
3592
3593 case DW_AT_GNU_all_call_sites:
3594 result = "GNU_all_call_sites";
3595 break;
3596
3597 case DW_AT_GNU_all_source_call_sites:
3598 result = "GNU_all_source_call_sites";
3599 break;
3600
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003601 default:
3602 if (attrnum < DW_AT_lo_user)
3603 snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"),
3604 attrnum);
3605 else
3606 snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"),
3607 attrnum);
3608 result = buf;
3609 break;
3610 }
3611
3612 return result;
3613}
3614
3615
3616static const char *
3617dwarf_form_string (unsigned int form)
3618{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003619 static const char *const known_forms[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003620 {
3621 [DW_FORM_addr] = "addr",
3622 [DW_FORM_block2] = "block2",
3623 [DW_FORM_block4] = "block4",
3624 [DW_FORM_data2] = "data2",
3625 [DW_FORM_data4] = "data4",
3626 [DW_FORM_data8] = "data8",
3627 [DW_FORM_string] = "string",
3628 [DW_FORM_block] = "block",
3629 [DW_FORM_block1] = "block1",
3630 [DW_FORM_data1] = "data1",
3631 [DW_FORM_flag] = "flag",
3632 [DW_FORM_sdata] = "sdata",
3633 [DW_FORM_strp] = "strp",
3634 [DW_FORM_udata] = "udata",
3635 [DW_FORM_ref_addr] = "ref_addr",
3636 [DW_FORM_ref1] = "ref1",
3637 [DW_FORM_ref2] = "ref2",
3638 [DW_FORM_ref4] = "ref4",
3639 [DW_FORM_ref8] = "ref8",
3640 [DW_FORM_ref_udata] = "ref_udata",
Roland McGrath7fac1ce2010-06-01 15:56:58 -07003641 [DW_FORM_indirect] = "indirect",
3642 [DW_FORM_sec_offset] = "sec_offset",
3643 [DW_FORM_exprloc] = "exprloc",
3644 [DW_FORM_flag_present] = "flag_present",
Mark Wielaardcf454ab2011-02-25 12:58:54 +01003645 [DW_FORM_ref_sig8] = "ref_sig8",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003646 };
3647 const unsigned int nknown_forms = (sizeof (known_forms)
3648 / sizeof (known_forms[0]));
3649 static char buf[40];
3650 const char *result = NULL;
3651
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003652 if (likely (form < nknown_forms))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003653 result = known_forms[form];
3654
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003655 if (unlikely (result == NULL))
Mark Wielaardcf454ab2011-02-25 12:58:54 +01003656 {
3657 snprintf (buf, sizeof buf, gettext ("unknown form %#" PRIx64),
3658 (uint64_t) form);
3659 result = buf;
3660 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003661
3662 return result;
3663}
3664
3665
3666static const char *
3667dwarf_lang_string (unsigned int lang)
3668{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003669 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003670 {
3671 [DW_LANG_C89] = "ISO C89",
3672 [DW_LANG_C] = "C",
3673 [DW_LANG_Ada83] = "Ada83",
Roland McGrath060fa052006-03-02 07:51:50 +00003674 [DW_LANG_C_plus_plus] = "C++",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003675 [DW_LANG_Cobol74] = "Cobol74",
3676 [DW_LANG_Cobol85] = "Cobol85",
3677 [DW_LANG_Fortran77] = "Fortran77",
3678 [DW_LANG_Fortran90] = "Fortran90",
3679 [DW_LANG_Pascal83] = "Pascal83",
3680 [DW_LANG_Modula2] = "Modula2",
3681 [DW_LANG_Java] = "Java",
3682 [DW_LANG_C99] = "ISO C99",
3683 [DW_LANG_Ada95] = "Ada95",
3684 [DW_LANG_Fortran95] = "Fortran95",
Roland McGrath060fa052006-03-02 07:51:50 +00003685 [DW_LANG_PL1] = "PL1",
3686 [DW_LANG_Objc] = "Objective C",
3687 [DW_LANG_ObjC_plus_plus] = "Objective C++",
3688 [DW_LANG_UPC] = "UPC",
3689 [DW_LANG_D] = "D",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003690 };
3691
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003692 if (likely (lang < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003693 return known[lang];
3694 else if (lang == DW_LANG_Mips_Assembler)
3695 /* This language tag is used for assembler in general. */
3696 return "Assembler";
3697
3698 if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user)
3699 {
3700 static char buf[30];
3701 snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user);
3702 return buf;
3703 }
3704
3705 return "???";
3706}
3707
3708
3709static const char *
3710dwarf_inline_string (unsigned int code)
3711{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003712 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003713 {
3714 [DW_INL_not_inlined] = "not_inlined",
3715 [DW_INL_inlined] = "inlined",
3716 [DW_INL_declared_not_inlined] = "declared_not_inlined",
3717 [DW_INL_declared_inlined] = "declared_inlined"
3718 };
3719
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003720 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003721 return known[code];
3722
3723 return "???";
3724}
3725
3726
3727static const char *
3728dwarf_encoding_string (unsigned int code)
3729{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003730 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003731 {
3732 [DW_ATE_void] = "void",
3733 [DW_ATE_address] = "address",
3734 [DW_ATE_boolean] = "boolean",
3735 [DW_ATE_complex_float] = "complex_float",
3736 [DW_ATE_float] = "float",
3737 [DW_ATE_signed] = "signed",
3738 [DW_ATE_signed_char] = "signed_char",
3739 [DW_ATE_unsigned] = "unsigned",
3740 [DW_ATE_unsigned_char] = "unsigned_char",
Roland McGrath060fa052006-03-02 07:51:50 +00003741 [DW_ATE_imaginary_float] = "imaginary_float",
3742 [DW_ATE_packed_decimal] = "packed_decimal",
3743 [DW_ATE_numeric_string] = "numeric_string",
3744 [DW_ATE_edited] = "edited",
3745 [DW_ATE_signed_fixed] = "signed_fixed",
3746 [DW_ATE_unsigned_fixed] = "unsigned_fixed",
3747 [DW_ATE_decimal_float] = "decimal_float",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003748 };
3749
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003750 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003751 return known[code];
3752
3753 if (code >= DW_ATE_lo_user && code <= DW_ATE_hi_user)
3754 {
3755 static char buf[30];
3756 snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_ATE_lo_user);
3757 return buf;
3758 }
3759
3760 return "???";
3761}
3762
3763
3764static const char *
3765dwarf_access_string (unsigned int code)
3766{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003767 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003768 {
3769 [DW_ACCESS_public] = "public",
3770 [DW_ACCESS_protected] = "protected",
3771 [DW_ACCESS_private] = "private"
3772 };
3773
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003774 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003775 return known[code];
3776
3777 return "???";
3778}
3779
3780
3781static const char *
3782dwarf_visibility_string (unsigned int code)
3783{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003784 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003785 {
3786 [DW_VIS_local] = "local",
3787 [DW_VIS_exported] = "exported",
3788 [DW_VIS_qualified] = "qualified"
3789 };
3790
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003791 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003792 return known[code];
3793
3794 return "???";
3795}
3796
3797
3798static const char *
3799dwarf_virtuality_string (unsigned int code)
3800{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003801 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003802 {
3803 [DW_VIRTUALITY_none] = "none",
3804 [DW_VIRTUALITY_virtual] = "virtual",
3805 [DW_VIRTUALITY_pure_virtual] = "pure_virtual"
3806 };
3807
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003808 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003809 return known[code];
3810
3811 return "???";
3812}
3813
3814
3815static const char *
3816dwarf_identifier_case_string (unsigned int code)
3817{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003818 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003819 {
3820 [DW_ID_case_sensitive] = "sensitive",
3821 [DW_ID_up_case] = "up_case",
3822 [DW_ID_down_case] = "down_case",
3823 [DW_ID_case_insensitive] = "insensitive"
3824 };
3825
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003826 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003827 return known[code];
3828
3829 return "???";
3830}
3831
3832
3833static const char *
3834dwarf_calling_convention_string (unsigned int code)
3835{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003836 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003837 {
3838 [DW_CC_normal] = "normal",
3839 [DW_CC_program] = "program",
3840 [DW_CC_nocall] = "nocall",
3841 };
3842
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003843 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003844 return known[code];
3845
3846 if (code >= DW_CC_lo_user && code <= DW_CC_hi_user)
3847 {
3848 static char buf[30];
3849 snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_CC_lo_user);
3850 return buf;
3851 }
3852
3853 return "???";
3854}
3855
3856
3857static const char *
3858dwarf_ordering_string (unsigned int code)
3859{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003860 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003861 {
3862 [DW_ORD_row_major] = "row_major",
3863 [DW_ORD_col_major] = "col_major"
3864 };
3865
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003866 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003867 return known[code];
3868
3869 return "???";
3870}
3871
3872
3873static const char *
3874dwarf_discr_list_string (unsigned int code)
3875{
Ulrich Drepper8b383102007-02-16 00:31:57 +00003876 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003877 {
3878 [DW_DSC_label] = "label",
3879 [DW_DSC_range] = "range"
3880 };
3881
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00003882 if (likely (code < sizeof (known) / sizeof (known[0])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003883 return known[code];
3884
3885 return "???";
3886}
3887
3888
3889static void
Roland McGrathbe4589d2009-07-24 16:23:12 -07003890print_block (size_t n, const void *block)
3891{
3892 if (n == 0)
3893 puts (_("empty block"));
3894 else
3895 {
3896 printf (_("%zu byte block:"), n);
3897 const unsigned char *data = block;
3898 do
3899 printf (" %02x", *data++);
3900 while (--n > 0);
3901 putchar ('\n');
3902 }
3903}
3904
3905static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00003906print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
Roland McGrath52604ba2010-07-26 21:29:44 -07003907 unsigned int vers, unsigned int addrsize, unsigned int offset_size,
Roland McGrath688f7fc2010-05-08 03:22:59 -07003908 Dwarf_Word len, const unsigned char *data)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003909{
Roland McGrath52604ba2010-07-26 21:29:44 -07003910 const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
3911
Ulrich Drepper8b383102007-02-16 00:31:57 +00003912 static const char *const known[] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003913 {
3914 [DW_OP_addr] = "addr",
3915 [DW_OP_deref] = "deref",
3916 [DW_OP_const1u] = "const1u",
3917 [DW_OP_const1s] = "const1s",
3918 [DW_OP_const2u] = "const2u",
3919 [DW_OP_const2s] = "const2s",
3920 [DW_OP_const4u] = "const4u",
3921 [DW_OP_const4s] = "const4s",
3922 [DW_OP_const8u] = "const8u",
3923 [DW_OP_const8s] = "const8s",
3924 [DW_OP_constu] = "constu",
3925 [DW_OP_consts] = "consts",
3926 [DW_OP_dup] = "dup",
3927 [DW_OP_drop] = "drop",
3928 [DW_OP_over] = "over",
3929 [DW_OP_pick] = "pick",
3930 [DW_OP_swap] = "swap",
3931 [DW_OP_rot] = "rot",
3932 [DW_OP_xderef] = "xderef",
3933 [DW_OP_abs] = "abs",
3934 [DW_OP_and] = "and",
3935 [DW_OP_div] = "div",
3936 [DW_OP_minus] = "minus",
3937 [DW_OP_mod] = "mod",
3938 [DW_OP_mul] = "mul",
3939 [DW_OP_neg] = "neg",
3940 [DW_OP_not] = "not",
3941 [DW_OP_or] = "or",
3942 [DW_OP_plus] = "plus",
3943 [DW_OP_plus_uconst] = "plus_uconst",
3944 [DW_OP_shl] = "shl",
3945 [DW_OP_shr] = "shr",
3946 [DW_OP_shra] = "shra",
3947 [DW_OP_xor] = "xor",
3948 [DW_OP_bra] = "bra",
3949 [DW_OP_eq] = "eq",
3950 [DW_OP_ge] = "ge",
3951 [DW_OP_gt] = "gt",
3952 [DW_OP_le] = "le",
3953 [DW_OP_lt] = "lt",
3954 [DW_OP_ne] = "ne",
3955 [DW_OP_skip] = "skip",
3956 [DW_OP_lit0] = "lit0",
3957 [DW_OP_lit1] = "lit1",
3958 [DW_OP_lit2] = "lit2",
3959 [DW_OP_lit3] = "lit3",
3960 [DW_OP_lit4] = "lit4",
3961 [DW_OP_lit5] = "lit5",
3962 [DW_OP_lit6] = "lit6",
3963 [DW_OP_lit7] = "lit7",
3964 [DW_OP_lit8] = "lit8",
3965 [DW_OP_lit9] = "lit9",
3966 [DW_OP_lit10] = "lit10",
3967 [DW_OP_lit11] = "lit11",
3968 [DW_OP_lit12] = "lit12",
3969 [DW_OP_lit13] = "lit13",
3970 [DW_OP_lit14] = "lit14",
3971 [DW_OP_lit15] = "lit15",
3972 [DW_OP_lit16] = "lit16",
3973 [DW_OP_lit17] = "lit17",
3974 [DW_OP_lit18] = "lit18",
3975 [DW_OP_lit19] = "lit19",
3976 [DW_OP_lit20] = "lit20",
3977 [DW_OP_lit21] = "lit21",
3978 [DW_OP_lit22] = "lit22",
3979 [DW_OP_lit23] = "lit23",
3980 [DW_OP_lit24] = "lit24",
3981 [DW_OP_lit25] = "lit25",
3982 [DW_OP_lit26] = "lit26",
3983 [DW_OP_lit27] = "lit27",
3984 [DW_OP_lit28] = "lit28",
3985 [DW_OP_lit29] = "lit29",
3986 [DW_OP_lit30] = "lit30",
3987 [DW_OP_lit31] = "lit31",
3988 [DW_OP_reg0] = "reg0",
3989 [DW_OP_reg1] = "reg1",
3990 [DW_OP_reg2] = "reg2",
3991 [DW_OP_reg3] = "reg3",
3992 [DW_OP_reg4] = "reg4",
3993 [DW_OP_reg5] = "reg5",
3994 [DW_OP_reg6] = "reg6",
3995 [DW_OP_reg7] = "reg7",
3996 [DW_OP_reg8] = "reg8",
3997 [DW_OP_reg9] = "reg9",
3998 [DW_OP_reg10] = "reg10",
3999 [DW_OP_reg11] = "reg11",
4000 [DW_OP_reg12] = "reg12",
4001 [DW_OP_reg13] = "reg13",
4002 [DW_OP_reg14] = "reg14",
4003 [DW_OP_reg15] = "reg15",
4004 [DW_OP_reg16] = "reg16",
4005 [DW_OP_reg17] = "reg17",
4006 [DW_OP_reg18] = "reg18",
4007 [DW_OP_reg19] = "reg19",
4008 [DW_OP_reg20] = "reg20",
4009 [DW_OP_reg21] = "reg21",
4010 [DW_OP_reg22] = "reg22",
4011 [DW_OP_reg23] = "reg23",
4012 [DW_OP_reg24] = "reg24",
4013 [DW_OP_reg25] = "reg25",
4014 [DW_OP_reg26] = "reg26",
4015 [DW_OP_reg27] = "reg27",
4016 [DW_OP_reg28] = "reg28",
4017 [DW_OP_reg29] = "reg29",
4018 [DW_OP_reg30] = "reg30",
4019 [DW_OP_reg31] = "reg31",
4020 [DW_OP_breg0] = "breg0",
4021 [DW_OP_breg1] = "breg1",
4022 [DW_OP_breg2] = "breg2",
4023 [DW_OP_breg3] = "breg3",
4024 [DW_OP_breg4] = "breg4",
4025 [DW_OP_breg5] = "breg5",
4026 [DW_OP_breg6] = "breg6",
4027 [DW_OP_breg7] = "breg7",
4028 [DW_OP_breg8] = "breg8",
4029 [DW_OP_breg9] = "breg9",
4030 [DW_OP_breg10] = "breg10",
4031 [DW_OP_breg11] = "breg11",
4032 [DW_OP_breg12] = "breg12",
4033 [DW_OP_breg13] = "breg13",
4034 [DW_OP_breg14] = "breg14",
4035 [DW_OP_breg15] = "breg15",
4036 [DW_OP_breg16] = "breg16",
4037 [DW_OP_breg17] = "breg17",
4038 [DW_OP_breg18] = "breg18",
4039 [DW_OP_breg19] = "breg19",
4040 [DW_OP_breg20] = "breg20",
4041 [DW_OP_breg21] = "breg21",
4042 [DW_OP_breg22] = "breg22",
4043 [DW_OP_breg23] = "breg23",
4044 [DW_OP_breg24] = "breg24",
4045 [DW_OP_breg25] = "breg25",
4046 [DW_OP_breg26] = "breg26",
4047 [DW_OP_breg27] = "breg27",
4048 [DW_OP_breg28] = "breg28",
4049 [DW_OP_breg29] = "breg29",
4050 [DW_OP_breg30] = "breg30",
4051 [DW_OP_breg31] = "breg31",
4052 [DW_OP_regx] = "regx",
4053 [DW_OP_fbreg] = "fbreg",
4054 [DW_OP_bregx] = "bregx",
4055 [DW_OP_piece] = "piece",
4056 [DW_OP_deref_size] = "deref_size",
4057 [DW_OP_xderef_size] = "xderef_size",
4058 [DW_OP_nop] = "nop",
4059 [DW_OP_push_object_address] = "push_object_address",
4060 [DW_OP_call2] = "call2",
4061 [DW_OP_call4] = "call4",
4062 [DW_OP_call_ref] = "call_ref",
Roland McGrath060fa052006-03-02 07:51:50 +00004063 [DW_OP_form_tls_address] = "form_tls_address",
4064 [DW_OP_call_frame_cfa] = "call_frame_cfa",
4065 [DW_OP_bit_piece] = "bit_piece",
Mark Wielaarddaf85b22009-07-24 15:49:51 -07004066 [DW_OP_implicit_value] = "implicit_value",
4067 [DW_OP_stack_value] = "stack_value",
Roland McGrath932585d2010-05-08 04:01:14 -07004068 [DW_OP_GNU_implicit_pointer] = "GNU_implicit_pointer",
Mark Wielaarde3368c52011-03-22 23:03:31 +01004069 [DW_OP_GNU_entry_value] = "GNU_entry_value",
Jakub Jelinek03124242011-05-17 17:00:14 +02004070 [DW_OP_GNU_const_type] = "GNU_const_type",
4071 [DW_OP_GNU_regval_type] = "GNU_regval_type",
4072 [DW_OP_GNU_deref_type] = "GNU_deref_type",
4073 [DW_OP_GNU_convert] = "GNU_convert",
4074 [DW_OP_GNU_reinterpret] = "GNU_reinterpret",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004075 };
4076
Roland McGrath51f01282009-01-27 17:08:03 -08004077 if (len == 0)
4078 {
4079 printf ("%*s(empty)\n", indent, "");
4080 return;
4081 }
4082
Roland McGratha1599152010-08-30 04:04:37 -07004083#define NEED(n) if (len < (Dwarf_Word) (n)) goto invalid
4084#define CONSUME(n) NEED (n); else len -= (n)
Roland McGrath51f01282009-01-27 17:08:03 -08004085
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004086 Dwarf_Word offset = 0;
4087 while (len-- > 0)
4088 {
Roland McGrath1a2e8f42007-12-15 23:39:34 +00004089 uint_fast8_t op = *data++;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004090
4091 switch (op)
4092 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004093 case DW_OP_addr:;
4094 /* Address operand. */
4095 Dwarf_Word addr;
Roland McGrath51f01282009-01-27 17:08:03 -08004096 NEED (addrsize);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004097 if (addrsize == 4)
4098 addr = read_4ubyte_unaligned (dbg, data);
4099 else
4100 {
4101 assert (addrsize == 8);
4102 addr = read_8ubyte_unaligned (dbg, data);
4103 }
4104 data += addrsize;
Roland McGratha1599152010-08-30 04:04:37 -07004105 CONSUME (addrsize);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004106
Roland McGrath688f7fc2010-05-08 03:22:59 -07004107 char *a = format_dwarf_addr (dwflmod, 0, addr);
4108 printf ("%*s[%4" PRIuMAX "] %s %s\n",
4109 indent, "", (uintmax_t) offset, known[op], a);
4110 free (a);
4111
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004112 offset += 1 + addrsize;
4113 break;
4114
Roland McGrath688f7fc2010-05-08 03:22:59 -07004115 case DW_OP_call_ref:
4116 /* Offset operand. */
Roland McGrath52604ba2010-07-26 21:29:44 -07004117 NEED (ref_size);
4118 if (ref_size == 4)
Roland McGrath688f7fc2010-05-08 03:22:59 -07004119 addr = read_4ubyte_unaligned (dbg, data);
4120 else
4121 {
Roland McGrath52604ba2010-07-26 21:29:44 -07004122 assert (ref_size == 8);
Roland McGrath688f7fc2010-05-08 03:22:59 -07004123 addr = read_8ubyte_unaligned (dbg, data);
4124 }
Roland McGrath52604ba2010-07-26 21:29:44 -07004125 data += ref_size;
Roland McGratha1599152010-08-30 04:04:37 -07004126 CONSUME (ref_size);
Roland McGrath688f7fc2010-05-08 03:22:59 -07004127
4128 printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
4129 indent, "", (uintmax_t) offset,
4130 known[op], (uintmax_t) addr);
Roland McGrath52604ba2010-07-26 21:29:44 -07004131 offset += 1 + ref_size;
Roland McGrath688f7fc2010-05-08 03:22:59 -07004132 break;
4133
Roland McGrath060fa052006-03-02 07:51:50 +00004134 case DW_OP_deref_size:
4135 case DW_OP_xderef_size:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004136 case DW_OP_pick:
4137 case DW_OP_const1u:
Ulrich Drepperac194d02009-01-06 00:30:01 -08004138 // XXX value might be modified by relocation
Roland McGrath51f01282009-01-27 17:08:03 -08004139 NEED (1);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004140 printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
4141 indent, "", (uintmax_t) offset,
Ulrich Drepperac194d02009-01-06 00:30:01 -08004142 known[op], *((uint8_t *) data));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004143 ++data;
4144 --len;
4145 offset += 2;
4146 break;
4147
4148 case DW_OP_const2u:
Roland McGrath51f01282009-01-27 17:08:03 -08004149 NEED (2);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004150 // XXX value might be modified by relocation
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004151 printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
4152 indent, "", (uintmax_t) offset,
Ulrich Drepperac194d02009-01-06 00:30:01 -08004153 known[op], read_2ubyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004154 CONSUME (2);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004155 data += 2;
4156 offset += 3;
4157 break;
4158
4159 case DW_OP_const4u:
Roland McGrath51f01282009-01-27 17:08:03 -08004160 NEED (4);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004161 // XXX value might be modified by relocation
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004162 printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
4163 indent, "", (uintmax_t) offset,
Ulrich Drepperac194d02009-01-06 00:30:01 -08004164 known[op], read_4ubyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004165 CONSUME (4);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004166 data += 4;
4167 offset += 5;
4168 break;
4169
4170 case DW_OP_const8u:
Roland McGrath51f01282009-01-27 17:08:03 -08004171 NEED (8);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004172 // XXX value might be modified by relocation
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004173 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
4174 indent, "", (uintmax_t) offset,
Ulrich Drepperac194d02009-01-06 00:30:01 -08004175 known[op], read_8ubyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004176 CONSUME (8);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004177 data += 8;
4178 offset += 9;
4179 break;
4180
4181 case DW_OP_const1s:
Roland McGrath51f01282009-01-27 17:08:03 -08004182 NEED (1);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004183 // XXX value might be modified by relocation
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004184 printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
4185 indent, "", (uintmax_t) offset,
Ulrich Drepperac194d02009-01-06 00:30:01 -08004186 known[op], *((int8_t *) data));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004187 ++data;
4188 --len;
4189 offset += 2;
4190 break;
4191
4192 case DW_OP_const2s:
Roland McGrath51f01282009-01-27 17:08:03 -08004193 NEED (2);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004194 // XXX value might be modified by relocation
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004195 printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
4196 indent, "", (uintmax_t) offset,
Ulrich Drepperac194d02009-01-06 00:30:01 -08004197 known[op], read_2sbyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004198 CONSUME (2);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004199 data += 2;
4200 offset += 3;
4201 break;
4202
4203 case DW_OP_const4s:
Roland McGrath51f01282009-01-27 17:08:03 -08004204 NEED (4);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004205 // XXX value might be modified by relocation
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004206 printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
4207 indent, "", (uintmax_t) offset,
Ulrich Drepperac194d02009-01-06 00:30:01 -08004208 known[op], read_4sbyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004209 CONSUME (4);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004210 data += 4;
4211 offset += 5;
4212 break;
4213
4214 case DW_OP_const8s:
Roland McGrath51f01282009-01-27 17:08:03 -08004215 NEED (8);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004216 // XXX value might be modified by relocation
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004217 printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
4218 indent, "", (uintmax_t) offset,
Ulrich Drepperac194d02009-01-06 00:30:01 -08004219 known[op], read_8sbyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004220 CONSUME (8);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004221 data += 8;
4222 offset += 9;
4223 break;
4224
Roland McGrath060fa052006-03-02 07:51:50 +00004225 case DW_OP_piece:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004226 case DW_OP_regx:
4227 case DW_OP_plus_uconst:
4228 case DW_OP_constu:;
4229 const unsigned char *start = data;
Roland McGrath0c5638c2010-06-21 23:00:35 -07004230 uint64_t uleb;
Roland McGratha1599152010-08-30 04:04:37 -07004231 NEED (1);
Roland McGrath51f01282009-01-27 17:08:03 -08004232 get_uleb128 (uleb, data); /* XXX check overrun */
Roland McGrath0c5638c2010-06-21 23:00:35 -07004233 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
Ulrich Drepperac194d02009-01-06 00:30:01 -08004234 indent, "", (uintmax_t) offset, known[op], uleb);
Roland McGratha1599152010-08-30 04:04:37 -07004235 CONSUME (data - start);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004236 offset += 1 + (data - start);
4237 break;
4238
Roland McGrath060fa052006-03-02 07:51:50 +00004239 case DW_OP_bit_piece:
4240 start = data;
Roland McGrath0c5638c2010-06-21 23:00:35 -07004241 uint64_t uleb2;
Roland McGratha1599152010-08-30 04:04:37 -07004242 NEED (2);
Roland McGrath51f01282009-01-27 17:08:03 -08004243 get_uleb128 (uleb, data); /* XXX check overrun */
4244 get_uleb128 (uleb2, data); /* XXX check overrun */
Roland McGrath0c5638c2010-06-21 23:00:35 -07004245 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
Ulrich Drepperac194d02009-01-06 00:30:01 -08004246 indent, "", (uintmax_t) offset, known[op], uleb, uleb2);
Roland McGratha1599152010-08-30 04:04:37 -07004247 CONSUME (data - start);
Roland McGrath060fa052006-03-02 07:51:50 +00004248 offset += 1 + (data - start);
4249 break;
4250
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004251 case DW_OP_fbreg:
4252 case DW_OP_breg0 ... DW_OP_breg31:
4253 case DW_OP_consts:
4254 start = data;
Roland McGrath0c5638c2010-06-21 23:00:35 -07004255 int64_t sleb;
Roland McGratha1599152010-08-30 04:04:37 -07004256 NEED (1);
Roland McGrath51f01282009-01-27 17:08:03 -08004257 get_sleb128 (sleb, data); /* XXX check overrun */
Roland McGrath0c5638c2010-06-21 23:00:35 -07004258 printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
Ulrich Drepperac194d02009-01-06 00:30:01 -08004259 indent, "", (uintmax_t) offset, known[op], sleb);
Roland McGratha1599152010-08-30 04:04:37 -07004260 CONSUME (data - start);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004261 offset += 1 + (data - start);
4262 break;
4263
4264 case DW_OP_bregx:
4265 start = data;
Roland McGratha1599152010-08-30 04:04:37 -07004266 NEED (2);
Roland McGrath51f01282009-01-27 17:08:03 -08004267 get_uleb128 (uleb, data); /* XXX check overrun */
4268 get_sleb128 (sleb, data); /* XXX check overrun */
Roland McGrath0c5638c2010-06-21 23:00:35 -07004269 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
Ulrich Drepperac194d02009-01-06 00:30:01 -08004270 indent, "", (uintmax_t) offset, known[op], uleb, sleb);
Roland McGratha1599152010-08-30 04:04:37 -07004271 CONSUME (data - start);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004272 offset += 1 + (data - start);
4273 break;
4274
4275 case DW_OP_call2:
Roland McGrath51f01282009-01-27 17:08:03 -08004276 NEED (2);
4277 printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
4278 indent, "", (uintmax_t) offset, known[op],
4279 read_2ubyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004280 CONSUME (2);
Roland McGrath51f01282009-01-27 17:08:03 -08004281 offset += 3;
4282 break;
4283
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004284 case DW_OP_call4:
Roland McGrath51f01282009-01-27 17:08:03 -08004285 NEED (4);
4286 printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
4287 indent, "", (uintmax_t) offset, known[op],
4288 read_4ubyte_unaligned (dbg, data));
Roland McGratha1599152010-08-30 04:04:37 -07004289 CONSUME (4);
Roland McGrath51f01282009-01-27 17:08:03 -08004290 offset += 5;
4291 break;
4292
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004293 case DW_OP_skip:
4294 case DW_OP_bra:
Roland McGrath51f01282009-01-27 17:08:03 -08004295 NEED (2);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004296 printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
Ulrich Drepperac194d02009-01-06 00:30:01 -08004297 indent, "", (uintmax_t) offset, known[op],
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004298 (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
Roland McGratha1599152010-08-30 04:04:37 -07004299 CONSUME (2);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004300 data += 2;
4301 offset += 3;
4302 break;
4303
Mark Wielaarddaf85b22009-07-24 15:49:51 -07004304 case DW_OP_implicit_value:
4305 start = data;
Roland McGratha1599152010-08-30 04:04:37 -07004306 NEED (1);
Mark Wielaarddaf85b22009-07-24 15:49:51 -07004307 get_uleb128 (uleb, data); /* XXX check overrun */
Roland McGrathbe4589d2009-07-24 16:23:12 -07004308 printf ("%*s[%4" PRIuMAX "] %s: ",
4309 indent, "", (uintmax_t) offset, known[op]);
Mark Wielaarddaf85b22009-07-24 15:49:51 -07004310 NEED (uleb);
Roland McGrathbe4589d2009-07-24 16:23:12 -07004311 print_block (uleb, data);
4312 data += uleb;
Roland McGratha1599152010-08-30 04:04:37 -07004313 CONSUME (data - start);
Mark Wielaarddaf85b22009-07-24 15:49:51 -07004314 offset += 1 + (data - start);
4315 break;
4316
Roland McGrath932585d2010-05-08 04:01:14 -07004317 case DW_OP_GNU_implicit_pointer:
4318 /* DIE offset operand. */
4319 start = data;
4320 NEED (ref_size + 1);
4321 if (ref_size == 4)
4322 addr = read_4ubyte_unaligned (dbg, data);
4323 else
4324 {
4325 assert (ref_size == 8);
4326 addr = read_8ubyte_unaligned (dbg, data);
4327 }
4328 data += ref_size;
4329 /* Byte offset operand. */
4330 get_sleb128 (sleb, data); /* XXX check overrun */
4331
4332 printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX ", %+" PRId64 "\n",
4333 indent, "", (intmax_t) offset,
4334 known[op], (uintmax_t) addr, sleb);
4335 CONSUME (data - start);
4336 offset += 1 + (data - start);
4337 break;
4338
Mark Wielaarde3368c52011-03-22 23:03:31 +01004339 case DW_OP_GNU_entry_value:
4340 /* Size plus expression block. */
4341 start = data;
4342 NEED (1);
4343 get_uleb128 (uleb, data); /* XXX check overrun */
4344 printf ("%*s[%4" PRIuMAX "] %s:\n",
4345 indent, "", (uintmax_t) offset, known[op]);
4346 NEED (uleb);
4347 print_ops (dwflmod, dbg, indent + 6, indent + 6, vers,
4348 addrsize, offset_size, uleb, data);
4349 data += uleb;
4350 CONSUME (data - start);
4351 offset += 1 + (data - start);
4352 break;
4353
Jakub Jelinek03124242011-05-17 17:00:14 +02004354 case DW_OP_GNU_const_type:
4355 /* DIE offset, size plus block. */
4356 start = data;
4357 NEED (2);
4358 get_uleb128 (uleb, data); /* XXX check overrun */
4359 uint8_t usize = *(uint8_t *) data++;
4360 NEED (usize);
4361 printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] ",
4362 indent, "", (uintmax_t) offset, known[op], uleb);
4363 print_block (usize, data);
4364 data += usize;
4365 CONSUME (data - start);
4366 offset += 1 + (data - start);
4367 break;
4368
4369 case DW_OP_GNU_regval_type:
4370 start = data;
4371 NEED (2);
4372 get_uleb128 (uleb, data); /* XXX check overrun */
4373 get_uleb128 (uleb2, data); /* XXX check overrun */
4374 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %#" PRIx64 "\n",
4375 indent, "", (uintmax_t) offset, known[op], uleb, uleb2);
4376 CONSUME (data - start);
4377 offset += 1 + (data - start);
4378 break;
4379
4380 case DW_OP_GNU_deref_type:
4381 start = data;
4382 NEED (2);
4383 usize = *(uint8_t *) data++;
4384 get_uleb128 (uleb, data); /* XXX check overrun */
4385 printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
4386 indent, "", (uintmax_t) offset,
4387 known[op], usize, uleb);
4388 CONSUME (data - start);
4389 offset += 1 + (data - start);
4390 break;
4391
4392 case DW_OP_GNU_convert:
4393 case DW_OP_GNU_reinterpret:
4394 start = data;
4395 NEED (1);
4396 get_uleb128 (uleb, data); /* XXX check overrun */
4397 printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
4398 indent, "", (uintmax_t) offset, known[op], uleb);
4399 CONSUME (data - start);
4400 offset += 1 + (data - start);
4401 break;
4402
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004403 default:
4404 /* No Operand. */
Roland McGrath1a2e8f42007-12-15 23:39:34 +00004405 if (op < sizeof known / sizeof known[0] && known[op] != NULL)
4406 printf ("%*s[%4" PRIuMAX "] %s\n",
4407 indent, "", (uintmax_t) offset, known[op]);
4408 else
4409 printf ("%*s[%4" PRIuMAX "] %#x\n",
4410 indent, "", (uintmax_t) offset, op);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004411 ++offset;
4412 break;
4413 }
4414
4415 indent = indentrest;
Roland McGrath51f01282009-01-27 17:08:03 -08004416 continue;
4417
4418 invalid:
4419 printf (gettext ("%*s[%4" PRIuMAX "] %s <TRUNCATED>\n"),
4420 indent, "", (uintmax_t) offset, known[op]);
4421 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004422 }
4423}
4424
4425
Roland McGrathfa144952010-08-30 19:22:41 -07004426struct listptr
4427{
4428 Dwarf_Off offset:(64 - 3);
4429 bool addr64:1;
4430 bool dwarf64:1;
4431 bool warned:1;
4432};
4433
4434#define listptr_offset_size(p) ((p)->dwarf64 ? 8 : 4)
4435#define listptr_address_size(p) ((p)->addr64 ? 8 : 4)
4436
4437static int
4438compare_listptr (const void *a, const void *b, void *arg)
4439{
4440 const char *name = arg;
4441 struct listptr *p1 = (void *) a;
4442 struct listptr *p2 = (void *) b;
4443
4444 if (p1->offset < p2->offset)
4445 return -1;
4446 if (p1->offset > p2->offset)
4447 return 1;
4448
4449 if (!p1->warned && !p2->warned)
4450 {
4451 if (p1->addr64 != p2->addr64)
4452 {
4453 p1->warned = p2->warned = true;
4454 error (0, 0,
4455 gettext ("%s %#" PRIx64 " used with different address sizes"),
4456 name, (uint64_t) p1->offset);
4457 }
4458 if (p1->dwarf64 != p2->dwarf64)
4459 {
4460 p1->warned = p2->warned = true;
4461 error (0, 0,
4462 gettext ("%s %#" PRIx64 " used with different offset sizes"),
4463 name, (uint64_t) p1->offset);
4464 }
4465 }
4466
4467 return 0;
4468}
4469
4470struct listptr_table
4471{
4472 size_t n;
4473 size_t alloc;
4474 struct listptr *table;
4475};
4476
4477static struct listptr_table known_loclistptr;
4478static struct listptr_table known_rangelistptr;
4479
4480static void
4481reset_listptr (struct listptr_table *table)
4482{
4483 free (table->table);
Jan Kratochvilfec39992011-02-27 12:01:25 -08004484 table->table = NULL;
Roland McGrathfa144952010-08-30 19:22:41 -07004485 table->n = table->alloc = 0;
4486}
4487
4488static void
4489notice_listptr (enum section_e section, struct listptr_table *table,
4490 uint_fast8_t address_size, uint_fast8_t offset_size,
4491 Dwarf_Off offset)
4492{
4493 if (print_debug_sections & section)
4494 {
4495 if (table->n == table->alloc)
4496 {
4497 if (table->alloc == 0)
4498 table->alloc = 128;
4499 else
4500 table->alloc *= 2;
4501 table->table = xrealloc (table->table,
4502 table->alloc * sizeof table->table[0]);
4503 }
4504
4505 struct listptr *p = &table->table[table->n++];
4506
4507 *p = (struct listptr)
4508 {
4509 .addr64 = address_size == 8,
4510 .dwarf64 = offset_size == 8,
4511 .offset = offset
4512 };
4513 assert (p->offset == offset);
4514 }
4515}
4516
4517static void
4518sort_listptr (struct listptr_table *table, const char *name)
4519{
4520 if (table->n > 0)
4521 qsort_r (table->table, table->n, sizeof table->table[0],
4522 &compare_listptr, (void *) name);
4523}
4524
4525static bool
4526skip_listptr_hole (struct listptr_table *table, size_t *idxp,
4527 uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
4528 ptrdiff_t offset, unsigned char **readp, unsigned char *endp)
4529{
4530 if (table->n == 0)
4531 return false;
4532
4533 while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
4534 ++*idxp;
4535
4536 struct listptr *p = &table->table[*idxp];
4537
4538 if (*idxp == table->n
4539 || p->offset >= (Dwarf_Off) (endp - *readp + offset))
4540 {
4541 *readp = endp;
4542 printf (gettext (" [%6tx] <UNUSED GARBAGE IN REST OF SECTION>\n"),
4543 offset);
4544 return true;
4545 }
4546
4547 if (p->offset != (Dwarf_Off) offset)
4548 {
4549 *readp += p->offset - offset;
4550 printf (gettext (" [%6tx] <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
4551 offset, (Dwarf_Off) p->offset - offset);
4552 return true;
4553 }
4554
4555 if (address_sizep != NULL)
4556 *address_sizep = listptr_address_size (p);
4557 if (offset_sizep != NULL)
4558 *offset_sizep = listptr_offset_size (p);
4559
4560 return false;
4561}
4562
4563
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004564static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004565print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Roland McGrath725aad52011-02-23 19:52:46 -08004566 Ebl *ebl, GElf_Ehdr *ehdr,
Ulrich Drepper351bf202009-01-15 20:18:40 -08004567 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004568{
Ulrich Drepper351bf202009-01-15 20:18:40 -08004569 printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004570 " [ Code]\n"),
Roland McGrath725aad52011-02-23 19:52:46 -08004571 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4572 (uint64_t) shdr->sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004573
4574 Dwarf_Off offset = 0;
Roland McGrath725aad52011-02-23 19:52:46 -08004575 while (offset < dbg->sectiondata[IDX_debug_abbrev]->d_size)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004576 {
4577 printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
4578 offset);
4579
4580 while (1)
4581 {
4582 size_t length;
4583 Dwarf_Abbrev abbrev;
4584
4585 int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
4586 if (res != 0)
4587 {
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00004588 if (unlikely (res < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004589 {
4590 printf (gettext ("\
4591 *** error while reading abbreviation: %s\n"),
4592 dwarf_errmsg (-1));
4593 return;
4594 }
4595
4596 /* This is the NUL byte at the end of the section. */
4597 ++offset;
4598 break;
4599 }
4600
4601 /* We know these calls can never fail. */
4602 unsigned int code = dwarf_getabbrevcode (&abbrev);
4603 unsigned int tag = dwarf_getabbrevtag (&abbrev);
4604 int has_children = dwarf_abbrevhaschildren (&abbrev);
4605
4606 printf (gettext (" [%5u] offset: %" PRId64
4607 ", children: %s, tag: %s\n"),
4608 code, (int64_t) offset,
4609 has_children ? gettext ("yes") : gettext ("no"),
4610 dwarf_tag_string (tag));
4611
4612 size_t cnt = 0;
4613 unsigned int name;
4614 unsigned int form;
4615 Dwarf_Off enoffset;
4616 while (dwarf_getabbrevattr (&abbrev, cnt,
4617 &name, &form, &enoffset) == 0)
4618 {
4619 printf (" attr: %s, form: %s, offset: %#" PRIx64 "\n",
4620 dwarf_attr_string (name), dwarf_form_string (form),
4621 (uint64_t) enoffset);
4622
4623 ++cnt;
4624 }
4625
4626 offset += length;
4627 }
4628 }
4629}
4630
4631
4632/* Print content of DWARF .debug_aranges section. We fortunately do
4633 not have to know a bit about the structure of the section, libdwarf
4634 takes care of it. */
4635static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004636print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Roland McGrath725aad52011-02-23 19:52:46 -08004637 Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004638 GElf_Shdr *shdr, Dwarf *dbg)
4639{
4640 Dwarf_Aranges *aranges;
4641 size_t cnt;
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00004642 if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004643 {
4644 error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
4645 dwarf_errmsg (-1));
4646 return;
4647 }
4648
4649 printf (ngettext ("\
Ulrich Drepper351bf202009-01-15 20:18:40 -08004650\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004651 "\
Ulrich Drepper351bf202009-01-15 20:18:40 -08004652\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004653 cnt),
Roland McGrath725aad52011-02-23 19:52:46 -08004654 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4655 (uint64_t) shdr->sh_offset, cnt);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004656
4657 /* Compute floor(log16(cnt)). */
4658 size_t tmp = cnt;
4659 int digits = 1;
4660 while (tmp >= 16)
4661 {
4662 ++digits;
4663 tmp >>= 4;
4664 }
4665
4666 for (size_t n = 0; n < cnt; ++n)
4667 {
4668 Dwarf_Arange *runp = dwarf_onearange (aranges, n);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00004669 if (unlikely (runp == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004670 {
4671 printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
4672 return;
4673 }
4674
4675 Dwarf_Addr start;
4676 Dwarf_Word length;
4677 Dwarf_Off offset;
4678
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00004679 if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004680 printf (gettext (" [%*zu] ???\n"), digits, n);
4681 else
4682 printf (gettext (" [%*zu] start: %0#*" PRIx64
4683 ", length: %5" PRIu64 ", CU DIE offset: %6"
4684 PRId64 "\n"),
4685 digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
4686 (uint64_t) start, (uint64_t) length, (int64_t) offset);
4687 }
4688}
4689
4690/* Print content of DWARF .debug_ranges section. */
4691static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004692print_debug_ranges_section (Dwfl_Module *dwflmod,
Roland McGrath725aad52011-02-23 19:52:46 -08004693 Ebl *ebl, GElf_Ehdr *ehdr,
4694 Elf_Scn *scn, GElf_Shdr *shdr,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004695 Dwarf *dbg)
4696{
4697 Elf_Data *data = elf_rawdata (scn, NULL);
4698
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00004699 if (unlikely (data == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004700 {
4701 error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
4702 elf_errmsg (-1));
4703 return;
4704 }
4705
4706 printf (gettext ("\
Ulrich Drepper351bf202009-01-15 20:18:40 -08004707\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
Roland McGrath725aad52011-02-23 19:52:46 -08004708 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
4709 (uint64_t) shdr->sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004710
Roland McGrathfa144952010-08-30 19:22:41 -07004711 sort_listptr (&known_rangelistptr, "rangelistptr");
4712 size_t listptr_idx = 0;
4713
4714 uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004715
4716 bool first = true;
Roland McGrathfa144952010-08-30 19:22:41 -07004717 unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004718 unsigned char *readp = data->d_buf;
Roland McGrathfa144952010-08-30 19:22:41 -07004719 while (readp < endp)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004720 {
4721 ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
4722
Roland McGrathfa144952010-08-30 19:22:41 -07004723 if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
4724 &address_size, NULL,
4725 offset, &readp, endp))
4726 continue;
4727
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00004728 if (unlikely (data->d_size - offset < address_size * 2))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004729 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004730 printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004731 break;
4732 }
4733
4734 Dwarf_Addr begin;
4735 Dwarf_Addr end;
4736 if (address_size == 8)
4737 {
4738 begin = read_8ubyte_unaligned_inc (dbg, readp);
4739 end = read_8ubyte_unaligned_inc (dbg, readp);
4740 }
4741 else
4742 {
4743 begin = read_4ubyte_unaligned_inc (dbg, readp);
4744 end = read_4ubyte_unaligned_inc (dbg, readp);
4745 if (begin == (Dwarf_Addr) (uint32_t) -1)
4746 begin = (Dwarf_Addr) -1l;
4747 }
4748
4749 if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004750 {
Roland McGrath671d6d82009-08-23 17:55:05 -07004751 char *b = format_dwarf_addr (dwflmod, address_size, end);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004752 printf (gettext (" [%6tx] base address %s\n"), offset, b);
4753 free (b);
4754 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004755 else if (begin == 0 && end == 0) /* End of list entry. */
Roland McGrathfa144952010-08-30 19:22:41 -07004756 {
4757 if (first)
4758 printf (gettext (" [%6tx] empty list\n"), offset);
4759 first = true;
4760 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004761 else
4762 {
Roland McGrath671d6d82009-08-23 17:55:05 -07004763 char *b = format_dwarf_addr (dwflmod, address_size, begin);
4764 char *e = format_dwarf_addr (dwflmod, address_size, end);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004765 /* We have an address range entry. */
4766 if (first) /* First address range entry in a list. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004767 printf (gettext (" [%6tx] %s..%s\n"), offset, b, e);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004768 else
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00004769 printf (gettext (" %s..%s\n"), b, e);
4770 free (b);
4771 free (e);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004772
4773 first = false;
4774 }
4775 }
4776}
4777
Roland McGrathdffc33d2009-07-06 16:06:41 -07004778#define REGNAMESZ 16
4779static const char *
4780register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
4781 char name[REGNAMESZ], int *bits, int *type)
4782{
4783 const char *set;
4784 const char *pfx;
4785 int ignore;
4786 ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
4787 bits ?: &ignore, type ?: &ignore);
4788 if (n <= 0)
4789 {
Marek Polacek8d1e2972011-10-04 05:11:42 -04004790 snprintf (name, REGNAMESZ, "reg%u", loc->regno);
Roland McGrathdffc33d2009-07-06 16:06:41 -07004791 if (bits != NULL)
4792 *bits = loc->bits;
4793 if (type != NULL)
4794 *type = DW_ATE_unsigned;
Roland McGrath46d58272009-07-06 17:57:33 -07004795 set = "??? unrecognized";
4796 }
4797 else
4798 {
4799 if (bits != NULL && *bits <= 0)
4800 *bits = loc->bits;
4801 if (type != NULL && *type == DW_ATE_void)
4802 *type = DW_ATE_unsigned;
4803
Roland McGrathdffc33d2009-07-06 16:06:41 -07004804 }
4805 return set;
4806}
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004807
4808static void
Ulrich Drepperac194d02009-01-06 00:30:01 -08004809print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
4810 Dwarf_Word vma_base, unsigned int code_align,
Roland McGrath52604ba2010-07-26 21:29:44 -07004811 int data_align,
4812 unsigned int version, unsigned int ptr_size,
4813 Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004814{
Roland McGrathdffc33d2009-07-06 16:06:41 -07004815 char regnamebuf[REGNAMESZ];
Ulrich Drepperac194d02009-01-06 00:30:01 -08004816 const char *regname (unsigned int regno)
4817 {
Roland McGrathdffc33d2009-07-06 16:06:41 -07004818 register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
4819 return regnamebuf;
Ulrich Drepperac194d02009-01-06 00:30:01 -08004820 }
4821
4822 puts ("\n Program:");
4823 Dwarf_Word pc = vma_base;
4824 while (readp < endp)
4825 {
4826 unsigned int opcode = *readp++;
4827
4828 if (opcode < DW_CFA_advance_loc)
4829 /* Extended opcode. */
4830 switch (opcode)
4831 {
4832 uint64_t op1;
4833 int64_t sop1;
4834 uint64_t op2;
4835 int64_t sop2;
4836
4837 case DW_CFA_nop:
4838 puts (" nop");
4839 break;
4840 case DW_CFA_set_loc:
4841 // XXX overflow check
4842 get_uleb128 (op1, readp);
4843 op1 += vma_base;
4844 printf (" set_loc %" PRIu64 "\n", op1 * code_align);
4845 break;
4846 case DW_CFA_advance_loc1:
4847 printf (" advance_loc1 %u to %#" PRIx64 "\n",
4848 *readp, pc += *readp * code_align);
4849 ++readp;
4850 break;
4851 case DW_CFA_advance_loc2:
4852 op1 = read_2ubyte_unaligned_inc (dbg, readp);
4853 printf (" advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
4854 op1, pc += op1 * code_align);
4855 break;
4856 case DW_CFA_advance_loc4:
4857 op1 = read_4ubyte_unaligned_inc (dbg, readp);
4858 printf (" advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
4859 op1, pc += op1 * code_align);
4860 break;
4861 case DW_CFA_offset_extended:
4862 // XXX overflow check
4863 get_uleb128 (op1, readp);
4864 get_uleb128 (op2, readp);
4865 printf (" offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
4866 "\n",
4867 op1, regname (op1), op2 * data_align);
4868 break;
4869 case DW_CFA_restore_extended:
4870 // XXX overflow check
4871 get_uleb128 (op1, readp);
4872 printf (" restore_extended r%" PRIu64 " (%s)\n",
4873 op1, regname (op1));
4874 break;
4875 case DW_CFA_undefined:
4876 // XXX overflow check
4877 get_uleb128 (op1, readp);
4878 printf (" undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
4879 break;
4880 case DW_CFA_same_value:
4881 // XXX overflow check
4882 get_uleb128 (op1, readp);
4883 printf (" same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
4884 break;
4885 case DW_CFA_register:
4886 // XXX overflow check
4887 get_uleb128 (op1, readp);
4888 get_uleb128 (op2, readp);
Ulrich Drepper8cbc8e62009-02-05 22:13:05 -08004889 printf (" register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
Ulrich Drepperac194d02009-01-06 00:30:01 -08004890 op1, regname (op1), op2, regname (op2));
4891 break;
4892 case DW_CFA_remember_state:
4893 puts (" remember_state");
4894 break;
4895 case DW_CFA_restore_state:
4896 puts (" restore_state");
4897 break;
4898 case DW_CFA_def_cfa:
4899 // XXX overflow check
4900 get_uleb128 (op1, readp);
4901 get_uleb128 (op2, readp);
4902 printf (" def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
4903 op1, regname (op1), op2);
4904 break;
4905 case DW_CFA_def_cfa_register:
4906 // XXX overflow check
4907 get_uleb128 (op1, readp);
4908 printf (" def_cfa_register r%" PRIu64 " (%s)\n",
4909 op1, regname (op1));
4910 break;
4911 case DW_CFA_def_cfa_offset:
4912 // XXX overflow check
4913 get_uleb128 (op1, readp);
4914 printf (" def_cfa_offset %" PRIu64 "\n", op1);
4915 break;
4916 case DW_CFA_def_cfa_expression:
4917 // XXX overflow check
4918 get_uleb128 (op1, readp); /* Length of DW_FORM_block. */
Ulrich Drepper411cdb22009-02-05 22:04:26 -08004919 printf (" def_cfa_expression %" PRIu64 "\n", op1);
Roland McGrath52604ba2010-07-26 21:29:44 -07004920 print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op1, readp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004921 readp += op1;
Ulrich Drepperac194d02009-01-06 00:30:01 -08004922 break;
4923 case DW_CFA_expression:
4924 // XXX overflow check
4925 get_uleb128 (op1, readp);
4926 get_uleb128 (op2, readp); /* Length of DW_FORM_block. */
Ulrich Drepperb3490b52009-02-05 22:34:30 -08004927 printf (" expression r%" PRIu64 " (%s) \n",
4928 op1, regname (op1));
Roland McGrath52604ba2010-07-26 21:29:44 -07004929 print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op2, readp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004930 readp += op2;
4931 break;
4932 case DW_CFA_offset_extended_sf:
4933 // XXX overflow check
4934 get_uleb128 (op1, readp);
4935 get_sleb128 (sop2, readp);
4936 printf (" offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
4937 PRId64 "\n",
4938 op1, regname (op1), sop2 * data_align);
4939 break;
4940 case DW_CFA_def_cfa_sf:
4941 // XXX overflow check
4942 get_uleb128 (op1, readp);
4943 get_sleb128 (sop2, readp);
4944 printf (" def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
4945 op1, regname (op1), sop2 * data_align);
4946 break;
4947 case DW_CFA_def_cfa_offset_sf:
4948 // XXX overflow check
4949 get_sleb128 (sop1, readp);
4950 printf (" def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
4951 break;
4952 case DW_CFA_val_offset:
4953 // XXX overflow check
4954 get_uleb128 (op1, readp);
4955 get_uleb128 (op2, readp);
4956 printf (" val_offset %" PRIu64 " at offset %" PRIu64 "\n",
4957 op1, op2 * data_align);
4958 break;
4959 case DW_CFA_val_offset_sf:
4960 // XXX overflow check
4961 get_uleb128 (op1, readp);
4962 get_sleb128 (sop2, readp);
Ulrich Drepper8cbc8e62009-02-05 22:13:05 -08004963 printf (" val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
Ulrich Drepperac194d02009-01-06 00:30:01 -08004964 op1, sop2 * data_align);
4965 break;
4966 case DW_CFA_val_expression:
4967 // XXX overflow check
4968 get_uleb128 (op1, readp);
4969 get_uleb128 (op2, readp); /* Length of DW_FORM_block. */
Ulrich Drepper973a9c72009-02-05 22:56:39 -08004970 printf (" val_expression r%" PRIu64 " (%s)\n",
4971 op1, regname (op1));
Roland McGrath52604ba2010-07-26 21:29:44 -07004972 print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op2, readp);
Ulrich Drepperac194d02009-01-06 00:30:01 -08004973 readp += op2;
4974 break;
4975 case DW_CFA_MIPS_advance_loc8:
4976 op1 = read_8ubyte_unaligned_inc (dbg, readp);
Ulrich Drepper8cbc8e62009-02-05 22:13:05 -08004977 printf (" MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
Ulrich Drepperac194d02009-01-06 00:30:01 -08004978 op1, pc += op1 * code_align);
4979 break;
4980 case DW_CFA_GNU_window_save:
Ulrich Drepper8cbc8e62009-02-05 22:13:05 -08004981 puts (" GNU_window_save");
Ulrich Drepperac194d02009-01-06 00:30:01 -08004982 break;
4983 case DW_CFA_GNU_args_size:
4984 // XXX overflow check
4985 get_uleb128 (op1, readp);
4986 printf (" args_size %" PRIu64 "\n", op1);
4987 break;
4988 default:
4989 printf (" ??? (%u)\n", opcode);
4990 break;
4991 }
4992 else if (opcode < DW_CFA_offset)
4993 printf (" advance_loc %u to %#" PRIx64 "\n",
4994 opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
4995 else if (opcode < DW_CFA_restore)
4996 {
Roland McGrath0c5638c2010-06-21 23:00:35 -07004997 uint64_t offset;
Ulrich Drepperac194d02009-01-06 00:30:01 -08004998 // XXX overflow check
4999 get_uleb128 (offset, readp);
Roland McGrath0c5638c2010-06-21 23:00:35 -07005000 printf (" offset r%u (%s) at cfa%+" PRId64 "\n",
Ulrich Drepperac194d02009-01-06 00:30:01 -08005001 opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
5002 }
5003 else
5004 printf (" restore r%u (%s)\n",
5005 opcode & 0x3f, regname (opcode & 0x3f));
5006 }
5007}
5008
5009
5010static unsigned int
5011encoded_ptr_size (int encoding, unsigned int ptr_size)
5012{
5013 switch (encoding & 7)
5014 {
5015 case 2:
5016 return 2;
5017 case 3:
5018 return 4;
5019 case 4:
5020 return 8;
5021 default:
5022 return ptr_size;
5023 }
5024}
5025
5026
Ulrich Drepper351bf202009-01-15 20:18:40 -08005027static unsigned int
5028print_encoding (unsigned int val)
5029{
5030 switch (val & 0xf)
5031 {
5032 case DW_EH_PE_absptr:
5033 fputs ("absptr", stdout);
5034 break;
5035 case DW_EH_PE_uleb128:
5036 fputs ("uleb128", stdout);
5037 break;
5038 case DW_EH_PE_udata2:
5039 fputs ("udata2", stdout);
5040 break;
5041 case DW_EH_PE_udata4:
5042 fputs ("udata4", stdout);
5043 break;
5044 case DW_EH_PE_udata8:
5045 fputs ("udata8", stdout);
5046 break;
5047 case DW_EH_PE_sleb128:
5048 fputs ("sleb128", stdout);
5049 break;
5050 case DW_EH_PE_sdata2:
5051 fputs ("sdata2", stdout);
5052 break;
5053 case DW_EH_PE_sdata4:
5054 fputs ("sdata4", stdout);
5055 break;
5056 case DW_EH_PE_sdata8:
5057 fputs ("sdata8", stdout);
5058 break;
5059 default:
5060 /* We did not use any of the bits after all. */
5061 return val;
5062 }
5063
5064 return val & ~0xf;
5065}
5066
5067
5068static unsigned int
5069print_relinfo (unsigned int val)
5070{
5071 switch (val & 0x70)
5072 {
5073 case DW_EH_PE_pcrel:
5074 fputs ("pcrel", stdout);
5075 break;
5076 case DW_EH_PE_textrel:
5077 fputs ("textrel", stdout);
5078 break;
5079 case DW_EH_PE_datarel:
5080 fputs ("datarel", stdout);
5081 break;
5082 case DW_EH_PE_funcrel:
5083 fputs ("funcrel", stdout);
5084 break;
5085 case DW_EH_PE_aligned:
5086 fputs ("aligned", stdout);
5087 break;
5088 default:
5089 return val;
5090 }
5091
5092 return val & ~0x70;
5093}
5094
5095
5096static void
Ulrich Drepperbc298972009-01-16 11:50:10 -08005097print_encoding_base (const char *pfx, unsigned int fde_encoding)
Ulrich Drepper351bf202009-01-15 20:18:40 -08005098{
Ulrich Drepperbc298972009-01-16 11:50:10 -08005099 printf ("(%s", pfx);
Ulrich Drepper351bf202009-01-15 20:18:40 -08005100
Ulrich Drepper05d2b202009-01-16 17:58:54 -08005101 if (fde_encoding == DW_EH_PE_omit)
5102 puts ("omit)");
5103 else
Ulrich Drepper351bf202009-01-15 20:18:40 -08005104 {
Ulrich Drepper05d2b202009-01-16 17:58:54 -08005105 unsigned int w = fde_encoding;
Ulrich Drepper351bf202009-01-15 20:18:40 -08005106
Roland McGrathf920fd52010-02-02 15:50:15 -08005107 w = print_encoding (w);
Ulrich Drepper05d2b202009-01-16 17:58:54 -08005108
5109 if (w & 0x70)
5110 {
5111 if (w != fde_encoding)
5112 fputc_unlocked (' ', stdout);
5113
5114 w = print_relinfo (w);
5115 }
5116
5117 if (w != 0)
5118 printf ("%s%x", w != fde_encoding ? " " : "", w);
5119
5120 puts (")");
Ulrich Drepper351bf202009-01-15 20:18:40 -08005121 }
Ulrich Drepper351bf202009-01-15 20:18:40 -08005122}
5123
5124
Ulrich Drepperbc298972009-01-16 11:50:10 -08005125static const unsigned char *
5126read_encoded (unsigned int encoding, const unsigned char *readp,
5127 const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
5128{
Roland McGrathf920fd52010-02-02 15:50:15 -08005129 if ((encoding & 0xf) == DW_EH_PE_absptr)
5130 encoding = gelf_getclass (dbg->elf) == ELFCLASS32
5131 ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
5132
Ulrich Drepperbc298972009-01-16 11:50:10 -08005133 switch (encoding & 0xf)
5134 {
5135 case DW_EH_PE_uleb128:
5136 // XXX buffer overrun check
5137 get_uleb128 (*res, readp);
5138 break;
5139 case DW_EH_PE_sleb128:
5140 // XXX buffer overrun check
5141 get_sleb128 (*res, readp);
5142 break;
5143 case DW_EH_PE_udata2:
5144 if (readp + 2 > endp)
5145 goto invalid;
5146 *res = read_2ubyte_unaligned_inc (dbg, readp);
5147 break;
5148 case DW_EH_PE_udata4:
5149 if (readp + 4 > endp)
5150 goto invalid;
5151 *res = read_4ubyte_unaligned_inc (dbg, readp);
5152 break;
5153 case DW_EH_PE_udata8:
5154 if (readp + 8 > endp)
5155 goto invalid;
5156 *res = read_8ubyte_unaligned_inc (dbg, readp);
5157 break;
5158 case DW_EH_PE_sdata2:
5159 if (readp + 2 > endp)
5160 goto invalid;
5161 *res = read_2sbyte_unaligned_inc (dbg, readp);
5162 break;
5163 case DW_EH_PE_sdata4:
5164 if (readp + 4 > endp)
5165 goto invalid;
5166 *res = read_4sbyte_unaligned_inc (dbg, readp);
5167 break;
5168 case DW_EH_PE_sdata8:
5169 if (readp + 8 > endp)
5170 goto invalid;
5171 *res = read_8sbyte_unaligned_inc (dbg, readp);
5172 break;
5173 default:
5174 invalid:
5175 error (1, 0,
5176 gettext ("invalid encoding"));
5177 }
5178
5179 return readp;
5180}
5181
5182
Ulrich Drepperac194d02009-01-06 00:30:01 -08005183static void
5184print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
5185 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5186{
5187 size_t shstrndx;
5188 /* We know this call will succeed since it did in the caller. */
Ulrich Drepperf1894932009-06-13 15:55:42 -07005189 (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005190 const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
5191
5192 Elf_Data *data = elf_rawdata (scn, NULL);
5193
5194 if (unlikely (data == NULL))
5195 {
5196 error (0, 0, gettext ("cannot get %s content: %s"),
5197 scnname, elf_errmsg (-1));
5198 return;
5199 }
Ulrich Drepper351bf202009-01-15 20:18:40 -08005200 bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005201
Ulrich Drepper351bf202009-01-15 20:18:40 -08005202 if (is_eh_frame)
5203 printf (gettext ("\
5204\nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5205 elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
5206 else
5207 printf (gettext ("\
5208\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5209 elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005210
5211 struct cieinfo
5212 {
5213 ptrdiff_t cie_offset;
5214 const char *augmentation;
5215 unsigned int code_alignment_factor;
5216 unsigned int data_alignment_factor;
Roland McGrath599f7f52010-06-20 17:12:43 -07005217 uint8_t address_size;
5218 uint8_t fde_encoding;
5219 uint8_t lsda_encoding;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005220 struct cieinfo *next;
5221 } *cies = NULL;
5222
5223 const unsigned char *readp = data->d_buf;
5224 const unsigned char *const dataend = ((unsigned char *) data->d_buf
5225 + data->d_size);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005226 while (readp < dataend)
5227 {
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005228 if (unlikely (readp + 4 > dataend))
Ulrich Drepperac194d02009-01-06 00:30:01 -08005229 {
5230 invalid_data:
5231 error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
5232 elf_ndxscn (scn), scnname);
5233 return;
5234 }
5235
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005236 /* At the beginning there must be a CIE. There can be multiple,
5237 hence we test tis in a loop. */
5238 ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005239
5240 Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
5241 unsigned int length = 4;
5242 if (unlikely (unit_length == 0xffffffff))
5243 {
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005244 if (unlikely (readp + 8 > dataend))
5245 goto invalid_data;
5246
Ulrich Drepperac194d02009-01-06 00:30:01 -08005247 unit_length = read_8ubyte_unaligned_inc (dbg, readp);
5248 length = 8;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005249 }
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005250
5251 if (unlikely (unit_length == 0))
5252 {
Roland McGrathe9de9b42009-01-22 13:05:40 -08005253 printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005254 continue;
5255 }
5256
5257 unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5258
Ulrich Drepperac194d02009-01-06 00:30:01 -08005259 ptrdiff_t start = readp - (unsigned char *) data->d_buf;
5260 const unsigned char *const cieend = readp + unit_length;
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005261 if (unlikely (cieend > dataend || readp + 8 > dataend))
Ulrich Drepperac194d02009-01-06 00:30:01 -08005262 goto invalid_data;
5263
Roland McGrath2fb90512009-04-15 14:47:13 -07005264 Dwarf_Off cie_id;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005265 if (length == 4)
Roland McGrath2fb90512009-04-15 14:47:13 -07005266 {
5267 cie_id = read_4ubyte_unaligned_inc (dbg, readp);
5268 if (!is_eh_frame && cie_id == DW_CIE_ID_32)
5269 cie_id = DW_CIE_ID_64;
5270 }
Ulrich Drepperac194d02009-01-06 00:30:01 -08005271 else
5272 cie_id = read_8ubyte_unaligned_inc (dbg, readp);
5273
Roland McGrath52604ba2010-07-26 21:29:44 -07005274 uint_fast8_t version = 2;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005275 unsigned int code_alignment_factor;
5276 int data_alignment_factor;
5277 unsigned int fde_encoding = 0;
Ulrich Drepperbc298972009-01-16 11:50:10 -08005278 unsigned int lsda_encoding = 0;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005279 Dwarf_Word initial_location = 0;
Ulrich Drepper62c46532009-01-24 17:01:08 -08005280 Dwarf_Word vma_base = 0;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005281
Roland McGrath2fb90512009-04-15 14:47:13 -07005282 if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
Ulrich Drepperac194d02009-01-06 00:30:01 -08005283 {
Roland McGrath52604ba2010-07-26 21:29:44 -07005284 version = *readp++;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005285 const char *const augmentation = (const char *) readp;
5286 readp = memchr (readp, '\0', cieend - readp);
5287 if (unlikely (readp == NULL))
5288 goto invalid_data;
5289 ++readp;
Roland McGrath599f7f52010-06-20 17:12:43 -07005290
5291 uint_fast8_t segment_size = 0;
5292 if (version >= 4)
5293 {
5294 if (cieend - readp < 5)
5295 goto invalid_data;
5296 ptr_size = *readp++;
5297 segment_size = *readp++;
5298 }
5299
Ulrich Drepperac194d02009-01-06 00:30:01 -08005300 // XXX Check overflow
5301 get_uleb128 (code_alignment_factor, readp);
5302 // XXX Check overflow
5303 get_sleb128 (data_alignment_factor, readp);
5304
5305 /* In some variant for unwind data there is another field. */
5306 if (strcmp (augmentation, "eh") == 0)
5307 readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5308
5309 unsigned int return_address_register;
5310 if (unlikely (version == 1))
5311 return_address_register = *readp++;
5312 else
5313 // XXX Check overflow
5314 get_uleb128 (return_address_register, readp);
5315
Roland McGrathe9de9b42009-01-22 13:05:40 -08005316 printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
Ulrich Drepperac194d02009-01-06 00:30:01 -08005317 " CIE_id: %" PRIu64 "\n"
5318 " version: %u\n"
Roland McGrath599f7f52010-06-20 17:12:43 -07005319 " augmentation: \"%s\"\n",
5320 offset, (uint64_t) unit_length, (uint64_t) cie_id,
5321 version, augmentation);
5322 if (version >= 4)
5323 printf (" address_size: %u\n"
5324 " segment_size: %u\n",
5325 ptr_size, segment_size);
5326 printf (" code_alignment_factor: %u\n"
Ulrich Drepperac194d02009-01-06 00:30:01 -08005327 " data_alignment_factor: %d\n"
5328 " return_address_register: %u\n",
Roland McGrath599f7f52010-06-20 17:12:43 -07005329 code_alignment_factor,
Ulrich Drepperac194d02009-01-06 00:30:01 -08005330 data_alignment_factor, return_address_register);
5331
5332 if (augmentation[0] == 'z')
5333 {
Ulrich Drepperac194d02009-01-06 00:30:01 -08005334 unsigned int augmentationlen;
5335 get_uleb128 (augmentationlen, readp);
5336
Roland McGrathc2b26f12010-02-15 15:16:15 -08005337 if (augmentationlen > (size_t) (dataend - readp))
Roland McGrathf920fd52010-02-02 15:50:15 -08005338 error (1, 0, gettext ("invalid augmentation length"));
5339
Ulrich Drepperac194d02009-01-06 00:30:01 -08005340 const char *hdr = "Augmentation data:";
5341 const char *cp = augmentation + 1;
5342 while (*cp != '\0')
5343 {
5344 printf (" %-26s%#x ", hdr, *readp);
5345 hdr = "";
5346
5347 if (*cp == 'R')
5348 {
Ulrich Drepperbc298972009-01-16 11:50:10 -08005349 fde_encoding = *readp++;
5350 print_encoding_base (gettext ("FDE address encoding: "),
5351 fde_encoding);
5352 }
5353 else if (*cp == 'L')
5354 {
5355 lsda_encoding = *readp++;
5356 print_encoding_base (gettext ("LSDA pointer encoding: "),
5357 lsda_encoding);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005358 }
5359 else if (*cp == 'P')
5360 {
Ulrich Drepper351bf202009-01-15 20:18:40 -08005361 /* Personality. This field usually has a relocation
5362 attached pointing to __gcc_personality_v0. */
Ulrich Drepperac194d02009-01-06 00:30:01 -08005363 const unsigned char *startp = readp;
5364 unsigned int encoding = *readp++;
5365 uint64_t val = 0;
Roland McGrathf920fd52010-02-02 15:50:15 -08005366 readp = read_encoded (encoding, readp,
5367 readp - 1 + augmentationlen,
5368 &val, dbg);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005369
5370 while (++startp < readp)
5371 printf ("%#x ", *startp);
5372
Roland McGrathf920fd52010-02-02 15:50:15 -08005373 putchar ('(');
5374 print_encoding (encoding);
5375 putchar (' ');
5376 switch (encoding & 0xf)
5377 {
5378 case DW_EH_PE_sleb128:
5379 case DW_EH_PE_sdata2:
5380 case DW_EH_PE_sdata4:
5381 printf ("%" PRId64 ")\n", val);
5382 break;
5383 default:
5384 printf ("%#" PRIx64 ")\n", val);
5385 break;
5386 }
Ulrich Drepperac194d02009-01-06 00:30:01 -08005387 }
5388 else
5389 printf ("(%x)\n", *readp++);
5390
5391 ++cp;
5392 }
Ulrich Drepperac194d02009-01-06 00:30:01 -08005393 }
5394
Roland McGrath599f7f52010-06-20 17:12:43 -07005395 if (likely (ptr_size == 4 || ptr_size == 8))
5396 {
5397 struct cieinfo *newp = alloca (sizeof (*newp));
5398 newp->cie_offset = offset;
5399 newp->augmentation = augmentation;
5400 newp->fde_encoding = fde_encoding;
5401 newp->lsda_encoding = lsda_encoding;
5402 newp->address_size = ptr_size;
5403 newp->code_alignment_factor = code_alignment_factor;
5404 newp->data_alignment_factor = data_alignment_factor;
5405 newp->next = cies;
5406 cies = newp;
5407 }
Ulrich Drepperac194d02009-01-06 00:30:01 -08005408 }
5409 else
5410 {
5411 struct cieinfo *cie = cies;
5412 while (cie != NULL)
Ulrich Drepper351bf202009-01-15 20:18:40 -08005413 if (is_eh_frame
5414 ? start - (ptrdiff_t) cie_id == cie->cie_offset
5415 : (ptrdiff_t) cie_id == cie->cie_offset)
Ulrich Drepperac194d02009-01-06 00:30:01 -08005416 break;
5417 else
5418 cie = cie->next;
5419 if (unlikely (cie == NULL))
5420 {
5421 puts ("invalid CIE reference in FDE");
5422 return;
5423 }
5424
5425 /* Initialize from CIE data. */
Ulrich Drepper351bf202009-01-15 20:18:40 -08005426 fde_encoding = cie->fde_encoding;
Ulrich Drepperbc298972009-01-16 11:50:10 -08005427 lsda_encoding = cie->lsda_encoding;
Roland McGrath599f7f52010-06-20 17:12:43 -07005428 ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005429 code_alignment_factor = cie->code_alignment_factor;
5430 data_alignment_factor = cie->data_alignment_factor;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005431
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005432 const unsigned char *base = readp;
Ulrich Drepper351bf202009-01-15 20:18:40 -08005433 // XXX There are sometimes relocations for this value
Ulrich Drepperac194d02009-01-06 00:30:01 -08005434 initial_location = read_ubyte_unaligned_inc (ptr_size, dbg, readp);
5435 Dwarf_Word address_range
5436 = read_ubyte_unaligned_inc (ptr_size, dbg, readp);
5437
Roland McGrath2f14a312010-07-02 11:16:25 -07005438 char *a = format_dwarf_addr (dwflmod, cie->address_size,
5439 initial_location);
Roland McGrathe9de9b42009-01-22 13:05:40 -08005440 printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
Ulrich Drepperac194d02009-01-06 00:30:01 -08005441 " CIE_pointer: %" PRIu64 "\n"
Roland McGrath2f14a312010-07-02 11:16:25 -07005442 " initial_location: %s",
Ulrich Drepperac194d02009-01-06 00:30:01 -08005443 offset, (uint64_t) unit_length,
Roland McGrath2f14a312010-07-02 11:16:25 -07005444 cie->cie_offset, (uint64_t) cie_id, a);
5445 free (a);
Ulrich Drepper351bf202009-01-15 20:18:40 -08005446 if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
Ulrich Drepper62c46532009-01-24 17:01:08 -08005447 {
5448 vma_base = (((uint64_t) shdr->sh_offset
5449 + (base - (const unsigned char *) data->d_buf)
5450 + (uint64_t) initial_location)
5451 & (ptr_size == 4
5452 ? UINT64_C (0xffffffff)
5453 : UINT64_C (0xffffffffffffffff)));
5454 printf (gettext (" (offset: %#" PRIx64 ")"),
5455 (uint64_t) vma_base);
5456 }
5457
5458 printf ("\n address_range: %#" PRIx64,
5459 (uint64_t) address_range);
5460 if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
5461 printf (gettext (" (end offset: %#" PRIx64 ")"),
5462 ((uint64_t) vma_base + (uint64_t) address_range)
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08005463 & (ptr_size == 4
5464 ? UINT64_C (0xffffffff)
5465 : UINT64_C (0xffffffffffffffff)));
Ulrich Drepper62c46532009-01-24 17:01:08 -08005466 putchar ('\n');
Ulrich Drepperac194d02009-01-06 00:30:01 -08005467
5468 if (cie->augmentation[0] == 'z')
5469 {
5470 unsigned int augmentationlen;
5471 get_uleb128 (augmentationlen, readp);
5472
Ulrich Drepper351bf202009-01-15 20:18:40 -08005473 if (augmentationlen > 0)
Ulrich Drepperac194d02009-01-06 00:30:01 -08005474 {
Ulrich Drepper351bf202009-01-15 20:18:40 -08005475 const char *hdr = "Augmentation data:";
5476 const char *cp = cie->augmentation + 1;
Ulrich Drepperbc298972009-01-16 11:50:10 -08005477 unsigned int u = 0;
5478 while (*cp != '\0')
Ulrich Drepper351bf202009-01-15 20:18:40 -08005479 {
Ulrich Drepperbc298972009-01-16 11:50:10 -08005480 if (*cp == 'L')
5481 {
5482 uint64_t lsda_pointer;
5483 const unsigned char *p
5484 = read_encoded (lsda_encoding, &readp[u],
5485 &readp[augmentationlen],
5486 &lsda_pointer, dbg);
5487 u = p - readp;
5488 printf (gettext ("\
5489 %-26sLSDA pointer: %#" PRIx64 "\n"),
5490 hdr, lsda_pointer);
5491 hdr = "";
5492 }
5493 ++cp;
5494 }
5495
5496 while (u < augmentationlen)
5497 {
5498 printf (" %-26s%#x\n", hdr, readp[u++]);
Ulrich Drepper351bf202009-01-15 20:18:40 -08005499 hdr = "";
5500 }
Ulrich Drepperac194d02009-01-06 00:30:01 -08005501 }
Ulrich Drepperbc298972009-01-16 11:50:10 -08005502
5503 readp += augmentationlen;
Ulrich Drepperac194d02009-01-06 00:30:01 -08005504 }
5505 }
5506
Ulrich Drepperac194d02009-01-06 00:30:01 -08005507 /* Handle the initialization instructions. */
5508 print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
Roland McGrath52604ba2010-07-26 21:29:44 -07005509 data_alignment_factor, version, ptr_size,
5510 dwflmod, ebl, dbg);
Ulrich Drepperac194d02009-01-06 00:30:01 -08005511 readp = cieend;
5512 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005513}
5514
5515
5516struct attrcb_args
5517{
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00005518 Dwfl_Module *dwflmod;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005519 Dwarf *dbg;
5520 int level;
Roland McGrathfa144952010-08-30 19:22:41 -07005521 bool silent;
Roland McGrath52604ba2010-07-26 21:29:44 -07005522 unsigned int version;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005523 unsigned int addrsize;
Roland McGrath688f7fc2010-05-08 03:22:59 -07005524 unsigned int offset_size;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005525 Dwarf_Off cu_offset;
5526};
5527
5528
5529static int
5530attr_callback (Dwarf_Attribute *attrp, void *arg)
5531{
5532 struct attrcb_args *cbargs = (struct attrcb_args *) arg;
5533 const int level = cbargs->level;
5534
5535 unsigned int attr = dwarf_whatattr (attrp);
5536 if (unlikely (attr == 0))
5537 {
Roland McGrathfa144952010-08-30 19:22:41 -07005538 if (!cbargs->silent)
5539 error (0, 0, gettext ("cannot get attribute code: %s"),
5540 dwarf_errmsg (-1));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005541 return DWARF_CB_ABORT;
5542 }
5543
5544 unsigned int form = dwarf_whatform (attrp);
5545 if (unlikely (form == 0))
5546 {
Roland McGrathfa144952010-08-30 19:22:41 -07005547 if (!cbargs->silent)
5548 error (0, 0, gettext ("cannot get attribute form: %s"),
5549 dwarf_errmsg (-1));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005550 return DWARF_CB_ABORT;
5551 }
5552
5553 switch (form)
5554 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00005555 case DW_FORM_addr:
Roland McGrathfa144952010-08-30 19:22:41 -07005556 if (!cbargs->silent)
5557 {
5558 Dwarf_Addr addr;
5559 if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
5560 {
5561 attrval_out:
5562 if (!cbargs->silent)
5563 error (0, 0, gettext ("cannot get attribute value: %s"),
5564 dwarf_errmsg (-1));
5565 return DWARF_CB_ABORT;
5566 }
5567 char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr);
5568 printf (" %*s%-20s (%s) %s\n",
5569 (int) (level * 2), "", dwarf_attr_string (attr),
5570 dwarf_form_string (form), a);
5571 free (a);
5572 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005573 break;
5574
5575 case DW_FORM_indirect:
5576 case DW_FORM_strp:
Roland McGrathfa144952010-08-30 19:22:41 -07005577 case DW_FORM_string:
5578 if (cbargs->silent)
5579 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005580 const char *str = dwarf_formstring (attrp);
5581 if (unlikely (str == NULL))
5582 goto attrval_out;
Ulrich Drepper173ade82010-05-28 07:39:49 -07005583 printf (" %*s%-20s (%s) \"%s\"\n",
5584 (int) (level * 2), "", dwarf_attr_string (attr),
5585 dwarf_form_string (form), str);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005586 break;
5587
5588 case DW_FORM_ref_addr:
5589 case DW_FORM_ref_udata:
5590 case DW_FORM_ref8:
5591 case DW_FORM_ref4:
5592 case DW_FORM_ref2:
5593 case DW_FORM_ref1:;
Roland McGrathfa144952010-08-30 19:22:41 -07005594 if (cbargs->silent)
5595 break;
Roland McGrathe4c22ea2007-10-23 13:07:39 +00005596 Dwarf_Die ref;
5597 if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005598 goto attrval_out;
5599
Ulrich Drepper173ade82010-05-28 07:39:49 -07005600 printf (" %*s%-20s (%s) [%6" PRIxMAX "]\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005601 (int) (level * 2), "", dwarf_attr_string (attr),
Ulrich Drepper173ade82010-05-28 07:39:49 -07005602 dwarf_form_string (form), (uintmax_t) dwarf_dieoffset (&ref));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005603 break;
5604
Roland McGrathc8a06732010-06-01 19:52:39 -07005605 case DW_FORM_ref_sig8:
Roland McGrathfa144952010-08-30 19:22:41 -07005606 if (cbargs->silent)
5607 break;
Roland McGrathc8a06732010-06-01 19:52:39 -07005608 printf (" %*s%-20s (%s) {%6" PRIx64 "}\n",
5609 (int) (level * 2), "", dwarf_attr_string (attr),
5610 dwarf_form_string (form),
5611 read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
5612 break;
5613
Roland McGrath7fac1ce2010-06-01 15:56:58 -07005614 case DW_FORM_sec_offset:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005615 case DW_FORM_udata:
5616 case DW_FORM_sdata:
5617 case DW_FORM_data8:
5618 case DW_FORM_data4:
5619 case DW_FORM_data2:
5620 case DW_FORM_data1:;
5621 Dwarf_Word num;
5622 if (unlikely (dwarf_formudata (attrp, &num) != 0))
5623 goto attrval_out;
5624
5625 const char *valuestr = NULL;
5626 switch (attr)
5627 {
Roland McGrathfa144952010-08-30 19:22:41 -07005628 /* This case can take either a constant or a loclistptr. */
Mark Wielaardf735db12009-07-08 19:18:53 +02005629 case DW_AT_data_member_location:
Roland McGrathfa144952010-08-30 19:22:41 -07005630 if (form != DW_FORM_sec_offset
5631 && (cbargs->version >= 4
5632 || (form != DW_FORM_data4 && form != DW_FORM_data8)))
Mark Wielaardf735db12009-07-08 19:18:53 +02005633 {
Roland McGrathfa144952010-08-30 19:22:41 -07005634 if (!cbargs->silent)
5635 printf (" %*s%-20s (%s) %" PRIxMAX "\n",
5636 (int) (level * 2), "", dwarf_attr_string (attr),
5637 dwarf_form_string (form), (uintmax_t) num);
Mark Wielaardf735db12009-07-08 19:18:53 +02005638 return DWARF_CB_OK;
5639 }
5640 /* else fallthrough */
5641
5642 /* These cases always take a loclistptr and no constant. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005643 case DW_AT_location:
Roland McGrath07a696e2007-11-09 22:44:26 +00005644 case DW_AT_data_location:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005645 case DW_AT_vtable_elem_location:
5646 case DW_AT_string_length:
5647 case DW_AT_use_location:
5648 case DW_AT_frame_base:
5649 case DW_AT_return_addr:
5650 case DW_AT_static_link:
Mark Wielaarde3368c52011-03-22 23:03:31 +01005651 case DW_AT_GNU_call_site_value:
5652 case DW_AT_GNU_call_site_data_value:
5653 case DW_AT_GNU_call_site_target:
5654 case DW_AT_GNU_call_site_target_clobbered:
Roland McGrathfa144952010-08-30 19:22:41 -07005655 notice_listptr (section_loc, &known_loclistptr,
5656 cbargs->addrsize, cbargs->offset_size, num);
5657 if (!cbargs->silent)
5658 printf (" %*s%-20s (%s) location list [%6" PRIxMAX "]\n",
5659 (int) (level * 2), "", dwarf_attr_string (attr),
5660 dwarf_form_string (form), (uintmax_t) num);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005661 return DWARF_CB_OK;
5662
5663 case DW_AT_ranges:
Roland McGrathfa144952010-08-30 19:22:41 -07005664 notice_listptr (section_ranges, &known_rangelistptr,
5665 cbargs->addrsize, cbargs->offset_size, num);
5666 if (!cbargs->silent)
5667 printf (" %*s%-20s (%s) range list [%6" PRIxMAX "]\n",
5668 (int) (level * 2), "", dwarf_attr_string (attr),
5669 dwarf_form_string (form), (uintmax_t) num);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005670 return DWARF_CB_OK;
5671
5672 case DW_AT_language:
5673 valuestr = dwarf_lang_string (num);
5674 break;
5675 case DW_AT_encoding:
5676 valuestr = dwarf_encoding_string (num);
5677 break;
5678 case DW_AT_accessibility:
5679 valuestr = dwarf_access_string (num);
5680 break;
5681 case DW_AT_visibility:
5682 valuestr = dwarf_visibility_string (num);
5683 break;
5684 case DW_AT_virtuality:
5685 valuestr = dwarf_virtuality_string (num);
5686 break;
5687 case DW_AT_identifier_case:
5688 valuestr = dwarf_identifier_case_string (num);
5689 break;
5690 case DW_AT_calling_convention:
5691 valuestr = dwarf_calling_convention_string (num);
5692 break;
5693 case DW_AT_inline:
5694 valuestr = dwarf_inline_string (num);
5695 break;
5696 case DW_AT_ordering:
5697 valuestr = dwarf_ordering_string (num);
5698 break;
5699 case DW_AT_discr_list:
5700 valuestr = dwarf_discr_list_string (num);
5701 break;
5702 default:
5703 /* Nothing. */
5704 break;
5705 }
5706
Roland McGrathfa144952010-08-30 19:22:41 -07005707 if (cbargs->silent)
5708 break;
5709
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005710 if (valuestr == NULL)
Ulrich Drepper173ade82010-05-28 07:39:49 -07005711 printf (" %*s%-20s (%s) %" PRIuMAX "\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005712 (int) (level * 2), "", dwarf_attr_string (attr),
Ulrich Drepper173ade82010-05-28 07:39:49 -07005713 dwarf_form_string (form), (uintmax_t) num);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005714 else
Ulrich Drepper173ade82010-05-28 07:39:49 -07005715 printf (" %*s%-20s (%s) %s (%" PRIuMAX ")\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005716 (int) (level * 2), "", dwarf_attr_string (attr),
Ulrich Drepper173ade82010-05-28 07:39:49 -07005717 dwarf_form_string (form), valuestr, (uintmax_t) num);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005718 break;
5719
Roland McGrathfa144952010-08-30 19:22:41 -07005720 case DW_FORM_flag:
5721 if (cbargs->silent)
5722 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005723 bool flag;
5724 if (unlikely (dwarf_formflag (attrp, &flag) != 0))
5725 goto attrval_out;
5726
Ulrich Drepper173ade82010-05-28 07:39:49 -07005727 printf (" %*s%-20s (%s) %s\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005728 (int) (level * 2), "", dwarf_attr_string (attr),
Ulrich Drepper173ade82010-05-28 07:39:49 -07005729 dwarf_form_string (form), nl_langinfo (flag ? YESSTR : NOSTR));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005730 break;
5731
Roland McGrath7fac1ce2010-06-01 15:56:58 -07005732 case DW_FORM_flag_present:
Roland McGrathfa144952010-08-30 19:22:41 -07005733 if (cbargs->silent)
5734 break;
Roland McGrath7fac1ce2010-06-01 15:56:58 -07005735 printf (" %*s%-20s (%s) %s\n",
5736 (int) (level * 2), "", dwarf_attr_string (attr),
5737 dwarf_form_string (form), nl_langinfo (YESSTR));
5738 break;
5739
5740 case DW_FORM_exprloc:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005741 case DW_FORM_block4:
5742 case DW_FORM_block2:
5743 case DW_FORM_block1:
Roland McGrathfa144952010-08-30 19:22:41 -07005744 case DW_FORM_block:
5745 if (cbargs->silent)
5746 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005747 Dwarf_Block block;
5748 if (unlikely (dwarf_formblock (attrp, &block) != 0))
5749 goto attrval_out;
5750
Ulrich Drepper173ade82010-05-28 07:39:49 -07005751 printf (" %*s%-20s (%s) ",
5752 (int) (level * 2), "", dwarf_attr_string (attr),
5753 dwarf_form_string (form));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005754
5755 switch (attr)
5756 {
Roland McGrath7fac1ce2010-06-01 15:56:58 -07005757 default:
5758 if (form != DW_FORM_exprloc)
5759 {
5760 print_block (block.length, block.data);
5761 break;
5762 }
5763 /* Fall through. */
5764
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005765 case DW_AT_location:
Roland McGrath07a696e2007-11-09 22:44:26 +00005766 case DW_AT_data_location:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005767 case DW_AT_data_member_location:
5768 case DW_AT_vtable_elem_location:
5769 case DW_AT_string_length:
5770 case DW_AT_use_location:
5771 case DW_AT_frame_base:
5772 case DW_AT_return_addr:
5773 case DW_AT_static_link:
Roland McGrath1a2e8f42007-12-15 23:39:34 +00005774 case DW_AT_allocated:
5775 case DW_AT_associated:
5776 case DW_AT_bit_size:
5777 case DW_AT_bit_offset:
5778 case DW_AT_bit_stride:
5779 case DW_AT_byte_size:
5780 case DW_AT_byte_stride:
5781 case DW_AT_count:
5782 case DW_AT_lower_bound:
5783 case DW_AT_upper_bound:
Mark Wielaarde3368c52011-03-22 23:03:31 +01005784 case DW_AT_GNU_call_site_value:
5785 case DW_AT_GNU_call_site_data_value:
5786 case DW_AT_GNU_call_site_target:
5787 case DW_AT_GNU_call_site_target_clobbered:
5788 putchar ('\n');
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00005789 print_ops (cbargs->dwflmod, cbargs->dbg,
5790 12 + level * 2, 12 + level * 2,
Roland McGrath52604ba2010-07-26 21:29:44 -07005791 cbargs->version, cbargs->addrsize, cbargs->offset_size,
Roland McGrath688f7fc2010-05-08 03:22:59 -07005792 block.length, block.data);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005793 break;
5794 }
5795 break;
5796
5797 default:
Roland McGrathfa144952010-08-30 19:22:41 -07005798 if (cbargs->silent)
5799 break;
Ulrich Drepper173ade82010-05-28 07:39:49 -07005800 printf (" %*s%-20s (form: %#x) ???\n",
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005801 (int) (level * 2), "", dwarf_attr_string (attr),
5802 (int) form);
5803 break;
5804 }
5805
5806 return DWARF_CB_OK;
5807}
5808
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005809static void
Roland McGrath2b1f0952010-06-20 17:55:50 -07005810print_debug_units (Dwfl_Module *dwflmod,
Roland McGrath725aad52011-02-23 19:52:46 -08005811 Ebl *ebl, GElf_Ehdr *ehdr,
5812 Elf_Scn *scn, GElf_Shdr *shdr,
5813 Dwarf *dbg, bool debug_types)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005814{
Roland McGrathfa144952010-08-30 19:22:41 -07005815 const bool silent = !(print_debug_sections & section_info);
Roland McGrath725aad52011-02-23 19:52:46 -08005816 const char *secname = section_name (ebl, ehdr, shdr);
Roland McGrath2b1f0952010-06-20 17:55:50 -07005817
Roland McGrathfa144952010-08-30 19:22:41 -07005818 if (!silent)
5819 printf (gettext ("\
Ulrich Drepper351bf202009-01-15 20:18:40 -08005820\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
Roland McGrathfa144952010-08-30 19:22:41 -07005821 elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005822
5823 /* If the section is empty we don't have to do anything. */
Roland McGrathfa144952010-08-30 19:22:41 -07005824 if (!silent && shdr->sh_size == 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005825 return;
5826
5827 int maxdies = 20;
5828 Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
5829
5830 Dwarf_Off offset = 0;
5831
5832 /* New compilation unit. */
5833 size_t cuhl;
Roland McGrath2b1f0952010-06-20 17:55:50 -07005834 Dwarf_Half version;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005835 Dwarf_Off abbroffset;
5836 uint8_t addrsize;
5837 uint8_t offsize;
5838 Dwarf_Off nextcu;
Roland McGrath2b1f0952010-06-20 17:55:50 -07005839 uint64_t typesig;
5840 Dwarf_Off typeoff;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005841 next_cu:
Roland McGrath2b1f0952010-06-20 17:55:50 -07005842 if (dwarf_next_unit (dbg, offset, &nextcu, &cuhl, &version,
5843 &abbroffset, &addrsize, &offsize,
5844 debug_types ? &typesig : NULL,
5845 debug_types ? &typeoff : NULL) != 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005846 goto do_return;
5847
Roland McGrathfa144952010-08-30 19:22:41 -07005848 if (!silent)
5849 {
5850 if (debug_types)
5851 printf (gettext (" Type unit at offset %" PRIu64 ":\n"
5852 " Version: %" PRIu16 ", Abbreviation section offset: %"
5853 PRIu64 ", Address size: %" PRIu8
5854 ", Offset size: %" PRIu8
5855 "\n Type signature: %#" PRIx64
5856 ", Type offset: %#" PRIx64 "\n"),
5857 (uint64_t) offset, version, abbroffset, addrsize, offsize,
5858 typesig, (uint64_t) typeoff);
5859 else
5860 printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
5861 " Version: %" PRIu16 ", Abbreviation section offset: %"
5862 PRIu64 ", Address size: %" PRIu8
5863 ", Offset size: %" PRIu8 "\n"),
5864 (uint64_t) offset, version, abbroffset, addrsize, offsize);
5865 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005866
Roland McGrath688f7fc2010-05-08 03:22:59 -07005867 struct attrcb_args args =
5868 {
5869 .dwflmod = dwflmod,
5870 .dbg = dbg,
Roland McGrathfa144952010-08-30 19:22:41 -07005871 .silent = silent,
Roland McGrath52604ba2010-07-26 21:29:44 -07005872 .version = version,
Roland McGrath688f7fc2010-05-08 03:22:59 -07005873 .addrsize = addrsize,
5874 .offset_size = offsize,
5875 .cu_offset = offset
5876 };
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005877
5878 offset += cuhl;
5879
5880 int level = 0;
5881
Roland McGrath2b1f0952010-06-20 17:55:50 -07005882 if (unlikely ((debug_types ? dwarf_offdie_types : dwarf_offdie)
5883 (dbg, offset, &dies[level]) == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005884 {
Roland McGrathfa144952010-08-30 19:22:41 -07005885 if (!silent)
5886 error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
5887 " in section '%s': %s"),
5888 (uint64_t) offset, secname, dwarf_errmsg (-1));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005889 goto do_return;
5890 }
5891
5892 do
5893 {
5894 offset = dwarf_dieoffset (&dies[level]);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00005895 if (unlikely (offset == ~0ul))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005896 {
Roland McGrathfa144952010-08-30 19:22:41 -07005897 if (!silent)
5898 error (0, 0, gettext ("cannot get DIE offset: %s"),
5899 dwarf_errmsg (-1));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005900 goto do_return;
5901 }
5902
5903 int tag = dwarf_tag (&dies[level]);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00005904 if (unlikely (tag == DW_TAG_invalid))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005905 {
Roland McGrathfa144952010-08-30 19:22:41 -07005906 if (!silent)
5907 error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
5908 " in section '%s': %s"),
5909 (uint64_t) offset, secname, dwarf_errmsg (-1));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005910 goto do_return;
5911 }
5912
Roland McGrathfa144952010-08-30 19:22:41 -07005913 if (!silent)
5914 printf (" [%6" PRIx64 "] %*s%s\n",
5915 (uint64_t) offset, (int) (level * 2), "",
5916 dwarf_tag_string (tag));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005917
5918 /* Print the attribute values. */
5919 args.level = level;
5920 (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
5921
5922 /* Make room for the next level's DIE. */
5923 if (level + 1 == maxdies)
5924 dies = (Dwarf_Die *) xrealloc (dies,
5925 (maxdies += 10)
5926 * sizeof (Dwarf_Die));
5927
5928 int res = dwarf_child (&dies[level], &dies[level + 1]);
5929 if (res > 0)
5930 {
5931 while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
Ulrich Drepperc911d5c2008-01-22 05:59:26 +00005932 if (level-- == 0)
5933 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005934
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00005935 if (unlikely (res == -1))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005936 {
Roland McGrathfa144952010-08-30 19:22:41 -07005937 if (!silent)
5938 error (0, 0, gettext ("cannot get next DIE: %s\n"),
5939 dwarf_errmsg (-1));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005940 goto do_return;
5941 }
5942 }
5943 else if (unlikely (res < 0))
5944 {
Roland McGrathfa144952010-08-30 19:22:41 -07005945 if (!silent)
5946 error (0, 0, gettext ("cannot get next DIE: %s"),
5947 dwarf_errmsg (-1));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005948 goto do_return;
5949 }
5950 else
5951 ++level;
5952 }
5953 while (level >= 0);
5954
5955 offset = nextcu;
5956 if (offset != 0)
5957 goto next_cu;
5958
5959 do_return:
5960 free (dies);
5961}
5962
Roland McGrath2b1f0952010-06-20 17:55:50 -07005963static void
5964print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
5965 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5966{
5967 print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
5968}
5969
5970static void
5971print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
5972 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5973{
5974 print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
5975}
5976
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005977
5978static void
Roland McGrath725aad52011-02-23 19:52:46 -08005979print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005980 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5981{
5982 printf (gettext ("\
Ulrich Drepper351bf202009-01-15 20:18:40 -08005983\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
Roland McGrath725aad52011-02-23 19:52:46 -08005984 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
5985 (uint64_t) shdr->sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005986
5987 if (shdr->sh_size == 0)
5988 return;
5989
5990 /* There is no functionality in libdw to read the information in the
5991 way it is represented here. Hardcode the decoder. */
5992 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00005993 if (unlikely (data == NULL || data->d_buf == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00005994 {
5995 error (0, 0, gettext ("cannot get line data section data: %s"),
5996 elf_errmsg (-1));
5997 return;
5998 }
5999
6000 const unsigned char *linep = (const unsigned char *) data->d_buf;
6001 const unsigned char *lineendp;
6002
6003 while (linep
6004 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
6005 {
6006 size_t start_offset = linep - (const unsigned char *) data->d_buf;
6007
6008 printf (gettext ("\nTable at offset %Zu:\n"), start_offset);
6009
6010 Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
6011 unsigned int length = 4;
6012 if (unlikely (unit_length == 0xffffffff))
6013 {
6014 if (unlikely (linep + 8 > lineendp))
6015 {
6016 invalid_data:
6017 error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
Roland McGrath725aad52011-02-23 19:52:46 -08006018 elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006019 return;
6020 }
6021 unit_length = read_8ubyte_unaligned_inc (dbg, linep);
6022 length = 8;
6023 }
6024
6025 /* Check whether we have enough room in the section. */
6026 if (unit_length < 2 + length + 5 * 1
6027 || unlikely (linep + unit_length > lineendp))
6028 goto invalid_data;
6029 lineendp = linep + unit_length;
6030
6031 /* The next element of the header is the version identifier. */
6032 uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
6033
6034 /* Next comes the header length. */
6035 Dwarf_Word header_length;
6036 if (length == 4)
6037 header_length = read_4ubyte_unaligned_inc (dbg, linep);
6038 else
6039 header_length = read_8ubyte_unaligned_inc (dbg, linep);
6040 //const unsigned char *header_start = linep;
6041
6042 /* Next the minimum instruction length. */
6043 uint_fast8_t minimum_instr_len = *linep++;
6044
Roland McGrathe5251a12010-06-20 16:59:39 -07006045 /* Next the maximum operations per instruction, in version 4 format. */
6046 uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++;
6047
Ulrich Drepper173ade82010-05-28 07:39:49 -07006048 /* Then the flag determining the default value of the is_stmt
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006049 register. */
6050 uint_fast8_t default_is_stmt = *linep++;
6051
6052 /* Now the line base. */
6053 int_fast8_t line_base = *((const int_fast8_t *) linep);
6054 ++linep;
6055
6056 /* And the line range. */
6057 uint_fast8_t line_range = *linep++;
6058
6059 /* The opcode base. */
6060 uint_fast8_t opcode_base = *linep++;
6061
6062 /* Print what we got so far. */
6063 printf (gettext ("\n"
6064 " Length: %" PRIu64 "\n"
6065 " DWARF version: %" PRIuFAST16 "\n"
6066 " Prologue length: %" PRIu64 "\n"
6067 " Minimum instruction length: %" PRIuFAST8 "\n"
Roland McGrathe5251a12010-06-20 16:59:39 -07006068 " Maximum operations per instruction: %" PRIuFAST8 "\n"
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006069 " Initial value if '%s': %" PRIuFAST8 "\n"
6070 " Line base: %" PRIdFAST8 "\n"
6071 " Line range: %" PRIuFAST8 "\n"
6072 " Opcode base: %" PRIuFAST8 "\n"
6073 "\n"
6074 "Opcodes:\n"),
6075 (uint64_t) unit_length, version, (uint64_t) header_length,
Roland McGrathe5251a12010-06-20 16:59:39 -07006076 minimum_instr_len, max_ops_per_instr,
6077 "is_stmt", default_is_stmt, line_base,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006078 line_range, opcode_base);
6079
6080 if (unlikely (linep + opcode_base - 1 >= lineendp))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006081 {
6082 invalid_unit:
6083 error (0, 0,
6084 gettext ("invalid data at offset %tu in section [%zu] '%s'"),
6085 linep - (const unsigned char *) data->d_buf,
Roland McGrath725aad52011-02-23 19:52:46 -08006086 elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006087 linep = lineendp;
6088 continue;
6089 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006090 int opcode_base_l10 = 1;
6091 unsigned int tmp = opcode_base;
6092 while (tmp > 10)
6093 {
6094 tmp /= 10;
6095 ++opcode_base_l10;
6096 }
6097 const uint8_t *standard_opcode_lengths = linep - 1;
6098 for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
6099 printf (ngettext (" [%*" PRIuFAST8 "] %hhu argument\n",
6100 " [%*" PRIuFAST8 "] %hhu arguments\n",
6101 (int) linep[cnt - 1]),
6102 opcode_base_l10, cnt, linep[cnt - 1]);
6103 linep += opcode_base - 1;
6104 if (unlikely (linep >= lineendp))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006105 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006106
6107 puts (gettext ("\nDirectory table:"));
6108 while (*linep != 0)
6109 {
6110 unsigned char *endp = memchr (linep, '\0', lineendp - linep);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006111 if (unlikely (endp == NULL))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006112 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006113
6114 printf (" %s\n", (char *) linep);
6115
6116 linep = endp + 1;
6117 }
6118 /* Skip the final NUL byte. */
6119 ++linep;
6120
6121 if (unlikely (linep >= lineendp))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006122 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006123 puts (gettext ("\nFile name table:\n"
6124 " Entry Dir Time Size Name"));
6125 for (unsigned int cnt = 1; *linep != 0; ++cnt)
6126 {
6127 /* First comes the file name. */
6128 char *fname = (char *) linep;
6129 unsigned char *endp = memchr (fname, '\0', lineendp - linep);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006130 if (unlikely (endp == NULL))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006131 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006132 linep = endp + 1;
6133
6134 /* Then the index. */
6135 unsigned int diridx;
6136 get_uleb128 (diridx, linep);
6137
6138 /* Next comes the modification time. */
6139 unsigned int mtime;
6140 get_uleb128 (mtime, linep);
6141
6142 /* Finally the length of the file. */
6143 unsigned int fsize;
6144 get_uleb128 (fsize, linep);
6145
6146 printf (" %-5u %-5u %-9u %-9u %s\n",
6147 cnt, diridx, mtime, fsize, fname);
6148 }
6149 /* Skip the final NUL byte. */
6150 ++linep;
6151
6152 puts (gettext ("\nLine number statements:"));
6153 Dwarf_Word address = 0;
Roland McGrathe5251a12010-06-20 16:59:39 -07006154 unsigned int op_index = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006155 size_t line = 1;
6156 uint_fast8_t is_stmt = default_is_stmt;
6157
6158 /* Default address value, in case we do not find the CU. */
6159 size_t address_size
6160 = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6161
6162 /* Determine the CU this block is for. */
6163 Dwarf_Off cuoffset;
6164 Dwarf_Off ncuoffset = 0;
6165 size_t hsize;
6166 while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
6167 NULL, NULL, NULL) == 0)
6168 {
6169 Dwarf_Die cudie;
6170 if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
6171 continue;
6172 Dwarf_Attribute stmt_list;
6173 if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
6174 continue;
6175 Dwarf_Word lineoff;
6176 if (dwarf_formudata (&stmt_list, &lineoff) != 0)
6177 continue;
6178 if (lineoff == start_offset)
6179 {
6180 /* Found the CU. */
6181 address_size = cudie.cu->address_size;
6182 break;
6183 }
6184 }
6185
Roland McGrathe5251a12010-06-20 16:59:39 -07006186 /* Apply the "operation advance" from a special opcode
6187 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */
6188 unsigned int op_addr_advance;
6189 bool show_op_index;
6190 inline void advance_pc (unsigned int op_advance)
6191 {
6192 op_addr_advance = minimum_instr_len * ((op_index + op_advance)
6193 / max_ops_per_instr);
6194 address += op_advance;
6195 show_op_index = (op_index > 0 ||
6196 (op_index + op_advance) % max_ops_per_instr > 0);
6197 op_index = (op_index + op_advance) % max_ops_per_instr;
6198 }
6199
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006200 while (linep < lineendp)
6201 {
Petr Machata1879e5b2011-03-25 15:17:04 +01006202 size_t offset = linep - (const unsigned char *) data->d_buf;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006203 unsigned int u128;
6204 int s128;
6205
6206 /* Read the opcode. */
6207 unsigned int opcode = *linep++;
6208
Petr Machata1879e5b2011-03-25 15:17:04 +01006209 printf (" [%6" PRIx64 "]", (uint64_t)offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006210 /* Is this a special opcode? */
6211 if (likely (opcode >= opcode_base))
6212 {
6213 /* Yes. Handling this is quite easy since the opcode value
6214 is computed with
6215
6216 opcode = (desired line increment - line_base)
Ulrich Drepper173ade82010-05-28 07:39:49 -07006217 + (line_range * address advance) + opcode_base
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006218 */
6219 int line_increment = (line_base
6220 + (opcode - opcode_base) % line_range);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006221
6222 /* Perform the increments. */
6223 line += line_increment;
Roland McGrathe5251a12010-06-20 16:59:39 -07006224 advance_pc ((opcode - opcode_base) / line_range);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006225
Roland McGrath671d6d82009-08-23 17:55:05 -07006226 char *a = format_dwarf_addr (dwflmod, 0, address);
Roland McGrathe5251a12010-06-20 16:59:39 -07006227 if (show_op_index)
6228 printf (gettext ("\
6229 special opcode %u: address+%u = %s, op_index = %u, line%+d = %zu\n"),
6230 opcode, op_addr_advance, a, op_index,
6231 line_increment, line);
6232 else
6233 printf (gettext ("\
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006234 special opcode %u: address+%u = %s, line%+d = %zu\n"),
Roland McGrathe5251a12010-06-20 16:59:39 -07006235 opcode, op_addr_advance, a, line_increment, line);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006236 free (a);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006237 }
6238 else if (opcode == 0)
6239 {
6240 /* This an extended opcode. */
6241 if (unlikely (linep + 2 > lineendp))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006242 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006243
6244 /* The length. */
6245 unsigned int len = *linep++;
6246
6247 if (unlikely (linep + len > lineendp))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006248 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006249
6250 /* The sub-opcode. */
6251 opcode = *linep++;
6252
6253 printf (gettext (" extended opcode %u: "), opcode);
6254
6255 switch (opcode)
6256 {
6257 case DW_LNE_end_sequence:
Petr Machata1879e5b2011-03-25 15:17:04 +01006258 puts (gettext (" end of sequence"));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006259
6260 /* Reset the registers we care about. */
6261 address = 0;
Roland McGrathe5251a12010-06-20 16:59:39 -07006262 op_index = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006263 line = 1;
6264 is_stmt = default_is_stmt;
6265 break;
6266
6267 case DW_LNE_set_address:
Roland McGrathe5251a12010-06-20 16:59:39 -07006268 op_index = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006269 if (address_size == 4)
6270 address = read_4ubyte_unaligned_inc (dbg, linep);
6271 else
6272 address = read_8ubyte_unaligned_inc (dbg, linep);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006273 {
Roland McGrath671d6d82009-08-23 17:55:05 -07006274 char *a = format_dwarf_addr (dwflmod, 0, address);
Petr Machata1879e5b2011-03-25 15:17:04 +01006275 printf (gettext (" set address to %s\n"), a);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006276 free (a);
6277 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006278 break;
6279
6280 case DW_LNE_define_file:
6281 {
6282 char *fname = (char *) linep;
6283 unsigned char *endp = memchr (linep, '\0',
6284 lineendp - linep);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006285 if (unlikely (endp == NULL))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006286 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006287 linep = endp + 1;
6288
6289 unsigned int diridx;
6290 get_uleb128 (diridx, linep);
6291 Dwarf_Word mtime;
6292 get_uleb128 (mtime, linep);
6293 Dwarf_Word filelength;
6294 get_uleb128 (filelength, linep);
6295
6296 printf (gettext ("\
Petr Machata1879e5b2011-03-25 15:17:04 +01006297 define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006298 diridx, (uint64_t) mtime, (uint64_t) filelength,
6299 fname);
6300 }
6301 break;
6302
Roland McGrathe5251a12010-06-20 16:59:39 -07006303 case DW_LNE_set_discriminator:
6304 /* Takes one ULEB128 parameter, the discriminator. */
6305 if (unlikely (standard_opcode_lengths[opcode] != 1))
6306 goto invalid_unit;
6307
6308 get_uleb128 (u128, linep);
6309 printf (gettext (" set discriminator to %u\n"), u128);
6310 break;
6311
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006312 default:
6313 /* Unknown, ignore it. */
Petr Machata1879e5b2011-03-25 15:17:04 +01006314 puts (gettext (" unknown opcode"));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006315 linep += len - 1;
6316 break;
6317 }
6318 }
Roland McGrathe5251a12010-06-20 16:59:39 -07006319 else if (opcode <= DW_LNS_set_isa)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006320 {
6321 /* This is a known standard opcode. */
6322 switch (opcode)
6323 {
6324 case DW_LNS_copy:
6325 /* Takes no argument. */
6326 puts (gettext (" copy"));
6327 break;
6328
6329 case DW_LNS_advance_pc:
6330 /* Takes one uleb128 parameter which is added to the
6331 address. */
6332 get_uleb128 (u128, linep);
Roland McGrathe5251a12010-06-20 16:59:39 -07006333 advance_pc (u128);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006334 {
Roland McGrath671d6d82009-08-23 17:55:05 -07006335 char *a = format_dwarf_addr (dwflmod, 0, address);
Roland McGrathe5251a12010-06-20 16:59:39 -07006336 if (show_op_index)
6337 printf (gettext ("\
Petr Machata1879e5b2011-03-25 15:17:04 +01006338 advance address by %u to %s, op_index to %u\n"),
Roland McGrathe5251a12010-06-20 16:59:39 -07006339 op_addr_advance, a, op_index);
6340 else
Petr Machata1879e5b2011-03-25 15:17:04 +01006341 printf (gettext (" advance address by %u to %s\n"),
Roland McGrathe5251a12010-06-20 16:59:39 -07006342 op_addr_advance, a);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006343 free (a);
6344 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006345 break;
6346
6347 case DW_LNS_advance_line:
6348 /* Takes one sleb128 parameter which is added to the
6349 line. */
6350 get_sleb128 (s128, linep);
6351 line += s128;
6352 printf (gettext ("\
6353 advance line by constant %d to %" PRId64 "\n"),
6354 s128, (int64_t) line);
6355 break;
6356
6357 case DW_LNS_set_file:
6358 /* Takes one uleb128 parameter which is stored in file. */
6359 get_uleb128 (u128, linep);
6360 printf (gettext (" set file to %" PRIu64 "\n"),
6361 (uint64_t) u128);
6362 break;
6363
6364 case DW_LNS_set_column:
6365 /* Takes one uleb128 parameter which is stored in column. */
6366 if (unlikely (standard_opcode_lengths[opcode] != 1))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006367 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006368
6369 get_uleb128 (u128, linep);
6370 printf (gettext (" set column to %" PRIu64 "\n"),
6371 (uint64_t) u128);
6372 break;
6373
6374 case DW_LNS_negate_stmt:
6375 /* Takes no argument. */
6376 is_stmt = 1 - is_stmt;
6377 printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
6378 "is_stmt", is_stmt);
6379 break;
6380
6381 case DW_LNS_set_basic_block:
6382 /* Takes no argument. */
6383 puts (gettext (" set basic block flag"));
6384 break;
6385
6386 case DW_LNS_const_add_pc:
6387 /* Takes no argument. */
Roland McGrathe5251a12010-06-20 16:59:39 -07006388 advance_pc ((255 - opcode_base) / line_range);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006389 {
Roland McGrath671d6d82009-08-23 17:55:05 -07006390 char *a = format_dwarf_addr (dwflmod, 0, address);
Roland McGrathe5251a12010-06-20 16:59:39 -07006391 if (show_op_index)
6392 printf (gettext ("\
Petr Machata1879e5b2011-03-25 15:17:04 +01006393 advance address by constant %u to %s, op_index to %u\n"),
Roland McGrathe5251a12010-06-20 16:59:39 -07006394 op_addr_advance, a, op_index);
6395 else
6396 printf (gettext ("\
Petr Machata1879e5b2011-03-25 15:17:04 +01006397 advance address by constant %u to %s\n"),
Roland McGrathe5251a12010-06-20 16:59:39 -07006398 op_addr_advance, a);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006399 free (a);
6400 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006401 break;
6402
6403 case DW_LNS_fixed_advance_pc:
6404 /* Takes one 16 bit parameter which is added to the
6405 address. */
6406 if (unlikely (standard_opcode_lengths[opcode] != 1))
Roland McGrathe4c22ea2007-10-23 13:07:39 +00006407 goto invalid_unit;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006408
6409 u128 = read_2ubyte_unaligned_inc (dbg, linep);
6410 address += u128;
Roland McGrathe5251a12010-06-20 16:59:39 -07006411 op_index = 0;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006412 {
Roland McGrath671d6d82009-08-23 17:55:05 -07006413 char *a = format_dwarf_addr (dwflmod, 0, address);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006414 printf (gettext ("\
Petr Machata1879e5b2011-03-25 15:17:04 +01006415 advance address by fixed value %u to %s\n"),
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006416 u128, a);
6417 free (a);
6418 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006419 break;
6420
6421 case DW_LNS_set_prologue_end:
6422 /* Takes no argument. */
6423 puts (gettext (" set prologue end flag"));
6424 break;
6425
Ulrich Drepper6d5c3bd2005-08-11 04:37:52 +00006426 case DW_LNS_set_epilogue_begin:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006427 /* Takes no argument. */
6428 puts (gettext (" set epilogue begin flag"));
6429 break;
Roland McGrathe5251a12010-06-20 16:59:39 -07006430
6431 case DW_LNS_set_isa:
6432 /* Takes one uleb128 parameter which is stored in isa. */
6433 if (unlikely (standard_opcode_lengths[opcode] != 1))
6434 goto invalid_unit;
6435
Roland McGrathfa799902010-06-22 13:05:23 -07006436 get_uleb128 (u128, linep);
Roland McGrathe5251a12010-06-20 16:59:39 -07006437 printf (gettext (" set isa to %u\n"), u128);
6438 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006439 }
6440 }
6441 else
6442 {
6443 /* This is a new opcode the generator but not we know about.
6444 Read the parameters associated with it but then discard
6445 everything. Read all the parameters for this opcode. */
6446 printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
6447 " unknown opcode with %" PRIu8 " parameters:",
6448 standard_opcode_lengths[opcode]),
6449 standard_opcode_lengths[opcode]);
6450 for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
6451 {
6452 get_uleb128 (u128, linep);
6453 if (n != standard_opcode_lengths[opcode])
6454 putc_unlocked (',', stdout);
6455 printf (" %u", u128);
6456 }
6457
6458 /* Next round, ignore this opcode. */
6459 continue;
6460 }
6461 }
6462 }
6463
6464 /* There must only be one data block. */
6465 assert (elf_getdata (scn, data) == NULL);
6466}
6467
6468
6469static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006470print_debug_loc_section (Dwfl_Module *dwflmod,
Roland McGrath725aad52011-02-23 19:52:46 -08006471 Ebl *ebl, GElf_Ehdr *ehdr,
Ulrich Drepper351bf202009-01-15 20:18:40 -08006472 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006473{
6474 Elf_Data *data = elf_rawdata (scn, NULL);
6475
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006476 if (unlikely (data == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006477 {
6478 error (0, 0, gettext ("cannot get .debug_loc content: %s"),
6479 elf_errmsg (-1));
6480 return;
6481 }
6482
6483 printf (gettext ("\
Ulrich Drepper351bf202009-01-15 20:18:40 -08006484\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
Roland McGrath725aad52011-02-23 19:52:46 -08006485 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6486 (uint64_t) shdr->sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006487
Roland McGrathfa144952010-08-30 19:22:41 -07006488 sort_listptr (&known_loclistptr, "loclistptr");
6489 size_t listptr_idx = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006490
Roland McGrathfa144952010-08-30 19:22:41 -07006491 uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6492 uint_fast8_t offset_size = 4;
Roland McGrath688f7fc2010-05-08 03:22:59 -07006493
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006494 bool first = true;
6495 unsigned char *readp = data->d_buf;
Roland McGratha1599152010-08-30 04:04:37 -07006496 unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
6497 while (readp < endp)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006498 {
6499 ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
6500
Roland McGrathfa144952010-08-30 19:22:41 -07006501 if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx,
6502 &address_size, &offset_size,
6503 offset, &readp, endp))
6504 continue;
6505
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006506 if (unlikely (data->d_size - offset < address_size * 2))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006507 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006508 printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006509 break;
6510 }
6511
6512 Dwarf_Addr begin;
6513 Dwarf_Addr end;
6514 if (address_size == 8)
6515 {
6516 begin = read_8ubyte_unaligned_inc (dbg, readp);
6517 end = read_8ubyte_unaligned_inc (dbg, readp);
6518 }
6519 else
6520 {
6521 begin = read_4ubyte_unaligned_inc (dbg, readp);
6522 end = read_4ubyte_unaligned_inc (dbg, readp);
6523 if (begin == (Dwarf_Addr) (uint32_t) -1)
6524 begin = (Dwarf_Addr) -1l;
6525 }
6526
6527 if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006528 {
Roland McGrath671d6d82009-08-23 17:55:05 -07006529 char *b = format_dwarf_addr (dwflmod, address_size, end);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006530 printf (gettext (" [%6tx] base address %s\n"), offset, b);
6531 free (b);
6532 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006533 else if (begin == 0 && end == 0) /* End of list entry. */
Roland McGrathfa144952010-08-30 19:22:41 -07006534 {
6535 if (first)
6536 printf (gettext (" [%6tx] empty list\n"), offset);
6537 first = true;
6538 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006539 else
6540 {
6541 /* We have a location expression entry. */
6542 uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
6543
Roland McGrath671d6d82009-08-23 17:55:05 -07006544 char *b = format_dwarf_addr (dwflmod, address_size, begin);
6545 char *e = format_dwarf_addr (dwflmod, address_size, end);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006546
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006547 if (first) /* First entry in a list. */
6548 printf (gettext (" [%6tx] %s..%s"), offset, b, e);
6549 else
6550 printf (gettext (" %s..%s"), b, e);
6551
6552 free (b);
6553 free (e);
6554
Roland McGratha1599152010-08-30 04:04:37 -07006555 if (endp - readp <= (ptrdiff_t) len)
6556 {
6557 fputs (gettext (" <INVALID DATA>\n"), stdout);
6558 break;
6559 }
6560
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006561 print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
Roland McGrath52604ba2010-07-26 21:29:44 -07006562 3 /*XXX*/, address_size, offset_size, len, readp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006563
6564 first = false;
6565 readp += len;
6566 }
6567 }
6568}
6569
6570struct mac_culist
6571{
6572 Dwarf_Die die;
6573 Dwarf_Off offset;
6574 Dwarf_Files *files;
6575 struct mac_culist *next;
6576};
6577
6578
6579static int
6580mac_compare (const void *p1, const void *p2)
6581{
6582 struct mac_culist *m1 = (struct mac_culist *) p1;
6583 struct mac_culist *m2 = (struct mac_culist *) p2;
6584
6585 if (m1->offset < m2->offset)
6586 return -1;
6587 if (m1->offset > m2->offset)
6588 return 1;
6589 return 0;
6590}
6591
6592
6593static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006594print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Roland McGrath725aad52011-02-23 19:52:46 -08006595 Ebl *ebl, GElf_Ehdr *ehdr,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006596 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
6597{
6598 printf (gettext ("\
Ulrich Drepper351bf202009-01-15 20:18:40 -08006599\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
Roland McGrath725aad52011-02-23 19:52:46 -08006600 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6601 (uint64_t) shdr->sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006602 putc_unlocked ('\n', stdout);
6603
6604 /* There is no function in libdw to iterate over the raw content of
6605 the section but it is easy enough to do. */
6606 Elf_Data *data = elf_getdata (scn, NULL);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006607 if (unlikely (data == NULL || data->d_buf == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006608 {
6609 error (0, 0, gettext ("cannot get macro information section data: %s"),
6610 elf_errmsg (-1));
6611 return;
6612 }
6613
6614 /* Get the source file information for all CUs. */
6615 Dwarf_Off offset;
6616 Dwarf_Off ncu = 0;
6617 size_t hsize;
6618 struct mac_culist *culist = NULL;
6619 size_t nculist = 0;
6620 while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
6621 {
6622 Dwarf_Die cudie;
6623 if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
6624 continue;
6625
6626 Dwarf_Attribute attr;
6627 if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
6628 continue;
6629
6630 Dwarf_Word macoff;
6631 if (dwarf_formudata (&attr, &macoff) != 0)
6632 continue;
6633
6634 struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
6635 newp->die = cudie;
6636 newp->offset = macoff;
6637 newp->files = NULL;
6638 newp->next = culist;
6639 culist = newp;
6640 ++nculist;
6641 }
6642
6643 /* Convert the list into an array for easier consumption. */
6644 struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
6645 * sizeof (*cus));
6646 /* Add sentinel. */
6647 cus[nculist].offset = data->d_size;
6648 if (nculist > 0)
6649 {
6650 for (size_t cnt = nculist - 1; culist != NULL; --cnt)
6651 {
6652 assert (cnt < nculist);
6653 cus[cnt] = *culist;
6654 culist = culist->next;
6655 }
6656
6657 /* Sort the array according to the offset in the .debug_macinfo
6658 section. Note we keep the sentinel at the end. */
6659 qsort (cus, nculist, sizeof (*cus), mac_compare);
6660 }
6661
6662 const unsigned char *readp = (const unsigned char *) data->d_buf;
6663 const unsigned char *readendp = readp + data->d_size;
6664 int level = 1;
6665
6666 while (readp < readendp)
6667 {
6668 unsigned int opcode = *readp++;
6669 unsigned int u128;
6670 unsigned int u128_2;
6671 const unsigned char *endp;
6672
6673 switch (opcode)
6674 {
6675 case DW_MACINFO_define:
6676 case DW_MACINFO_undef:
6677 case DW_MACINFO_vendor_ext:
6678 /* For the first two opcodes the parameters are
Ulrich Drepper173ade82010-05-28 07:39:49 -07006679 line, string
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006680 For the latter
Ulrich Drepper173ade82010-05-28 07:39:49 -07006681 number, string.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006682 We can treat these cases together. */
6683 get_uleb128 (u128, readp);
6684
6685 endp = memchr (readp, '\0', readendp - readp);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006686 if (unlikely (endp == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006687 {
6688 printf (gettext ("\
6689%*s*** non-terminated string at end of section"),
6690 level, "");
6691 return;
6692 }
6693
6694 if (opcode == DW_MACINFO_define)
6695 printf ("%*s#define %s, line %u\n",
6696 level, "", (char *) readp, u128);
6697 else if (opcode == DW_MACINFO_undef)
6698 printf ("%*s#undef %s, line %u\n",
6699 level, "", (char *) readp, u128);
6700 else
6701 printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
6702
6703 readp = endp + 1;
6704 break;
6705
6706 case DW_MACINFO_start_file:
6707 /* The two parameters are line and file index, in this order. */
6708 get_uleb128 (u128, readp);
6709 get_uleb128 (u128_2, readp);
6710
6711 /* Find the CU DIE for this file. */
6712 size_t macoff = readp - (const unsigned char *) data->d_buf;
6713 const char *fname = "???";
6714 if (macoff >= cus[0].offset)
6715 {
6716 while (macoff >= cus[1].offset)
6717 ++cus;
6718
6719 if (cus[0].files == NULL
6720 && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
6721 cus[0].files = (Dwarf_Files *) -1l;
6722
6723 if (cus[0].files != (Dwarf_Files *) -1l)
6724 fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
6725 ?: "???");
6726 }
6727
6728 printf ("%*sstart_file %u, [%u] %s\n",
6729 level, "", u128, u128_2, fname);
6730 ++level;
6731 break;
6732
6733 case DW_MACINFO_end_file:
6734 --level;
6735 printf ("%*send_file\n", level, "");
6736 /* Nothing more to do. */
6737 break;
6738
6739 default:
6740 // XXX gcc seems to generate files with a trailing zero.
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006741 if (unlikely (opcode != 0 || readp != readendp))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006742 printf ("%*s*** invalid opcode %u\n", level, "", opcode);
6743 break;
6744 }
6745 }
6746}
6747
6748
6749/* Callback for printing global names. */
6750static int
6751print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
6752 void *arg)
6753{
6754 int *np = (int *) arg;
6755
6756 printf (gettext (" [%5d] DIE offset: %6" PRId64
6757 ", CU DIE offset: %6" PRId64 ", name: %s\n"),
6758 (*np)++, global->die_offset, global->cu_offset, global->name);
6759
6760 return 0;
6761}
6762
6763
6764/* Print the known exported symbols in the DWARF section '.debug_pubnames'. */
6765static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006766print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Roland McGrath725aad52011-02-23 19:52:46 -08006767 Ebl *ebl, GElf_Ehdr *ehdr,
Ulrich Drepper351bf202009-01-15 20:18:40 -08006768 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006769{
Ulrich Drepper351bf202009-01-15 20:18:40 -08006770 printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
Roland McGrath725aad52011-02-23 19:52:46 -08006771 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
6772 (uint64_t) shdr->sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006773
6774 int n = 0;
6775 (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
6776}
6777
6778/* Print the content of the DWARF string section '.debug_str'. */
6779static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00006780print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Roland McGrath725aad52011-02-23 19:52:46 -08006781 Ebl *ebl, GElf_Ehdr *ehdr,
Ulrich Drepper351bf202009-01-15 20:18:40 -08006782 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006783{
Roland McGrath725aad52011-02-23 19:52:46 -08006784 const size_t sh_size = dbg->sectiondata[IDX_debug_str]->d_size;
6785
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006786 /* Compute floor(log16(shdr->sh_size)). */
Roland McGrath725aad52011-02-23 19:52:46 -08006787 GElf_Addr tmp = sh_size;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006788 int digits = 1;
6789 while (tmp >= 16)
6790 {
6791 ++digits;
6792 tmp >>= 4;
6793 }
6794 digits = MAX (4, digits);
6795
Ulrich Drepper351bf202009-01-15 20:18:40 -08006796 printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006797 " %*s String\n"),
Ulrich Drepper351bf202009-01-15 20:18:40 -08006798 elf_ndxscn (scn),
Roland McGrath725aad52011-02-23 19:52:46 -08006799 section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006800 /* TRANS: the debugstr| prefix makes the string unique. */
6801 digits + 2, sgettext ("debugstr|Offset"));
6802
6803 Dwarf_Off offset = 0;
Roland McGrath725aad52011-02-23 19:52:46 -08006804 while (offset < sh_size)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006805 {
6806 size_t len;
6807 const char *str = dwarf_getstring (dbg, offset, &len);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00006808 if (unlikely (str == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00006809 {
6810 printf (gettext (" *** error while reading strings: %s\n"),
6811 dwarf_errmsg (-1));
6812 break;
6813 }
6814
6815 printf (" [%*" PRIx64 "] \"%s\"\n", digits, (uint64_t) offset, str);
6816
6817 offset += len + 1;
6818 }
6819}
6820
Ulrich Drepper351bf202009-01-15 20:18:40 -08006821
Ulrich Drepper351bf202009-01-15 20:18:40 -08006822/* Print the content of the call frame search table section
6823 '.eh_frame_hdr'. */
6824static void
6825print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6826 Ebl *ebl __attribute__ ((unused)),
6827 GElf_Ehdr *ehdr __attribute__ ((unused)),
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08006828 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
Ulrich Drepper351bf202009-01-15 20:18:40 -08006829{
6830 printf (gettext ("\
6831\nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
6832 elf_ndxscn (scn));
6833
6834 Elf_Data *data = elf_rawdata (scn, NULL);
6835
6836 if (unlikely (data == NULL))
6837 {
6838 error (0, 0, gettext ("cannot get %s content: %s"),
6839 ".eh_frame_hdr", elf_errmsg (-1));
6840 return;
6841 }
6842
6843 const unsigned char *readp = data->d_buf;
6844 const unsigned char *const dataend = ((unsigned char *) data->d_buf
6845 + data->d_size);
6846
6847 if (unlikely (readp + 4 > dataend))
6848 {
6849 invalid_data:
6850 error (0, 0, gettext ("invalid data"));
6851 return;
6852 }
6853
6854 unsigned int version = *readp++;
6855 unsigned int eh_frame_ptr_enc = *readp++;
6856 unsigned int fde_count_enc = *readp++;
6857 unsigned int table_enc = *readp++;
6858
6859 printf (" version: %u\n"
6860 " eh_frame_ptr_enc: %#x ",
6861 version, eh_frame_ptr_enc);
Ulrich Drepperbc298972009-01-16 11:50:10 -08006862 print_encoding_base ("", eh_frame_ptr_enc);
Ulrich Drepper351bf202009-01-15 20:18:40 -08006863 printf (" fde_count_enc: %#x ", fde_count_enc);
Ulrich Drepperbc298972009-01-16 11:50:10 -08006864 print_encoding_base ("", fde_count_enc);
Ulrich Drepper351bf202009-01-15 20:18:40 -08006865 printf (" table_enc: %#x ", table_enc);
Ulrich Drepperbc298972009-01-16 11:50:10 -08006866 print_encoding_base ("", table_enc);
Ulrich Drepper351bf202009-01-15 20:18:40 -08006867
6868 uint64_t eh_frame_ptr = 0;
6869 if (eh_frame_ptr_enc != DW_EH_PE_omit)
6870 {
6871 readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
6872 dbg);
6873 if (unlikely (readp == NULL))
6874 goto invalid_data;
6875
6876 printf (" eh_frame_ptr: %#" PRIx64, eh_frame_ptr);
6877 if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
6878 printf (" (offset: %#" PRIx64 ")",
6879 /* +4 because of the 4 byte header of the section. */
6880 (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
6881
6882 putchar_unlocked ('\n');
6883 }
6884
6885 uint64_t fde_count = 0;
6886 if (fde_count_enc != DW_EH_PE_omit)
6887 {
6888 readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
6889 if (unlikely (readp == NULL))
6890 goto invalid_data;
6891
6892 printf (" fde_count: %" PRIu64 "\n", fde_count);
6893 }
6894
6895 if (fde_count == 0 || table_enc == DW_EH_PE_omit)
6896 return;
6897
6898 puts (" Table:");
6899
6900 /* Optimize for the most common case. */
6901 if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
6902 while (fde_count > 0 && readp + 8 <= dataend)
6903 {
6904 int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
6905 uint64_t initial_offset = ((uint64_t) shdr->sh_offset
6906 + (int64_t) initial_location);
6907 int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
6908 // XXX Possibly print symbol name or section offset for initial_offset
6909 printf (" %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
6910 " fde=[%6" PRIx64 "]\n",
6911 initial_location, initial_offset,
6912 address, address - (eh_frame_ptr + 4));
6913 }
6914 else
6915 while (0 && readp < dataend)
6916 {
6917
6918 }
6919}
6920
6921
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08006922/* Print the content of the exception handling table section
6923 '.eh_frame_hdr'. */
6924static void
6925print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
6926 Ebl *ebl __attribute__ ((unused)),
6927 GElf_Ehdr *ehdr __attribute__ ((unused)),
Ulrich Drepper05d2b202009-01-16 17:58:54 -08006928 Elf_Scn *scn,
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08006929 GElf_Shdr *shdr __attribute__ ((unused)),
6930 Dwarf *dbg __attribute__ ((unused)))
6931{
6932 printf (gettext ("\
6933\nException handling table section [%2zu] '.gcc_except_table':\n"),
6934 elf_ndxscn (scn));
6935
6936 Elf_Data *data = elf_rawdata (scn, NULL);
6937
6938 if (unlikely (data == NULL))
6939 {
6940 error (0, 0, gettext ("cannot get %s content: %s"),
6941 ".gcc_except_table", elf_errmsg (-1));
6942 return;
6943 }
Ulrich Drepper05d2b202009-01-16 17:58:54 -08006944
6945 const unsigned char *readp = data->d_buf;
6946 const unsigned char *const dataend = readp + data->d_size;
6947
6948 if (unlikely (readp + 1 > dataend))
6949 {
6950 invalid_data:
6951 error (0, 0, gettext ("invalid data"));
6952 return;
6953 }
6954 unsigned int lpstart_encoding = *readp++;
6955 printf (gettext (" LPStart encoding: %#x "), lpstart_encoding);
6956 print_encoding_base ("", lpstart_encoding);
6957 if (lpstart_encoding != DW_EH_PE_omit)
6958 {
6959 uint64_t lpstart;
6960 readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
6961 printf (" LPStart: %#" PRIx64 "\n", lpstart);
6962 }
6963
6964 if (unlikely (readp + 1 > dataend))
6965 goto invalid_data;
6966 unsigned int ttype_encoding = *readp++;
6967 printf (gettext (" TType encoding: %#x "), ttype_encoding);
6968 print_encoding_base ("", ttype_encoding);
6969 const unsigned char *ttype_base = NULL;
6970 if (ttype_encoding != DW_EH_PE_omit)
6971 {
6972 unsigned int ttype_base_offset;
6973 get_uleb128 (ttype_base_offset, readp);
6974 printf (" TType base offset: %#x\n", ttype_base_offset);
6975 ttype_base = readp + ttype_base_offset;
6976 }
6977
6978 if (unlikely (readp + 1 > dataend))
6979 goto invalid_data;
6980 unsigned int call_site_encoding = *readp++;
6981 printf (gettext (" Call site encoding: %#x "), call_site_encoding);
6982 print_encoding_base ("", call_site_encoding);
6983 unsigned int call_site_table_len;
6984 get_uleb128 (call_site_table_len, readp);
6985
6986 const unsigned char *const action_table = readp + call_site_table_len;
6987 if (unlikely (action_table > dataend))
6988 goto invalid_data;
6989 unsigned int u = 0;
6990 unsigned int max_action = 0;
6991 while (readp < action_table)
6992 {
6993 if (u == 0)
6994 puts (gettext ("\n Call site table:"));
6995
6996 uint64_t call_site_start;
6997 readp = read_encoded (call_site_encoding, readp, dataend,
6998 &call_site_start, dbg);
6999 uint64_t call_site_length;
7000 readp = read_encoded (call_site_encoding, readp, dataend,
7001 &call_site_length, dbg);
7002 uint64_t landing_pad;
7003 readp = read_encoded (call_site_encoding, readp, dataend,
7004 &landing_pad, dbg);
7005 unsigned int action;
7006 get_uleb128 (action, readp);
7007 max_action = MAX (action, max_action);
7008 printf (gettext (" [%4u] Call site start: %#" PRIx64 "\n"
7009 " Call site length: %" PRIu64 "\n"
7010 " Landing pad: %#" PRIx64 "\n"
7011 " Action: %u\n"),
7012 u++, call_site_start, call_site_length, landing_pad, action);
7013 }
7014 assert (readp == action_table);
7015
7016 unsigned int max_ar_filter = 0;
7017 if (max_action > 0)
7018 {
7019 puts ("\n Action table:");
7020
7021 const unsigned char *const action_table_end
7022 = action_table + max_action + 1;
7023
7024 u = 0;
7025 do
7026 {
7027 int ar_filter;
7028 get_sleb128 (ar_filter, readp);
7029 if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
7030 max_ar_filter = ar_filter;
7031 int ar_disp;
7032 get_sleb128 (ar_disp, readp);
7033
Ulrich Drepper935edde2009-01-17 16:06:42 -08007034 printf (" [%4u] ar_filter: % d\n"
7035 " ar_disp: % -5d",
7036 u, ar_filter, ar_disp);
7037 if (abs (ar_disp) & 1)
7038 printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
7039 else if (ar_disp != 0)
7040 puts (" -> ???");
7041 else
7042 putchar_unlocked ('\n');
7043 ++u;
Ulrich Drepper05d2b202009-01-16 17:58:54 -08007044 }
7045 while (readp < action_table_end);
7046 }
7047
7048 if (max_ar_filter > 0)
7049 {
7050 puts ("\n TType table:");
7051
7052 // XXX Not *4, size of encoding;
7053 switch (ttype_encoding & 7)
7054 {
7055 case DW_EH_PE_udata2:
7056 case DW_EH_PE_sdata2:
7057 readp = ttype_base - max_ar_filter * 2;
7058 break;
7059 case DW_EH_PE_udata4:
7060 case DW_EH_PE_sdata4:
7061 readp = ttype_base - max_ar_filter * 4;
7062 break;
7063 case DW_EH_PE_udata8:
7064 case DW_EH_PE_sdata8:
7065 readp = ttype_base - max_ar_filter * 8;
7066 break;
7067 default:
7068 error (1, 0, gettext ("invalid TType encoding"));
7069 }
7070
7071 do
7072 {
7073 uint64_t ttype;
7074 readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
7075 dbg);
7076 printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
7077 }
7078 while (readp < ttype_base);
7079 }
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08007080}
7081
Mark Wielaard093a1d32011-04-14 23:47:26 +02007082/* Print the content of the '.gdb_index' section.
7083 http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
7084*/
7085static void
7086print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
7087 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7088{
7089 printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
7090 " contains %" PRId64 " bytes :\n"),
7091 elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
7092 (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
7093
7094 Elf_Data *data = elf_rawdata (scn, NULL);
7095
7096 if (unlikely (data == NULL))
7097 {
7098 error (0, 0, gettext ("cannot get %s content: %s"),
7099 ".gdb_index", elf_errmsg (-1));
7100 return;
7101 }
7102
7103 // .gdb_index is always in little endian.
7104 Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
7105 dbg = &dummy_dbg;
7106
7107 const unsigned char *readp = data->d_buf;
7108 const unsigned char *const dataend = readp + data->d_size;
7109
7110 if (unlikely (readp + 4 > dataend))
7111 {
7112 invalid_data:
7113 error (0, 0, gettext ("invalid data"));
7114 return;
7115 }
7116
7117 int32_t vers = read_4ubyte_unaligned (dbg, readp);
7118 printf (gettext (" Version: %" PRId32 "\n"), vers);
7119
7120 // The only difference between version 4 and version 5 is the
Mark Wielaard30bb7142012-03-21 16:05:31 +01007121 // hash used for generating the table. Version 6 contains symbols
7122 // for inlined functions, older versions didn't.
7123 if (vers < 4 || vers > 6)
Mark Wielaard093a1d32011-04-14 23:47:26 +02007124 {
7125 printf (gettext (" unknown version, cannot parse section\n"));
7126 return;
7127 }
7128
7129 readp += 4;
7130 if (unlikely (readp + 4 > dataend))
7131 goto invalid_data;
7132
7133 uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
7134 printf (gettext (" CU offset: %#" PRIx32 "\n"), cu_off);
7135
7136 readp += 4;
7137 if (unlikely (readp + 4 > dataend))
7138 goto invalid_data;
7139
7140 uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
7141 printf (gettext (" TU offset: %#" PRIx32 "\n"), tu_off);
7142
7143 readp += 4;
7144 if (unlikely (readp + 4 > dataend))
7145 goto invalid_data;
7146
7147 uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
7148 printf (gettext (" address offset: %#" PRIx32 "\n"), addr_off);
7149
7150 readp += 4;
7151 if (unlikely (readp + 4 > dataend))
7152 goto invalid_data;
7153
7154 uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
7155 printf (gettext (" symbol offset: %#" PRIx32 "\n"), sym_off);
7156
7157 readp += 4;
7158 if (unlikely (readp + 4 > dataend))
7159 goto invalid_data;
7160
7161 uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
7162 printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
7163
7164 readp = data->d_buf + cu_off;
7165
7166 const unsigned char *nextp = data->d_buf + tu_off;
7167 size_t nr = (nextp - readp) / 16;
7168
7169 printf (gettext ("\n CU list at offset %#" PRIx32
7170 " contains %zu entries:\n"),
7171 cu_off, nr);
7172
7173 size_t n = 0;
7174 while (readp + 16 <= dataend && n < nr)
7175 {
7176 uint64_t off = read_8ubyte_unaligned (dbg, readp);
7177 readp += 8;
7178
7179 uint64_t len = read_8ubyte_unaligned (dbg, readp);
7180 readp += 8;
7181
7182 printf (" [%4zu] start: %0#8" PRIx64
7183 ", length: %5" PRIu64 "\n", n, off, len);
7184 n++;
7185 }
7186
7187 readp = data->d_buf + tu_off;
7188 nextp = data->d_buf + addr_off;
7189 nr = (nextp - readp) / 24;
7190
7191 printf (gettext ("\n TU list at offset %#" PRIx32
7192 " contains %zu entries:\n"),
7193 tu_off, nr);
7194
7195 n = 0;
7196 while (readp + 24 <= dataend && n < nr)
7197 {
7198 uint64_t off = read_8ubyte_unaligned (dbg, readp);
7199 readp += 8;
7200
7201 uint64_t type = read_8ubyte_unaligned (dbg, readp);
7202 readp += 8;
7203
7204 uint64_t sig = read_8ubyte_unaligned (dbg, readp);
7205 readp += 8;
7206
7207 printf (" [%4zu] CU offset: %5" PRId64
7208 ", type offset: %5" PRId64
7209 ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
7210 n++;
7211 }
7212
7213 readp = data->d_buf + addr_off;
7214 nextp = data->d_buf + sym_off;
7215 nr = (nextp - readp) / 20;
7216
7217 printf (gettext ("\n Address list at offset %#" PRIx32
7218 " contains %zu entries:\n"),
7219 addr_off, nr);
7220
7221 n = 0;
7222 while (readp + 20 <= dataend && n < nr)
7223 {
7224 uint64_t low = read_8ubyte_unaligned (dbg, readp);
7225 readp += 8;
7226
7227 uint64_t high = read_8ubyte_unaligned (dbg, readp);
7228 readp += 8;
7229
7230 uint32_t idx = read_4ubyte_unaligned (dbg, readp);
7231 readp += 4;
7232
7233 char *l = format_dwarf_addr (dwflmod, 8, low);
7234 char *h = format_dwarf_addr (dwflmod, 8, high - 1);
7235 printf (" [%4zu] %s..%s, CU index: %5" PRId32 "\n",
7236 n, l, h, idx);
7237 n++;
7238 }
7239
7240 readp = data->d_buf + sym_off;
7241 nextp = data->d_buf + const_off;
7242 nr = (nextp - readp) / 8;
7243
7244 printf (gettext ("\n Symbol table at offset %#" PRIx32
7245 " contains %zu slots:\n"),
7246 addr_off, nr);
7247
7248 n = 0;
7249 while (readp + 8 <= dataend && n < nr)
7250 {
7251 uint32_t name = read_4ubyte_unaligned (dbg, readp);
7252 readp += 4;
7253
7254 uint32_t vector = read_4ubyte_unaligned (dbg, readp);
7255 readp += 4;
7256
7257 if (name != 0 || vector != 0)
7258 {
7259 const unsigned char *sym = data->d_buf + const_off + name;
7260 if (unlikely (sym > dataend))
7261 goto invalid_data;
7262
7263 printf (" [%4zu] symbol: %s, CUs: ", n, sym);
7264
7265 const unsigned char *readcus = data->d_buf + const_off + vector;
7266 if (unlikely (readcus + 8 > dataend))
7267 goto invalid_data;
7268
7269 uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
7270 while (cus--)
7271 {
7272 uint32_t cu;
7273 readcus += 4;
7274 cu = read_4ubyte_unaligned (dbg, readcus);
7275 printf ("%" PRId32 "%s", cu, ((cus > 0) ? ", " : ""));
7276 }
7277 printf ("\n");
7278 }
7279 n++;
7280 }
7281}
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08007282
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007283static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00007284print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007285{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007286 /* Before we start the real work get a debug context descriptor. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00007287 Dwarf_Addr dwbias;
7288 Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
Roland McGratha065c4b2011-12-20 10:55:01 -08007289 Dwarf dummy_dbg =
7290 {
7291 .elf = ebl->elf,
7292 .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
7293 };
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007294 if (dbg == NULL)
7295 {
Roland McGrath7a5bed82010-06-01 13:44:00 -07007296 if ((print_debug_sections & ~section_exception) != 0)
Roland McGrath2e79deb2010-01-04 20:36:10 -08007297 error (0, 0, gettext ("cannot get debug context descriptor: %s"),
7298 dwfl_errmsg (-1));
Roland McGrath7a5bed82010-06-01 13:44:00 -07007299 if ((print_debug_sections & section_exception) == 0)
7300 return;
7301 dbg = &dummy_dbg;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007302 }
7303
7304 /* Get the section header string table index. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00007305 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07007306 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007307 error (EXIT_FAILURE, 0,
7308 gettext ("cannot get section header string table index"));
7309
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00007310 /* Look through all the sections for the debugging sections to print. */
7311 Elf_Scn *scn = NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007312 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
7313 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007314 GElf_Shdr shdr_mem;
7315 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
7316
Ulrich Drepper903c1162007-02-15 19:40:37 +00007317 if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007318 {
7319 static const struct
7320 {
7321 const char *name;
7322 enum section_e bitmask;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00007323 void (*fp) (Dwfl_Module *, Ebl *,
7324 GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007325 } debug_sections[] =
7326 {
7327#define NEW_SECTION(name) \
7328 { ".debug_" #name, section_##name, print_debug_##name##_section }
7329 NEW_SECTION (abbrev),
7330 NEW_SECTION (aranges),
7331 NEW_SECTION (frame),
7332 NEW_SECTION (info),
Roland McGrath2b1f0952010-06-20 17:55:50 -07007333 NEW_SECTION (types),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007334 NEW_SECTION (line),
7335 NEW_SECTION (loc),
7336 NEW_SECTION (pubnames),
7337 NEW_SECTION (str),
7338 NEW_SECTION (macinfo),
7339 NEW_SECTION (ranges),
Ulrich Drepperb006fbf2009-01-16 03:08:25 -08007340 { ".eh_frame", section_frame | section_exception,
7341 print_debug_frame_section },
7342 { ".eh_frame_hdr", section_frame | section_exception,
7343 print_debug_frame_hdr_section },
7344 { ".gcc_except_table", section_frame | section_exception,
Mark Wielaard093a1d32011-04-14 23:47:26 +02007345 print_debug_exception_table },
7346 { ".gdb_index", section_gdb_index, print_gdb_index_section }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007347 };
7348 const int ndebug_sections = (sizeof (debug_sections)
7349 / sizeof (debug_sections[0]));
7350 const char *name = elf_strptr (ebl->elf, shstrndx,
7351 shdr->sh_name);
7352 int n;
7353
7354 for (n = 0; n < ndebug_sections; ++n)
Roland McGrath725aad52011-02-23 19:52:46 -08007355 if (strcmp (name, debug_sections[n].name) == 0
7356#if USE_ZLIB
7357 || (name[0] == '.' && name[1] == 'z'
7358 && debug_sections[n].name[1] == 'd'
7359 && strcmp (&name[2], &debug_sections[n].name[1]) == 0)
7360#endif
7361 )
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007362 {
Roland McGrath2e79deb2010-01-04 20:36:10 -08007363 if ((print_debug_sections | implicit_debug_sections)
7364 & debug_sections[n].bitmask)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00007365 debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007366 break;
7367 }
7368 }
7369 }
Roland McGrathfa144952010-08-30 19:22:41 -07007370
7371 reset_listptr (&known_loclistptr);
7372 reset_listptr (&known_rangelistptr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007373}
7374
7375
Roland McGrathcb6d8652007-08-23 08:10:54 +00007376#define ITEM_INDENT 4
7377#define ITEM_WRAP_COLUMN 150
7378#define REGISTER_WRAP_COLUMN 75
7379
7380/* Print "NAME: FORMAT", wrapping when FORMAT_MAX chars of FORMAT would
7381 make the line exceed ITEM_WRAP_COLUMN. Unpadded numbers look better
7382 for the core items. But we do not want the line breaks to depend on
7383 the particular values. */
7384static unsigned int
7385__attribute__ ((format (printf, 7, 8)))
7386print_core_item (unsigned int colno, char sep, unsigned int wrap,
7387 size_t name_width, const char *name,
7388 size_t format_max, const char *format, ...)
7389{
7390 size_t len = strlen (name);
7391 if (name_width < len)
7392 name_width = len;
7393
7394 size_t n = name_width + sizeof ": " - 1 + format_max;
7395
7396 if (colno == 0)
7397 {
7398 printf ("%*s", ITEM_INDENT, "");
7399 colno = ITEM_INDENT + n;
7400 }
7401 else if (colno + 2 + n < wrap)
7402 {
7403 printf ("%c ", sep);
7404 colno += 2 + n;
7405 }
7406 else
7407 {
7408 printf ("\n%*s", ITEM_INDENT, "");
7409 colno = ITEM_INDENT + n;
7410 }
7411
7412 printf ("%s: %*s", name, (int) (name_width - len), "");
7413
7414 va_list ap;
7415 va_start (ap, format);
7416 vprintf (format, ap);
7417 va_end (ap);
7418
7419 return colno;
7420}
7421
7422static const void *
7423convert (Elf *core, Elf_Type type, uint_fast16_t count,
Roland McGrath1d8bb252008-08-07 08:39:41 +00007424 void *value, const void *data, size_t size)
Roland McGrathcb6d8652007-08-23 08:10:54 +00007425{
7426 Elf_Data valuedata =
7427 {
7428 .d_type = type,
7429 .d_buf = value,
Roland McGrath1d8bb252008-08-07 08:39:41 +00007430 .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
Roland McGrathcb6d8652007-08-23 08:10:54 +00007431 .d_version = EV_CURRENT,
7432 };
7433 Elf_Data indata =
7434 {
7435 .d_type = type,
7436 .d_buf = (void *) data,
7437 .d_size = valuedata.d_size,
7438 .d_version = EV_CURRENT,
7439 };
7440
7441 Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
7442 ? elf32_xlatetom : elf64_xlatetom)
7443 (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
7444 if (d == NULL)
7445 error (EXIT_FAILURE, 0,
7446 gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
7447
7448 return data + indata.d_size;
7449}
7450
7451typedef uint8_t GElf_Byte;
7452
7453static unsigned int
7454handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
Roland McGrath1d8bb252008-08-07 08:39:41 +00007455 unsigned int colno, size_t *repeated_size)
Roland McGrathcb6d8652007-08-23 08:10:54 +00007456{
7457 uint_fast16_t count = item->count ?: 1;
7458
7459#define TYPES \
7460 DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8, 4); \
7461 DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16, 6); \
7462 DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32, 11); \
7463 DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32, 11); \
7464 DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64, 20); \
7465 DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64, 20)
7466
7467#define DO_TYPE(NAME, Name, hex, dec, max) GElf_##Name Name[count]
7468 union { TYPES; } value;
7469#undef DO_TYPE
7470
Roland McGrath1d8bb252008-08-07 08:39:41 +00007471 void *data = &value;
7472 size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
7473 size_t convsize = size;
7474 if (repeated_size != NULL)
7475 {
7476 if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
7477 {
7478 data = alloca (*repeated_size);
7479 count *= *repeated_size / size;
7480 convsize = count * size;
7481 *repeated_size -= convsize;
7482 }
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08007483 else if (item->count != 0 || item->format != '\n')
Roland McGrath1d8bb252008-08-07 08:39:41 +00007484 *repeated_size -= size;
7485 }
7486
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08007487 convert (core, item->type, count, data, desc + item->offset, convsize);
Roland McGrath1d8bb252008-08-07 08:39:41 +00007488
7489 Elf_Type type = item->type;
7490 if (type == ELF_T_ADDR)
7491 type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
Roland McGrathcb6d8652007-08-23 08:10:54 +00007492
7493 switch (item->format)
7494 {
7495 case 'd':
7496 assert (count == 1);
Roland McGrath1d8bb252008-08-07 08:39:41 +00007497 switch (type)
Roland McGrathcb6d8652007-08-23 08:10:54 +00007498 {
7499#define DO_TYPE(NAME, Name, hex, dec, max) \
7500 case ELF_T_##NAME: \
7501 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, \
7502 0, item->name, max, dec, value.Name[0]); \
7503 break
7504 TYPES;
7505#undef DO_TYPE
7506 default:
7507 abort ();
7508 }
7509 break;
7510
7511 case 'x':
7512 assert (count == 1);
Roland McGrath1d8bb252008-08-07 08:39:41 +00007513 switch (type)
Roland McGrathcb6d8652007-08-23 08:10:54 +00007514 {
7515#define DO_TYPE(NAME, Name, hex, dec, max) \
7516 case ELF_T_##NAME: \
7517 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, \
7518 0, item->name, max, hex, value.Name[0]); \
7519 break
7520 TYPES;
7521#undef DO_TYPE
7522 default:
7523 abort ();
7524 }
7525 break;
7526
7527 case 'b':
Roland McGrath1d8bb252008-08-07 08:39:41 +00007528 case 'B':
7529 assert (size % sizeof (unsigned int) == 0);
7530 unsigned int nbits = count * size * 8;
7531 unsigned int pop = 0;
7532 for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
7533 pop += __builtin_popcount (*i);
7534 bool negate = pop > nbits / 2;
7535 const unsigned int bias = item->format == 'b';
7536
7537 {
7538 char printed[(negate ? nbits - pop : pop) * 16];
7539 char *p = printed;
7540 *p = '\0';
7541
7542 if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
7543 {
7544 assert (size == sizeof (unsigned int) * 2);
7545 for (unsigned int *i = data;
7546 (void *) i < data + count * size; i += 2)
7547 {
7548 unsigned int w = i[1];
7549 i[1] = i[0];
7550 i[0] = w;
7551 }
7552 }
7553
7554 unsigned int lastbit = 0;
7555 for (const unsigned int *i = data;
7556 (void *) i < data + count * size; ++i)
7557 {
7558 unsigned int bit = ((void *) i - data) * 8;
7559 unsigned int w = negate ? ~*i : *i;
Roland McGrath62b28b62010-04-14 11:54:06 -07007560 unsigned int run = 0;
Roland McGrath1d8bb252008-08-07 08:39:41 +00007561 while (w != 0)
7562 {
7563 int n = ffs (w);
7564 w >>= n;
7565 bit += n;
7566
Roland McGrath62b28b62010-04-14 11:54:06 -07007567 if (lastbit + 1 == bit)
7568 ++run;
7569 else
7570 {
7571 if (lastbit == 0)
7572 p += sprintf (p, "%u", bit - bias);
7573 else if (run == 0)
7574 p += sprintf (p, ",%u", bit - bias);
7575 else
7576 p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
7577 run = 0;
7578 }
Roland McGrath1d8bb252008-08-07 08:39:41 +00007579
7580 lastbit = bit;
7581 }
7582 }
7583 if (lastbit > 0 && lastbit + 1 != nbits)
7584 p += sprintf (p, "-%u", nbits - bias);
7585
7586 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7587 4 + nbits * 4,
7588 negate ? "~<%s>" : "<%s>", printed);
7589 }
Roland McGrathcb6d8652007-08-23 08:10:54 +00007590 break;
7591
7592 case 'T':
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00007593 case (char) ('T'|0x80):
Roland McGrathcb6d8652007-08-23 08:10:54 +00007594 assert (count == 2);
7595 Dwarf_Word sec;
7596 Dwarf_Word usec;
7597 size_t maxfmt = 7;
Roland McGrath1d8bb252008-08-07 08:39:41 +00007598 switch (type)
Roland McGrathcb6d8652007-08-23 08:10:54 +00007599 {
7600#define DO_TYPE(NAME, Name, hex, dec, max) \
7601 case ELF_T_##NAME: \
7602 sec = value.Name[0]; \
7603 usec = value.Name[1]; \
7604 maxfmt += max; \
7605 break
7606 TYPES;
7607#undef DO_TYPE
7608 default:
7609 abort ();
7610 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00007611 if (unlikely (item->format == (char) ('T'|0x80)))
7612 {
7613 /* This is a hack for an ill-considered 64-bit ABI where
7614 tv_usec is actually a 32-bit field with 32 bits of padding
7615 rounding out struct timeval. We've already converted it as
7616 a 64-bit field. For little-endian, this just means the
7617 high half is the padding; it's presumably zero, but should
7618 be ignored anyway. For big-endian, it means the 32-bit
7619 field went into the high half of USEC. */
7620 GElf_Ehdr ehdr_mem;
7621 GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
7622 if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
7623 usec >>= 32;
7624 else
7625 usec &= UINT32_MAX;
7626 }
Roland McGrathcb6d8652007-08-23 08:10:54 +00007627 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7628 maxfmt, "%" PRIu64 ".%.6" PRIu64, sec, usec);
7629 break;
7630
7631 case 'c':
7632 assert (count == 1);
7633 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7634 1, "%c", value.Byte[0]);
7635 break;
7636
7637 case 's':
7638 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
7639 count, "%.*s", (int) count, value.Byte);
7640 break;
7641
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08007642 case '\n':
7643 /* This is a list of strings separated by '\n'. */
7644 assert (item->count == 0);
7645 assert (repeated_size != NULL);
7646 assert (item->name == NULL);
7647 if (unlikely (item->offset >= *repeated_size))
7648 break;
7649
7650 const char *s = desc + item->offset;
7651 size = *repeated_size - item->offset;
7652 *repeated_size = 0;
7653 while (size > 0)
7654 {
7655 const char *eol = memchr (s, '\n', size);
7656 int len = size;
7657 if (eol != NULL)
7658 len = eol - s;
7659 printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
7660 if (eol == NULL)
7661 break;
7662 size -= eol + 1 - s;
7663 s = eol + 1;
7664 }
7665
7666 colno = ITEM_WRAP_COLUMN;
7667 break;
7668
Roland McGrathcb6d8652007-08-23 08:10:54 +00007669 default:
7670 error (0, 0, "XXX not handling format '%c' for %s",
7671 item->format, item->name);
7672 break;
7673 }
7674
7675#undef TYPES
7676
7677 return colno;
7678}
7679
7680
7681/* Sort items by group, and by layout offset within each group. */
7682static int
7683compare_core_items (const void *a, const void *b)
7684{
7685 const Ebl_Core_Item *const *p1 = a;
7686 const Ebl_Core_Item *const *p2 = b;
7687 const Ebl_Core_Item *item1 = *p1;
7688 const Ebl_Core_Item *item2 = *p2;
7689
7690 return ((item1->group == item2->group ? 0
7691 : strcmp (item1->group, item2->group))
7692 ?: (int) item1->offset - (int) item2->offset);
7693}
7694
7695/* Sort item groups by layout offset of the first item in the group. */
7696static int
7697compare_core_item_groups (const void *a, const void *b)
7698{
7699 const Ebl_Core_Item *const *const *p1 = a;
7700 const Ebl_Core_Item *const *const *p2 = b;
7701 const Ebl_Core_Item *const *group1 = *p1;
7702 const Ebl_Core_Item *const *group2 = *p2;
7703 const Ebl_Core_Item *item1 = *group1;
7704 const Ebl_Core_Item *item2 = *group2;
7705
7706 return (int) item1->offset - (int) item2->offset;
7707}
7708
7709static unsigned int
Roland McGrath059c83e2008-02-21 06:19:39 +00007710handle_core_items (Elf *core, const void *desc, size_t descsz,
Roland McGrathcb6d8652007-08-23 08:10:54 +00007711 const Ebl_Core_Item *items, size_t nitems)
7712{
7713 if (nitems == 0)
7714 return 0;
7715
7716 /* Sort to collect the groups together. */
7717 const Ebl_Core_Item *sorted_items[nitems];
7718 for (size_t i = 0; i < nitems; ++i)
7719 sorted_items[i] = &items[i];
7720 qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
7721
7722 /* Collect the unique groups and sort them. */
7723 const Ebl_Core_Item **groups[nitems];
7724 groups[0] = &sorted_items[0];
7725 size_t ngroups = 1;
7726 for (size_t i = 1; i < nitems; ++i)
7727 if (sorted_items[i]->group != sorted_items[i - 1]->group
7728 && strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
7729 groups[ngroups++] = &sorted_items[i];
7730 qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
7731
7732 /* Write out all the groups. */
7733 unsigned int colno = 0;
Roland McGrathcb6d8652007-08-23 08:10:54 +00007734
Roland McGrath1d8bb252008-08-07 08:39:41 +00007735 const void *last = desc;
7736 if (nitems == 1)
7737 {
7738 size_t size = descsz;
7739 colno = handle_core_item (core, sorted_items[0], desc, colno, &size);
7740 if (size == 0)
7741 return colno;
7742 desc += descsz - size;
7743 descsz = size;
7744 }
7745
Roland McGrath059c83e2008-02-21 06:19:39 +00007746 do
7747 {
7748 for (size_t i = 0; i < ngroups; ++i)
7749 {
7750 for (const Ebl_Core_Item **item = groups[i];
7751 (item < &sorted_items[nitems]
7752 && ((*item)->group == groups[i][0]->group
7753 || !strcmp ((*item)->group, groups[i][0]->group)));
7754 ++item)
Roland McGrath1d8bb252008-08-07 08:39:41 +00007755 colno = handle_core_item (core, *item, desc, colno, NULL);
Roland McGrath059c83e2008-02-21 06:19:39 +00007756
7757 /* Force a line break at the end of the group. */
7758 colno = ITEM_WRAP_COLUMN;
7759 }
7760
7761 if (descsz == 0)
7762 break;
7763
7764 /* This set of items consumed a certain amount of the note's data.
7765 If there is more data there, we have another unit of the same size.
7766 Loop to print that out too. */
7767 const Ebl_Core_Item *item = &items[nitems - 1];
7768 size_t eltsz = item->offset + gelf_fsize (core, item->type,
7769 item->count ?: 1, EV_CURRENT);
Roland McGrath1d8bb252008-08-07 08:39:41 +00007770
7771 int reps = -1;
7772 do
7773 {
7774 ++reps;
7775 desc += eltsz;
7776 descsz -= eltsz;
7777 }
7778 while (descsz >= eltsz && !memcmp (desc, last, eltsz));
7779
7780 if (reps == 1)
7781 {
7782 /* For just one repeat, print it unabridged twice. */
7783 desc -= eltsz;
7784 descsz += eltsz;
7785 }
7786 else if (reps > 1)
7787 printf (gettext ("\n%*s... <repeats %u more times> ..."),
7788 ITEM_INDENT, "", reps);
7789
7790 last = desc;
Roland McGrathcb6d8652007-08-23 08:10:54 +00007791 }
Roland McGrath059c83e2008-02-21 06:19:39 +00007792 while (descsz > 0);
Roland McGrathcb6d8652007-08-23 08:10:54 +00007793
7794 return colno;
7795}
7796
7797static unsigned int
7798handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
7799 unsigned int colno)
7800{
7801 desc += regloc->offset;
7802
7803 abort (); /* XXX */
7804 return colno;
7805}
7806
7807
7808static unsigned int
7809handle_core_register (Ebl *ebl, Elf *core, int maxregname,
7810 const Ebl_Register_Location *regloc, const void *desc,
7811 unsigned int colno)
7812{
7813 if (regloc->bits % 8 != 0)
7814 return handle_bit_registers (regloc, desc, colno);
7815
7816 desc += regloc->offset;
7817
7818 for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
7819 {
Roland McGrathdffc33d2009-07-06 16:06:41 -07007820 char name[REGNAMESZ];
Roland McGrathcb6d8652007-08-23 08:10:54 +00007821 int bits;
7822 int type;
Roland McGrathdffc33d2009-07-06 16:06:41 -07007823 register_info (ebl, reg, regloc, name, &bits, &type);
Roland McGrathcb6d8652007-08-23 08:10:54 +00007824
7825#define TYPES \
7826 BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8, 4); \
7827 BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16, 6); \
7828 BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32, 11); \
7829 BITS (64, XWORD, "%20" PRId64, " 0x%.16" PRIx64, 20)
7830
7831#define BITS(bits, xtype, sfmt, ufmt, max) \
7832 uint##bits##_t b##bits; int##bits##_t b##bits##s
7833 union { TYPES; uint64_t b128[2]; } value;
7834#undef BITS
7835
7836 switch (type)
7837 {
7838 case DW_ATE_unsigned:
7839 case DW_ATE_signed:
7840 case DW_ATE_address:
7841 switch (bits)
7842 {
7843#define BITS(bits, xtype, sfmt, ufmt, max) \
7844 case bits: \
Roland McGrath1d8bb252008-08-07 08:39:41 +00007845 desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0); \
Roland McGrathcb6d8652007-08-23 08:10:54 +00007846 if (type == DW_ATE_signed) \
7847 colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, \
7848 maxregname, name, \
7849 max, sfmt, value.b##bits##s); \
7850 else \
7851 colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, \
7852 maxregname, name, \
7853 max, ufmt, value.b##bits); \
7854 break
7855
7856 TYPES;
7857
7858 case 128:
7859 assert (type == DW_ATE_unsigned);
Roland McGrath1d8bb252008-08-07 08:39:41 +00007860 desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
Roland McGrathcb6d8652007-08-23 08:10:54 +00007861 int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
7862 colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
7863 maxregname, name,
7864 34, "0x%.16" PRIx64 "%.16" PRIx64,
7865 value.b128[!be], value.b128[be]);
7866 break;
7867
7868 default:
7869 abort ();
7870#undef BITS
7871 }
7872 break;
7873
7874 default:
7875 /* Print each byte in hex, the whole thing in native byte order. */
7876 assert (bits % 8 == 0);
7877 const uint8_t *bytes = desc;
7878 desc += bits / 8;
7879 char hex[bits / 4 + 1];
7880 hex[bits / 4] = '\0';
7881 int incr = 1;
7882 if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
7883 {
7884 bytes += bits / 8 - 1;
7885 incr = -1;
7886 }
7887 size_t idx = 0;
7888 for (char *h = hex; bits > 0; bits -= 8, idx += incr)
7889 {
7890 *h++ = "0123456789abcdef"[bytes[idx] >> 4];
7891 *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
7892 }
7893 colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
7894 maxregname, name,
7895 2 + sizeof hex - 1, "0x%s", hex);
7896 break;
7897 }
7898 desc += regloc->pad;
7899
7900#undef TYPES
7901 }
7902
7903 return colno;
7904}
7905
7906
7907struct register_info
7908{
7909 const Ebl_Register_Location *regloc;
7910 const char *set;
Roland McGrathdffc33d2009-07-06 16:06:41 -07007911 char name[REGNAMESZ];
7912 int regno;
7913 int bits;
7914 int type;
Roland McGrathcb6d8652007-08-23 08:10:54 +00007915};
7916
7917static int
7918register_bitpos (const struct register_info *r)
7919{
7920 return (r->regloc->offset * 8
7921 + ((r->regno - r->regloc->regno)
7922 * (r->regloc->bits + r->regloc->pad * 8)));
7923}
7924
7925static int
7926compare_sets_by_info (const struct register_info *r1,
7927 const struct register_info *r2)
7928{
7929 return ((int) r2->bits - (int) r1->bits
7930 ?: register_bitpos (r1) - register_bitpos (r2));
7931}
7932
7933/* Sort registers by set, and by size and layout offset within each set. */
7934static int
7935compare_registers (const void *a, const void *b)
7936{
7937 const struct register_info *r1 = a;
7938 const struct register_info *r2 = b;
7939
7940 /* Unused elements sort last. */
7941 if (r1->regloc == NULL)
7942 return r2->regloc == NULL ? 0 : 1;
7943 if (r2->regloc == NULL)
7944 return -1;
7945
7946 return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
7947 ?: compare_sets_by_info (r1, r2));
7948}
7949
7950/* Sort register sets by layout offset of the first register in the set. */
7951static int
7952compare_register_sets (const void *a, const void *b)
7953{
7954 const struct register_info *const *p1 = a;
7955 const struct register_info *const *p2 = b;
7956 return compare_sets_by_info (*p1, *p2);
7957}
7958
7959static unsigned int
7960handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
7961 const Ebl_Register_Location *reglocs, size_t nregloc)
7962{
7963 if (nregloc == 0)
7964 return 0;
7965
7966 ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
7967 if (maxnreg <= 0)
Roland McGrathdffc33d2009-07-06 16:06:41 -07007968 {
7969 for (size_t i = 0; i < nregloc; ++i)
7970 if (maxnreg < reglocs[i].regno + reglocs[i].count)
7971 maxnreg = reglocs[i].regno + reglocs[i].count;
7972 assert (maxnreg > 0);
7973 }
Roland McGrathcb6d8652007-08-23 08:10:54 +00007974
7975 struct register_info regs[maxnreg];
7976 memset (regs, 0, sizeof regs);
7977
7978 /* Sort to collect the sets together. */
7979 int maxreg = 0;
7980 for (size_t i = 0; i < nregloc; ++i)
7981 for (int reg = reglocs[i].regno;
7982 reg < reglocs[i].regno + reglocs[i].count;
7983 ++reg)
7984 {
7985 assert (reg < maxnreg);
7986 if (reg > maxreg)
7987 maxreg = reg;
7988 struct register_info *info = &regs[reg];
Roland McGrathcb6d8652007-08-23 08:10:54 +00007989 info->regloc = &reglocs[i];
Roland McGrathf7a6f032009-07-08 14:08:32 -07007990 info->regno = reg;
Roland McGrathdffc33d2009-07-06 16:06:41 -07007991 info->set = register_info (ebl, reg, &reglocs[i],
7992 info->name, &info->bits, &info->type);
Roland McGrathcb6d8652007-08-23 08:10:54 +00007993 }
7994 qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
7995
7996 /* Collect the unique sets and sort them. */
7997 inline bool same_set (const struct register_info *a,
7998 const struct register_info *b)
7999 {
8000 return (a < &regs[maxnreg] && a->regloc != NULL
8001 && b < &regs[maxnreg] && b->regloc != NULL
8002 && a->bits == b->bits
8003 && (a->set == b->set || !strcmp (a->set, b->set)));
8004 }
8005 struct register_info *sets[maxreg + 1];
8006 sets[0] = &regs[0];
8007 size_t nsets = 1;
8008 for (int i = 1; i <= maxreg; ++i)
8009 if (regs[i].regloc != NULL && !same_set (&regs[i], &regs[i - 1]))
8010 sets[nsets++] = &regs[i];
8011 qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
8012
8013 /* Write out all the sets. */
8014 unsigned int colno = 0;
8015 for (size_t i = 0; i < nsets; ++i)
8016 {
8017 /* Find the longest name of a register in this set. */
8018 size_t maxname = 0;
8019 const struct register_info *end;
8020 for (end = sets[i]; same_set (sets[i], end); ++end)
8021 {
8022 size_t len = strlen (end->name);
8023 if (len > maxname)
8024 maxname = len;
8025 }
8026
8027 for (const struct register_info *reg = sets[i];
8028 reg < end;
8029 reg += reg->regloc->count ?: 1)
8030 colno = handle_core_register (ebl, core, maxname,
8031 reg->regloc, desc, colno);
8032
8033 /* Force a line break at the end of the group. */
8034 colno = REGISTER_WRAP_COLUMN;
8035 }
8036
8037 return colno;
8038}
8039
8040static void
Roland McGrath59ea7f32007-10-04 08:50:09 +00008041handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
Roland McGrathcb6d8652007-08-23 08:10:54 +00008042{
Roland McGrath59ea7f32007-10-04 08:50:09 +00008043 Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
8044 if (data == NULL)
8045 elf_error:
8046 error (EXIT_FAILURE, 0,
8047 gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
8048
Roland McGrathcb6d8652007-08-23 08:10:54 +00008049 const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
8050 for (size_t i = 0; i < nauxv; ++i)
8051 {
Roland McGrath59ea7f32007-10-04 08:50:09 +00008052 GElf_auxv_t av_mem;
8053 GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
8054 if (av == NULL)
8055 goto elf_error;
Roland McGrathcb6d8652007-08-23 08:10:54 +00008056
8057 const char *name;
8058 const char *fmt;
8059 if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
8060 {
8061 /* Unknown type. */
8062 if (av->a_un.a_val == 0)
8063 printf (" %" PRIu64 "\n", av->a_type);
8064 else
8065 printf (" %" PRIu64 ": %#" PRIx64 "\n",
8066 av->a_type, av->a_un.a_val);
8067 }
8068 else
8069 switch (fmt[0])
8070 {
8071 case '\0': /* Normally zero. */
8072 if (av->a_un.a_val == 0)
8073 {
8074 printf (" %s\n", name);
8075 break;
8076 }
8077 /* Fall through */
8078 case 'x': /* hex */
8079 case 'p': /* address */
8080 case 's': /* address of string */
8081 printf (" %s: %#" PRIx64 "\n", name, av->a_un.a_val);
8082 break;
8083 case 'u':
8084 printf (" %s: %" PRIu64 "\n", name, av->a_un.a_val);
8085 break;
8086 case 'd':
8087 printf (" %s: %" PRId64 "\n", name, av->a_un.a_val);
8088 break;
8089
8090 case 'b':
8091 printf (" %s: %#" PRIx64 " ", name, av->a_un.a_val);
8092 GElf_Xword bit = 1;
8093 const char *pfx = "<";
8094 for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
8095 {
8096 if (av->a_un.a_val & bit)
8097 {
8098 printf ("%s%s", pfx, p);
8099 pfx = " ";
8100 }
8101 bit <<= 1;
8102 }
8103 printf (">\n");
8104 break;
8105
8106 default:
8107 abort ();
8108 }
8109 }
8110}
8111
8112static void
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08008113handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
8114 const char *name, const void *desc)
Roland McGrathcb6d8652007-08-23 08:10:54 +00008115{
8116 GElf_Word regs_offset;
8117 size_t nregloc;
8118 const Ebl_Register_Location *reglocs;
8119 size_t nitems;
8120 const Ebl_Core_Item *items;
8121
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08008122 if (! ebl_core_note (ebl, nhdr, name,
Roland McGrathcb6d8652007-08-23 08:10:54 +00008123 &regs_offset, &nregloc, &reglocs, &nitems, &items))
8124 return;
8125
Roland McGrath059c83e2008-02-21 06:19:39 +00008126 /* Pass 0 for DESCSZ when there are registers in the note,
8127 so that the ITEMS array does not describe the whole thing.
8128 For non-register notes, the actual descsz might be a multiple
8129 of the unit size, not just exactly the unit size. */
8130 unsigned int colno = handle_core_items (ebl->elf, desc,
8131 nregloc == 0 ? nhdr->n_descsz : 0,
8132 items, nitems);
Roland McGrathcb6d8652007-08-23 08:10:54 +00008133 if (colno != 0)
8134 putchar_unlocked ('\n');
8135
8136 colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
8137 reglocs, nregloc);
8138 if (colno != 0)
8139 putchar_unlocked ('\n');
8140}
8141
Roland McGrath59ea7f32007-10-04 08:50:09 +00008142static void
8143handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
8144 GElf_Off start, Elf_Data *data)
8145{
8146 fputs_unlocked (gettext (" Owner Data size Type\n"), stdout);
8147
8148 if (data == NULL)
8149 goto bad_note;
8150
8151 size_t offset = 0;
8152 GElf_Nhdr nhdr;
8153 size_t name_offset;
8154 size_t desc_offset;
8155 while (offset < data->d_size
8156 && (offset = gelf_getnote (data, offset,
8157 &nhdr, &name_offset, &desc_offset)) > 0)
8158 {
8159 const char *name = data->d_buf + name_offset;
8160 const char *desc = data->d_buf + desc_offset;
8161
8162 char buf[100];
8163 char buf2[100];
8164 printf (gettext (" %-13.*s %9" PRId32 " %s\n"),
8165 (int) nhdr.n_namesz, name, nhdr.n_descsz,
8166 ehdr->e_type == ET_CORE
8167 ? ebl_core_note_type_name (ebl, nhdr.n_type,
8168 buf, sizeof (buf))
Mark Wielaardbb9d1b42011-04-24 17:53:38 +02008169 : ebl_object_note_type_name (ebl, name, nhdr.n_type,
Roland McGrath59ea7f32007-10-04 08:50:09 +00008170 buf2, sizeof (buf2)));
8171
8172 /* Filter out invalid entries. */
8173 if (memchr (name, '\0', nhdr.n_namesz) != NULL
8174 /* XXX For now help broken Linux kernels. */
8175 || 1)
8176 {
8177 if (ehdr->e_type == ET_CORE)
8178 {
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08008179 if (nhdr.n_type == NT_AUXV
8180 && (nhdr.n_namesz == 4 /* Broken old Linux kernels. */
8181 || (nhdr.n_namesz == 5 && name[4] == '\0'))
8182 && !memcmp (name, "CORE", 4))
Roland McGrath59ea7f32007-10-04 08:50:09 +00008183 handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
8184 start + desc_offset);
8185 else
Roland McGrath0ccbbcd2010-01-04 21:59:07 -08008186 handle_core_note (ebl, &nhdr, name, desc);
Roland McGrath59ea7f32007-10-04 08:50:09 +00008187 }
8188 else
8189 ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc);
8190 }
8191 }
8192
8193 if (offset == data->d_size)
8194 return;
8195
8196 bad_note:
8197 error (EXIT_FAILURE, 0,
8198 gettext ("cannot get content of note section: %s"),
8199 elf_errmsg (-1));
8200}
Roland McGrathcb6d8652007-08-23 08:10:54 +00008201
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008202static void
8203handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
8204{
Roland McGrath59ea7f32007-10-04 08:50:09 +00008205 /* If we have section headers, just look for SHT_NOTE sections.
8206 In a debuginfo file, the program headers are not reliable. */
8207 if (shnum != 0)
8208 {
8209 /* Get the section header string table index. */
8210 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07008211 if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
Roland McGrath59ea7f32007-10-04 08:50:09 +00008212 error (EXIT_FAILURE, 0,
8213 gettext ("cannot get section header string table index"));
8214
8215 Elf_Scn *scn = NULL;
8216 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
8217 {
8218 GElf_Shdr shdr_mem;
8219 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
8220
8221 if (shdr == NULL || shdr->sh_type != SHT_NOTE)
8222 /* Not what we are looking for. */
8223 continue;
8224
8225 printf (gettext ("\
8226\nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
8227 elf_ndxscn (scn),
8228 elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
8229 shdr->sh_size, shdr->sh_offset);
8230
8231 handle_notes_data (ebl, ehdr, shdr->sh_offset,
8232 elf_getdata (scn, NULL));
8233 }
8234 return;
8235 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008236
8237 /* We have to look through the program header to find the note
8238 sections. There can be more than one. */
Roland McGrath8111da02010-01-07 20:31:59 -08008239 for (size_t cnt = 0; cnt < phnum; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008240 {
8241 GElf_Phdr mem;
8242 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
8243
8244 if (phdr == NULL || phdr->p_type != PT_NOTE)
8245 /* Not what we are looking for. */
8246 continue;
8247
8248 printf (gettext ("\
Roland McGrath59ea7f32007-10-04 08:50:09 +00008249\nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008250 phdr->p_filesz, phdr->p_offset);
8251
Roland McGrath59ea7f32007-10-04 08:50:09 +00008252 handle_notes_data (ebl, ehdr, phdr->p_offset,
8253 elf_getdata_rawchunk (ebl->elf,
8254 phdr->p_offset, phdr->p_filesz,
8255 ELF_T_NHDR));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008256 }
8257}
Roland McGrath60fc84c2007-08-03 21:59:15 +00008258
8259
8260static void
8261hex_dump (const uint8_t *data, size_t len)
8262{
8263 size_t pos = 0;
8264 while (pos < len)
8265 {
Roland McGrath241ac022007-10-01 18:21:46 +00008266 printf (" 0x%08Zx ", pos);
Roland McGrath60fc84c2007-08-03 21:59:15 +00008267
8268 const size_t chunk = MIN (len - pos, 16);
8269
8270 for (size_t i = 0; i < chunk; ++i)
8271 if (i % 4 == 3)
8272 printf ("%02x ", data[pos + i]);
8273 else
8274 printf ("%02x", data[pos + i]);
8275
8276 if (chunk < 16)
Roland McGrathe4c22ea2007-10-23 13:07:39 +00008277 printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
Roland McGrath60fc84c2007-08-03 21:59:15 +00008278
8279 for (size_t i = 0; i < chunk; ++i)
8280 {
8281 unsigned char b = data[pos + i];
Ulrich Drepperc98bcc72007-08-04 17:06:14 +00008282 printf ("%c", isprint (b) ? b : '.');
Roland McGrath60fc84c2007-08-03 21:59:15 +00008283 }
8284
8285 putchar ('\n');
8286 pos += chunk;
8287 }
8288}
8289
8290static void
Roland McGrathc76f0b02007-09-27 07:31:33 +00008291dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
8292{
8293 if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
8294 printf (gettext ("\nSection [%Zu] '%s' has no data to dump.\n"),
8295 elf_ndxscn (scn), name);
8296 else
8297 {
8298 Elf_Data *data = elf_rawdata (scn, NULL);
8299 if (data == NULL)
8300 error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
8301 elf_ndxscn (scn), name, elf_errmsg (-1));
8302 else
8303 {
8304 printf (gettext ("\nHex dump of section [%Zu] '%s', %" PRIu64
8305 " bytes at offset %#0" PRIx64 ":\n"),
8306 elf_ndxscn (scn), name,
8307 shdr->sh_size, shdr->sh_offset);
8308 hex_dump (data->d_buf, data->d_size);
8309 }
8310 }
8311}
8312
8313static void
8314print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
8315{
Roland McGrathefa64962009-11-16 01:50:58 -08008316 if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
8317 printf (gettext ("\nSection [%Zu] '%s' has no strings to dump.\n"),
Roland McGrathc76f0b02007-09-27 07:31:33 +00008318 elf_ndxscn (scn), name);
Roland McGrathc76f0b02007-09-27 07:31:33 +00008319 else
8320 {
Roland McGrathefa64962009-11-16 01:50:58 -08008321 Elf_Data *data = elf_rawdata (scn, NULL);
8322 if (data == NULL)
8323 error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
8324 elf_ndxscn (scn), name, elf_errmsg (-1));
8325 else
Roland McGrathc76f0b02007-09-27 07:31:33 +00008326 {
Roland McGrathefa64962009-11-16 01:50:58 -08008327 printf (gettext ("\nString section [%Zu] '%s' contains %" PRIu64
8328 " bytes at offset %#0" PRIx64 ":\n"),
8329 elf_ndxscn (scn), name,
8330 shdr->sh_size, shdr->sh_offset);
8331
8332 const char *start = data->d_buf;
8333 const char *const limit = start + data->d_size;
8334 do
Roland McGrathc76f0b02007-09-27 07:31:33 +00008335 {
Roland McGrathefa64962009-11-16 01:50:58 -08008336 const char *end = memchr (start, '\0', limit - start);
8337 const size_t pos = start - (const char *) data->d_buf;
8338 if (unlikely (end == NULL))
8339 {
8340 printf (" [%6Zx]- %.*s\n",
8341 pos, (int) (limit - start), start);
8342 break;
8343 }
8344 printf (" [%6Zx] %s\n", pos, start);
8345 start = end + 1;
8346 } while (start < limit);
8347 }
Roland McGrathc76f0b02007-09-27 07:31:33 +00008348 }
8349}
8350
8351static void
8352for_each_section_argument (Elf *elf, const struct section_argument *list,
8353 void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
8354 const char *name))
Roland McGrath60fc84c2007-08-03 21:59:15 +00008355{
8356 /* Get the section header string table index. */
8357 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07008358 if (elf_getshdrstrndx (elf, &shstrndx) < 0)
Roland McGrath60fc84c2007-08-03 21:59:15 +00008359 error (EXIT_FAILURE, 0,
8360 gettext ("cannot get section header string table index"));
8361
Roland McGrathc76f0b02007-09-27 07:31:33 +00008362 for (const struct section_argument *a = list; a != NULL; a = a->next)
Roland McGrath60fc84c2007-08-03 21:59:15 +00008363 {
8364 Elf_Scn *scn;
8365 GElf_Shdr shdr_mem;
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00008366 const char *name = NULL;
Roland McGrath60fc84c2007-08-03 21:59:15 +00008367
8368 char *endp = NULL;
8369 unsigned long int shndx = strtoul (a->arg, &endp, 0);
Ulrich Drepperc98bcc72007-08-04 17:06:14 +00008370 if (endp != a->arg && *endp == '\0')
Roland McGrath60fc84c2007-08-03 21:59:15 +00008371 {
Roland McGrathc76f0b02007-09-27 07:31:33 +00008372 scn = elf_getscn (elf, shndx);
Roland McGrath60fc84c2007-08-03 21:59:15 +00008373 if (scn == NULL)
8374 {
8375 error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
8376 continue;
8377 }
8378
8379 if (gelf_getshdr (scn, &shdr_mem) == NULL)
8380 error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
8381 elf_errmsg (-1));
Roland McGrathc76f0b02007-09-27 07:31:33 +00008382 name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
Roland McGrath60fc84c2007-08-03 21:59:15 +00008383 }
8384 else
8385 {
8386 /* Need to look up the section by name. */
8387 scn = NULL;
Roland McGrathf4763cf2010-08-11 13:04:12 -07008388 bool found = false;
Roland McGrathc76f0b02007-09-27 07:31:33 +00008389 while ((scn = elf_nextscn (elf, scn)) != NULL)
Roland McGrath60fc84c2007-08-03 21:59:15 +00008390 {
8391 if (gelf_getshdr (scn, &shdr_mem) == NULL)
8392 continue;
Roland McGrathc76f0b02007-09-27 07:31:33 +00008393 name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
Roland McGrath60fc84c2007-08-03 21:59:15 +00008394 if (name == NULL)
8395 continue;
8396 if (!strcmp (name, a->arg))
Roland McGrathf4763cf2010-08-11 13:04:12 -07008397 {
8398 found = true;
8399 (*dump) (scn, &shdr_mem, name);
8400 }
Roland McGrath60fc84c2007-08-03 21:59:15 +00008401 }
8402
Roland McGrathf4763cf2010-08-11 13:04:12 -07008403 if (unlikely (!found) && !a->implicit)
8404 error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
Roland McGrath60fc84c2007-08-03 21:59:15 +00008405 }
Roland McGrath60fc84c2007-08-03 21:59:15 +00008406 }
8407}
8408
8409static void
Roland McGrathc76f0b02007-09-27 07:31:33 +00008410dump_data (Ebl *ebl)
8411{
8412 for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
8413}
8414
8415static void
8416dump_strings (Ebl *ebl)
8417{
8418 for_each_section_argument (ebl->elf, string_sections, &print_string_section);
8419}
8420
8421static void
Roland McGrath60fc84c2007-08-03 21:59:15 +00008422print_strings (Ebl *ebl)
8423{
8424 /* Get the section header string table index. */
8425 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07008426 if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
Roland McGrath60fc84c2007-08-03 21:59:15 +00008427 error (EXIT_FAILURE, 0,
8428 gettext ("cannot get section header string table index"));
8429
8430 Elf_Scn *scn;
8431 GElf_Shdr shdr_mem;
8432 const char *name;
8433 scn = NULL;
8434 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
8435 {
8436 if (gelf_getshdr (scn, &shdr_mem) == NULL)
8437 continue;
8438
8439 if (shdr_mem.sh_type != SHT_PROGBITS
8440 || !(shdr_mem.sh_flags & SHF_STRINGS))
8441 continue;
8442
8443 name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
8444 if (name == NULL)
8445 continue;
8446
Roland McGrathc76f0b02007-09-27 07:31:33 +00008447 print_string_section (scn, &shdr_mem, name);
Roland McGrath60fc84c2007-08-03 21:59:15 +00008448 }
8449}
Roland McGrath59ea7f32007-10-04 08:50:09 +00008450
8451static void
8452dump_archive_index (Elf *elf, const char *fname)
8453{
8454 size_t narsym;
8455 const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
8456 if (arsym == NULL)
8457 {
8458 int result = elf_errno ();
Ulrich Drepper3fc3d7b2007-10-04 18:40:28 +00008459 if (unlikely (result != ELF_E_NO_INDEX))
Roland McGrath59ea7f32007-10-04 08:50:09 +00008460 error (EXIT_FAILURE, 0,
8461 gettext ("cannot get symbol index of archive '%s': %s"),
8462 fname, elf_errmsg (result));
8463 else
8464 printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
8465 return;
8466 }
8467
8468 printf (gettext ("\nIndex of archive '%s' has %Zu entries:\n"),
8469 fname, narsym);
8470
8471 size_t as_off = 0;
8472 for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
8473 {
8474 if (s->as_off != as_off)
8475 {
8476 as_off = s->as_off;
8477
8478 Elf *subelf;
Ulrich Drepper3fc3d7b2007-10-04 18:40:28 +00008479 if (unlikely (elf_rand (elf, as_off) == 0)
8480 || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
8481 == NULL))
8482#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
8483 while (1)
8484#endif
8485 error (EXIT_FAILURE, 0,
8486 gettext ("cannot extract member at offset %Zu in '%s': %s"),
8487 as_off, fname, elf_errmsg (-1));
Roland McGrath59ea7f32007-10-04 08:50:09 +00008488
8489 const Elf_Arhdr *h = elf_getarhdr (subelf);
8490
8491 printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
8492
8493 elf_end (subelf);
8494 }
8495
8496 printf ("\t%s\n", s->as_name);
8497 }
8498}
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00008499
8500#include "debugpred.h"